@html-eslint/eslint-plugin 0.51.0 → 0.52.0
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/lib/configs/recommended.js +8 -2
- package/lib/index.js +2 -6
- package/lib/languages/html-language.js +23 -15
- package/lib/languages/html-source-code.js +34 -26
- package/lib/languages/html-traversal-step.js +6 -10
- package/lib/rules/attrs-newline.js +9 -9
- package/lib/rules/class-spacing.js +148 -0
- package/lib/rules/element-newline.js +18 -21
- package/lib/rules/id-naming-convention.js +15 -12
- package/lib/rules/indent/indent-level.js +10 -17
- package/lib/rules/indent/indent.js +51 -56
- package/lib/rules/index.js +5 -1
- package/lib/rules/lowercase.js +11 -23
- package/lib/rules/max-element-depth.js +8 -10
- package/lib/rules/no-abstract-roles.js +8 -8
- package/lib/rules/no-accesskey-attrs.js +8 -8
- package/lib/rules/no-aria-hidden-body.js +2 -6
- package/lib/rules/no-aria-hidden-on-focusable.js +4 -5
- package/lib/rules/no-duplicate-attrs.js +12 -8
- package/lib/rules/no-duplicate-class.js +8 -14
- package/lib/rules/no-duplicate-id.js +9 -15
- package/lib/rules/no-duplicate-in-head.js +10 -17
- package/lib/rules/no-empty-headings.js +7 -8
- package/lib/rules/no-extra-spacing-attrs.js +13 -8
- package/lib/rules/no-extra-spacing-text.js +11 -14
- package/lib/rules/no-heading-inside-button.js +2 -6
- package/lib/rules/no-ineffective-attrs.js +14 -15
- package/lib/rules/no-inline-styles.js +2 -6
- package/lib/rules/no-invalid-entity.js +4 -8
- package/lib/rules/no-invalid-role.js +3 -10
- package/lib/rules/no-multiple-empty-lines.js +7 -7
- package/lib/rules/no-multiple-h1.js +4 -8
- package/lib/rules/no-nested-interactive.js +5 -9
- package/lib/rules/no-non-scalable-viewport.js +2 -6
- package/lib/rules/no-obsolete-attrs.js +83 -0
- package/lib/rules/no-obsolete-tags.js +2 -6
- package/lib/rules/no-positive-tabindex.js +8 -8
- package/lib/rules/no-restricted-attr-values.js +18 -21
- package/lib/rules/no-restricted-attrs.js +18 -22
- package/lib/rules/no-restricted-tags.js +17 -20
- package/lib/rules/no-script-style-type.js +7 -6
- package/lib/rules/no-skip-heading-levels.js +4 -8
- package/lib/rules/no-target-blank.js +3 -6
- package/lib/rules/no-trailing-spaces.js +7 -6
- package/lib/rules/no-whitespace-only-children.js +7 -8
- package/lib/rules/prefer-https.js +11 -14
- package/lib/rules/quotes.js +13 -16
- package/lib/rules/require-attrs.js +18 -17
- package/lib/rules/require-button-type.js +6 -5
- package/lib/rules/require-closing-tags.js +9 -12
- package/lib/rules/require-doctype.js +2 -6
- package/lib/rules/require-explicit-size.js +2 -5
- package/lib/rules/require-form-method.js +2 -6
- package/lib/rules/require-frame-title.js +2 -6
- package/lib/rules/require-img-alt.js +3 -6
- package/lib/rules/require-input-label.js +3 -5
- package/lib/rules/require-lang.js +2 -6
- package/lib/rules/require-li-container.js +2 -6
- package/lib/rules/require-meta-charset.js +6 -5
- package/lib/rules/require-meta-description.js +6 -5
- package/lib/rules/require-meta-viewport.js +6 -5
- package/lib/rules/require-open-graph-protocol.js +7 -8
- package/lib/rules/require-title.js +7 -5
- package/lib/rules/sort-attrs.js +13 -19
- package/lib/rules/use-baseline.js +8 -6
- package/lib/rules/utils/baseline.js +4 -6
- package/lib/rules/utils/naming.js +14 -7
- package/lib/rules/utils/node.js +63 -29
- package/lib/rules/utils/rule.js +1 -4
- package/lib/rules/utils/settings.js +9 -3
- package/lib/rules/utils/source-code.js +2 -6
- package/lib/rules/utils/template-literal.js +16 -7
- package/lib/rules/utils/visitors.js +4 -1
- package/lib/specs/index.js +5 -0
- package/lib/specs/obsolete-attrs.js +604 -0
- package/lib/types/ast.ts +5 -2
- package/package.json +6 -6
- package/types/configs/recommended.d.ts +2 -1
- package/types/configs/recommended.d.ts.map +1 -1
- package/types/index.d.ts +2 -6
- package/types/index.d.ts.map +1 -1
- package/types/languages/html-language.d.ts +12 -10
- package/types/languages/html-language.d.ts.map +1 -1
- package/types/languages/html-source-code.d.ts +13 -6
- package/types/languages/html-source-code.d.ts.map +1 -1
- package/types/languages/html-traversal-step.d.ts +5 -5
- package/types/languages/html-traversal-step.d.ts.map +1 -1
- package/types/rules/attrs-newline.d.ts +1 -1
- package/types/rules/attrs-newline.d.ts.map +1 -1
- package/types/rules/class-spacing.d.ts +4 -0
- package/types/rules/class-spacing.d.ts.map +1 -0
- package/types/rules/element-newline.d.ts +3 -3
- package/types/rules/element-newline.d.ts.map +1 -1
- package/types/rules/id-naming-convention.d.ts.map +1 -1
- package/types/rules/indent/indent-level.d.ts +10 -17
- package/types/rules/indent/indent-level.d.ts.map +1 -1
- package/types/rules/indent/indent.d.ts.map +1 -1
- package/types/rules/lowercase.d.ts.map +1 -1
- package/types/rules/max-element-depth.d.ts.map +1 -1
- package/types/rules/no-abstract-roles.d.ts.map +1 -1
- package/types/rules/no-accesskey-attrs.d.ts.map +1 -1
- package/types/rules/no-aria-hidden-body.d.ts.map +1 -1
- package/types/rules/no-aria-hidden-on-focusable.d.ts.map +1 -1
- package/types/rules/no-duplicate-attrs.d.ts.map +1 -1
- package/types/rules/no-duplicate-class.d.ts.map +1 -1
- package/types/rules/no-duplicate-id.d.ts.map +1 -1
- package/types/rules/no-duplicate-in-head.d.ts.map +1 -1
- package/types/rules/no-empty-headings.d.ts.map +1 -1
- package/types/rules/no-extra-spacing-attrs.d.ts.map +1 -1
- package/types/rules/no-extra-spacing-text.d.ts.map +1 -1
- package/types/rules/no-heading-inside-button.d.ts.map +1 -1
- package/types/rules/no-ineffective-attrs.d.ts.map +1 -1
- package/types/rules/no-inline-styles.d.ts.map +1 -1
- package/types/rules/no-invalid-entity.d.ts.map +1 -1
- package/types/rules/no-invalid-role.d.ts.map +1 -1
- package/types/rules/no-multiple-empty-lines.d.ts.map +1 -1
- package/types/rules/no-multiple-h1.d.ts.map +1 -1
- package/types/rules/no-nested-interactive.d.ts.map +1 -1
- package/types/rules/no-non-scalable-viewport.d.ts.map +1 -1
- package/types/rules/no-obsolete-attrs.d.ts +4 -0
- package/types/rules/no-obsolete-attrs.d.ts.map +1 -0
- package/types/rules/no-obsolete-tags.d.ts.map +1 -1
- package/types/rules/no-positive-tabindex.d.ts.map +1 -1
- package/types/rules/no-restricted-attr-values.d.ts.map +1 -1
- package/types/rules/no-restricted-attrs.d.ts.map +1 -1
- package/types/rules/no-restricted-tags.d.ts.map +1 -1
- package/types/rules/no-script-style-type.d.ts.map +1 -1
- package/types/rules/no-skip-heading-levels.d.ts.map +1 -1
- package/types/rules/no-target-blank.d.ts.map +1 -1
- package/types/rules/no-trailing-spaces.d.ts.map +1 -1
- package/types/rules/no-whitespace-only-children.d.ts.map +1 -1
- package/types/rules/prefer-https.d.ts.map +1 -1
- package/types/rules/quotes.d.ts.map +1 -1
- package/types/rules/require-attrs.d.ts.map +1 -1
- package/types/rules/require-button-type.d.ts.map +1 -1
- package/types/rules/require-closing-tags.d.ts.map +1 -1
- package/types/rules/require-doctype.d.ts.map +1 -1
- package/types/rules/require-explicit-size.d.ts.map +1 -1
- package/types/rules/require-form-method.d.ts.map +1 -1
- package/types/rules/require-frame-title.d.ts.map +1 -1
- package/types/rules/require-img-alt.d.ts.map +1 -1
- package/types/rules/require-input-label.d.ts.map +1 -1
- package/types/rules/require-lang.d.ts.map +1 -1
- package/types/rules/require-li-container.d.ts.map +1 -1
- package/types/rules/require-meta-charset.d.ts.map +1 -1
- package/types/rules/require-meta-description.d.ts.map +1 -1
- package/types/rules/require-meta-viewport.d.ts.map +1 -1
- package/types/rules/require-open-graph-protocol.d.ts.map +1 -1
- package/types/rules/require-title.d.ts.map +1 -1
- package/types/rules/sort-attrs.d.ts.map +1 -1
- package/types/rules/use-baseline.d.ts.map +1 -1
- package/types/rules/utils/baseline.d.ts +1 -3
- package/types/rules/utils/baseline.d.ts.map +1 -1
- package/types/rules/utils/naming.d.ts +14 -7
- package/types/rules/utils/naming.d.ts.map +1 -1
- package/types/rules/utils/node.d.ts +11 -10
- package/types/rules/utils/node.d.ts.map +1 -1
- package/types/rules/utils/rule.d.ts +1 -4
- package/types/rules/utils/rule.d.ts.map +1 -1
- package/types/rules/utils/settings.d.ts +0 -1
- package/types/rules/utils/settings.d.ts.map +1 -1
- package/types/rules/utils/source-code.d.ts +2 -6
- package/types/rules/utils/source-code.d.ts.map +1 -1
- package/types/rules/utils/template-literal.d.ts +2 -1
- package/types/rules/utils/template-literal.d.ts.map +1 -1
- package/types/rules/utils/visitors.d.ts.map +1 -1
- package/types/specs/index.d.ts +3 -0
- package/types/specs/index.d.ts.map +1 -0
- package/types/specs/obsolete-attrs.d.ts +19 -0
- package/types/specs/obsolete-attrs.d.ts.map +1 -0
- package/types/types/ast.d.ts +5 -2
- package/types/types/ast.d.ts.map +1 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* Tag,
|
|
4
|
+
* Text
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -15,9 +18,7 @@ const MESSAGE_IDS = {
|
|
|
15
18
|
|
|
16
19
|
const HEADING_NAMES = new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
17
20
|
|
|
18
|
-
/**
|
|
19
|
-
* @param {Tag} node
|
|
20
|
-
*/
|
|
21
|
+
/** @param {Tag} node */
|
|
21
22
|
function isAriaHidden(node) {
|
|
22
23
|
const ariaHiddenAttr = findAttr(node, "aria-hidden");
|
|
23
24
|
return (
|
|
@@ -85,9 +86,7 @@ function getAccessibleText(node) {
|
|
|
85
86
|
return text;
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
/**
|
|
89
|
-
* @type {RuleModule<[]>}
|
|
90
|
-
*/
|
|
89
|
+
/** @type {RuleModule<[]>} */
|
|
91
90
|
module.exports = {
|
|
92
91
|
meta: {
|
|
93
92
|
type: "code",
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* Attribute,
|
|
5
|
+
* OpenScriptTagStart,
|
|
6
|
+
* OpenStyleTagStart,
|
|
7
|
+
* OpenTagStart,
|
|
8
|
+
* ScriptTag,
|
|
9
|
+
* StyleTag,
|
|
10
|
+
* Tag
|
|
11
|
+
* } from "@html-eslint/types"
|
|
12
|
+
* @import {RuleModule} from "../types"
|
|
4
13
|
* @typedef {Object} Option
|
|
5
14
|
* @property {boolean} [Option.disallowInAssignment]
|
|
6
15
|
* @property {boolean} [Option.disallowMissing]
|
|
@@ -28,9 +37,7 @@ const MESSAGE_IDS = {
|
|
|
28
37
|
EXTRA_TAB_BETWEEN: "unexpectedTabBetween",
|
|
29
38
|
};
|
|
30
39
|
|
|
31
|
-
/**
|
|
32
|
-
* @type {RuleModule<[Option]>}
|
|
33
|
-
*/
|
|
40
|
+
/** @type {RuleModule<[Option]>} */
|
|
34
41
|
module.exports = {
|
|
35
42
|
meta: {
|
|
36
43
|
type: "code",
|
|
@@ -93,9 +100,7 @@ module.exports = {
|
|
|
93
100
|
|
|
94
101
|
const sourceCode = getSourceCode(context).text;
|
|
95
102
|
|
|
96
|
-
/**
|
|
97
|
-
* @param {Attribute[]} attrs
|
|
98
|
-
*/
|
|
103
|
+
/** @param {Attribute[]} attrs */
|
|
99
104
|
function checkExtraSpacesBetweenAttrs(attrs) {
|
|
100
105
|
attrs.forEach((current, index, attrs) => {
|
|
101
106
|
if (index >= attrs.length - 1) {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* Comment,
|
|
4
|
+
* CommentContent,
|
|
5
|
+
* Tag,
|
|
6
|
+
* Text
|
|
7
|
+
* } from "@html-eslint/types"
|
|
8
|
+
* @import {RuleModule} from "../types"
|
|
4
9
|
* @typedef {Object} Option
|
|
5
10
|
* @property {string[]} [Option.skip]
|
|
6
11
|
*/
|
|
@@ -15,9 +20,7 @@ const MESSAGE_IDS = {
|
|
|
15
20
|
UNEXPECTED: "unexpected",
|
|
16
21
|
};
|
|
17
22
|
|
|
18
|
-
/**
|
|
19
|
-
* @type {RuleModule<[Option]>}
|
|
20
|
-
*/
|
|
23
|
+
/** @type {RuleModule<[Option]>} */
|
|
21
24
|
module.exports = {
|
|
22
25
|
meta: {
|
|
23
26
|
type: "code",
|
|
@@ -52,14 +55,10 @@ module.exports = {
|
|
|
52
55
|
|
|
53
56
|
create(context) {
|
|
54
57
|
const options = context.options[0] || {};
|
|
55
|
-
/**
|
|
56
|
-
* @type {string[]}
|
|
57
|
-
*/
|
|
58
|
+
/** @type {string[]} */
|
|
58
59
|
const skipTags = options.skip || [];
|
|
59
60
|
const sourceCode = getSourceCode(context);
|
|
60
|
-
/**
|
|
61
|
-
* @type {Tag[]}
|
|
62
|
-
*/
|
|
61
|
+
/** @type {Tag[]} */
|
|
63
62
|
const tagStack = [];
|
|
64
63
|
|
|
65
64
|
/**
|
|
@@ -80,9 +79,7 @@ module.exports = {
|
|
|
80
79
|
return false;
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
/**
|
|
84
|
-
* @param {CommentContent | Text} node
|
|
85
|
-
*/
|
|
82
|
+
/** @param {CommentContent | Text} node */
|
|
86
83
|
function stripConsecutiveSpaces(node) {
|
|
87
84
|
const text = node.value;
|
|
88
85
|
const matcher = /(^|[^\n \t])([ \t]+\n|\t[\t ]*|[ \t]{2,})/g;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
4
|
const { findParent, isTag } = require("./utils/node");
|
|
@@ -13,9 +11,7 @@ const MESSAGE_IDS = {
|
|
|
13
11
|
|
|
14
12
|
const HEADING_NAMES = new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
15
13
|
|
|
16
|
-
/**
|
|
17
|
-
* @type {RuleModule<[]>}
|
|
18
|
-
*/
|
|
14
|
+
/** @type {RuleModule<[]>} */
|
|
19
15
|
module.exports = {
|
|
20
16
|
meta: {
|
|
21
17
|
type: "code",
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* ScriptTag,
|
|
4
|
+
* Tag
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
7
|
+
* @typedef {{
|
|
8
|
+
* attr: string;
|
|
9
|
+
* when: (node: Tag | ScriptTag) => boolean;
|
|
10
|
+
* message: string;
|
|
11
|
+
* }} AttributeChecker
|
|
5
12
|
*/
|
|
6
13
|
|
|
7
14
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -32,9 +39,7 @@ function isTemplateValueAttr(node, attrName) {
|
|
|
32
39
|
return hasTemplate(attr.value);
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
/**
|
|
36
|
-
* @type {Record<string, AttributeChecker[]>}
|
|
37
|
-
*/
|
|
42
|
+
/** @type {Record<string, AttributeChecker[]>} */
|
|
38
43
|
const checkersByTag = {
|
|
39
44
|
input: [
|
|
40
45
|
{
|
|
@@ -110,9 +115,7 @@ const checkersByTag = {
|
|
|
110
115
|
],
|
|
111
116
|
};
|
|
112
117
|
|
|
113
|
-
/**
|
|
114
|
-
* @type {RuleModule<[]>}
|
|
115
|
-
*/
|
|
118
|
+
/** @type {RuleModule<[]>} */
|
|
116
119
|
module.exports = {
|
|
117
120
|
name: "no-ineffective-attrs",
|
|
118
121
|
meta: {
|
|
@@ -131,9 +134,7 @@ module.exports = {
|
|
|
131
134
|
defaultOptions: [],
|
|
132
135
|
create(context) {
|
|
133
136
|
return createVisitors(context, {
|
|
134
|
-
/**
|
|
135
|
-
* @param {Tag} node
|
|
136
|
-
*/
|
|
137
|
+
/** @param {Tag} node */
|
|
137
138
|
Tag(node) {
|
|
138
139
|
const tagCheckers = checkersByTag[node.name];
|
|
139
140
|
if (!tagCheckers) return;
|
|
@@ -155,9 +156,7 @@ module.exports = {
|
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
},
|
|
158
|
-
/**
|
|
159
|
-
* @param {ScriptTag} node
|
|
160
|
-
*/
|
|
159
|
+
/** @param {ScriptTag} node */
|
|
161
160
|
ScriptTag(node) {
|
|
162
161
|
const scriptCheckers = checkersByTag.script;
|
|
163
162
|
if (!scriptCheckers) return;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
4
|
const { findAttr } = require("./utils/node");
|
|
@@ -11,9 +9,7 @@ const MESSAGE_IDS = {
|
|
|
11
9
|
INLINE_STYLE: "unexpectedInlineStyle",
|
|
12
10
|
};
|
|
13
11
|
|
|
14
|
-
/**
|
|
15
|
-
* @type {RuleModule<[]>}
|
|
16
|
-
*/
|
|
12
|
+
/** @type {RuleModule<[]>} */
|
|
17
13
|
module.exports = {
|
|
18
14
|
meta: {
|
|
19
15
|
type: "code",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
* @import {
|
|
2
|
+
* @import {Text} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Define the type for entities.json
|
|
@@ -21,9 +21,7 @@ const MESSAGE_IDS = {
|
|
|
21
21
|
INVALID_ENTITY: "invalidEntity",
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
* @type {RuleModule<[]>}
|
|
26
|
-
*/
|
|
24
|
+
/** @type {RuleModule<[]>} */
|
|
27
25
|
module.exports = {
|
|
28
26
|
meta: {
|
|
29
27
|
type: "code",
|
|
@@ -42,9 +40,7 @@ module.exports = {
|
|
|
42
40
|
},
|
|
43
41
|
|
|
44
42
|
create(context) {
|
|
45
|
-
/**
|
|
46
|
-
* @param {Text} node
|
|
47
|
-
*/
|
|
43
|
+
/** @param {Text} node */
|
|
48
44
|
function check(node) {
|
|
49
45
|
const text = node.value;
|
|
50
46
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { NODE_TYPES } = require("@html-eslint/parser");
|
|
6
4
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -226,9 +224,7 @@ const ELEMENTS_DISALLOWING_PRESENTATION_OR_NONE_ROLE = new Set([
|
|
|
226
224
|
"wbr",
|
|
227
225
|
]);
|
|
228
226
|
|
|
229
|
-
/**
|
|
230
|
-
* @type {RuleModule<[]>}
|
|
231
|
-
*/
|
|
227
|
+
/** @type {RuleModule<[]>} */
|
|
232
228
|
module.exports = {
|
|
233
229
|
meta: {
|
|
234
230
|
type: "code",
|
|
@@ -256,10 +252,7 @@ module.exports = {
|
|
|
256
252
|
if (!role) {
|
|
257
253
|
return;
|
|
258
254
|
}
|
|
259
|
-
/**
|
|
260
|
-
* Allow template expression.
|
|
261
|
-
* ex: html`<div role=${role}></div>`
|
|
262
|
-
*/
|
|
255
|
+
/** Allow template expression. ex: html`<div role=${role}></div>` */
|
|
263
256
|
if (
|
|
264
257
|
role.value &&
|
|
265
258
|
role.value.parts.some((part) => part.type === NODE_TYPES.Template)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* CommentContent,
|
|
4
|
+
* Text
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
5
7
|
* @typedef {Object} Option
|
|
6
8
|
* @property {number} Option.max
|
|
7
9
|
*/
|
|
@@ -24,9 +26,7 @@ const MESSAGE_IDS = {
|
|
|
24
26
|
UNEXPECTED: "unexpected",
|
|
25
27
|
};
|
|
26
28
|
|
|
27
|
-
/**
|
|
28
|
-
* @type {RuleModule<[Option]>}
|
|
29
|
-
*/
|
|
29
|
+
/** @type {RuleModule<[Option]>} */
|
|
30
30
|
module.exports = {
|
|
31
31
|
meta: {
|
|
32
32
|
type: "code",
|
|
@@ -64,7 +64,7 @@ module.exports = {
|
|
|
64
64
|
/**
|
|
65
65
|
* @param {string[]} lines
|
|
66
66
|
* @param {number} lineOffset
|
|
67
|
-
* @param {(
|
|
67
|
+
* @param {(CommentContent | Text)["parts"][number][]} tokens
|
|
68
68
|
*/
|
|
69
69
|
function check(lines, lineOffset, tokens) {
|
|
70
70
|
/** @type {number[]} */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {Tag} from "@html-eslint/types"
|
|
3
|
-
* @import {RuleModule} from "../types"
|
|
2
|
+
* @import {Tag} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -10,9 +10,7 @@ const MESSAGE_IDS = {
|
|
|
10
10
|
MULTIPLE_H1: "unexpectedMultiH1",
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* @type {RuleModule<[]>}
|
|
15
|
-
*/
|
|
13
|
+
/** @type {RuleModule<[]>} */
|
|
16
14
|
module.exports = {
|
|
17
15
|
meta: {
|
|
18
16
|
type: "code",
|
|
@@ -32,9 +30,7 @@ module.exports = {
|
|
|
32
30
|
},
|
|
33
31
|
|
|
34
32
|
create(context) {
|
|
35
|
-
/**
|
|
36
|
-
* @type {Tag[]}
|
|
37
|
-
*/
|
|
33
|
+
/** @type {Tag[]} */
|
|
38
34
|
const h1s = [];
|
|
39
35
|
|
|
40
36
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {Tag} from "@html-eslint/types"
|
|
3
|
-
* @import {RuleModule} from "../types"
|
|
2
|
+
* @import {Tag} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -13,9 +13,9 @@ const MESSAGE_IDS = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content-2
|
|
17
16
|
* @param {Tag} tag
|
|
18
17
|
* @returns {boolean}
|
|
18
|
+
* @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content-2
|
|
19
19
|
*/
|
|
20
20
|
function isInteractive(tag) {
|
|
21
21
|
const tagName = tag.name.toLowerCase();
|
|
@@ -55,9 +55,7 @@ function isInteractive(tag) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
/**
|
|
59
|
-
* @type {RuleModule<[]>}
|
|
60
|
-
*/
|
|
58
|
+
/** @type {RuleModule<[]>} */
|
|
61
59
|
module.exports = {
|
|
62
60
|
meta: {
|
|
63
61
|
type: "code",
|
|
@@ -78,9 +76,7 @@ module.exports = {
|
|
|
78
76
|
},
|
|
79
77
|
|
|
80
78
|
create(context) {
|
|
81
|
-
/**
|
|
82
|
-
* @type {Tag[]}
|
|
83
|
-
*/
|
|
79
|
+
/** @type {Tag[]} */
|
|
84
80
|
let interactiveStack = [];
|
|
85
81
|
|
|
86
82
|
return createVisitors(context, {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
4
|
const { findAttr } = require("./utils/node");
|
|
@@ -10,9 +8,7 @@ const MESSAGE_IDS = {
|
|
|
10
8
|
UNEXPECTED: "unexpected",
|
|
11
9
|
};
|
|
12
10
|
|
|
13
|
-
/**
|
|
14
|
-
* @type {RuleModule<[]>}
|
|
15
|
-
*/
|
|
11
|
+
/** @type {RuleModule<[]>} */
|
|
16
12
|
module.exports = {
|
|
17
13
|
meta: {
|
|
18
14
|
type: "code",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import {
|
|
3
|
+
* ScriptTag,
|
|
4
|
+
* StyleTag,
|
|
5
|
+
* Tag
|
|
6
|
+
* } from "@html-eslint/types"
|
|
7
|
+
* @import {RuleModule} from "../types"
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { RULE_CATEGORY } = require("../constants");
|
|
11
|
+
const { OBSOLETE_ATTRS } = require("../specs");
|
|
12
|
+
const { createVisitors } = require("./utils/visitors");
|
|
13
|
+
const { getRuleUrl } = require("./utils/rule");
|
|
14
|
+
const { getNameOf } = require("./utils/node");
|
|
15
|
+
|
|
16
|
+
const MESSAGE_IDS = {
|
|
17
|
+
UNEXPECTED: "unexpected",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** @type {RuleModule<[]>} */
|
|
21
|
+
module.exports = {
|
|
22
|
+
meta: {
|
|
23
|
+
type: "code",
|
|
24
|
+
|
|
25
|
+
docs: {
|
|
26
|
+
description: "Disallow use of obsolete attributes in HTML5",
|
|
27
|
+
category: RULE_CATEGORY.BEST_PRACTICE,
|
|
28
|
+
recommended: true,
|
|
29
|
+
url: getRuleUrl("no-obsolete-attrs"),
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
fixable: null,
|
|
33
|
+
schema: [],
|
|
34
|
+
messages: {
|
|
35
|
+
[MESSAGE_IDS.UNEXPECTED]:
|
|
36
|
+
"The {{attr}} attribute on <{{element}}> is obsolete. {{suggestion}}",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
create(context) {
|
|
41
|
+
/** @param {Tag | ScriptTag | StyleTag} node */
|
|
42
|
+
function checkObsoleteAttrs(node) {
|
|
43
|
+
const tagName = getNameOf(node);
|
|
44
|
+
// Check each attribute on the element
|
|
45
|
+
if (node.attributes) {
|
|
46
|
+
for (const attr of node.attributes) {
|
|
47
|
+
const attrName = attr.key.value.toLowerCase();
|
|
48
|
+
|
|
49
|
+
// Check if this attribute is in the obsolete list
|
|
50
|
+
if (OBSOLETE_ATTRS[attrName]) {
|
|
51
|
+
const obsoleteConfigs = OBSOLETE_ATTRS[attrName];
|
|
52
|
+
|
|
53
|
+
// Check if this attribute is obsolete for this specific element
|
|
54
|
+
for (const config of obsoleteConfigs) {
|
|
55
|
+
// Handle wildcard (*) for all elements
|
|
56
|
+
if (
|
|
57
|
+
config.elements.includes("*") ||
|
|
58
|
+
config.elements.includes(tagName)
|
|
59
|
+
) {
|
|
60
|
+
context.report({
|
|
61
|
+
node: attr,
|
|
62
|
+
messageId: MESSAGE_IDS.UNEXPECTED,
|
|
63
|
+
data: {
|
|
64
|
+
attr: attrName,
|
|
65
|
+
element: tagName,
|
|
66
|
+
suggestion: config.suggestion,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return createVisitors(context, {
|
|
78
|
+
Tag: checkObsoleteAttrs,
|
|
79
|
+
ScriptTag: checkObsoleteAttrs,
|
|
80
|
+
StyleTag: checkObsoleteAttrs,
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { RULE_CATEGORY, OBSOLETE_TAGS } = require("../constants");
|
|
6
4
|
const { createVisitors } = require("./utils/visitors");
|
|
@@ -12,9 +10,7 @@ const MESSAGE_IDS = {
|
|
|
12
10
|
UNEXPECTED: "unexpected",
|
|
13
11
|
};
|
|
14
12
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {RuleModule<[]>}
|
|
17
|
-
*/
|
|
13
|
+
/** @type {RuleModule<[]>} */
|
|
18
14
|
module.exports = {
|
|
19
15
|
meta: {
|
|
20
16
|
type: "code",
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* ScriptTag,
|
|
4
|
+
* StyleTag,
|
|
5
|
+
* Tag
|
|
6
|
+
* } from "@html-eslint/types"
|
|
7
|
+
* @import {RuleModule} from "../types"
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -12,9 +16,7 @@ const MESSAGE_IDS = {
|
|
|
12
16
|
UNEXPECTED: "unexpected",
|
|
13
17
|
};
|
|
14
18
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {RuleModule<[]>}
|
|
17
|
-
*/
|
|
19
|
+
/** @type {RuleModule<[]>} */
|
|
18
20
|
module.exports = {
|
|
19
21
|
meta: {
|
|
20
22
|
type: "code",
|
|
@@ -34,9 +36,7 @@ module.exports = {
|
|
|
34
36
|
},
|
|
35
37
|
|
|
36
38
|
create(context) {
|
|
37
|
-
/**
|
|
38
|
-
* @param {Tag | StyleTag | ScriptTag} node
|
|
39
|
-
*/
|
|
39
|
+
/** @param {Tag | StyleTag | ScriptTag} node */
|
|
40
40
|
function check(node) {
|
|
41
41
|
const tabIndexAttr = findAttr(node, "tabindex");
|
|
42
42
|
if (
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* Attribute,
|
|
4
|
+
* ScriptTag,
|
|
5
|
+
* StyleTag,
|
|
6
|
+
* Tag
|
|
7
|
+
* } from "@html-eslint/types"
|
|
8
|
+
* @import {RuleModule} from "../types"
|
|
9
|
+
* @typedef {{
|
|
10
|
+
* attrPatterns: string[];
|
|
11
|
+
* attrValuePatterns: string[];
|
|
12
|
+
* message?: string;
|
|
13
|
+
* }[]} Options
|
|
5
14
|
*/
|
|
6
15
|
|
|
7
16
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -12,9 +21,7 @@ const MESSAGE_IDS = {
|
|
|
12
21
|
RESTRICTED: "restricted",
|
|
13
22
|
};
|
|
14
23
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {RuleModule<Options>}
|
|
17
|
-
*/
|
|
24
|
+
/** @type {RuleModule<Options>} */
|
|
18
25
|
module.exports = {
|
|
19
26
|
meta: {
|
|
20
27
|
type: "code",
|
|
@@ -60,14 +67,10 @@ module.exports = {
|
|
|
60
67
|
},
|
|
61
68
|
|
|
62
69
|
create(context) {
|
|
63
|
-
/**
|
|
64
|
-
* @type {Options}
|
|
65
|
-
*/
|
|
70
|
+
/** @type {Options} */
|
|
66
71
|
const options = context.options;
|
|
67
72
|
const checkers = options.map((option) => new PatternChecker(option));
|
|
68
|
-
/**
|
|
69
|
-
* @param {Tag | StyleTag | ScriptTag} node
|
|
70
|
-
*/
|
|
73
|
+
/** @param {Tag | StyleTag | ScriptTag} node */
|
|
71
74
|
function check(node) {
|
|
72
75
|
node.attributes.forEach((attr) => {
|
|
73
76
|
if (
|
|
@@ -88,9 +91,7 @@ module.exports = {
|
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
/**
|
|
92
|
-
* @type {{node: Attribute, message: string, messageId?: string}}
|
|
93
|
-
*/
|
|
94
|
+
/** @type {{ node: Attribute; message: string; messageId?: string }} */
|
|
94
95
|
const result = {
|
|
95
96
|
node: attr,
|
|
96
97
|
message: "",
|
|
@@ -120,9 +121,7 @@ module.exports = {
|
|
|
120
121
|
};
|
|
121
122
|
|
|
122
123
|
class PatternChecker {
|
|
123
|
-
/**
|
|
124
|
-
* @param {Options[number]} option
|
|
125
|
-
*/
|
|
124
|
+
/** @param {Options[number]} option */
|
|
126
125
|
constructor(option) {
|
|
127
126
|
this.option = option;
|
|
128
127
|
this.attrRegExps = option.attrPatterns.map(
|
|
@@ -147,9 +146,7 @@ class PatternChecker {
|
|
|
147
146
|
return result;
|
|
148
147
|
}
|
|
149
148
|
|
|
150
|
-
/**
|
|
151
|
-
* @returns {string}
|
|
152
|
-
*/
|
|
149
|
+
/** @returns {string} */
|
|
153
150
|
getMessage() {
|
|
154
151
|
return this.message || "";
|
|
155
152
|
}
|