@html-eslint/eslint-plugin 0.51.0 → 0.52.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.
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 +15 -11
  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,6 @@
1
1
  /**
2
- * @import {RuleModule} from "../types";
3
- * @import {Tag} from "@html-eslint/types";
2
+ * @import {Tag} from "@html-eslint/types"
3
+ * @import {RuleModule} from "../types"
4
4
  */
5
5
 
6
6
  const { RULE_CATEGORY } = require("../constants");
@@ -16,9 +16,7 @@ const INPUT_TAGS = new Set(["input", "textarea", "select"]);
16
16
 
17
17
  const LABEL_ATTRIBUTES = new Set(["id", "aria-labelledby", "aria-label"]);
18
18
 
19
- /**
20
- * @type {RuleModule<[]>}
21
- */
19
+ /** @type {RuleModule<[]>} */
22
20
  module.exports = {
23
21
  meta: {
24
22
  type: "code",
@@ -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");
@@ -12,9 +10,7 @@ const MESSAGE_IDS = {
12
10
  EMPTY: "empty",
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,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");
@@ -12,9 +10,7 @@ const MESSAGE_IDS = {
12
10
 
13
11
  const VALID_CONTAINERS = ["ul", "ol", "menu"];
14
12
 
15
- /**
16
- * @type {RuleModule<[]>}
17
- */
13
+ /** @type {RuleModule<[]>} */
18
14
  module.exports = {
19
15
  meta: {
20
16
  type: "code",
@@ -1,6 +1,9 @@
1
1
  /**
2
- * @import {RuleModule} from "../types";
3
- * @import {Tag, AnyNode} from "@html-eslint/types";
2
+ * @import {
3
+ * AnyNode,
4
+ * Tag
5
+ * } from "@html-eslint/types"
6
+ * @import {RuleModule} from "../types"
4
7
  */
5
8
 
6
9
  const { RULE_CATEGORY } = require("../constants");
@@ -21,9 +24,7 @@ function isMetaCharset(node) {
21
24
  return isTag(node) && node.name === "meta" && !!findAttr(node, "charset");
22
25
  }
23
26
 
24
- /**
25
- * @type {RuleModule<[]>}
26
- */
27
+ /** @type {RuleModule<[]>} */
27
28
  module.exports = {
28
29
  meta: {
29
30
  type: "code",
@@ -1,6 +1,9 @@
1
1
  /**
2
- * @import {Tag, AnyNode} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
2
+ * @import {
3
+ * AnyNode,
4
+ * Tag
5
+ * } from "@html-eslint/types"
6
+ * @import {RuleModule} from "../types"
4
7
  */
5
8
  const { RULE_CATEGORY } = require("../constants");
6
9
  const { filter } = require("./utils/array");
@@ -20,9 +23,7 @@ function isMetaTagNode(node) {
20
23
  return isTag(node) && node.name === "meta";
21
24
  }
22
25
 
23
- /**
24
- * @type {RuleModule<[]>}
25
- */
26
+ /** @type {RuleModule<[]>} */
26
27
  module.exports = {
27
28
  meta: {
28
29
  type: "code",
@@ -1,6 +1,9 @@
1
1
  /**
2
- * @import {Tag, AnyNode} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
2
+ * @import {
3
+ * AnyNode,
4
+ * Tag
5
+ * } from "@html-eslint/types"
6
+ * @import {RuleModule} from "../types"
4
7
  */
5
8
 
6
9
  const { RULE_CATEGORY } = require("../constants");
@@ -29,9 +32,7 @@ function isMetaViewport(node) {
29
32
  return false;
30
33
  }
31
34
 
32
- /**
33
- * @type {RuleModule<[]>}
34
- */
35
+ /** @type {RuleModule<[]>} */
35
36
  module.exports = {
36
37
  meta: {
37
38
  type: "code",
@@ -1,6 +1,9 @@
1
1
  /**
2
- * @import {Tag, AnyNode} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
2
+ * @import {
3
+ * AnyNode,
4
+ * Tag
5
+ * } from "@html-eslint/types"
6
+ * @import {RuleModule} from "../types"
4
7
  * @typedef {string[]} Option
5
8
  */
6
9
 
@@ -32,9 +35,7 @@ function normalize(properties) {
32
35
  });
33
36
  }
34
37
 
35
- /**
36
- * @type {RuleModule<[Option]>}
37
- */
38
+ /** @type {RuleModule<[Option]>} */
38
39
  module.exports = {
39
40
  meta: {
40
41
  type: "code",
@@ -65,9 +66,7 @@ module.exports = {
65
66
  },
66
67
 
67
68
  create(context) {
68
- /**
69
- * @type {string[]}
70
- */
69
+ /** @type {string[]} */
71
70
  const requiredProperties = normalize(
72
71
  (context.options && context.options[0]) || DEFAULT_REQUIRED_PROPERTIES
73
72
  );
@@ -1,6 +1,10 @@
1
1
  /**
2
- * @import {Tag, Text, AnyNode} from "@html-eslint/types";
3
- * @import {RuleModule} from "../types";
2
+ * @import {
3
+ * AnyNode,
4
+ * Tag,
5
+ * Text
6
+ * } from "@html-eslint/types"
7
+ * @import {RuleModule} from "../types"
4
8
  */
5
9
 
6
10
  const { RULE_CATEGORY } = require("../constants");
@@ -29,9 +33,7 @@ function isNonEmptyText(node) {
29
33
  return isText(node) && node.value.trim().length > 0;
30
34
  }
31
35
 
32
- /**
33
- * @type {RuleModule<[]>}
34
- */
36
+ /** @type {RuleModule<[]>} */
35
37
  module.exports = {
36
38
  meta: {
37
39
  type: "code",
@@ -1,9 +1,11 @@
1
1
  /**
2
- * @import {Attribute} from "@html-eslint/types";
3
- * @import {RuleFixer, RuleModule} from "../types";
4
- *
2
+ * @import {Attribute} from "@html-eslint/types"
3
+ * @import {
4
+ * RuleFixer,
5
+ * RuleModule
6
+ * } from "../types"
5
7
  * @typedef {Object} Option
6
- * @property {Array<string | {pattern: string}>} [Option.priority]
8
+ * @property {(string | { pattern: string })[]} [Option.priority]
7
9
  */
8
10
 
9
11
  const { hasTemplate } = require("./utils/node");
@@ -16,9 +18,7 @@ const MESSAGE_IDS = {
16
18
  UNSORTED: "unsorted",
17
19
  };
18
20
 
19
- /**
20
- * @type {RuleModule<[Option]>}
21
- */
21
+ /** @type {RuleModule<[Option]>} */
22
22
  module.exports = {
23
23
  meta: {
24
24
  type: "code",
@@ -69,9 +69,7 @@ module.exports = {
69
69
  const option = context.options[0] || {
70
70
  priority: ["id", "type", "class", "style"],
71
71
  };
72
- /**
73
- * @type {Array<string | {pattern: string, regex: RegExp}>}
74
- */
72
+ /** @type {(string | { pattern: string; regex: RegExp })[]} */
75
73
  const priority = (option.priority || []).map((item) => {
76
74
  if (item && typeof item === "object" && "pattern" in item) {
77
75
  return {
@@ -84,7 +82,7 @@ module.exports = {
84
82
 
85
83
  /**
86
84
  * @param {string} attrName
87
- * @param {string | {pattern: string, regex: RegExp}} priorityItem
85
+ * @param {string | { pattern: string; regex: RegExp }} priorityItem
88
86
  * @returns {boolean}
89
87
  */
90
88
  function matchesPriority(attrName, priorityItem) {
@@ -117,7 +115,7 @@ module.exports = {
117
115
  /**
118
116
  * @param {Attribute} attrA
119
117
  * @param {Attribute} attrB
120
- * @return {number}
118
+ * @returns {number}
121
119
  */
122
120
  function compare(attrA, attrB) {
123
121
  const keyA = attrA.key.value;
@@ -185,12 +183,10 @@ module.exports = {
185
183
 
186
184
  /**
187
185
  * @param {Attribute[]} attributes
188
- * @return {Attribute[][]}
186
+ * @returns {Attribute[][]}
189
187
  */
190
188
  function groupAttributes(attributes) {
191
- /**
192
- * @type {Attribute[][]}
193
- */
189
+ /** @type {Attribute[][]} */
194
190
  const attributesList = [];
195
191
  let index = 0;
196
192
 
@@ -207,9 +203,7 @@ module.exports = {
207
203
  return attributesList;
208
204
  }
209
205
 
210
- /**
211
- * @param {Attribute[]} unsorted
212
- */
206
+ /** @param {Attribute[]} unsorted */
213
207
  function checkSorting(unsorted) {
214
208
  if (unsorted.length <= 1) {
215
209
  return;
@@ -1,6 +1,11 @@
1
1
  /**
2
- * @import {RuleModule} from "../types";
3
- * @import {Attribute, Tag, ScriptTag, StyleTag} from "@html-eslint/types";
2
+ * @import {
3
+ * Attribute,
4
+ * ScriptTag,
5
+ * StyleTag,
6
+ * Tag
7
+ * } from "@html-eslint/types"
8
+ * @import {RuleModule} from "../types"
4
9
  * @typedef {Object} Option
5
10
  * @property {"widely" | "newly" | number} Option.available
6
11
  */
@@ -21,9 +26,7 @@ const MESSAGE_IDS = {
21
26
  NOT_BASELINE_GLOBAL_ATTRIBUTE: "notBaselineGlobalAttribute",
22
27
  };
23
28
 
24
- /**
25
- * @type {RuleModule<[Option]>}
26
- */
29
+ /** @type {RuleModule<[Option]>} */
27
30
  module.exports = {
28
31
  meta: {
29
32
  type: "code",
@@ -178,7 +181,6 @@ module.exports = {
178
181
  }
179
182
 
180
183
  /**
181
- *
182
184
  * @param {string} element
183
185
  * @param {string} key
184
186
  * @param {string} value
@@ -1,6 +1,4 @@
1
- /**
2
- * This file is auto-generated. (yarn run baseline)
3
- */
1
+ /** This file is auto-generated. (yarn run baseline) */
4
2
  const BASELINE_HIGH = 10;
5
3
  const BASELINE_LOW = 5;
6
4
  const BASELINE_FALSE = 0;
@@ -70,9 +68,9 @@ const elements = new Map([
70
68
  ["body", "10:2015"],
71
69
  ["br", "10:2015"],
72
70
  ["button", "10:2015"],
73
- ["button.command", "0:"],
74
- ["button.command.request-close", "0:"],
75
- ["button.commandfor", "0:"],
71
+ ["button.command", "5:2025"],
72
+ ["button.command.request-close", "5:2025"],
73
+ ["button.commandfor", "5:2025"],
76
74
  ["button.disabled", "10:2015"],
77
75
  ["button.form", "10:2017"],
78
76
  ["button.formaction", "10:2015"],
@@ -7,8 +7,10 @@ const CAMEL_CASE_REGEX = /^[a-z][a-zA-Z0-9]+$/;
7
7
  module.exports = {
8
8
  /**
9
9
  * Checks a given name follows `kebab-case` or not.
10
- * @param {string} name name to check
11
- * @returns {boolean} `true` if a name follows `kebab-case`, otherwise `false`.
10
+ *
11
+ * @param {string} name Name to check
12
+ * @returns {boolean} `true` if a name follows `kebab-case`, otherwise
13
+ * `false`.
12
14
  */
13
15
  isKebabCase(name) {
14
16
  return KEBAB_CASE_REGEX.test(name);
@@ -16,8 +18,10 @@ module.exports = {
16
18
 
17
19
  /**
18
20
  * Checks a given name follows `snake_case` or not.
19
- * @param {string} name name to check
20
- * @returns {boolean} `true` if a name follows `snake_case`, otherwise `false`.
21
+ *
22
+ * @param {string} name Name to check
23
+ * @returns {boolean} `true` if a name follows `snake_case`, otherwise
24
+ * `false`.
21
25
  */
22
26
  isSnakeCase(name) {
23
27
  return SNAKE_CASE_REGEX.test(name);
@@ -25,8 +29,10 @@ module.exports = {
25
29
 
26
30
  /**
27
31
  * Checks a given name follows `PascalCase` or not.
28
- * @param {string} name name to check
29
- * @returns {boolean} `true` if a name follows `PascalCase`, otherwise `false`.
32
+ *
33
+ * @param {string} name Name to check
34
+ * @returns {boolean} `true` if a name follows `PascalCase`, otherwise
35
+ * `false`.
30
36
  */
31
37
  isPascalCase(name) {
32
38
  return PASCAL_CASE_REGEX.test(name);
@@ -34,7 +40,8 @@ module.exports = {
34
40
 
35
41
  /**
36
42
  * Checks a given name follows `camelCase` or not.
37
- * @param {string} name name to check
43
+ *
44
+ * @param {string} name Name to check
38
45
  * @returns {boolean} `true` if a name follows `camelCase`, otherwise `false`.
39
46
  */
40
47
  isCamelCase(name) {
@@ -1,7 +1,24 @@
1
1
  /**
2
- * @import {Attribute, Tag, ScriptTag, StyleTag, AnyNode, Text, CommentContent, Comment, AttributeValue, AttributeKey, AnyToken} from "@html-eslint/types";
3
- * @import {Line, BaseNode} from "../../types";
4
- * @import {AST} from "eslint";
2
+ * @import {
3
+ * AnyNode,
4
+ * AnyToken,
5
+ * Attribute,
6
+ * AttributeKey,
7
+ * AttributeValue,
8
+ * CloseTemplate,
9
+ * Comment,
10
+ * CommentContent,
11
+ * OpenTemplate,
12
+ * ScriptTag,
13
+ * StyleTag,
14
+ * Tag,
15
+ * Text
16
+ * } from "@html-eslint/types"
17
+ * @import {AST} from "eslint"
18
+ * @import {
19
+ * BaseNode,
20
+ * Line
21
+ * } from "../../types"
5
22
  */
6
23
 
7
24
  const { NODE_TYPES } = require("@html-eslint/parser");
@@ -30,6 +47,7 @@ function hasAttr(node, attrName) {
30
47
 
31
48
  /**
32
49
  * Checks whether a node's attributes is empty or not.
50
+ *
33
51
  * @param {Tag | ScriptTag | StyleTag} node
34
52
  * @returns {boolean}
35
53
  */
@@ -39,15 +57,16 @@ function isAttributesEmpty(node) {
39
57
 
40
58
  /**
41
59
  * Checks whether a node's all tokens are on the same line or not.
60
+ *
42
61
  * @param {AnyNode} node A node to check
43
- * @returns {boolean} `true` if a node's tokens are on the same line, otherwise `false`.
62
+ * @returns {boolean} `true` if a node's tokens are on the same line, otherwise
63
+ * `false`.
44
64
  */
45
65
  function isNodeTokensOnSameLine(node) {
46
66
  return node.loc.start.line === node.loc.end.line;
47
67
  }
48
68
 
49
69
  /**
50
- *
51
70
  * @param {AST.Range} rangeA
52
71
  * @param {AST.Range} rangeB
53
72
  * @returns {boolean}
@@ -57,7 +76,7 @@ function isRangesOverlap(rangeA, rangeB) {
57
76
  }
58
77
 
59
78
  /**
60
- * @param {(Text | CommentContent)['parts']} parts
79
+ * @param {(Text | CommentContent)["parts"]} parts
61
80
  * @param {AST.Range} range
62
81
  * @returns {boolean}
63
82
  */
@@ -76,7 +95,6 @@ function hasTemplate(node) {
76
95
  }
77
96
 
78
97
  /**
79
- *
80
98
  * @param {Text | CommentContent} node
81
99
  * @returns {Line[]}
82
100
  */
@@ -84,27 +102,45 @@ function splitToLineNodes(node) {
84
102
  let start = node.range[0];
85
103
  let line = node.loc.start.line;
86
104
  const startCol = node.loc.start.column;
87
- /**
88
- * @type {Line[]}
89
- */
105
+ /** @type {Line[]} */
90
106
  const lineNodes = [];
91
107
  const parts = node.parts || [];
108
+
92
109
  /**
93
- *
94
110
  * @param {AST.Range} range
111
+ * @returns {{
112
+ * isOverlapTemplate: boolean;
113
+ * hasOpenTemplate: boolean;
114
+ * hasCloseTemplate: boolean;
115
+ * }}
95
116
  */
96
- function hasTemplate(range) {
97
- return parts.some(
98
- (part) =>
99
- part.type !== NODE_TYPES.Part && isRangesOverlap(part.range, range)
100
- );
117
+ function getTemplateInfo(range) {
118
+ let isOverlapTemplate = false;
119
+ let hasOpenTemplate = false;
120
+ let hasCloseTemplate = false;
121
+ for (const part of parts) {
122
+ if (part.type === NODE_TYPES.Template) {
123
+ if (isRangesOverlap(part.range, range)) {
124
+ isOverlapTemplate = true;
125
+ }
126
+ if (part.open && isRangesOverlap(part.open.range, range)) {
127
+ hasOpenTemplate = true;
128
+ }
129
+ if (part.close && isRangesOverlap(part.close.range, range)) {
130
+ hasCloseTemplate = true;
131
+ }
132
+ }
133
+ }
134
+ return {
135
+ isOverlapTemplate,
136
+ hasCloseTemplate,
137
+ hasOpenTemplate,
138
+ };
101
139
  }
102
140
 
103
141
  node.value.split("\n").forEach((value, index) => {
104
142
  const columnStart = index === 0 ? startCol : 0;
105
- /**
106
- * @type {AST.Range}
107
- */
143
+ /** @type {AST.Range} */
108
144
  const range = [start, start + value.length];
109
145
  const loc = {
110
146
  start: {
@@ -116,15 +152,13 @@ function splitToLineNodes(node) {
116
152
  column: columnStart + value.length,
117
153
  },
118
154
  };
119
- /**
120
- * @type {Line}
121
- */
155
+ /** @type {Line} */
122
156
  const lineNode = {
123
157
  type: "Line",
124
158
  value,
125
159
  range,
126
160
  loc,
127
- hasTemplate: hasTemplate(range),
161
+ ...getTemplateInfo(range),
128
162
  };
129
163
 
130
164
  start += value.length + 1;
@@ -138,9 +172,10 @@ function splitToLineNodes(node) {
138
172
 
139
173
  /**
140
174
  * Get location between two nodes.
141
- * @param {{loc: AST.SourceLocation}} before A node placed in before
142
- * @param {{loc: AST.SourceLocation}} after A node placed in after
143
- * @returns {AST.SourceLocation} location between two nodes.
175
+ *
176
+ * @param {{ loc: AST.SourceLocation }} before A node placed in before
177
+ * @param {{ loc: AST.SourceLocation }} after A node placed in after
178
+ * @returns {AST.SourceLocation} Location between two nodes.
144
179
  */
145
180
  function getLocBetween(before, after) {
146
181
  return {
@@ -230,9 +265,8 @@ function findParent(node, predicate) {
230
265
  }
231
266
 
232
267
  /**
233
- *
234
268
  * @param {AnyToken[]} tokens
235
- * @returns {((CommentContent | Text)['parts'][number])[]}
269
+ * @returns {(CommentContent | Text)["parts"][number][]}
236
270
  */
237
271
  function getTemplateTokens(tokens) {
238
272
  return (
@@ -258,7 +292,7 @@ function getNameOf(node) {
258
292
  if (isStyle(node)) {
259
293
  return "style";
260
294
  }
261
- return node.name;
295
+ return node.name.toLowerCase();
262
296
  }
263
297
 
264
298
  module.exports = {
@@ -1,7 +1,4 @@
1
- /**
2
- *
3
- * @param {string} ruleName
4
- */
1
+ /** @param {string} ruleName */
5
2
  function getRuleUrl(ruleName) {
6
3
  return "https://html-eslint.org/docs/rules/" + ruleName;
7
4
  }
@@ -1,6 +1,13 @@
1
1
  /**
2
- * @import {MaybeHTMLSettings, HTMLSettings, Context} from "../../types";
3
- * @import {TaggedTemplateExpression, TemplateLiteral} from "@html-eslint/types";
2
+ * @import {
3
+ * TaggedTemplateExpression,
4
+ * TemplateLiteral
5
+ * } from "@html-eslint/types"
6
+ * @import {
7
+ * Context,
8
+ * HTMLSettings,
9
+ * MaybeHTMLSettings
10
+ * } from "../../types"
4
11
  */
5
12
 
6
13
  const { getSourceCode } = require("../utils/source-code");
@@ -54,7 +61,6 @@ function shouldCheckTaggedTemplateExpression(node, context) {
54
61
  }
55
62
 
56
63
  /**
57
- *
58
64
  * @param {TemplateLiteral} node
59
65
  * @param {Context<any[]>} context
60
66
  * @returns {boolean}
@@ -1,10 +1,6 @@
1
- /**
2
- * @import {Context} from "../../types";
3
- */
1
+ /** @import {Context} from "../../types" */
4
2
 
5
- /**
6
- * @param {Context<any[]>} context
7
- */
3
+ /** @param {Context<any[]>} context */
8
4
  function getSourceCode(context) {
9
5
  return context.sourceCode || context.getSourceCode();
10
6
  }
@@ -1,25 +1,34 @@
1
1
  /**
2
- * @import {TemplateLiteral} from "@html-eslint/types";
3
- * @import {DocumentNode, AnyToken} from "es-html-parser";
4
- * @import {SourceCode} from "eslint";
5
2
  * @import {TemplateHTMLVisitor} from "@html-eslint/template-parser"
3
+ * @import {TemplateLiteral} from "@html-eslint/types"
4
+ * @import {
5
+ * AnyToken,
6
+ * DocumentNode
7
+ * } from "es-html-parser"
8
+ * @import {SourceCode} from "eslint"
6
9
  */
7
10
 
8
11
  const { parse, traverse } = require("@html-eslint/template-parser");
9
12
 
10
13
  /**
11
- * Cache for parsed template literals to avoid re-parsing the same template multiple times.
12
- * Uses WeakMap for automatic garbage collection when nodes are no longer referenced.
13
- * @type {WeakMap<TemplateLiteral, {ast: any, html: string, tokens: any[]}>}
14
+ * Cache for parsed template literals to avoid re-parsing the same template
15
+ * multiple times. Uses WeakMap for automatic garbage collection when nodes are
16
+ * no longer referenced.
17
+ *
18
+ * @type {WeakMap<
19
+ * TemplateLiteral,
20
+ * { ast: any; html: string; tokens: any[] }
21
+ * >}
14
22
  */
15
23
  const templateCache = new WeakMap();
16
24
 
17
25
  /**
18
26
  * Get or create cached parse result for a template literal.
27
+ *
19
28
  * @param {TemplateLiteral} node
20
29
  * @param {SourceCode} sourceCode
21
30
  * @param {TemplateHTMLVisitor} [visitor]
22
- * @returns {{ast: DocumentNode, html: string, tokens: AnyToken[]}}
31
+ * @returns {{ ast: DocumentNode; html: string; tokens: AnyToken[] }}
23
32
  */
24
33
  function parseTemplateLiteral(node, sourceCode, visitor) {
25
34
  // Check if we already have a cached result for this node
@@ -1,5 +1,8 @@
1
1
  /**
2
- * @import {Context, RuleListener} from "../../types";
2
+ * @import {
3
+ * Context,
4
+ * RuleListener
5
+ * } from "../../types"
3
6
  */
4
7
 
5
8
  const {
@@ -0,0 +1,5 @@
1
+ const OBSOLETE_ATTRS = require("./obsolete-attrs");
2
+
3
+ module.exports = {
4
+ OBSOLETE_ATTRS,
5
+ };