@herb-tools/linter 0.7.4 → 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 (395) hide show
  1. package/README.md +253 -13
  2. package/dist/herb-lint.js +26087 -3414
  3. package/dist/herb-lint.js.map +1 -1
  4. package/dist/index.cjs +5783 -1568
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.js +5749 -1569
  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 +42 -35
  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 +109 -43
  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 +48 -0
  42. package/dist/src/rules/erb-comment-syntax.js.map +1 -0
  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 +70 -20
  60. package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +1 -1
  61. package/dist/src/rules/erb-right-trim.js +45 -0
  62. package/dist/src/rules/erb-right-trim.js.map +1 -0
  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 +20 -2
  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} +46 -14
  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 +14 -0
  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 +14 -0
  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 +20 -2
  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 +14 -0
  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 +14 -0
  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 +20 -2
  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 +19 -3
  285. package/docs/rules/erb-comment-syntax.md +44 -0
  286. package/docs/rules/erb-no-case-node-children.md +50 -0
  287. package/docs/rules/erb-no-extra-newline.md +74 -0
  288. package/docs/rules/erb-no-extra-whitespace-inside-tags.md +39 -0
  289. package/docs/rules/{erb-requires-trailing-newline.md → erb-require-trailing-newline.md} +1 -1
  290. package/docs/rules/erb-right-trim.md +52 -0
  291. package/docs/rules/herb-disable-comment-malformed.md +45 -0
  292. package/docs/rules/herb-disable-comment-missing-rules.md +60 -0
  293. package/docs/rules/herb-disable-comment-no-duplicate-rules.md +49 -0
  294. package/docs/rules/herb-disable-comment-no-redundant-all.md +53 -0
  295. package/docs/rules/herb-disable-comment-unnecessary.md +44 -0
  296. package/docs/rules/herb-disable-comment-valid-rule-name.md +41 -0
  297. package/docs/rules/html-aria-attribute-must-be-valid.md +2 -5
  298. package/docs/rules/html-aria-label-is-well-formatted.md +1 -1
  299. package/docs/rules/html-attribute-double-quotes.md +2 -2
  300. package/docs/rules/html-attribute-equals-spacing.md +2 -2
  301. package/docs/rules/html-attribute-values-require-quotes.md +3 -3
  302. package/docs/rules/html-avoid-both-disabled-and-aria-disabled.md +2 -2
  303. package/docs/rules/html-body-only-elements.md +99 -0
  304. package/docs/rules/html-boolean-attributes-no-value.md +2 -2
  305. package/docs/rules/html-head-only-elements.md +81 -0
  306. package/docs/rules/html-input-require-autocomplete.md +64 -0
  307. package/docs/rules/html-no-aria-hidden-on-focusable.md +2 -2
  308. package/docs/rules/html-no-duplicate-attributes.md +2 -2
  309. package/docs/rules/html-no-duplicate-meta-names.md +64 -0
  310. package/docs/rules/html-no-empty-attributes.md +3 -3
  311. package/docs/rules/html-no-empty-headings.md +4 -26
  312. package/docs/rules/html-no-positive-tab-index.md +1 -2
  313. package/docs/rules/html-no-self-closing.md +17 -2
  314. package/docs/rules/html-no-space-in-tag.md +66 -0
  315. package/docs/rules/html-no-title-attribute.md +2 -2
  316. package/docs/rules/html-no-underscores-in-attribute-names.md +2 -2
  317. package/docs/rules/html-tag-name-lowercase.md +2 -2
  318. package/package.json +13 -5
  319. package/src/cli/argument-parser.ts +50 -39
  320. package/src/cli/file-processor.ts +159 -28
  321. package/src/cli/formatters/detailed-formatter.ts +21 -3
  322. package/src/cli/formatters/github-actions-formatter.ts +17 -1
  323. package/src/cli/formatters/json-formatter.ts +9 -0
  324. package/src/cli/formatters/simple-formatter.ts +24 -8
  325. package/src/cli/output-manager.ts +23 -3
  326. package/src/cli/summary-reporter.ts +40 -3
  327. package/src/cli.ts +137 -52
  328. package/src/custom-rule-loader.ts +189 -0
  329. package/src/herb-disable-comment-utils.ts +175 -0
  330. package/src/index.ts +2 -0
  331. package/src/linter.ts +501 -36
  332. package/src/loader.ts +30 -0
  333. package/src/rules/erb-comment-syntax.ts +73 -0
  334. package/src/rules/erb-no-case-node-children.ts +68 -0
  335. package/src/rules/erb-no-empty-tags.ts +9 -3
  336. package/src/rules/erb-no-extra-newline.ts +91 -0
  337. package/src/rules/erb-no-extra-whitespace-inside-tags.ts +147 -0
  338. package/src/rules/erb-no-output-control-flow.ts +9 -3
  339. package/src/rules/erb-no-silent-tag-in-attribute-name.ts +9 -3
  340. package/src/rules/erb-prefer-image-tag-helper.ts +9 -3
  341. package/src/rules/erb-require-trailing-newline.ts +47 -0
  342. package/src/rules/erb-require-whitespace-inside-tags.ts +96 -26
  343. package/src/rules/erb-right-trim.ts +67 -0
  344. package/src/rules/herb-disable-comment-base.ts +76 -0
  345. package/src/rules/herb-disable-comment-malformed.ts +66 -0
  346. package/src/rules/herb-disable-comment-missing-rules.ts +41 -0
  347. package/src/rules/herb-disable-comment-no-duplicate-rules.ts +46 -0
  348. package/src/rules/herb-disable-comment-no-redundant-all.ts +40 -0
  349. package/src/rules/herb-disable-comment-unnecessary.ts +103 -0
  350. package/src/rules/herb-disable-comment-valid-rule-name.ts +62 -0
  351. package/src/rules/html-anchor-require-href.ts +9 -3
  352. package/src/rules/html-aria-attribute-must-be-valid.ts +9 -3
  353. package/src/rules/html-aria-label-is-well-formatted.ts +9 -5
  354. package/src/rules/html-aria-level-must-be-valid.ts +9 -2
  355. package/src/rules/html-aria-role-heading-requires-level.ts +9 -3
  356. package/src/rules/html-aria-role-must-be-valid.ts +9 -3
  357. package/src/rules/html-attribute-double-quotes.ts +42 -8
  358. package/src/rules/html-attribute-equals-spacing.ts +31 -7
  359. package/src/rules/html-attribute-values-require-quotes.ts +56 -10
  360. package/src/rules/html-avoid-both-disabled-and-aria-disabled.ts +9 -3
  361. package/src/rules/html-body-only-elements.ts +60 -0
  362. package/src/rules/html-boolean-attributes-no-value.ts +31 -6
  363. package/src/rules/html-head-only-elements.ts +65 -0
  364. package/src/rules/html-iframe-has-title.ts +9 -4
  365. package/src/rules/html-img-require-alt.ts +10 -4
  366. package/src/rules/html-input-require-autocomplete.ts +85 -0
  367. package/src/rules/html-navigation-has-label.ts +9 -3
  368. package/src/rules/html-no-aria-hidden-on-focusable.ts +9 -3
  369. package/src/rules/html-no-block-inside-inline.ts +9 -3
  370. package/src/rules/html-no-duplicate-attributes.ts +9 -3
  371. package/src/rules/html-no-duplicate-ids.ts +11 -7
  372. package/src/rules/html-no-duplicate-meta-names.ts +188 -0
  373. package/src/rules/html-no-empty-attributes.ts +58 -10
  374. package/src/rules/html-no-empty-headings.ts +10 -8
  375. package/src/rules/html-no-nested-links.ts +10 -4
  376. package/src/rules/html-no-positive-tab-index.ts +9 -3
  377. package/src/rules/html-no-self-closing.ts +69 -9
  378. package/src/rules/html-no-space-in-tag.ts +221 -0
  379. package/src/rules/html-no-title-attribute.ts +9 -3
  380. package/src/rules/html-no-underscores-in-attribute-names.ts +12 -4
  381. package/src/rules/html-tag-name-lowercase.ts +41 -10
  382. package/src/rules/index.ts +24 -2
  383. package/src/rules/parser-no-errors.ts +8 -1
  384. package/src/rules/rule-utils.ts +250 -44
  385. package/src/rules/svg-tag-name-capitalization.ts +39 -6
  386. package/src/{default-rules.ts → rules.ts} +53 -13
  387. package/src/types.ts +133 -15
  388. package/dist/src/default-rules.js.map +0 -1
  389. package/dist/src/rules/erb-requires-trailing-newline.js +0 -22
  390. package/dist/src/rules/erb-requires-trailing-newline.js.map +0 -1
  391. package/dist/types/default-rules.d.ts +0 -2
  392. package/dist/types/rules/erb-requires-trailing-newline.d.ts +0 -6
  393. package/dist/types/src/default-rules.d.ts +0 -2
  394. package/dist/types/src/rules/erb-requires-trailing-newline.d.ts +0 -6
  395. package/src/rules/erb-requires-trailing-newline.ts +0 -29
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Utilities for parsing herb:disable comments
3
+ */
4
+ /**
5
+ * Prefix for herb:disable comments
6
+ */
7
+ const HERB_DISABLE_PREFIX = "herb:disable";
8
+ /**
9
+ * Parse a herb:disable comment from ERB comment content.
10
+ * Use this when you have the content inside <%# ... %> (e.g., from ERBContentNode.content.value)
11
+ *
12
+ * @param content - The content string (without <%# %> delimiters)
13
+ * @returns Parsed comment data or null if not a valid herb:disable comment
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const result = parseHerbDisableContent("herb:disable rule1, rule2")
18
+ * // { match: "herb:disable rule1, rule2", ruleNames: ["rule1", "rule2"], rulesString: "rule1, rule2" }
19
+ * ```
20
+ */
21
+ export function parseHerbDisableContent(content) {
22
+ const trimmed = content.trim();
23
+ if (!trimmed.startsWith(HERB_DISABLE_PREFIX))
24
+ return null;
25
+ const afterPrefix = trimmed.substring(HERB_DISABLE_PREFIX.length).trimStart();
26
+ if (afterPrefix.length === 0)
27
+ return null;
28
+ const rulesString = afterPrefix.trimEnd();
29
+ const ruleNames = rulesString.split(',').map(name => name.trim());
30
+ if (ruleNames.some(name => name.length === 0))
31
+ return null;
32
+ if (ruleNames.length === 0)
33
+ return null;
34
+ const herbDisablePrefix = content.indexOf(HERB_DISABLE_PREFIX);
35
+ const searchStart = herbDisablePrefix + HERB_DISABLE_PREFIX.length;
36
+ const rulesStringOffset = content.indexOf(rulesString, searchStart);
37
+ const ruleNameDetails = [];
38
+ let currentOffset = 0;
39
+ for (const ruleName of ruleNames) {
40
+ const ruleOffset = rulesString.indexOf(ruleName, currentOffset);
41
+ ruleNameDetails.push({
42
+ name: ruleName,
43
+ offset: rulesStringOffset + ruleOffset,
44
+ length: ruleName.length
45
+ });
46
+ currentOffset = ruleOffset + ruleName.length;
47
+ }
48
+ return {
49
+ match: trimmed,
50
+ ruleNames,
51
+ ruleNameDetails,
52
+ rulesString
53
+ };
54
+ }
55
+ /**
56
+ * Parse a herb:disable comment from a full source line.
57
+ * Use this when you have a complete line that may contain <%# herb:disable ... %>
58
+ *
59
+ * @param line - The source line that may contain a herb:disable comment
60
+ * @returns Parsed comment data or null if not a valid herb:disable comment
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const result = parseHerbDisableLine("<div>test</div> <%# herb:disable rule1, rule2 %>")
65
+ * // { match: "<%# herb:disable rule1, rule2 %>", ruleNames: ["rule1", "rule2"], rulesString: "rule1, rule2" }
66
+ * ```
67
+ */
68
+ export function parseHerbDisableLine(line) {
69
+ const startTag = "<%#";
70
+ const endTag = "%>";
71
+ const startIndex = line.indexOf(startTag);
72
+ if (startIndex === -1)
73
+ return null;
74
+ const endIndex = line.indexOf(endTag, startIndex);
75
+ if (endIndex === -1)
76
+ return null;
77
+ const content = line.substring(startIndex + startTag.length, endIndex).trim();
78
+ if (!content.startsWith(HERB_DISABLE_PREFIX))
79
+ return null;
80
+ const afterPrefix = content.substring(HERB_DISABLE_PREFIX.length).trimStart();
81
+ if (afterPrefix.length === 0)
82
+ return null;
83
+ const rulesString = afterPrefix.trimEnd();
84
+ const ruleNames = rulesString.split(',').map(name => name.trim());
85
+ if (ruleNames.some(name => name.length === 0))
86
+ return null;
87
+ if (ruleNames.length === 0)
88
+ return null;
89
+ const herbDisablePrefix = line.indexOf(HERB_DISABLE_PREFIX);
90
+ const searchStart = herbDisablePrefix + HERB_DISABLE_PREFIX.length;
91
+ const rulesStringOffset = line.indexOf(rulesString, searchStart);
92
+ const ruleNameDetails = [];
93
+ let currentOffset = 0;
94
+ for (const ruleName of ruleNames) {
95
+ const ruleOffset = rulesString.indexOf(ruleName, currentOffset);
96
+ ruleNameDetails.push({
97
+ name: ruleName,
98
+ offset: rulesStringOffset + ruleOffset,
99
+ length: ruleName.length
100
+ });
101
+ currentOffset = ruleOffset + ruleName.length;
102
+ }
103
+ const fullMatch = line.substring(startIndex, endIndex + endTag.length);
104
+ return {
105
+ match: fullMatch,
106
+ ruleNames,
107
+ ruleNameDetails,
108
+ rulesString
109
+ };
110
+ }
111
+ /**
112
+ * Check if an ERB comment content contains a herb:disable directive.
113
+ *
114
+ * @param content - The content string (without <%# %> delimiters)
115
+ * @returns true if the content contains a herb:disable directive
116
+ */
117
+ export function isHerbDisableContent(content) {
118
+ return parseHerbDisableContent(content) !== null;
119
+ }
120
+ /**
121
+ * Check if a source line contains a herb:disable comment.
122
+ *
123
+ * @param line - The source line
124
+ * @returns true if the line contains a herb:disable comment
125
+ */
126
+ export function isHerbDisableLine(line) {
127
+ return parseHerbDisableLine(line) !== null;
128
+ }
129
+ //# sourceMappingURL=herb-disable-comment-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"herb-disable-comment-utils.js","sourceRoot":"","sources":["../../src/herb-disable-comment-utils.ts"],"names":[],"mappings":"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"}
package/dist/src/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./linter.js";
2
2
  export * from "./rules/index.js";
3
3
  export * from "./types.js";
4
+ export { rules } from "./rules.js";
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA"}
@@ -1,24 +1,104 @@
1
- import { defaultRules } from "./default-rules.js";
1
+ import { Location } from "@herb-tools/core";
2
+ import { IdentityPrinter } from "@herb-tools/printer";
3
+ import { minimatch } from "minimatch";
4
+ import { rules } from "./rules.js";
5
+ import { findNodeByLocation } from "./rules/rule-utils.js";
6
+ import { parseHerbDisableLine } from "./herb-disable-comment-utils.js";
7
+ import { ParserNoErrorsRule } from "./rules/parser-no-errors.js";
8
+ import { DEFAULT_RULE_CONFIG } from "./types.js";
2
9
  export class Linter {
3
10
  rules;
11
+ allAvailableRules;
4
12
  herb;
5
13
  offenses;
14
+ config;
15
+ /**
16
+ * Creates a new Linter instance with automatic rule filtering based on config.
17
+ *
18
+ * @param herb - The Herb backend instance for parsing and lexing
19
+ * @param config - Optional full Config instance for rule filtering, severity overrides, and path-based filtering
20
+ * @param customRules - Optional array of custom rules to include alongside built-in rules
21
+ * @returns A configured Linter instance
22
+ */
23
+ static from(herb, config, customRules) {
24
+ const allRules = customRules ? [...rules, ...customRules] : rules;
25
+ const filteredRules = config?.linter?.rules
26
+ ? Linter.filterRulesByConfig(allRules, config.linter.rules)
27
+ : undefined;
28
+ return new Linter(herb, filteredRules, config, allRules);
29
+ }
6
30
  /**
7
31
  * Creates a new Linter instance.
32
+ *
33
+ * For most use cases, prefer `Linter.from()` which handles config-based filtering.
34
+ * Use this constructor directly when you need explicit control over rules.
35
+ *
8
36
  * @param herb - The Herb backend instance for parsing and lexing
9
37
  * @param rules - Array of rule classes (Parser/AST or Lexer) to use. If not provided, uses default rules.
38
+ * @param config - Optional full Config instance for severity overrides and path-based rule filtering
39
+ * @param allAvailableRules - Optional array of ALL available rules (including disabled) for herb:disable validation
10
40
  */
11
- constructor(herb, rules) {
41
+ constructor(herb, rules, config, allAvailableRules) {
12
42
  this.herb = herb;
43
+ this.config = config;
13
44
  this.rules = rules !== undefined ? rules : this.getDefaultRules();
45
+ this.allAvailableRules = allAvailableRules !== undefined ? allAvailableRules : this.rules;
14
46
  this.offenses = [];
15
47
  }
48
+ /**
49
+ * Filters rules based on default config and optional user config overrides.
50
+ *
51
+ * Priority:
52
+ * 1. User config override (if rule config exists in userRulesConfig)
53
+ * 2. Default config from rule's defaultConfig getter
54
+ *
55
+ * @param allRules - All available rule classes to filter from
56
+ * @param userRulesConfig - Optional user configuration for rules
57
+ * @returns Filtered array of rule classes that should be enabled
58
+ */
59
+ static filterRulesByConfig(allRules, userRulesConfig) {
60
+ return allRules.filter(ruleClass => {
61
+ const instance = new ruleClass();
62
+ const ruleName = instance.name;
63
+ const defaultEnabled = instance.defaultConfig?.enabled ?? DEFAULT_RULE_CONFIG.enabled;
64
+ const userRuleConfig = userRulesConfig?.[ruleName];
65
+ if (userRuleConfig !== undefined) {
66
+ return userRuleConfig.enabled !== false;
67
+ }
68
+ return defaultEnabled;
69
+ });
70
+ }
16
71
  /**
17
72
  * Returns the default set of rule classes used by the linter.
18
- * @returns Array of rule classes
73
+ * These are the rules enabled when no custom rules are provided.
74
+ * Filters all available rules to only include those enabled by default.
75
+ * @returns Array of default rule classes
19
76
  */
20
77
  getDefaultRules() {
21
- return defaultRules;
78
+ return Linter.filterRulesByConfig(rules);
79
+ }
80
+ /**
81
+ * Returns all available rule classes that can be referenced in herb:disable comments.
82
+ * This includes all rules that exist, regardless of whether they're currently enabled.
83
+ * Includes both built-in rules and any loaded custom rules.
84
+ * @returns Array of all available rule classes
85
+ */
86
+ getAvailableRules() {
87
+ return this.allAvailableRules;
88
+ }
89
+ /**
90
+ * Meta-linting rules for herb:disable comments cannot be disabled
91
+ * This ensures that invalid herb:disable comments are always caught
92
+ */
93
+ get nonExcludableRules() {
94
+ return [
95
+ "herb-disable-comment-valid-rule-name",
96
+ "herb-disable-comment-no-redundant-all",
97
+ "herb-disable-comment-no-duplicate-rules",
98
+ "herb-disable-comment-malformed",
99
+ "herb-disable-comment-missing-rules",
100
+ "herb-disable-comment-unnecessary"
101
+ ];
22
102
  }
23
103
  getRuleCount() {
24
104
  return this.rules.length;
@@ -35,6 +115,97 @@ export class Linter {
35
115
  isSourceRule(rule) {
36
116
  return rule.constructor.type === "source";
37
117
  }
118
+ /**
119
+ * Execute a single rule and return its unbound offenses.
120
+ * Handles rule type checking (Lexer/Parser/Source) and isEnabled checks.
121
+ */
122
+ executeRule(rule, parseResult, lexResult, source, context) {
123
+ if (this.config && context?.fileName) {
124
+ if (!this.config.isRuleEnabledForPath(rule.name, context.fileName)) {
125
+ return [];
126
+ }
127
+ }
128
+ if (context?.fileName && !this.config?.linter?.rules?.[rule.name]?.exclude) {
129
+ const defaultExclude = rule.defaultConfig?.exclude ?? DEFAULT_RULE_CONFIG.exclude;
130
+ if (defaultExclude && defaultExclude.length > 0) {
131
+ const isExcluded = defaultExclude.some((pattern) => minimatch(context.fileName, pattern));
132
+ if (isExcluded) {
133
+ return [];
134
+ }
135
+ }
136
+ }
137
+ let isEnabled = true;
138
+ let ruleOffenses;
139
+ if (this.isLexerRule(rule)) {
140
+ if (rule.isEnabled) {
141
+ isEnabled = rule.isEnabled(lexResult, context);
142
+ }
143
+ if (isEnabled) {
144
+ ruleOffenses = rule.check(lexResult, context);
145
+ }
146
+ else {
147
+ ruleOffenses = [];
148
+ }
149
+ }
150
+ else if (this.isSourceRule(rule)) {
151
+ if (rule.isEnabled) {
152
+ isEnabled = rule.isEnabled(source, context);
153
+ }
154
+ if (isEnabled) {
155
+ ruleOffenses = rule.check(source, context);
156
+ }
157
+ else {
158
+ ruleOffenses = [];
159
+ }
160
+ }
161
+ else {
162
+ if (rule.isEnabled) {
163
+ isEnabled = rule.isEnabled(parseResult, context);
164
+ }
165
+ if (isEnabled) {
166
+ ruleOffenses = rule.check(parseResult, context);
167
+ }
168
+ else {
169
+ ruleOffenses = [];
170
+ }
171
+ }
172
+ return ruleOffenses;
173
+ }
174
+ filterOffenses(ruleOffenses, ruleName, ignoredOffensesByLine, herbDisableCache, ignoreDisableComments) {
175
+ const kept = [];
176
+ const ignored = [];
177
+ const wouldBeIgnored = [];
178
+ if (this.nonExcludableRules.includes(ruleName)) {
179
+ return { kept: ruleOffenses, ignored: [], wouldBeIgnored: [] };
180
+ }
181
+ if (ignoreDisableComments) {
182
+ for (const offense of ruleOffenses) {
183
+ const line = offense.location.start.line;
184
+ const disabledRules = herbDisableCache?.get(line) || [];
185
+ if (disabledRules.includes(ruleName) || disabledRules.includes("all")) {
186
+ wouldBeIgnored.push(offense);
187
+ }
188
+ }
189
+ return { kept: ruleOffenses, ignored: [], wouldBeIgnored };
190
+ }
191
+ for (const offense of ruleOffenses) {
192
+ const line = offense.location.start.line;
193
+ const disabledRules = herbDisableCache?.get(line) || [];
194
+ if (disabledRules.includes(ruleName) || disabledRules.includes("all")) {
195
+ ignored.push(offense);
196
+ if (ignoredOffensesByLine) {
197
+ if (!ignoredOffensesByLine.has(line)) {
198
+ ignoredOffensesByLine.set(line, new Set());
199
+ }
200
+ const usedRuleName = disabledRules.includes(ruleName) ? ruleName : "all";
201
+ ignoredOffensesByLine.get(line).add(usedRuleName);
202
+ }
203
+ continue;
204
+ }
205
+ kept.push(offense);
206
+ }
207
+ return { kept, ignored, wouldBeIgnored: [] };
208
+ }
38
209
  /**
39
210
  * Lint source code using Parser/AST, Lexer, and Source rules.
40
211
  * @param source - The source code to lint
@@ -42,53 +213,217 @@ export class Linter {
42
213
  */
43
214
  lint(source, context) {
44
215
  this.offenses = [];
216
+ let ignoredCount = 0;
217
+ let wouldBeIgnoredCount = 0;
45
218
  const parseResult = this.herb.parse(source, { track_whitespace: true });
46
219
  const lexResult = this.herb.lex(source);
47
- for (const RuleClass of this.rules) {
220
+ const hasParserErrors = parseResult.recursiveErrors().length > 0;
221
+ const sourceLines = source.split("\n");
222
+ const ignoredOffensesByLine = new Map();
223
+ const herbDisableCache = new Map();
224
+ if (hasParserErrors) {
225
+ const hasParserRule = this.rules.find(RuleClass => (new RuleClass()).name === "parser-no-errors");
226
+ if (hasParserRule) {
227
+ const rule = new ParserNoErrorsRule();
228
+ const offenses = rule.check(parseResult);
229
+ this.offenses.push(...offenses);
230
+ }
231
+ return {
232
+ offenses: this.offenses,
233
+ errors: this.offenses.filter(o => o.severity === "error").length,
234
+ warnings: this.offenses.filter(o => o.severity === "warning").length,
235
+ info: this.offenses.filter(o => o.severity === "info").length,
236
+ hints: this.offenses.filter(o => o.severity === "hint").length,
237
+ ignored: 0
238
+ };
239
+ }
240
+ for (let i = 0; i < sourceLines.length; i++) {
241
+ const line = sourceLines[i];
242
+ if (line.includes("herb:disable")) {
243
+ const herbDisable = parseHerbDisableLine(line);
244
+ herbDisableCache.set(i + 1, herbDisable?.ruleNames || []);
245
+ }
246
+ }
247
+ context = {
248
+ ...context,
249
+ validRuleNames: this.getAvailableRules().map(RuleClass => new RuleClass().name),
250
+ ignoredOffensesByLine
251
+ };
252
+ const regularRules = this.rules.filter(RuleClass => {
48
253
  const rule = new RuleClass();
49
- let isEnabled = true;
50
- let ruleOffenses;
51
- if (this.isLexerRule(rule)) {
52
- if (rule.isEnabled) {
53
- isEnabled = rule.isEnabled(lexResult, context);
54
- }
55
- if (isEnabled) {
56
- ruleOffenses = rule.check(lexResult, context);
254
+ return rule.name !== "herb-disable-comment-unnecessary";
255
+ });
256
+ for (const RuleClass of regularRules) {
257
+ const rule = new RuleClass();
258
+ const unboundOffenses = this.executeRule(rule, parseResult, lexResult, source, context);
259
+ const boundOffenses = this.bindSeverity(unboundOffenses, rule.name);
260
+ const { kept, ignored, wouldBeIgnored } = this.filterOffenses(boundOffenses, rule.name, ignoredOffensesByLine, herbDisableCache, context?.ignoreDisableComments);
261
+ ignoredCount += ignored.length;
262
+ wouldBeIgnoredCount += wouldBeIgnored.length;
263
+ this.offenses.push(...kept);
264
+ }
265
+ const unnecessaryRuleClass = this.rules.find(RuleClass => {
266
+ const rule = new RuleClass();
267
+ return rule.name === "herb-disable-comment-unnecessary";
268
+ });
269
+ if (unnecessaryRuleClass) {
270
+ const unnecessaryRule = new unnecessaryRuleClass();
271
+ const unboundOffenses = unnecessaryRule.check(parseResult, context);
272
+ const boundOffenses = this.bindSeverity(unboundOffenses, unnecessaryRule.name);
273
+ this.offenses.push(...boundOffenses);
274
+ }
275
+ const finalOffenses = this.offenses;
276
+ const errors = finalOffenses.filter(offense => offense.severity === "error").length;
277
+ const warnings = finalOffenses.filter(offense => offense.severity === "warning").length;
278
+ const info = finalOffenses.filter(offense => offense.severity === "info").length;
279
+ const hints = finalOffenses.filter(offense => offense.severity === "hint").length;
280
+ const result = {
281
+ offenses: finalOffenses,
282
+ errors,
283
+ warnings,
284
+ info,
285
+ hints,
286
+ ignored: ignoredCount
287
+ };
288
+ if (wouldBeIgnoredCount > 0) {
289
+ result.wouldBeIgnored = wouldBeIgnoredCount;
290
+ }
291
+ return result;
292
+ }
293
+ /**
294
+ * Bind severity to unbound offenses based on rule's defaultConfig and user config overrides.
295
+ *
296
+ * Priority:
297
+ * 1. User config severity override (if specified in config)
298
+ * 2. Rule's default severity (from defaultConfig.severity)
299
+ *
300
+ * @param unboundOffenses - Array of offenses without severity
301
+ * @param ruleName - Name of the rule that produced the offenses
302
+ * @returns Array of offenses with severity bound
303
+ */
304
+ bindSeverity(unboundOffenses, ruleName) {
305
+ const RuleClass = this.rules.find(rule => {
306
+ const instance = new rule();
307
+ return instance.name === ruleName;
308
+ });
309
+ if (!RuleClass) {
310
+ return unboundOffenses.map(offense => ({
311
+ ...offense,
312
+ severity: "error"
313
+ }));
314
+ }
315
+ const ruleInstance = new RuleClass();
316
+ const defaultSeverity = ruleInstance.defaultConfig?.severity ?? DEFAULT_RULE_CONFIG.severity;
317
+ const userRuleConfig = this.config?.linter?.rules?.[ruleName];
318
+ const severity = userRuleConfig?.severity ?? defaultSeverity;
319
+ return unboundOffenses.map(offense => ({
320
+ ...offense,
321
+ severity
322
+ }));
323
+ }
324
+ /**
325
+ * Automatically fix offenses in the source code.
326
+ * Uses AST mutation for parser rules and token mutation for lexer rules.
327
+ * @param source - The source code to fix
328
+ * @param context - Optional context for linting (e.g., fileName)
329
+ * @param offensesToFix - Optional array of specific offenses to fix. If not provided, all fixable offenses will be fixed.
330
+ * @returns AutofixResult containing the corrected source and lists of fixed/unfixed offenses
331
+ */
332
+ autofix(source, context, offensesToFix) {
333
+ const lintResult = offensesToFix ? { offenses: offensesToFix } : this.lint(source, context);
334
+ const parserOffenses = [];
335
+ const lexerOffenses = [];
336
+ const sourceOffenses = [];
337
+ for (const offense of lintResult.offenses) {
338
+ const RuleClass = this.rules.find(rule => {
339
+ const instance = new rule();
340
+ return instance.name === offense.rule;
341
+ });
342
+ if (!RuleClass)
343
+ continue;
344
+ if (RuleClass.type === "lexer") {
345
+ lexerOffenses.push(offense);
346
+ }
347
+ else if (RuleClass.type === "source") {
348
+ sourceOffenses.push(offense);
349
+ }
350
+ else {
351
+ parserOffenses.push(offense);
352
+ }
353
+ }
354
+ let currentSource = source;
355
+ const fixed = [];
356
+ const unfixed = [];
357
+ if (parserOffenses.length > 0) {
358
+ const parseResult = this.herb.parse(currentSource, { track_whitespace: true });
359
+ for (const offense of parserOffenses) {
360
+ const RuleClass = this.rules.find(rule => new rule().name === offense.rule);
361
+ if (!RuleClass) {
362
+ unfixed.push(offense);
363
+ continue;
57
364
  }
58
- else {
59
- ruleOffenses = [];
365
+ const rule = new RuleClass();
366
+ if (!rule.autofix) {
367
+ unfixed.push(offense);
368
+ continue;
60
369
  }
61
- }
62
- else if (this.isSourceRule(rule)) {
63
- if (rule.isEnabled) {
64
- isEnabled = rule.isEnabled(source, context);
370
+ if (offense.autofixContext) {
371
+ const originalNodeType = offense.autofixContext.node.type;
372
+ const location = offense.autofixContext.node.location ? Location.from(offense.autofixContext.node.location) : offense.location;
373
+ const freshNode = findNodeByLocation(parseResult.value, location, (node) => node.type === originalNodeType);
374
+ if (freshNode) {
375
+ offense.autofixContext.node = freshNode;
376
+ }
377
+ else {
378
+ unfixed.push(offense);
379
+ continue;
380
+ }
65
381
  }
66
- if (isEnabled) {
67
- ruleOffenses = rule.check(source, context);
382
+ const fixedResult = rule.autofix(offense, parseResult, context);
383
+ if (fixedResult) {
384
+ fixed.push(offense);
68
385
  }
69
386
  else {
70
- ruleOffenses = [];
387
+ unfixed.push(offense);
71
388
  }
72
389
  }
73
- else {
74
- if (rule.isEnabled) {
75
- isEnabled = rule.isEnabled(parseResult, context);
390
+ if (fixed.length > 0) {
391
+ const printer = new IdentityPrinter();
392
+ currentSource = printer.print(parseResult.value);
393
+ }
394
+ }
395
+ if (sourceOffenses.length > 0) {
396
+ const sortedSourceOffenses = sourceOffenses.sort((a, b) => {
397
+ if (a.location.start.line !== b.location.start.line) {
398
+ return b.location.start.line - a.location.start.line;
399
+ }
400
+ return b.location.start.column - a.location.start.column;
401
+ });
402
+ for (const offense of sortedSourceOffenses) {
403
+ const RuleClass = this.rules.find(rule => new rule().name === offense.rule);
404
+ if (!RuleClass) {
405
+ unfixed.push(offense);
406
+ continue;
76
407
  }
77
- if (isEnabled) {
78
- ruleOffenses = rule.check(parseResult, context);
408
+ const rule = new RuleClass();
409
+ if (!rule.autofix) {
410
+ unfixed.push(offense);
411
+ continue;
412
+ }
413
+ const correctedSource = rule.autofix(offense, currentSource, context);
414
+ if (correctedSource) {
415
+ currentSource = correctedSource;
416
+ fixed.push(offense);
79
417
  }
80
418
  else {
81
- ruleOffenses = [];
419
+ unfixed.push(offense);
82
420
  }
83
421
  }
84
- this.offenses.push(...ruleOffenses);
85
422
  }
86
- const errors = this.offenses.filter(offense => offense.severity === "error").length;
87
- const warnings = this.offenses.filter(offense => offense.severity === "warning").length;
88
423
  return {
89
- offenses: this.offenses,
90
- errors,
91
- warnings
424
+ source: currentSource,
425
+ fixed,
426
+ unfixed
92
427
  };
93
428
  }
94
429
  }
@@ -1 +1 @@
1
- {"version":3,"file":"linter.js","sourceRoot":"","sources":["../../src/linter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"linter.js","sourceRoot":"","sources":["../../src/linter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export * from "./index.js";
2
+ export { CustomRuleLoader } from "./custom-rule-loader.js";
3
+ import { CustomRuleLoader } from "./custom-rule-loader.js";
4
+ /**
5
+ * Loads custom rules from the filesystem.
6
+ * Only available in Node.js environments.
7
+ */
8
+ export async function loadCustomRules(options) {
9
+ const loader = new CustomRuleLoader(options);
10
+ const { rules: customRules, ruleInfo, duplicateWarnings } = await loader.loadRulesWithInfo();
11
+ return {
12
+ rules: customRules,
13
+ ruleInfo,
14
+ warnings: duplicateWarnings
15
+ };
16
+ }
17
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/loader.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAG1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAG1D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAIrC;IAKC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAA;IAE5F,OAAO;QACL,KAAK,EAAE,WAAW;QAClB,QAAQ;QACR,QAAQ,EAAE,iBAAiB;KAC5B,CAAA;AACH,CAAC"}