@markuplint/rules 5.0.0-rc.2 → 5.0.0-rc.5
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/CHANGELOG.md +98 -0
- package/CLAUDE.md +31 -2
- package/lib/{wai-aria-deprecated-role → aria-prop-requires-role}/index.d.ts +0 -1
- package/lib/{wai-aria-no-global-prop → aria-prop-requires-role}/index.js +0 -1
- package/lib/attr-check.d.ts +0 -48
- package/lib/attr-check.js +0 -36
- package/lib/attr-eligibility.d.ts +41 -0
- package/lib/attr-eligibility.js +60 -0
- package/lib/attr-value-quotes/index.d.ts +0 -7
- package/lib/attr-value-quotes/index.js +0 -7
- package/lib/attr-value-quotes/meta.d.ts +0 -1
- package/lib/attr-value-quotes/meta.js +0 -1
- package/lib/case-sensitive-attr-name/index.d.ts +0 -8
- package/lib/case-sensitive-attr-name/index.js +0 -8
- package/lib/case-sensitive-attr-name/meta.d.ts +0 -1
- package/lib/case-sensitive-attr-name/meta.js +0 -1
- package/lib/case-sensitive-tag-name/index.d.ts +0 -8
- package/lib/case-sensitive-tag-name/index.js +0 -8
- package/lib/case-sensitive-tag-name/meta.d.ts +0 -1
- package/lib/case-sensitive-tag-name/meta.js +0 -1
- package/lib/class-naming/index.d.ts +0 -8
- package/lib/class-naming/index.js +0 -8
- package/lib/class-naming/meta.d.ts +1 -2
- package/lib/class-naming/meta.js +1 -2
- package/lib/consistent-table-row-length/index.d.ts +14 -0
- package/lib/consistent-table-row-length/index.js +69 -0
- package/lib/consistent-table-row-length/meta.d.ts +4 -0
- package/lib/consistent-table-row-length/meta.js +3 -0
- package/lib/create-message.d.ts +2 -25
- package/lib/create-message.js +2 -53
- package/lib/debug.d.ts +1 -9
- package/lib/debug.js +1 -5
- package/lib/element-supports-aria-prop/index.d.ts +12 -0
- package/lib/element-supports-aria-prop/index.js +38 -0
- package/lib/form-attr-references-form/index.d.ts +12 -0
- package/lib/form-attr-references-form/index.js +64 -0
- package/lib/{correct-aspect-ratio → form-attr-references-form}/meta.d.ts +1 -1
- package/lib/form-attr-references-form/meta.js +3 -0
- package/lib/head-element-order/meta.d.ts +1 -1
- package/lib/head-element-order/meta.js +1 -1
- package/lib/helpers.d.ts +8 -138
- package/lib/helpers.js +24 -165
- package/lib/index.d.ts +135 -78
- package/lib/index.js +167 -82
- package/lib/input-list-references-datalist/index.d.ts +13 -0
- package/lib/input-list-references-datalist/index.js +46 -0
- package/lib/input-list-references-datalist/meta.d.ts +4 -0
- package/lib/input-list-references-datalist/meta.js +3 -0
- package/lib/itemprop-requires-itemscope/index.d.ts +21 -0
- package/lib/itemprop-requires-itemscope/index.js +53 -0
- package/lib/itemprop-requires-itemscope/meta.d.ts +4 -0
- package/lib/itemprop-requires-itemscope/meta.js +3 -0
- package/lib/label-for-references-labelable/index.d.ts +12 -0
- package/lib/label-for-references-labelable/index.js +68 -0
- package/lib/label-for-references-labelable/meta.d.ts +4 -0
- package/lib/label-for-references-labelable/meta.js +3 -0
- package/lib/label-has-control/index.d.ts +5 -5
- package/lib/label-has-control/index.js +5 -18
- package/lib/label-has-control/meta.d.ts +0 -1
- package/lib/label-has-control/meta.js +0 -1
- package/lib/label-no-multiple-controls/index.d.ts +31 -0
- package/lib/label-no-multiple-controls/index.js +104 -0
- package/lib/label-no-multiple-controls/meta.d.ts +4 -0
- package/lib/label-no-multiple-controls/meta.js +3 -0
- package/lib/landmark-roles/roles.d.ts +32 -0
- package/lib/landmark-roles/roles.js +73 -0
- package/lib/link-types/index.d.ts +0 -5
- package/lib/link-types/index.js +5 -6
- package/lib/link-types/meta.d.ts +1 -2
- package/lib/link-types/meta.js +1 -2
- package/lib/map-id-name-match/index.d.ts +10 -0
- package/lib/map-id-name-match/index.js +39 -0
- package/lib/map-id-name-match/meta.d.ts +4 -0
- package/lib/map-id-name-match/meta.js +3 -0
- package/lib/meta-charset-position/index.d.ts +15 -0
- package/lib/meta-charset-position/index.js +31 -0
- package/lib/meta-charset-position/meta.d.ts +4 -0
- package/lib/meta-charset-position/meta.js +3 -0
- package/lib/meter-value-bounds/index.d.ts +10 -0
- package/lib/meter-value-bounds/index.js +123 -0
- package/lib/meter-value-bounds/meta.d.ts +4 -0
- package/lib/meter-value-bounds/meta.js +3 -0
- package/lib/{wai-aria-required-props → no-abstract-role}/index.d.ts +0 -1
- package/lib/{wai-aria-abstract-role → no-abstract-role}/index.js +0 -1
- package/lib/no-always-matching-source/index.d.ts +13 -0
- package/lib/no-always-matching-source/index.js +100 -0
- package/lib/no-always-matching-source/meta.d.ts +4 -0
- package/lib/no-always-matching-source/meta.js +3 -0
- package/lib/no-ambiguous-navigable-target-names/index.d.ts +0 -8
- package/lib/no-ambiguous-navigable-target-names/index.js +0 -8
- package/lib/no-ambiguous-navigable-target-names/meta.d.ts +1 -2
- package/lib/no-ambiguous-navigable-target-names/meta.js +1 -2
- package/lib/{wai-aria-required-owned-elements → no-aria-on-presentational-children}/index.d.ts +0 -1
- package/lib/{wai-aria-presentational-children → no-aria-on-presentational-children}/index.js +0 -1
- package/lib/no-aria-on-unsupported-element/index.d.ts +11 -0
- package/lib/no-aria-on-unsupported-element/index.js +35 -0
- package/lib/no-aria-on-unsupported-element/meta.d.ts +9 -0
- package/lib/no-aria-on-unsupported-element/meta.js +8 -0
- package/lib/no-boolean-attr-value/index.d.ts +0 -7
- package/lib/no-boolean-attr-value/index.js +0 -7
- package/lib/no-boolean-attr-value/meta.d.ts +0 -1
- package/lib/no-boolean-attr-value/meta.js +0 -1
- package/lib/no-broken-fragment-link/index.d.ts +15 -0
- package/lib/no-broken-fragment-link/index.js +93 -0
- package/lib/no-broken-fragment-link/meta.d.ts +4 -0
- package/lib/no-broken-fragment-link/meta.js +3 -0
- package/lib/no-consecutive-br/index.d.ts +0 -8
- package/lib/no-consecutive-br/index.js +0 -8
- package/lib/no-consecutive-br/meta.d.ts +0 -1
- package/lib/no-consecutive-br/meta.js +0 -1
- package/lib/no-content-after-body/index.d.ts +25 -0
- package/lib/no-content-after-body/index.js +51 -0
- package/lib/no-content-after-body/meta.d.ts +4 -0
- package/lib/no-content-after-body/meta.js +3 -0
- package/lib/no-contradictory-aria-prop/index.d.ts +10 -0
- package/lib/no-contradictory-aria-prop/index.js +34 -0
- package/lib/{wai-aria-abstract-role → no-default-aria-value}/index.d.ts +0 -1
- package/lib/{wai-aria-default-value → no-default-aria-value}/index.js +0 -1
- package/lib/no-default-value/index.d.ts +0 -7
- package/lib/no-default-value/index.js +0 -7
- package/lib/no-default-value/meta.d.ts +0 -1
- package/lib/no-default-value/meta.js +0 -1
- package/lib/no-deprecated-aria-prop/index.d.ts +3 -0
- package/lib/{wai-aria-deprecated-props → no-deprecated-aria-prop}/index.js +0 -1
- package/lib/no-deprecated-attr/index.d.ts +2 -0
- package/lib/{deprecated-attr → no-deprecated-attr}/index.js +5 -9
- package/lib/no-deprecated-attr/meta.d.ts +4 -0
- package/lib/no-deprecated-attr/meta.js +3 -0
- package/lib/no-deprecated-element/index.d.ts +2 -0
- package/lib/no-deprecated-element/index.js +27 -0
- package/lib/no-deprecated-element/meta.d.ts +4 -0
- package/lib/no-deprecated-element/meta.js +3 -0
- package/lib/no-deprecated-role/index.d.ts +3 -0
- package/lib/{wai-aria-deprecated-role → no-deprecated-role}/index.js +0 -1
- package/lib/no-disallowed-ancestor/index.d.ts +2 -0
- package/lib/no-disallowed-ancestor/index.js +25 -0
- package/lib/no-disallowed-ancestor/meta.d.ts +4 -0
- package/lib/no-disallowed-ancestor/meta.js +3 -0
- package/lib/no-disallowed-attr/index.d.ts +28 -0
- package/lib/no-disallowed-attr/index.js +77 -0
- package/lib/no-disallowed-attr/meta.d.ts +4 -0
- package/lib/no-disallowed-attr/meta.js +3 -0
- package/lib/no-duplicate-attr/index.d.ts +2 -0
- package/lib/{attr-duplication → no-duplicate-attr}/index.js +0 -7
- package/lib/no-duplicate-attr/meta.d.ts +6 -0
- package/lib/no-duplicate-attr/meta.js +10 -0
- package/lib/no-duplicate-autofocus/index.d.ts +0 -5
- package/lib/no-duplicate-autofocus/index.js +20 -6
- package/lib/no-duplicate-autofocus/meta.d.ts +1 -1
- package/lib/no-duplicate-autofocus/meta.js +1 -1
- package/lib/no-duplicate-dt/index.d.ts +0 -6
- package/lib/no-duplicate-dt/index.js +1 -6
- package/lib/no-duplicate-dt/meta.d.ts +1 -2
- package/lib/no-duplicate-dt/meta.js +1 -2
- package/lib/no-duplicate-h1/index.d.ts +18 -0
- package/lib/no-duplicate-h1/index.js +41 -0
- package/lib/no-duplicate-h1/meta.d.ts +4 -0
- package/lib/no-duplicate-h1/meta.js +3 -0
- package/lib/no-duplicate-id/index.d.ts +2 -0
- package/lib/{id-duplication → no-duplicate-id}/index.js +0 -7
- package/lib/no-duplicate-id/meta.d.ts +4 -0
- package/lib/no-duplicate-id/meta.js +3 -0
- package/lib/no-duplicate-sibling-attr/index.d.ts +2 -0
- package/lib/no-duplicate-sibling-attr/index.js +35 -0
- package/lib/no-duplicate-sibling-attr/meta.d.ts +4 -0
- package/lib/no-duplicate-sibling-attr/meta.js +3 -0
- package/lib/no-duplicate-visible-main/index.d.ts +0 -1
- package/lib/no-duplicate-visible-main/index.js +0 -1
- package/lib/no-duplicate-visible-main/meta.d.ts +1 -1
- package/lib/no-duplicate-visible-main/meta.js +1 -1
- package/lib/no-empty-palpable-content/index.d.ts +0 -8
- package/lib/no-empty-palpable-content/index.js +0 -8
- package/lib/no-empty-palpable-content/meta.d.ts +1 -2
- package/lib/no-empty-palpable-content/meta.js +1 -2
- package/lib/no-empty-table-track/index.d.ts +12 -0
- package/lib/no-empty-table-track/index.js +42 -0
- package/lib/no-empty-table-track/meta.d.ts +4 -0
- package/lib/no-empty-table-track/meta.js +3 -0
- package/lib/no-event-handler-attr/index.d.ts +7 -0
- package/lib/{no-use-event-handler-attr → no-event-handler-attr}/index.js +0 -11
- package/lib/no-event-handler-attr/meta.d.ts +4 -0
- package/lib/no-event-handler-attr/meta.js +3 -0
- package/lib/no-experimental-features/index.d.ts +9 -0
- package/lib/no-experimental-features/index.js +53 -0
- package/lib/no-experimental-features/meta.d.ts +4 -0
- package/lib/no-experimental-features/meta.js +3 -0
- package/lib/no-extra-selected-options/index.d.ts +10 -0
- package/lib/no-extra-selected-options/index.js +37 -0
- package/lib/no-extra-selected-options/meta.d.ts +4 -0
- package/lib/no-extra-selected-options/meta.js +3 -0
- package/lib/no-focusable-in-aria-hidden/index.d.ts +3 -0
- package/lib/{wai-aria-interaction-in-hidden → no-focusable-in-aria-hidden}/index.js +0 -1
- package/lib/no-focusable-in-aria-hidden/meta.d.ts +4 -0
- package/lib/no-focusable-in-aria-hidden/meta.js +3 -0
- package/lib/no-hardcoded-id/index.d.ts +2 -0
- package/lib/{no-hard-code-id → no-hardcoded-id}/index.js +0 -8
- package/lib/no-hardcoded-id/meta.d.ts +4 -0
- package/lib/no-hardcoded-id/meta.js +3 -0
- package/lib/no-ineffective-attr/index.d.ts +2 -0
- package/lib/{ineffective-attr → no-ineffective-attr}/index.js +0 -7
- package/lib/no-ineffective-attr/meta.d.ts +5 -0
- package/lib/no-ineffective-attr/meta.js +4 -0
- package/lib/no-input-file-value/index.d.ts +10 -0
- package/lib/no-input-file-value/index.js +41 -0
- package/lib/no-input-file-value/meta.d.ts +4 -0
- package/lib/no-input-file-value/meta.js +3 -0
- package/lib/no-invalid-aria-prop-value/index.d.ts +3 -0
- package/lib/{wai-aria-value → no-invalid-aria-prop-value}/index.js +0 -1
- package/lib/no-invalid-aria-prop-value/meta.d.ts +4 -0
- package/lib/no-invalid-aria-prop-value/meta.js +3 -0
- package/lib/no-invalid-attr-value/index.d.ts +27 -0
- package/lib/no-invalid-attr-value/index.js +83 -0
- package/lib/no-invalid-attr-value/meta.d.ts +4 -0
- package/lib/no-invalid-attr-value/meta.js +3 -0
- package/lib/no-malformed-character-reference/index.d.ts +2 -0
- package/lib/no-malformed-character-reference/index.js +38 -0
- package/lib/no-malformed-character-reference/meta.d.ts +5 -0
- package/lib/no-malformed-character-reference/meta.js +20 -0
- package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/index.js +13 -3
- package/lib/no-mismatched-aspect-ratio/meta.d.ts +4 -0
- package/lib/no-mismatched-aspect-ratio/meta.js +3 -0
- package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/resolve-image-size.js +8 -2
- package/lib/no-mixed-srcset-descriptors/index.d.ts +12 -0
- package/lib/no-mixed-srcset-descriptors/index.js +47 -0
- package/lib/no-mixed-srcset-descriptors/meta.d.ts +4 -0
- package/lib/no-mixed-srcset-descriptors/meta.js +3 -0
- package/lib/no-nested-top-level-landmark/index.d.ts +10 -0
- package/lib/no-nested-top-level-landmark/index.js +52 -0
- package/lib/no-nested-top-level-landmark/meta.d.ts +4 -0
- package/lib/no-nested-top-level-landmark/meta.js +3 -0
- package/lib/no-nonstandard-features/index.d.ts +9 -0
- package/lib/no-nonstandard-features/index.js +53 -0
- package/lib/no-nonstandard-features/meta.d.ts +4 -0
- package/lib/no-nonstandard-features/meta.js +3 -0
- package/lib/no-obsolete-attr/index.d.ts +2 -0
- package/lib/no-obsolete-attr/index.js +27 -0
- package/lib/no-obsolete-attr/meta.d.ts +4 -0
- package/lib/no-obsolete-attr/meta.js +3 -0
- package/lib/no-obsolete-doctype/index.d.ts +2 -0
- package/lib/{doctype → no-obsolete-doctype}/index.js +9 -16
- package/lib/no-obsolete-doctype/meta.d.ts +4 -0
- package/lib/no-obsolete-doctype/meta.js +3 -0
- package/lib/no-obsolete-element/index.d.ts +2 -0
- package/lib/{deprecated-element → no-obsolete-element}/index.js +6 -10
- package/lib/no-obsolete-element/meta.d.ts +4 -0
- package/lib/no-obsolete-element/meta.js +3 -0
- package/lib/no-orphaned-end-tag/index.d.ts +0 -7
- package/lib/no-orphaned-end-tag/index.js +0 -7
- package/lib/no-orphaned-end-tag/meta.d.ts +2 -2
- package/lib/no-orphaned-end-tag/meta.js +5 -2
- package/lib/no-prohibited-naming/index.d.ts +8 -0
- package/lib/no-prohibited-naming/index.js +36 -0
- package/lib/no-prohibited-naming/meta.d.ts +4 -0
- package/lib/no-prohibited-naming/meta.js +3 -0
- package/lib/{use-list → no-pseudo-list}/index.d.ts +1 -8
- package/lib/{use-list → no-pseudo-list}/index.js +0 -7
- package/lib/no-pseudo-list/meta.d.ts +4 -0
- package/lib/no-pseudo-list/meta.js +3 -0
- package/lib/{redundant-accessible-name → no-redundant-accessible-name}/index.d.ts +0 -4
- package/lib/{redundant-accessible-name → no-redundant-accessible-name}/index.js +0 -4
- package/lib/no-redundant-accessible-name/meta.d.ts +4 -0
- package/lib/no-redundant-accessible-name/meta.js +3 -0
- package/lib/no-redundant-aria-prop/index.d.ts +10 -0
- package/lib/{wai-aria-implicit-props → no-redundant-aria-prop}/index.js +9 -3
- package/lib/no-redundant-aria-prop/meta.d.ts +4 -0
- package/lib/no-redundant-aria-prop/meta.js +3 -0
- package/lib/no-redundant-role/index.d.ts +3 -0
- package/lib/{wai-aria-implicit-role → no-redundant-role}/index.js +0 -1
- package/lib/no-redundant-role/meta.d.ts +4 -0
- package/lib/no-redundant-role/meta.js +3 -0
- package/lib/no-refer-to-non-existent-id/index.d.ts +0 -9
- package/lib/no-refer-to-non-existent-id/index.js +1 -62
- package/lib/no-refer-to-non-existent-id/meta.d.ts +1 -2
- package/lib/no-refer-to-non-existent-id/meta.js +1 -2
- package/lib/no-restricted-attr/index.d.ts +27 -0
- package/lib/no-restricted-attr/index.js +96 -0
- package/lib/no-restricted-attr/meta.d.ts +4 -0
- package/lib/no-restricted-attr/meta.js +3 -0
- package/lib/no-restricted-element/index.d.ts +2 -0
- package/lib/{disallowed-element → no-restricted-element}/index.js +7 -8
- package/lib/no-restricted-element/meta.d.ts +4 -0
- package/lib/no-restricted-element/meta.js +3 -0
- package/lib/no-skipped-heading-level/index.d.ts +13 -0
- package/lib/{heading-levels → no-skipped-heading-level}/index.js +10 -5
- package/lib/no-skipped-heading-level/meta.d.ts +4 -0
- package/lib/no-skipped-heading-level/meta.js +3 -0
- package/lib/no-stray-head-or-body-tag/index.d.ts +28 -0
- package/lib/no-stray-head-or-body-tag/index.js +61 -0
- package/lib/no-stray-head-or-body-tag/meta.d.ts +4 -0
- package/lib/no-stray-head-or-body-tag/meta.js +3 -0
- package/lib/no-table-cell-overlap/index.d.ts +12 -0
- package/lib/no-table-cell-overlap/index.js +30 -0
- package/lib/no-table-cell-overlap/meta.d.ts +4 -0
- package/lib/no-table-cell-overlap/meta.js +3 -0
- package/lib/no-table-span-overflow/index.d.ts +12 -0
- package/lib/no-table-span-overflow/index.js +37 -0
- package/lib/no-table-span-overflow/meta.d.ts +4 -0
- package/lib/no-table-span-overflow/meta.js +3 -0
- package/lib/no-unclosed-element-at-eof/index.d.ts +2 -0
- package/lib/no-unclosed-element-at-eof/index.js +86 -0
- package/lib/no-unclosed-element-at-eof/meta.d.ts +4 -0
- package/lib/no-unclosed-element-at-eof/meta.js +3 -0
- package/lib/no-unescaped-char/index.d.ts +14 -0
- package/lib/{character-reference → no-unescaped-char}/index.js +31 -20
- package/lib/no-unescaped-char/meta.d.ts +4 -0
- package/lib/no-unescaped-char/meta.js +3 -0
- package/lib/{invalid-attr → no-unknown-attr}/index.d.ts +4 -19
- package/lib/no-unknown-attr/index.js +91 -0
- package/lib/no-unknown-attr/meta.d.ts +4 -0
- package/lib/no-unknown-attr/meta.js +3 -0
- package/lib/no-unknown-role/index.d.ts +3 -0
- package/lib/{wai-aria-non-existent-role → no-unknown-role}/index.js +0 -1
- package/lib/no-unknown-role/meta.d.ts +4 -0
- package/lib/no-unknown-role/meta.js +3 -0
- package/lib/no-unpaired-srcset-sizes/index.d.ts +12 -0
- package/lib/no-unpaired-srcset-sizes/index.js +77 -0
- package/lib/no-unpaired-srcset-sizes/meta.d.ts +4 -0
- package/lib/no-unpaired-srcset-sizes/meta.js +3 -0
- package/lib/{no-unsupported-features → no-unsupported-browser-features}/index.d.ts +1 -10
- package/lib/no-unsupported-browser-features/index.js +81 -0
- package/lib/no-unsupported-browser-features/meta.d.ts +4 -0
- package/lib/no-unsupported-browser-features/meta.js +3 -0
- package/lib/permitted-contents/index.d.ts +0 -18
- package/lib/permitted-contents/index.js +0 -78
- package/lib/permitted-contents/meta.d.ts +1 -2
- package/lib/permitted-contents/meta.js +1 -2
- package/lib/permitted-contents/represent-transparent-nodes.js +15 -6
- package/lib/permitted-roles/index.d.ts +3 -0
- package/lib/{wai-aria-permitted-roles → permitted-roles}/index.js +0 -1
- package/lib/permitted-roles/meta.d.ts +4 -0
- package/lib/permitted-roles/meta.js +3 -0
- package/lib/placeholder-label-option/index.d.ts +10 -4
- package/lib/placeholder-label-option/index.js +30 -17
- package/lib/placeholder-label-option/meta.d.ts +1 -2
- package/lib/placeholder-label-option/meta.js +1 -2
- package/lib/progress-value-bounds/index.d.ts +10 -0
- package/lib/progress-value-bounds/index.js +59 -0
- package/lib/progress-value-bounds/meta.d.ts +4 -0
- package/lib/progress-value-bounds/meta.js +3 -0
- package/lib/require-accessible-name/index.d.ts +0 -7
- package/lib/require-accessible-name/index.js +0 -7
- package/lib/require-accessible-name/meta.d.ts +0 -1
- package/lib/require-accessible-name/meta.js +0 -1
- package/lib/require-adjacent-popover/index.d.ts +2 -0
- package/lib/{neighbor-popovers → require-adjacent-popover}/index.js +1 -8
- package/lib/require-adjacent-popover/meta.d.ts +4 -0
- package/lib/require-adjacent-popover/meta.js +3 -0
- package/lib/require-ancestor/index.d.ts +2 -0
- package/lib/require-ancestor/index.js +29 -0
- package/lib/require-ancestor/meta.d.ts +4 -0
- package/lib/require-ancestor/meta.js +3 -0
- package/lib/require-aria-prop/index.d.ts +3 -0
- package/lib/{wai-aria-required-props → require-aria-prop}/index.js +0 -1
- package/lib/require-aria-prop/meta.d.ts +4 -0
- package/lib/require-aria-prop/meta.js +3 -0
- package/lib/{required-attr → require-attr}/index.d.ts +2 -9
- package/lib/{required-attr → require-attr}/index.js +0 -7
- package/lib/require-attr/meta.d.ts +4 -0
- package/lib/require-attr/meta.js +3 -0
- package/lib/require-datetime/index.d.ts +0 -8
- package/lib/require-datetime/index.js +0 -8
- package/lib/require-datetime/meta.d.ts +1 -2
- package/lib/require-datetime/meta.js +1 -2
- package/lib/require-dialog-autofocus/index.d.ts +0 -10
- package/lib/require-dialog-autofocus/index.js +0 -10
- package/lib/require-dialog-autofocus/meta.d.ts +0 -1
- package/lib/require-dialog-autofocus/meta.js +0 -1
- package/lib/require-doctype/index.d.ts +2 -0
- package/lib/require-doctype/index.js +19 -0
- package/lib/require-doctype/meta.d.ts +5 -0
- package/lib/require-doctype/meta.js +10 -0
- package/lib/{required-element → require-element}/index.d.ts +1 -9
- package/lib/{required-element → require-element}/index.js +0 -8
- package/lib/require-element/meta.d.ts +4 -0
- package/lib/require-element/meta.js +3 -0
- package/lib/require-end-tag/index.d.ts +2 -0
- package/lib/{end-tag → require-end-tag}/index.js +0 -7
- package/lib/require-end-tag/meta.d.ts +4 -0
- package/lib/require-end-tag/meta.js +3 -0
- package/lib/require-h1/index.d.ts +17 -0
- package/lib/{required-h1 → require-h1}/index.js +6 -14
- package/lib/require-h1/meta.d.ts +4 -0
- package/lib/require-h1/meta.js +3 -0
- package/lib/require-landmark-label/index.d.ts +11 -0
- package/lib/require-landmark-label/index.js +55 -0
- package/lib/require-landmark-label/meta.d.ts +4 -0
- package/lib/require-landmark-label/meta.js +3 -0
- package/lib/require-owned-elements/index.d.ts +3 -0
- package/lib/{wai-aria-required-owned-elements → require-owned-elements}/index.js +0 -2
- package/lib/require-owned-elements/meta.d.ts +4 -0
- package/lib/require-owned-elements/meta.js +3 -0
- package/lib/require-parent-role/index.d.ts +3 -0
- package/lib/{wai-aria-required-parent-role → require-parent-role}/index.js +0 -1
- package/lib/require-parent-role/meta.d.ts +4 -0
- package/lib/require-parent-role/meta.js +3 -0
- package/lib/role-supports-aria-prop/index.d.ts +8 -0
- package/lib/{wai-aria-disallowed-props → role-supports-aria-prop}/index.js +11 -10
- package/lib/role-supports-aria-prop/meta.d.ts +4 -0
- package/lib/role-supports-aria-prop/meta.js +3 -0
- package/lib/rule-aliases.d.ts +2 -0
- package/lib/rule-aliases.js +325 -0
- package/lib/sizes-auto-requires-lazy-loading/index.d.ts +14 -0
- package/lib/sizes-auto-requires-lazy-loading/index.js +68 -0
- package/lib/sizes-auto-requires-lazy-loading/meta.d.ts +4 -0
- package/lib/sizes-auto-requires-lazy-loading/meta.js +3 -0
- package/lib/srcset-sizes-constraint/parse-srcset.d.ts +6 -0
- package/lib/srcset-sizes-constraint/parse-srcset.js +6 -0
- package/lib/srcset-sizes-constraint/sibling-helpers.d.ts +21 -0
- package/lib/srcset-sizes-constraint/sibling-helpers.js +37 -0
- package/lib/tab-requires-tabpanel/index.d.ts +3 -0
- package/lib/tab-requires-tabpanel/index.js +21 -0
- package/lib/tab-requires-tabpanel/meta.d.ts +4 -0
- package/lib/tab-requires-tabpanel/meta.js +3 -0
- package/lib/table-row-column-alignment/grid.d.ts +108 -52
- package/lib/table-row-column-alignment/grid.js +276 -203
- package/lib/table-row-column-alignment/types.d.ts +6 -8
- package/lib/usemap-references-map/index.d.ts +14 -0
- package/lib/usemap-references-map/index.js +46 -0
- package/lib/usemap-references-map/meta.d.ts +4 -0
- package/lib/usemap-references-map/meta.js +3 -0
- package/lib/valid-importmap/index.d.ts +2 -0
- package/lib/valid-importmap/index.js +176 -0
- package/lib/valid-importmap/meta.d.ts +4 -0
- package/lib/valid-importmap/meta.js +3 -0
- package/lib/valid-speculation-rules/index.d.ts +2 -0
- package/lib/valid-speculation-rules/index.js +292 -0
- package/lib/valid-speculation-rules/meta.d.ts +4 -0
- package/lib/valid-speculation-rules/meta.js +3 -0
- package/lib/wai-aria/checkings/contradictory-aria-prop.d.ts +23 -0
- package/lib/wai-aria/checkings/{implicit-props.js → contradictory-aria-prop.js} +22 -14
- package/lib/wai-aria/checkings/element-supports-aria-prop.d.ts +20 -0
- package/lib/wai-aria/checkings/element-supports-aria-prop.js +83 -0
- package/lib/wai-aria/checkings/prohibited-naming.d.ts +35 -0
- package/lib/wai-aria/checkings/prohibited-naming.js +64 -0
- package/lib/wai-aria/checkings/redundant-aria-prop.d.ts +23 -0
- package/lib/wai-aria/checkings/redundant-aria-prop.js +53 -0
- package/lib/wai-aria/checkings/required-prop.d.ts +4 -0
- package/lib/wai-aria/checkings/required-prop.js +16 -3
- package/lib/wai-aria/checkings/role-supports-aria-prop.d.ts +20 -0
- package/lib/wai-aria/checkings/role-supports-aria-prop.js +30 -0
- package/lib/wai-aria/checkings/tab-requires-tabpanel.d.ts +19 -0
- package/lib/wai-aria/checkings/tab-requires-tabpanel.js +56 -0
- package/lib/wai-aria/default-options.js +1 -0
- package/lib/wai-aria/types.d.ts +2 -0
- package/package.json +11 -10
- package/schema.json +275 -59
- package/SKILL.md +0 -77
- package/lib/attr-duplication/index.d.ts +0 -9
- package/lib/attr-duplication/meta.d.ts +0 -6
- package/lib/attr-duplication/meta.js +0 -5
- package/lib/character-reference/index.d.ts +0 -12
- package/lib/character-reference/meta.d.ts +0 -5
- package/lib/character-reference/meta.js +0 -4
- package/lib/correct-aspect-ratio/meta.js +0 -3
- package/lib/deprecated-attr/index.d.ts +0 -8
- package/lib/deprecated-attr/meta.d.ts +0 -5
- package/lib/deprecated-attr/meta.js +0 -4
- package/lib/deprecated-element/index.d.ts +0 -8
- package/lib/deprecated-element/meta.d.ts +0 -5
- package/lib/deprecated-element/meta.js +0 -4
- package/lib/disallowed-element/index.d.ts +0 -9
- package/lib/disallowed-element/meta.d.ts +0 -5
- package/lib/disallowed-element/meta.js +0 -4
- package/lib/doctype/index.d.ts +0 -15
- package/lib/doctype/meta.d.ts +0 -5
- package/lib/doctype/meta.js +0 -4
- package/lib/end-tag/index.d.ts +0 -9
- package/lib/end-tag/meta.d.ts +0 -5
- package/lib/end-tag/meta.js +0 -4
- package/lib/heading-levels/index.d.ts +0 -8
- package/lib/heading-levels/meta.d.ts +0 -5
- package/lib/heading-levels/meta.js +0 -4
- package/lib/id-duplication/index.d.ts +0 -9
- package/lib/id-duplication/meta.d.ts +0 -5
- package/lib/id-duplication/meta.js +0 -4
- package/lib/ineffective-attr/index.d.ts +0 -9
- package/lib/ineffective-attr/meta.d.ts +0 -6
- package/lib/ineffective-attr/meta.js +0 -5
- package/lib/invalid-attr/index.js +0 -207
- package/lib/invalid-attr/meta.d.ts +0 -5
- package/lib/invalid-attr/meta.js +0 -4
- package/lib/landmark-roles/index.d.ts +0 -22
- package/lib/landmark-roles/index.js +0 -142
- package/lib/landmark-roles/meta.d.ts +0 -5
- package/lib/landmark-roles/meta.js +0 -4
- package/lib/neighbor-popovers/index.d.ts +0 -10
- package/lib/neighbor-popovers/meta.d.ts +0 -5
- package/lib/neighbor-popovers/meta.js +0 -4
- package/lib/no-hard-code-id/index.d.ts +0 -10
- package/lib/no-hard-code-id/meta.d.ts +0 -5
- package/lib/no-hard-code-id/meta.js +0 -4
- package/lib/no-unsupported-features/index.js +0 -139
- package/lib/no-unsupported-features/meta.d.ts +0 -5
- package/lib/no-unsupported-features/meta.js +0 -4
- package/lib/no-use-event-handler-attr/index.d.ts +0 -18
- package/lib/no-use-event-handler-attr/meta.d.ts +0 -5
- package/lib/no-use-event-handler-attr/meta.js +0 -4
- package/lib/redundant-accessible-name/meta.d.ts +0 -5
- package/lib/redundant-accessible-name/meta.js +0 -4
- package/lib/required-attr/meta.d.ts +0 -5
- package/lib/required-attr/meta.js +0 -4
- package/lib/required-element/meta.d.ts +0 -5
- package/lib/required-element/meta.js +0 -4
- package/lib/required-h1/index.d.ts +0 -18
- package/lib/required-h1/meta.d.ts +0 -5
- package/lib/required-h1/meta.js +0 -4
- package/lib/srcset-sizes-constraint/index.d.ts +0 -6
- package/lib/srcset-sizes-constraint/index.js +0 -108
- package/lib/srcset-sizes-constraint/meta.d.ts +0 -5
- package/lib/srcset-sizes-constraint/meta.js +0 -4
- package/lib/table-row-column-alignment/index.d.ts +0 -10
- package/lib/table-row-column-alignment/index.js +0 -97
- package/lib/table-row-column-alignment/meta.d.ts +0 -5
- package/lib/table-row-column-alignment/meta.js +0 -4
- package/lib/use-list/meta.d.ts +0 -5
- package/lib/use-list/meta.js +0 -4
- package/lib/wai-aria/checkings/disallowed-prop.d.ts +0 -23
- package/lib/wai-aria/checkings/disallowed-prop.js +0 -84
- package/lib/wai-aria/checkings/implicit-props.d.ts +0 -20
- package/lib/wai-aria/index.d.ts +0 -13
- package/lib/wai-aria/index.js +0 -115
- package/lib/wai-aria/meta.d.ts +0 -5
- package/lib/wai-aria/meta.js +0 -4
- package/lib/wai-aria-default-value/index.d.ts +0 -4
- package/lib/wai-aria-default-value/meta.d.ts +0 -5
- package/lib/wai-aria-default-value/meta.js +0 -4
- package/lib/wai-aria-deprecated-props/index.d.ts +0 -4
- package/lib/wai-aria-deprecated-props/meta.d.ts +0 -5
- package/lib/wai-aria-deprecated-props/meta.js +0 -4
- package/lib/wai-aria-disallowed-props/index.d.ts +0 -4
- package/lib/wai-aria-disallowed-props/meta.d.ts +0 -5
- package/lib/wai-aria-disallowed-props/meta.js +0 -4
- package/lib/wai-aria-implicit-props/index.d.ts +0 -4
- package/lib/wai-aria-implicit-props/meta.d.ts +0 -5
- package/lib/wai-aria-implicit-props/meta.js +0 -4
- package/lib/wai-aria-implicit-role/index.d.ts +0 -4
- package/lib/wai-aria-interaction-in-hidden/index.d.ts +0 -4
- package/lib/wai-aria-interaction-in-hidden/meta.d.ts +0 -5
- package/lib/wai-aria-interaction-in-hidden/meta.js +0 -4
- package/lib/wai-aria-no-global-prop/index.d.ts +0 -4
- package/lib/wai-aria-no-global-prop/meta.d.ts +0 -5
- package/lib/wai-aria-no-global-prop/meta.js +0 -4
- package/lib/wai-aria-non-existent-role/index.d.ts +0 -4
- package/lib/wai-aria-permitted-roles/index.d.ts +0 -4
- package/lib/wai-aria-presentational-children/index.d.ts +0 -4
- package/lib/wai-aria-presentational-children/meta.d.ts +0 -5
- package/lib/wai-aria-presentational-children/meta.js +0 -4
- package/lib/wai-aria-required-parent-role/index.d.ts +0 -4
- package/lib/wai-aria-value/index.d.ts +0 -4
- package/lib/wai-aria-value/meta.d.ts +0 -5
- package/lib/wai-aria-value/meta.js +0 -4
- /package/lib/{wai-aria-abstract-role → aria-prop-requires-role}/meta.d.ts +0 -0
- /package/lib/{wai-aria-abstract-role → aria-prop-requires-role}/meta.js +0 -0
- /package/lib/{wai-aria-deprecated-role → element-supports-aria-prop}/meta.d.ts +0 -0
- /package/lib/{wai-aria-deprecated-role → element-supports-aria-prop}/meta.js +0 -0
- /package/lib/{wai-aria-implicit-role → no-abstract-role}/meta.d.ts +0 -0
- /package/lib/{wai-aria-implicit-role → no-abstract-role}/meta.js +0 -0
- /package/lib/{wai-aria-non-existent-role → no-aria-on-presentational-children}/meta.d.ts +0 -0
- /package/lib/{wai-aria-non-existent-role → no-aria-on-presentational-children}/meta.js +0 -0
- /package/lib/{wai-aria-permitted-roles → no-contradictory-aria-prop}/meta.d.ts +0 -0
- /package/lib/{wai-aria-permitted-roles → no-contradictory-aria-prop}/meta.js +0 -0
- /package/lib/{wai-aria-required-owned-elements → no-default-aria-value}/meta.d.ts +0 -0
- /package/lib/{wai-aria-required-owned-elements → no-default-aria-value}/meta.js +0 -0
- /package/lib/{wai-aria-required-parent-role → no-deprecated-aria-prop}/meta.d.ts +0 -0
- /package/lib/{wai-aria-required-parent-role → no-deprecated-aria-prop}/meta.js +0 -0
- /package/lib/{wai-aria-required-props → no-deprecated-role}/meta.d.ts +0 -0
- /package/lib/{wai-aria-required-props → no-deprecated-role}/meta.js +0 -0
- /package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/index.d.ts +0 -0
- /package/lib/{correct-aspect-ratio → no-mismatched-aspect-ratio}/resolve-image-size.d.ts +0 -0
- /package/lib/{no-unsupported-features → no-unsupported-browser-features}/compat-data.d.ts +0 -0
- /package/lib/{no-unsupported-features → no-unsupported-browser-features}/compat-data.js +0 -0
- /package/lib/{no-unsupported-features → no-unsupported-browser-features}/resolve-browsers.d.ts +0 -0
- /package/lib/{no-unsupported-features → no-unsupported-browser-features}/resolve-browsers.js +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import { isVoidElement } from '@markuplint/ml-spec';
|
|
3
|
+
import meta from './meta.js';
|
|
4
|
+
/**
|
|
5
|
+
* HTML LS "in body" insertion mode, "An end-of-file token":
|
|
6
|
+
*
|
|
7
|
+
* > If there is a node in the stack of open elements that is not either a dd
|
|
8
|
+
* > element, a dt element, an li element, an optgroup element, an option
|
|
9
|
+
* > element, a p element, an rb element, an rp element, an rt element, an
|
|
10
|
+
* > rtc element, a tbody element, a td element, a tfoot element, a th
|
|
11
|
+
* > element, a thead element, a tr element, the body element, or the html
|
|
12
|
+
* > element, then this is a parse error.
|
|
13
|
+
*
|
|
14
|
+
* Every name in that list has its own optional-tag-omission rule elsewhere in
|
|
15
|
+
* the spec, so parse5 never records an explicit end tag for it even in
|
|
16
|
+
* well-formed documents; excluding them keeps this rule from re-flagging
|
|
17
|
+
* markup that `end-tag` (a style preference, not this spec-conformance rule)
|
|
18
|
+
* already tolerates. Anything else still open when the source runs out —
|
|
19
|
+
* e.g. `<picture>`, which has no such omission rule — is this parse error.
|
|
20
|
+
*
|
|
21
|
+
* @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody
|
|
22
|
+
*/
|
|
23
|
+
const EOF_EXEMPT_NAMES = new Set([
|
|
24
|
+
'dd',
|
|
25
|
+
'dt',
|
|
26
|
+
'li',
|
|
27
|
+
'optgroup',
|
|
28
|
+
'option',
|
|
29
|
+
'p',
|
|
30
|
+
'rb',
|
|
31
|
+
'rp',
|
|
32
|
+
'rt',
|
|
33
|
+
'rtc',
|
|
34
|
+
'tbody',
|
|
35
|
+
'td',
|
|
36
|
+
'tfoot',
|
|
37
|
+
'th',
|
|
38
|
+
'thead',
|
|
39
|
+
'tr',
|
|
40
|
+
'body',
|
|
41
|
+
'html',
|
|
42
|
+
]);
|
|
43
|
+
/**
|
|
44
|
+
* The end offset of a node's own content, following the last descendant to
|
|
45
|
+
* its end when the node itself has no end tag. Elements without an explicit
|
|
46
|
+
* end tag only carry a start-tag span in `raw`/`startOffset`
|
|
47
|
+
* (`@markuplint/html-parser`'s `nodeize`), so their children's own closing
|
|
48
|
+
* position is the only way to find where the element's content actually
|
|
49
|
+
* ends in the source.
|
|
50
|
+
*/
|
|
51
|
+
function deepEndOffset(node) {
|
|
52
|
+
if (node.closeTag) {
|
|
53
|
+
return node.closeTag.startOffset + node.closeTag.raw.length;
|
|
54
|
+
}
|
|
55
|
+
const last = node.childNodes ? [...node.childNodes].at(-1) : undefined;
|
|
56
|
+
if (last) {
|
|
57
|
+
return deepEndOffset(last);
|
|
58
|
+
}
|
|
59
|
+
return node.startOffset + node.raw.length;
|
|
60
|
+
}
|
|
61
|
+
export default createRule({
|
|
62
|
+
meta: meta,
|
|
63
|
+
async verify({ document, report, t }) {
|
|
64
|
+
const eof = document.raw.length;
|
|
65
|
+
await document.walkOn('Element', el => {
|
|
66
|
+
if (el.isOmitted)
|
|
67
|
+
return;
|
|
68
|
+
if (isVoidElement(el))
|
|
69
|
+
return;
|
|
70
|
+
if (el.closeTag != null)
|
|
71
|
+
return;
|
|
72
|
+
if (EOF_EXEMPT_NAMES.has(el.localName))
|
|
73
|
+
return;
|
|
74
|
+
// Only the case where nothing but whitespace follows is the EOF
|
|
75
|
+
// case this rule targets — content implicitly closing the element
|
|
76
|
+
// mid-document (e.g. a sibling autoclosing it) is out of scope.
|
|
77
|
+
const contentEnd = deepEndOffset(el);
|
|
78
|
+
if (document.raw.slice(contentEnd, eof).trim() !== '')
|
|
79
|
+
return;
|
|
80
|
+
report({
|
|
81
|
+
scope: el,
|
|
82
|
+
message: t('{0} is not closed at the end of the file', t('the "{0}" {1}', el.localName, 'element')),
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the `no-unescaped-char` rule.
|
|
3
|
+
*/
|
|
4
|
+
type Option = {
|
|
5
|
+
/**
|
|
6
|
+
* When `true`, also flags `>`, `"`, and every bare `&` (not just a
|
|
7
|
+
* literal `<`). Off by default because HTML LS only prohibits `<` and
|
|
8
|
+
* ambiguous ampersands unescaped — `>` and `"` are conforming as-is, and
|
|
9
|
+
* a bare `&` not shaped like a reference attempt is not "ambiguous".
|
|
10
|
+
*/
|
|
11
|
+
strict?: boolean;
|
|
12
|
+
};
|
|
13
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Option>>;
|
|
14
|
+
export default _default;
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import { createRule, getLocationFromChars } from '@markuplint/ml-core';
|
|
2
2
|
import meta from './meta.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* and attribute values
|
|
4
|
+
* HTML LS §13.1.2.3–4 prohibits exactly two things unescaped in text content
|
|
5
|
+
* and attribute values: a literal `<`, and an "ambiguous ampersand" (`&`
|
|
6
|
+
* followed by ASCII alphanumerics and a `;` that don't form a recognized
|
|
7
|
+
* named/numeric reference). Detecting the latter precisely requires
|
|
8
|
+
* validating the name against the full named-character-reference table —
|
|
9
|
+
* work parse5's tokenizer already does, surfaced as `no-malformed-character-reference`
|
|
10
|
+
* (`unknown-named-character-reference` and friends). So by default this rule
|
|
11
|
+
* only checks `<`; `strict` restores the pre-split behavior of also flagging
|
|
12
|
+
* `>`, `"`, and every bare `&` (entity-shaped sequences still exempted, so
|
|
13
|
+
* `&` is never flagged even in strict mode).
|
|
6
14
|
*/
|
|
7
|
-
|
|
15
|
+
/** Characters that must always be escaped, regardless of `strict`. */
|
|
16
|
+
const defaultChars = ['<'];
|
|
17
|
+
/** Characters `strict: true` additionally requires to be escaped. */
|
|
18
|
+
const strictChars = ['"', '&', '<', '>'];
|
|
8
19
|
/**
|
|
9
20
|
* Parent elements whose text content is exempt from character reference checks
|
|
10
21
|
* because their content is not parsed as HTML.
|
|
11
22
|
*/
|
|
12
23
|
const ignoreParentElement = new Set(['script', 'style']);
|
|
13
|
-
/**
|
|
14
|
-
* Rule that checks whether special characters are properly escaped as
|
|
15
|
-
* character references.
|
|
16
|
-
*
|
|
17
|
-
* Scans text nodes and attribute values for the characters `"`, `&`, `<`,
|
|
18
|
-
* and `>` that are not already part of a valid character reference. Text
|
|
19
|
-
* inside `<script>` and `<style>` elements is excluded, as are bogus
|
|
20
|
-
* text nodes (e.g., orphaned end tags).
|
|
21
|
-
*/
|
|
22
24
|
export default createRule({
|
|
23
25
|
meta: meta,
|
|
26
|
+
defaultOptions: {},
|
|
24
27
|
async verify({ document, report, t }) {
|
|
25
28
|
const targetNodes = [];
|
|
26
29
|
await document.walkOn('Text', node => {
|
|
@@ -50,21 +53,29 @@ export default createRule({
|
|
|
50
53
|
continue;
|
|
51
54
|
}
|
|
52
55
|
const valueNode = attr.valueNode;
|
|
56
|
+
if (!valueNode) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
53
59
|
targetNodes.push({
|
|
54
60
|
scope: node,
|
|
55
|
-
line: valueNode
|
|
56
|
-
col: valueNode
|
|
57
|
-
raw: valueNode
|
|
61
|
+
line: valueNode.startLine,
|
|
62
|
+
col: valueNode.startCol,
|
|
63
|
+
raw: valueNode.raw,
|
|
58
64
|
message,
|
|
59
65
|
});
|
|
60
66
|
}
|
|
61
67
|
});
|
|
62
68
|
for (const targetNode of targetNodes) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
const strict = targetNode.scope.rule.options?.strict ?? false;
|
|
70
|
+
const chars = strict ? strictChars : defaultChars;
|
|
71
|
+
// Entity-shaped sequences (`&name;`, `{`, ``) are never
|
|
72
|
+
// flagged, valid name or not — an unrecognized name is
|
|
73
|
+
// `no-malformed-character-reference`'s concern (it mirrors parse5's
|
|
74
|
+
// `unknown-named-character-reference`), not this rule's.
|
|
75
|
+
const escapedText = strict
|
|
76
|
+
? targetNode.raw.replaceAll(/&(?:[a-z]+|#\d+|#x[\da-f]+);/gi, $0 => '*'.repeat($0.length))
|
|
77
|
+
: targetNode.raw;
|
|
78
|
+
for (const location of getLocationFromChars(chars, escapedText, targetNode.line, targetNode.col)) {
|
|
68
79
|
report({
|
|
69
80
|
scope: targetNode.scope,
|
|
70
81
|
message: targetNode.message,
|
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
import type { AttributeType } from '@markuplint/ml-spec';
|
|
2
2
|
import type { Pattern } from '@markuplint/types';
|
|
3
3
|
/**
|
|
4
|
-
* Configuration options for the `
|
|
4
|
+
* Configuration options for the `no-unknown-attr` rule.
|
|
5
5
|
*/
|
|
6
6
|
type Option = {
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Attribute names to treat as known, beyond what the spec defines.
|
|
9
|
+
* The value type is used by `no-invalid-attr-value` to validate the
|
|
10
|
+
* attribute's value; here it only determines whether the name is known.
|
|
10
11
|
*
|
|
11
12
|
* @since 3.7.0
|
|
12
13
|
*/
|
|
13
14
|
allowAttrs?: (string | Attr)[] | Record<string, AttributeType | Pattern>;
|
|
14
|
-
/**
|
|
15
|
-
* Attributes to disallow in addition to spec restrictions.
|
|
16
|
-
*
|
|
17
|
-
* @since 3.7.0
|
|
18
|
-
*/
|
|
19
|
-
disallowAttrs?: (string | Attr)[] | Record<string, AttributeType | Pattern>;
|
|
20
15
|
/** Attribute name prefix(es) to ignore during validation. */
|
|
21
16
|
ignoreAttrNamePrefix?: string | string[];
|
|
22
17
|
/** Whether to allow additional properties for pretender elements (defaults to `true`). */
|
|
@@ -31,15 +26,5 @@ type Attr = {
|
|
|
31
26
|
/** The expected attribute value type or validation rule. */
|
|
32
27
|
value: AttributeType | Pattern;
|
|
33
28
|
};
|
|
34
|
-
/**
|
|
35
|
-
* Rule that validates attributes against the HTML spec, allowed lists,
|
|
36
|
-
* and disallowed lists.
|
|
37
|
-
*
|
|
38
|
-
* Checks each attribute for: existence in the spec, correct value type,
|
|
39
|
-
* allowed/disallowed overrides from configuration, and typo suggestions
|
|
40
|
-
* via candidate matching. Supports `allowAttrs` and `disallowAttrs`.
|
|
41
|
-
* Non-existent attributes on elements that allow additional properties
|
|
42
|
-
* (pretenders) can be optionally permitted.
|
|
43
|
-
*/
|
|
44
29
|
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Option>>;
|
|
45
30
|
export default _default;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createRule, getAttrSpecs, getSpec } from '@markuplint/ml-core';
|
|
2
|
+
import { resolveAttrEligibility, suggestionSuffix } from '../attr-eligibility.js';
|
|
3
|
+
import meta from './meta.js';
|
|
4
|
+
function allowedNames(allowAttrs) {
|
|
5
|
+
if (!allowAttrs) {
|
|
6
|
+
return new Set();
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(allowAttrs)) {
|
|
9
|
+
return new Set(allowAttrs.map(a => (typeof a === 'string' ? a : a.name)));
|
|
10
|
+
}
|
|
11
|
+
return new Set(Object.keys(allowAttrs));
|
|
12
|
+
}
|
|
13
|
+
export default createRule({
|
|
14
|
+
meta: meta,
|
|
15
|
+
defaultOptions: {},
|
|
16
|
+
async verify({ document, report, t }) {
|
|
17
|
+
await document.walkOn('Attr', attr => {
|
|
18
|
+
if (attr.isDirective) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const allowToAddPropertiesForPretender = attr.rule.options.allowToAddPropertiesForPretender ?? true;
|
|
22
|
+
const name = attr.name;
|
|
23
|
+
const attrName = attr.nameNode;
|
|
24
|
+
// A parser-supplied IDL naming suggestion (e.g. `tabindex` -> `tabIndex`
|
|
25
|
+
// in JSX) takes priority over spec-driven typo detection below.
|
|
26
|
+
if (attr.ownerElement.elementType === 'html' && attr.candidate) {
|
|
27
|
+
report({
|
|
28
|
+
scope: attr,
|
|
29
|
+
line: attrName?.startLine,
|
|
30
|
+
col: attrName?.startCol,
|
|
31
|
+
raw: attrName?.raw,
|
|
32
|
+
message: t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
|
|
33
|
+
t('. ') +
|
|
34
|
+
t('Did you mean "{0}"?', attr.candidate),
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (attr.rule.options.ignoreAttrNamePrefix != null) {
|
|
39
|
+
const prefixes = Array.isArray(attr.rule.options.ignoreAttrNamePrefix)
|
|
40
|
+
? attr.rule.options.ignoreAttrNamePrefix
|
|
41
|
+
: [attr.rule.options.ignoreAttrNamePrefix];
|
|
42
|
+
if (prefixes.some(prefix => name.indexOf(prefix) === 0)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (allowedNames(attr.rule.options.allowAttrs).has(name)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (attr.ownerElement.elementType !== 'html') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const attrSpecs = getAttrSpecs(attr.ownerElement, document.specs);
|
|
53
|
+
if (!attrSpecs) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const eligibility = resolveAttrEligibility(name, attr.ownerElement, attrSpecs);
|
|
57
|
+
let message;
|
|
58
|
+
switch (eligibility.status) {
|
|
59
|
+
case 'unknown': {
|
|
60
|
+
message =
|
|
61
|
+
t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
|
|
62
|
+
suggestionSuffix(t, eligibility.candidate);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case 'case-mismatch': {
|
|
66
|
+
message =
|
|
67
|
+
t('{0} is {1:c}', t('the "{0*}" {1}', name, 'attribute'), 'disallowed') +
|
|
68
|
+
suggestionSuffix(t, eligibility.expectedName);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
default: {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (allowToAddPropertiesForPretender && attr.ownerElement.pretenderContext?.type === 'origin') {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const spec = getSpec(attr.ownerElement, document.specs.specs);
|
|
79
|
+
if (spec?.possibleToAddProperties) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
report({
|
|
83
|
+
scope: attr,
|
|
84
|
+
message,
|
|
85
|
+
line: attrName?.startLine,
|
|
86
|
+
col: attrName?.startCol,
|
|
87
|
+
raw: attrName?.raw,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
});
|
|
@@ -2,7 +2,6 @@ import { createRule, getSpec } from '@markuplint/ml-core';
|
|
|
2
2
|
import { checkingNonExistentRole } from '../wai-aria/checkings/non-existent-role.js';
|
|
3
3
|
import { defaultOptions } from '../wai-aria/default-options.js';
|
|
4
4
|
import meta from './meta.js';
|
|
5
|
-
/** Warns when a role attribute value does not exist in the WAI-ARIA specification. */
|
|
6
5
|
export default createRule({
|
|
7
6
|
meta,
|
|
8
7
|
defaultOptions,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML LS § img/source `srcset` attributes: `sizes` and a width-descriptor
|
|
3
|
+
* `srcset` are mutually required. Split out of the former
|
|
4
|
+
* `srcset-sizes-constraint` rule's Checks 1 and 5, the two directions of this
|
|
5
|
+
* one constraint.
|
|
6
|
+
*
|
|
7
|
+
* `<source>`'s direction (Check 5) is conditional: `sizes` "may" be omitted
|
|
8
|
+
* when the following sibling `<img>` has `loading="lazy"` (auto-sizes
|
|
9
|
+
* support). `<img>`'s direction (Check 1) has no such escape.
|
|
10
|
+
*/
|
|
11
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import { parseSrcset } from '../srcset-sizes-constraint/parse-srcset.js';
|
|
3
|
+
import { findFollowingImg } from '../srcset-sizes-constraint/sibling-helpers.js';
|
|
4
|
+
import meta from './meta.js';
|
|
5
|
+
/**
|
|
6
|
+
* HTML LS § img/source `srcset` attributes: `sizes` and a width-descriptor
|
|
7
|
+
* `srcset` are mutually required. Split out of the former
|
|
8
|
+
* `srcset-sizes-constraint` rule's Checks 1 and 5, the two directions of this
|
|
9
|
+
* one constraint.
|
|
10
|
+
*
|
|
11
|
+
* `<source>`'s direction (Check 5) is conditional: `sizes` "may" be omitted
|
|
12
|
+
* when the following sibling `<img>` has `loading="lazy"` (auto-sizes
|
|
13
|
+
* support). `<img>`'s direction (Check 1) has no such escape.
|
|
14
|
+
*/
|
|
15
|
+
export default createRule({
|
|
16
|
+
meta,
|
|
17
|
+
async verify({ document, report }) {
|
|
18
|
+
await document.walkOn('Element', el => {
|
|
19
|
+
const localName = el.localName;
|
|
20
|
+
// Only check img and source (inside picture) elements
|
|
21
|
+
if (localName !== 'img' && localName !== 'source') {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// source is only relevant inside <picture>
|
|
25
|
+
if (localName === 'source' && el.parentElement?.localName !== 'picture') {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Skip if element has spread attributes (dynamic props)
|
|
29
|
+
if (el.hasSpreadAttr) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const srcsetAttr = el.getAttributeNode('srcset');
|
|
33
|
+
if (!srcsetAttr) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const srcsetIsDynamic = srcsetAttr.isDynamicValue;
|
|
37
|
+
const sizesAttr = el.getAttributeNode('sizes');
|
|
38
|
+
const sizesIsDynamic = sizesAttr?.isDynamicValue;
|
|
39
|
+
// Parse srcset unless dynamic
|
|
40
|
+
const parsed = srcsetIsDynamic ? null : parseSrcset(srcsetAttr.value);
|
|
41
|
+
// sizes present → srcset must use width descriptors
|
|
42
|
+
if (sizesAttr && !sizesIsDynamic && parsed && !parsed.hasWidth) {
|
|
43
|
+
report({
|
|
44
|
+
scope: el,
|
|
45
|
+
line: srcsetAttr.valueNode?.startLine,
|
|
46
|
+
col: srcsetAttr.valueNode?.startCol,
|
|
47
|
+
raw: srcsetAttr.valueNode?.raw,
|
|
48
|
+
message: 'The "srcset" attribute requires width descriptors when the "sizes" attribute is present',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// img / source-in-picture with w descriptors → sizes required.
|
|
52
|
+
//
|
|
53
|
+
// HTML LS § img srcset: unconditional — "the sizes attribute must
|
|
54
|
+
// also be present" when any candidate uses a width descriptor.
|
|
55
|
+
//
|
|
56
|
+
// HTML LS § source: conditional — sizes "may" be present with w
|
|
57
|
+
// descriptors, but the following sibling img must support
|
|
58
|
+
// auto-sizes for it to be omittable. img supports auto-sizes when
|
|
59
|
+
// loading=lazy (the dimensionsAttribute condition is also part of
|
|
60
|
+
// the spec but the lazy attribute is the user-facing trigger).
|
|
61
|
+
if (parsed && parsed.hasWidth && !sizesAttr) {
|
|
62
|
+
// For `<source>`, `findFollowingImg` may return null (malformed
|
|
63
|
+
// <picture> with no img). Optional chaining short-circuits to
|
|
64
|
+
// undefined, and `undefined === 'lazy'` is false → sizes is
|
|
65
|
+
// required. That's the correct fail-closed behaviour: an absent
|
|
66
|
+
// img cannot supply auto-sizes for the source.
|
|
67
|
+
const siblingImgLazy = localName === 'source' && findFollowingImg(el)?.getAttribute('loading') === 'lazy';
|
|
68
|
+
if (!siblingImgLazy) {
|
|
69
|
+
report({
|
|
70
|
+
scope: el,
|
|
71
|
+
message: 'The "sizes" attribute is required when the "srcset" attribute uses width descriptors',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Options for the `no-unsupported-features` rule.
|
|
2
|
+
* Options for the `no-unsupported-browser-features` rule.
|
|
3
3
|
*/
|
|
4
4
|
type Options = {
|
|
5
5
|
/** A browserslist query to override project configuration. */
|
|
@@ -10,15 +10,6 @@ type Options = {
|
|
|
10
10
|
readonly browserslistEnv?: string;
|
|
11
11
|
/** Features to ignore. Element name ("dialog") or attribute pattern ("input[list]"). */
|
|
12
12
|
readonly ignoreFeatures?: readonly string[];
|
|
13
|
-
/** Whether to warn about experimental elements and attributes. */
|
|
14
|
-
readonly checkExperimental?: boolean;
|
|
15
|
-
/** Whether to warn about non-standard elements and attributes. */
|
|
16
|
-
readonly checkNonStandard?: boolean;
|
|
17
13
|
};
|
|
18
|
-
/**
|
|
19
|
-
* Rule that warns when using HTML elements or attributes that are not
|
|
20
|
-
* supported by the project's target browsers (via browserslist),
|
|
21
|
-
* or that are experimental/non-standard.
|
|
22
|
-
*/
|
|
23
14
|
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
|
|
24
15
|
export default _default;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import { checkAttributeSupport, checkElementSupport } from './compat-data.js';
|
|
3
|
+
import meta from './meta.js';
|
|
4
|
+
import { clearBrowserslistCache, resolveTargetBrowsers } from './resolve-browsers.js';
|
|
5
|
+
export default createRule({
|
|
6
|
+
meta: meta,
|
|
7
|
+
defaultSeverity: 'warning',
|
|
8
|
+
defaultOptions: {},
|
|
9
|
+
async verify({ document, report, t }) {
|
|
10
|
+
const options = document.rule.options;
|
|
11
|
+
const targetBrowsers = resolveTargetBrowsers(document.filename, {
|
|
12
|
+
browserslist: options.browserslist,
|
|
13
|
+
browserslistConfig: options.browserslistConfig,
|
|
14
|
+
browserslistEnv: options.browserslistEnv,
|
|
15
|
+
});
|
|
16
|
+
// Without a browserslist configuration, there is nothing to check against.
|
|
17
|
+
if (targetBrowsers == null || targetBrowsers.length === 0) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const ignoreFeatures = new Set(options.ignoreFeatures);
|
|
21
|
+
await document.walkOn('Element', async (el) => {
|
|
22
|
+
// Web components and authored elements (JSX/Vue/Svelte) reach this rule
|
|
23
|
+
// via `pretenders`: they masquerade as a known HTML element on `el.localName`,
|
|
24
|
+
// so BCD lookups below resolve correctly. See #3740.
|
|
25
|
+
if (el.namespaceURI !== 'http://www.w3.org/1999/xhtml' ||
|
|
26
|
+
(el.elementType !== 'html' && el.pretenderContext?.type !== 'pretender')) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const elName = el.localName;
|
|
30
|
+
const elOptions = el.rule.options;
|
|
31
|
+
const elIgnoreFeatures = new Set(elOptions.ignoreFeatures ?? ignoreFeatures);
|
|
32
|
+
if (!elIgnoreFeatures.has(elName)) {
|
|
33
|
+
const unsupported = await checkElementSupport(elName, targetBrowsers);
|
|
34
|
+
if (unsupported.length > 0) {
|
|
35
|
+
report({
|
|
36
|
+
scope: el,
|
|
37
|
+
message: formatUnsupportedMessage(t, elName, 'element', unsupported),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
for (const attr of el.attributes) {
|
|
42
|
+
if (attr.isDirective) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const attrName = attr.name;
|
|
46
|
+
const ignoreKey = `${elName}[${attrName}]`;
|
|
47
|
+
if (elIgnoreFeatures.has(ignoreKey)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const unsupported = await checkAttributeSupport(elName, attrName, targetBrowsers);
|
|
51
|
+
if (unsupported.length > 0) {
|
|
52
|
+
report({
|
|
53
|
+
scope: attr,
|
|
54
|
+
line: attr.nameNode?.startLine,
|
|
55
|
+
col: attr.nameNode?.startCol,
|
|
56
|
+
raw: attr.nameNode?.raw,
|
|
57
|
+
message: formatUnsupportedMessage(t, attrName, 'attribute', unsupported),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
clearBrowserslistCache();
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Format an unsupported feature message listing affected browsers.
|
|
67
|
+
*/
|
|
68
|
+
function formatUnsupportedMessage(t, featureName, featureType, unsupported) {
|
|
69
|
+
const browserDetails = unsupported
|
|
70
|
+
.map(u => {
|
|
71
|
+
if (u.addedVersion === false) {
|
|
72
|
+
if (u.removedVersion) {
|
|
73
|
+
return `${u.displayName} (removed in ${u.removedVersion})`;
|
|
74
|
+
}
|
|
75
|
+
return `${u.displayName} (not supported)`;
|
|
76
|
+
}
|
|
77
|
+
return `${u.displayName} (added in ${u.addedVersion}, target: ${u.targetVersion})`;
|
|
78
|
+
})
|
|
79
|
+
.join(', ');
|
|
80
|
+
return t('{0} is not supported in {1}', t('the "{0*}" {1}', featureName, featureType), browserDetails);
|
|
81
|
+
}
|
|
@@ -1,21 +1,3 @@
|
|
|
1
1
|
import type { Options, TagRule } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* The `permitted-contents` rule validates that each element's child nodes conform
|
|
4
|
-
* to the HTML content model specification. It is the most complex rule in markuplint,
|
|
5
|
-
* implementing a full content model validation engine that handles ordered sequences,
|
|
6
|
-
* quantified patterns (require, optional, oneOrMore, zeroOrMore), choice alternations,
|
|
7
|
-
* transparent content models, and conditional child node branches.
|
|
8
|
-
*
|
|
9
|
-
* For each element, it resolves the applicable content model (from the HTML spec or
|
|
10
|
-
* user-defined tag rules), evaluates the element's children against that model, and
|
|
11
|
-
* reports violations such as unexpected elements, missing required elements, or
|
|
12
|
-
* disallowed content through transparent models. It also checks forbidden ancestor
|
|
13
|
-
* constraints — elements like `<header>`, `<footer>`, `<main>`, and `<address>` must
|
|
14
|
-
* not appear as descendants of certain other elements as defined by the HTML spec.
|
|
15
|
-
* Additionally, it enforces required ancestor constraints (`descendantOf`) — certain
|
|
16
|
-
* elements must appear as descendants of specific other elements. It also validates
|
|
17
|
-
* sibling-unique attribute constraints (`uniqueAttrs`) — certain attributes must not
|
|
18
|
-
* appear on more than one element of the same type within the same parent.
|
|
19
|
-
*/
|
|
20
2
|
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<TagRule[], Options>>;
|
|
21
3
|
export default _default;
|