@shayanthenerd/eslint-config
Version:
A modern, flexible ESLint configuration for enforcing best practices and maintaining a consistent coding style
174 lines (172 loc) • 6.82 kB
JavaScript
import { isEnabled } from "../utils/isEnabled.js";
import { defaultOptions } from "../utils/options/defaultOptions.js";
import { getRestrictedVueInputs } from "../utils/vue/getRestrictedVueInputs.js";
import { getRestrictedVueElements } from "../utils/vue/getRestrictedVueElements.js";
//#region src/rules/vue.ts
function getVueRules(options) {
const { typescript, stylistic, tailwind, vue, nuxt } = options.configs;
const { indent, useTabs, trailingComma, maxLineLength, maxAttributesPerLine, maxConsecutiveEmptyLines, selfCloseVoidHTMLElements } = isEnabled(stylistic) ? stylistic : defaultOptions.configs.stylistic;
const { blockLang, blocksOrder, macrosOrder, attributesOrder, destructureProps, vForDelimiterStyle, attributeHyphenation, allowedStyleAttributes, preferVBindTrueShorthand, componentNameCaseInTemplate, preferVBindSameNameShorthand, restrictedElements: userRestrictedElements, ignoredUndefinedComponents: userIgnoredUndefinedComponents, restrictedStaticAttributes: userRestrictedStaticAttributes } = isEnabled(vue) ? vue : defaultOptions.configs.vue;
const nuxtImage = isEnabled(nuxt) ? nuxt.image : void 0;
const nuxtUI = isEnabled(nuxt) ? nuxt.ui : void 0;
const nuxtUIPrefix = isEnabled(nuxt) && isEnabled(nuxt.ui) ? nuxt.ui.prefix : void 0;
const isScriptLangTS = blockLang.script === "ts";
const isStyleLangImplicit = blockLang.style === "implicit";
const vueRules = {
"no-undef": "off",
"no-useless-assignment": "off",
"import-x/default": "off",
"import-x/no-unresolved": "off",
"vue/comment-directive": ["error", { reportUnusedDisableDirectives: true }],
"vue/html-closing-bracket-newline": "warn",
"vue/singleline-html-element-content-newline": "off",
"vue/html-indent": ["warn", useTabs ? "tab" : indent],
"vue/v-slot-style": ["warn", { atComponent: "shorthand" }],
"vue/attribute-hyphenation": ["warn", attributeHyphenation],
"vue/first-attribute-linebreak": ["warn", { singleline: "beside" }],
"vue/v-on-event-hyphenation": [
"warn",
attributeHyphenation,
{ autofix: true }
],
"vue/v-bind-style": [
"warn",
"shorthand",
{ sameNameShorthand: preferVBindSameNameShorthand }
],
"vue/html-self-closing": ["error", { html: {
normal: "never",
void: selfCloseVoidHTMLElements
} }],
"vue/max-attributes-per-line": ["warn", { singleline: { max: maxAttributesPerLine } }],
"vue/attributes-order": ["warn", { order: attributesOrder }],
"vue/camelcase": "warn",
"vue/no-root-v-if": "warn",
"vue/require-expose": "error",
"vue/no-unused-refs": "error",
"vue/prop-name-casing": "warn",
"vue/slot-name-casing": "warn",
"vue/no-useless-v-bind": "error",
"vue/component-api-style": "error",
"vue/html-button-has-type": "error",
"vue/valid-define-options": "error",
"vue/prefer-define-options": "warn",
"vue/require-emit-validator": "error",
"vue/require-default-export": "error",
"vue/custom-event-name-casing": "warn",
"vue/no-use-v-else-with-v-for": "error",
"vue/no-empty-component-block": "error",
"vue/no-import-compiler-macros": "error",
"vue/require-typed-object-prop": "error",
"vue/require-macro-variable-name": "warn",
"vue/padding-line-between-blocks": "warn",
"vue/match-component-import-name": "error",
"vue/html-comment-content-newline": "warn",
"vue/no-multiple-objects-in-class": "warn",
"vue/prefer-separate-static-class": "warn",
"vue/html-comment-content-spacing": "warn",
"vue/comma-dangle": ["warn", trailingComma],
"vue/component-options-name-casing": "warn",
"vue/no-ref-object-reactivity-loss": "error",
"vue/no-duplicate-attr-inheritance": "error",
"vue/no-this-in-before-route-enter": "error",
"vue/prefer-prop-type-boolean-first": "warn",
"vue/no-setup-props-reactivity-loss": "error",
"vue/block-order": ["warn", { order: blocksOrder }],
"vue/v-for-delimiter-style": ["warn", vForDelimiterStyle],
"vue/require-typed-ref": isScriptLangTS ? "error" : "off",
"vue/define-macros-order": ["warn", { order: macrosOrder }],
"vue/html-comment-indent": ["warn", useTabs ? "tab" : indent],
"vue/no-static-inline-styles": ["warn", { allowBinding: true }],
"vue/no-required-prop-with-default": ["error", { autofix: true }],
"vue/prefer-true-attribute-shorthand": ["warn", preferVBindTrueShorthand],
"vue/no-deprecated-model-definition": ["error", { allowVue3Compat: true }],
"vue/enforce-style-attribute": ["error", { allow: allowedStyleAttributes }],
"vue/define-props-destructuring": ["warn", { destructure: destructureProps }],
"vue/define-emits-declaration": ["warn", isScriptLangTS ? "type-based" : "runtime"],
"vue/define-props-declaration": ["error", isScriptLangTS ? "type-based" : "runtime"],
"vue/max-len": [tailwind ? "off" : "warn", {
tabWidth: indent,
code: maxLineLength,
template: Infinity,
ignoreUrls: true,
ignoreStrings: true,
ignoreComments: true,
ignoreRegExpLiterals: true,
ignoreTrailingComments: true,
ignoreTemplateLiterals: true,
ignoreHTMLTextContents: true,
ignoreHTMLAttributeValues: true
}],
"vue/block-lang": ["error", {
script: { lang: blockLang.script },
style: {
lang: isStyleLangImplicit ? void 0 : blockLang.style,
allowNoLang: isStyleLangImplicit
}
}],
"vue/block-tag-newline": ["warn", {
singleline: "always",
maxEmptyLines: maxConsecutiveEmptyLines ? maxConsecutiveEmptyLines - 1 : 0
}],
"vue/no-restricted-html-elements": [
"error",
{
element: nuxt ? "time" : "",
message: "Use `<NuxtTime>`."
},
{
element: nuxtImage ? "img" : "",
message: "Use `<NuxtImg>`."
},
{
element: nuxtImage ? "picture" : "",
message: "Use `<NuxtPicture>`."
},
{
element: nuxtUI ? [
"a",
"RouterLink",
"NuxtLink"
] : "",
message: nuxtUI && nuxtUIPrefix ? `Use <${nuxtUIPrefix}Link>.` : void 0
},
{
element: ["a", nuxt ? "RouterLink" : ""],
message: `Use <${nuxt ? "NuxtLink" : "RouterLink"}>.`
},
...nuxtUI && nuxtUIPrefix ? getRestrictedVueElements(nuxtUIPrefix) : [],
...userRestrictedElements
],
"vue/no-restricted-static-attribute": [
"error",
...nuxtUI && nuxtUIPrefix ? getRestrictedVueInputs(nuxtUIPrefix) : [],
...userRestrictedStaticAttributes
],
"vue/no-undef-components": ["error", { ignorePatterns: [
"^(Nuxt|U)",
"^(Icon|Html|Head|Title|Base|Meta|Link|Style|Body|NoScript)$",
...userIgnoredUndefinedComponents
] }],
"vue/match-component-file-name": ["error", {
shouldMatchCase: true,
extensions: [
"vue",
"js",
"jsx",
...typescript ? ["ts", "tsx"] : []
]
}],
"vue/component-name-in-template-casing": [
"warn",
componentNameCaseInTemplate,
{
ignores: ["*.*"],
registeredComponentsOnly: false
}
]
};
return vueRules;
}
//#endregion
export { getVueRules };