@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.
Files changed (172) hide show
  1. package/lib/configs/recommended.js +8 -2
  2. package/lib/index.js +2 -6
  3. package/lib/languages/html-language.js +23 -15
  4. package/lib/languages/html-source-code.js +34 -26
  5. package/lib/languages/html-traversal-step.js +6 -10
  6. package/lib/rules/attrs-newline.js +9 -9
  7. package/lib/rules/class-spacing.js +148 -0
  8. package/lib/rules/element-newline.js +18 -21
  9. package/lib/rules/id-naming-convention.js +15 -12
  10. package/lib/rules/indent/indent-level.js +10 -17
  11. package/lib/rules/indent/indent.js +51 -56
  12. package/lib/rules/index.js +5 -1
  13. package/lib/rules/lowercase.js +11 -23
  14. package/lib/rules/max-element-depth.js +8 -10
  15. package/lib/rules/no-abstract-roles.js +8 -8
  16. package/lib/rules/no-accesskey-attrs.js +8 -8
  17. package/lib/rules/no-aria-hidden-body.js +2 -6
  18. package/lib/rules/no-aria-hidden-on-focusable.js +4 -5
  19. package/lib/rules/no-duplicate-attrs.js +12 -8
  20. package/lib/rules/no-duplicate-class.js +8 -14
  21. package/lib/rules/no-duplicate-id.js +9 -15
  22. package/lib/rules/no-duplicate-in-head.js +10 -17
  23. package/lib/rules/no-empty-headings.js +7 -8
  24. package/lib/rules/no-extra-spacing-attrs.js +13 -8
  25. package/lib/rules/no-extra-spacing-text.js +11 -14
  26. package/lib/rules/no-heading-inside-button.js +2 -6
  27. package/lib/rules/no-ineffective-attrs.js +14 -15
  28. package/lib/rules/no-inline-styles.js +2 -6
  29. package/lib/rules/no-invalid-entity.js +4 -8
  30. package/lib/rules/no-invalid-role.js +3 -10
  31. package/lib/rules/no-multiple-empty-lines.js +7 -7
  32. package/lib/rules/no-multiple-h1.js +4 -8
  33. package/lib/rules/no-nested-interactive.js +5 -9
  34. package/lib/rules/no-non-scalable-viewport.js +2 -6
  35. package/lib/rules/no-obsolete-attrs.js +83 -0
  36. package/lib/rules/no-obsolete-tags.js +2 -6
  37. package/lib/rules/no-positive-tabindex.js +8 -8
  38. package/lib/rules/no-restricted-attr-values.js +18 -21
  39. package/lib/rules/no-restricted-attrs.js +18 -22
  40. package/lib/rules/no-restricted-tags.js +17 -20
  41. package/lib/rules/no-script-style-type.js +7 -6
  42. package/lib/rules/no-skip-heading-levels.js +4 -8
  43. package/lib/rules/no-target-blank.js +3 -6
  44. package/lib/rules/no-trailing-spaces.js +7 -6
  45. package/lib/rules/no-whitespace-only-children.js +7 -8
  46. package/lib/rules/prefer-https.js +11 -14
  47. package/lib/rules/quotes.js +13 -16
  48. package/lib/rules/require-attrs.js +18 -17
  49. package/lib/rules/require-button-type.js +6 -5
  50. package/lib/rules/require-closing-tags.js +9 -12
  51. package/lib/rules/require-doctype.js +2 -6
  52. package/lib/rules/require-explicit-size.js +2 -5
  53. package/lib/rules/require-form-method.js +2 -6
  54. package/lib/rules/require-frame-title.js +2 -6
  55. package/lib/rules/require-img-alt.js +3 -6
  56. package/lib/rules/require-input-label.js +3 -5
  57. package/lib/rules/require-lang.js +2 -6
  58. package/lib/rules/require-li-container.js +2 -6
  59. package/lib/rules/require-meta-charset.js +6 -5
  60. package/lib/rules/require-meta-description.js +6 -5
  61. package/lib/rules/require-meta-viewport.js +6 -5
  62. package/lib/rules/require-open-graph-protocol.js +7 -8
  63. package/lib/rules/require-title.js +7 -5
  64. package/lib/rules/sort-attrs.js +13 -19
  65. package/lib/rules/use-baseline.js +8 -6
  66. package/lib/rules/utils/baseline.js +4 -6
  67. package/lib/rules/utils/naming.js +14 -7
  68. package/lib/rules/utils/node.js +63 -29
  69. package/lib/rules/utils/rule.js +1 -4
  70. package/lib/rules/utils/settings.js +9 -3
  71. package/lib/rules/utils/source-code.js +2 -6
  72. package/lib/rules/utils/template-literal.js +16 -7
  73. package/lib/rules/utils/visitors.js +4 -1
  74. package/lib/specs/index.js +5 -0
  75. package/lib/specs/obsolete-attrs.js +604 -0
  76. package/lib/types/ast.ts +5 -2
  77. package/package.json +6 -6
  78. package/types/configs/recommended.d.ts +2 -1
  79. package/types/configs/recommended.d.ts.map +1 -1
  80. package/types/index.d.ts +2 -6
  81. package/types/index.d.ts.map +1 -1
  82. package/types/languages/html-language.d.ts +12 -10
  83. package/types/languages/html-language.d.ts.map +1 -1
  84. package/types/languages/html-source-code.d.ts +13 -6
  85. package/types/languages/html-source-code.d.ts.map +1 -1
  86. package/types/languages/html-traversal-step.d.ts +5 -5
  87. package/types/languages/html-traversal-step.d.ts.map +1 -1
  88. package/types/rules/attrs-newline.d.ts +1 -1
  89. package/types/rules/attrs-newline.d.ts.map +1 -1
  90. package/types/rules/class-spacing.d.ts +4 -0
  91. package/types/rules/class-spacing.d.ts.map +1 -0
  92. package/types/rules/element-newline.d.ts +3 -3
  93. package/types/rules/element-newline.d.ts.map +1 -1
  94. package/types/rules/id-naming-convention.d.ts.map +1 -1
  95. package/types/rules/indent/indent-level.d.ts +10 -17
  96. package/types/rules/indent/indent-level.d.ts.map +1 -1
  97. package/types/rules/indent/indent.d.ts.map +1 -1
  98. package/types/rules/lowercase.d.ts.map +1 -1
  99. package/types/rules/max-element-depth.d.ts.map +1 -1
  100. package/types/rules/no-abstract-roles.d.ts.map +1 -1
  101. package/types/rules/no-accesskey-attrs.d.ts.map +1 -1
  102. package/types/rules/no-aria-hidden-body.d.ts.map +1 -1
  103. package/types/rules/no-aria-hidden-on-focusable.d.ts.map +1 -1
  104. package/types/rules/no-duplicate-attrs.d.ts.map +1 -1
  105. package/types/rules/no-duplicate-class.d.ts.map +1 -1
  106. package/types/rules/no-duplicate-id.d.ts.map +1 -1
  107. package/types/rules/no-duplicate-in-head.d.ts.map +1 -1
  108. package/types/rules/no-empty-headings.d.ts.map +1 -1
  109. package/types/rules/no-extra-spacing-attrs.d.ts.map +1 -1
  110. package/types/rules/no-extra-spacing-text.d.ts.map +1 -1
  111. package/types/rules/no-heading-inside-button.d.ts.map +1 -1
  112. package/types/rules/no-ineffective-attrs.d.ts.map +1 -1
  113. package/types/rules/no-inline-styles.d.ts.map +1 -1
  114. package/types/rules/no-invalid-entity.d.ts.map +1 -1
  115. package/types/rules/no-invalid-role.d.ts.map +1 -1
  116. package/types/rules/no-multiple-empty-lines.d.ts.map +1 -1
  117. package/types/rules/no-multiple-h1.d.ts.map +1 -1
  118. package/types/rules/no-nested-interactive.d.ts.map +1 -1
  119. package/types/rules/no-non-scalable-viewport.d.ts.map +1 -1
  120. package/types/rules/no-obsolete-attrs.d.ts +4 -0
  121. package/types/rules/no-obsolete-attrs.d.ts.map +1 -0
  122. package/types/rules/no-obsolete-tags.d.ts.map +1 -1
  123. package/types/rules/no-positive-tabindex.d.ts.map +1 -1
  124. package/types/rules/no-restricted-attr-values.d.ts.map +1 -1
  125. package/types/rules/no-restricted-attrs.d.ts.map +1 -1
  126. package/types/rules/no-restricted-tags.d.ts.map +1 -1
  127. package/types/rules/no-script-style-type.d.ts.map +1 -1
  128. package/types/rules/no-skip-heading-levels.d.ts.map +1 -1
  129. package/types/rules/no-target-blank.d.ts.map +1 -1
  130. package/types/rules/no-trailing-spaces.d.ts.map +1 -1
  131. package/types/rules/no-whitespace-only-children.d.ts.map +1 -1
  132. package/types/rules/prefer-https.d.ts.map +1 -1
  133. package/types/rules/quotes.d.ts.map +1 -1
  134. package/types/rules/require-attrs.d.ts.map +1 -1
  135. package/types/rules/require-button-type.d.ts.map +1 -1
  136. package/types/rules/require-closing-tags.d.ts.map +1 -1
  137. package/types/rules/require-doctype.d.ts.map +1 -1
  138. package/types/rules/require-explicit-size.d.ts.map +1 -1
  139. package/types/rules/require-form-method.d.ts.map +1 -1
  140. package/types/rules/require-frame-title.d.ts.map +1 -1
  141. package/types/rules/require-img-alt.d.ts.map +1 -1
  142. package/types/rules/require-input-label.d.ts.map +1 -1
  143. package/types/rules/require-lang.d.ts.map +1 -1
  144. package/types/rules/require-li-container.d.ts.map +1 -1
  145. package/types/rules/require-meta-charset.d.ts.map +1 -1
  146. package/types/rules/require-meta-description.d.ts.map +1 -1
  147. package/types/rules/require-meta-viewport.d.ts.map +1 -1
  148. package/types/rules/require-open-graph-protocol.d.ts.map +1 -1
  149. package/types/rules/require-title.d.ts.map +1 -1
  150. package/types/rules/sort-attrs.d.ts.map +1 -1
  151. package/types/rules/use-baseline.d.ts.map +1 -1
  152. package/types/rules/utils/baseline.d.ts +1 -3
  153. package/types/rules/utils/baseline.d.ts.map +1 -1
  154. package/types/rules/utils/naming.d.ts +14 -7
  155. package/types/rules/utils/naming.d.ts.map +1 -1
  156. package/types/rules/utils/node.d.ts +11 -10
  157. package/types/rules/utils/node.d.ts.map +1 -1
  158. package/types/rules/utils/rule.d.ts +1 -4
  159. package/types/rules/utils/rule.d.ts.map +1 -1
  160. package/types/rules/utils/settings.d.ts +0 -1
  161. package/types/rules/utils/settings.d.ts.map +1 -1
  162. package/types/rules/utils/source-code.d.ts +2 -6
  163. package/types/rules/utils/source-code.d.ts.map +1 -1
  164. package/types/rules/utils/template-literal.d.ts +2 -1
  165. package/types/rules/utils/template-literal.d.ts.map +1 -1
  166. package/types/rules/utils/visitors.d.ts.map +1 -1
  167. package/types/specs/index.d.ts +3 -0
  168. package/types/specs/index.d.ts.map +1 -0
  169. package/types/specs/obsolete-attrs.d.ts +19 -0
  170. package/types/specs/obsolete-attrs.d.ts.map +1 -0
  171. package/types/types/ast.d.ts +5 -2
  172. package/types/types/ast.d.ts.map +1 -1
@@ -1,6 +1,9 @@
1
1
  /**
2
- * @import {Tag, Text} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
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 {Attribute, OpenScriptTagStart, OpenTagStart, OpenStyleTagStart, Tag, StyleTag, ScriptTag, AnyNode} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
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 {CommentContent, Tag, Comment, Text} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
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 {RuleModule} from "../types";
3
- * @import {Tag, ScriptTag} from "@html-eslint/types"
4
- * @typedef {{ attr: string; when: (node: Tag | ScriptTag) => boolean; message: string; }} AttributeChecker
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 {RuleModule} from "../types";
3
- * @import {Text} from "@html-eslint/types";
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 {CommentContent, Text} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
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 {((CommentContent | Text)['parts'][number])[]} tokens
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 {Tag, StyleTag,ScriptTag } from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
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 {StyleTag, Attribute, Tag, ScriptTag } from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
4
- * @typedef {{attrPatterns: string[], attrValuePatterns: string[], message?: string}[]} Options
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
  }