@herb-tools/linter 0.7.5 → 0.8.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 (394) hide show
  1. package/README.md +253 -13
  2. package/dist/herb-lint.js +26023 -3424
  3. package/dist/herb-lint.js.map +1 -1
  4. package/dist/index.cjs +5759 -1583
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.js +5727 -1584
  7. package/dist/index.js.map +1 -1
  8. package/dist/loader.cjs +17010 -0
  9. package/dist/loader.cjs.map +1 -0
  10. package/dist/loader.js +16879 -0
  11. package/dist/loader.js.map +1 -0
  12. package/dist/package.json +13 -5
  13. package/dist/src/cli/argument-parser.js +38 -33
  14. package/dist/src/cli/argument-parser.js.map +1 -1
  15. package/dist/src/cli/file-processor.js +124 -23
  16. package/dist/src/cli/file-processor.js.map +1 -1
  17. package/dist/src/cli/formatters/detailed-formatter.js +18 -3
  18. package/dist/src/cli/formatters/detailed-formatter.js.map +1 -1
  19. package/dist/src/cli/formatters/github-actions-formatter.js +15 -1
  20. package/dist/src/cli/formatters/github-actions-formatter.js.map +1 -1
  21. package/dist/src/cli/formatters/json-formatter.js +3 -0
  22. package/dist/src/cli/formatters/json-formatter.js.map +1 -1
  23. package/dist/src/cli/formatters/simple-formatter.js +20 -7
  24. package/dist/src/cli/formatters/simple-formatter.js.map +1 -1
  25. package/dist/src/cli/output-manager.js +22 -3
  26. package/dist/src/cli/output-manager.js.map +1 -1
  27. package/dist/src/cli/summary-reporter.js +26 -3
  28. package/dist/src/cli/summary-reporter.js.map +1 -1
  29. package/dist/src/cli.js +107 -42
  30. package/dist/src/cli.js.map +1 -1
  31. package/dist/src/custom-rule-loader.js +139 -0
  32. package/dist/src/custom-rule-loader.js.map +1 -0
  33. package/dist/src/herb-disable-comment-utils.js +129 -0
  34. package/dist/src/herb-disable-comment-utils.js.map +1 -0
  35. package/dist/src/index.js +1 -0
  36. package/dist/src/index.js.map +1 -1
  37. package/dist/src/linter.js +369 -34
  38. package/dist/src/linter.js.map +1 -1
  39. package/dist/src/loader.js +17 -0
  40. package/dist/src/loader.js.map +1 -0
  41. package/dist/src/rules/erb-comment-syntax.js +31 -2
  42. package/dist/src/rules/erb-comment-syntax.js.map +1 -1
  43. package/dist/src/rules/erb-no-case-node-children.js +52 -0
  44. package/dist/src/rules/erb-no-case-node-children.js.map +1 -0
  45. package/dist/src/rules/erb-no-empty-tags.js +7 -1
  46. package/dist/src/rules/erb-no-empty-tags.js.map +1 -1
  47. package/dist/src/rules/erb-no-extra-newline.js +65 -0
  48. package/dist/src/rules/erb-no-extra-newline.js.map +1 -0
  49. package/dist/src/rules/erb-no-extra-whitespace-inside-tags.js +95 -0
  50. package/dist/src/rules/erb-no-extra-whitespace-inside-tags.js.map +1 -0
  51. package/dist/src/rules/erb-no-output-control-flow.js +7 -1
  52. package/dist/src/rules/erb-no-output-control-flow.js.map +1 -1
  53. package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js +7 -1
  54. package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js.map +1 -1
  55. package/dist/src/rules/erb-prefer-image-tag-helper.js +7 -1
  56. package/dist/src/rules/erb-prefer-image-tag-helper.js.map +1 -1
  57. package/dist/src/rules/erb-require-trailing-newline.js +35 -0
  58. package/dist/src/rules/erb-require-trailing-newline.js.map +1 -0
  59. package/dist/src/rules/erb-require-whitespace-inside-tags.js +69 -11
  60. package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +1 -1
  61. package/dist/src/rules/erb-right-trim.js +26 -9
  62. package/dist/src/rules/erb-right-trim.js.map +1 -1
  63. package/dist/src/rules/herb-disable-comment-base.js +51 -0
  64. package/dist/src/rules/herb-disable-comment-base.js.map +1 -0
  65. package/dist/src/rules/herb-disable-comment-malformed.js +51 -0
  66. package/dist/src/rules/herb-disable-comment-malformed.js.map +1 -0
  67. package/dist/src/rules/herb-disable-comment-missing-rules.js +29 -0
  68. package/dist/src/rules/herb-disable-comment-missing-rules.js.map +1 -0
  69. package/dist/src/rules/herb-disable-comment-no-duplicate-rules.js +32 -0
  70. package/dist/src/rules/herb-disable-comment-no-duplicate-rules.js.map +1 -0
  71. package/dist/src/rules/herb-disable-comment-no-redundant-all.js +31 -0
  72. package/dist/src/rules/herb-disable-comment-no-redundant-all.js.map +1 -0
  73. package/dist/src/rules/herb-disable-comment-unnecessary.js +65 -0
  74. package/dist/src/rules/herb-disable-comment-unnecessary.js.map +1 -0
  75. package/dist/src/rules/herb-disable-comment-valid-rule-name.js +44 -0
  76. package/dist/src/rules/herb-disable-comment-valid-rule-name.js.map +1 -0
  77. package/dist/src/rules/html-anchor-require-href.js +7 -1
  78. package/dist/src/rules/html-anchor-require-href.js.map +1 -1
  79. package/dist/src/rules/html-aria-attribute-must-be-valid.js +7 -1
  80. package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +1 -1
  81. package/dist/src/rules/html-aria-label-is-well-formatted.js +9 -3
  82. package/dist/src/rules/html-aria-label-is-well-formatted.js.map +1 -1
  83. package/dist/src/rules/html-aria-level-must-be-valid.js +6 -0
  84. package/dist/src/rules/html-aria-level-must-be-valid.js.map +1 -1
  85. package/dist/src/rules/html-aria-role-heading-requires-level.js +7 -1
  86. package/dist/src/rules/html-aria-role-heading-requires-level.js.map +1 -1
  87. package/dist/src/rules/html-aria-role-must-be-valid.js +7 -1
  88. package/dist/src/rules/html-aria-role-must-be-valid.js.map +1 -1
  89. package/dist/src/rules/html-attribute-double-quotes.js +29 -2
  90. package/dist/src/rules/html-attribute-double-quotes.js.map +1 -1
  91. package/dist/src/rules/html-attribute-equals-spacing.js +18 -2
  92. package/dist/src/rules/html-attribute-equals-spacing.js.map +1 -1
  93. package/dist/src/rules/html-attribute-values-require-quotes.js +39 -3
  94. package/dist/src/rules/html-attribute-values-require-quotes.js.map +1 -1
  95. package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js +7 -1
  96. package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js.map +1 -1
  97. package/dist/src/rules/html-body-only-elements.js +46 -0
  98. package/dist/src/rules/html-body-only-elements.js.map +1 -0
  99. package/dist/src/rules/html-boolean-attributes-no-value.js +18 -1
  100. package/dist/src/rules/html-boolean-attributes-no-value.js.map +1 -1
  101. package/dist/src/rules/html-head-only-elements.js +51 -0
  102. package/dist/src/rules/html-head-only-elements.js.map +1 -0
  103. package/dist/src/rules/html-iframe-has-title.js +8 -2
  104. package/dist/src/rules/html-iframe-has-title.js.map +1 -1
  105. package/dist/src/rules/html-img-require-alt.js +7 -1
  106. package/dist/src/rules/html-img-require-alt.js.map +1 -1
  107. package/dist/src/rules/html-input-require-autocomplete.js +70 -0
  108. package/dist/src/rules/html-input-require-autocomplete.js.map +1 -0
  109. package/dist/src/rules/html-navigation-has-label.js +7 -1
  110. package/dist/src/rules/html-navigation-has-label.js.map +1 -1
  111. package/dist/src/rules/html-no-aria-hidden-on-focusable.js +7 -1
  112. package/dist/src/rules/html-no-aria-hidden-on-focusable.js.map +1 -1
  113. package/dist/src/rules/html-no-block-inside-inline.js +7 -1
  114. package/dist/src/rules/html-no-block-inside-inline.js.map +1 -1
  115. package/dist/src/rules/html-no-duplicate-attributes.js +7 -1
  116. package/dist/src/rules/html-no-duplicate-attributes.js.map +1 -1
  117. package/dist/src/rules/html-no-duplicate-ids.js +9 -3
  118. package/dist/src/rules/html-no-duplicate-ids.js.map +1 -1
  119. package/dist/src/rules/html-no-duplicate-meta-names.js +136 -0
  120. package/dist/src/rules/html-no-duplicate-meta-names.js.map +1 -0
  121. package/dist/src/rules/html-no-empty-attributes.js +45 -7
  122. package/dist/src/rules/html-no-empty-attributes.js.map +1 -1
  123. package/dist/src/rules/html-no-empty-headings.js +7 -6
  124. package/dist/src/rules/html-no-empty-headings.js.map +1 -1
  125. package/dist/src/rules/html-no-nested-links.js +7 -1
  126. package/dist/src/rules/html-no-nested-links.js.map +1 -1
  127. package/dist/src/rules/html-no-positive-tab-index.js +7 -1
  128. package/dist/src/rules/html-no-positive-tab-index.js.map +1 -1
  129. package/dist/src/rules/html-no-self-closing.js +48 -3
  130. package/dist/src/rules/html-no-self-closing.js.map +1 -1
  131. package/dist/src/rules/html-no-space-in-tag.js +173 -0
  132. package/dist/src/rules/html-no-space-in-tag.js.map +1 -0
  133. package/dist/src/rules/html-no-title-attribute.js +7 -1
  134. package/dist/src/rules/html-no-title-attribute.js.map +1 -1
  135. package/dist/src/rules/html-no-underscores-in-attribute-names.js +7 -1
  136. package/dist/src/rules/html-no-underscores-in-attribute-names.js.map +1 -1
  137. package/dist/src/rules/html-tag-name-lowercase.js +23 -5
  138. package/dist/src/rules/html-tag-name-lowercase.js.map +1 -1
  139. package/dist/src/rules/index.js +19 -3
  140. package/dist/src/rules/index.js.map +1 -1
  141. package/dist/src/rules/parser-no-errors.js +6 -0
  142. package/dist/src/rules/parser-no-errors.js.map +1 -1
  143. package/dist/src/rules/rule-utils.js +211 -31
  144. package/dist/src/rules/rule-utils.js.map +1 -1
  145. package/dist/src/rules/svg-tag-name-capitalization.js +22 -2
  146. package/dist/src/rules/svg-tag-name-capitalization.js.map +1 -1
  147. package/dist/src/{default-rules.js → rules.js} +44 -16
  148. package/dist/src/rules.js.map +1 -0
  149. package/dist/src/types.js +34 -1
  150. package/dist/src/types.js.map +1 -1
  151. package/dist/tsconfig.tsbuildinfo +1 -1
  152. package/dist/types/cli/argument-parser.d.ts +8 -2
  153. package/dist/types/cli/file-processor.d.ts +15 -0
  154. package/dist/types/cli/formatters/json-formatter.d.ts +6 -0
  155. package/dist/types/cli/formatters/simple-formatter.d.ts +1 -0
  156. package/dist/types/cli/summary-reporter.d.ts +6 -0
  157. package/dist/types/cli.d.ts +9 -4
  158. package/dist/types/custom-rule-loader.d.ts +62 -0
  159. package/dist/types/herb-disable-comment-utils.d.ts +69 -0
  160. package/dist/types/index.d.ts +1 -0
  161. package/dist/types/linter.d.ts +99 -3
  162. package/dist/types/loader.d.ts +20 -0
  163. package/dist/types/rules/erb-comment-syntax.d.ts +12 -5
  164. package/dist/types/rules/erb-no-case-node-children.d.ts +8 -0
  165. package/dist/types/rules/erb-no-empty-tags.d.ts +3 -2
  166. package/dist/types/rules/erb-no-extra-newline.d.ts +14 -0
  167. package/dist/types/rules/erb-no-extra-whitespace-inside-tags.d.ts +18 -0
  168. package/dist/types/rules/erb-no-output-control-flow.d.ts +3 -2
  169. package/dist/types/rules/erb-no-silent-tag-in-attribute-name.d.ts +3 -2
  170. package/dist/types/rules/erb-prefer-image-tag-helper.d.ts +3 -2
  171. package/dist/types/rules/erb-require-trailing-newline.d.ts +9 -0
  172. package/dist/types/rules/erb-require-whitespace-inside-tags.d.ts +16 -5
  173. package/dist/types/rules/erb-right-trim.d.ts +12 -5
  174. package/dist/types/rules/herb-disable-comment-base.d.ts +37 -0
  175. package/dist/types/rules/herb-disable-comment-malformed.d.ts +8 -0
  176. package/dist/types/rules/herb-disable-comment-missing-rules.d.ts +8 -0
  177. package/dist/types/rules/herb-disable-comment-no-duplicate-rules.d.ts +8 -0
  178. package/dist/types/rules/herb-disable-comment-no-redundant-all.d.ts +8 -0
  179. package/dist/types/rules/herb-disable-comment-unnecessary.d.ts +8 -0
  180. package/dist/types/rules/herb-disable-comment-valid-rule-name.d.ts +8 -0
  181. package/dist/types/rules/html-anchor-require-href.d.ts +3 -2
  182. package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +3 -2
  183. package/dist/types/rules/html-aria-label-is-well-formatted.d.ts +3 -2
  184. package/dist/types/rules/html-aria-level-must-be-valid.d.ts +3 -2
  185. package/dist/types/rules/html-aria-role-heading-requires-level.d.ts +3 -2
  186. package/dist/types/rules/html-aria-role-must-be-valid.d.ts +3 -2
  187. package/dist/types/rules/html-attribute-double-quotes.d.ts +13 -5
  188. package/dist/types/rules/html-attribute-equals-spacing.d.ts +12 -5
  189. package/dist/types/rules/html-attribute-values-require-quotes.d.ts +13 -5
  190. package/dist/types/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +3 -2
  191. package/dist/types/rules/html-body-only-elements.d.ts +9 -0
  192. package/dist/types/rules/html-boolean-attributes-no-value.d.ts +12 -5
  193. package/dist/types/rules/html-head-only-elements.d.ts +9 -0
  194. package/dist/types/rules/html-iframe-has-title.d.ts +3 -2
  195. package/dist/types/rules/html-img-require-alt.d.ts +3 -2
  196. package/dist/types/rules/html-input-require-autocomplete.d.ts +8 -0
  197. package/dist/types/rules/html-navigation-has-label.d.ts +3 -2
  198. package/dist/types/rules/html-no-aria-hidden-on-focusable.d.ts +3 -2
  199. package/dist/types/rules/html-no-block-inside-inline.d.ts +3 -2
  200. package/dist/types/rules/html-no-duplicate-attributes.d.ts +3 -2
  201. package/dist/types/rules/html-no-duplicate-ids.d.ts +3 -2
  202. package/dist/types/rules/html-no-duplicate-meta-names.d.ts +9 -0
  203. package/dist/types/rules/html-no-empty-attributes.d.ts +3 -2
  204. package/dist/types/rules/html-no-empty-headings.d.ts +3 -2
  205. package/dist/types/rules/html-no-nested-links.d.ts +3 -2
  206. package/dist/types/rules/html-no-positive-tab-index.d.ts +3 -2
  207. package/dist/types/rules/html-no-self-closing.d.ts +14 -5
  208. package/dist/types/rules/html-no-space-in-tag.d.ts +16 -0
  209. package/dist/types/rules/html-no-title-attribute.d.ts +3 -2
  210. package/dist/types/rules/html-no-underscores-in-attribute-names.d.ts +3 -2
  211. package/dist/types/rules/html-tag-name-lowercase.d.ts +16 -6
  212. package/dist/types/rules/index.d.ts +19 -3
  213. package/dist/types/rules/parser-no-errors.d.ts +2 -1
  214. package/dist/types/rules/rule-utils.d.ts +72 -25
  215. package/dist/types/rules/svg-tag-name-capitalization.d.ts +13 -4
  216. package/dist/types/rules.d.ts +2 -0
  217. package/dist/types/src/cli/argument-parser.d.ts +8 -2
  218. package/dist/types/src/cli/file-processor.d.ts +15 -0
  219. package/dist/types/src/cli/formatters/json-formatter.d.ts +6 -0
  220. package/dist/types/src/cli/formatters/simple-formatter.d.ts +1 -0
  221. package/dist/types/src/cli/summary-reporter.d.ts +6 -0
  222. package/dist/types/src/cli.d.ts +9 -4
  223. package/dist/types/src/custom-rule-loader.d.ts +62 -0
  224. package/dist/types/src/herb-disable-comment-utils.d.ts +69 -0
  225. package/dist/types/src/index.d.ts +1 -0
  226. package/dist/types/src/linter.d.ts +99 -3
  227. package/dist/types/src/loader.d.ts +20 -0
  228. package/dist/types/src/rules/erb-comment-syntax.d.ts +12 -5
  229. package/dist/types/src/rules/erb-no-case-node-children.d.ts +8 -0
  230. package/dist/types/src/rules/erb-no-empty-tags.d.ts +3 -2
  231. package/dist/types/src/rules/erb-no-extra-newline.d.ts +14 -0
  232. package/dist/types/src/rules/erb-no-extra-whitespace-inside-tags.d.ts +18 -0
  233. package/dist/types/src/rules/erb-no-output-control-flow.d.ts +3 -2
  234. package/dist/types/src/rules/erb-no-silent-tag-in-attribute-name.d.ts +3 -2
  235. package/dist/types/src/rules/erb-prefer-image-tag-helper.d.ts +3 -2
  236. package/dist/types/src/rules/erb-require-trailing-newline.d.ts +9 -0
  237. package/dist/types/src/rules/erb-require-whitespace-inside-tags.d.ts +16 -5
  238. package/dist/types/src/rules/erb-right-trim.d.ts +12 -5
  239. package/dist/types/src/rules/herb-disable-comment-base.d.ts +37 -0
  240. package/dist/types/src/rules/herb-disable-comment-malformed.d.ts +8 -0
  241. package/dist/types/src/rules/herb-disable-comment-missing-rules.d.ts +8 -0
  242. package/dist/types/src/rules/herb-disable-comment-no-duplicate-rules.d.ts +8 -0
  243. package/dist/types/src/rules/herb-disable-comment-no-redundant-all.d.ts +8 -0
  244. package/dist/types/src/rules/herb-disable-comment-unnecessary.d.ts +8 -0
  245. package/dist/types/src/rules/herb-disable-comment-valid-rule-name.d.ts +8 -0
  246. package/dist/types/src/rules/html-anchor-require-href.d.ts +3 -2
  247. package/dist/types/src/rules/html-aria-attribute-must-be-valid.d.ts +3 -2
  248. package/dist/types/src/rules/html-aria-label-is-well-formatted.d.ts +3 -2
  249. package/dist/types/src/rules/html-aria-level-must-be-valid.d.ts +3 -2
  250. package/dist/types/src/rules/html-aria-role-heading-requires-level.d.ts +3 -2
  251. package/dist/types/src/rules/html-aria-role-must-be-valid.d.ts +3 -2
  252. package/dist/types/src/rules/html-attribute-double-quotes.d.ts +13 -5
  253. package/dist/types/src/rules/html-attribute-equals-spacing.d.ts +12 -5
  254. package/dist/types/src/rules/html-attribute-values-require-quotes.d.ts +13 -5
  255. package/dist/types/src/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +3 -2
  256. package/dist/types/src/rules/html-body-only-elements.d.ts +9 -0
  257. package/dist/types/src/rules/html-boolean-attributes-no-value.d.ts +12 -5
  258. package/dist/types/src/rules/html-head-only-elements.d.ts +9 -0
  259. package/dist/types/src/rules/html-iframe-has-title.d.ts +3 -2
  260. package/dist/types/src/rules/html-img-require-alt.d.ts +3 -2
  261. package/dist/types/src/rules/html-input-require-autocomplete.d.ts +8 -0
  262. package/dist/types/src/rules/html-navigation-has-label.d.ts +3 -2
  263. package/dist/types/src/rules/html-no-aria-hidden-on-focusable.d.ts +3 -2
  264. package/dist/types/src/rules/html-no-block-inside-inline.d.ts +3 -2
  265. package/dist/types/src/rules/html-no-duplicate-attributes.d.ts +3 -2
  266. package/dist/types/src/rules/html-no-duplicate-ids.d.ts +3 -2
  267. package/dist/types/src/rules/html-no-duplicate-meta-names.d.ts +9 -0
  268. package/dist/types/src/rules/html-no-empty-attributes.d.ts +3 -2
  269. package/dist/types/src/rules/html-no-empty-headings.d.ts +3 -2
  270. package/dist/types/src/rules/html-no-nested-links.d.ts +3 -2
  271. package/dist/types/src/rules/html-no-positive-tab-index.d.ts +3 -2
  272. package/dist/types/src/rules/html-no-self-closing.d.ts +14 -5
  273. package/dist/types/src/rules/html-no-space-in-tag.d.ts +16 -0
  274. package/dist/types/src/rules/html-no-title-attribute.d.ts +3 -2
  275. package/dist/types/src/rules/html-no-underscores-in-attribute-names.d.ts +3 -2
  276. package/dist/types/src/rules/html-tag-name-lowercase.d.ts +16 -6
  277. package/dist/types/src/rules/index.d.ts +19 -3
  278. package/dist/types/src/rules/parser-no-errors.d.ts +2 -1
  279. package/dist/types/src/rules/rule-utils.d.ts +72 -25
  280. package/dist/types/src/rules/svg-tag-name-capitalization.d.ts +13 -4
  281. package/dist/types/src/rules.d.ts +2 -0
  282. package/dist/types/src/types.d.ts +102 -11
  283. package/dist/types/types.d.ts +102 -11
  284. package/docs/rules/README.md +16 -2
  285. package/docs/rules/erb-no-case-node-children.md +50 -0
  286. package/docs/rules/erb-no-extra-newline.md +74 -0
  287. package/docs/rules/erb-no-extra-whitespace-inside-tags.md +39 -0
  288. package/docs/rules/{erb-requires-trailing-newline.md → erb-require-trailing-newline.md} +1 -1
  289. package/docs/rules/erb-right-trim.md +5 -10
  290. package/docs/rules/herb-disable-comment-malformed.md +45 -0
  291. package/docs/rules/herb-disable-comment-missing-rules.md +60 -0
  292. package/docs/rules/herb-disable-comment-no-duplicate-rules.md +49 -0
  293. package/docs/rules/herb-disable-comment-no-redundant-all.md +53 -0
  294. package/docs/rules/herb-disable-comment-unnecessary.md +44 -0
  295. package/docs/rules/herb-disable-comment-valid-rule-name.md +41 -0
  296. package/docs/rules/html-aria-attribute-must-be-valid.md +2 -5
  297. package/docs/rules/html-aria-label-is-well-formatted.md +1 -1
  298. package/docs/rules/html-attribute-double-quotes.md +2 -2
  299. package/docs/rules/html-attribute-equals-spacing.md +2 -2
  300. package/docs/rules/html-attribute-values-require-quotes.md +3 -3
  301. package/docs/rules/html-avoid-both-disabled-and-aria-disabled.md +2 -2
  302. package/docs/rules/html-body-only-elements.md +99 -0
  303. package/docs/rules/html-boolean-attributes-no-value.md +2 -2
  304. package/docs/rules/html-head-only-elements.md +81 -0
  305. package/docs/rules/html-input-require-autocomplete.md +64 -0
  306. package/docs/rules/html-no-aria-hidden-on-focusable.md +2 -2
  307. package/docs/rules/html-no-duplicate-attributes.md +2 -2
  308. package/docs/rules/html-no-duplicate-meta-names.md +64 -0
  309. package/docs/rules/html-no-empty-attributes.md +3 -3
  310. package/docs/rules/html-no-empty-headings.md +4 -26
  311. package/docs/rules/html-no-positive-tab-index.md +1 -2
  312. package/docs/rules/html-no-self-closing.md +17 -2
  313. package/docs/rules/html-no-space-in-tag.md +66 -0
  314. package/docs/rules/html-no-title-attribute.md +2 -2
  315. package/docs/rules/html-no-underscores-in-attribute-names.md +2 -2
  316. package/docs/rules/html-tag-name-lowercase.md +2 -2
  317. package/package.json +13 -5
  318. package/src/cli/argument-parser.ts +46 -37
  319. package/src/cli/file-processor.ts +159 -28
  320. package/src/cli/formatters/detailed-formatter.ts +21 -3
  321. package/src/cli/formatters/github-actions-formatter.ts +17 -1
  322. package/src/cli/formatters/json-formatter.ts +9 -0
  323. package/src/cli/formatters/simple-formatter.ts +24 -8
  324. package/src/cli/output-manager.ts +23 -3
  325. package/src/cli/summary-reporter.ts +40 -3
  326. package/src/cli.ts +134 -51
  327. package/src/custom-rule-loader.ts +189 -0
  328. package/src/herb-disable-comment-utils.ts +175 -0
  329. package/src/index.ts +2 -0
  330. package/src/linter.ts +501 -36
  331. package/src/loader.ts +30 -0
  332. package/src/rules/erb-comment-syntax.ts +53 -10
  333. package/src/rules/erb-no-case-node-children.ts +68 -0
  334. package/src/rules/erb-no-empty-tags.ts +9 -3
  335. package/src/rules/erb-no-extra-newline.ts +91 -0
  336. package/src/rules/erb-no-extra-whitespace-inside-tags.ts +147 -0
  337. package/src/rules/erb-no-output-control-flow.ts +9 -3
  338. package/src/rules/erb-no-silent-tag-in-attribute-name.ts +9 -3
  339. package/src/rules/erb-prefer-image-tag-helper.ts +9 -3
  340. package/src/rules/erb-require-trailing-newline.ts +47 -0
  341. package/src/rules/erb-require-whitespace-inside-tags.ts +94 -16
  342. package/src/rules/erb-right-trim.ts +45 -22
  343. package/src/rules/herb-disable-comment-base.ts +76 -0
  344. package/src/rules/herb-disable-comment-malformed.ts +66 -0
  345. package/src/rules/herb-disable-comment-missing-rules.ts +41 -0
  346. package/src/rules/herb-disable-comment-no-duplicate-rules.ts +46 -0
  347. package/src/rules/herb-disable-comment-no-redundant-all.ts +40 -0
  348. package/src/rules/herb-disable-comment-unnecessary.ts +103 -0
  349. package/src/rules/herb-disable-comment-valid-rule-name.ts +62 -0
  350. package/src/rules/html-anchor-require-href.ts +9 -3
  351. package/src/rules/html-aria-attribute-must-be-valid.ts +9 -3
  352. package/src/rules/html-aria-label-is-well-formatted.ts +9 -5
  353. package/src/rules/html-aria-level-must-be-valid.ts +9 -2
  354. package/src/rules/html-aria-role-heading-requires-level.ts +9 -3
  355. package/src/rules/html-aria-role-must-be-valid.ts +9 -3
  356. package/src/rules/html-attribute-double-quotes.ts +42 -8
  357. package/src/rules/html-attribute-equals-spacing.ts +31 -7
  358. package/src/rules/html-attribute-values-require-quotes.ts +56 -10
  359. package/src/rules/html-avoid-both-disabled-and-aria-disabled.ts +9 -3
  360. package/src/rules/html-body-only-elements.ts +60 -0
  361. package/src/rules/html-boolean-attributes-no-value.ts +31 -6
  362. package/src/rules/html-head-only-elements.ts +65 -0
  363. package/src/rules/html-iframe-has-title.ts +9 -4
  364. package/src/rules/html-img-require-alt.ts +10 -4
  365. package/src/rules/html-input-require-autocomplete.ts +85 -0
  366. package/src/rules/html-navigation-has-label.ts +9 -3
  367. package/src/rules/html-no-aria-hidden-on-focusable.ts +9 -3
  368. package/src/rules/html-no-block-inside-inline.ts +9 -3
  369. package/src/rules/html-no-duplicate-attributes.ts +9 -3
  370. package/src/rules/html-no-duplicate-ids.ts +11 -7
  371. package/src/rules/html-no-duplicate-meta-names.ts +188 -0
  372. package/src/rules/html-no-empty-attributes.ts +58 -10
  373. package/src/rules/html-no-empty-headings.ts +10 -8
  374. package/src/rules/html-no-nested-links.ts +10 -4
  375. package/src/rules/html-no-positive-tab-index.ts +9 -3
  376. package/src/rules/html-no-self-closing.ts +69 -9
  377. package/src/rules/html-no-space-in-tag.ts +221 -0
  378. package/src/rules/html-no-title-attribute.ts +9 -3
  379. package/src/rules/html-no-underscores-in-attribute-names.ts +12 -4
  380. package/src/rules/html-tag-name-lowercase.ts +41 -10
  381. package/src/rules/index.ts +23 -3
  382. package/src/rules/parser-no-errors.ts +8 -1
  383. package/src/rules/rule-utils.ts +248 -42
  384. package/src/rules/svg-tag-name-capitalization.ts +39 -6
  385. package/src/{default-rules.ts → rules.ts} +51 -15
  386. package/src/types.ts +133 -15
  387. package/dist/src/default-rules.js.map +0 -1
  388. package/dist/src/rules/erb-requires-trailing-newline.js +0 -22
  389. package/dist/src/rules/erb-requires-trailing-newline.js.map +0 -1
  390. package/dist/types/default-rules.d.ts +0 -2
  391. package/dist/types/rules/erb-requires-trailing-newline.d.ts +0 -6
  392. package/dist/types/src/default-rules.d.ts +0 -2
  393. package/dist/types/src/rules/erb-requires-trailing-newline.d.ts +0 -6
  394. package/src/rules/erb-requires-trailing-newline.ts +0 -29
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-no-space-in-tag.js","sourceRoot":"","sources":["../../../src/rules/html-no-space-in-tag.ts"],"names":[],"mappings":"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"}
@@ -12,12 +12,18 @@ class NoTitleAttributeVisitor extends BaseRuleVisitor {
12
12
  return;
13
13
  }
14
14
  if (hasAttribute(node, "title")) {
15
- this.addOffense("The `title` attribute should never be used as it is inaccessible for several groups of users. Use `aria-label` or `aria-describedby` instead. Exceptions are provided for `<iframe>` and `<link>` elements.", node.tag_name.location, "error");
15
+ this.addOffense("The `title` attribute should never be used as it is inaccessible for several groups of users. Use `aria-label` or `aria-describedby` instead. Exceptions are provided for `<iframe>` and `<link>` elements.", node.tag_name.location);
16
16
  }
17
17
  }
18
18
  }
19
19
  export class HTMLNoTitleAttributeRule extends ParserRule {
20
20
  name = "html-no-title-attribute";
21
+ get defaultConfig() {
22
+ return {
23
+ enabled: false,
24
+ severity: "error"
25
+ };
26
+ }
21
27
  check(result, context) {
22
28
  const visitor = new NoTitleAttributeVisitor(this.name, context);
23
29
  visitor.visit(result.value);
@@ -1 +1 @@
1
- {"version":3,"file":"html-no-title-attribute.js","sourceRoot":"","sources":["../../../src/rules/html-no-title-attribute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAK3E,MAAM,uBAAwB,SAAQ,eAAe;IACnD,2BAA2B,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA;IAEzD,oBAAoB,CAAC,IAAqB;QACxC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAA;QAC9B,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAEO,mBAAmB,CAAC,IAAqB;QAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9D,OAAM;QACR,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,CACb,6MAA6M,EAC7M,IAAI,CAAC,QAAS,CAAC,QAAQ,EACvB,OAAO,CACR,CAAA;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACtD,IAAI,GAAG,yBAAyB,CAAA;IAEhC,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAE/D,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
1
+ {"version":3,"file":"html-no-title-attribute.js","sourceRoot":"","sources":["../../../src/rules/html-no-title-attribute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAK3E,MAAM,uBAAwB,SAAQ,eAAe;IACnD,2BAA2B,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA;IAEzD,oBAAoB,CAAC,IAAqB;QACxC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAA;QAC9B,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAEO,mBAAmB,CAAC,IAAqB;QAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9D,OAAM;QACR,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,CACb,6MAA6M,EAC7M,IAAI,CAAC,QAAS,CAAC,QAAQ,CACxB,CAAA;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACtD,IAAI,GAAG,yBAAyB,CAAA;IAEhC,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,OAAO;SAClB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAE/D,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
@@ -21,12 +21,18 @@ class HTMLNoUnderscoresInAttributeNamesVisitor extends AttributeVisitorMixin {
21
21
  if (!attributeName)
22
22
  return;
23
23
  if (attributeName.includes("_")) {
24
- this.addOffense(`Attribute \`${IdentityPrinter.print(attributeNode.name)}\` should not contain underscores. Use hyphens (-) instead.`, attributeNode.value.location, "warning");
24
+ this.addOffense(`Attribute \`${IdentityPrinter.print(attributeNode.name)}\` should not contain underscores. Use hyphens (-) instead.`, attributeNode.name?.location ?? attributeNode.location);
25
25
  }
26
26
  }
27
27
  }
28
28
  export class HTMLNoUnderscoresInAttributeNamesRule extends ParserRule {
29
29
  name = "html-no-underscores-in-attribute-names";
30
+ get defaultConfig() {
31
+ return {
32
+ enabled: true,
33
+ severity: "warning"
34
+ };
35
+ }
30
36
  check(result, context) {
31
37
  const visitor = new HTMLNoUnderscoresInAttributeNamesVisitor(this.name, context);
32
38
  visitor.visit(result.value);
@@ -1 +1 @@
1
- {"version":3,"file":"html-no-underscores-in-attribute-names.js","sourceRoot":"","sources":["../../../src/rules/html-no-underscores-in-attribute-names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EACL,qBAAqB,EAKtB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAIrD,MAAM,wCAAyC,SAAQ,qBAAqB;IAChE,+BAA+B,CAAC,EAAE,aAAa,EAAE,aAAa,EAAoC;QAC1G,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,gCAAgC,CAAC,EAAE,aAAa,EAAE,aAAa,EAAqC;QAC5G,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,gCAAgC,CAAC,EAAE,SAAS,EAAE,aAAa,EAAqC;QACxG,MAAM,aAAa,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAA;QAE1D,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,iCAAiC,CAAC,EAAE,SAAS,EAAE,aAAa,EAAsC;QAC1G,MAAM,aAAa,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAA;QAE1D,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAEO,KAAK,CAAC,aAA4B,EAAE,aAAgC;QAC1E,IAAI,CAAC,aAAa;YAAE,OAAM;QAE1B,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,CACb,eAAe,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,6DAA6D,EACrH,aAAa,CAAC,KAAM,CAAC,QAAQ,EAC7B,SAAS,CACV,CAAA;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,qCAAsC,SAAQ,UAAU;IACnE,IAAI,GAAG,wCAAwC,CAAA;IAE/C,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,wCAAwC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEhF,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
1
+ {"version":3,"file":"html-no-underscores-in-attribute-names.js","sourceRoot":"","sources":["../../../src/rules/html-no-underscores-in-attribute-names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EACL,qBAAqB,EAKtB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAKrD,MAAM,wCAAyC,SAAQ,qBAAqB;IAChE,+BAA+B,CAAC,EAAE,aAAa,EAAE,aAAa,EAAoC;QAC1G,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,gCAAgC,CAAC,EAAE,aAAa,EAAE,aAAa,EAAqC;QAC5G,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,gCAAgC,CAAC,EAAE,SAAS,EAAE,aAAa,EAAqC;QACxG,MAAM,aAAa,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAA;QAE1D,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,iCAAiC,CAAC,EAAE,SAAS,EAAE,aAAa,EAAsC;QAC1G,MAAM,aAAa,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAA;QAE1D,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAEO,KAAK,CAAC,aAA4B,EAAE,aAAgC;QAC1E,IAAI,CAAC,aAAa;YAAE,OAAM;QAE1B,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,CACb,eAAe,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,6DAA6D,EACrH,aAAa,CAAC,IAAI,EAAE,QAAQ,IAAI,aAAa,CAAC,QAAQ,CACvD,CAAA;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,qCAAsC,SAAQ,UAAU;IACnE,IAAI,GAAG,wCAAwC,CAAA;IAE/C,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,SAAS;SACpB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,wCAAwC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEhF,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
@@ -38,16 +38,25 @@ class TagNameLowercaseVisitor extends BaseRuleVisitor {
38
38
  const type = isNode(node, HTMLOpenTagNode) ? "Opening" : "Closing";
39
39
  const open = isNode(node, HTMLOpenTagNode) ? "<" : "</";
40
40
  if (tagName !== lowercaseTagName) {
41
- this.addOffense(`${type} tag name \`${open}${tagName}>\` should be lowercase. Use \`${open}${lowercaseTagName}>\` instead.`, node.tag_name.location, "error");
41
+ this.addOffense(`${type} tag name \`${open}${tagName}>\` should be lowercase. Use \`${open}${lowercaseTagName}>\` instead.`, node.tag_name.location, {
42
+ node,
43
+ tagName,
44
+ correctedTagName: lowercaseTagName
45
+ });
42
46
  }
43
47
  }
44
48
  }
45
49
  export class HTMLTagNameLowercaseRule extends ParserRule {
50
+ static autocorrectable = true;
46
51
  name = "html-tag-name-lowercase";
47
- isEnabled(result, context) {
48
- if (context?.fileName?.endsWith(".xml") || context?.fileName?.endsWith(".xml.erb")) {
49
- return false;
50
- }
52
+ get defaultConfig() {
53
+ return {
54
+ enabled: true,
55
+ severity: "error",
56
+ exclude: ["**/*.xml", "**/*.xml.erb"]
57
+ };
58
+ }
59
+ isEnabled(result, _context) {
51
60
  const checker = new XMLDeclarationChecker(this.name);
52
61
  checker.visit(result.value);
53
62
  return !checker.hasXMLDeclaration;
@@ -57,5 +66,14 @@ export class HTMLTagNameLowercaseRule extends ParserRule {
57
66
  visitor.visit(result.value);
58
67
  return visitor.offenses;
59
68
  }
69
+ autofix(offense, result, _context) {
70
+ if (!offense.autofixContext)
71
+ return null;
72
+ const { node: { tag_name }, correctedTagName } = offense.autofixContext;
73
+ if (!tag_name)
74
+ return null;
75
+ tag_name.value = correctedTagName;
76
+ return result;
77
+ }
60
78
  }
61
79
  //# sourceMappingURL=html-tag-name-lowercase.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-tag-name-lowercase.js","sourceRoot":"","sources":["../../../src/rules/html-tag-name-lowercase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAmB,eAAe,EAA2D,MAAM,kBAAkB,CAAA;AAIhJ,MAAM,qBAAsB,SAAQ,eAAe;IACjD,iBAAiB,GAAY,KAAK,CAAA;IAElC,uBAAuB,CAAC,KAAyB;QAC/C,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAA;IAC/B,CAAC;IAED,eAAe,CAAC,IAAU;QACxB,IAAI,IAAI,CAAC,iBAAiB;YAAE,OAAM;QAClC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC;CACF;AAED,MAAM,uBAAwB,SAAQ,eAAe;IACnD,oBAAoB,CAAC,IAAqB;QACxC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;YAC7C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAChC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED,oBAAoB,CAAC,IAAqB;QACxC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,qBAAqB,CAAC,IAAsB;QAC1C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAEO,YAAY,CAAC,IAA+C;QAClE,IAAI,CAAC,IAAI;YAAE,OAAM;QAEjB,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhC,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;QAE9C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAA;QAClE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;QAEvD,IAAI,OAAO,KAAK,gBAAgB,EAAE,CAAC;YACjC,IAAI,CAAC,UAAU,CACb,GAAG,IAAI,eAAe,IAAI,GAAG,OAAO,kCAAkC,IAAI,GAAG,gBAAgB,cAAc,EAC3G,IAAI,CAAC,QAAS,CAAC,QAAQ,EACvB,OAAO,CACR,CAAA;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACtD,IAAI,GAAG,yBAAyB,CAAA;IAEhC,SAAS,CAAC,MAAmB,EAAE,OAA8B;QAC3D,IAAI,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACnF,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpD,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3B,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC/D,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
1
+ {"version":3,"file":"html-tag-name-lowercase.js","sourceRoot":"","sources":["../../../src/rules/html-tag-name-lowercase.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,22 @@
1
1
  export * from "./rule-utils.js";
2
+ export * from "./herb-disable-comment-base.js";
2
3
  export * from "./erb-comment-syntax.js";
4
+ export * from "./erb-no-case-node-children.js";
3
5
  export * from "./erb-no-empty-tags.js";
6
+ export * from "./erb-no-extra-newline.js";
7
+ export * from "./erb-no-extra-whitespace-inside-tags.js";
4
8
  export * from "./erb-no-output-control-flow.js";
5
9
  export * from "./erb-no-silent-tag-in-attribute-name.js";
6
10
  export * from "./erb-prefer-image-tag-helper.js";
7
- export * from "./erb-requires-trailing-newline.js";
11
+ export * from "./erb-require-trailing-newline.js";
12
+ export * from "./erb-require-whitespace-inside-tags.js";
13
+ export * from "./erb-right-trim.js";
14
+ export * from "./herb-disable-comment-valid-rule-name.js";
15
+ export * from "./herb-disable-comment-no-redundant-all.js";
16
+ export * from "./herb-disable-comment-no-duplicate-rules.js";
17
+ export * from "./herb-disable-comment-missing-rules.js";
18
+ export * from "./herb-disable-comment-malformed.js";
19
+ export * from "./herb-disable-comment-unnecessary.js";
8
20
  export * from "./html-anchor-require-href.js";
9
21
  export * from "./html-aria-label-is-well-formatted.js";
10
22
  export * from "./html-aria-level-must-be-valid.js";
@@ -14,22 +26,26 @@ export * from "./html-attribute-double-quotes.js";
14
26
  export * from "./html-attribute-equals-spacing.js";
15
27
  export * from "./html-attribute-values-require-quotes.js";
16
28
  export * from "./html-avoid-both-disabled-and-aria-disabled.js";
29
+ export * from "./html-body-only-elements.js";
17
30
  export * from "./html-boolean-attributes-no-value.js";
31
+ export * from "./html-head-only-elements.js";
18
32
  export * from "./html-iframe-has-title.js";
19
33
  export * from "./html-img-require-alt.js";
34
+ export * from "./html-input-require-autocomplete.js";
20
35
  export * from "./html-navigation-has-label.js";
21
36
  export * from "./html-no-aria-hidden-on-focusable.js";
22
37
  export * from "./html-no-block-inside-inline.js";
23
38
  export * from "./html-no-duplicate-attributes.js";
24
39
  export * from "./html-no-duplicate-ids.js";
40
+ export * from "./html-no-duplicate-meta-names.js";
25
41
  export * from "./html-no-empty-attributes.js";
26
42
  export * from "./html-no-empty-headings.js";
27
43
  export * from "./html-no-nested-links.js";
28
44
  export * from "./html-no-positive-tab-index.js";
29
45
  export * from "./html-no-self-closing.js";
46
+ export * from "./html-no-space-in-tag.js";
30
47
  export * from "./html-no-title-attribute.js";
48
+ export * from "./html-no-underscores-in-attribute-names.js";
31
49
  export * from "./html-tag-name-lowercase.js";
32
50
  export * from "./svg-tag-name-capitalization.js";
33
- export * from "./html-no-underscores-in-attribute-names.js";
34
- export * from "./erb-right-trim.js";
35
51
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA;AACtC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,oCAAoC,CAAA;AAClD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,wCAAwC,CAAA;AACtD,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,2CAA2C,CAAA;AACzD,cAAc,iDAAiD,CAAA;AAC/D,cAAc,uCAAuC,CAAA;AACrD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uCAAuC,CAAA;AACrD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,kCAAkC,CAAA;AAChD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gCAAgC,CAAA;AAE9C,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0CAA0C,CAAA;AACxD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AACvD,cAAc,qBAAqB,CAAA;AAEnC,cAAc,2CAA2C,CAAA;AACzD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,8CAA8C,CAAA;AAC5D,cAAc,yCAAyC,CAAA;AACvD,cAAc,qCAAqC,CAAA;AACnD,cAAc,uCAAuC,CAAA;AAErD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,wCAAwC,CAAA;AACtD,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,2CAA2C,CAAA;AACzD,cAAc,iDAAiD,CAAA;AAC/D,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uCAAuC,CAAA;AACrD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sCAAsC,CAAA;AACpD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uCAAuC,CAAA;AACrD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6CAA6C,CAAA;AAC3D,cAAc,8BAA8B,CAAA;AAE5C,cAAc,kCAAkC,CAAA"}
@@ -1,6 +1,12 @@
1
1
  import { ParserRule } from "../types.js";
2
2
  export class ParserNoErrorsRule extends ParserRule {
3
3
  name = "parser-no-errors";
4
+ get defaultConfig() {
5
+ return {
6
+ enabled: true,
7
+ severity: "error"
8
+ };
9
+ }
4
10
  check(result) {
5
11
  return result.recursiveErrors().map(error => this.herbErrorToLintOffense(error));
6
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parser-no-errors.js","sourceRoot":"","sources":["../../../src/rules/parser-no-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAKxC,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAChD,IAAI,GAAG,kBAAkB,CAAA;IAEzB,KAAK,CAAC,MAAmB;QACvB,OAAO,MAAM,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAC1C,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CACnC,CAAA;IACH,CAAC;IAEO,sBAAsB,CAAC,KAAgB;QAC7C,OAAO;YACL,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,OAAO,KAAK,CAAC,IAAI,KAAK;YAC/C,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,QAAQ;SACjB,CAAA;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"parser-no-errors.js","sourceRoot":"","sources":["../../../src/rules/parser-no-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAKxC,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAChD,IAAI,GAAG,kBAAkB,CAAA;IAEzB,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,OAAO;SAClB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAmB;QACvB,OAAO,MAAM,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAC1C,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CACnC,CAAA;IACH,CAAC;IAEO,sBAAsB,CAAC,KAAgB;QAC7C,OAAO;YACL,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,OAAO,KAAK,CAAC,IAAI,KAAK;YAC/C,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,QAAQ;SACjB,CAAA;IACH,CAAC;CACF"}
@@ -1,4 +1,4 @@
1
- import { Visitor, Position, Location, getStaticAttributeName, hasDynamicAttributeName as hasNodeDynamicAttributeName, getCombinedAttributeName, hasERBOutput, getStaticContentFromNodes, hasStaticContent, isEffectivelyStatic, getValidatableStaticContent } from "@herb-tools/core";
1
+ import { Visitor, Location, getStaticAttributeName, hasDynamicAttributeName as hasNodeDynamicAttributeName, getCombinedAttributeName, hasERBOutput, getStaticContentFromNodes, hasStaticContent, isEffectivelyStatic, getValidatableStaticContent } from "@herb-tools/core";
2
2
  import { DEFAULT_LINT_CONTEXT } from "../types.js";
3
3
  export var ControlFlowType;
4
4
  (function (ControlFlowType) {
@@ -18,23 +18,24 @@ export class BaseRuleVisitor extends Visitor {
18
18
  this.context = { ...DEFAULT_LINT_CONTEXT, ...context };
19
19
  }
20
20
  /**
21
- * Helper method to create a lint offense
21
+ * Helper method to create an unbound lint offense (without severity).
22
+ * The Linter will bind severity based on the rule's config.
22
23
  */
23
- createOffense(message, location, severity = "error") {
24
+ createOffense(message, location, autofixContext) {
24
25
  return {
25
26
  rule: this.ruleName,
26
27
  code: this.ruleName,
27
28
  source: "Herb Linter",
28
29
  message,
29
30
  location,
30
- severity,
31
+ autofixContext,
31
32
  };
32
33
  }
33
34
  /**
34
35
  * Helper method to add an offense to the offenses array
35
36
  */
36
- addOffense(message, location, severity = "error") {
37
- this.offenses.push(this.createOffense(message, location, severity));
37
+ addOffense(message, location, autofixContext) {
38
+ this.offenses.push(this.createOffense(message, location, autofixContext));
38
39
  }
39
40
  }
40
41
  /**
@@ -42,6 +43,7 @@ export class BaseRuleVisitor extends Visitor {
42
43
  * This allows rules to track state across different control flow structures
43
44
  * like if/else branches, loops, etc.
44
45
  *
46
+ * @template TAutofixContext - Type for autofix context (node + custom data)
45
47
  * @template TControlFlowState - Type for state passed between onEnterControlFlow and onExitControlFlow
46
48
  * @template TBranchState - Type for state passed between onEnterBranch and onExitBranch
47
49
  */
@@ -51,7 +53,7 @@ export class ControlFlowTrackingVisitor extends BaseRuleVisitor {
51
53
  /**
52
54
  * Handle visiting a control flow node with proper scope management
53
55
  */
54
- handleControlFlowNode(node, controlFlowType, visitChildren) {
56
+ handleControlFlowNode(_node, controlFlowType, visitChildren) {
55
57
  const wasInControlFlow = this.isInControlFlow;
56
58
  const previousControlFlowType = this.currentControlFlowType;
57
59
  this.isInControlFlow = true;
@@ -111,6 +113,8 @@ export function getAttributes(node) {
111
113
  * Gets the tag name from an HTML tag node (lowercased)
112
114
  */
113
115
  export function getTagName(node) {
116
+ if (!node)
117
+ return null;
114
118
  return node.tag_name?.value.toLowerCase() || null;
115
119
  }
116
120
  /**
@@ -426,9 +430,7 @@ export function createEndOfFileLocation(source) {
426
430
  const lastLine = lines[lines.length - 1];
427
431
  const lastColumnNumber = lastLine.length;
428
432
  const startColumn = lastColumnNumber > 0 ? lastColumnNumber - 1 : 0;
429
- const start = new Position(lastLineNumber, startColumn);
430
- const end = new Position(lastLineNumber, lastColumnNumber);
431
- return new Location(start, end);
433
+ return Location.from(lastLineNumber, startColumn, lastLineNumber, lastColumnNumber);
432
434
  }
433
435
  /**
434
436
  * Checks if an element is inline
@@ -571,23 +573,24 @@ export class BaseLexerRuleVisitor {
571
573
  this.context = { ...DEFAULT_LINT_CONTEXT, ...context };
572
574
  }
573
575
  /**
574
- * Helper method to create a lint offense for lexer rules
576
+ * Helper method to create an unbound lint offense (without severity).
577
+ * The Linter will bind severity based on the rule's config.
575
578
  */
576
- createOffense(message, location, severity = "error") {
579
+ createOffense(message, location, autofixContext) {
577
580
  return {
578
581
  rule: this.ruleName,
579
582
  code: this.ruleName,
580
583
  source: "Herb Linter",
581
584
  message,
582
585
  location,
583
- severity,
586
+ autofixContext,
584
587
  };
585
588
  }
586
589
  /**
587
590
  * Helper method to add an offense to the offenses array
588
591
  */
589
- addOffense(message, location, severity = "error") {
590
- this.offenses.push(this.createOffense(message, location, severity));
592
+ addOffense(message, location, autofixContext) {
593
+ this.offenses.push(this.createOffense(message, location, autofixContext));
591
594
  }
592
595
  /**
593
596
  * Main entry point for lexer rule visitors
@@ -625,23 +628,24 @@ export class BaseSourceRuleVisitor {
625
628
  this.context = { ...DEFAULT_LINT_CONTEXT, ...context };
626
629
  }
627
630
  /**
628
- * Helper method to create a lint offense for source rules
631
+ * Helper method to create an unbound lint offense (without severity).
632
+ * The Linter will bind severity based on the rule's config.
629
633
  */
630
- createOffense(message, location, severity = "error") {
634
+ createOffense(message, location, autofixContext) {
631
635
  return {
632
636
  rule: this.ruleName,
633
637
  code: this.ruleName,
634
638
  source: "Herb Linter",
635
639
  message,
636
640
  location,
637
- severity,
641
+ autofixContext,
638
642
  };
639
643
  }
640
644
  /**
641
645
  * Helper method to add an offense to the offenses array
642
646
  */
643
- addOffense(message, location, severity = "error") {
644
- this.offenses.push(this.createOffense(message, location, severity));
647
+ addOffense(message, location, autofixContext) {
648
+ this.offenses.push(this.createOffense(message, location, autofixContext));
645
649
  }
646
650
  /**
647
651
  * Main entry point for source rule visitors
@@ -650,17 +654,193 @@ export class BaseSourceRuleVisitor {
650
654
  visit(source) {
651
655
  this.visitSource(source);
652
656
  }
653
- /**
654
- * Helper method to create a location for a specific position in the source
655
- */
656
- createLocationAt(source, position) {
657
- const beforePosition = source.substring(0, position);
658
- const lines = beforePosition.split('\n');
659
- const line = lines.length;
660
- const column = lines[lines.length - 1].length + 1;
661
- const start = new Position(line, column);
662
- const end = new Position(line, column);
663
- return new Location(start, end);
657
+ }
658
+ /**
659
+ * Autofix utilities for applying string replacements
660
+ */
661
+ /**
662
+ * Checks if two locations are equal
663
+ * @param a - First location
664
+ * @param b - Second location
665
+ * @returns true if locations are equal
666
+ */
667
+ export function locationsEqual(a, b) {
668
+ return a.start.line === b.start.line &&
669
+ a.start.column === b.start.column &&
670
+ a.end.line === b.end.line &&
671
+ a.end.column === b.end.column;
672
+ }
673
+ /**
674
+ * Finds a node in the AST that has a specific location
675
+ * Uses direct recursive traversal for reliability
676
+ * @param root - The root node to search from
677
+ * @param location - The location to match
678
+ * @param predicate - Optional predicate function to filter nodes (e.g., isERBNode)
679
+ * @returns The matching node or null if not found
680
+ */
681
+ export function findNodeByLocation(root, location, predicate) {
682
+ const visited = new Set();
683
+ function search(node) {
684
+ if (!node || visited.has(node))
685
+ return null;
686
+ visited.add(node);
687
+ if (node.location && locationsEqual(node.location, location)) {
688
+ if (!predicate || predicate(node)) {
689
+ return node;
690
+ }
691
+ }
692
+ const propsToCheck = ['tag_opening', 'tag_closing', 'tag_name', 'name', 'equals', 'value', 'content'];
693
+ for (const prop of propsToCheck) {
694
+ if (node[prop]?.location && locationsEqual(node[prop].location, location)) {
695
+ if (!predicate || predicate(node)) {
696
+ return node;
697
+ }
698
+ }
699
+ }
700
+ if (typeof node.compactChildNodes === 'function') {
701
+ for (const child of node.compactChildNodes()) {
702
+ const found = search(child);
703
+ if (found)
704
+ return found;
705
+ }
706
+ }
707
+ else {
708
+ if (node.children && Array.isArray(node.children)) {
709
+ for (const child of node.children) {
710
+ const found = search(child);
711
+ if (found)
712
+ return found;
713
+ }
714
+ }
715
+ if (node.body && Array.isArray(node.body)) {
716
+ for (const child of node.body) {
717
+ const found = search(child);
718
+ if (found)
719
+ return found;
720
+ }
721
+ }
722
+ }
723
+ return null;
664
724
  }
725
+ return search(root);
726
+ }
727
+ /**
728
+ * AST Navigation Utilities
729
+ * These utilities help navigate the AST tree for complex autofix operations
730
+ */
731
+ /**
732
+ * Finds the parent node of a given child node in the AST
733
+ * @param root - The root node to search from (typically the document node)
734
+ * @param target - The child node to find the parent of
735
+ * @returns The parent node, or null if not found
736
+ *
737
+ * @example
738
+ * const parent = findParent(result.value, offense.autofixContext.node)
739
+ * if (parent?.type === "AST_HTML_ELEMENT_NODE") {
740
+ * // Modify parent...
741
+ * }
742
+ */
743
+ export function findParent(root, target) {
744
+ let parentNode = null;
745
+ const search = (node, _parent = null) => {
746
+ if (parentNode)
747
+ return;
748
+ const nodeAny = node;
749
+ if (nodeAny.children) {
750
+ for (const child of nodeAny.children) {
751
+ if (child === target) {
752
+ parentNode = node;
753
+ return;
754
+ }
755
+ }
756
+ }
757
+ const propsToCheck = ['open_tag', 'close_tag', 'body', 'name', 'value'];
758
+ for (const prop of propsToCheck) {
759
+ const value = node[prop];
760
+ if (value === target) {
761
+ parentNode = node;
762
+ return;
763
+ }
764
+ if (Array.isArray(value) && value.includes(target)) {
765
+ parentNode = node;
766
+ return;
767
+ }
768
+ }
769
+ if (nodeAny.children) {
770
+ for (const child of nodeAny.children) {
771
+ search(child, node);
772
+ if (parentNode)
773
+ return;
774
+ }
775
+ }
776
+ for (const prop of propsToCheck) {
777
+ const value = node[prop];
778
+ if (Array.isArray(value)) {
779
+ for (const item of value) {
780
+ if (item && typeof item === 'object' && 'type' in item) {
781
+ search(item, node);
782
+ if (parentNode)
783
+ return;
784
+ }
785
+ }
786
+ }
787
+ else if (value && typeof value === 'object' && 'type' in value) {
788
+ search(value, node);
789
+ if (parentNode)
790
+ return;
791
+ }
792
+ }
793
+ };
794
+ search(root);
795
+ return parentNode;
796
+ }
797
+ export const DOCUMENT_ONLY_TAG_NAMES = new Set([
798
+ "html"
799
+ ]);
800
+ export const HTML_ONLY_TAG_NAMES = new Set([
801
+ "head", "body"
802
+ ]);
803
+ export const HEAD_ONLY_TAG_NAMES = new Set([
804
+ "base",
805
+ "title",
806
+ "style",
807
+ "meta",
808
+ "link",
809
+ ]);
810
+ export const HEAD_AND_BODY_TAG_NAMES = new Set([
811
+ "script",
812
+ "noscript",
813
+ "template",
814
+ ]);
815
+ export function isDocumentOnlyTag(tagName) {
816
+ return DOCUMENT_ONLY_TAG_NAMES.has(tagName.toLowerCase());
817
+ }
818
+ export function isHtmlOnlyTag(tagName) {
819
+ return HTML_ONLY_TAG_NAMES.has(tagName.toLowerCase());
820
+ }
821
+ export function isHeadOnlyTag(tagName) {
822
+ return HEAD_ONLY_TAG_NAMES.has(tagName.toLowerCase());
823
+ }
824
+ export function isHeadAndBodyTag(tagName) {
825
+ return HEAD_AND_BODY_TAG_NAMES.has(tagName.toLowerCase());
826
+ }
827
+ export function isBodyOnlyTag(tagName) {
828
+ const tag = tagName.toLowerCase();
829
+ return (!isDocumentOnlyTag(tag) &&
830
+ !isHtmlOnlyTag(tag) &&
831
+ !isHeadOnlyTag(tag) &&
832
+ !isHeadAndBodyTag(tag));
833
+ }
834
+ export function isBodyTag(tagName) {
835
+ const tag = tagName.toLowerCase();
836
+ return (!isDocumentOnlyTag(tag) &&
837
+ !isHtmlOnlyTag(tag) &&
838
+ (isBodyOnlyTag(tag) || isHeadAndBodyTag(tag)));
839
+ }
840
+ export function isHeadTag(tagName) {
841
+ const tag = tagName.toLowerCase();
842
+ return (!isDocumentOnlyTag(tag) &&
843
+ !isHtmlOnlyTag(tag) &&
844
+ (isHeadOnlyTag(tag) || isHeadAndBodyTag(tag)));
665
845
  }
666
846
  //# sourceMappingURL=rule-utils.js.map