routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+177
@@ -0,0 +1,177 @@
|
||||
'use strict';
|
||||
|
||||
const require_runtime = require('../_virtual/_rolldown/runtime.js');
|
||||
const require_index = require('../utils/index.js');
|
||||
|
||||
//#region lib/rules/block-lang.js
|
||||
/**
|
||||
* @fileoverview Disallow use other than available `lang`
|
||||
* @author Yosuke Ota
|
||||
*/
|
||||
var require_block_lang = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
|
||||
const utils = require_index.default;
|
||||
/**
|
||||
* @typedef {object} BlockOptions
|
||||
* @property {Set<string>} lang
|
||||
* @property {boolean} allowNoLang
|
||||
*/
|
||||
/**
|
||||
* @typedef { { [element: string]: BlockOptions | undefined } } Options
|
||||
*/
|
||||
/**
|
||||
* @typedef {object} UserBlockOptions
|
||||
* @property {string[] | string} [lang]
|
||||
* @property {boolean} [allowNoLang]
|
||||
*/
|
||||
/**
|
||||
* @typedef { { [element: string]: UserBlockOptions | undefined } } UserOptions
|
||||
*/
|
||||
/**
|
||||
* https://vuejs.github.io/vetur/guide/highlighting.html
|
||||
* <template lang="html"></template>
|
||||
* <style lang="css"></style>
|
||||
* <script lang="js"><\/script>
|
||||
* <script lang="javascript"><\/script>
|
||||
* @type {Record<string, string[] | undefined>}
|
||||
*/
|
||||
const DEFAULT_LANGUAGES = {
|
||||
template: ["html"],
|
||||
style: ["css"],
|
||||
script: ["js", "javascript"]
|
||||
};
|
||||
/**
|
||||
* @param {NonNullable<BlockOptions['lang']>} lang
|
||||
*/
|
||||
function getAllowsLangPhrase(lang) {
|
||||
const langs = [...lang].map((s) => `'${s}'`);
|
||||
switch (langs.length) {
|
||||
case 1: return langs[0];
|
||||
default: return `${langs.slice(0, -1).join(", ")}, and ${langs.at(-1)}`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Normalizes a given option.
|
||||
* @param {string} blockName The block name.
|
||||
* @param {UserBlockOptions} option An option to parse.
|
||||
* @returns {BlockOptions} Normalized option.
|
||||
*/
|
||||
function normalizeOption(blockName, option) {
|
||||
/** @type {Set<string>} */
|
||||
let lang;
|
||||
if (Array.isArray(option.lang)) lang = new Set(option.lang);
|
||||
else if (typeof option.lang === "string") lang = new Set([option.lang]);
|
||||
else lang = /* @__PURE__ */ new Set();
|
||||
let hasDefault = false;
|
||||
for (const def of DEFAULT_LANGUAGES[blockName] || []) if (lang.has(def)) {
|
||||
lang.delete(def);
|
||||
hasDefault = true;
|
||||
}
|
||||
if (lang.size === 0) return {
|
||||
lang,
|
||||
allowNoLang: true
|
||||
};
|
||||
return {
|
||||
lang,
|
||||
allowNoLang: hasDefault || Boolean(option.allowNoLang)
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Normalizes a given options.
|
||||
* @param { UserOptions } options An option to parse.
|
||||
* @returns {Options} Normalized option.
|
||||
*/
|
||||
function normalizeOptions(options) {
|
||||
if (!options) return {};
|
||||
/** @type {Options} */
|
||||
const normalized = {};
|
||||
for (const blockName of Object.keys(options)) {
|
||||
const value = options[blockName];
|
||||
if (value) normalized[blockName] = normalizeOption(blockName, value);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
docs: {
|
||||
description: "disallow use other than available `lang`",
|
||||
categories: void 0,
|
||||
url: "https://eslint.vuejs.org/rules/block-lang.html"
|
||||
},
|
||||
schema: [{
|
||||
type: "object",
|
||||
patternProperties: { "^(?:\\S+)$": { oneOf: [{
|
||||
type: "object",
|
||||
properties: {
|
||||
lang: { oneOf: [{ type: "string" }, {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
uniqueItems: true,
|
||||
additionalItems: false
|
||||
}] },
|
||||
allowNoLang: { type: "boolean" }
|
||||
},
|
||||
additionalProperties: false
|
||||
}] } },
|
||||
minProperties: 1,
|
||||
additionalProperties: false
|
||||
}],
|
||||
messages: {
|
||||
expected: "Only {{allows}} can be used for the 'lang' attribute of '<{{tag}}>'.",
|
||||
missing: "The 'lang' attribute of '<{{tag}}>' is missing.",
|
||||
unexpected: "Do not specify the 'lang' attribute of '<{{tag}}>'.",
|
||||
useOrNot: "Only {{allows}} can be used for the 'lang' attribute of '<{{tag}}>'. Or, not specifying the 'lang' attribute is allowed.",
|
||||
unexpectedDefault: "Do not explicitly specify the default language for the 'lang' attribute of '<{{tag}}>'."
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const options = normalizeOptions(context.options[0] || {
|
||||
script: { allowNoLang: true },
|
||||
template: { allowNoLang: true },
|
||||
style: { allowNoLang: true }
|
||||
});
|
||||
if (Object.keys(options).length === 0) return {};
|
||||
/**
|
||||
* @param {VElement} element
|
||||
* @returns {void}
|
||||
*/
|
||||
function verify(element) {
|
||||
const tag = element.name;
|
||||
const option = options[tag];
|
||||
if (!option) return;
|
||||
const lang = utils.getAttribute(element, "lang");
|
||||
if (lang == null || lang.value == null) {
|
||||
if (!option.allowNoLang) context.report({
|
||||
node: element.startTag,
|
||||
messageId: "missing",
|
||||
data: { tag }
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!option.lang.has(lang.value.value)) {
|
||||
let messageId;
|
||||
if (!option.allowNoLang) messageId = "expected";
|
||||
else if (option.lang.size === 0) messageId = (DEFAULT_LANGUAGES[tag] || []).includes(lang.value.value) ? "unexpectedDefault" : "unexpected";
|
||||
else messageId = "useOrNot";
|
||||
context.report({
|
||||
node: lang,
|
||||
messageId,
|
||||
data: {
|
||||
tag,
|
||||
allows: getAllowsLangPhrase(option.lang)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return utils.defineDocumentVisitor(context, { "VDocumentFragment > VElement": verify });
|
||||
}
|
||||
};
|
||||
}));
|
||||
|
||||
//#endregion
|
||||
Object.defineProperty(exports, 'default', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return require_block_lang();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user