@herb-tools/linter 0.4.2 → 0.5.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 (202) hide show
  1. package/README.md +221 -10
  2. package/dist/herb-lint.js +817 -292
  3. package/dist/herb-lint.js.map +1 -1
  4. package/dist/index.cjs +360 -81
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.js +355 -83
  7. package/dist/index.js.map +1 -1
  8. package/dist/package.json +4 -4
  9. package/dist/src/cli/argument-parser.js +28 -18
  10. package/dist/src/cli/argument-parser.js.map +1 -1
  11. package/dist/src/cli/file-processor.js +21 -17
  12. package/dist/src/cli/file-processor.js.map +1 -1
  13. package/dist/src/cli/formatters/detailed-formatter.js +9 -9
  14. package/dist/src/cli/formatters/detailed-formatter.js.map +1 -1
  15. package/dist/src/cli/formatters/github-actions-formatter.js +50 -0
  16. package/dist/src/cli/formatters/github-actions-formatter.js.map +1 -0
  17. package/dist/src/cli/formatters/index.js +2 -0
  18. package/dist/src/cli/formatters/index.js.map +1 -1
  19. package/dist/src/cli/formatters/json-formatter.js +58 -0
  20. package/dist/src/cli/formatters/json-formatter.js.map +1 -0
  21. package/dist/src/cli/formatters/simple-formatter.js +15 -15
  22. package/dist/src/cli/formatters/simple-formatter.js.map +1 -1
  23. package/dist/src/cli/output-manager.js +120 -0
  24. package/dist/src/cli/output-manager.js.map +1 -0
  25. package/dist/src/cli/summary-reporter.js +22 -22
  26. package/dist/src/cli/summary-reporter.js.map +1 -1
  27. package/dist/src/cli.js +41 -26
  28. package/dist/src/cli.js.map +1 -1
  29. package/dist/src/default-rules.js +8 -0
  30. package/dist/src/default-rules.js.map +1 -1
  31. package/dist/src/linter.js +37 -6
  32. package/dist/src/linter.js.map +1 -1
  33. package/dist/src/rules/erb-no-empty-tags.js +5 -4
  34. package/dist/src/rules/erb-no-empty-tags.js.map +1 -1
  35. package/dist/src/rules/erb-no-output-control-flow.js +5 -4
  36. package/dist/src/rules/erb-no-output-control-flow.js.map +1 -1
  37. package/dist/src/rules/erb-prefer-image-tag-helper.js +93 -0
  38. package/dist/src/rules/erb-prefer-image-tag-helper.js.map +1 -0
  39. package/dist/src/rules/erb-require-whitespace-inside-tags.js +5 -4
  40. package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +1 -1
  41. package/dist/src/rules/erb-requires-trailing-newline.js +22 -0
  42. package/dist/src/rules/erb-requires-trailing-newline.js.map +1 -0
  43. package/dist/src/rules/html-anchor-require-href.js +5 -4
  44. package/dist/src/rules/html-anchor-require-href.js.map +1 -1
  45. package/dist/src/rules/html-aria-attribute-must-be-valid.js +5 -4
  46. package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +1 -1
  47. package/dist/src/rules/html-aria-level-must-be-valid.js +27 -0
  48. package/dist/src/rules/html-aria-level-must-be-valid.js.map +1 -0
  49. package/dist/src/rules/html-aria-role-heading-requires-level.js +5 -4
  50. package/dist/src/rules/html-aria-role-heading-requires-level.js.map +1 -1
  51. package/dist/src/rules/html-aria-role-must-be-valid.js +5 -4
  52. package/dist/src/rules/html-aria-role-must-be-valid.js.map +1 -1
  53. package/dist/src/rules/html-attribute-double-quotes.js +5 -4
  54. package/dist/src/rules/html-attribute-double-quotes.js.map +1 -1
  55. package/dist/src/rules/html-attribute-values-require-quotes.js +5 -4
  56. package/dist/src/rules/html-attribute-values-require-quotes.js.map +1 -1
  57. package/dist/src/rules/html-boolean-attributes-no-value.js +5 -4
  58. package/dist/src/rules/html-boolean-attributes-no-value.js.map +1 -1
  59. package/dist/src/rules/html-img-require-alt.js +5 -4
  60. package/dist/src/rules/html-img-require-alt.js.map +1 -1
  61. package/dist/src/rules/html-no-block-inside-inline.js +7 -6
  62. package/dist/src/rules/html-no-block-inside-inline.js.map +1 -1
  63. package/dist/src/rules/html-no-duplicate-attributes.js +5 -4
  64. package/dist/src/rules/html-no-duplicate-attributes.js.map +1 -1
  65. package/dist/src/rules/html-no-duplicate-ids.js +5 -4
  66. package/dist/src/rules/html-no-duplicate-ids.js.map +1 -1
  67. package/dist/src/rules/html-no-empty-headings.js +5 -4
  68. package/dist/src/rules/html-no-empty-headings.js.map +1 -1
  69. package/dist/src/rules/html-no-nested-links.js +5 -4
  70. package/dist/src/rules/html-no-nested-links.js.map +1 -1
  71. package/dist/src/rules/html-tag-name-lowercase.js +5 -4
  72. package/dist/src/rules/html-tag-name-lowercase.js.map +1 -1
  73. package/dist/src/rules/index.js +3 -0
  74. package/dist/src/rules/index.js.map +1 -1
  75. package/dist/src/rules/parser-no-errors.js +18 -0
  76. package/dist/src/rules/parser-no-errors.js.map +1 -0
  77. package/dist/src/rules/rule-utils.js +125 -2
  78. package/dist/src/rules/rule-utils.js.map +1 -1
  79. package/dist/src/rules/svg-tag-name-capitalization.js +5 -4
  80. package/dist/src/rules/svg-tag-name-capitalization.js.map +1 -1
  81. package/dist/src/types.js +15 -1
  82. package/dist/src/types.js.map +1 -1
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/dist/types/cli/argument-parser.d.ts +2 -1
  85. package/dist/types/cli/file-processor.d.ts +6 -5
  86. package/dist/types/cli/formatters/base-formatter.d.ts +2 -2
  87. package/dist/types/cli/formatters/detailed-formatter.d.ts +2 -2
  88. package/dist/types/cli/formatters/github-actions-formatter.d.ts +12 -0
  89. package/dist/types/cli/formatters/index.d.ts +2 -0
  90. package/dist/types/cli/formatters/json-formatter.d.ts +42 -0
  91. package/dist/types/cli/formatters/simple-formatter.d.ts +2 -2
  92. package/dist/types/cli/output-manager.d.ts +31 -0
  93. package/dist/types/cli/summary-reporter.d.ts +3 -3
  94. package/dist/types/cli.d.ts +3 -1
  95. package/dist/types/linter.d.ts +20 -5
  96. package/dist/types/rules/erb-no-empty-tags.d.ts +5 -4
  97. package/dist/types/rules/erb-no-output-control-flow.d.ts +5 -4
  98. package/dist/types/rules/erb-prefer-image-tag-helper.d.ts +7 -0
  99. package/dist/types/rules/erb-require-whitespace-inside-tags.d.ts +5 -4
  100. package/dist/types/rules/erb-requires-trailing-newline.d.ts +6 -0
  101. package/dist/types/rules/html-anchor-require-href.d.ts +5 -4
  102. package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +5 -4
  103. package/dist/types/rules/html-aria-level-must-be-valid.d.ts +7 -0
  104. package/dist/types/rules/html-aria-role-heading-requires-level.d.ts +5 -4
  105. package/dist/types/rules/html-aria-role-must-be-valid.d.ts +5 -4
  106. package/dist/types/rules/html-attribute-double-quotes.d.ts +5 -4
  107. package/dist/types/rules/html-attribute-values-require-quotes.d.ts +5 -4
  108. package/dist/types/rules/html-boolean-attributes-no-value.d.ts +5 -4
  109. package/dist/types/rules/html-img-require-alt.d.ts +5 -4
  110. package/dist/types/rules/html-no-block-inside-inline.d.ts +5 -4
  111. package/dist/types/rules/html-no-duplicate-attributes.d.ts +5 -4
  112. package/dist/types/rules/html-no-duplicate-ids.d.ts +5 -4
  113. package/dist/types/rules/html-no-empty-headings.d.ts +5 -4
  114. package/dist/types/rules/html-no-nested-links.d.ts +5 -4
  115. package/dist/types/rules/html-tag-name-lowercase.d.ts +5 -4
  116. package/dist/types/rules/index.d.ts +3 -0
  117. package/dist/types/rules/parser-no-errors.d.ts +8 -0
  118. package/dist/types/rules/rule-utils.d.ts +73 -4
  119. package/dist/types/rules/svg-tag-name-capitalization.d.ts +5 -4
  120. package/dist/types/src/cli/argument-parser.d.ts +2 -1
  121. package/dist/types/src/cli/file-processor.d.ts +6 -5
  122. package/dist/types/src/cli/formatters/base-formatter.d.ts +2 -2
  123. package/dist/types/src/cli/formatters/detailed-formatter.d.ts +2 -2
  124. package/dist/types/src/cli/formatters/github-actions-formatter.d.ts +12 -0
  125. package/dist/types/src/cli/formatters/index.d.ts +2 -0
  126. package/dist/types/src/cli/formatters/json-formatter.d.ts +42 -0
  127. package/dist/types/src/cli/formatters/simple-formatter.d.ts +2 -2
  128. package/dist/types/src/cli/output-manager.d.ts +31 -0
  129. package/dist/types/src/cli/summary-reporter.d.ts +3 -3
  130. package/dist/types/src/cli.d.ts +3 -1
  131. package/dist/types/src/linter.d.ts +20 -5
  132. package/dist/types/src/rules/erb-no-empty-tags.d.ts +5 -4
  133. package/dist/types/src/rules/erb-no-output-control-flow.d.ts +5 -4
  134. package/dist/types/src/rules/erb-prefer-image-tag-helper.d.ts +7 -0
  135. package/dist/types/src/rules/erb-require-whitespace-inside-tags.d.ts +5 -4
  136. package/dist/types/src/rules/erb-requires-trailing-newline.d.ts +6 -0
  137. package/dist/types/src/rules/html-anchor-require-href.d.ts +5 -4
  138. package/dist/types/src/rules/html-aria-attribute-must-be-valid.d.ts +5 -4
  139. package/dist/types/src/rules/html-aria-level-must-be-valid.d.ts +7 -0
  140. package/dist/types/src/rules/html-aria-role-heading-requires-level.d.ts +5 -4
  141. package/dist/types/src/rules/html-aria-role-must-be-valid.d.ts +5 -4
  142. package/dist/types/src/rules/html-attribute-double-quotes.d.ts +5 -4
  143. package/dist/types/src/rules/html-attribute-values-require-quotes.d.ts +5 -4
  144. package/dist/types/src/rules/html-boolean-attributes-no-value.d.ts +5 -4
  145. package/dist/types/src/rules/html-img-require-alt.d.ts +5 -4
  146. package/dist/types/src/rules/html-no-block-inside-inline.d.ts +5 -4
  147. package/dist/types/src/rules/html-no-duplicate-attributes.d.ts +5 -4
  148. package/dist/types/src/rules/html-no-duplicate-ids.d.ts +5 -4
  149. package/dist/types/src/rules/html-no-empty-headings.d.ts +5 -4
  150. package/dist/types/src/rules/html-no-nested-links.d.ts +5 -4
  151. package/dist/types/src/rules/html-tag-name-lowercase.d.ts +5 -4
  152. package/dist/types/src/rules/index.d.ts +3 -0
  153. package/dist/types/src/rules/parser-no-errors.d.ts +8 -0
  154. package/dist/types/src/rules/rule-utils.d.ts +73 -4
  155. package/dist/types/src/rules/svg-tag-name-capitalization.d.ts +5 -4
  156. package/dist/types/src/types.d.ts +50 -7
  157. package/dist/types/types.d.ts +50 -7
  158. package/docs/rules/README.md +5 -1
  159. package/docs/rules/erb-prefer-image-tag-helper.md +65 -0
  160. package/docs/rules/erb-requires-trailing-newline.md +37 -0
  161. package/docs/rules/html-anchor-require-href.md +1 -1
  162. package/docs/rules/html-aria-level-must-be-valid.md +37 -0
  163. package/docs/rules/parser-no-errors.md +84 -0
  164. package/package.json +4 -4
  165. package/src/cli/argument-parser.ts +33 -19
  166. package/src/cli/file-processor.ts +27 -21
  167. package/src/cli/formatters/base-formatter.ts +2 -2
  168. package/src/cli/formatters/detailed-formatter.ts +9 -9
  169. package/src/cli/formatters/github-actions-formatter.ts +70 -0
  170. package/src/cli/formatters/index.ts +2 -0
  171. package/src/cli/formatters/json-formatter.ts +107 -0
  172. package/src/cli/formatters/simple-formatter.ts +15 -15
  173. package/src/cli/output-manager.ts +143 -0
  174. package/src/cli/summary-reporter.ts +24 -24
  175. package/src/cli.ts +48 -31
  176. package/src/default-rules.ts +8 -0
  177. package/src/linter.ts +42 -8
  178. package/src/rules/erb-no-empty-tags.ts +7 -6
  179. package/src/rules/erb-no-output-control-flow.ts +8 -6
  180. package/src/rules/erb-prefer-image-tag-helper.ts +124 -0
  181. package/src/rules/erb-require-whitespace-inside-tags.ts +7 -6
  182. package/src/rules/erb-requires-trailing-newline.ts +29 -0
  183. package/src/rules/html-anchor-require-href.ts +7 -6
  184. package/src/rules/html-aria-attribute-must-be-valid.ts +7 -7
  185. package/src/rules/html-aria-level-must-be-valid.ts +42 -0
  186. package/src/rules/html-aria-role-heading-requires-level.ts +7 -6
  187. package/src/rules/html-aria-role-must-be-valid.ts +7 -6
  188. package/src/rules/html-attribute-double-quotes.ts +7 -6
  189. package/src/rules/html-attribute-values-require-quotes.ts +7 -6
  190. package/src/rules/html-boolean-attributes-no-value.ts +7 -6
  191. package/src/rules/html-img-require-alt.ts +7 -6
  192. package/src/rules/html-no-block-inside-inline.ts +9 -8
  193. package/src/rules/html-no-duplicate-attributes.ts +7 -6
  194. package/src/rules/html-no-duplicate-ids.ts +7 -7
  195. package/src/rules/html-no-empty-headings.ts +7 -6
  196. package/src/rules/html-no-nested-links.ts +7 -6
  197. package/src/rules/html-tag-name-lowercase.ts +7 -6
  198. package/src/rules/index.ts +3 -0
  199. package/src/rules/parser-no-errors.ts +25 -0
  200. package/src/rules/rule-utils.ts +156 -4
  201. package/src/rules/svg-tag-name-capitalization.ts +7 -6
  202. package/src/types.ts +61 -7
@@ -1,6 +1,7 @@
1
- import type { Node } from "@herb-tools/core";
2
- import type { Rule, LintOffense } from "../types.js";
3
- export declare class ERBNoOutputControlFlowRule implements Rule {
1
+ import type { ParseResult } from "@herb-tools/core";
2
+ import { ParserRule } from "../types.js";
3
+ import type { LintOffense, LintContext } from "../types.js";
4
+ export declare class ERBNoOutputControlFlowRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -0,0 +1,7 @@
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class ERBPreferImageTagHelperRule extends ParserRule {
5
+ name: string;
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
7
+ }
@@ -1,6 +1,7 @@
1
- import type { Node } from "@herb-tools/core";
2
- import type { LintOffense, Rule } from "../types.js";
3
- export declare class ERBRequireWhitespaceRule implements Rule {
1
+ import type { ParseResult } from "@herb-tools/core";
2
+ import { ParserRule } from "../types.js";
3
+ import type { LintOffense, LintContext } from "../types.js";
4
+ export declare class ERBRequireWhitespaceRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -0,0 +1,6 @@
1
+ import { SourceRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ export declare class ERBRequiresTrailingNewlineRule extends SourceRule {
4
+ name: string;
5
+ check(source: string, context?: Partial<LintContext>): LintOffense[];
6
+ }
@@ -1,6 +1,7 @@
1
- import { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLAnchorRequireHrefRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAnchorRequireHrefRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { LintOffense, Rule } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLAriaAttributeMustBeValid implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAriaAttributeMustBeValid extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -0,0 +1,7 @@
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAriaLevelMustBeValidRule extends ParserRule {
5
+ name: string;
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
7
+ }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLAriaRoleHeadingRequiresLevelRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAriaRoleHeadingRequiresLevelRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLAriaRoleMustBeValidRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAriaRoleMustBeValidRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLAttributeDoubleQuotesRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAttributeDoubleQuotesRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLAttributeValuesRequireQuotesRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLAttributeValuesRequireQuotesRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLBooleanAttributesNoValueRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLBooleanAttributesNoValueRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLImgRequireAltRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLImgRequireAltRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLNoBlockInsideInlineRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLNoBlockInsideInlineRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLNoDuplicateAttributesRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLNoDuplicateAttributesRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Node } from "@herb-tools/core";
2
- import type { LintOffense, Rule } from "../types";
3
- export declare class HTMLNoDuplicateIdsRule implements Rule {
1
+ import { ParserRule } from "../types";
2
+ import type { ParseResult } from "@herb-tools/core";
3
+ import type { LintOffense, LintContext } from "../types";
4
+ export declare class HTMLNoDuplicateIdsRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLNoEmptyHeadingsRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLNoEmptyHeadingsRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLNoNestedLinksRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLNoNestedLinksRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class HTMLTagNameLowercaseRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class HTMLTagNameLowercaseRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,6 +1,9 @@
1
1
  export * from "./erb-no-empty-tags.js";
2
2
  export * from "./erb-no-output-control-flow.js";
3
+ export * from "./erb-prefer-image-tag-helper.js";
4
+ export * from "./erb-requires-trailing-newline.js";
3
5
  export * from "./html-anchor-require-href.js";
6
+ export * from "./html-aria-level-must-be-valid.js";
4
7
  export * from "./html-aria-role-heading-requires-level.js";
5
8
  export * from "./html-aria-role-must-be-valid.js";
6
9
  export * from "./html-attribute-double-quotes.js";
@@ -0,0 +1,8 @@
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class ParserNoErrorsRule extends ParserRule {
5
+ name: string;
6
+ check(result: ParseResult): LintOffense[];
7
+ private herbErrorToLintOffense;
8
+ }
@@ -1,13 +1,14 @@
1
- import { Visitor } from "@herb-tools/core";
2
- import type { HTMLAttributeNode, HTMLOpenTagNode, HTMLSelfCloseTagNode, Location } from "@herb-tools/core";
3
- import type { LintOffense, LintSeverity } from "../types.js";
1
+ import { Visitor, Location } from "@herb-tools/core";
2
+ import type { HTMLAttributeNode, HTMLOpenTagNode, HTMLSelfCloseTagNode, LexResult, Token } from "@herb-tools/core";
3
+ import type { LintOffense, LintSeverity, LintContext } from "../types.js";
4
4
  /**
5
5
  * Base visitor class that provides common functionality for rule visitors
6
6
  */
7
7
  export declare abstract class BaseRuleVisitor extends Visitor {
8
8
  readonly offenses: LintOffense[];
9
9
  protected ruleName: string;
10
- constructor(ruleName: string);
10
+ protected context: LintContext;
11
+ constructor(ruleName: string, context?: Partial<LintContext>);
11
12
  /**
12
13
  * Helper method to create a lint offense
13
14
  */
@@ -67,6 +68,10 @@ export declare const SVG_CAMEL_CASE_ELEMENTS: Set<string>;
67
68
  export declare const SVG_LOWERCASE_TO_CAMELCASE: Map<string, string>;
68
69
  export declare const VALID_ARIA_ROLES: Set<string>;
69
70
  export declare const ARIA_ATTRIBUTES: Set<string>;
71
+ /**
72
+ * Helper function to create a location at the end of the source with a 1-character range
73
+ */
74
+ export declare function createEndOfFileLocation(source: string): Location;
70
75
  /**
71
76
  * Checks if an element is inline
72
77
  */
@@ -85,6 +90,7 @@ export declare function isBooleanAttribute(attributeName: string): boolean;
85
90
  * and attribute iteration logic. Provides simplified interface with extracted attribute info.
86
91
  */
87
92
  export declare abstract class AttributeVisitorMixin extends BaseRuleVisitor {
93
+ constructor(ruleName: string, context?: Partial<LintContext>);
88
94
  visitHTMLOpenTagNode(node: HTMLOpenTagNode): void;
89
95
  visitHTMLSelfCloseTagNode(node: HTMLSelfCloseTagNode): void;
90
96
  private checkAttributesOnNode;
@@ -98,3 +104,66 @@ export declare function isAttributeValueQuoted(attributeNode: HTMLAttributeNode)
98
104
  * Iterates over all attributes of a tag node, calling the callback for each attribute
99
105
  */
100
106
  export declare function forEachAttribute(node: HTMLOpenTagNode | HTMLSelfCloseTagNode, callback: (attributeNode: HTMLAttributeNode) => void): void;
107
+ /**
108
+ * Base lexer visitor class that provides common functionality for lexer-based rule visitors
109
+ */
110
+ export declare abstract class BaseLexerRuleVisitor {
111
+ readonly offenses: LintOffense[];
112
+ protected ruleName: string;
113
+ protected context: LintContext;
114
+ constructor(ruleName: string, context?: Partial<LintContext>);
115
+ /**
116
+ * Helper method to create a lint offense for lexer rules
117
+ */
118
+ protected createOffense(message: string, location: Location, severity?: LintSeverity): LintOffense;
119
+ /**
120
+ * Helper method to add an offense to the offenses array
121
+ */
122
+ protected addOffense(message: string, location: Location, severity?: LintSeverity): void;
123
+ /**
124
+ * Main entry point for lexer rule visitors
125
+ * @param lexResult - The lexer result containing tokens and source
126
+ */
127
+ visit(lexResult: LexResult): void;
128
+ /**
129
+ * Visit all tokens
130
+ * Override this method to implement token-level checks
131
+ */
132
+ protected visitTokens(tokens: Token[]): void;
133
+ /**
134
+ * Visit individual tokens
135
+ * Override this method to implement per-token checks
136
+ */
137
+ protected visitToken(_token: Token): void;
138
+ }
139
+ /**
140
+ * Base source visitor class that provides common functionality for source-based rule visitors
141
+ */
142
+ export declare abstract class BaseSourceRuleVisitor {
143
+ readonly offenses: LintOffense[];
144
+ protected ruleName: string;
145
+ protected context: LintContext;
146
+ constructor(ruleName: string, context?: Partial<LintContext>);
147
+ /**
148
+ * Helper method to create a lint offense for source rules
149
+ */
150
+ protected createOffense(message: string, location: Location, severity?: LintSeverity): LintOffense;
151
+ /**
152
+ * Helper method to add an offense to the offenses array
153
+ */
154
+ protected addOffense(message: string, location: Location, severity?: LintSeverity): void;
155
+ /**
156
+ * Main entry point for source rule visitors
157
+ * @param source - The raw source code
158
+ */
159
+ visit(source: string): void;
160
+ /**
161
+ * Visit the source code directly
162
+ * Override this method to implement source-level checks
163
+ */
164
+ protected abstract visitSource(source: string): void;
165
+ /**
166
+ * Helper method to create a location for a specific position in the source
167
+ */
168
+ protected createLocationAt(source: string, position: number): Location;
169
+ }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class SVGTagNameCapitalizationRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class SVGTagNameCapitalizationRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }
@@ -1,7 +1,8 @@
1
1
  import type { ThemeInput } from "@herb-tools/highlighter";
2
+ export type FormatOption = "simple" | "detailed" | "json" | "github";
2
3
  export interface ParsedArguments {
3
4
  pattern: string;
4
- formatOption: 'simple' | 'detailed';
5
+ formatOption: FormatOption;
5
6
  showTiming: boolean;
6
7
  theme: ThemeInput;
7
8
  wrapLines: boolean;
@@ -1,21 +1,22 @@
1
1
  import type { Diagnostic } from "@herb-tools/core";
2
+ import type { FormatOption } from "./argument-parser.js";
2
3
  export interface ProcessedFile {
3
4
  filename: string;
4
- diagnostic: Diagnostic;
5
+ offense: Diagnostic;
5
6
  content: string;
6
7
  }
7
8
  export interface ProcessingResult {
8
9
  totalErrors: number;
9
10
  totalWarnings: number;
10
- filesWithIssues: number;
11
+ filesWithOffenses: number;
11
12
  ruleCount: number;
12
- allDiagnostics: ProcessedFile[];
13
- ruleViolations: Map<string, {
13
+ allOffenses: ProcessedFile[];
14
+ ruleOffenses: Map<string, {
14
15
  count: number;
15
16
  files: Set<string>;
16
17
  }>;
17
18
  }
18
19
  export declare class FileProcessor {
19
20
  private linter;
20
- processFiles(files: string[]): Promise<ProcessingResult>;
21
+ processFiles(files: string[], formatOption?: FormatOption): Promise<ProcessingResult>;
21
22
  }
@@ -1,6 +1,6 @@
1
1
  import type { Diagnostic } from "@herb-tools/core";
2
2
  import type { ProcessedFile } from "../file-processor.js";
3
3
  export declare abstract class BaseFormatter {
4
- abstract format(allDiagnostics: ProcessedFile[], isSingleFile?: boolean): Promise<void>;
5
- abstract formatFile(filename: string, diagnostics: Diagnostic[]): void;
4
+ abstract format(allOffenses: ProcessedFile[], isSingleFile?: boolean): Promise<void>;
5
+ abstract formatFile(filename: string, offenses: Diagnostic[]): void;
6
6
  }
@@ -8,6 +8,6 @@ export declare class DetailedFormatter extends BaseFormatter {
8
8
  private wrapLines;
9
9
  private truncateLines;
10
10
  constructor(theme?: ThemeInput, wrapLines?: boolean, truncateLines?: boolean);
11
- format(allDiagnostics: ProcessedFile[], isSingleFile?: boolean): Promise<void>;
12
- formatFile(_filename: string, _diagnostics: Diagnostic[]): void;
11
+ format(allOffenses: ProcessedFile[], isSingleFile?: boolean): Promise<void>;
12
+ formatFile(_filename: string, _offenses: Diagnostic[]): void;
13
13
  }
@@ -0,0 +1,12 @@
1
+ import { BaseFormatter } from "./base-formatter.js";
2
+ import type { Diagnostic } from "@herb-tools/core";
3
+ import type { ProcessedFile } from "../file-processor.js";
4
+ export declare class GitHubActionsFormatter extends BaseFormatter {
5
+ private static readonly MESSAGE_ESCAPE_MAP;
6
+ private static readonly PARAM_ESCAPE_MAP;
7
+ format(allDiagnostics: ProcessedFile[]): Promise<void>;
8
+ formatFile(filename: string, diagnostics: Diagnostic[]): void;
9
+ private formatDiagnostic;
10
+ private escapeMessage;
11
+ private escapeParam;
12
+ }
@@ -1,3 +1,5 @@
1
1
  export { BaseFormatter } from "./base-formatter.js";
2
2
  export { SimpleFormatter } from "./simple-formatter.js";
3
3
  export { DetailedFormatter } from "./detailed-formatter.js";
4
+ export { JSONFormatter, type JSONOutput } from "./json-formatter.js";
5
+ export { GitHubActionsFormatter } from "./github-actions-formatter.js";
@@ -0,0 +1,42 @@
1
+ import { BaseFormatter } from "./base-formatter.js";
2
+ import type { Diagnostic, SerializedDiagnostic } from "@herb-tools/core";
3
+ import type { ProcessedFile } from "../file-processor.js";
4
+ interface JSONOffense extends SerializedDiagnostic {
5
+ filename: string;
6
+ }
7
+ interface JSONSummary {
8
+ filesChecked: number;
9
+ filesWithOffenses: number;
10
+ totalErrors: number;
11
+ totalWarnings: number;
12
+ totalOffenses: number;
13
+ ruleCount: number;
14
+ }
15
+ interface JSONTiming {
16
+ startTime: string;
17
+ duration: number;
18
+ }
19
+ export interface JSONOutput {
20
+ offenses: JSONOffense[];
21
+ summary: JSONSummary | null;
22
+ timing: JSONTiming | null;
23
+ completed: boolean;
24
+ clean: boolean | null;
25
+ message: string | null;
26
+ }
27
+ interface JSONFormatOptions {
28
+ files: string[];
29
+ totalErrors: number;
30
+ totalWarnings: number;
31
+ filesWithOffenses: number;
32
+ ruleCount: number;
33
+ startTime: number;
34
+ startDate: Date;
35
+ showTiming: boolean;
36
+ }
37
+ export declare class JSONFormatter extends BaseFormatter {
38
+ format(allOffenses: ProcessedFile[]): Promise<void>;
39
+ formatWithSummary(allOffenses: ProcessedFile[], options: JSONFormatOptions): Promise<void>;
40
+ formatFile(_filename: string, _offenses: Diagnostic[]): void;
41
+ }
42
+ export {};
@@ -2,6 +2,6 @@ import { BaseFormatter } from "./base-formatter.js";
2
2
  import type { Diagnostic } from "@herb-tools/core";
3
3
  import type { ProcessedFile } from "../file-processor.js";
4
4
  export declare class SimpleFormatter extends BaseFormatter {
5
- format(allDiagnostics: ProcessedFile[]): Promise<void>;
6
- formatFile(filename: string, diagnostics: Diagnostic[]): void;
5
+ format(allOffenses: ProcessedFile[]): Promise<void>;
6
+ formatFile(filename: string, offenses: Diagnostic[]): void;
7
7
  }
@@ -0,0 +1,31 @@
1
+ import type { ThemeInput } from "@herb-tools/highlighter";
2
+ import type { FormatOption } from "./argument-parser.js";
3
+ import type { ProcessingResult } from "./file-processor.js";
4
+ interface OutputOptions {
5
+ formatOption: FormatOption;
6
+ theme: ThemeInput;
7
+ wrapLines: boolean;
8
+ truncateLines: boolean;
9
+ showTiming: boolean;
10
+ startTime: number;
11
+ startDate: Date;
12
+ }
13
+ interface LintResults extends ProcessingResult {
14
+ files: string[];
15
+ }
16
+ export declare class OutputManager {
17
+ private summaryReporter;
18
+ /**
19
+ * Output successful lint results
20
+ */
21
+ outputResults(results: LintResults, options: OutputOptions): Promise<void>;
22
+ /**
23
+ * Output informational message (like "no files found")
24
+ */
25
+ outputInfo(message: string, options: OutputOptions): void;
26
+ /**
27
+ * Output error message
28
+ */
29
+ outputError(message: string, options: OutputOptions): void;
30
+ }
31
+ export {};
@@ -2,12 +2,12 @@ export interface SummaryData {
2
2
  files: string[];
3
3
  totalErrors: number;
4
4
  totalWarnings: number;
5
- filesWithViolations: number;
5
+ filesWithOffenses: number;
6
6
  ruleCount: number;
7
7
  startTime: number;
8
8
  startDate: Date;
9
9
  showTiming: boolean;
10
- ruleViolations: Map<string, {
10
+ ruleOffenses: Map<string, {
11
11
  count: number;
12
12
  files: Set<string>;
13
13
  }>;
@@ -15,7 +15,7 @@ export interface SummaryData {
15
15
  export declare class SummaryReporter {
16
16
  private pluralize;
17
17
  displaySummary(data: SummaryData): void;
18
- displayMostViolatedRules(ruleViolations: Map<string, {
18
+ displayMostViolatedRules(ruleOffenses: Map<string, {
19
19
  count: number;
20
20
  files: Set<string>;
21
21
  }>, limit?: number): void;
@@ -1,6 +1,8 @@
1
1
  export declare class CLI {
2
2
  private argumentParser;
3
3
  private fileProcessor;
4
- private summaryReporter;
4
+ private outputManager;
5
+ private exitWithError;
6
+ private exitWithInfo;
5
7
  run(): Promise<void>;
6
8
  }
@@ -1,18 +1,33 @@
1
- import type { RuleClass, LintResult } from "./types.js";
2
- import type { DocumentNode } from "@herb-tools/core";
1
+ import type { RuleClass, LintResult, LintContext } from "./types.js";
2
+ import type { HerbBackend } from "@herb-tools/core";
3
3
  export declare class Linter {
4
4
  private rules;
5
+ private herb;
5
6
  private offenses;
6
7
  /**
7
8
  * Creates a new Linter instance.
8
- * @param rules - Array of rule classes (not instances) to use. If not provided, uses default rules.
9
+ * @param herb - The Herb backend instance for parsing and lexing
10
+ * @param rules - Array of rule classes (Parser/AST or Lexer) to use. If not provided, uses default rules.
9
11
  */
10
- constructor(rules?: RuleClass[]);
12
+ constructor(herb: HerbBackend, rules?: RuleClass[]);
11
13
  /**
12
14
  * Returns the default set of rule classes used by the linter.
13
15
  * @returns Array of rule classes
14
16
  */
15
17
  private getDefaultRules;
16
18
  getRuleCount(): number;
17
- lint(document: DocumentNode): LintResult;
19
+ /**
20
+ * Type guard to check if a rule is a LexerRule
21
+ */
22
+ private isLexerRule;
23
+ /**
24
+ * Type guard to check if a rule is a SourceRule
25
+ */
26
+ private isSourceRule;
27
+ /**
28
+ * Lint source code using Parser/AST, Lexer, and Source rules.
29
+ * @param source - The source code to lint
30
+ * @param context - Optional context for linting (e.g., fileName for distinguishing files vs snippets)
31
+ */
32
+ lint(source: string, context?: Partial<LintContext>): LintResult;
18
33
  }
@@ -1,6 +1,7 @@
1
- import type { Rule, LintOffense } from "../types.js";
2
- import type { Node } from "@herb-tools/core";
3
- export declare class ERBNoEmptyTagsRule implements Rule {
1
+ import { ParserRule } from "../types.js";
2
+ import type { LintOffense, LintContext } from "../types.js";
3
+ import type { ParseResult } from "@herb-tools/core";
4
+ export declare class ERBNoEmptyTagsRule extends ParserRule {
4
5
  name: string;
5
- check(node: Node): LintOffense[];
6
+ check(result: ParseResult, context?: Partial<LintContext>): LintOffense[];
6
7
  }