@herb-tools/linter 0.4.3 → 0.6.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.
- package/README.md +216 -19
- package/dist/herb-lint.js +5559 -1860
- package/dist/herb-lint.js.map +1 -1
- package/dist/index.cjs +722 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +714 -189
- package/dist/index.js.map +1 -1
- package/dist/package.json +4 -4
- package/dist/src/cli/argument-parser.js +28 -22
- package/dist/src/cli/argument-parser.js.map +1 -1
- package/dist/src/cli/file-processor.js +19 -13
- package/dist/src/cli/file-processor.js.map +1 -1
- package/dist/src/cli/formatters/detailed-formatter.js +9 -9
- package/dist/src/cli/formatters/detailed-formatter.js.map +1 -1
- package/dist/src/cli/formatters/github-actions-formatter.js +50 -0
- package/dist/src/cli/formatters/github-actions-formatter.js.map +1 -0
- package/dist/src/cli/formatters/index.js +2 -0
- package/dist/src/cli/formatters/index.js.map +1 -1
- package/dist/src/cli/formatters/json-formatter.js +58 -0
- package/dist/src/cli/formatters/json-formatter.js.map +1 -0
- package/dist/src/cli/formatters/simple-formatter.js +15 -15
- package/dist/src/cli/formatters/simple-formatter.js.map +1 -1
- package/dist/src/cli/output-manager.js +120 -0
- package/dist/src/cli/output-manager.js.map +1 -0
- package/dist/src/cli/summary-reporter.js +22 -22
- package/dist/src/cli/summary-reporter.js.map +1 -1
- package/dist/src/cli.js +41 -26
- package/dist/src/cli.js.map +1 -1
- package/dist/src/default-rules.js +22 -0
- package/dist/src/default-rules.js.map +1 -1
- package/dist/src/linter.js +29 -4
- package/dist/src/linter.js.map +1 -1
- package/dist/src/rules/erb-no-empty-tags.js +2 -2
- package/dist/src/rules/erb-no-empty-tags.js.map +1 -1
- package/dist/src/rules/erb-no-output-control-flow.js +2 -2
- package/dist/src/rules/erb-no-output-control-flow.js.map +1 -1
- package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js +26 -0
- package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js.map +1 -0
- package/dist/src/rules/erb-prefer-image-tag-helper.js +2 -6
- package/dist/src/rules/erb-prefer-image-tag-helper.js.map +1 -1
- package/dist/src/rules/erb-require-whitespace-inside-tags.js +2 -2
- package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +1 -1
- package/dist/src/rules/erb-requires-trailing-newline.js.map +1 -1
- package/dist/src/rules/html-anchor-require-href.js +2 -2
- package/dist/src/rules/html-anchor-require-href.js.map +1 -1
- package/dist/src/rules/html-aria-attribute-must-be-valid.js +13 -12
- package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-aria-label-is-well-formatted.js +33 -0
- package/dist/src/rules/html-aria-label-is-well-formatted.js.map +1 -0
- package/dist/src/rules/html-aria-level-must-be-valid.js +28 -6
- package/dist/src/rules/html-aria-level-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-aria-role-heading-requires-level.js +9 -15
- package/dist/src/rules/html-aria-role-heading-requires-level.js.map +1 -1
- package/dist/src/rules/html-aria-role-must-be-valid.js +5 -5
- package/dist/src/rules/html-aria-role-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-attribute-double-quotes.js +16 -6
- package/dist/src/rules/html-attribute-double-quotes.js.map +1 -1
- package/dist/src/rules/html-attribute-equals-spacing.js +24 -0
- package/dist/src/rules/html-attribute-equals-spacing.js.map +1 -0
- package/dist/src/rules/html-attribute-values-require-quotes.js +21 -10
- package/dist/src/rules/html-attribute-values-require-quotes.js.map +1 -1
- package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js +47 -0
- package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js.map +1 -0
- package/dist/src/rules/html-boolean-attributes-no-value.js +11 -4
- package/dist/src/rules/html-boolean-attributes-no-value.js.map +1 -1
- package/dist/src/rules/html-iframe-has-title.js +39 -0
- package/dist/src/rules/html-iframe-has-title.js.map +1 -0
- package/dist/src/rules/html-img-require-alt.js +2 -6
- package/dist/src/rules/html-img-require-alt.js.map +1 -1
- package/dist/src/rules/html-navigation-has-label.js +43 -0
- package/dist/src/rules/html-navigation-has-label.js.map +1 -0
- package/dist/src/rules/html-no-aria-hidden-on-focusable.js +67 -0
- package/dist/src/rules/html-no-aria-hidden-on-focusable.js.map +1 -0
- package/dist/src/rules/html-no-block-inside-inline.js +4 -4
- package/dist/src/rules/html-no-block-inside-inline.js.map +1 -1
- package/dist/src/rules/html-no-duplicate-attributes.js +24 -27
- package/dist/src/rules/html-no-duplicate-attributes.js.map +1 -1
- package/dist/src/rules/html-no-duplicate-ids.js +4 -4
- package/dist/src/rules/html-no-duplicate-ids.js.map +1 -1
- package/dist/src/rules/html-no-empty-headings.js +2 -23
- package/dist/src/rules/html-no-empty-headings.js.map +1 -1
- package/dist/src/rules/html-no-nested-links.js +2 -2
- package/dist/src/rules/html-no-nested-links.js.map +1 -1
- package/dist/src/rules/html-no-positive-tab-index.js +21 -0
- package/dist/src/rules/html-no-positive-tab-index.js.map +1 -0
- package/dist/src/rules/html-no-self-closing.js +22 -0
- package/dist/src/rules/html-no-self-closing.js.map +1 -0
- package/dist/src/rules/html-no-title-attribute.js +27 -0
- package/dist/src/rules/html-no-title-attribute.js.map +1 -0
- package/dist/src/rules/html-tag-name-lowercase.js +37 -25
- package/dist/src/rules/html-tag-name-lowercase.js.map +1 -1
- package/dist/src/rules/index.js +10 -0
- package/dist/src/rules/index.js.map +1 -1
- package/dist/src/rules/parser-no-errors.js +18 -0
- package/dist/src/rules/parser-no-errors.js.map +1 -0
- package/dist/src/rules/rule-utils.js +176 -22
- package/dist/src/rules/rule-utils.js.map +1 -1
- package/dist/src/rules/svg-tag-name-capitalization.js +2 -10
- package/dist/src/rules/svg-tag-name-capitalization.js.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/cli/argument-parser.d.ts +2 -1
- package/dist/types/cli/file-processor.d.ts +6 -5
- package/dist/types/cli/formatters/base-formatter.d.ts +2 -2
- package/dist/types/cli/formatters/detailed-formatter.d.ts +2 -2
- package/dist/types/cli/formatters/github-actions-formatter.d.ts +12 -0
- package/dist/types/cli/formatters/index.d.ts +2 -0
- package/dist/types/cli/formatters/json-formatter.d.ts +42 -0
- package/dist/types/cli/formatters/simple-formatter.d.ts +2 -2
- package/dist/types/cli/index.d.ts +4 -0
- package/dist/types/cli/output-manager.d.ts +31 -0
- package/dist/types/cli/summary-reporter.d.ts +3 -3
- package/dist/types/cli.d.ts +3 -1
- package/dist/types/rules/erb-no-empty-tags.d.ts +2 -2
- package/dist/types/rules/erb-no-output-control-flow.d.ts +2 -2
- package/dist/types/rules/erb-no-silent-tag-in-attribute-name.d.ts +7 -0
- package/dist/types/rules/erb-prefer-image-tag-helper.d.ts +2 -2
- package/dist/types/rules/erb-require-whitespace-inside-tags.d.ts +2 -2
- package/dist/types/rules/html-anchor-require-href.d.ts +2 -2
- package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +2 -2
- package/dist/types/rules/html-aria-label-is-well-formatted.d.ts +7 -0
- package/dist/types/rules/html-aria-level-must-be-valid.d.ts +2 -2
- package/dist/types/rules/html-aria-role-heading-requires-level.d.ts +2 -2
- package/dist/types/rules/html-aria-role-must-be-valid.d.ts +2 -2
- package/dist/types/rules/html-attribute-double-quotes.d.ts +2 -2
- package/dist/types/rules/html-attribute-equals-spacing.d.ts +7 -0
- package/dist/types/rules/html-attribute-values-require-quotes.d.ts +2 -2
- package/dist/types/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +7 -0
- package/dist/types/rules/html-boolean-attributes-no-value.d.ts +2 -2
- package/dist/types/rules/html-iframe-has-title.d.ts +7 -0
- package/dist/types/rules/html-img-require-alt.d.ts +2 -2
- package/dist/types/rules/html-navigation-has-label.d.ts +7 -0
- package/dist/types/rules/html-no-aria-hidden-on-focusable.d.ts +7 -0
- package/dist/types/rules/html-no-block-inside-inline.d.ts +2 -2
- package/dist/types/rules/html-no-duplicate-attributes.d.ts +2 -2
- package/dist/types/rules/html-no-duplicate-ids.d.ts +2 -2
- package/dist/types/rules/html-no-empty-headings.d.ts +2 -2
- package/dist/types/rules/html-no-nested-links.d.ts +2 -2
- package/dist/types/rules/html-no-positive-tab-index.d.ts +7 -0
- package/dist/types/rules/html-no-self-closing.d.ts +7 -0
- package/dist/types/rules/html-no-title-attribute.d.ts +7 -0
- package/dist/types/rules/html-tag-name-lowercase.d.ts +3 -2
- package/dist/types/rules/index.d.ts +10 -0
- package/dist/types/rules/parser-no-errors.d.ts +8 -0
- package/dist/types/rules/rule-utils.d.ts +107 -13
- package/dist/types/rules/svg-tag-name-capitalization.d.ts +2 -2
- package/dist/types/src/cli/argument-parser.d.ts +2 -1
- package/dist/types/src/cli/file-processor.d.ts +6 -5
- package/dist/types/src/cli/formatters/base-formatter.d.ts +2 -2
- package/dist/types/src/cli/formatters/detailed-formatter.d.ts +2 -2
- package/dist/types/src/cli/formatters/github-actions-formatter.d.ts +12 -0
- package/dist/types/src/cli/formatters/index.d.ts +2 -0
- package/dist/types/src/cli/formatters/json-formatter.d.ts +42 -0
- package/dist/types/src/cli/formatters/simple-formatter.d.ts +2 -2
- package/dist/types/src/cli/output-manager.d.ts +31 -0
- package/dist/types/src/cli/summary-reporter.d.ts +3 -3
- package/dist/types/src/cli.d.ts +3 -1
- package/dist/types/src/rules/erb-no-empty-tags.d.ts +2 -2
- package/dist/types/src/rules/erb-no-output-control-flow.d.ts +2 -2
- package/dist/types/src/rules/erb-no-silent-tag-in-attribute-name.d.ts +7 -0
- package/dist/types/src/rules/erb-prefer-image-tag-helper.d.ts +2 -2
- package/dist/types/src/rules/erb-require-whitespace-inside-tags.d.ts +2 -2
- package/dist/types/src/rules/html-anchor-require-href.d.ts +2 -2
- package/dist/types/src/rules/html-aria-attribute-must-be-valid.d.ts +2 -2
- package/dist/types/src/rules/html-aria-label-is-well-formatted.d.ts +7 -0
- package/dist/types/src/rules/html-aria-level-must-be-valid.d.ts +2 -2
- package/dist/types/src/rules/html-aria-role-heading-requires-level.d.ts +2 -2
- package/dist/types/src/rules/html-aria-role-must-be-valid.d.ts +2 -2
- package/dist/types/src/rules/html-attribute-double-quotes.d.ts +2 -2
- package/dist/types/src/rules/html-attribute-equals-spacing.d.ts +7 -0
- package/dist/types/src/rules/html-attribute-values-require-quotes.d.ts +2 -2
- package/dist/types/src/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +7 -0
- package/dist/types/src/rules/html-boolean-attributes-no-value.d.ts +2 -2
- package/dist/types/src/rules/html-iframe-has-title.d.ts +7 -0
- package/dist/types/src/rules/html-img-require-alt.d.ts +2 -2
- package/dist/types/src/rules/html-navigation-has-label.d.ts +7 -0
- package/dist/types/src/rules/html-no-aria-hidden-on-focusable.d.ts +7 -0
- package/dist/types/src/rules/html-no-block-inside-inline.d.ts +2 -2
- package/dist/types/src/rules/html-no-duplicate-attributes.d.ts +2 -2
- package/dist/types/src/rules/html-no-duplicate-ids.d.ts +2 -2
- package/dist/types/src/rules/html-no-empty-headings.d.ts +2 -2
- package/dist/types/src/rules/html-no-nested-links.d.ts +2 -2
- package/dist/types/src/rules/html-no-positive-tab-index.d.ts +7 -0
- package/dist/types/src/rules/html-no-self-closing.d.ts +7 -0
- package/dist/types/src/rules/html-no-title-attribute.d.ts +7 -0
- package/dist/types/src/rules/html-tag-name-lowercase.d.ts +3 -2
- package/dist/types/src/rules/index.d.ts +10 -0
- package/dist/types/src/rules/parser-no-errors.d.ts +8 -0
- package/dist/types/src/rules/rule-utils.d.ts +107 -13
- package/dist/types/src/rules/svg-tag-name-capitalization.d.ts +2 -2
- package/dist/types/src/types.d.ts +27 -3
- package/dist/types/types.d.ts +27 -3
- package/docs/rules/README.md +13 -2
- package/docs/rules/erb-no-silent-tag-in-attribute-name.md +34 -0
- package/docs/rules/html-aria-label-is-well-formatted.md +49 -0
- package/docs/rules/html-attribute-equals-spacing.md +35 -0
- package/docs/rules/html-avoid-both-disabled-and-aria-disabled.md +48 -0
- package/docs/rules/html-iframe-has-title.md +43 -0
- package/docs/rules/html-navigation-has-label.md +61 -0
- package/docs/rules/html-no-aria-hidden-on-focusable.md +54 -0
- package/docs/rules/html-no-positive-tab-index.md +55 -0
- package/docs/rules/html-no-self-closing.md +65 -0
- package/docs/rules/html-no-title-attribute.md +69 -0
- package/docs/rules/html-tag-name-lowercase.md +16 -3
- package/docs/rules/parser-no-errors.md +84 -0
- package/package.json +4 -4
- package/src/cli/argument-parser.ts +33 -24
- package/src/cli/file-processor.ts +25 -17
- package/src/cli/formatters/base-formatter.ts +2 -2
- package/src/cli/formatters/detailed-formatter.ts +9 -9
- package/src/cli/formatters/github-actions-formatter.ts +70 -0
- package/src/cli/formatters/index.ts +2 -0
- package/src/cli/formatters/json-formatter.ts +107 -0
- package/src/cli/formatters/simple-formatter.ts +15 -15
- package/src/cli/output-manager.ts +143 -0
- package/src/cli/summary-reporter.ts +24 -24
- package/src/cli.ts +48 -31
- package/src/default-rules.ts +22 -0
- package/src/linter.ts +30 -4
- package/src/rules/erb-no-empty-tags.ts +3 -3
- package/src/rules/erb-no-output-control-flow.ts +3 -3
- package/src/rules/erb-no-silent-tag-in-attribute-name.ts +40 -0
- package/src/rules/erb-prefer-image-tag-helper.ts +4 -9
- package/src/rules/erb-require-whitespace-inside-tags.ts +3 -3
- package/src/rules/erb-requires-trailing-newline.ts +2 -0
- package/src/rules/html-anchor-require-href.ts +3 -3
- package/src/rules/html-aria-attribute-must-be-valid.ts +29 -33
- package/src/rules/html-aria-label-is-well-formatted.ts +59 -0
- package/src/rules/html-aria-level-must-be-valid.ts +40 -7
- package/src/rules/html-aria-role-heading-requires-level.ts +18 -30
- package/src/rules/html-aria-role-must-be-valid.ts +7 -7
- package/src/rules/html-attribute-double-quotes.ts +23 -8
- package/src/rules/html-attribute-equals-spacing.ts +41 -0
- package/src/rules/html-attribute-values-require-quotes.ts +32 -12
- package/src/rules/html-avoid-both-disabled-and-aria-disabled.ts +66 -0
- package/src/rules/html-boolean-attributes-no-value.ts +19 -6
- package/src/rules/html-iframe-has-title.ts +62 -0
- package/src/rules/html-img-require-alt.ts +4 -9
- package/src/rules/html-navigation-has-label.ts +64 -0
- package/src/rules/html-no-aria-hidden-on-focusable.ts +90 -0
- package/src/rules/html-no-block-inside-inline.ts +5 -5
- package/src/rules/html-no-duplicate-attributes.ts +30 -30
- package/src/rules/html-no-duplicate-ids.ts +6 -5
- package/src/rules/html-no-empty-headings.ts +4 -33
- package/src/rules/html-no-nested-links.ts +3 -3
- package/src/rules/html-no-positive-tab-index.ts +33 -0
- package/src/rules/html-no-self-closing.ts +36 -0
- package/src/rules/html-no-title-attribute.ts +42 -0
- package/src/rules/html-tag-name-lowercase.ts +44 -31
- package/src/rules/index.ts +10 -0
- package/src/rules/parser-no-errors.ts +25 -0
- package/src/rules/rule-utils.ts +260 -39
- package/src/rules/svg-tag-name-capitalization.ts +4 -11
- package/src/types.ts +30 -3
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Linter Rule: `iframe` elements must have a `title` attribute
|
|
2
|
+
|
|
3
|
+
**Rule:** `html-iframe-has-title`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Ensure that all `iframe` elements have a meaningful `title` attribute that describes the content of the frame. The title should not be empty or contain only whitespace.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
The `title` attribute on `iframe` elements provides essential context for screen reader users about what content the frame contains. Without this information, users of assistive technology cannot understand the purpose or content of the embedded frame, creating significant accessibility barriers.
|
|
12
|
+
|
|
13
|
+
::: tip Note
|
|
14
|
+
`<iframe>`'s with `aria-hidden="true"` are exempt from this requirement as they are hidden from assistive technologies.
|
|
15
|
+
:::
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### ✅ Good
|
|
20
|
+
|
|
21
|
+
```erb
|
|
22
|
+
<iframe src="https://youtube.com/embed/123" title="Product demonstration video"></iframe>
|
|
23
|
+
<iframe src="https://example.com" title="Example website content"></iframe>
|
|
24
|
+
|
|
25
|
+
<!-- Hidden from screen readers -->
|
|
26
|
+
<iframe aria-hidden="true"></iframe>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 🚫 Bad
|
|
30
|
+
|
|
31
|
+
```erb
|
|
32
|
+
<iframe src="https://example.com"></iframe>
|
|
33
|
+
|
|
34
|
+
<iframe src="https://example.com" title=""></iframe>
|
|
35
|
+
|
|
36
|
+
<iframe src="https://example.com" title=" "></iframe>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## References
|
|
40
|
+
|
|
41
|
+
- [HTML: `iframe` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
|
|
42
|
+
- [HTML: `title` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title)
|
|
43
|
+
- [erblint-github: GitHub::Accessibility::IframeHasTitle](https://github.com/github/erblint-github/blob/main/docs/rules/accessibility/iframe-has-title.md)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Linter Rule: Navigation landmarks must have accessible labels
|
|
2
|
+
|
|
3
|
+
**Rule:** `html-navigation-has-label`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Ensure that navigation landmarks have a unique accessible name via `aria-label` or `aria-labelledby` attributes. This applies to both `<nav>` elements and elements with `role="navigation"`.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
Navigation landmarks help users of assistive technology quickly understand and navigate to different sections of a website. When multiple navigation landmarks exist on a page, each needs a unique accessible name so users can distinguish between them (e.g., "Main navigation", "Footer links", "Breadcrumb navigation").
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### ✅ Good
|
|
16
|
+
|
|
17
|
+
```erb
|
|
18
|
+
<nav aria-label="Main navigation">
|
|
19
|
+
<ul>
|
|
20
|
+
<li><a href="/">Home</a></li>
|
|
21
|
+
<li><a href="/about">About</a></li>
|
|
22
|
+
</ul>
|
|
23
|
+
</nav>
|
|
24
|
+
|
|
25
|
+
<nav aria-labelledby="breadcrumb-title">
|
|
26
|
+
<h2 id="breadcrumb-title">Breadcrumb</h2>
|
|
27
|
+
<ol>
|
|
28
|
+
<li><a href="/">Home</a></li>
|
|
29
|
+
<li>Current Page</li>
|
|
30
|
+
</ol>
|
|
31
|
+
</nav>
|
|
32
|
+
|
|
33
|
+
<div role="navigation" aria-label="Footer links">
|
|
34
|
+
<a href="/privacy">Privacy</a>
|
|
35
|
+
<a href="/terms">Terms</a>
|
|
36
|
+
</div>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 🚫 Bad
|
|
40
|
+
|
|
41
|
+
```erb
|
|
42
|
+
<nav>
|
|
43
|
+
<ul>
|
|
44
|
+
<li><a href="/">Home</a></li>
|
|
45
|
+
<li><a href="/about">About</a></li>
|
|
46
|
+
</ul>
|
|
47
|
+
</nav>
|
|
48
|
+
|
|
49
|
+
<div role="navigation">
|
|
50
|
+
<a href="/privacy">Privacy</a>
|
|
51
|
+
<a href="/terms">Terms</a>
|
|
52
|
+
</div>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## References
|
|
56
|
+
|
|
57
|
+
- [ARIA: `navigation` role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/navigation_role)
|
|
58
|
+
- [HTML: `nav` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
|
|
59
|
+
- [ARIA: `aria-label` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label)
|
|
60
|
+
- [ARIA: `aria-labelledby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-labelledby)
|
|
61
|
+
- [erblint-github: GitHub::Accessibility::NavigationHasLabel](https://github.com/github/erblint-github/blob/main/docs/rules/accessibility/navigation-has-label.md)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Linter Rule: Focusable elements should not have `aria-hidden="true"`
|
|
2
|
+
|
|
3
|
+
**Rule:** `html-no-aria-hidden-on-focusable`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Prevent using `aria-hidden="true"` on elements that can receive keyboard focus. When an element is focusable but hidden from screen readers, it creates a confusing experience where keyboard users can tab to "invisible" elements.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
Elements with `aria-hidden="true"` are completely hidden from assistive technologies, but they remain visible and interactive for mouse and keyboard users. If a focusable element is hidden from screen readers, keyboard-only users (especially those using screen readers) will encounter focused elements that provide no accessible information, creating a broken user experience.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### ✅ Good
|
|
16
|
+
|
|
17
|
+
```erb
|
|
18
|
+
<button>Submit</button>
|
|
19
|
+
<a href="/link">Link</a>
|
|
20
|
+
<input type="text">
|
|
21
|
+
<textarea></textarea>
|
|
22
|
+
|
|
23
|
+
<div aria-hidden="true">Decorative content</div>
|
|
24
|
+
<span aria-hidden="true">🎉</span>
|
|
25
|
+
|
|
26
|
+
<button tabindex="-1" aria-hidden="true">Hidden button</button>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 🚫 Bad
|
|
30
|
+
|
|
31
|
+
```erb
|
|
32
|
+
<button aria-hidden="true">Submit</button>
|
|
33
|
+
|
|
34
|
+
<a href="/link" aria-hidden="true">Link</a>
|
|
35
|
+
|
|
36
|
+
<input type="text" aria-hidden="true">
|
|
37
|
+
|
|
38
|
+
<textarea aria-hidden="true"></textarea>
|
|
39
|
+
|
|
40
|
+
<select aria-hidden="true">
|
|
41
|
+
<option>Option</option>
|
|
42
|
+
</select>
|
|
43
|
+
|
|
44
|
+
<div tabindex="0" aria-hidden="true">Focusable div</div>
|
|
45
|
+
|
|
46
|
+
<a href="/link" aria-hidden="true">Hidden link</a>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## References
|
|
50
|
+
|
|
51
|
+
- [ARIA: `aria-hidden` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-hidden)
|
|
52
|
+
- [HTML: `tabindex` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
|
|
53
|
+
- [WebAIM: Keyboard Accessibility](https://webaim.org/techniques/keyboard/)
|
|
54
|
+
- [erblint-github: GitHub::Accessibility::NoAriaHiddenOnFocusable](https://github.com/github/erblint-github/blob/main/docs/rules/accessibility/no-aria-hidden-on-focusable.md)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Linter Rule: Avoid positive `tabindex` values
|
|
2
|
+
|
|
3
|
+
**Rule:** `html-no-positive-tab-index`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Prevent using positive values for the `tabindex` attribute. Only `tabindex="0"` (to make elements focusable) and `tabindex="-1"` (to remove from tab order) should be used.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
Positive `tabindex` values create a custom tab order that can be confusing and unpredictable for keyboard users. They override the natural document flow and can cause elements to be focused in an unexpected sequence. This breaks the logical reading order and creates usability issues, especially for screen reader users who rely on a predictable navigation pattern.
|
|
12
|
+
|
|
13
|
+
The recommended approach is to structure your HTML in the correct tab order and use `tabindex="0"` only when you need to make non-interactive elements focusable, or `tabindex="-1"` to remove elements from the tab sequence while keeping them programmatically focusable.
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
### ✅ Good
|
|
18
|
+
|
|
19
|
+
```erb
|
|
20
|
+
<!-- Natural tab order (no tabindex needed) -->
|
|
21
|
+
<button>First</button>
|
|
22
|
+
<button>Second</button>
|
|
23
|
+
<button>Third</button>
|
|
24
|
+
|
|
25
|
+
<!-- Make non-interactive element focusable -->
|
|
26
|
+
<div tabindex="0" role="button">Custom button</div>
|
|
27
|
+
|
|
28
|
+
<!-- Remove from tab order but keep programmatically focusable -->
|
|
29
|
+
<button tabindex="-1">Skip this in tab order</button>
|
|
30
|
+
|
|
31
|
+
<!-- Zero tabindex to ensure focusability -->
|
|
32
|
+
<span tabindex="0" role="button">Focusable span</span>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 🚫 Bad
|
|
36
|
+
|
|
37
|
+
```erb
|
|
38
|
+
<button tabindex="3">Third in tab order</button>
|
|
39
|
+
|
|
40
|
+
<button tabindex="1">First in tab order</button>
|
|
41
|
+
|
|
42
|
+
<button tabindex="2">Second in tab order</button>
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<input tabindex="5" type="text">
|
|
46
|
+
|
|
47
|
+
<button tabindex="10">Submit</button>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## References
|
|
51
|
+
|
|
52
|
+
- [HTML: `tabindex` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex)
|
|
53
|
+
- [WebAIM: Keyboard Accessibility](https://webaim.org/techniques/keyboard/tabindex)
|
|
54
|
+
- [WCAG: Focus Order](https://www.w3.org/WAI/WCAG21/Understanding/focus-order.html)
|
|
55
|
+
- [erblint-github: GitHub::Accessibility::NoPositiveTabIndex](https://github.com/github/erblint-github/blob/main/docs/rules/accessibility/no-positive-tab-index.md)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Linter Rule: Disallow self-closing tag syntax for void elements
|
|
2
|
+
|
|
3
|
+
**Rule:** `html-no-self-closing`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Disallow self-closing syntax (`<tag />`) in HTML for all elements.
|
|
8
|
+
|
|
9
|
+
In HTML5, the trailing slash in a start tag is obsolete and has no effect.
|
|
10
|
+
Non-void elements require explicit end tags, and void elements are
|
|
11
|
+
self-contained without the slash.
|
|
12
|
+
|
|
13
|
+
## Rationale
|
|
14
|
+
|
|
15
|
+
Self-closing syntax is an XHTML artifact. In HTML:
|
|
16
|
+
|
|
17
|
+
- On **non-void** elements, it’s a parse error and produces invalid markup
|
|
18
|
+
(`<div />` is invalid).
|
|
19
|
+
- On **void elements**, the slash is ignored and unnecessary (`<input />` is
|
|
20
|
+
equivalent to `<input>`).
|
|
21
|
+
|
|
22
|
+
Removing the slash ensures HTML5-compliant, cleaner markup and avoids mixing
|
|
23
|
+
XHTML and HTML styles.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### ✅ Good
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<span></span>
|
|
31
|
+
<div></div>
|
|
32
|
+
<section></section>
|
|
33
|
+
<custom-element></custom-element>
|
|
34
|
+
|
|
35
|
+
<img src="/logo.png" alt="Logo">
|
|
36
|
+
<input type="text">
|
|
37
|
+
<br>
|
|
38
|
+
<hr>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 🚫 Bad
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<span />
|
|
45
|
+
|
|
46
|
+
<div />
|
|
47
|
+
|
|
48
|
+
<section />
|
|
49
|
+
|
|
50
|
+
<custom-element />
|
|
51
|
+
|
|
52
|
+
<img src="/logo.png" alt="Logo" />
|
|
53
|
+
|
|
54
|
+
<input type="text" />
|
|
55
|
+
|
|
56
|
+
<br />
|
|
57
|
+
|
|
58
|
+
<hr />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## References
|
|
62
|
+
|
|
63
|
+
- [HTML Living Standard: Void Elements](https://html.spec.whatwg.org/multipage/syntax.html#void-elements)
|
|
64
|
+
- [MDN: Void element](https://developer.mozilla.org/en-US/docs/Glossary/Void_element)
|
|
65
|
+
- [erb_lint: SelfClosingTag](https://github.com/Shopify/erb_lint#selfclosingtag)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Linter Rule: Avoid using the `title` attribute
|
|
2
|
+
|
|
3
|
+
**Rule:** `html-no-title-attribute`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Discourage the use of the `title` attribute on most HTML elements, as it provides poor accessibility and user experience. The `title` attribute is only accessible via mouse hover and is not reliably exposed to screen readers or keyboard users.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
The `title` attribute has several accessibility problems:
|
|
12
|
+
- It's only visible on mouse hover, making it inaccessible to keyboard and touch users
|
|
13
|
+
- Screen readers don't consistently announce title attributes
|
|
14
|
+
- Mobile devices don't show title tooltips
|
|
15
|
+
- The visual presentation is inconsistent across browsers and operating systems
|
|
16
|
+
|
|
17
|
+
Instead of relying on `title`, use visible text, `aria-label`, `aria-describedby`, or other accessible alternatives.
|
|
18
|
+
|
|
19
|
+
::: warning Exceptions
|
|
20
|
+
This rule allows `title` on `<iframe>` and `<link>` elements where it serves specific accessibility purposes.
|
|
21
|
+
:::
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
### ✅ Good
|
|
26
|
+
|
|
27
|
+
```erb
|
|
28
|
+
<!-- Use visible text instead of title -->
|
|
29
|
+
<button>Save document</button>
|
|
30
|
+
<span class="help-text">Click to save your changes</span>
|
|
31
|
+
|
|
32
|
+
<!-- Use aria-label for accessible names -->
|
|
33
|
+
<button aria-label="Close dialog">×</button>
|
|
34
|
+
|
|
35
|
+
<!-- Use aria-describedby for additional context -->
|
|
36
|
+
<input type="password" aria-describedby="pwd-help">
|
|
37
|
+
<div id="pwd-help">Password must be at least 8 characters</div>
|
|
38
|
+
|
|
39
|
+
<!-- Exceptions: title allowed on iframe and links -->
|
|
40
|
+
<iframe src="https://example.com" title="Example website content"></iframe>
|
|
41
|
+
<link href="default.css" rel="stylesheet" title="Default Style">
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 🚫 Bad
|
|
45
|
+
|
|
46
|
+
```erb
|
|
47
|
+
<!-- Don't use title for essential information -->
|
|
48
|
+
<button title="Save your changes">Save</button>
|
|
49
|
+
|
|
50
|
+
<div title="This is important information">Content</div>
|
|
51
|
+
|
|
52
|
+
<span title="Required field">*</span>
|
|
53
|
+
|
|
54
|
+
<!-- Don't use title on form elements -->
|
|
55
|
+
<input type="text" title="Enter your name">
|
|
56
|
+
|
|
57
|
+
<select title="Choose your country">
|
|
58
|
+
<option>US</option>
|
|
59
|
+
<option>CA</option>
|
|
60
|
+
</select>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## References
|
|
64
|
+
|
|
65
|
+
- [HTML: `title` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title)
|
|
66
|
+
- [WebAIM: Accessible Forms](https://webaim.org/techniques/forms/)
|
|
67
|
+
- [ARIA: `aria-label` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label)
|
|
68
|
+
- [ARIA: `aria-describedby` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-describedby)
|
|
69
|
+
- [erblint-github: GitHub::Accessibility::NoTitleAttribute](https://github.com/github/erblint-github/blob/main/docs/rules/accessibility/no-title-attribute.md)
|
|
@@ -12,15 +12,28 @@ HTML is case-insensitive for tag names, but lowercase is the widely accepted con
|
|
|
12
12
|
|
|
13
13
|
Writing tags in uppercase or mixed case can lead to inconsistent code and unnecessary diffs during reviews and merges.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Notes
|
|
16
|
+
|
|
17
|
+
::: tip XML Documents
|
|
18
|
+
This rule is automatically disabled for XML documents and XML+ERB templates. XML allows uppercase tag names and follows different naming conventions than HTML.
|
|
19
|
+
|
|
20
|
+
The rule will be disabled when:
|
|
21
|
+
- The document contains an XML declaration (`<?xml version="1.0" ?>`)
|
|
22
|
+
- The file extension is `.xml` or `.xml.erb`
|
|
23
|
+
:::
|
|
16
24
|
|
|
25
|
+
::: tip SVG Elements
|
|
26
|
+
This rule does not apply to child elements within `<svg>` tags, as SVG element names are case-sensitive and may require specific capitalization (e.g., `linearGradient`, `clipPath`). However, the rule still applies to the `<svg>` element itself.
|
|
27
|
+
:::
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
17
30
|
|
|
18
31
|
### ✅ Good
|
|
19
32
|
|
|
20
33
|
```erb
|
|
21
34
|
<div class="container"></div>
|
|
22
35
|
|
|
23
|
-
<input type="text" name="username"
|
|
36
|
+
<input type="text" name="username">
|
|
24
37
|
|
|
25
38
|
<span>Label</span>
|
|
26
39
|
|
|
@@ -32,7 +45,7 @@ Writing tags in uppercase or mixed case can lead to inconsistent code and unnece
|
|
|
32
45
|
```erb
|
|
33
46
|
<DIV class="container"></DIV>
|
|
34
47
|
|
|
35
|
-
<Input type="text" name="username"
|
|
48
|
+
<Input type="text" name="username">
|
|
36
49
|
|
|
37
50
|
<Span>Label</Span>
|
|
38
51
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Linter Rule: Disallow parser errors in HTML+ERB documents
|
|
2
|
+
|
|
3
|
+
**Rule:** `parser-no-errors`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Report parser errors as linting offenses. This rule surfaces syntax errors, malformed HTML, and other parsing issues that prevent the document from being correctly parsed.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
Parser errors indicate fundamental structural problems in HTML+ERB documents that can lead to unexpected rendering behavior, accessibility issues, and maintenance difficulties. These errors should be fixed before addressing other linting concerns as they represent invalid markup that browsers may interpret inconsistently.
|
|
12
|
+
|
|
13
|
+
By surfacing parser errors through the linter, developers can catch these critical issues when running lint checks directly, without needing to switch to the language server or other tools.
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
### ✅ Good
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<h2>Welcome to our site</h2>
|
|
21
|
+
<p>This is a paragraph with proper structure.</p>
|
|
22
|
+
|
|
23
|
+
<div class="container">
|
|
24
|
+
<img src="image.jpg" alt="Description">
|
|
25
|
+
</div>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```erb
|
|
29
|
+
<h2><%= @page.title %></h2>
|
|
30
|
+
<p><%= @page.description %></p>
|
|
31
|
+
|
|
32
|
+
<% if user_signed_in? %>
|
|
33
|
+
<div class="user-section">
|
|
34
|
+
<%= current_user.name %>
|
|
35
|
+
</div>
|
|
36
|
+
<% end %>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 🚫 Bad
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<!-- Mismatched closing tag -->
|
|
43
|
+
<h2>Welcome to our site</h3>
|
|
44
|
+
|
|
45
|
+
<!-- Unclosed element -->
|
|
46
|
+
<div>
|
|
47
|
+
<p>This paragraph is never closed
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<!-- Missing opening tag -->
|
|
51
|
+
Some content
|
|
52
|
+
</div>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```erb
|
|
56
|
+
<!-- Invalid Ruby syntax in ERB -->
|
|
57
|
+
<%= 1 + %>
|
|
58
|
+
|
|
59
|
+
<!-- Mismatched quotes -->
|
|
60
|
+
<div class="container'>Content</div>
|
|
61
|
+
|
|
62
|
+
<!-- Void element with closing tag -->
|
|
63
|
+
<img src="image.jpg" alt="Description"></img>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Error Types
|
|
67
|
+
|
|
68
|
+
This rule reports various parser error types:
|
|
69
|
+
|
|
70
|
+
- **`UNCLOSED_ELEMENT_ERROR`**: Elements that are opened but never closed
|
|
71
|
+
- **`MISSING_CLOSING_TAG_ERROR`**: Opening tags without matching closing tags
|
|
72
|
+
- **`MISSING_OPENING_TAG_ERROR`**: Closing tags without matching opening tags
|
|
73
|
+
- **`TAG_NAMES_MISMATCH_ERROR`**: Opening and closing tags with different names
|
|
74
|
+
- **`QUOTES_MISMATCH_ERROR`**: Mismatched quotation marks in attributes
|
|
75
|
+
- **`VOID_ELEMENT_CLOSING_TAG_ERROR`**: Void elements (like `<img>`) with closing tags
|
|
76
|
+
- **`RUBY_PARSE_ERROR`**: Invalid Ruby syntax within ERB tags
|
|
77
|
+
- **`UNEXPECTED_TOKEN_ERROR`**: Unexpected tokens during parsing
|
|
78
|
+
- **`UNEXPECTED_ERROR`**: Other unexpected parsing issues
|
|
79
|
+
|
|
80
|
+
## References
|
|
81
|
+
|
|
82
|
+
* [HTML Living Standard - Parsing](https://html.spec.whatwg.org/multipage/parsing.html)
|
|
83
|
+
* [W3C HTML Validator](https://validator.w3.org/)
|
|
84
|
+
* [ERB Template Guide](https://guides.rubyonrails.org/layouts_and_rendering.html)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herb-tools/linter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "HTML+ERB linter for validating HTML structure and enforcing best practices",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://herb-tools.dev",
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@herb-tools/core": "0.
|
|
37
|
-
"@herb-tools/highlighter": "0.
|
|
38
|
-
"@herb-tools/node-wasm": "0.
|
|
36
|
+
"@herb-tools/core": "0.6.0",
|
|
37
|
+
"@herb-tools/highlighter": "0.6.0",
|
|
38
|
+
"@herb-tools/node-wasm": "0.6.0",
|
|
39
39
|
"glob": "^11.0.3"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
@@ -11,9 +11,11 @@ import type { ThemeInput } from "@herb-tools/highlighter"
|
|
|
11
11
|
|
|
12
12
|
import { name, version } from "../../package.json"
|
|
13
13
|
|
|
14
|
+
export type FormatOption = "simple" | "detailed" | "json" | "github"
|
|
15
|
+
|
|
14
16
|
export interface ParsedArguments {
|
|
15
17
|
pattern: string
|
|
16
|
-
formatOption:
|
|
18
|
+
formatOption: FormatOption
|
|
17
19
|
showTiming: boolean
|
|
18
20
|
theme: ThemeInput
|
|
19
21
|
wrapLines: boolean
|
|
@@ -32,9 +34,11 @@ export class ArgumentParser {
|
|
|
32
34
|
Options:
|
|
33
35
|
-h, --help show help
|
|
34
36
|
-v, --version show version
|
|
35
|
-
--format output format (simple|detailed) [default: detailed]
|
|
37
|
+
--format output format (simple|detailed|json|github) [default: detailed]
|
|
36
38
|
--simple use simple output format (shortcut for --format simple)
|
|
37
|
-
--
|
|
39
|
+
--json use JSON output format (shortcut for --format json)
|
|
40
|
+
--github use GitHub Actions output format (shortcut for --format github)
|
|
41
|
+
--theme syntax highlighting theme (${THEME_NAMES.join("|")}) or path to custom theme file [default: ${DEFAULT_THEME}]
|
|
38
42
|
--no-color disable colored output
|
|
39
43
|
--no-timing hide timing information
|
|
40
44
|
--no-wrap-lines disable line wrapping
|
|
@@ -45,15 +49,17 @@ export class ArgumentParser {
|
|
|
45
49
|
const { values, positionals } = parseArgs({
|
|
46
50
|
args: argv.slice(2),
|
|
47
51
|
options: {
|
|
48
|
-
help: { type:
|
|
49
|
-
version: { type:
|
|
50
|
-
format: { type:
|
|
51
|
-
simple: { type:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
help: { type: "boolean", short: "h" },
|
|
53
|
+
version: { type: "boolean", short: "v" },
|
|
54
|
+
format: { type: "string" },
|
|
55
|
+
simple: { type: "boolean" },
|
|
56
|
+
json: { type: "boolean" },
|
|
57
|
+
github: { type: "boolean" },
|
|
58
|
+
theme: { type: "string" },
|
|
59
|
+
"no-color": { type: "boolean" },
|
|
60
|
+
"no-timing": { type: "boolean" },
|
|
61
|
+
"no-wrap-lines": { type: "boolean" },
|
|
62
|
+
"truncate-lines": { type: "boolean" }
|
|
57
63
|
},
|
|
58
64
|
allowPositionals: true
|
|
59
65
|
})
|
|
@@ -69,8 +75,8 @@ export class ArgumentParser {
|
|
|
69
75
|
process.exit(0)
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
let formatOption:
|
|
73
|
-
if (values.format && (values.format === "detailed" || values.format === "simple")) {
|
|
78
|
+
let formatOption: FormatOption = "detailed"
|
|
79
|
+
if (values.format && (values.format === "detailed" || values.format === "simple" || values.format === "json" || values.format === "github")) {
|
|
74
80
|
formatOption = values.format
|
|
75
81
|
}
|
|
76
82
|
|
|
@@ -78,21 +84,29 @@ export class ArgumentParser {
|
|
|
78
84
|
formatOption = "simple"
|
|
79
85
|
}
|
|
80
86
|
|
|
81
|
-
if (values
|
|
87
|
+
if (values.json) {
|
|
88
|
+
formatOption = "json"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (values.github) {
|
|
92
|
+
formatOption = "github"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (values["no-color"]) {
|
|
82
96
|
process.env.NO_COLOR = "1"
|
|
83
97
|
}
|
|
84
98
|
|
|
85
|
-
const showTiming = !values[
|
|
99
|
+
const showTiming = !values["no-timing"]
|
|
86
100
|
|
|
87
|
-
let wrapLines = !values[
|
|
101
|
+
let wrapLines = !values["no-wrap-lines"]
|
|
88
102
|
let truncateLines = false
|
|
89
103
|
|
|
90
|
-
if (values[
|
|
104
|
+
if (values["truncate-lines"]) {
|
|
91
105
|
truncateLines = true
|
|
92
106
|
wrapLines = false
|
|
93
107
|
}
|
|
94
108
|
|
|
95
|
-
if (!values[
|
|
109
|
+
if (!values["no-wrap-lines"] && values["truncate-lines"]) {
|
|
96
110
|
console.error("Error: Line wrapping and --truncate-lines cannot be used together. Use --no-wrap-lines with --truncate-lines.")
|
|
97
111
|
process.exit(1)
|
|
98
112
|
}
|
|
@@ -100,11 +114,6 @@ export class ArgumentParser {
|
|
|
100
114
|
const theme = values.theme || DEFAULT_THEME
|
|
101
115
|
const pattern = this.getFilePattern(positionals)
|
|
102
116
|
|
|
103
|
-
if (positionals.length === 0) {
|
|
104
|
-
console.error("Please specify input file.")
|
|
105
|
-
process.exit(1)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
117
|
return { pattern, formatOption, showTiming, theme, wrapLines, truncateLines }
|
|
109
118
|
}
|
|
110
119
|
|