@herb-tools/linter 0.8.9 → 0.9.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 +5 -5
- package/dist/{src/cli → cli}/argument-parser.js +15 -2
- package/dist/cli/argument-parser.js.map +1 -0
- package/dist/{src/cli → cli}/file-processor.js +155 -9
- package/dist/cli/file-processor.js.map +1 -0
- package/dist/cli/file-url.js +6 -0
- package/dist/cli/file-url.js.map +1 -0
- package/dist/cli/formatters/base-formatter.js.map +1 -0
- package/dist/{src/cli → cli}/formatters/detailed-formatter.js +16 -19
- package/dist/cli/formatters/detailed-formatter.js.map +1 -0
- package/dist/cli/formatters/github-actions-formatter.js.map +1 -0
- package/dist/cli/formatters/index.js.map +1 -0
- package/dist/cli/formatters/json-formatter.js.map +1 -0
- package/dist/cli/formatters/simple-formatter.js +54 -0
- package/dist/cli/formatters/simple-formatter.js.map +1 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/lint-worker.js +143 -0
- package/dist/cli/lint-worker.js.map +1 -0
- package/dist/cli/output-manager.js.map +1 -0
- package/dist/{src/cli → cli}/summary-reporter.js +13 -16
- package/dist/cli/summary-reporter.js.map +1 -0
- package/dist/{src/cli.js → cli.js} +5 -3
- package/dist/cli.js.map +1 -0
- package/dist/{src/custom-rule-loader.js → custom-rule-loader.js} +20 -4
- package/dist/custom-rule-loader.js.map +1 -0
- package/dist/herb-disable-comment-utils.js.map +1 -0
- package/dist/herb-lint.js +60648 -17513
- package/dist/herb-lint.js.map +1 -1
- package/dist/index.cjs +2621 -934
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2554 -873
- package/dist/index.js.map +1 -1
- package/dist/lint-worker.js +71462 -0
- package/dist/lint-worker.js.map +1 -0
- package/dist/linter-ignore.js.map +1 -0
- package/dist/{src/linter.js → linter.js} +89 -74
- package/dist/linter.js.map +1 -0
- package/dist/loader.cjs +31206 -7834
- package/dist/loader.cjs.map +1 -1
- package/dist/loader.js +31168 -7802
- package/dist/loader.js.map +1 -1
- package/dist/parse-cache.js +30 -0
- package/dist/parse-cache.js.map +1 -0
- package/dist/rules/actionview-no-silent-helper.js +45 -0
- package/dist/rules/actionview-no-silent-helper.js.map +1 -0
- package/dist/{src/rules → rules}/erb-comment-syntax.js +2 -2
- package/dist/rules/erb-comment-syntax.js.map +1 -0
- package/dist/{src/rules → rules}/erb-no-case-node-children.js +2 -2
- package/dist/rules/erb-no-case-node-children.js.map +1 -0
- package/dist/rules/erb-no-conditional-html-element.js +38 -0
- package/dist/rules/erb-no-conditional-html-element.js.map +1 -0
- package/dist/rules/erb-no-conditional-open-tag.js +24 -0
- package/dist/rules/erb-no-conditional-open-tag.js.map +1 -0
- package/dist/rules/erb-no-duplicate-branch-elements.js +245 -0
- package/dist/rules/erb-no-duplicate-branch-elements.js.map +1 -0
- package/dist/{src/rules → rules}/erb-no-empty-tags.js +2 -2
- package/dist/rules/erb-no-empty-tags.js.map +1 -0
- package/dist/{src/rules → rules}/erb-no-extra-newline.js +4 -21
- package/dist/rules/erb-no-extra-newline.js.map +1 -0
- package/dist/{src/rules → rules}/erb-no-extra-whitespace-inside-tags.js +39 -13
- package/dist/rules/erb-no-extra-whitespace-inside-tags.js.map +1 -0
- package/dist/rules/erb-no-inline-case-conditions.js +40 -0
- package/dist/rules/erb-no-inline-case-conditions.js.map +1 -0
- package/dist/rules/erb-no-instance-variables-in-partials.js +67 -0
- package/dist/rules/erb-no-instance-variables-in-partials.js.map +1 -0
- package/dist/rules/erb-no-interpolated-class-names.js +47 -0
- package/dist/rules/erb-no-interpolated-class-names.js.map +1 -0
- package/dist/rules/erb-no-javascript-tag-helper.js +34 -0
- package/dist/rules/erb-no-javascript-tag-helper.js.map +1 -0
- package/dist/{src/rules → rules}/erb-no-output-control-flow.js +9 -12
- package/dist/rules/erb-no-output-control-flow.js.map +1 -0
- package/dist/rules/erb-no-output-in-attribute-name.js +30 -0
- package/dist/rules/erb-no-output-in-attribute-name.js.map +1 -0
- package/dist/rules/erb-no-output-in-attribute-position.js +30 -0
- package/dist/rules/erb-no-output-in-attribute-position.js.map +1 -0
- package/dist/rules/erb-no-raw-output-in-attribute-value.js +35 -0
- package/dist/rules/erb-no-raw-output-in-attribute-value.js.map +1 -0
- package/dist/{src/rules → rules}/erb-no-silent-tag-in-attribute-name.js +2 -2
- package/dist/rules/erb-no-silent-tag-in-attribute-name.js.map +1 -0
- package/dist/rules/erb-no-statement-in-script.js +58 -0
- package/dist/rules/erb-no-statement-in-script.js.map +1 -0
- package/dist/rules/erb-no-then-in-control-flow.js +45 -0
- package/dist/rules/erb-no-then-in-control-flow.js.map +1 -0
- package/dist/rules/erb-no-trailing-whitespace.js +138 -0
- package/dist/rules/erb-no-trailing-whitespace.js.map +1 -0
- package/dist/rules/erb-no-unsafe-js-attribute.js +36 -0
- package/dist/rules/erb-no-unsafe-js-attribute.js.map +1 -0
- package/dist/rules/erb-no-unsafe-raw.js +63 -0
- package/dist/rules/erb-no-unsafe-raw.js.map +1 -0
- package/dist/rules/erb-no-unsafe-script-interpolation.js +54 -0
- package/dist/rules/erb-no-unsafe-script-interpolation.js.map +1 -0
- package/dist/{src/rules → rules}/erb-prefer-image-tag-helper.js +5 -4
- package/dist/rules/erb-prefer-image-tag-helper.js.map +1 -0
- package/dist/{src/rules → rules}/erb-require-trailing-newline.js +2 -2
- package/dist/rules/erb-require-trailing-newline.js.map +1 -0
- package/dist/{src/rules → rules}/erb-require-whitespace-inside-tags.js +39 -15
- package/dist/rules/erb-require-whitespace-inside-tags.js.map +1 -0
- package/dist/{src/rules → rules}/erb-right-trim.js +2 -2
- package/dist/rules/erb-right-trim.js.map +1 -0
- package/dist/{src/rules → rules}/erb-strict-locals-comment-syntax.js +5 -5
- package/dist/rules/erb-strict-locals-comment-syntax.js.map +1 -0
- package/dist/{src/rules → rules}/erb-strict-locals-required.js +2 -2
- package/dist/rules/erb-strict-locals-required.js.map +1 -0
- package/dist/rules/file-utils.js.map +1 -0
- package/dist/rules/herb-disable-comment-base.js.map +1 -0
- package/dist/{src/rules → rules}/herb-disable-comment-malformed.js +2 -2
- package/dist/rules/herb-disable-comment-malformed.js.map +1 -0
- package/dist/{src/rules → rules}/herb-disable-comment-missing-rules.js +2 -2
- package/dist/rules/herb-disable-comment-missing-rules.js.map +1 -0
- package/dist/{src/rules → rules}/herb-disable-comment-no-duplicate-rules.js +2 -2
- package/dist/rules/herb-disable-comment-no-duplicate-rules.js.map +1 -0
- package/dist/{src/rules → rules}/herb-disable-comment-no-redundant-all.js +2 -2
- package/dist/rules/herb-disable-comment-no-redundant-all.js.map +1 -0
- package/dist/{src/rules → rules}/herb-disable-comment-unnecessary.js +2 -2
- package/dist/rules/herb-disable-comment-unnecessary.js.map +1 -0
- package/dist/{src/rules → rules}/herb-disable-comment-valid-rule-name.js +2 -2
- package/dist/rules/herb-disable-comment-valid-rule-name.js.map +1 -0
- package/dist/rules/html-allowed-script-type.js +57 -0
- package/dist/rules/html-allowed-script-type.js.map +1 -0
- package/dist/rules/html-anchor-require-href.js +68 -0
- package/dist/rules/html-anchor-require-href.js.map +1 -0
- package/dist/{src/rules → rules}/html-aria-attribute-must-be-valid.js +3 -3
- package/dist/rules/html-aria-attribute-must-be-valid.js.map +1 -0
- package/dist/{src/rules → rules}/html-aria-label-is-well-formatted.js +3 -3
- package/dist/rules/html-aria-label-is-well-formatted.js.map +1 -0
- package/dist/{src/rules → rules}/html-aria-level-must-be-valid.js +3 -3
- package/dist/rules/html-aria-level-must-be-valid.js.map +1 -0
- package/dist/{src/rules → rules}/html-aria-role-heading-requires-level.js +5 -4
- package/dist/rules/html-aria-role-heading-requires-level.js.map +1 -0
- package/dist/{src/rules → rules}/html-aria-role-must-be-valid.js +3 -3
- package/dist/rules/html-aria-role-must-be-valid.js.map +1 -0
- package/dist/{src/rules → rules}/html-attribute-double-quotes.js +4 -4
- package/dist/rules/html-attribute-double-quotes.js.map +1 -0
- package/dist/{src/rules → rules}/html-attribute-equals-spacing.js +2 -2
- package/dist/rules/html-attribute-equals-spacing.js.map +1 -0
- package/dist/{src/rules → rules}/html-attribute-values-require-quotes.js +2 -2
- package/dist/rules/html-attribute-values-require-quotes.js.map +1 -0
- package/dist/{src/rules → rules}/html-avoid-both-disabled-and-aria-disabled.js +9 -9
- package/dist/rules/html-avoid-both-disabled-and-aria-disabled.js.map +1 -0
- package/dist/{src/rules → rules}/html-body-only-elements.js +5 -4
- package/dist/rules/html-body-only-elements.js.map +1 -0
- package/dist/{src/rules → rules}/html-boolean-attributes-no-value.js +4 -3
- package/dist/rules/html-boolean-attributes-no-value.js.map +1 -0
- package/dist/rules/html-details-has-summary.js +52 -0
- package/dist/rules/html-details-has-summary.js.map +1 -0
- package/dist/{src/rules → rules}/html-head-only-elements.js +6 -5
- package/dist/rules/html-head-only-elements.js.map +1 -0
- package/dist/{src/rules → rules}/html-iframe-has-title.js +8 -11
- package/dist/rules/html-iframe-has-title.js.map +1 -0
- package/dist/{src/rules → rules}/html-img-require-alt.js +11 -5
- package/dist/rules/html-img-require-alt.js.map +1 -0
- package/dist/{src/rules → rules}/html-input-require-autocomplete.js +7 -10
- package/dist/rules/html-input-require-autocomplete.js.map +1 -0
- package/dist/{src/rules → rules}/html-navigation-has-label.js +6 -5
- package/dist/rules/html-navigation-has-label.js.map +1 -0
- package/dist/rules/html-no-abstract-roles.js +29 -0
- package/dist/rules/html-no-abstract-roles.js.map +1 -0
- package/dist/rules/html-no-aria-hidden-on-body.js +42 -0
- package/dist/rules/html-no-aria-hidden-on-body.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-aria-hidden-on-focusable.js +6 -5
- package/dist/rules/html-no-aria-hidden-on-focusable.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-block-inside-inline.js +6 -9
- package/dist/rules/html-no-block-inside-inline.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-duplicate-attributes.js +4 -3
- package/dist/rules/html-no-duplicate-attributes.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-duplicate-ids.js +14 -11
- package/dist/rules/html-no-duplicate-ids.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-duplicate-meta-names.js +22 -20
- package/dist/rules/html-no-duplicate-meta-names.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-empty-attributes.js +2 -2
- package/dist/rules/html-no-empty-attributes.js.map +1 -0
- package/dist/rules/html-no-empty-headings.js +98 -0
- package/dist/rules/html-no-empty-headings.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-nested-links.js +23 -15
- package/dist/rules/html-no-nested-links.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-positive-tab-index.js +3 -3
- package/dist/rules/html-no-positive-tab-index.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-self-closing.js +4 -4
- package/dist/rules/html-no-self-closing.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-space-in-tag.js +4 -6
- package/dist/rules/html-no-space-in-tag.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-title-attribute.js +6 -5
- package/dist/rules/html-no-title-attribute.js.map +1 -0
- package/dist/{src/rules → rules}/html-no-underscores-in-attribute-names.js +2 -2
- package/dist/rules/html-no-underscores-in-attribute-names.js.map +1 -0
- package/dist/rules/html-require-closing-tags.js +29 -0
- package/dist/rules/html-require-closing-tags.js.map +1 -0
- package/dist/{src/rules → rules}/html-tag-name-lowercase.js +13 -9
- package/dist/rules/html-tag-name-lowercase.js.map +1 -0
- package/dist/{src/rules → rules}/index.js +19 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/{src/rules → rules}/parser-no-errors.js +3 -3
- package/dist/rules/parser-no-errors.js.map +1 -0
- package/dist/{src/rules → rules}/rule-utils.js +141 -219
- package/dist/rules/rule-utils.js.map +1 -0
- package/dist/rules/string-utils.js.map +1 -0
- package/dist/{src/rules → rules}/svg-tag-name-capitalization.js +7 -6
- package/dist/rules/svg-tag-name-capitalization.js.map +1 -0
- package/dist/rules/turbo-permanent-require-id.js +34 -0
- package/dist/rules/turbo-permanent-require-id.js.map +1 -0
- package/dist/{src/rules.js → rules.js} +56 -10
- package/dist/rules.js.map +1 -0
- package/dist/types/cli/argument-parser.d.ts +1 -0
- package/dist/types/cli/file-processor.d.ts +13 -0
- package/dist/types/cli/file-url.d.ts +1 -0
- package/dist/types/cli/index.d.ts +1 -0
- package/dist/types/cli/lint-worker.d.ts +34 -0
- package/dist/types/custom-rule-loader.d.ts +4 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/linter.d.ts +13 -6
- package/dist/types/parse-cache.d.ts +9 -0
- package/dist/types/{src/rules/html-aria-level-must-be-valid.d.ts → rules/actionview-no-silent-helper.d.ts} +4 -3
- package/dist/types/rules/erb-comment-syntax.d.ts +1 -1
- package/dist/types/rules/erb-no-case-node-children.d.ts +1 -1
- package/dist/types/{src/rules/herb-disable-comment-malformed.d.ts → rules/erb-no-conditional-html-element.d.ts} +3 -3
- package/dist/types/{src/rules/erb-prefer-image-tag-helper.d.ts → rules/erb-no-conditional-open-tag.d.ts} +3 -3
- package/dist/types/rules/erb-no-duplicate-branch-elements.d.ts +17 -0
- package/dist/types/rules/erb-no-empty-tags.d.ts +1 -1
- package/dist/types/rules/erb-no-extra-newline.d.ts +1 -1
- package/dist/types/rules/erb-no-extra-whitespace-inside-tags.d.ts +1 -1
- package/dist/types/{src/rules/html-no-duplicate-attributes.d.ts → rules/erb-no-inline-case-conditions.d.ts} +4 -3
- package/dist/types/rules/erb-no-instance-variables-in-partials.d.ts +10 -0
- package/dist/types/{src/rules/html-no-aria-hidden-on-focusable.d.ts → rules/erb-no-interpolated-class-names.d.ts} +2 -2
- package/dist/types/{src/rules/html-aria-attribute-must-be-valid.d.ts → rules/erb-no-javascript-tag-helper.d.ts} +2 -2
- package/dist/types/rules/erb-no-output-control-flow.d.ts +1 -1
- package/dist/types/{src/rules/erb-no-silent-tag-in-attribute-name.d.ts → rules/erb-no-output-in-attribute-name.d.ts} +2 -2
- package/dist/types/{src/rules/herb-disable-comment-missing-rules.d.ts → rules/erb-no-output-in-attribute-position.d.ts} +2 -2
- package/dist/types/{src/rules/erb-no-empty-tags.d.ts → rules/erb-no-raw-output-in-attribute-value.d.ts} +2 -2
- package/dist/types/rules/erb-no-silent-tag-in-attribute-name.d.ts +1 -1
- package/dist/types/{src/rules/html-navigation-has-label.d.ts → rules/erb-no-statement-in-script.d.ts} +2 -2
- package/dist/types/rules/erb-no-then-in-control-flow.d.ts +9 -0
- package/dist/types/rules/erb-no-trailing-whitespace.d.ts +19 -0
- package/dist/types/{src/rules/html-no-positive-tab-index.d.ts → rules/erb-no-unsafe-js-attribute.d.ts} +2 -2
- package/dist/types/{src/rules/erb-no-case-node-children.d.ts → rules/erb-no-unsafe-raw.d.ts} +2 -2
- package/dist/types/rules/erb-no-unsafe-script-interpolation.d.ts +8 -0
- package/dist/types/rules/erb-prefer-image-tag-helper.d.ts +1 -1
- package/dist/types/rules/erb-require-trailing-newline.d.ts +1 -1
- package/dist/types/rules/erb-require-whitespace-inside-tags.d.ts +1 -1
- package/dist/types/rules/erb-right-trim.d.ts +1 -1
- package/dist/types/rules/erb-strict-locals-comment-syntax.d.ts +1 -1
- package/dist/types/rules/erb-strict-locals-required.d.ts +1 -1
- package/dist/types/rules/herb-disable-comment-malformed.d.ts +1 -1
- package/dist/types/rules/herb-disable-comment-missing-rules.d.ts +1 -1
- package/dist/types/rules/herb-disable-comment-no-duplicate-rules.d.ts +1 -1
- package/dist/types/rules/herb-disable-comment-no-redundant-all.d.ts +1 -1
- package/dist/types/rules/herb-disable-comment-unnecessary.d.ts +1 -1
- package/dist/types/rules/herb-disable-comment-valid-rule-name.d.ts +1 -1
- package/dist/types/{src/rules/html-anchor-require-href.d.ts → rules/html-allowed-script-type.d.ts} +2 -2
- package/dist/types/rules/html-anchor-require-href.d.ts +3 -2
- package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +1 -1
- package/dist/types/rules/html-aria-label-is-well-formatted.d.ts +1 -1
- package/dist/types/rules/html-aria-level-must-be-valid.d.ts +1 -1
- package/dist/types/rules/html-aria-role-heading-requires-level.d.ts +1 -1
- package/dist/types/rules/html-aria-role-must-be-valid.d.ts +1 -1
- package/dist/types/rules/html-attribute-double-quotes.d.ts +1 -1
- package/dist/types/rules/html-attribute-equals-spacing.d.ts +1 -1
- package/dist/types/rules/html-attribute-values-require-quotes.d.ts +1 -1
- package/dist/types/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +1 -1
- package/dist/types/rules/html-body-only-elements.d.ts +1 -1
- package/dist/types/rules/html-boolean-attributes-no-value.d.ts +1 -1
- package/dist/types/{src/rules/html-no-empty-attributes.d.ts → rules/html-details-has-summary.d.ts} +4 -3
- package/dist/types/rules/html-head-only-elements.d.ts +1 -1
- package/dist/types/rules/html-iframe-has-title.d.ts +1 -1
- package/dist/types/rules/html-img-require-alt.d.ts +1 -1
- package/dist/types/rules/html-input-require-autocomplete.d.ts +1 -1
- package/dist/types/rules/html-navigation-has-label.d.ts +1 -1
- package/dist/types/{src/rules/html-no-empty-headings.d.ts → rules/html-no-abstract-roles.d.ts} +2 -2
- package/dist/types/{src/rules/erb-no-output-control-flow.d.ts → rules/html-no-aria-hidden-on-body.d.ts} +3 -3
- package/dist/types/rules/html-no-aria-hidden-on-focusable.d.ts +1 -1
- package/dist/types/rules/html-no-block-inside-inline.d.ts +1 -1
- package/dist/types/rules/html-no-duplicate-attributes.d.ts +1 -1
- package/dist/types/rules/html-no-duplicate-ids.d.ts +1 -1
- package/dist/types/rules/html-no-duplicate-meta-names.d.ts +1 -1
- package/dist/types/rules/html-no-empty-attributes.d.ts +1 -1
- package/dist/types/rules/html-no-empty-headings.d.ts +1 -1
- package/dist/types/rules/html-no-nested-links.d.ts +1 -1
- package/dist/types/rules/html-no-positive-tab-index.d.ts +1 -1
- package/dist/types/rules/html-no-self-closing.d.ts +1 -1
- package/dist/types/rules/html-no-space-in-tag.d.ts +1 -1
- package/dist/types/rules/html-no-title-attribute.d.ts +1 -1
- package/dist/types/rules/html-no-underscores-in-attribute-names.d.ts +1 -1
- package/dist/types/{src/rules/html-body-only-elements.d.ts → rules/html-require-closing-tags.d.ts} +4 -3
- package/dist/types/rules/html-tag-name-lowercase.d.ts +1 -1
- package/dist/types/rules/index.d.ts +19 -0
- package/dist/types/rules/parser-no-errors.d.ts +1 -1
- package/dist/types/rules/rule-utils.d.ts +35 -88
- package/dist/types/rules/svg-tag-name-capitalization.d.ts +1 -1
- package/dist/types/{src/rules/html-aria-role-must-be-valid.d.ts → rules/turbo-permanent-require-id.d.ts} +2 -2
- package/dist/types/types.d.ts +25 -7
- package/dist/types/urls.d.ts +1 -0
- package/dist/{src/types.js → types.js} +53 -0
- package/dist/types.js.map +1 -0
- package/dist/urls.js +5 -0
- package/dist/urls.js.map +1 -0
- package/docs/rules/README.md +23 -2
- package/docs/rules/actionview-no-silent-helper.md +57 -0
- package/docs/rules/erb-no-conditional-html-element.md +90 -0
- package/docs/rules/erb-no-conditional-open-tag.md +130 -0
- package/docs/rules/erb-no-duplicate-branch-elements.md +98 -0
- package/docs/rules/erb-no-inline-case-conditions.md +85 -0
- package/docs/rules/erb-no-instance-variables-in-partials.md +43 -0
- package/docs/rules/erb-no-interpolated-class-names.md +57 -0
- package/docs/rules/erb-no-javascript-tag-helper.md +33 -0
- package/docs/rules/erb-no-output-in-attribute-name.md +38 -0
- package/docs/rules/erb-no-output-in-attribute-position.md +60 -0
- package/docs/rules/erb-no-raw-output-in-attribute-value.md +37 -0
- package/docs/rules/erb-no-statement-in-script.md +68 -0
- package/docs/rules/erb-no-then-in-control-flow.md +86 -0
- package/docs/rules/erb-no-trailing-whitespace.md +69 -0
- package/docs/rules/erb-no-unsafe-js-attribute.md +41 -0
- package/docs/rules/erb-no-unsafe-raw.md +47 -0
- package/docs/rules/erb-no-unsafe-script-interpolation.md +73 -0
- package/docs/rules/html-allowed-script-type.md +59 -0
- package/docs/rules/html-anchor-require-href.md +19 -6
- package/docs/rules/html-details-has-summary.md +46 -0
- package/docs/rules/html-img-require-alt.md +5 -3
- package/docs/rules/html-no-abstract-roles.md +74 -0
- package/docs/rules/html-no-aria-hidden-on-body.md +44 -0
- package/docs/rules/html-require-closing-tags.md +142 -0
- package/docs/rules/parser-no-errors.md +4 -17
- package/docs/rules/turbo-permanent-require-id.md +41 -0
- package/package.json +12 -11
- package/src/cli/argument-parser.ts +20 -2
- package/src/cli/file-processor.ts +189 -10
- package/src/cli/file-url.ts +6 -0
- package/src/cli/formatters/detailed-formatter.ts +19 -21
- package/src/cli/formatters/simple-formatter.ts +23 -13
- package/src/cli/index.ts +2 -0
- package/src/cli/lint-worker.ts +208 -0
- package/src/cli/summary-reporter.ts +14 -15
- package/src/cli.ts +5 -3
- package/src/custom-rule-loader.ts +20 -5
- package/src/herb-disable-comment-utils.ts +0 -3
- package/src/index.ts +1 -0
- package/src/linter.ts +98 -79
- package/src/parse-cache.ts +39 -0
- package/src/rules/actionview-no-silent-helper.ts +58 -0
- package/src/rules/erb-comment-syntax.ts +2 -2
- package/src/rules/erb-no-case-node-children.ts +2 -2
- package/src/rules/erb-no-conditional-html-element.ts +53 -0
- package/src/rules/erb-no-conditional-open-tag.ts +37 -0
- package/src/rules/erb-no-duplicate-branch-elements.ts +320 -0
- package/src/rules/erb-no-empty-tags.ts +2 -2
- package/src/rules/erb-no-extra-newline.ts +5 -25
- package/src/rules/erb-no-extra-whitespace-inside-tags.ts +45 -15
- package/src/rules/erb-no-inline-case-conditions.ts +54 -0
- package/src/rules/erb-no-instance-variables-in-partials.ts +101 -0
- package/src/rules/erb-no-interpolated-class-names.ts +65 -0
- package/src/rules/erb-no-javascript-tag-helper.ts +47 -0
- package/src/rules/erb-no-output-control-flow.ts +10 -10
- package/src/rules/erb-no-output-in-attribute-name.ts +39 -0
- package/src/rules/erb-no-output-in-attribute-position.ts +39 -0
- package/src/rules/erb-no-raw-output-in-attribute-value.ts +47 -0
- package/src/rules/erb-no-silent-tag-in-attribute-name.ts +2 -2
- package/src/rules/erb-no-statement-in-script.ts +82 -0
- package/src/rules/erb-no-then-in-control-flow.ts +62 -0
- package/src/rules/erb-no-trailing-whitespace.ts +187 -0
- package/src/rules/erb-no-unsafe-js-attribute.ts +47 -0
- package/src/rules/erb-no-unsafe-raw.ts +83 -0
- package/src/rules/erb-no-unsafe-script-interpolation.ts +76 -0
- package/src/rules/erb-prefer-image-tag-helper.ts +5 -4
- package/src/rules/erb-require-trailing-newline.ts +2 -2
- package/src/rules/erb-require-whitespace-inside-tags.ts +42 -18
- package/src/rules/erb-right-trim.ts +2 -2
- package/src/rules/erb-strict-locals-comment-syntax.ts +5 -5
- package/src/rules/erb-strict-locals-required.ts +2 -2
- package/src/rules/herb-disable-comment-malformed.ts +2 -2
- package/src/rules/herb-disable-comment-missing-rules.ts +2 -2
- package/src/rules/herb-disable-comment-no-duplicate-rules.ts +2 -2
- package/src/rules/herb-disable-comment-no-redundant-all.ts +2 -2
- package/src/rules/herb-disable-comment-unnecessary.ts +2 -2
- package/src/rules/herb-disable-comment-valid-rule-name.ts +2 -2
- package/src/rules/html-allowed-script-type.ts +84 -0
- package/src/rules/html-anchor-require-href.ts +73 -11
- package/src/rules/html-aria-attribute-must-be-valid.ts +3 -3
- package/src/rules/html-aria-label-is-well-formatted.ts +3 -3
- package/src/rules/html-aria-level-must-be-valid.ts +3 -3
- package/src/rules/html-aria-role-heading-requires-level.ts +5 -4
- package/src/rules/html-aria-role-must-be-valid.ts +3 -3
- package/src/rules/html-attribute-double-quotes.ts +4 -4
- package/src/rules/html-attribute-equals-spacing.ts +2 -2
- package/src/rules/html-attribute-values-require-quotes.ts +2 -2
- package/src/rules/html-avoid-both-disabled-and-aria-disabled.ts +10 -11
- package/src/rules/html-body-only-elements.ts +5 -4
- package/src/rules/html-boolean-attributes-no-value.ts +4 -3
- package/src/rules/html-details-has-summary.ts +69 -0
- package/src/rules/html-head-only-elements.ts +6 -5
- package/src/rules/html-iframe-has-title.ts +8 -11
- package/src/rules/html-img-require-alt.ts +16 -5
- package/src/rules/html-input-require-autocomplete.ts +7 -10
- package/src/rules/html-navigation-has-label.ts +6 -5
- package/src/rules/html-no-abstract-roles.ts +40 -0
- package/src/rules/html-no-aria-hidden-on-body.ts +58 -0
- package/src/rules/html-no-aria-hidden-on-focusable.ts +6 -5
- package/src/rules/html-no-block-inside-inline.ts +7 -13
- package/src/rules/html-no-duplicate-attributes.ts +4 -3
- package/src/rules/html-no-duplicate-ids.ts +16 -13
- package/src/rules/html-no-duplicate-meta-names.ts +20 -19
- package/src/rules/html-no-empty-attributes.ts +2 -2
- package/src/rules/html-no-empty-headings.ts +44 -58
- package/src/rules/html-no-nested-links.ts +25 -16
- package/src/rules/html-no-positive-tab-index.ts +3 -3
- package/src/rules/html-no-self-closing.ts +5 -5
- package/src/rules/html-no-space-in-tag.ts +5 -8
- package/src/rules/html-no-title-attribute.ts +6 -5
- package/src/rules/html-no-underscores-in-attribute-names.ts +2 -2
- package/src/rules/html-require-closing-tags.ts +41 -0
- package/src/rules/html-tag-name-lowercase.ts +14 -9
- package/src/rules/index.ts +19 -0
- package/src/rules/parser-no-errors.ts +3 -3
- package/src/rules/rule-utils.ts +162 -279
- package/src/rules/svg-tag-name-capitalization.ts +10 -10
- package/src/rules/turbo-permanent-require-id.ts +49 -0
- package/src/rules.ts +60 -10
- package/src/types.ts +76 -7
- package/src/urls.ts +5 -0
- package/dist/package.json +0 -65
- package/dist/src/cli/argument-parser.js.map +0 -1
- package/dist/src/cli/file-processor.js.map +0 -1
- package/dist/src/cli/formatters/base-formatter.js.map +0 -1
- package/dist/src/cli/formatters/detailed-formatter.js.map +0 -1
- package/dist/src/cli/formatters/github-actions-formatter.js.map +0 -1
- package/dist/src/cli/formatters/index.js.map +0 -1
- package/dist/src/cli/formatters/json-formatter.js.map +0 -1
- package/dist/src/cli/formatters/simple-formatter.js +0 -44
- package/dist/src/cli/formatters/simple-formatter.js.map +0 -1
- package/dist/src/cli/index.js.map +0 -1
- package/dist/src/cli/output-manager.js.map +0 -1
- package/dist/src/cli/summary-reporter.js.map +0 -1
- package/dist/src/cli.js.map +0 -1
- package/dist/src/custom-rule-loader.js.map +0 -1
- package/dist/src/herb-disable-comment-utils.js.map +0 -1
- package/dist/src/herb-lint.js +0 -5
- package/dist/src/herb-lint.js.map +0 -1
- package/dist/src/index.js +0 -5
- package/dist/src/index.js.map +0 -1
- package/dist/src/linter-ignore.js.map +0 -1
- package/dist/src/linter.js.map +0 -1
- package/dist/src/loader.js +0 -17
- package/dist/src/loader.js.map +0 -1
- package/dist/src/rules/erb-comment-syntax.js.map +0 -1
- package/dist/src/rules/erb-no-case-node-children.js.map +0 -1
- package/dist/src/rules/erb-no-empty-tags.js.map +0 -1
- package/dist/src/rules/erb-no-extra-newline.js.map +0 -1
- package/dist/src/rules/erb-no-extra-whitespace-inside-tags.js.map +0 -1
- package/dist/src/rules/erb-no-output-control-flow.js.map +0 -1
- package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js.map +0 -1
- package/dist/src/rules/erb-prefer-image-tag-helper.js.map +0 -1
- package/dist/src/rules/erb-require-trailing-newline.js.map +0 -1
- package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +0 -1
- package/dist/src/rules/erb-right-trim.js.map +0 -1
- package/dist/src/rules/erb-strict-locals-comment-syntax.js.map +0 -1
- package/dist/src/rules/erb-strict-locals-required.js.map +0 -1
- package/dist/src/rules/file-utils.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-base.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-malformed.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-missing-rules.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-no-duplicate-rules.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-no-redundant-all.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-unnecessary.js.map +0 -1
- package/dist/src/rules/herb-disable-comment-valid-rule-name.js.map +0 -1
- package/dist/src/rules/html-anchor-require-href.js +0 -32
- package/dist/src/rules/html-anchor-require-href.js.map +0 -1
- package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +0 -1
- package/dist/src/rules/html-aria-label-is-well-formatted.js.map +0 -1
- package/dist/src/rules/html-aria-level-must-be-valid.js.map +0 -1
- package/dist/src/rules/html-aria-role-heading-requires-level.js.map +0 -1
- package/dist/src/rules/html-aria-role-must-be-valid.js.map +0 -1
- package/dist/src/rules/html-attribute-double-quotes.js.map +0 -1
- package/dist/src/rules/html-attribute-equals-spacing.js.map +0 -1
- package/dist/src/rules/html-attribute-values-require-quotes.js.map +0 -1
- package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js.map +0 -1
- package/dist/src/rules/html-body-only-elements.js.map +0 -1
- package/dist/src/rules/html-boolean-attributes-no-value.js.map +0 -1
- package/dist/src/rules/html-head-only-elements.js.map +0 -1
- package/dist/src/rules/html-iframe-has-title.js.map +0 -1
- package/dist/src/rules/html-img-require-alt.js.map +0 -1
- package/dist/src/rules/html-input-require-autocomplete.js.map +0 -1
- package/dist/src/rules/html-navigation-has-label.js.map +0 -1
- package/dist/src/rules/html-no-aria-hidden-on-focusable.js.map +0 -1
- package/dist/src/rules/html-no-block-inside-inline.js.map +0 -1
- package/dist/src/rules/html-no-duplicate-attributes.js.map +0 -1
- package/dist/src/rules/html-no-duplicate-ids.js.map +0 -1
- package/dist/src/rules/html-no-duplicate-meta-names.js.map +0 -1
- package/dist/src/rules/html-no-empty-attributes.js.map +0 -1
- package/dist/src/rules/html-no-empty-headings.js +0 -115
- package/dist/src/rules/html-no-empty-headings.js.map +0 -1
- package/dist/src/rules/html-no-nested-links.js.map +0 -1
- package/dist/src/rules/html-no-positive-tab-index.js.map +0 -1
- package/dist/src/rules/html-no-self-closing.js.map +0 -1
- package/dist/src/rules/html-no-space-in-tag.js.map +0 -1
- package/dist/src/rules/html-no-title-attribute.js.map +0 -1
- package/dist/src/rules/html-no-underscores-in-attribute-names.js.map +0 -1
- package/dist/src/rules/html-tag-name-lowercase.js.map +0 -1
- package/dist/src/rules/index.js.map +0 -1
- package/dist/src/rules/parser-no-errors.js.map +0 -1
- package/dist/src/rules/rule-utils.js.map +0 -1
- package/dist/src/rules/string-utils.js.map +0 -1
- package/dist/src/rules/svg-tag-name-capitalization.js.map +0 -1
- package/dist/src/rules.js.map +0 -1
- package/dist/src/types.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/types/src/cli/argument-parser.d.ts +0 -25
- package/dist/types/src/cli/file-processor.d.ts +0 -43
- package/dist/types/src/cli/formatters/base-formatter.d.ts +0 -6
- package/dist/types/src/cli/formatters/detailed-formatter.d.ts +0 -13
- package/dist/types/src/cli/formatters/github-actions-formatter.d.ts +0 -17
- package/dist/types/src/cli/formatters/index.d.ts +0 -5
- package/dist/types/src/cli/formatters/json-formatter.d.ts +0 -48
- package/dist/types/src/cli/formatters/simple-formatter.d.ts +0 -8
- package/dist/types/src/cli/index.d.ts +0 -5
- package/dist/types/src/cli/output-manager.d.ts +0 -32
- package/dist/types/src/cli/summary-reporter.d.ts +0 -28
- package/dist/types/src/cli.d.ts +0 -28
- package/dist/types/src/custom-rule-loader.d.ts +0 -62
- package/dist/types/src/herb-disable-comment-utils.d.ts +0 -69
- package/dist/types/src/herb-lint.d.ts +0 -2
- package/dist/types/src/index.d.ts +0 -4
- package/dist/types/src/linter-ignore.d.ts +0 -12
- package/dist/types/src/linter.d.ts +0 -133
- package/dist/types/src/loader.d.ts +0 -20
- package/dist/types/src/rules/erb-comment-syntax.d.ts +0 -14
- package/dist/types/src/rules/erb-no-extra-newline.d.ts +0 -14
- package/dist/types/src/rules/erb-no-extra-whitespace-inside-tags.d.ts +0 -18
- package/dist/types/src/rules/erb-require-trailing-newline.d.ts +0 -9
- package/dist/types/src/rules/erb-require-whitespace-inside-tags.d.ts +0 -18
- package/dist/types/src/rules/erb-right-trim.d.ts +0 -14
- package/dist/types/src/rules/erb-strict-locals-comment-syntax.d.ts +0 -9
- package/dist/types/src/rules/erb-strict-locals-required.d.ts +0 -9
- package/dist/types/src/rules/file-utils.d.ts +0 -13
- package/dist/types/src/rules/herb-disable-comment-base.d.ts +0 -37
- package/dist/types/src/rules/herb-disable-comment-no-duplicate-rules.d.ts +0 -8
- package/dist/types/src/rules/herb-disable-comment-no-redundant-all.d.ts +0 -8
- package/dist/types/src/rules/herb-disable-comment-unnecessary.d.ts +0 -8
- package/dist/types/src/rules/herb-disable-comment-valid-rule-name.d.ts +0 -8
- package/dist/types/src/rules/html-aria-label-is-well-formatted.d.ts +0 -8
- package/dist/types/src/rules/html-aria-role-heading-requires-level.d.ts +0 -8
- package/dist/types/src/rules/html-attribute-double-quotes.d.ts +0 -15
- package/dist/types/src/rules/html-attribute-equals-spacing.d.ts +0 -14
- package/dist/types/src/rules/html-attribute-values-require-quotes.d.ts +0 -15
- package/dist/types/src/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +0 -8
- package/dist/types/src/rules/html-boolean-attributes-no-value.d.ts +0 -14
- package/dist/types/src/rules/html-head-only-elements.d.ts +0 -9
- package/dist/types/src/rules/html-iframe-has-title.d.ts +0 -8
- package/dist/types/src/rules/html-img-require-alt.d.ts +0 -8
- package/dist/types/src/rules/html-input-require-autocomplete.d.ts +0 -8
- package/dist/types/src/rules/html-no-block-inside-inline.d.ts +0 -8
- package/dist/types/src/rules/html-no-duplicate-ids.d.ts +0 -8
- package/dist/types/src/rules/html-no-duplicate-meta-names.d.ts +0 -9
- package/dist/types/src/rules/html-no-nested-links.d.ts +0 -8
- package/dist/types/src/rules/html-no-self-closing.d.ts +0 -16
- package/dist/types/src/rules/html-no-space-in-tag.d.ts +0 -16
- package/dist/types/src/rules/html-no-title-attribute.d.ts +0 -8
- package/dist/types/src/rules/html-no-underscores-in-attribute-names.d.ts +0 -8
- package/dist/types/src/rules/html-tag-name-lowercase.d.ts +0 -18
- package/dist/types/src/rules/index.d.ts +0 -54
- package/dist/types/src/rules/parser-no-errors.d.ts +0 -9
- package/dist/types/src/rules/rule-utils.d.ts +0 -351
- package/dist/types/src/rules/string-utils.d.ts +0 -15
- package/dist/types/src/rules/svg-tag-name-capitalization.d.ts +0 -16
- package/dist/types/src/rules.d.ts +0 -2
- package/dist/types/src/types.d.ts +0 -190
- /package/dist/{src/cli → cli}/formatters/base-formatter.js +0 -0
- /package/dist/{src/cli → cli}/formatters/github-actions-formatter.js +0 -0
- /package/dist/{src/cli → cli}/formatters/index.js +0 -0
- /package/dist/{src/cli → cli}/formatters/json-formatter.js +0 -0
- /package/dist/{src/cli → cli}/index.js +0 -0
- /package/dist/{src/cli → cli}/output-manager.js +0 -0
- /package/dist/{src/herb-disable-comment-utils.js → herb-disable-comment-utils.js} +0 -0
- /package/dist/{src/linter-ignore.js → linter-ignore.js} +0 -0
- /package/dist/{src/rules → rules}/file-utils.js +0 -0
- /package/dist/{src/rules → rules}/herb-disable-comment-base.js +0 -0
- /package/dist/{src/rules → rules}/string-utils.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Visitor, Location } from "@herb-tools/core";
|
|
2
|
-
import type { HTMLAttributeNode,
|
|
1
|
+
import { Visitor, Location, Position } from "@herb-tools/core";
|
|
2
|
+
import type { HTMLAttributeNode, HTMLOpenTagNode, LexResult, Token, Node } from "@herb-tools/core";
|
|
3
3
|
import type * as Nodes from "@herb-tools/core";
|
|
4
|
-
import type { UnboundLintOffense, LintContext, BaseAutofixContext } from "../types.js";
|
|
4
|
+
import type { UnboundLintOffense, LintContext, LintSeverity, BaseAutofixContext } from "../types.js";
|
|
5
5
|
export declare enum ControlFlowType {
|
|
6
6
|
CONDITIONAL = 0,
|
|
7
7
|
LOOP = 1
|
|
@@ -18,11 +18,11 @@ export declare abstract class BaseRuleVisitor<TAutofixContext extends BaseAutofi
|
|
|
18
18
|
* Helper method to create an unbound lint offense (without severity).
|
|
19
19
|
* The Linter will bind severity based on the rule's config.
|
|
20
20
|
*/
|
|
21
|
-
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext): UnboundLintOffense<TAutofixContext>;
|
|
21
|
+
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): UnboundLintOffense<TAutofixContext>;
|
|
22
22
|
/**
|
|
23
23
|
* Helper method to add an offense to the offenses array
|
|
24
24
|
*/
|
|
25
|
-
protected addOffense(message: string, location: Location, autofixContext?: TAutofixContext): void;
|
|
25
|
+
protected addOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): void;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* Mixin that adds control flow tracking capabilities to rule visitors
|
|
@@ -59,77 +59,6 @@ export declare abstract class ControlFlowTrackingVisitor<TAutofixContext extends
|
|
|
59
59
|
protected abstract onEnterBranch(): TBranchState;
|
|
60
60
|
protected abstract onExitBranch(stateToRestore: TBranchState): void;
|
|
61
61
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Gets attributes from an HTMLOpenTagNode
|
|
64
|
-
*/
|
|
65
|
-
export declare function getAttributes(node: HTMLOpenTagNode): HTMLAttributeNode[];
|
|
66
|
-
/**
|
|
67
|
-
* Gets the tag name from an HTML tag node (lowercased)
|
|
68
|
-
*/
|
|
69
|
-
export declare function getTagName(node: HTMLElementNode | HTMLOpenTagNode | null | undefined): string | null;
|
|
70
|
-
/**
|
|
71
|
-
* Gets the attribute name from an HTMLAttributeNode (lowercased)
|
|
72
|
-
* Returns null if the attribute name contains dynamic content (ERB)
|
|
73
|
-
*/
|
|
74
|
-
export declare function getAttributeName(attributeNode: HTMLAttributeNode, lowercase?: boolean): string | null;
|
|
75
|
-
/**
|
|
76
|
-
* Checks if an attribute has a dynamic (ERB-containing) name
|
|
77
|
-
*/
|
|
78
|
-
export declare function hasDynamicAttributeName(attributeNode: HTMLAttributeNode): boolean;
|
|
79
|
-
/**
|
|
80
|
-
* Gets the combined string representation of an attribute name (for debugging)
|
|
81
|
-
* This includes both static content and ERB syntax
|
|
82
|
-
*/
|
|
83
|
-
export declare function getCombinedAttributeNameString(attributeNode: HTMLAttributeNode): string;
|
|
84
|
-
/**
|
|
85
|
-
* Checks if an attribute value contains only static content (no ERB)
|
|
86
|
-
*/
|
|
87
|
-
export declare function hasStaticAttributeValue(attributeNode: HTMLAttributeNode): boolean;
|
|
88
|
-
/**
|
|
89
|
-
* Checks if an attribute value contains dynamic content (ERB)
|
|
90
|
-
*/
|
|
91
|
-
export declare function hasDynamicAttributeValue(attributeNode: HTMLAttributeNode): boolean;
|
|
92
|
-
/**
|
|
93
|
-
* Gets the static string value of an attribute (returns null if it contains ERB)
|
|
94
|
-
*/
|
|
95
|
-
export declare function getStaticAttributeValue(attributeNode: HTMLAttributeNode): string | null;
|
|
96
|
-
/**
|
|
97
|
-
* Gets the value nodes array for dynamic inspection
|
|
98
|
-
*/
|
|
99
|
-
export declare function getAttributeValueNodes(attributeNode: HTMLAttributeNode): Node[];
|
|
100
|
-
/**
|
|
101
|
-
* Checks if an attribute value contains any static content (for validation purposes)
|
|
102
|
-
*/
|
|
103
|
-
export declare function hasStaticAttributeValueContent(attributeNode: HTMLAttributeNode): boolean;
|
|
104
|
-
/**
|
|
105
|
-
* Gets the static content of an attribute value (all literal parts combined)
|
|
106
|
-
* Returns the concatenated literal content, or null if no literal nodes exist
|
|
107
|
-
*/
|
|
108
|
-
export declare function getStaticAttributeValueContent(attributeNode: HTMLAttributeNode): string | null;
|
|
109
|
-
/**
|
|
110
|
-
* Gets the attribute value content from an HTMLAttributeValueNode
|
|
111
|
-
*/
|
|
112
|
-
export declare function getAttributeValue(attributeNode: HTMLAttributeNode): string | null;
|
|
113
|
-
/**
|
|
114
|
-
* Checks if an attribute has a value
|
|
115
|
-
*/
|
|
116
|
-
export declare function hasAttributeValue(attributeNode: HTMLAttributeNode): boolean;
|
|
117
|
-
/**
|
|
118
|
-
* Gets the quote type used for an attribute value
|
|
119
|
-
*/
|
|
120
|
-
export declare function getAttributeValueQuoteType(nodeOrAttribute: HTMLAttributeNode | HTMLAttributeValueNode): "single" | "double" | "none" | null;
|
|
121
|
-
/**
|
|
122
|
-
* Finds an attribute by name in a list of attributes
|
|
123
|
-
*/
|
|
124
|
-
export declare function findAttributeByName(attributes: Node[], attributeName: string): HTMLAttributeNode | null;
|
|
125
|
-
/**
|
|
126
|
-
* Checks if a tag has a specific attribute
|
|
127
|
-
*/
|
|
128
|
-
export declare function hasAttribute(node: HTMLOpenTagNode | null | undefined, attributeName: string): boolean;
|
|
129
|
-
/**
|
|
130
|
-
* Checks if a tag has a specific attribute
|
|
131
|
-
*/
|
|
132
|
-
export declare function getAttribute(node: HTMLOpenTagNode, attributeName: string): HTMLAttributeNode | null;
|
|
133
62
|
/**
|
|
134
63
|
* Common HTML element categorization
|
|
135
64
|
*/
|
|
@@ -148,6 +77,12 @@ export declare const SVG_CAMEL_CASE_ELEMENTS: Set<string>;
|
|
|
148
77
|
*/
|
|
149
78
|
export declare const SVG_LOWERCASE_TO_CAMELCASE: Map<string, string>;
|
|
150
79
|
export declare const VALID_ARIA_ROLES: Set<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Abstract ARIA roles used to support the WAI-ARIA Roles Model.
|
|
82
|
+
* Authors MUST NOT use abstract roles in content.
|
|
83
|
+
* @see https://www.w3.org/TR/wai-aria-1.0/roles#abstract_roles
|
|
84
|
+
*/
|
|
85
|
+
export declare const ABSTRACT_ARIA_ROLES: Set<string>;
|
|
151
86
|
/**
|
|
152
87
|
* Parameter types for AttributeVisitorMixin methods
|
|
153
88
|
*/
|
|
@@ -233,14 +168,6 @@ export declare abstract class AttributeVisitorMixin<TAutofixContext extends Base
|
|
|
233
168
|
*/
|
|
234
169
|
protected checkDynamicAttributeDynamicValue(_params: DynamicAttributeDynamicValueParams): void;
|
|
235
170
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Checks if an attribute value is quoted
|
|
238
|
-
*/
|
|
239
|
-
export declare function isAttributeValueQuoted(attributeNode: HTMLAttributeNode): boolean;
|
|
240
|
-
/**
|
|
241
|
-
* Iterates over all attributes of a tag node, calling the callback for each attribute
|
|
242
|
-
*/
|
|
243
|
-
export declare function forEachAttribute(node: HTMLOpenTagNode, callback: (attributeNode: HTMLAttributeNode) => void): void;
|
|
244
171
|
/**
|
|
245
172
|
* Base lexer visitor class that provides common functionality for lexer-based rule visitors
|
|
246
173
|
*/
|
|
@@ -253,11 +180,11 @@ export declare abstract class BaseLexerRuleVisitor<TAutofixContext extends BaseA
|
|
|
253
180
|
* Helper method to create an unbound lint offense (without severity).
|
|
254
181
|
* The Linter will bind severity based on the rule's config.
|
|
255
182
|
*/
|
|
256
|
-
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext): UnboundLintOffense<TAutofixContext>;
|
|
183
|
+
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): UnboundLintOffense<TAutofixContext>;
|
|
257
184
|
/**
|
|
258
185
|
* Helper method to add an offense to the offenses array
|
|
259
186
|
*/
|
|
260
|
-
protected addOffense(message: string, location: Location, autofixContext?: TAutofixContext): void;
|
|
187
|
+
protected addOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): void;
|
|
261
188
|
/**
|
|
262
189
|
* Main entry point for lexer rule visitors
|
|
263
190
|
* @param lexResult - The lexer result containing tokens and source
|
|
@@ -286,11 +213,11 @@ export declare abstract class BaseSourceRuleVisitor<TAutofixContext extends Base
|
|
|
286
213
|
* Helper method to create an unbound lint offense (without severity).
|
|
287
214
|
* The Linter will bind severity based on the rule's config.
|
|
288
215
|
*/
|
|
289
|
-
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext): UnboundLintOffense<TAutofixContext>;
|
|
216
|
+
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): UnboundLintOffense<TAutofixContext>;
|
|
290
217
|
/**
|
|
291
218
|
* Helper method to add an offense to the offenses array
|
|
292
219
|
*/
|
|
293
|
-
protected addOffense(message: string, location: Location, autofixContext?: TAutofixContext): void;
|
|
220
|
+
protected addOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): void;
|
|
294
221
|
/**
|
|
295
222
|
* Main entry point for source rule visitors
|
|
296
223
|
* @param source - The raw source code
|
|
@@ -349,3 +276,23 @@ export declare function isHeadAndBodyTag(tagName: string): boolean;
|
|
|
349
276
|
export declare function isBodyOnlyTag(tagName: string): boolean;
|
|
350
277
|
export declare function isBodyTag(tagName: string): boolean;
|
|
351
278
|
export declare function isHeadTag(tagName: string): boolean;
|
|
279
|
+
/**
|
|
280
|
+
* Converts a character offset in a source string to a Position (line, column).
|
|
281
|
+
* Lines are 1-based, columns are 0-based.
|
|
282
|
+
*/
|
|
283
|
+
export declare function positionFromOffset(source: string, offset: number): Position;
|
|
284
|
+
/**
|
|
285
|
+
* Creates a Location from a source string, a start offset, and a length.
|
|
286
|
+
*/
|
|
287
|
+
export declare function locationFromOffset(source: string, startOffset: number, length: number): Location;
|
|
288
|
+
/**
|
|
289
|
+
* Finds a node in the AST that contains a specific position.
|
|
290
|
+
* Returns the deepest (most specific) node that matches the position and optional predicate.
|
|
291
|
+
*
|
|
292
|
+
* @param root - The root node to search from
|
|
293
|
+
* @param line - Line number (1-based)
|
|
294
|
+
* @param column - Column number (0-based)
|
|
295
|
+
* @param predicate - Optional predicate function to filter nodes
|
|
296
|
+
* @returns The matching node or null if not found
|
|
297
|
+
*/
|
|
298
|
+
export declare function findNodeAtPosition(root: Node, line: number, column: number, predicate?: (node: Node) => boolean): Node | null;
|
|
@@ -8,7 +8,7 @@ interface SVGTagNameCapitalizationAutofixContext extends BaseAutofixContext {
|
|
|
8
8
|
}
|
|
9
9
|
export declare class SVGTagNameCapitalizationRule extends ParserRule<SVGTagNameCapitalizationAutofixContext> {
|
|
10
10
|
static autocorrectable: boolean;
|
|
11
|
-
|
|
11
|
+
static ruleName: string;
|
|
12
12
|
get defaultConfig(): FullRuleConfig;
|
|
13
13
|
check(result: ParseResult, context?: Partial<LintContext>): UnboundLintOffense<SVGTagNameCapitalizationAutofixContext>[];
|
|
14
14
|
autofix(offense: LintOffense<SVGTagNameCapitalizationAutofixContext>, result: ParseResult, _context?: Partial<LintContext>): ParseResult | null;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ParserRule } from "../types.js";
|
|
2
2
|
import type { UnboundLintOffense, LintContext, FullRuleConfig } from "../types.js";
|
|
3
3
|
import type { ParseResult } from "@herb-tools/core";
|
|
4
|
-
export declare class
|
|
5
|
-
|
|
4
|
+
export declare class TurboPermanentRequireIdRule extends ParserRule {
|
|
5
|
+
static ruleName: string;
|
|
6
6
|
get defaultConfig(): FullRuleConfig;
|
|
7
7
|
check(result: ParseResult, context?: Partial<LintContext>): UnboundLintOffense[];
|
|
8
8
|
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { Diagnostic, LexResult, ParseResult } from "@herb-tools/core";
|
|
1
|
+
import { Diagnostic, LexResult, ParseResult, Location } from "@herb-tools/core";
|
|
2
2
|
import type { rules } from "./rules.js";
|
|
3
|
-
import type { Node } from "@herb-tools/core";
|
|
3
|
+
import type { Node, ParserOptions } from "@herb-tools/core";
|
|
4
4
|
import type { RuleConfig } from "@herb-tools/config";
|
|
5
5
|
import type { Mutable } from "@herb-tools/rewriter";
|
|
6
6
|
export type { Mutable } from "@herb-tools/rewriter";
|
|
7
7
|
export type LintSeverity = "error" | "warning" | "info" | "hint";
|
|
8
|
+
export declare const DEFAULT_LINTER_PARSER_OPTIONS: Partial<ParserOptions>;
|
|
8
9
|
export type FullRuleConfig = Required<Pick<RuleConfig, 'enabled' | 'severity'>> & Omit<RuleConfig, 'enabled' | 'severity'>;
|
|
9
10
|
/**
|
|
10
11
|
* Automatically inferred union type of all available linter rule names.
|
|
11
|
-
* This type extracts the '
|
|
12
|
+
* This type extracts the 'ruleName' property from each rule class.
|
|
12
13
|
*/
|
|
13
|
-
export type LinterRule =
|
|
14
|
+
export type LinterRule = (typeof rules[number])['ruleName'];
|
|
14
15
|
/**
|
|
15
16
|
* Base context for autofix operations. Contains the offending node.
|
|
16
17
|
* Rules can extend this interface to include rule-specific autofix data.
|
|
@@ -19,6 +20,8 @@ export type LinterRule = InstanceType<typeof rules[number]>['name'];
|
|
|
19
20
|
export interface BaseAutofixContext {
|
|
20
21
|
/** The AST node, token, or data structure that caused the offense (mutable) */
|
|
21
22
|
node: Mutable<Node>;
|
|
23
|
+
/** If true, this fix requires --fix-unsafely to be applied */
|
|
24
|
+
unsafe?: boolean;
|
|
22
25
|
}
|
|
23
26
|
/**
|
|
24
27
|
* A lint offense without severity bound. Rules produce these, and the Linter
|
|
@@ -28,6 +31,8 @@ export interface UnboundLintOffense<TAutofixContext extends BaseAutofixContext =
|
|
|
28
31
|
rule: LinterRule;
|
|
29
32
|
/** Context data for autofix, including the offending node and rule-specific data */
|
|
30
33
|
autofixContext?: TAutofixContext;
|
|
34
|
+
/** If set, overrides rule-level severity for this specific offense */
|
|
35
|
+
severity?: LintSeverity;
|
|
31
36
|
}
|
|
32
37
|
/**
|
|
33
38
|
* A lint offense with severity bound. The Linter produces these by binding
|
|
@@ -66,12 +71,17 @@ export declare const DEFAULT_RULE_CONFIG: FullRuleConfig;
|
|
|
66
71
|
*/
|
|
67
72
|
export declare abstract class ParserRule<TAutofixContext extends BaseAutofixContext = BaseAutofixContext> {
|
|
68
73
|
static type: "parser";
|
|
74
|
+
static ruleName: string;
|
|
69
75
|
/** Indicates whether this rule supports autofix. Defaults to false. */
|
|
70
76
|
static autocorrectable: boolean;
|
|
71
77
|
/** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
|
|
72
78
|
static unsafeAutocorrectable: boolean;
|
|
73
|
-
|
|
79
|
+
/** Indicates whether the source should be re-indented after autofix. Defaults to false. */
|
|
80
|
+
static reindentAfterAutofix: boolean;
|
|
81
|
+
get ruleName(): string;
|
|
74
82
|
get defaultConfig(): FullRuleConfig;
|
|
83
|
+
get parserOptions(): Partial<ParserOptions>;
|
|
84
|
+
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): UnboundLintOffense<TAutofixContext>;
|
|
75
85
|
abstract check(result: ParseResult, context?: Partial<LintContext>): UnboundLintOffense<TAutofixContext>[];
|
|
76
86
|
/**
|
|
77
87
|
* Optional method to determine if this rule should run.
|
|
@@ -96,12 +106,14 @@ export declare abstract class ParserRule<TAutofixContext extends BaseAutofixCont
|
|
|
96
106
|
*/
|
|
97
107
|
export declare abstract class LexerRule<TAutofixContext extends BaseAutofixContext = BaseAutofixContext> {
|
|
98
108
|
static type: "lexer";
|
|
109
|
+
static ruleName: string;
|
|
99
110
|
/** Indicates whether this rule supports autofix. Defaults to false. */
|
|
100
111
|
static autocorrectable: boolean;
|
|
101
112
|
/** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
|
|
102
113
|
static unsafeAutocorrectable: boolean;
|
|
103
|
-
|
|
114
|
+
get ruleName(): string;
|
|
104
115
|
get defaultConfig(): FullRuleConfig;
|
|
116
|
+
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): UnboundLintOffense<TAutofixContext>;
|
|
105
117
|
abstract check(lexResult: LexResult, context?: Partial<LintContext>): UnboundLintOffense<TAutofixContext>[];
|
|
106
118
|
/**
|
|
107
119
|
* Optional method to determine if this rule should run.
|
|
@@ -124,6 +136,7 @@ export declare abstract class LexerRule<TAutofixContext extends BaseAutofixConte
|
|
|
124
136
|
export interface LexerRuleConstructor {
|
|
125
137
|
type: "lexer";
|
|
126
138
|
new (): LexerRule;
|
|
139
|
+
ruleName: string;
|
|
127
140
|
}
|
|
128
141
|
/**
|
|
129
142
|
* Complete lint context with all properties defined.
|
|
@@ -141,12 +154,14 @@ export interface LintContext {
|
|
|
141
154
|
export declare const DEFAULT_LINT_CONTEXT: LintContext;
|
|
142
155
|
export declare abstract class SourceRule<TAutofixContext extends BaseAutofixContext = BaseAutofixContext> {
|
|
143
156
|
static type: "source";
|
|
157
|
+
static ruleName: string;
|
|
144
158
|
/** Indicates whether this rule supports autofix. Defaults to false. */
|
|
145
159
|
static autocorrectable: boolean;
|
|
146
160
|
/** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
|
|
147
161
|
static unsafeAutocorrectable: boolean;
|
|
148
|
-
|
|
162
|
+
get ruleName(): string;
|
|
149
163
|
get defaultConfig(): FullRuleConfig;
|
|
164
|
+
protected createOffense(message: string, location: Location, autofixContext?: TAutofixContext, severity?: LintSeverity): UnboundLintOffense<TAutofixContext>;
|
|
150
165
|
abstract check(source: string, context?: Partial<LintContext>): UnboundLintOffense<TAutofixContext>[];
|
|
151
166
|
/**
|
|
152
167
|
* Optional method to determine if this rule should run.
|
|
@@ -169,6 +184,7 @@ export declare abstract class SourceRule<TAutofixContext extends BaseAutofixCont
|
|
|
169
184
|
export interface SourceRuleConstructor {
|
|
170
185
|
type: "source";
|
|
171
186
|
new (): SourceRule;
|
|
187
|
+
ruleName: string;
|
|
172
188
|
}
|
|
173
189
|
/**
|
|
174
190
|
* Type representing a parser/AST rule class constructor.
|
|
@@ -177,6 +193,8 @@ export interface SourceRuleConstructor {
|
|
|
177
193
|
*/
|
|
178
194
|
export type ParserRuleClass = (new () => ParserRule) & {
|
|
179
195
|
type?: "parser";
|
|
196
|
+
ruleName: string;
|
|
197
|
+
reindentAfterAutofix?: boolean;
|
|
180
198
|
};
|
|
181
199
|
export type LexerRuleClass = LexerRuleConstructor;
|
|
182
200
|
export type SourceRuleClass = SourceRuleConstructor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ruleDocumentationUrl(ruleId: string): string;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export const DEFAULT_LINTER_PARSER_OPTIONS = {
|
|
2
|
+
track_whitespace: true,
|
|
3
|
+
};
|
|
1
4
|
/**
|
|
2
5
|
* Default configuration for rules when defaultConfig is not specified.
|
|
3
6
|
* Custom rules can omit defaultConfig and will use these defaults.
|
|
@@ -12,26 +15,61 @@ export const DEFAULT_RULE_CONFIG = {
|
|
|
12
15
|
*/
|
|
13
16
|
export class ParserRule {
|
|
14
17
|
static type = "parser";
|
|
18
|
+
static ruleName;
|
|
15
19
|
/** Indicates whether this rule supports autofix. Defaults to false. */
|
|
16
20
|
static autocorrectable = false;
|
|
17
21
|
/** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
|
|
18
22
|
static unsafeAutocorrectable = false;
|
|
23
|
+
/** Indicates whether the source should be re-indented after autofix. Defaults to false. */
|
|
24
|
+
static reindentAfterAutofix = false;
|
|
25
|
+
get ruleName() {
|
|
26
|
+
return this.constructor.ruleName;
|
|
27
|
+
}
|
|
19
28
|
get defaultConfig() {
|
|
20
29
|
return DEFAULT_RULE_CONFIG;
|
|
21
30
|
}
|
|
31
|
+
get parserOptions() {
|
|
32
|
+
return DEFAULT_LINTER_PARSER_OPTIONS;
|
|
33
|
+
}
|
|
34
|
+
createOffense(message, location, autofixContext, severity) {
|
|
35
|
+
return {
|
|
36
|
+
rule: this.ruleName,
|
|
37
|
+
code: this.ruleName,
|
|
38
|
+
source: "Herb Linter",
|
|
39
|
+
message,
|
|
40
|
+
location,
|
|
41
|
+
autofixContext,
|
|
42
|
+
severity,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
22
45
|
}
|
|
23
46
|
/**
|
|
24
47
|
* Base class for lexer rules.
|
|
25
48
|
*/
|
|
26
49
|
export class LexerRule {
|
|
27
50
|
static type = "lexer";
|
|
51
|
+
static ruleName;
|
|
28
52
|
/** Indicates whether this rule supports autofix. Defaults to false. */
|
|
29
53
|
static autocorrectable = false;
|
|
30
54
|
/** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
|
|
31
55
|
static unsafeAutocorrectable = false;
|
|
56
|
+
get ruleName() {
|
|
57
|
+
return this.constructor.ruleName;
|
|
58
|
+
}
|
|
32
59
|
get defaultConfig() {
|
|
33
60
|
return DEFAULT_RULE_CONFIG;
|
|
34
61
|
}
|
|
62
|
+
createOffense(message, location, autofixContext, severity) {
|
|
63
|
+
return {
|
|
64
|
+
rule: this.ruleName,
|
|
65
|
+
code: this.ruleName,
|
|
66
|
+
source: "Herb Linter",
|
|
67
|
+
message,
|
|
68
|
+
location,
|
|
69
|
+
autofixContext,
|
|
70
|
+
severity,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
35
73
|
}
|
|
36
74
|
/**
|
|
37
75
|
* Default context object with all keys defined but set to undefined
|
|
@@ -44,12 +82,27 @@ export const DEFAULT_LINT_CONTEXT = {
|
|
|
44
82
|
};
|
|
45
83
|
export class SourceRule {
|
|
46
84
|
static type = "source";
|
|
85
|
+
static ruleName;
|
|
47
86
|
/** Indicates whether this rule supports autofix. Defaults to false. */
|
|
48
87
|
static autocorrectable = false;
|
|
49
88
|
/** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
|
|
50
89
|
static unsafeAutocorrectable = false;
|
|
90
|
+
get ruleName() {
|
|
91
|
+
return this.constructor.ruleName;
|
|
92
|
+
}
|
|
51
93
|
get defaultConfig() {
|
|
52
94
|
return DEFAULT_RULE_CONFIG;
|
|
53
95
|
}
|
|
96
|
+
createOffense(message, location, autofixContext, severity) {
|
|
97
|
+
return {
|
|
98
|
+
rule: this.ruleName,
|
|
99
|
+
code: this.ruleName,
|
|
100
|
+
source: "Herb Linter",
|
|
101
|
+
message,
|
|
102
|
+
location,
|
|
103
|
+
autofixContext,
|
|
104
|
+
severity,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
54
107
|
}
|
|
55
108
|
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,6BAA6B,GAA2B;IACnE,gBAAgB,EAAE,IAAI;CACvB,CAAA;AAiED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,EAAE;CACZ,CAAA;AAED;;GAEG;AACH,MAAM,OAAgB,UAAU;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAiB,CAAA;IAC/B,MAAM,CAAC,QAAQ,CAAQ;IACvB,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,wGAAwG;IACxG,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAA;IACpC,2FAA2F;IAC3F,MAAM,CAAC,oBAAoB,GAAG,KAAK,CAAA;IAEnC,IAAI,QAAQ;QACV,OAAQ,IAAI,CAAC,WAAiC,CAAC,QAAQ,CAAA;IACzD,CAAC;IAED,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,6BAA6B,CAAA;IACtC,CAAC;IAES,aAAa,CAAC,OAAe,EAAE,QAAkB,EAAE,cAAgC,EAAE,QAAuB;QACpH,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,MAAM,EAAE,aAAa;YACrB,OAAO;YACP,QAAQ;YACR,cAAc;YACd,QAAQ;SACT,CAAA;IACH,CAAC;;AAwBH;;GAEG;AACH,MAAM,OAAgB,SAAS;IAC7B,MAAM,CAAC,IAAI,GAAG,OAAgB,CAAA;IAC9B,MAAM,CAAC,QAAQ,CAAQ;IACvB,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,wGAAwG;IACxG,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAA;IAEpC,IAAI,QAAQ;QACV,OAAQ,IAAI,CAAC,WAAgC,CAAC,QAAQ,CAAA;IACxD,CAAC;IAED,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;IAES,aAAa,CAAC,OAAe,EAAE,QAAkB,EAAE,cAAgC,EAAE,QAAuB;QACpH,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,MAAM,EAAE,aAAa;YACrB,OAAO;YACP,QAAQ;YACR,cAAc;YACd,QAAQ;SACT,CAAA;IACH,CAAC;;AAyCH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,QAAQ,EAAE,SAAS;IACnB,cAAc,EAAE,SAAS;IACzB,qBAAqB,EAAE,SAAS;IAChC,qBAAqB,EAAE,SAAS;CACxB,CAAA;AAEV,MAAM,OAAgB,UAAU;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAiB,CAAA;IAC/B,MAAM,CAAC,QAAQ,CAAQ;IACvB,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,wGAAwG;IACxG,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAA;IAEpC,IAAI,QAAQ;QACV,OAAQ,IAAI,CAAC,WAAiC,CAAC,QAAQ,CAAA;IACzD,CAAC;IAED,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;IAES,aAAa,CAAC,OAAe,EAAE,QAAkB,EAAE,cAAgC,EAAE,QAAuB;QACpH,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,IAAI,EAAE,IAAI,CAAC,QAAQ;YACnB,MAAM,EAAE,aAAa;YACrB,OAAO;YACP,QAAQ;YACR,cAAc;YACd,QAAQ;SACT,CAAA;IACH,CAAC"}
|
package/dist/urls.js
ADDED
package/dist/urls.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../src/urls.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,qCAAqC,CAAA;AAE3D,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,GAAG,aAAa,IAAI,MAAM,EAAE,CAAA;AACrC,CAAC"}
|
package/docs/rules/README.md
CHANGED
|
@@ -4,16 +4,32 @@ This page contains documentation for all Herb Linter rules.
|
|
|
4
4
|
|
|
5
5
|
## Available Rules
|
|
6
6
|
|
|
7
|
+
- [`actionview-no-silent-helper`](./actionview-no-silent-helper.md) - Disallow silent ERB tags for Action View helpers
|
|
7
8
|
- [`erb-comment-syntax`](./erb-comment-syntax.md) - Disallow Ruby comments immediately after ERB tags
|
|
8
9
|
- [`erb-no-case-node-children`](./erb-no-case-node-children.md) - Don't use `children` for `case/when` and `case/in` nodes
|
|
10
|
+
- [`erb-no-conditional-html-element`](./erb-no-conditional-html-element.md) - Disallow conditional HTML elements
|
|
11
|
+
- [`erb-no-duplicate-branch-elements`](./erb-no-duplicate-branch-elements.md) - Disallow duplicate elements across conditional branches
|
|
9
12
|
- [`erb-no-empty-tags`](./erb-no-empty-tags.md) - Disallow empty ERB tags
|
|
10
13
|
- [`erb-no-extra-newline`](./erb-no-extra-newline.md) - Disallow extra newlines.
|
|
11
14
|
- [`erb-no-extra-whitespace-inside-tags`](./erb-no-extra-whitespace-inside-tags.md) - Disallow multiple consecutive spaces inside ERB tags
|
|
15
|
+
- [`erb-no-inline-case-conditions`](./erb-no-inline-case-conditions.md) - Disallow inline `case`/`when` and `case`/`in` conditions in a single ERB tag
|
|
16
|
+
- [`erb-no-instance-variables-in-partials`](./erb-no-instance-variables-in-partials.md) - Disallow instance variables in partials
|
|
17
|
+
- [`erb-no-interpolated-class-names`](./erb-no-interpolated-class-names.md) - Disallow ERB interpolation inside CSS class names
|
|
18
|
+
- [`erb-no-javascript-tag-helper`](./erb-no-javascript-tag-helper.md) - Disallow `javascript_tag` helper
|
|
12
19
|
- [`erb-no-output-control-flow`](./erb-no-output-control-flow.md) - Prevents outputting control flow blocks
|
|
20
|
+
- [`erb-no-output-in-attribute-name`](./erb-no-output-in-attribute-name.md) - Disallow ERB output in attribute names
|
|
21
|
+
- [`erb-no-output-in-attribute-position`](./erb-no-output-in-attribute-position.md) - Disallow ERB output in attribute position
|
|
22
|
+
- [`erb-no-raw-output-in-attribute-value`](./erb-no-raw-output-in-attribute-value.md) - Disallow `<%==` in attribute values
|
|
13
23
|
- [`erb-no-silent-tag-in-attribute-name`](./erb-no-silent-tag-in-attribute-name.md) - Disallow ERB silent tags in HTML attribute names
|
|
24
|
+
- [`erb-no-statement-in-script`](./erb-no-statement-in-script.md) - Disallow ERB statements inside `<script>` tags
|
|
25
|
+
- [`erb-no-then-in-control-flow`](./erb-no-then-in-control-flow.md) - Disallow `then` in ERB control flow expressions
|
|
26
|
+
- [`erb-no-trailing-whitespace`](./erb-no-trailing-whitespace.md) - Disallow trailing whitespace at end of lines.
|
|
27
|
+
- [`erb-no-unsafe-js-attribute`](./erb-no-unsafe-js-attribute.md) - Disallow unsafe ERB output in JavaScript attributes
|
|
28
|
+
- [`erb-no-unsafe-raw`](./erb-no-unsafe-raw.md) - Disallow `raw()` and `.html_safe` in ERB output
|
|
29
|
+
- [`erb-no-unsafe-script-interpolation`](./erb-no-unsafe-script-interpolation.md) - Disallow unsafe ERB output inside `<script>` tags
|
|
14
30
|
- [`erb-prefer-image-tag-helper`](./erb-prefer-image-tag-helper.md) - Prefer `image_tag` helper over `<img>` with ERB expressions
|
|
15
|
-
- [`erb-require-whitespace-inside-tags`](./erb-require-whitespace-inside-tags.md) - Requires whitespace around ERB tags
|
|
16
31
|
- [`erb-require-trailing-newline`](./erb-require-trailing-newline.md) - Enforces that all HTML+ERB template files end with exactly one trailing newline character.
|
|
32
|
+
- [`erb-require-whitespace-inside-tags`](./erb-require-whitespace-inside-tags.md) - Requires whitespace around ERB tags
|
|
17
33
|
- [`erb-right-trim`](./erb-right-trim.md) - Enforce consistent right-trimming syntax.
|
|
18
34
|
- [`erb-strict-locals-comment-syntax`](./erb-strict-locals-comment-syntax.md) - Enforce strict locals comment syntax.
|
|
19
35
|
- [`herb-disable-comment-malformed`](./herb-disable-comment-malformed.md) - Detect malformed `herb:disable` comments.
|
|
@@ -22,6 +38,7 @@ This page contains documentation for all Herb Linter rules.
|
|
|
22
38
|
- [`herb-disable-comment-no-redundant-all`](./herb-disable-comment-no-redundant-all.md) - Disallow redundant use of `all` in `herb:disable` comments.
|
|
23
39
|
- [`herb-disable-comment-unnecessary`](./herb-disable-comment-unnecessary.md) - Detect unnecessary `herb:disable` comments.
|
|
24
40
|
- [`herb-disable-comment-valid-rule-name`](./herb-disable-comment-valid-rule-name.md) - Validate rule names in `herb:disable` comments.
|
|
41
|
+
- [`html-allowed-script-type`](./html-allowed-script-type.md) - Restrict allowed `type` attributes for `<script>` tags
|
|
25
42
|
- [`html-anchor-require-href`](./html-anchor-require-href.md) - Requires an href attribute on anchor tags
|
|
26
43
|
- [`html-aria-attribute-must-be-valid`](./html-aria-attribute-must-be-valid.md) - Disallow invalid or unknown `aria-*` attributes.
|
|
27
44
|
- [`html-aria-label-is-well-formatted`](./html-aria-label-is-well-formatted.md) - `aria-label` must be well-formatted
|
|
@@ -33,12 +50,15 @@ This page contains documentation for all Herb Linter rules.
|
|
|
33
50
|
- [`html-attribute-values-require-quotes`](./html-attribute-values-require-quotes.md) - Requires quotes around attribute values
|
|
34
51
|
- [`html-avoid-both-disabled-and-aria-disabled`](./html-avoid-both-disabled-and-aria-disabled.md) - Avoid using both `disabled` and `aria-disabled` attributes
|
|
35
52
|
- [`html-body-only-elements`](./html-body-only-elements.md) - Require content elements inside `<body>`.
|
|
53
|
+
- [`html-details-has-summary`](./html-details-has-summary.md) - Require `<summary>` in `<details>` elements
|
|
36
54
|
- [`html-boolean-attributes-no-value`](./html-boolean-attributes-no-value.md) - Prevents values on boolean attributes
|
|
37
55
|
- [`html-head-only-elements`](./html-head-only-elements.md) - Require head-scoped elements inside `<head>`.
|
|
38
56
|
- [`html-iframe-has-title`](./html-iframe-has-title.md) - `iframe` elements must have a `title` attribute
|
|
39
|
-
- [`html-input-require-autocomplete`](./html-input-require-autocomplete.md) - Require `autocomplete` attributes on `<input>` tags.
|
|
40
57
|
- [`html-img-require-alt`](./html-img-require-alt.md) - Requires `alt` attributes on `<img>` tags
|
|
58
|
+
- [`html-input-require-autocomplete`](./html-input-require-autocomplete.md) - Require `autocomplete` attributes on `<input>` tags.
|
|
41
59
|
- [`html-navigation-has-label`](./html-navigation-has-label.md) - Navigation landmarks must have accessible labels
|
|
60
|
+
- [`html-no-abstract-roles`](./html-no-abstract-roles.md) - No abstract ARIA roles
|
|
61
|
+
- [`html-no-aria-hidden-on-body`](./html-no-aria-hidden-on-body.md) - No `aria-hidden` on `<body>`
|
|
42
62
|
- [`html-no-aria-hidden-on-focusable`](./html-no-aria-hidden-on-focusable.md) - Focusable elements should not have `aria-hidden="true"`
|
|
43
63
|
- [`html-no-block-inside-inline`](./html-no-block-inside-inline.md) - Prevents block-level elements inside inline elements
|
|
44
64
|
- [`html-no-duplicate-attributes`](./html-no-duplicate-attributes.md) - Prevents duplicate attributes on HTML elements
|
|
@@ -54,6 +74,7 @@ This page contains documentation for all Herb Linter rules.
|
|
|
54
74
|
- [`html-tag-name-lowercase`](./html-tag-name-lowercase.md) - Enforces lowercase tag names in HTML
|
|
55
75
|
- [`parser-no-errors`](./parser-no-errors.md) - Disallow parser errors in HTML+ERB documents
|
|
56
76
|
- [`svg-tag-name-capitalization`](./svg-tag-name-capitalization.md) - Enforces proper camelCase capitalization for SVG elements
|
|
77
|
+
- [`turbo-permanent-require-id`](./turbo-permanent-require-id.md) - Require `id` attribute on elements with `data-turbo-permanent`
|
|
57
78
|
|
|
58
79
|
## Contributing
|
|
59
80
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Linter Rule: Disallow silent ERB tags for Action View helpers
|
|
2
|
+
|
|
3
|
+
**Rule:** `actionview-no-silent-helper`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Action View helpers like `link_to`, `form_with`, and `content_tag` must use output ERB tags (`<%= %>`) so their rendered HTML is included in the page. Using silent ERB tags (`<% %>`) discards the helper's output entirely.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
Action View helpers generate HTML that needs to be rendered into the template. When a helper is called with a silent ERB tag (`<% %>`), the return value is evaluated but silently discarded, meaning the generated HTML never appears in the output. This is almost always a mistake and can lead to confusing bugs where elements are missing from the page with no obvious cause. Using `<%= %>` ensures the helper's output is properly rendered.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
### ✅ Good
|
|
16
|
+
|
|
17
|
+
```erb
|
|
18
|
+
<%= link_to "Home", root_path %>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```erb
|
|
22
|
+
<%= form_with model: @user do |f| %>
|
|
23
|
+
<%= f.text_field :name %>
|
|
24
|
+
<% end %>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```erb
|
|
28
|
+
<%= button_to "Delete", user_path(@user), method: :delete %>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```erb
|
|
32
|
+
<%= content_tag :div, "Hello", class: "greeting" %>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 🚫 Bad
|
|
36
|
+
|
|
37
|
+
```erb
|
|
38
|
+
<% link_to "Home", root_path %>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
```erb
|
|
42
|
+
<% form_with model: @user do |f| %>
|
|
43
|
+
<%= f.text_field :name %>
|
|
44
|
+
<% end %>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```erb
|
|
48
|
+
<% button_to "Delete", user_path(@user), method: :delete %>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```erb
|
|
52
|
+
<% content_tag :div, "Hello", class: "greeting" %>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## References
|
|
56
|
+
|
|
57
|
+
* [Rails Action View Helpers documentation](https://api.rubyonrails.org/classes/ActionView/Helpers.html)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Linter Rule: Disallow conditional HTML elements
|
|
2
|
+
|
|
3
|
+
**Rule:** `erb-no-conditional-html-element`
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Disallow the pattern of opening an HTML tag in one conditional block and closing it in another conditional block with the same condition. This creates a "conditional element" where the element's existence depends on a runtime condition.
|
|
8
|
+
|
|
9
|
+
## Rationale
|
|
10
|
+
|
|
11
|
+
This pattern is difficult to read, maintain, and reason about. It can lead to confusion when trying to understand the document structure, and it makes the template harder to format, lint, and analyze. The opening and closing tags are visually separated, making it non-obvious that they form a matched pair.
|
|
12
|
+
|
|
13
|
+
Instead, prefer using `capture` blocks with `content_tag` helpers, which make the conditional wrapping explicit and keeps the logic together.
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
### ✅ Good
|
|
18
|
+
|
|
19
|
+
Using a `capture` block to conditionally wrap content:
|
|
20
|
+
|
|
21
|
+
```erb
|
|
22
|
+
<% content = capture do %>
|
|
23
|
+
<div>Content</div>
|
|
24
|
+
<% end %>
|
|
25
|
+
|
|
26
|
+
<% if wrap_in_dialog? %>
|
|
27
|
+
<dialog><%= content %></dialog>
|
|
28
|
+
<% else %>
|
|
29
|
+
<%= content %>
|
|
30
|
+
<% end %>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```erb
|
|
34
|
+
<% content = capture do %>
|
|
35
|
+
<div>Content</div>
|
|
36
|
+
<% end %>
|
|
37
|
+
|
|
38
|
+
<%= wrap_in_dialog? ? content_tag(:dialog, content) : content %>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Complete elements within conditional branches:
|
|
42
|
+
|
|
43
|
+
```erb
|
|
44
|
+
<% if some_condition %>
|
|
45
|
+
<div class="a">Content</div>
|
|
46
|
+
<% else %>
|
|
47
|
+
<div class="b">Content</div>
|
|
48
|
+
<% end %>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 🚫 Bad
|
|
52
|
+
|
|
53
|
+
Opening and closing tags in separate conditional blocks:
|
|
54
|
+
|
|
55
|
+
```erb
|
|
56
|
+
<% if wrap_in_dialog? %>
|
|
57
|
+
<dialog>
|
|
58
|
+
<% end %>
|
|
59
|
+
|
|
60
|
+
<div>Stuff</div>
|
|
61
|
+
|
|
62
|
+
<% if wrap_in_dialog? %>
|
|
63
|
+
</dialog>
|
|
64
|
+
<% end %>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```erb
|
|
68
|
+
<% if @with_icon %>
|
|
69
|
+
<div class="icon">
|
|
70
|
+
<% end %>
|
|
71
|
+
<span>Hello</span>
|
|
72
|
+
<% if @with_icon %>
|
|
73
|
+
</div>
|
|
74
|
+
<% end %>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```erb
|
|
78
|
+
<% if @with_icon %>
|
|
79
|
+
<div class="icon">
|
|
80
|
+
<% else %>
|
|
81
|
+
<div class="no-icon">
|
|
82
|
+
<% end %>
|
|
83
|
+
|
|
84
|
+
<span>Hello</span>
|
|
85
|
+
</div>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## References
|
|
89
|
+
|
|
90
|
+
\-
|