@shayanthenerd/eslint-config 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/configs/html.js +1 -0
- package/dist/configs/typescript.js +5 -3
- package/dist/configs/vueComponentNames.js +1 -2
- package/dist/configs/vueServerComponents.js +14 -0
- package/dist/index.js +2 -2
- package/dist/oxlint.config.jsonc +7 -0
- package/dist/rules/html.js +1 -0
- package/dist/rules/javascript.js +5 -2
- package/dist/rules/tailwind.js +1 -0
- package/dist/rules/vue.js +19 -7
- package/dist/types/configOptions/vue.d.ts +0 -2
- package/dist/types/configOptions/vueAccessibility.d.ts +7 -1
- package/dist/types/eslint-schema.d.ts +52 -27
- package/dist/utils/globs.js +2 -3
- package/dist/utils/isPackageDetected.js +1 -0
- package/dist/utils/options/defaultOptions.js +3 -2
- package/dist/utils/options/mergeWithDefaults.js +11 -0
- package/dist/utils/vue/getRestrictedVueElements.js +1 -1
- package/dist/utils/vue/getRestrictedVueInputs.js +1 -1
- package/package.json +31 -31
- package/dist/configs/nuxtMultiRootTemplate.js +0 -14
package/dist/configs/html.js
CHANGED
|
@@ -3,6 +3,7 @@ import { isEnabled } from "../utils/isEnabled.js";
|
|
|
3
3
|
import { defaultOptions } from "../utils/options/defaultOptions.js";
|
|
4
4
|
import { getTypeScriptRules } from "../rules/typescript.js";
|
|
5
5
|
import typescriptESLint from "typescript-eslint";
|
|
6
|
+
import path from "node:path";
|
|
6
7
|
import { mergeConfigs } from "eslint-flat-config-utils";
|
|
7
8
|
|
|
8
9
|
//#region src/configs/typescript.ts
|
|
@@ -15,10 +16,11 @@ function getTypeScriptConfig(options) {
|
|
|
15
16
|
files: [globs.ts, vue ? globs.vue : ""],
|
|
16
17
|
extends: [typescriptESLint.configs.strictTypeChecked, typescriptESLint.configs.stylisticTypeChecked],
|
|
17
18
|
languageOptions: { parserOptions: {
|
|
18
|
-
|
|
19
|
+
warnOnUnsupportedTypeScriptVersion: false,
|
|
20
|
+
tsconfigRootDir: tsConfig ? path.resolve(tsConfig.rootDir) : void 0,
|
|
19
21
|
projectService: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
defaultProject: tsConfig ? tsConfig.filename : void 0,
|
|
23
|
+
allowDefaultProject: allowedDefaultProjects
|
|
22
24
|
}
|
|
23
25
|
} },
|
|
24
26
|
rules: getTypeScriptRules(options)
|
|
@@ -4,8 +4,7 @@ import { globs } from "../utils/globs.js";
|
|
|
4
4
|
function getVueComponentNamesConfig() {
|
|
5
5
|
const vueComponentNamesConfig = {
|
|
6
6
|
name: "shayanthenerd/vue/multi-word-component-names",
|
|
7
|
-
files: [globs.
|
|
8
|
-
ignores: [globs.vueComponentNamesIgnore],
|
|
7
|
+
files: [globs.vueAppErrorLayoutsPages],
|
|
9
8
|
rules: {
|
|
10
9
|
"vue/match-component-file-name": "off",
|
|
11
10
|
"vue/multi-word-component-names": "off",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { globs } from "../utils/globs.js";
|
|
2
|
+
|
|
3
|
+
//#region src/configs/vueServerComponents.ts
|
|
4
|
+
function getVueServerComponentsConfig() {
|
|
5
|
+
const vueServerComponentsConfig = {
|
|
6
|
+
name: "shayanthenerd/vue/server-components",
|
|
7
|
+
files: [globs.vueServerComponents],
|
|
8
|
+
rules: { "vue/no-multiple-template-root": "error" }
|
|
9
|
+
};
|
|
10
|
+
return vueServerComponentsConfig;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { getVueServerComponentsConfig };
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { getOXLintOverridesConfig } from "./configs/oxlintOverrides.js";
|
|
|
18
18
|
import { getIgnorePatterns } from "./utils/ignores/getIgnorePatterns.js";
|
|
19
19
|
import { mergeWithDefaults } from "./utils/options/mergeWithDefaults.js";
|
|
20
20
|
import { getVueComponentNamesConfig } from "./configs/vueComponentNames.js";
|
|
21
|
-
import {
|
|
21
|
+
import { getVueServerComponentsConfig } from "./configs/vueServerComponents.js";
|
|
22
22
|
import { globalIgnores } from "eslint/config";
|
|
23
23
|
import eslintPluginOXLint from "eslint-plugin-oxlint";
|
|
24
24
|
import { config } from "typescript-eslint";
|
|
@@ -46,7 +46,7 @@ function defineConfig(options = {}, ...configs) {
|
|
|
46
46
|
linterOptions,
|
|
47
47
|
settings,
|
|
48
48
|
rules
|
|
49
|
-
}, globalIgnores(ignorePatterns, "shayanthenerd/ignores"), getBaseConfig(mergedOptions), preferNamedExports ? getRestrictedExports() : {}, isEnabled(importX) ? getImportXConfig(mergedOptions) : {}, isEnabled(stylistic) ? getStylisticConfig(mergedOptions) : {}, isEnabled(perfectionist) ? getPerfectionistConfig(mergedOptions) : {}, isEnabled(typescript) ? getTypeScriptConfig(mergedOptions) : {}, isEnabled(html) ? getHTMLConfig(mergedOptions) : {}, isEnabled(css) ? getCSSConfig(mergedOptions) : {}, isEnabled(tailwind) ? getTailwindConfig(mergedOptions) : {}, isEnabled(vue) ? getVueConfig(mergedOptions) : {}, isEnabled(vue) ? getVueComponentNamesConfig() : {}, isEnabled(vue) && isEnabled(nuxt) ?
|
|
49
|
+
}, globalIgnores(ignorePatterns, "shayanthenerd/ignores"), getBaseConfig(mergedOptions), preferNamedExports ? getRestrictedExports() : {}, isEnabled(importX) ? getImportXConfig(mergedOptions) : {}, isEnabled(stylistic) ? getStylisticConfig(mergedOptions) : {}, isEnabled(perfectionist) ? getPerfectionistConfig(mergedOptions) : {}, isEnabled(typescript) ? getTypeScriptConfig(mergedOptions) : {}, isEnabled(html) ? getHTMLConfig(mergedOptions) : {}, isEnabled(css) ? getCSSConfig(mergedOptions) : {}, isEnabled(tailwind) ? getTailwindConfig(mergedOptions) : {}, isEnabled(vue) ? getVueConfig(mergedOptions) : {}, isEnabled(vue) ? getVueComponentNamesConfig() : {}, isEnabled(vue) && isEnabled(nuxt) ? getVueServerComponentsConfig() : {}, isEnabled(storybook) ? getStorybookConfig(mergedOptions) : {}, isEnabled(vitest) ? getVitestConfig(mergedOptions) : {}, isEnabled(playwright) ? getPlaywrightConfig(mergedOptions) : {}, isEnabled(cypress) ? getCypressConfig(mergedOptions) : {}, ...oxlint ? eslintPluginOXLint.buildFromOxlintConfigFile(oxlintConfigPath) : [], oxlint ? getOXLintOverridesConfig(mergedOptions) : {}, ...configs);
|
|
50
50
|
return eslintConfig;
|
|
51
51
|
}
|
|
52
52
|
|
package/dist/oxlint.config.jsonc
CHANGED
|
@@ -81,11 +81,13 @@
|
|
|
81
81
|
"import/no-anonymous-default-export": "off",
|
|
82
82
|
|
|
83
83
|
/*** Unicorn ***/
|
|
84
|
+
"unicorn/no-null": "off",
|
|
84
85
|
"unicorn/filename-case": "off",
|
|
85
86
|
"unicorn/prefer-set-has": "off",
|
|
86
87
|
"unicorn/no-array-reduce": "off",
|
|
87
88
|
"unicorn/prefer-string-raw": "off",
|
|
88
89
|
"unicorn/no-array-for-each": "off",
|
|
90
|
+
"unicorn/prefer-global-this": "off",
|
|
89
91
|
"unicorn/no-useless-undefined": "off",
|
|
90
92
|
"unicorn/prefer-prototype-methods": "off",
|
|
91
93
|
"unicorn/no-await-expression-member": "off",
|
|
@@ -95,6 +97,11 @@
|
|
|
95
97
|
"jest/prefer-lowercase-title": "warn",
|
|
96
98
|
"jest/require-top-level-describe": "off",
|
|
97
99
|
|
|
100
|
+
/*** JSDoc ***/
|
|
101
|
+
"jsdoc/require-param": "off",
|
|
102
|
+
"jsdoc/require-returns": "off",
|
|
103
|
+
"jsdoc/require-property": "off",
|
|
104
|
+
|
|
98
105
|
/*** Customizable Overrides ***/
|
|
99
106
|
/* These rules are customizable in the ESLint config, but OXLint doesn't respect them. */
|
|
100
107
|
"eslint/max-depth": "off",
|
package/dist/rules/html.js
CHANGED
|
@@ -11,6 +11,7 @@ function getHTMLRules(options) {
|
|
|
11
11
|
"@html-eslint/no-target-blank": "error",
|
|
12
12
|
"@html-eslint/no-duplicate-class": "warn",
|
|
13
13
|
"@html-eslint/require-button-type": "error",
|
|
14
|
+
"@html-eslint/no-ineffective-attrs": "error",
|
|
14
15
|
"@html-eslint/no-script-style-type": "error",
|
|
15
16
|
"@html-eslint/require-meta-charset": "error",
|
|
16
17
|
"@html-eslint/quotes": [
|
package/dist/rules/javascript.js
CHANGED
|
@@ -37,7 +37,6 @@ function getJavaScriptRules(options) {
|
|
|
37
37
|
"no-void": "error",
|
|
38
38
|
"no-proto": "warn",
|
|
39
39
|
"no-empty": "warn",
|
|
40
|
-
"camelcase": "warn",
|
|
41
40
|
"no-caller": "error",
|
|
42
41
|
"no-eq-null": "warn",
|
|
43
42
|
"complexity": "warn",
|
|
@@ -90,7 +89,6 @@ function getJavaScriptRules(options) {
|
|
|
90
89
|
"prefer-destructuring": "warn",
|
|
91
90
|
"no-implicit-coercion": "error",
|
|
92
91
|
"no-array-constructor": "error",
|
|
93
|
-
"no-underscore-dangle": "error",
|
|
94
92
|
"prefer-object-spread": "error",
|
|
95
93
|
"radix": ["error", "as-needed"],
|
|
96
94
|
"curly": ["warn", "multi-line"],
|
|
@@ -121,6 +119,11 @@ function getJavaScriptRules(options) {
|
|
|
121
119
|
"prefer-promise-reject-errors": ["error", { allowEmptyReject: true }],
|
|
122
120
|
"prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
|
|
123
121
|
"no-extra-boolean-cast": ["error", { enforceForInnerExpressions: true }],
|
|
122
|
+
"camelcase": ["warn", {
|
|
123
|
+
properties: "never",
|
|
124
|
+
ignoreImports: true,
|
|
125
|
+
ignoreDestructuring: true
|
|
126
|
+
}],
|
|
124
127
|
"no-console": ["warn", { allow: [
|
|
125
128
|
"info",
|
|
126
129
|
"warn",
|
package/dist/rules/tailwind.js
CHANGED
|
@@ -10,6 +10,7 @@ function getTailwindRules(options) {
|
|
|
10
10
|
const tailwindRules = {
|
|
11
11
|
"@stylistic/max-len": "off",
|
|
12
12
|
"css/no-duplicate-imports": "off",
|
|
13
|
+
"vue/first-attribute-linebreak": "off",
|
|
13
14
|
"better-tailwindcss/no-duplicate-classes": "error",
|
|
14
15
|
"better-tailwindcss/no-deprecated-classes": "error",
|
|
15
16
|
"better-tailwindcss/no-conflicting-classes": "error",
|
package/dist/rules/vue.js
CHANGED
|
@@ -10,7 +10,7 @@ function getVueRules(options) {
|
|
|
10
10
|
const { blockLang, blocksOrder, macrosOrder, attributesOrder, destructureProps, vForDelimiterStyle, attributeHyphenation, allowedStyleAttributes, preferVBindTrueShorthand, componentNameCaseInTemplate, preferVBindSameNameShorthand, restrictedElements: userRestrictedElements, ignoredUndefinedComponents: userIgnoredUndefinedComponents, restrictedStaticAttributes: userRestrictedStaticAttributes } = isEnabled(vue) ? vue : defaultOptions.configs.vue;
|
|
11
11
|
const nuxtImage = isEnabled(nuxt) ? nuxt.image : void 0;
|
|
12
12
|
const nuxtUI = isEnabled(nuxt) ? nuxt.ui : void 0;
|
|
13
|
-
const nuxtUIPrefix = isEnabled(nuxt) && isEnabled(nuxt.ui) ? nuxt.ui.prefix :
|
|
13
|
+
const nuxtUIPrefix = isEnabled(nuxt) && isEnabled(nuxt.ui) ? nuxt.ui.prefix : defaultOptions.configs.nuxt.ui.prefix;
|
|
14
14
|
const isScriptLangTS = blockLang.script === "ts";
|
|
15
15
|
const isStyleLangImplicit = blockLang.style === "implicit";
|
|
16
16
|
const vueRules = {
|
|
@@ -18,13 +18,14 @@ function getVueRules(options) {
|
|
|
18
18
|
"no-useless-assignment": "off",
|
|
19
19
|
"import-x/default": "off",
|
|
20
20
|
"import-x/no-unresolved": "off",
|
|
21
|
+
"vue/no-multiple-template-root": "off",
|
|
21
22
|
"vue/comment-directive": ["error", { reportUnusedDisableDirectives: true }],
|
|
23
|
+
"vue/require-default-prop": "off",
|
|
22
24
|
"vue/html-closing-bracket-newline": "warn",
|
|
23
25
|
"vue/singleline-html-element-content-newline": "off",
|
|
24
26
|
"vue/html-indent": ["warn", useTabs ? "tab" : indent],
|
|
25
27
|
"vue/v-slot-style": ["warn", { atComponent: "shorthand" }],
|
|
26
28
|
"vue/attribute-hyphenation": ["warn", attributeHyphenation],
|
|
27
|
-
"vue/first-attribute-linebreak": ["warn", { singleline: "beside" }],
|
|
28
29
|
"vue/v-on-event-hyphenation": [
|
|
29
30
|
"warn",
|
|
30
31
|
attributeHyphenation,
|
|
@@ -57,6 +58,7 @@ function getVueRules(options) {
|
|
|
57
58
|
"vue/custom-event-name-casing": "warn",
|
|
58
59
|
"vue/no-use-v-else-with-v-for": "error",
|
|
59
60
|
"vue/no-empty-component-block": "error",
|
|
61
|
+
"vue/no-negated-v-if-condition": "warn",
|
|
60
62
|
"vue/no-import-compiler-macros": "error",
|
|
61
63
|
"vue/require-typed-object-prop": "error",
|
|
62
64
|
"vue/require-macro-variable-name": "warn",
|
|
@@ -130,18 +132,28 @@ function getVueRules(options) {
|
|
|
130
132
|
"RouterLink",
|
|
131
133
|
"NuxtLink"
|
|
132
134
|
] : "",
|
|
133
|
-
message: nuxtUI
|
|
135
|
+
message: nuxtUI ? `Use \`<${nuxtUIPrefix}Link>\`.` : void 0
|
|
134
136
|
},
|
|
135
137
|
{
|
|
136
138
|
element: ["a", nuxt ? "RouterLink" : ""],
|
|
137
|
-
message: `Use
|
|
139
|
+
message: `Use \`<${nuxt ? "NuxtLink" : "RouterLink"}>\`.`
|
|
138
140
|
},
|
|
139
|
-
...nuxtUI
|
|
141
|
+
...nuxtUI ? getRestrictedVueElements(nuxtUIPrefix) : [],
|
|
140
142
|
...userRestrictedElements
|
|
141
143
|
],
|
|
142
144
|
"vue/no-restricted-static-attribute": [
|
|
143
145
|
"error",
|
|
144
|
-
...nuxtUI
|
|
146
|
+
...nuxtUI ? getRestrictedVueInputs(nuxtUIPrefix) : [],
|
|
147
|
+
nuxtUI ? {
|
|
148
|
+
key: "href",
|
|
149
|
+
element: `${nuxtUIPrefix}Link`,
|
|
150
|
+
message: "Use `v-bind:to=\"\"`."
|
|
151
|
+
} : { key: "" },
|
|
152
|
+
nuxtUI ? {
|
|
153
|
+
key: "href",
|
|
154
|
+
element: `${nuxtUIPrefix}Button`,
|
|
155
|
+
message: "Use `v-bind:to=\"\"`."
|
|
156
|
+
} : { key: " " },
|
|
145
157
|
...userRestrictedStaticAttributes
|
|
146
158
|
],
|
|
147
159
|
"vue/no-undef-components": ["error", { ignorePatterns: [
|
|
@@ -162,7 +174,7 @@ function getVueRules(options) {
|
|
|
162
174
|
"warn",
|
|
163
175
|
componentNameCaseInTemplate,
|
|
164
176
|
{
|
|
165
|
-
ignores: ["
|
|
177
|
+
ignores: ["/^\\w+(\\.\\w+)+$/"],
|
|
166
178
|
registeredComponentsOnly: false
|
|
167
179
|
}
|
|
168
180
|
]
|
|
@@ -176,8 +176,6 @@ interface VueOptions extends ConfigWithOverrides {
|
|
|
176
176
|
*
|
|
177
177
|
* When NuxtUI or NuxtImage are enabled, certain HTML elements (e.g., `<img>`, `<a>`, `<form>`, `<input>`) are disallowed in favor of their alternative components.
|
|
178
178
|
*
|
|
179
|
-
* New items extend the defaults, they don't override it.
|
|
180
|
-
*
|
|
181
179
|
* @default []
|
|
182
180
|
*
|
|
183
181
|
* @see [vue/no-restricted-html-elements](https://eslint.vuejs.org/rules/no-restricted-html-elements)
|
|
@@ -6,6 +6,8 @@ interface VueAccessibilityOptions {
|
|
|
6
6
|
/**
|
|
7
7
|
* Names of components that render an `<a>` element.
|
|
8
8
|
*
|
|
9
|
+
* New items extend the defaults, they don't override it.
|
|
10
|
+
*
|
|
9
11
|
* @default ['RouterLink', 'NuxtLink', 'ULink']
|
|
10
12
|
*
|
|
11
13
|
* @see [vuejs-accessibility/anchor-has-content: `components` option](https://vue-a11y.github.io/eslint-plugin-vuejs-accessibility/rules/anchor-has-content#%F0%9F%94%A7-options)
|
|
@@ -15,6 +17,8 @@ interface VueAccessibilityOptions {
|
|
|
15
17
|
/**
|
|
16
18
|
* Names of components that render an `<img>` element.
|
|
17
19
|
*
|
|
20
|
+
* New items extend the defaults, they don't override it.
|
|
21
|
+
*
|
|
18
22
|
* @default ['NuxtImg']
|
|
19
23
|
*
|
|
20
24
|
* @see [vuejs-accessibility/alt-text: `img` option](https://vue-a11y.github.io/eslint-plugin-vuejs-accessibility/rules/alt-text#%F0%9F%94%A7-options)
|
|
@@ -24,7 +28,9 @@ interface VueAccessibilityOptions {
|
|
|
24
28
|
/**
|
|
25
29
|
* Names of components that should be considered accessible child elements.
|
|
26
30
|
*
|
|
27
|
-
*
|
|
31
|
+
* New items extend the defaults, they don't override it.
|
|
32
|
+
*
|
|
33
|
+
* @default ['img', 'picture', 'NuxtImg', 'NuxtPicture', 'UBadge']
|
|
28
34
|
*
|
|
29
35
|
* @see [vuejs-accessibility/anchor-has-content: `accessibleChildren` option](https://vue-a11y.github.io/eslint-plugin-vuejs-accessibility/rules/anchor-has-content#%F0%9F%94%A7-options)
|
|
30
36
|
*/
|
|
@@ -43,7 +43,7 @@ declare module 'eslint-flat-config-utils' {
|
|
|
43
43
|
'shayanthenerd/vue__vuejs-accessibility:setup:with-files-rules-and-parser'?: true;
|
|
44
44
|
'shayanthenerd/vue'?: true;
|
|
45
45
|
'shayanthenerd/vue/multi-word-component-names'?: true;
|
|
46
|
-
'shayanthenerd/
|
|
46
|
+
'shayanthenerd/vue/server-components'?: true;
|
|
47
47
|
'shayanthenerd/storybook__storybook:recommended:setup'?: true;
|
|
48
48
|
'shayanthenerd/storybook__storybook:recommended:stories-rules'?: true;
|
|
49
49
|
'shayanthenerd/storybook__storybook:recommended:main-rules'?: true;
|
|
@@ -72,7 +72,7 @@ interface ESLintSchema {
|
|
|
72
72
|
*/
|
|
73
73
|
'@html-eslint/element-newline'?: Linter.RuleEntry<HtmlEslintElementNewline>;
|
|
74
74
|
/**
|
|
75
|
-
* Enforce consistent naming id attributes
|
|
75
|
+
* Enforce consistent naming of id attributes
|
|
76
76
|
* @see https://html-eslint.org/docs/rules/id-naming-convention
|
|
77
77
|
*/
|
|
78
78
|
'@html-eslint/id-naming-convention'?: Linter.RuleEntry<HtmlEslintIdNamingConvention>;
|
|
@@ -81,27 +81,27 @@ interface ESLintSchema {
|
|
|
81
81
|
*/
|
|
82
82
|
'@html-eslint/indent'?: Linter.RuleEntry<HtmlEslintIndent>;
|
|
83
83
|
/**
|
|
84
|
-
* Enforce
|
|
84
|
+
* Enforce use of lowercase for tag and attribute names.
|
|
85
85
|
* @see https://html-eslint.org/docs/rules/lowercase
|
|
86
86
|
*/
|
|
87
87
|
'@html-eslint/lowercase'?: Linter.RuleEntry<[]>;
|
|
88
88
|
/**
|
|
89
|
-
* Enforce element
|
|
89
|
+
* Enforce maximum element depth
|
|
90
90
|
* @see https://html-eslint.org/docs/rules/max-element-depth
|
|
91
91
|
*/
|
|
92
92
|
'@html-eslint/max-element-depth'?: Linter.RuleEntry<HtmlEslintMaxElementDepth>;
|
|
93
93
|
/**
|
|
94
|
-
* Disallow
|
|
94
|
+
* Disallow use of abstract roles
|
|
95
95
|
* @see https://html-eslint.org/docs/rules/no-abstract-roles
|
|
96
96
|
*/
|
|
97
97
|
'@html-eslint/no-abstract-roles'?: Linter.RuleEntry<[]>;
|
|
98
98
|
/**
|
|
99
|
-
* Disallow
|
|
99
|
+
* Disallow use of accesskey attribute
|
|
100
100
|
* @see https://html-eslint.org/docs/rules/no-accesskey-attrs
|
|
101
101
|
*/
|
|
102
102
|
'@html-eslint/no-accesskey-attrs'?: Linter.RuleEntry<[]>;
|
|
103
103
|
/**
|
|
104
|
-
* Disallow
|
|
104
|
+
* Disallow use of aria-hidden attributes on the `body` element.
|
|
105
105
|
* @see https://html-eslint.org/docs/rules/no-aria-hidden-body
|
|
106
106
|
*/
|
|
107
107
|
'@html-eslint/no-aria-hidden-body'?: Linter.RuleEntry<[]>;
|
|
@@ -111,17 +111,17 @@ interface ESLintSchema {
|
|
|
111
111
|
*/
|
|
112
112
|
'@html-eslint/no-aria-hidden-on-focusable'?: Linter.RuleEntry<[]>;
|
|
113
113
|
/**
|
|
114
|
-
* Disallow
|
|
114
|
+
* Disallow duplicate attributes
|
|
115
115
|
* @see https://html-eslint.org/docs/rules/no-duplicate-attrs
|
|
116
116
|
*/
|
|
117
117
|
'@html-eslint/no-duplicate-attrs'?: Linter.RuleEntry<[]>;
|
|
118
118
|
/**
|
|
119
|
-
* Disallow
|
|
119
|
+
* Disallow duplicate class names
|
|
120
120
|
* @see https://html-eslint.org/docs/rules/no-duplicate-class
|
|
121
121
|
*/
|
|
122
122
|
'@html-eslint/no-duplicate-class'?: Linter.RuleEntry<[]>;
|
|
123
123
|
/**
|
|
124
|
-
* Disallow
|
|
124
|
+
* Disallow duplicate id attributes
|
|
125
125
|
* @see https://html-eslint.org/docs/rules/no-duplicate-id
|
|
126
126
|
*/
|
|
127
127
|
'@html-eslint/no-duplicate-id'?: Linter.RuleEntry<[]>;
|
|
@@ -136,7 +136,7 @@ interface ESLintSchema {
|
|
|
136
136
|
*/
|
|
137
137
|
'@html-eslint/no-empty-headings'?: Linter.RuleEntry<[]>;
|
|
138
138
|
/**
|
|
139
|
-
* Disallow
|
|
139
|
+
* Disallow extra spacing around attributes
|
|
140
140
|
* @see https://html-eslint.org/docs/rules/no-extra-spacing-attrs
|
|
141
141
|
*/
|
|
142
142
|
'@html-eslint/no-extra-spacing-attrs'?: Linter.RuleEntry<HtmlEslintNoExtraSpacingAttrs>;
|
|
@@ -150,6 +150,10 @@ interface ESLintSchema {
|
|
|
150
150
|
* @see https://html-eslint.org/docs/rules/no-heading-inside-button
|
|
151
151
|
*/
|
|
152
152
|
'@html-eslint/no-heading-inside-button'?: Linter.RuleEntry<[]>;
|
|
153
|
+
/**
|
|
154
|
+
* Disallow HTML attributes that have no effect in their context
|
|
155
|
+
*/
|
|
156
|
+
'@html-eslint/no-ineffective-attrs'?: Linter.RuleEntry<[]>;
|
|
153
157
|
/**
|
|
154
158
|
* Disallow using inline style
|
|
155
159
|
* @see https://html-eslint.org/docs/rules/no-inline-styles
|
|
@@ -186,7 +190,7 @@ interface ESLintSchema {
|
|
|
186
190
|
*/
|
|
187
191
|
'@html-eslint/no-non-scalable-viewport'?: Linter.RuleEntry<[]>;
|
|
188
192
|
/**
|
|
189
|
-
* Disallow
|
|
193
|
+
* Disallow use of obsolete elements in HTML5
|
|
190
194
|
* @see https://html-eslint.org/docs/rules/no-obsolete-tags
|
|
191
195
|
*/
|
|
192
196
|
'@html-eslint/no-obsolete-tags'?: Linter.RuleEntry<[]>;
|
|
@@ -241,7 +245,7 @@ interface ESLintSchema {
|
|
|
241
245
|
*/
|
|
242
246
|
'@html-eslint/require-attrs'?: Linter.RuleEntry<HtmlEslintRequireAttrs>;
|
|
243
247
|
/**
|
|
244
|
-
* Require use of button element with a valid type attribute.
|
|
248
|
+
* Require use of the button element with a valid type attribute.
|
|
245
249
|
* @see https://html-eslint.org/docs/rules/require-button-type
|
|
246
250
|
*/
|
|
247
251
|
'@html-eslint/require-button-type'?: Linter.RuleEntry<[]>;
|
|
@@ -251,7 +255,7 @@ interface ESLintSchema {
|
|
|
251
255
|
*/
|
|
252
256
|
'@html-eslint/require-closing-tags'?: Linter.RuleEntry<HtmlEslintRequireClosingTags>;
|
|
253
257
|
/**
|
|
254
|
-
* Require `<!DOCTYPE HTML>` in
|
|
258
|
+
* Require `<!DOCTYPE HTML>` in HTML
|
|
255
259
|
* @see https://html-eslint.org/docs/rules/require-doctype
|
|
256
260
|
*/
|
|
257
261
|
'@html-eslint/require-doctype'?: Linter.RuleEntry<[]>;
|
|
@@ -271,7 +275,7 @@ interface ESLintSchema {
|
|
|
271
275
|
*/
|
|
272
276
|
'@html-eslint/require-frame-title'?: Linter.RuleEntry<[]>;
|
|
273
277
|
/**
|
|
274
|
-
* Require `alt` attribute
|
|
278
|
+
* Require `alt` attribute on `<img>` tag
|
|
275
279
|
* @see https://html-eslint.org/docs/rules/require-img-alt
|
|
276
280
|
*/
|
|
277
281
|
'@html-eslint/require-img-alt'?: Linter.RuleEntry<HtmlEslintRequireImgAlt>;
|
|
@@ -281,17 +285,17 @@ interface ESLintSchema {
|
|
|
281
285
|
*/
|
|
282
286
|
'@html-eslint/require-input-label'?: Linter.RuleEntry<[]>;
|
|
283
287
|
/**
|
|
284
|
-
* Require `lang` attribute
|
|
288
|
+
* Require `lang` attribute on `<html>` tag
|
|
285
289
|
* @see https://html-eslint.org/docs/rules/require-lang
|
|
286
290
|
*/
|
|
287
291
|
'@html-eslint/require-lang'?: Linter.RuleEntry<[]>;
|
|
288
292
|
/**
|
|
289
|
-
* Enforce `<li>` to be in
|
|
293
|
+
* Enforce `<li>` to be in `<ul>`, `<ol>` or `<menu>`.
|
|
290
294
|
* @see https://html-eslint.org/docs/rules/require-li-container
|
|
291
295
|
*/
|
|
292
296
|
'@html-eslint/require-li-container'?: Linter.RuleEntry<[]>;
|
|
293
297
|
/**
|
|
294
|
-
* Enforce
|
|
298
|
+
* Enforce use of `<meta charset="...">` in `<head>`
|
|
295
299
|
* @see https://html-eslint.org/docs/rules/require-meta-charset
|
|
296
300
|
*/
|
|
297
301
|
'@html-eslint/require-meta-charset'?: Linter.RuleEntry<[]>;
|
|
@@ -301,22 +305,22 @@ interface ESLintSchema {
|
|
|
301
305
|
*/
|
|
302
306
|
'@html-eslint/require-meta-description'?: Linter.RuleEntry<[]>;
|
|
303
307
|
/**
|
|
304
|
-
* Enforce
|
|
308
|
+
* Enforce use of `<meta name="viewport">` in `<head>`
|
|
305
309
|
* @see https://html-eslint.org/docs/rules/require-meta-viewport
|
|
306
310
|
*/
|
|
307
311
|
'@html-eslint/require-meta-viewport'?: Linter.RuleEntry<[]>;
|
|
308
312
|
/**
|
|
309
|
-
* Enforce
|
|
313
|
+
* Enforce use of specified meta tags for open graph protocol.
|
|
310
314
|
* @see https://html-eslint.org/docs/rules/require-open-graph-protocol
|
|
311
315
|
*/
|
|
312
316
|
'@html-eslint/require-open-graph-protocol'?: Linter.RuleEntry<HtmlEslintRequireOpenGraphProtocol>;
|
|
313
317
|
/**
|
|
314
|
-
* Require `<title
|
|
318
|
+
* Require `<title>` in the `<head>`
|
|
315
319
|
* @see https://html-eslint.org/docs/rules/require-title
|
|
316
320
|
*/
|
|
317
321
|
'@html-eslint/require-title'?: Linter.RuleEntry<[]>;
|
|
318
322
|
/**
|
|
319
|
-
* Enforce
|
|
323
|
+
* Enforce priority and alphabetical sorting of attributes
|
|
320
324
|
* @see https://html-eslint.org/docs/rules/sort-attrs
|
|
321
325
|
*/
|
|
322
326
|
'@html-eslint/sort-attrs'?: Linter.RuleEntry<HtmlEslintSortAttrs>;
|
|
@@ -4741,6 +4745,16 @@ interface ESLintSchema {
|
|
|
4741
4745
|
* @see https://eslint.vuejs.org/rules/no-mutating-props.html
|
|
4742
4746
|
*/
|
|
4743
4747
|
'vue/no-mutating-props'?: Linter.RuleEntry<VueNoMutatingProps>;
|
|
4748
|
+
/**
|
|
4749
|
+
* Disallow negated conditions in `<template>`
|
|
4750
|
+
* @see https://eslint.vuejs.org/rules/no-negated-condition.html
|
|
4751
|
+
*/
|
|
4752
|
+
'vue/no-negated-condition'?: Linter.RuleEntry<[]>;
|
|
4753
|
+
/**
|
|
4754
|
+
* disallow negated conditions in v-if/v-else
|
|
4755
|
+
* @see https://eslint.vuejs.org/rules/no-negated-v-if-condition.html
|
|
4756
|
+
*/
|
|
4757
|
+
'vue/no-negated-v-if-condition'?: Linter.RuleEntry<[]>;
|
|
4744
4758
|
/**
|
|
4745
4759
|
* disallow parsing errors in `<template>`
|
|
4746
4760
|
* @see https://eslint.vuejs.org/rules/no-parsing-error.html
|
|
@@ -5616,6 +5630,7 @@ type HtmlEslintRequireAttrs = {
|
|
|
5616
5630
|
tag: string;
|
|
5617
5631
|
attr: string;
|
|
5618
5632
|
value?: string;
|
|
5633
|
+
message?: string;
|
|
5619
5634
|
}[];
|
|
5620
5635
|
// ----- @html-eslint/require-closing-tags -----
|
|
5621
5636
|
type HtmlEslintRequireClosingTags = [] | [{
|
|
@@ -5635,7 +5650,9 @@ type HtmlEslintRequireImgAlt = [] | [{
|
|
|
5635
5650
|
type HtmlEslintRequireOpenGraphProtocol = [] | [string[]];
|
|
5636
5651
|
// ----- @html-eslint/sort-attrs -----
|
|
5637
5652
|
type HtmlEslintSortAttrs = [] | [{
|
|
5638
|
-
priority?: string
|
|
5653
|
+
priority?: (string | {
|
|
5654
|
+
pattern: string;
|
|
5655
|
+
})[];
|
|
5639
5656
|
}];
|
|
5640
5657
|
// ----- @html-eslint/use-baseline -----
|
|
5641
5658
|
type HtmlEslintUseBaseline = [] | [{
|
|
@@ -9602,10 +9619,17 @@ type NoRestrictedExports = [] | [({
|
|
|
9602
9619
|
};
|
|
9603
9620
|
})];
|
|
9604
9621
|
// ----- no-restricted-globals -----
|
|
9605
|
-
type NoRestrictedGlobals = (string | {
|
|
9622
|
+
type NoRestrictedGlobals = ((string | {
|
|
9606
9623
|
name: string;
|
|
9607
9624
|
message?: string;
|
|
9608
|
-
})[]
|
|
9625
|
+
})[] | [] | [{
|
|
9626
|
+
globals: (string | {
|
|
9627
|
+
name: string;
|
|
9628
|
+
message?: string;
|
|
9629
|
+
})[];
|
|
9630
|
+
checkGlobalObject?: boolean;
|
|
9631
|
+
globalObjects?: string[];
|
|
9632
|
+
}]);
|
|
9609
9633
|
// ----- no-restricted-imports -----
|
|
9610
9634
|
type NoRestrictedImports = ((string | {
|
|
9611
9635
|
name: string;
|
|
@@ -9833,6 +9857,8 @@ type OneVar = [] | [(("always" | "never" | "consecutive") | {
|
|
|
9833
9857
|
var?: ("always" | "never" | "consecutive");
|
|
9834
9858
|
let?: ("always" | "never" | "consecutive");
|
|
9835
9859
|
const?: ("always" | "never" | "consecutive");
|
|
9860
|
+
using?: ("always" | "never" | "consecutive");
|
|
9861
|
+
awaitUsing?: ("always" | "never" | "consecutive");
|
|
9836
9862
|
} | {
|
|
9837
9863
|
initialized?: ("always" | "never" | "consecutive");
|
|
9838
9864
|
uninitialized?: ("always" | "never" | "consecutive");
|
|
@@ -11643,11 +11669,9 @@ type PlaywrightValidExpect = [] | [{
|
|
|
11643
11669
|
type PlaywrightValidTestTags = [] | [{
|
|
11644
11670
|
allowedTags?: (string | {
|
|
11645
11671
|
source?: string;
|
|
11646
|
-
[k: string]: unknown | undefined;
|
|
11647
11672
|
})[];
|
|
11648
11673
|
disallowedTags?: (string | {
|
|
11649
11674
|
source?: string;
|
|
11650
|
-
[k: string]: unknown | undefined;
|
|
11651
11675
|
})[];
|
|
11652
11676
|
}];
|
|
11653
11677
|
// ----- playwright/valid-title -----
|
|
@@ -12712,6 +12736,7 @@ type VueNoDeprecatedRouterLinkTagProp = [] | [{
|
|
|
12712
12736
|
// ----- vue/no-deprecated-slot-attribute -----
|
|
12713
12737
|
type VueNoDeprecatedSlotAttribute = [] | [{
|
|
12714
12738
|
ignore?: string[];
|
|
12739
|
+
ignoreParents?: string[];
|
|
12715
12740
|
}];
|
|
12716
12741
|
// ----- vue/no-dupe-keys -----
|
|
12717
12742
|
type VueNoDupeKeys = [] | [{
|
package/dist/utils/globs.js
CHANGED
|
@@ -18,9 +18,8 @@ const globs = {
|
|
|
18
18
|
src: `**/*.${srcExtensions}`,
|
|
19
19
|
restrictedExports: `**/{${restrictedExportsFolders.join(",")}}/**/*.${srcExtensions}`,
|
|
20
20
|
vue: `**/*.${vueExtensions}`,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
vueComponentNamesIgnore: `**/{layouts,pages}/**/(_|-)components/**/*.${vueExtensions}`,
|
|
21
|
+
vueServerComponents: `**/*.server.${vueExtensions}`,
|
|
22
|
+
vueAppErrorLayoutsPages: `**/{{app,error},{layouts,pages}/**/*}.${vueExtensions}`,
|
|
24
23
|
storybook: `**/*.(story|stories).${srcExtensions}`,
|
|
25
24
|
test: `**/{__tests__/*,*.{test,spec,cy,bench?(mark)}.${srcExtensions}`
|
|
26
25
|
};
|
|
@@ -13,6 +13,7 @@ function isPackageDetected(packageName, options = defaultOptions) {
|
|
|
13
13
|
if (!autoDetectDeps) return false;
|
|
14
14
|
const isPackageInstalled = isPackageExists(packageName, { paths: [path.resolve(packageDir)] });
|
|
15
15
|
if (isPackageInstalled) detectedPackages.push(packageName);
|
|
16
|
+
detectedPackages.sort();
|
|
16
17
|
return isPackageInstalled;
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -92,7 +92,8 @@ const defaultOptions = {
|
|
|
92
92
|
"img",
|
|
93
93
|
"picture",
|
|
94
94
|
"NuxtImg",
|
|
95
|
-
"NuxtPicture"
|
|
95
|
+
"NuxtPicture",
|
|
96
|
+
"UBadge"
|
|
96
97
|
]
|
|
97
98
|
},
|
|
98
99
|
blocksOrder: [
|
|
@@ -122,8 +123,8 @@ const defaultOptions = {
|
|
|
122
123
|
"LIST_RENDERING",
|
|
123
124
|
"UNIQUE",
|
|
124
125
|
"GLOBAL",
|
|
125
|
-
"TWO_WAY_BINDING",
|
|
126
126
|
"SLOT",
|
|
127
|
+
"TWO_WAY_BINDING",
|
|
127
128
|
"CONTENT",
|
|
128
129
|
"OTHER_DIRECTIVES",
|
|
129
130
|
"EVENTS",
|
|
@@ -5,6 +5,17 @@ import { createDefu } from "defu";
|
|
|
5
5
|
|
|
6
6
|
//#region src/utils/options/mergeWithDefaults.ts
|
|
7
7
|
const mergeOptions = createDefu((object, key, value) => {
|
|
8
|
+
const stringKey = key.toString();
|
|
9
|
+
const uniqueArrayOptions = [
|
|
10
|
+
"allowedRelativeFontUnits",
|
|
11
|
+
"macrosOrder",
|
|
12
|
+
"blocksOrder",
|
|
13
|
+
"attributesOrder"
|
|
14
|
+
];
|
|
15
|
+
if (uniqueArrayOptions.includes(stringKey)) {
|
|
16
|
+
object[key] = value;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
8
19
|
const isValueTrue = value === true;
|
|
9
20
|
const isDefaultValueFalse = object[key] === false;
|
|
10
21
|
const isValueEmptyString = isEmptyString(value);
|
|
@@ -18,7 +18,7 @@ function getRestrictedVueElements(prefix) {
|
|
|
18
18
|
const restrictedElements = [];
|
|
19
19
|
for (const [element, component] of alternativeComponentPairs) restrictedElements.push({
|
|
20
20
|
element,
|
|
21
|
-
message: `Use
|
|
21
|
+
message: `Use \`<${prefix}${component}>\`.`
|
|
22
22
|
});
|
|
23
23
|
return restrictedElements;
|
|
24
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shayanthenerd/eslint-config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "A modern, flexible ESLint configuration for enforcing best practices and maintaining a consistent coding style",
|
|
6
6
|
"keywords": [
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"#configs/*": "./src/configs/*"
|
|
53
53
|
},
|
|
54
54
|
"type": "module",
|
|
55
|
-
"packageManager": "bun@1.2.
|
|
55
|
+
"packageManager": "bun@1.2.21",
|
|
56
56
|
"scripts": {
|
|
57
|
-
"prepare": "bun
|
|
57
|
+
"prepare": "bun git:gitmessage && bunx simple-git-hooks && bun generate:types",
|
|
58
58
|
"prepublishOnly": "bun build:package",
|
|
59
|
-
"
|
|
59
|
+
"git:gitmessage": "git config --local commit.template \".gitmessage\"",
|
|
60
60
|
"inspect": "bunx @eslint/config-inspector",
|
|
61
61
|
"build:package": "tsdown --no-report",
|
|
62
62
|
"build:inspector": "bunx @eslint/config-inspector build --config=./scripts/defaultESLintConfigReference.ts",
|
|
@@ -75,48 +75,48 @@
|
|
|
75
75
|
"pre-commit": "./node_modules/.bin/nano-staged"
|
|
76
76
|
},
|
|
77
77
|
"nano-staged": {
|
|
78
|
-
"**/*.{
|
|
79
|
-
"**/*.{
|
|
80
|
-
"oxlint --fix",
|
|
81
|
-
"eslint --fix --cache --cache-location=./node_modules/.cache/.eslintcache"
|
|
82
|
-
]
|
|
78
|
+
"**/*.{js,ts}": "bun lint",
|
|
79
|
+
"**/*.{json,jsonc,yaml,yml,lock}": "bun format"
|
|
83
80
|
},
|
|
84
81
|
"dependencies": {
|
|
85
|
-
"@eslint/compat": "1.3.
|
|
82
|
+
"@eslint/compat": "1.3.2",
|
|
86
83
|
"@eslint/css": "0.10.0",
|
|
87
|
-
"@eslint/js": "9.
|
|
88
|
-
"@html-eslint/eslint-plugin": "0.
|
|
89
|
-
"@stylistic/eslint-plugin": "5.2.
|
|
84
|
+
"@eslint/js": "9.34.0",
|
|
85
|
+
"@html-eslint/eslint-plugin": "0.46.1",
|
|
86
|
+
"@stylistic/eslint-plugin": "5.2.3",
|
|
90
87
|
"@vitest/eslint-plugin": "1.3.4",
|
|
91
88
|
"defu": "6.1.4",
|
|
92
|
-
"eslint": "9.
|
|
89
|
+
"eslint": "9.34.0",
|
|
93
90
|
"eslint-flat-config-utils": "2.1.1",
|
|
94
91
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
95
|
-
"eslint-plugin-better-tailwindcss": "3.7.
|
|
96
|
-
"eslint-plugin-cypress": "5.1.
|
|
92
|
+
"eslint-plugin-better-tailwindcss": "3.7.5",
|
|
93
|
+
"eslint-plugin-cypress": "5.1.1",
|
|
97
94
|
"eslint-plugin-import-x": "4.16.1",
|
|
98
|
-
"eslint-plugin-oxlint": "1.
|
|
95
|
+
"eslint-plugin-oxlint": "1.13.0",
|
|
99
96
|
"eslint-plugin-perfectionist": "4.15.0",
|
|
100
|
-
"eslint-plugin-playwright": "2.2.
|
|
101
|
-
"eslint-plugin-storybook": "9.
|
|
102
|
-
"eslint-plugin-unused-imports": "4.
|
|
103
|
-
"eslint-plugin-vue": "10.
|
|
97
|
+
"eslint-plugin-playwright": "2.2.2",
|
|
98
|
+
"eslint-plugin-storybook": "9.1.3",
|
|
99
|
+
"eslint-plugin-unused-imports": "4.2.0",
|
|
100
|
+
"eslint-plugin-vue": "10.4.0",
|
|
104
101
|
"eslint-plugin-vuejs-accessibility": "2.4.1",
|
|
105
102
|
"globals": "16.3.0",
|
|
106
|
-
"local-pkg": "1.1.
|
|
107
|
-
"oxlint": "1.
|
|
108
|
-
"tailwind-csstree": "0.1.
|
|
109
|
-
"typescript-eslint": "8.
|
|
103
|
+
"local-pkg": "1.1.2",
|
|
104
|
+
"oxlint": "1.13.0",
|
|
105
|
+
"tailwind-csstree": "0.1.3",
|
|
106
|
+
"typescript-eslint": "8.41.0"
|
|
110
107
|
},
|
|
111
108
|
"devDependencies": {
|
|
112
|
-
"@types/node": "24.
|
|
109
|
+
"@types/node": "24.3.0",
|
|
113
110
|
"eslint-typegen": "2.3.0",
|
|
114
|
-
"lint-staged": "16.1.2",
|
|
115
111
|
"nano-staged": "0.8.0",
|
|
116
112
|
"prettier": "3.6.2",
|
|
117
113
|
"publint": "0.3.12",
|
|
118
|
-
"tsdown": "0.
|
|
119
|
-
"typescript": "5.
|
|
120
|
-
"unplugin-unused": "0.5.
|
|
121
|
-
}
|
|
114
|
+
"tsdown": "0.14.2",
|
|
115
|
+
"typescript": "5.9.2",
|
|
116
|
+
"unplugin-unused": "0.5.2"
|
|
117
|
+
},
|
|
118
|
+
"trustedDependencies": [
|
|
119
|
+
"esbuild",
|
|
120
|
+
"unrs-resolver"
|
|
121
|
+
]
|
|
122
122
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { globs } from "../utils/globs.js";
|
|
2
|
-
|
|
3
|
-
//#region src/configs/nuxtMultiRootTemplate.ts
|
|
4
|
-
function getNuxtMultiRootTemplateConfig() {
|
|
5
|
-
const nuxtMultiRootTemplateConfig = {
|
|
6
|
-
name: "shayanthenerd/nuxt/allow-multiple-template-root",
|
|
7
|
-
files: [globs.vueMultiRootTemplate],
|
|
8
|
-
rules: { "vue/no-multiple-template-root": "off" }
|
|
9
|
-
};
|
|
10
|
-
return nuxtMultiRootTemplateConfig;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
//#endregion
|
|
14
|
-
export { getNuxtMultiRootTemplateConfig };
|