@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,74 @@
1
+ # Linter Rule: Disallow extra newlines
2
+
3
+ **Rule:** `erb-no-extra-newline`
4
+
5
+ ## Description
6
+
7
+ Disallow more than two consecutive blank lines in ERB templates. This rule enforces a maximum of two blank lines between content to maintain consistent vertical spacing throughout your templates.
8
+
9
+ ## Rationale
10
+
11
+ Excessive blank lines can make templates harder to read and maintain. While some vertical spacing improves readability by visually separating logical sections, too many blank lines create unnecessary whitespace that:
12
+
13
+ * Makes it harder to see related code on the same screen
14
+ * Creates inconsistent visual rhythm in the codebase
15
+ * Can accidentally accumulate through merge conflicts or refactoring
16
+ * Provides no additional clarity beyond what 1-2 blank lines already achieve
17
+
18
+ Limiting to two consecutive blank lines strikes a balance between allowing clear section separation while maintaining code density and readability.
19
+
20
+ ## Examples
21
+
22
+ ### ✅ Good
23
+
24
+ ```html
25
+ line 1
26
+
27
+ line 3
28
+
29
+ <div>
30
+ <h1>Title</h1>
31
+ </div>
32
+
33
+ <div>
34
+ <h1>Section 1</h1>
35
+
36
+ <p>Content here</p>
37
+ </div>
38
+
39
+ <div>
40
+ <h1>Section 1</h1>
41
+
42
+
43
+ <h1>Section 2</h1>
44
+ </div>
45
+ ```
46
+
47
+ ### 🚫 Bad
48
+
49
+ ```erb
50
+ line 1
51
+
52
+
53
+
54
+ line 3
55
+
56
+ <div>
57
+ <h1>Title</h1>
58
+
59
+
60
+
61
+ <p>Content</p>
62
+ </div>
63
+
64
+ <%= user.name %>
65
+
66
+
67
+
68
+
69
+ <%= user.email %>
70
+ ```
71
+
72
+ ## References
73
+
74
+ - [Inspiration: ERB Lint `ExtraNewline` rule](https://github.com/Shopify/erb_lint/blob/main/README.md)
@@ -0,0 +1,39 @@
1
+ # Linter Rule: Avoid extra whitespace inside ERB tags
2
+
3
+ **Rule:** `erb-no-extra-whitespace-inside-tags`
4
+
5
+ ## Description
6
+
7
+ This rule disallows **multiple consecutive spaces** immediately inside ERB tags (`<%`, `<%=`) or before the closing delimiter (`%>`). It ensures that ERB code is consistently and cleanly formatted, with exactly one space after the opening tag and one space before the closing tag (when appropriate).
8
+
9
+ ## Rationale
10
+
11
+ Excess whitespace inside ERB tags can lead to inconsistent formatting and untidy templates. By enforcing a consistent amount of whitespace inside ERB tags, this rule improves code readability, aligns with the formatter and style guide expectations, and avoids unnecessary visual noise.
12
+
13
+ ## Examples
14
+
15
+ ### ✅ Good
16
+
17
+ ```erb
18
+ <%= output %>
19
+
20
+ <% if condition %>
21
+ True
22
+ <% end %>
23
+ ```
24
+
25
+ ### 🚫 Bad
26
+
27
+ ```erb
28
+ <%= output %>
29
+
30
+ <%= output %>
31
+
32
+ <% if condition %>
33
+ True
34
+ <% end %>
35
+ ```
36
+
37
+ ## References
38
+
39
+ \-
@@ -1,6 +1,6 @@
1
1
  # Linter Rule: Enforce trailing newline
2
2
 
3
- **Rule:** `erb-requires-trailing-newline`
3
+ **Rule:** `erb-require-trailing-newline`
4
4
 
5
5
  ## Description
6
6
 
@@ -4,15 +4,13 @@
4
4
 
5
5
  ## Description
6
6
 
7
- This rule enforces the use of `-%>` for right-trimming ERB output tags (like `<%= %>`) instead of `=%>`. It also warns when right-trimming syntax (`-%>` or `=%>`) is used on non-output ERB tags (like `<% %>`, `<% if %>`, etc.) where it has no effect.
7
+ This rule enforces the use of `-%>` for right-trimming ERB output tags (like `<%= %>`) instead of `=%>`.
8
8
 
9
9
  ## Rationale
10
10
 
11
- While `=%>` can be used for right-trimming whitespace in some ERB engines (like Erubi), it is an obscure and not well-defined syntax that lacks consistent support across most ERB implementations. The `-%>` syntax is the standard, well-documented approach for right-trimming that is universally supported and consistent with left-trimming syntax (`<%-`).
11
+ While `=%>` can be used for right-trimming whitespace in some ERB engines (like Erubi), it is an obscure and not well-defined syntax that lacks consistent support across most ERB implementations.
12
12
 
13
- Additionally, right-trimming syntax only has an effect on ERB output tags (`<%=` and `<%==`). Using `-%>` or `=%>` on non-output ERB tags (control flow like `<% if %>`, `<% each %>`, etc.) has no effect and is misleading.
14
-
15
- Using `-%>` for output tags ensures compatibility across different ERB engines, improves code clarity, and aligns with established Rails and ERB conventions.
13
+ The `-%>` syntax is the standard, well-documented approach for right-trimming that is universally supported and consistent with left-trimming syntax (`<%-`). Using `-%>` ensures compatibility across different ERB engines, improves code clarity, and aligns with established Rails and ERB conventions.
16
14
 
17
15
  ## Examples
18
16
 
@@ -21,7 +19,7 @@ Using `-%>` for output tags ensures compatibility across different ERB engines,
21
19
  ```erb
22
20
  <%= title -%>
23
21
 
24
- <% if true %>
22
+ <% if condition? %>
25
23
  <h1>Content</h1>
26
24
  <% end %>
27
25
 
@@ -39,10 +37,7 @@ Using `-%>` for output tags ensures compatibility across different ERB engines,
39
37
  <% title =%>
40
38
 
41
39
 
42
- <% title -%>
43
-
44
-
45
- <% if true -%>
40
+ <% if true =%>
46
41
  <h1>Content</h1>
47
42
  <% end %>
48
43
 
@@ -0,0 +1,45 @@
1
+ # Linter Rule: Detect malformed `herb:disable` comments
2
+
3
+ **Rule:** `herb-disable-comment-malformed`
4
+
5
+ ## Description
6
+
7
+ Detects malformed `<%# herb:disable ... %>` comments that have syntax errors like trailing commas, leading commas, consecutive commas, or missing spaces after `herb:disable`.
8
+
9
+ ## Rationale
10
+
11
+ Malformed `<%# herb:disable ... %>` comments can fail to parse correctly, leading to unexpected behavior where rules aren't actually disabled. This rule catches common syntax errors to ensure your disable comments work as intended.
12
+
13
+ ## Examples
14
+
15
+ ### ✅ Good
16
+
17
+ ```erb
18
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
19
+
20
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
21
+
22
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase , html-attribute-double-quotes %>
23
+
24
+ <DIV>test</DIV> <%# herb:disable all %>
25
+ ```
26
+
27
+ ### 🚫 Bad
28
+
29
+ ```erb
30
+ <div>test</div> <%# herb:disable html-tag-name-lowercase, %>
31
+
32
+ <div>test</div> <%# herb:disable , html-tag-name-lowercase %>
33
+
34
+ <div>test</div> <%# herb:disable html-tag-name-lowercase,, html-attribute-double-quotes %>
35
+
36
+ <div>test</div> <%# herb:disable html-tag-name-lowercase,, %>
37
+
38
+ <DIV>test</DIV> <%# herb:disableall %>
39
+
40
+ <DIV>test</DIV> <%# herb:disablehtml-tag-name-lowercase %>
41
+ ```
42
+
43
+ ## References
44
+
45
+ \-
@@ -0,0 +1,60 @@
1
+ # Linter Rule: Require rule names in `herb:disable` comments
2
+
3
+ **Rule:** `herb-disable-comment-missing-rules`
4
+
5
+ ## Description
6
+
7
+ Requires that `<%# herb:disable %>` comments specify either `all` or at least one specific rule name.
8
+
9
+ ## Rationale
10
+
11
+ A `<%# herb:disable %>` comment without any rule names serves no purpose and likely indicates an incomplete edit or mistake. The developer either:
12
+
13
+ - Forgot to specify which rules to disable
14
+ - Intended to use `herb:disable all` but forgot to add `all`
15
+ - Started typing a comment but didn't finish
16
+
17
+ This rule ensures all `<%# herb:disable %>` comments are complete and functional.
18
+
19
+ ## Examples
20
+
21
+ ### ✅ Good
22
+
23
+ ```erb
24
+ <DIV class='value'>test</DIV> <%# herb:disable all %>
25
+
26
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
27
+
28
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
29
+ ```
30
+
31
+ ### 🚫 Bad
32
+
33
+ ```erb
34
+ <div>test</div> <%# herb:disable %>
35
+
36
+ <div>test</div> <%# herb:disable %>
37
+ ```
38
+
39
+ ## Fix
40
+
41
+ Add either `all` or specific rule names:
42
+
43
+ **Option 1:** Disable all rules
44
+ ```erb
45
+ <DIV>test</DIV> <%# herb:disable all %>
46
+ ```
47
+
48
+ **Option 2:** Disable specific rules
49
+ ```erb
50
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
51
+ ```
52
+
53
+ **Option 3:** Remove the comment if it's not needed
54
+ ```erb
55
+ <div>test</div>
56
+ ```
57
+
58
+ ## References
59
+
60
+ \-
@@ -0,0 +1,49 @@
1
+ # Linter Rule: Disallow duplicate rule names in `herb:disable` comments
2
+
3
+ **Rule:** `herb-disable-comment-no-duplicate-rules`
4
+
5
+ ## Description
6
+
7
+ Prevents listing the same rule name multiple times in a `<%# herb:disable ... %>` comment.
8
+
9
+ ## Rationale
10
+
11
+ Listing a rule name more than once in a `<%# herb:disable ... %>` comment is unnecessary and likely indicates a copy-paste error or mistake. Each rule only needs to be mentioned once to be disabled.
12
+
13
+ This rule helps keep disable comments clean and prevents confusion about which rules are being disabled.
14
+
15
+ ## Examples
16
+
17
+ ### ✅ Good
18
+
19
+ ```erb
20
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
21
+
22
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
23
+
24
+ <DIV>test</DIV> <%# herb:disable all %>
25
+ ```
26
+
27
+ ### 🚫 Bad
28
+
29
+ ```erb
30
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase, html-tag-name-lowercase %>
31
+
32
+ <DIV class='value'>test</DIV> <%# herb:disable html-attribute-double-quotes, html-tag-name-lowercase, html-tag-name-lowercase %>
33
+
34
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-tag-name-lowercase, html-attribute-double-quotes, html-attribute-double-quotes %>
35
+
36
+ <DIV>test</DIV> <%# herb:disable all, all %>
37
+ ```
38
+
39
+ ## Fix
40
+
41
+ Remove the duplicate rule names, keeping only one instance of each:
42
+
43
+ ```erb
44
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
45
+ ```
46
+
47
+ ## References
48
+
49
+ \-
@@ -0,0 +1,53 @@
1
+ # Linter Rule: Disallow redundant use of `all` in `herb:disable` comments
2
+
3
+ **Rule:** `herb-disable-comment-no-redundant-all`
4
+
5
+ ## Description
6
+
7
+ Prevents using `all` together with specific rule names in `<%# herb:disable ... %>` comments, as this is redundant.
8
+
9
+ ## Rationale
10
+
11
+ When you use `all` in a `<%# herb:disable ... %>` comment, it disables every linter rule for that line. Adding specific rule names alongside `all` is redundant because `all` already covers them.
12
+
13
+ This rule helps maintain clean, concise disable comments by ensuring you either use `herb:disable all` by itself to disable all rules or lists only the specific rules you want to disable.
14
+
15
+ ## Examples
16
+
17
+ ### ✅ Good
18
+
19
+ ```erb
20
+ <DIV>test</DIV> <%# herb:disable all %>
21
+
22
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
23
+
24
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
25
+ ```
26
+
27
+ ### 🚫 Bad
28
+
29
+ ```erb
30
+ <DIV>test</DIV> <%# herb:disable all, html-tag-name-lowercase %>
31
+
32
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase, all, html-attribute-double-quotes %>
33
+
34
+ <DIV>test</DIV> <%# herb:disable all, all %>
35
+ ```
36
+
37
+ ## Fix
38
+
39
+ Remove either the `all` keyword or the specific rule names:
40
+
41
+ **Option 1:** Keep only `all`
42
+ ```erb
43
+ <DIV class='value'>test</DIV> <%# herb:disable all %>
44
+ ```
45
+
46
+ **Option 2:** Keep only specific rules
47
+ ```erb
48
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
49
+ ```
50
+
51
+ ## References
52
+
53
+ \-
@@ -0,0 +1,44 @@
1
+ # Linter Rule: Detect unnecessary `herb:disable` comments
2
+
3
+ **Rule:** `herb-disable-comment-unnecessary`
4
+
5
+ ## Description
6
+
7
+ Warns when a `<%# herb:disable ... %>` comment doesn't actually suppress any linter offenses on that line, indicating it's unnecessary and should be removed.
8
+
9
+ ## Rationale
10
+
11
+ Unnecessary `<%# herb:disable ... %>` comments create noise in the codebase and can mislead developers about which rules are being suppressed. These comments often remain after the code has been refactored and no longer triggers the offense.
12
+
13
+ Removing unnecessary disable comments keeps the codebase clean and ensures that suppression comments accurately reflect actual rule violations being intentionally ignored.
14
+
15
+ ## Examples
16
+
17
+ ### ✅ Good
18
+
19
+ ```erb
20
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
21
+
22
+ <DIV id='test-1'>content</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
23
+
24
+ <DIV id='test-2'>content</DIV> <%# herb:disable all %>
25
+ ```
26
+
27
+ ### 🚫 Bad
28
+
29
+ ```erb
30
+ <div>test</div> <%# herb:disable html-tag-name-lowercase %>
31
+
32
+ <div id="test">content</div> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
33
+
34
+ <div id="test-1">content</div> <%# herb:disable all %>
35
+
36
+ <DIV id='test-2'>content</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes, html-no-empty-headings %>
37
+
38
+ <div>test</div> <%# herb:disableall %>
39
+ ```
40
+
41
+
42
+ ## References
43
+
44
+ \-
@@ -0,0 +1,41 @@
1
+ # Linter Rule: Validate rule names in `herb:disable` comments
2
+
3
+ **Rule:** `herb-disable-comment-valid-rule-name`
4
+
5
+ ## Description
6
+
7
+ Ensures that all rule names specified in `<%# herb:disable ... %>` comments are valid and exist in the linter. This catches typos, references to non-existent rules and missing comma between rule names.
8
+
9
+ ## Rationale
10
+
11
+ Using invalid or misspelled rule names in `<%# herb:disable ... %>` comments can lead to confusion and unexpected behavior. The comment won't disable anything if the rule name doesn't exist, leaving developers wondering why linter warnings persist.
12
+
13
+ By validating rule names, this rule helps catch typos early, identify removed or renamed rule and provide helpful suggestions for similar rule names using fuzzy matching.
14
+
15
+ ## Examples
16
+
17
+ ### ✅ Good
18
+
19
+ ```erb
20
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase %>
21
+
22
+ <DIV class='value'>test</DIV> <%# herb:disable html-tag-name-lowercase, html-attribute-double-quotes %>
23
+
24
+ <DIV>test</DIV> <%# herb:disable all %>
25
+ ```
26
+
27
+ ### 🚫 Bad
28
+
29
+ ```erb
30
+ <div>test</div> <%# herb:disable this-rule-doesnt-exist %>
31
+
32
+ <div>test</div> <%# herb:disable html-tag-lowercase %>
33
+
34
+ <DIV>test</DIV> <%# herb:disable html-tag-name-lowercase, invalid-rule-name %>
35
+
36
+ <div>test</div> <%# herb:disable html-tag-name-lowercase html-attribute-double-quotes %>
37
+ ```
38
+
39
+ ## References
40
+
41
+ \-
@@ -22,20 +22,17 @@ Validating against a known list ensures you're using correct and effective ARIA
22
22
 
23
23
  ```html
24
24
  <div role="button" aria-pressed="false">Toggle</div>
25
- <input type="text" aria-label="Search" />
25
+ <input type="text" aria-label="Search" autocomplete="off">
26
26
  <span role="heading" aria-level="2">Title</span>
27
27
  ```
28
28
 
29
29
  ### 🚫 Bad
30
30
 
31
31
  ```html
32
- <!-- typo -->
33
32
  <div role="button" aria-presed="false">Toggle</div>
34
33
 
35
- <!-- typo -->
36
- <input type="text" aria-lable="Search" />
34
+ <input type="text" aria-lable="Search" autocomplete="off">
37
35
 
38
- <!-- invalid -->
39
36
  <span aria-size="large" role="heading" aria-level="2">Title</span>
40
37
  ```
41
38
 
@@ -16,7 +16,7 @@ The `aria-label` attribute provides an accessible name for elements that will be
16
16
 
17
17
  ```erb
18
18
  <button aria-label="Close dialog">X</button>
19
- <input aria-label="Search products" type="search">
19
+ <input aria-label="Search products" type="search" autocomplete="off">
20
20
  <button aria-label="Page 2 of 10">2</button>
21
21
  ```
22
22
 
@@ -17,7 +17,7 @@ Double quotes are the most widely used and expected style for HTML attributes. C
17
17
  ### ✅ Good
18
18
 
19
19
  ```html
20
- <input type="text">
20
+ <input type="text" autocomplete="off">
21
21
 
22
22
  <a href="/profile">Profile</a>
23
23
 
@@ -31,7 +31,7 @@ Double quotes are the most widely used and expected style for HTML attributes. C
31
31
  ### 🚫 Bad
32
32
 
33
33
  ```html
34
- <input type='text'>
34
+ <input type='text' autocomplete="off">
35
35
 
36
36
  <a href='/profile'>Profile</a>
37
37
 
@@ -17,7 +17,7 @@ Extra whitespace around the `=` in HTML attribute assignments is unnecessary, in
17
17
  ```erb
18
18
  <div class="container"></div>
19
19
  <img src="/logo.png" alt="Logo">
20
- <input type="text" value="<%= @value %>">
20
+ <input type="text" value="<%= @value %>" autocomplete="off">
21
21
  ```
22
22
 
23
23
  ### 🚫 Bad
@@ -27,7 +27,7 @@ Extra whitespace around the `=` in HTML attribute assignments is unnecessary, in
27
27
 
28
28
  <img src= "/logo.png" alt="Logo">
29
29
 
30
- <input type = "text">
30
+ <input type = "text" autocomplete="off">
31
31
  ```
32
32
 
33
33
  ## References
@@ -23,7 +23,7 @@ Additionally, always quoting is the common convention in most HTML formatters, l
23
23
  ```html
24
24
  <div id="hello"></div>
25
25
 
26
- <input type="text">
26
+ <input type="text" autocomplete="off">
27
27
 
28
28
  <a href="/profile">Profile</a>
29
29
  ```
@@ -33,9 +33,9 @@ Additionally, always quoting is the common convention in most HTML formatters, l
33
33
  ```html
34
34
  <div id=hello></div>
35
35
 
36
- <input type=text>
36
+ <input type=text autocomplete="off">
37
37
 
38
- <a href=/profile></a>
38
+ <a href=profile></a>
39
39
  ```
40
40
 
41
41
  ## References
@@ -19,7 +19,7 @@ Elements that support the native `disabled` attribute include: `button`, `fields
19
19
  ```erb
20
20
  <!-- Use only the native disabled attribute -->
21
21
  <button disabled>Submit</button>
22
- <input type="text" disabled>
22
+ <input type="text" autocomplete="off" disabled>
23
23
 
24
24
  <!-- Use only aria-disabled for custom elements -->
25
25
  <div role="button" aria-disabled="true">Custom Button</div>
@@ -34,7 +34,7 @@ Elements that support the native `disabled` attribute include: `button`, `fields
34
34
  <!-- Both disabled and aria-disabled -->
35
35
  <button disabled aria-disabled="true">Submit</button>
36
36
 
37
- <input type="text" disabled aria-disabled="true">
37
+ <input type="text" autocomplete="off" disabled aria-disabled="true">
38
38
 
39
39
  <select disabled aria-disabled="true">
40
40
  <option>Option 1</option>
@@ -0,0 +1,99 @@
1
+ # Linter Rule: Require content elements inside `<body>`
2
+
3
+ **Rule:** `html-body-only-elements`
4
+
5
+ ## Description
6
+
7
+ Enforce that specific HTML elements are only placed within the `<body>` tag.
8
+
9
+ ## Rationale
10
+
11
+ According to the HTML specification, certain elements are meant to contain content and should only appear within the `<body>` section of an HTML document. Placing content-bearing or interactive elements in the `<head>` section or outside the HTML structure can lead to:
12
+
13
+ - Unpredictable browser rendering behavior
14
+ - Accessibility issues for screen readers and assistive technologies
15
+ - SEO problems as search engines may not properly index misplaced content
16
+ - Validation errors and non-compliant HTML
17
+
18
+ This rule enforces proper document structure by ensuring semantic and content elements are correctly placed within the `<body>` element.
19
+
20
+ ## Examples
21
+
22
+ ### ✅ Good
23
+
24
+ ```erb
25
+ <html>
26
+ <head>
27
+ <title>Page Title</title>
28
+ <meta charset="utf-8">
29
+ </head>
30
+
31
+ <body>
32
+ <header>
33
+ <h1>Welcome</h1>
34
+ <nav>
35
+ <ul>
36
+ <li>Home</li>
37
+ </ul>
38
+ </nav>
39
+ </header>
40
+
41
+ <main>
42
+ <article>
43
+ <section>
44
+ <p>This is valid content.</p>
45
+ <table>
46
+ <tr><td>Data</td></tr>
47
+ </table>
48
+ </section>
49
+ </article>
50
+ <aside>
51
+ <form>
52
+ <input type="text" autocomplete="on">
53
+ </form>
54
+ </aside>
55
+ </main>
56
+
57
+ <footer>
58
+ <h2>Footer</h2>
59
+ </footer>
60
+ </body>
61
+ </html>
62
+ ```
63
+
64
+ ### 🚫 Bad
65
+
66
+ ```erb
67
+ <html>
68
+ <head>
69
+ <title>Page Title</title>
70
+ <h1>Welcome</h1>
71
+
72
+ <p>This should not be here.</p>
73
+
74
+ </head>
75
+
76
+ <body>
77
+ <main>Valid content</main>
78
+ </body>
79
+ </html>
80
+ ```
81
+
82
+ ```erb
83
+ <html>
84
+ <head>
85
+ <nav>Navigation</nav>
86
+
87
+ <form>Form</form>
88
+
89
+ </head>
90
+
91
+ <body>
92
+ </body>
93
+ </html>
94
+ ```
95
+
96
+ ## References
97
+
98
+ - [HTML Living Standard - The `body` element](https://html.spec.whatwg.org/multipage/sections.html#the-body-element)
99
+ - [MDN: HTML `document` structure](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure)