@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,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enforce the descendant-control constraints on a `<label>` element.
|
|
3
|
+
*
|
|
4
|
+
* Per HTML LS §4.10.4 content model: "Phrasing content, but with no
|
|
5
|
+
* descendant labelable elements unless it is the element's labeled
|
|
6
|
+
* control, and no descendant label elements." The labeled control is
|
|
7
|
+
* either the element whose ID equals the `for` attribute (when set to
|
|
8
|
+
* a labelable element in the same tree) or the first labelable
|
|
9
|
+
* descendant in tree order.
|
|
10
|
+
*
|
|
11
|
+
* Two branches follow from that definition:
|
|
12
|
+
*
|
|
13
|
+
* - `for` resolves to an external labelable element → no descendant
|
|
14
|
+
* form control may appear inside the label (the labeled control is
|
|
15
|
+
* outside).
|
|
16
|
+
* - Otherwise → at most one descendant form control; the first in tree
|
|
17
|
+
* order is the labeled control, any subsequent ones are excess.
|
|
18
|
+
*
|
|
19
|
+
* ID existence itself is delegated to `no-refer-to-non-existent-id`;
|
|
20
|
+
* `for` referencing a non-labelable element is delegated to
|
|
21
|
+
* `label-for-references-labelable`. This rule only inspects the label
|
|
22
|
+
* subtree once the target's category has been classified.
|
|
23
|
+
*
|
|
24
|
+
* The `for` target lookup uses `document.querySelectorAll('[id]')` per
|
|
25
|
+
* matching label, not a cached id map. Kept in sync with
|
|
26
|
+
* `label-for-references-labelable` on purpose — the number of `<label>`
|
|
27
|
+
* elements per document is typically small, so a shared id-index would
|
|
28
|
+
* amortize poorly and split rule ownership across a helper module.
|
|
29
|
+
*/
|
|
30
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, null>>;
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import meta from './meta.js';
|
|
3
|
+
/**
|
|
4
|
+
* The HTML LS list of form-control descendants that may appear under a
|
|
5
|
+
* `<label>` element. Per the spec only one of these may exist per label,
|
|
6
|
+
* and only when the label is not already bound to an external labeled
|
|
7
|
+
* control via `for`.
|
|
8
|
+
*
|
|
9
|
+
* @see https://html.spec.whatwg.org/multipage/forms.html#the-label-element
|
|
10
|
+
*/
|
|
11
|
+
const FORM_CONTROL_SELECTOR = ['button', 'input', 'meter', 'output', 'progress', 'select', 'textarea'].join(',');
|
|
12
|
+
/**
|
|
13
|
+
* Labelable elements per HTML LS §4.10.2 *Categories: Labelable elements*.
|
|
14
|
+
* The set matches `label-for-references-labelable`; kept in sync to
|
|
15
|
+
* classify the target of `for` consistently across both rules.
|
|
16
|
+
*
|
|
17
|
+
* @see https://html.spec.whatwg.org/multipage/forms.html#category-label
|
|
18
|
+
*/
|
|
19
|
+
const LABELABLE_SELECTOR = [
|
|
20
|
+
'button',
|
|
21
|
+
'input:not([type="hidden" i])',
|
|
22
|
+
'meter',
|
|
23
|
+
'output',
|
|
24
|
+
'progress',
|
|
25
|
+
'select',
|
|
26
|
+
'textarea',
|
|
27
|
+
].join(',');
|
|
28
|
+
/**
|
|
29
|
+
* Enforce the descendant-control constraints on a `<label>` element.
|
|
30
|
+
*
|
|
31
|
+
* Per HTML LS §4.10.4 content model: "Phrasing content, but with no
|
|
32
|
+
* descendant labelable elements unless it is the element's labeled
|
|
33
|
+
* control, and no descendant label elements." The labeled control is
|
|
34
|
+
* either the element whose ID equals the `for` attribute (when set to
|
|
35
|
+
* a labelable element in the same tree) or the first labelable
|
|
36
|
+
* descendant in tree order.
|
|
37
|
+
*
|
|
38
|
+
* Two branches follow from that definition:
|
|
39
|
+
*
|
|
40
|
+
* - `for` resolves to an external labelable element → no descendant
|
|
41
|
+
* form control may appear inside the label (the labeled control is
|
|
42
|
+
* outside).
|
|
43
|
+
* - Otherwise → at most one descendant form control; the first in tree
|
|
44
|
+
* order is the labeled control, any subsequent ones are excess.
|
|
45
|
+
*
|
|
46
|
+
* ID existence itself is delegated to `no-refer-to-non-existent-id`;
|
|
47
|
+
* `for` referencing a non-labelable element is delegated to
|
|
48
|
+
* `label-for-references-labelable`. This rule only inspects the label
|
|
49
|
+
* subtree once the target's category has been classified.
|
|
50
|
+
*
|
|
51
|
+
* The `for` target lookup uses `document.querySelectorAll('[id]')` per
|
|
52
|
+
* matching label, not a cached id map. Kept in sync with
|
|
53
|
+
* `label-for-references-labelable` on purpose — the number of `<label>`
|
|
54
|
+
* elements per document is typically small, so a shared id-index would
|
|
55
|
+
* amortize poorly and split rule ownership across a helper module.
|
|
56
|
+
*/
|
|
57
|
+
export default createRule({
|
|
58
|
+
meta: meta,
|
|
59
|
+
defaultValue: true,
|
|
60
|
+
defaultOptions: null,
|
|
61
|
+
async verify({ document, report, t }) {
|
|
62
|
+
await document.walkOn('Element', el => {
|
|
63
|
+
if (el.localName !== 'label')
|
|
64
|
+
return;
|
|
65
|
+
// Pretender labels have unknown descendants until the `as` attribute pins the type.
|
|
66
|
+
if (el.pretenderContext?.type === 'pretender' && !el.hasAttribute('as'))
|
|
67
|
+
return;
|
|
68
|
+
const controls = [...el.querySelectorAll(FORM_CONTROL_SELECTOR)];
|
|
69
|
+
if (controls.length === 0)
|
|
70
|
+
return;
|
|
71
|
+
const forAttr = el.getAttributeNode('for');
|
|
72
|
+
const hasExternalLabeledControl = (() => {
|
|
73
|
+
if (!forAttr || forAttr.isDynamicValue)
|
|
74
|
+
return false;
|
|
75
|
+
const target = [...document.querySelectorAll('[id]')].find(candidate => candidate.getAttribute('id') === forAttr.value);
|
|
76
|
+
if (!target)
|
|
77
|
+
return false;
|
|
78
|
+
// A descendant with a matching id is still the label's labeled control
|
|
79
|
+
// per the same-tree resolution rule; treat only truly external targets
|
|
80
|
+
// as the external-labeled-control case.
|
|
81
|
+
if (el.contains(target))
|
|
82
|
+
return false;
|
|
83
|
+
return target.matches(LABELABLE_SELECTOR);
|
|
84
|
+
})();
|
|
85
|
+
if (hasExternalLabeledControl) {
|
|
86
|
+
for (const control of controls) {
|
|
87
|
+
report({
|
|
88
|
+
scope: control,
|
|
89
|
+
message: t('The "{0}" element must not contain a form-control descendant when the "{1}" attribute references an external labelable element', 'label', 'for'),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (controls.length <= 1)
|
|
95
|
+
return;
|
|
96
|
+
for (const control of controls.slice(1)) {
|
|
97
|
+
report({
|
|
98
|
+
scope: control,
|
|
99
|
+
message: t('The "{0}" element may contain at most one form-control descendant ({1})', 'label', 'button, input, meter, output, progress, select, or textarea'),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
},
|
|
104
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Element } from '@markuplint/ml-core';
|
|
2
|
+
import type { PlainData } from '@markuplint/ml-config';
|
|
3
|
+
/**
|
|
4
|
+
* Shared by the two rules split out of the former `landmark-roles` rule:
|
|
5
|
+
* `no-nested-top-level-landmark` and `require-landmark-label`. Both need the
|
|
6
|
+
* same set of landmark-role elements; only what each rule does with that set
|
|
7
|
+
* differs.
|
|
8
|
+
*/
|
|
9
|
+
/** Landmark roles that APG requires to be top-level (not nested in another landmark). */
|
|
10
|
+
export type TopLevelRoles = 'banner' | 'main' | 'contentinfo' | 'complementary';
|
|
11
|
+
/** All recognized ARIA landmark roles for these rules. */
|
|
12
|
+
export type Roles = TopLevelRoles | 'form' | 'navigation' | 'region';
|
|
13
|
+
/** A mapping from each landmark role to its matched elements in the document. */
|
|
14
|
+
export type RoleSet<O extends PlainData> = {
|
|
15
|
+
[role in Roles]: Element<boolean, O>[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Collects every landmark-role element in the document, keyed by role.
|
|
19
|
+
*
|
|
20
|
+
* @param document - The document to search.
|
|
21
|
+
* @returns The mapping from role to its matched elements.
|
|
22
|
+
*/
|
|
23
|
+
export declare function computeLandmarkRoles<O extends PlainData>(document: {
|
|
24
|
+
querySelectorAll(selector: string): Iterable<Element<boolean, O>>;
|
|
25
|
+
}): RoleSet<O>;
|
|
26
|
+
/**
|
|
27
|
+
* Collects all UUIDs of elements that have landmark roles.
|
|
28
|
+
*
|
|
29
|
+
* @param roleset - The mapping of roles to their matched elements.
|
|
30
|
+
* @returns A flat array of UUIDs for all landmark role elements.
|
|
31
|
+
*/
|
|
32
|
+
export declare function landmarkRoleElementUUIDList<O extends PlainData>(roleset: RoleSet<O>): string[];
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** CSS selectors used to identify elements with each landmark role. */
|
|
2
|
+
const selectors = {
|
|
3
|
+
complementary: ['[role="complementary"]', 'aside'],
|
|
4
|
+
contentinfo: ['[role="contentinfo"]'],
|
|
5
|
+
form: ['[role="form"]', 'form[aria-labelledby]', 'form[aria-label]', 'form[title]'],
|
|
6
|
+
banner: ['[role="banner"]'],
|
|
7
|
+
main: ['[role="main"]', 'main'],
|
|
8
|
+
navigation: ['[role="navigation"]', 'nav'],
|
|
9
|
+
region: ['[role="region"]', 'section[aria-labelledby]', 'section[aria-label]', 'section[title]'],
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Collects every landmark-role element in the document, keyed by role.
|
|
13
|
+
*
|
|
14
|
+
* @param document - The document to search.
|
|
15
|
+
* @returns The mapping from role to its matched elements.
|
|
16
|
+
*/
|
|
17
|
+
export function computeLandmarkRoles(
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
19
|
+
document) {
|
|
20
|
+
const roles = {
|
|
21
|
+
complementary: [...document.querySelectorAll(selectors.complementary.join(','))],
|
|
22
|
+
contentinfo: [...document.querySelectorAll(selectors.contentinfo.join(','))],
|
|
23
|
+
form: [...document.querySelectorAll(selectors.form.join(','))],
|
|
24
|
+
banner: [...document.querySelectorAll(selectors.banner.join(','))],
|
|
25
|
+
main: [...document.querySelectorAll(selectors.main.join(','))],
|
|
26
|
+
navigation: [...document.querySelectorAll(selectors.navigation.join(','))],
|
|
27
|
+
region: [...document.querySelectorAll(selectors.region.join(','))],
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* `<header>`
|
|
31
|
+
*
|
|
32
|
+
* @cite https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/
|
|
33
|
+
*
|
|
34
|
+
* > When in context of the body element. The header element is not a banner landmark when it is a descendant of the following HTML sectioning elements:
|
|
35
|
+
* > - article
|
|
36
|
+
* > - aside
|
|
37
|
+
* > - main
|
|
38
|
+
* > - nav
|
|
39
|
+
* > - section
|
|
40
|
+
*/
|
|
41
|
+
const headers = [...document.querySelectorAll('header')].filter(header => {
|
|
42
|
+
return !header.closest('article, aside, main, nav, section');
|
|
43
|
+
});
|
|
44
|
+
roles.banner.push(...headers);
|
|
45
|
+
/**
|
|
46
|
+
* `<footer>`
|
|
47
|
+
*
|
|
48
|
+
* @cite https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/
|
|
49
|
+
*
|
|
50
|
+
* > When in context of the body element. The footer element is not a contentinfo landmark when it is a descendant of the following HTML sectioning elements:
|
|
51
|
+
* > - article
|
|
52
|
+
* > - aside
|
|
53
|
+
* > - main
|
|
54
|
+
* > - nav
|
|
55
|
+
* > - section
|
|
56
|
+
*/
|
|
57
|
+
const footers = [...document.querySelectorAll('footer')].filter(footer => {
|
|
58
|
+
return !footer.closest('article, aside, main, nav, section');
|
|
59
|
+
});
|
|
60
|
+
roles.contentinfo.push(...footers);
|
|
61
|
+
return roles;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Collects all UUIDs of elements that have landmark roles.
|
|
65
|
+
*
|
|
66
|
+
* @param roleset - The mapping of roles to their matched elements.
|
|
67
|
+
* @returns A flat array of UUIDs for all landmark role elements.
|
|
68
|
+
*/
|
|
69
|
+
export function landmarkRoleElementUUIDList(
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
71
|
+
roleset) {
|
|
72
|
+
return Object.values(roleset).flatMap(elements => elements.map(element => element.uuid));
|
|
73
|
+
}
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
type Options = {
|
|
2
2
|
readonly allowMicroformats?: boolean | readonly string[];
|
|
3
3
|
};
|
|
4
|
-
/**
|
|
5
|
-
* Rule that validates link type keywords in the `rel` attribute on
|
|
6
|
-
* `<link>`, `<a>`, `<area>`, and `<form>` elements against the WHATWG
|
|
7
|
-
* standard and optionally the Microformats registry.
|
|
8
|
-
*/
|
|
9
4
|
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
|
|
10
5
|
export default _default;
|
package/lib/link-types/index.js
CHANGED
|
@@ -2,15 +2,14 @@ import { createRule } from '@markuplint/ml-core';
|
|
|
2
2
|
import { DEF_LINK_TYPE_WHATWG, ALLOWED_LINK_TYPE_MICROFORMATS, DEF_LINK_TYPE_MICROFORMATS_DROPPED, DEF_LINK_TYPE_MICROFORMATS_DROPPED_WITHOUT_PREJUDICE, DEF_LINK_TYPE_MICROFORMATS_REJECTED, DEF_LINK_TYPE_MICROFORMATS_NON_HTML_REL_VALUES, } from '@markuplint/types';
|
|
3
3
|
import meta from './meta.js';
|
|
4
4
|
const TARGET_ELEMENTS = new Set(['link', 'a', 'area', 'form']);
|
|
5
|
-
/**
|
|
6
|
-
* Rule that validates link type keywords in the `rel` attribute on
|
|
7
|
-
* `<link>`, `<a>`, `<area>`, and `<form>` elements against the WHATWG
|
|
8
|
-
* standard and optionally the Microformats registry.
|
|
9
|
-
*/
|
|
10
5
|
export default createRule({
|
|
11
6
|
meta: meta,
|
|
7
|
+
// HTML LS §4.6.6 the rel attribute requires conformance checkers to accept
|
|
8
|
+
// keywords registered on the microformats wiki (proposed or ratified) as
|
|
9
|
+
// extensions to this specification, so accepting them is the spec-conformant
|
|
10
|
+
// default rather than an opt-in.
|
|
12
11
|
defaultOptions: {
|
|
13
|
-
allowMicroformats:
|
|
12
|
+
allowMicroformats: true,
|
|
14
13
|
},
|
|
15
14
|
async verify({ document, report, t }) {
|
|
16
15
|
await document.walkOn('Element', el => {
|
package/lib/link-types/meta.d.ts
CHANGED
package/lib/link-types/meta.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Require that a `<map>` element's `id` attribute, when present, has
|
|
3
|
+
* the same value as its `name` attribute. Per HTML LS §4.8.13:
|
|
4
|
+
* "If the id attribute is also specified, both attributes must have
|
|
5
|
+
* the same value."
|
|
6
|
+
*
|
|
7
|
+
* @see https://html.spec.whatwg.org/multipage/image-maps.html#the-map-element
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, null>>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import meta from './meta.js';
|
|
3
|
+
/**
|
|
4
|
+
* Require that a `<map>` element's `id` attribute, when present, has
|
|
5
|
+
* the same value as its `name` attribute. Per HTML LS §4.8.13:
|
|
6
|
+
* "If the id attribute is also specified, both attributes must have
|
|
7
|
+
* the same value."
|
|
8
|
+
*
|
|
9
|
+
* @see https://html.spec.whatwg.org/multipage/image-maps.html#the-map-element
|
|
10
|
+
*/
|
|
11
|
+
export default createRule({
|
|
12
|
+
meta: meta,
|
|
13
|
+
defaultValue: true,
|
|
14
|
+
defaultOptions: null,
|
|
15
|
+
async verify({ document, report, t }) {
|
|
16
|
+
await document.walkOn('Element', el => {
|
|
17
|
+
if (el.localName !== 'map')
|
|
18
|
+
return;
|
|
19
|
+
// Pretender maps with no `as` pin: attributes are unknown until typed.
|
|
20
|
+
if (el.pretenderContext?.type === 'pretender' && !el.hasAttribute('as'))
|
|
21
|
+
return;
|
|
22
|
+
const idAttr = el.getAttributeNode('id');
|
|
23
|
+
const nameAttr = el.getAttributeNode('name');
|
|
24
|
+
if (!idAttr || !nameAttr)
|
|
25
|
+
return;
|
|
26
|
+
if (idAttr.isDynamicValue || nameAttr.isDynamicValue)
|
|
27
|
+
return;
|
|
28
|
+
if (idAttr.value === nameAttr.value)
|
|
29
|
+
return;
|
|
30
|
+
report({
|
|
31
|
+
scope: idAttr,
|
|
32
|
+
line: idAttr.valueNode?.startLine,
|
|
33
|
+
col: idAttr.valueNode?.startCol,
|
|
34
|
+
raw: idAttr.valueNode?.raw,
|
|
35
|
+
message: t('The "{0}" attribute on a "{1}" element must have the same value as the "{2}" attribute', 'id', 'map', 'name'),
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML LS §4.2.5.4 Specifying the document's character encoding:
|
|
3
|
+
*
|
|
4
|
+
* > The element containing the character encoding declaration must be
|
|
5
|
+
* > serialized completely within the first 1024 bytes of the document.
|
|
6
|
+
*
|
|
7
|
+
* The limit is a byte count, not a character count — `Buffer.byteLength`
|
|
8
|
+
* measures the UTF-8-encoded prefix rather than `String#length`, so
|
|
9
|
+
* multi-byte characters before the declaration are counted at their actual
|
|
10
|
+
* encoded size.
|
|
11
|
+
*
|
|
12
|
+
* @see https://html.spec.whatwg.org/multipage/semantics.html#charset
|
|
13
|
+
*/
|
|
14
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import meta from './meta.js';
|
|
3
|
+
const BYTE_LIMIT = 1024;
|
|
4
|
+
/**
|
|
5
|
+
* HTML LS §4.2.5.4 Specifying the document's character encoding:
|
|
6
|
+
*
|
|
7
|
+
* > The element containing the character encoding declaration must be
|
|
8
|
+
* > serialized completely within the first 1024 bytes of the document.
|
|
9
|
+
*
|
|
10
|
+
* The limit is a byte count, not a character count — `Buffer.byteLength`
|
|
11
|
+
* measures the UTF-8-encoded prefix rather than `String#length`, so
|
|
12
|
+
* multi-byte characters before the declaration are counted at their actual
|
|
13
|
+
* encoded size.
|
|
14
|
+
*
|
|
15
|
+
* @see https://html.spec.whatwg.org/multipage/semantics.html#charset
|
|
16
|
+
*/
|
|
17
|
+
export default createRule({
|
|
18
|
+
meta: meta,
|
|
19
|
+
verify({ document, report, t }) {
|
|
20
|
+
const declarations = document.querySelectorAll('meta[charset], meta[http-equiv="content-type" i]');
|
|
21
|
+
for (const el of declarations) {
|
|
22
|
+
const byteOffset = Buffer.byteLength(document.raw.slice(0, el.startOffset), 'utf8');
|
|
23
|
+
if (byteOffset < BYTE_LIMIT)
|
|
24
|
+
continue;
|
|
25
|
+
report({
|
|
26
|
+
scope: el,
|
|
27
|
+
message: t('The character encoding declaration must be within the first {0} bytes of the document', String(BYTE_LIMIT)),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enforce HTML LS §4.10.14 inequalities for `<meter>`:
|
|
3
|
+
* minimum ≤ value ≤ maximum, plus minimum ≤ low/high/optimum ≤ maximum
|
|
4
|
+
* and low ≤ high when both are specified. Defaults: min=0, max=1,
|
|
5
|
+
* value=min.
|
|
6
|
+
*
|
|
7
|
+
* @see https://html.spec.whatwg.org/multipage/form-elements.html#the-meter-element
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, null>>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import meta from './meta.js';
|
|
3
|
+
const DEFAULT_MIN = 0;
|
|
4
|
+
const DEFAULT_MAX = 1;
|
|
5
|
+
function parseFloatAttr(raw) {
|
|
6
|
+
if (raw === undefined)
|
|
7
|
+
return null;
|
|
8
|
+
const trimmed = raw.trim();
|
|
9
|
+
if (trimmed === '')
|
|
10
|
+
return null;
|
|
11
|
+
const n = Number(trimmed);
|
|
12
|
+
return Number.isFinite(n) ? n : null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Enforce HTML LS §4.10.14 inequalities for `<meter>`:
|
|
16
|
+
* minimum ≤ value ≤ maximum, plus minimum ≤ low/high/optimum ≤ maximum
|
|
17
|
+
* and low ≤ high when both are specified. Defaults: min=0, max=1,
|
|
18
|
+
* value=min.
|
|
19
|
+
*
|
|
20
|
+
* @see https://html.spec.whatwg.org/multipage/form-elements.html#the-meter-element
|
|
21
|
+
*/
|
|
22
|
+
export default createRule({
|
|
23
|
+
meta: meta,
|
|
24
|
+
defaultValue: true,
|
|
25
|
+
defaultOptions: null,
|
|
26
|
+
async verify({ document, report, t }) {
|
|
27
|
+
await document.walkOn('Element', el => {
|
|
28
|
+
if (el.localName !== 'meter')
|
|
29
|
+
return;
|
|
30
|
+
// Pretender meters with no `as` pin: descendants/attributes are unknown until typed.
|
|
31
|
+
if (el.pretenderContext?.type === 'pretender' && !el.hasAttribute('as'))
|
|
32
|
+
return;
|
|
33
|
+
const valueAttr = el.getAttributeNode('value');
|
|
34
|
+
const minAttr = el.getAttributeNode('min');
|
|
35
|
+
const maxAttr = el.getAttributeNode('max');
|
|
36
|
+
const lowAttr = el.getAttributeNode('low');
|
|
37
|
+
const highAttr = el.getAttributeNode('high');
|
|
38
|
+
const optimumAttr = el.getAttributeNode('optimum');
|
|
39
|
+
if (valueAttr?.isDynamicValue ||
|
|
40
|
+
minAttr?.isDynamicValue ||
|
|
41
|
+
maxAttr?.isDynamicValue ||
|
|
42
|
+
lowAttr?.isDynamicValue ||
|
|
43
|
+
highAttr?.isDynamicValue ||
|
|
44
|
+
optimumAttr?.isDynamicValue) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const valueNum = parseFloatAttr(valueAttr?.value);
|
|
48
|
+
const minNum = parseFloatAttr(minAttr?.value);
|
|
49
|
+
const maxNum = parseFloatAttr(maxAttr?.value);
|
|
50
|
+
const lowNum = parseFloatAttr(lowAttr?.value);
|
|
51
|
+
const highNum = parseFloatAttr(highAttr?.value);
|
|
52
|
+
const optimumNum = parseFloatAttr(optimumAttr?.value);
|
|
53
|
+
// Authored-but-unparsable values are reported by `no-invalid-attr-value`; skip the bounds
|
|
54
|
+
// check entirely so we don't compound the diagnostic noise.
|
|
55
|
+
if ((valueAttr && valueNum === null) ||
|
|
56
|
+
(minAttr && minNum === null) ||
|
|
57
|
+
(maxAttr && maxNum === null) ||
|
|
58
|
+
(lowAttr && lowNum === null) ||
|
|
59
|
+
(highAttr && highNum === null) ||
|
|
60
|
+
(optimumAttr && optimumNum === null)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const minValue = minNum ?? DEFAULT_MIN;
|
|
64
|
+
const maxValue = maxNum ?? DEFAULT_MAX;
|
|
65
|
+
const valueValue = valueNum ?? minValue;
|
|
66
|
+
const reportLE = (lowerName, lowerAttr, upperName, upperAttr, upperDefault) => {
|
|
67
|
+
const upperDesc = upperAttr
|
|
68
|
+
? t('the value of the "{0}" attribute', upperName)
|
|
69
|
+
: t('{0} when the "{1}" attribute is absent', upperDefault === 1 ? 'one' : String(upperDefault), upperName);
|
|
70
|
+
const message = t('The value of the "{0}" attribute must be less than or equal to {1}', lowerName, upperDesc);
|
|
71
|
+
const scope = lowerAttr ?? upperAttr;
|
|
72
|
+
if (scope) {
|
|
73
|
+
report({
|
|
74
|
+
scope: scope,
|
|
75
|
+
line: scope.valueNode?.startLine,
|
|
76
|
+
col: scope.valueNode?.startCol,
|
|
77
|
+
raw: scope.valueNode?.raw,
|
|
78
|
+
message: message,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
report({ scope: el, message: message });
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
if (minValue > maxValue) {
|
|
86
|
+
reportLE('min', minAttr, 'max', maxAttr, DEFAULT_MAX);
|
|
87
|
+
}
|
|
88
|
+
if (minValue > valueValue) {
|
|
89
|
+
reportLE('min', minAttr, 'value', valueAttr, DEFAULT_MIN);
|
|
90
|
+
}
|
|
91
|
+
if (valueValue > maxValue) {
|
|
92
|
+
reportLE('value', valueAttr, 'max', maxAttr, DEFAULT_MAX);
|
|
93
|
+
}
|
|
94
|
+
if (lowAttr && lowNum !== null) {
|
|
95
|
+
if (minValue > lowNum) {
|
|
96
|
+
reportLE('min', minAttr, 'low', lowAttr, DEFAULT_MIN);
|
|
97
|
+
}
|
|
98
|
+
if (lowNum > maxValue) {
|
|
99
|
+
reportLE('low', lowAttr, 'max', maxAttr, DEFAULT_MAX);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (highAttr && highNum !== null) {
|
|
103
|
+
if (minValue > highNum) {
|
|
104
|
+
reportLE('min', minAttr, 'high', highAttr, DEFAULT_MIN);
|
|
105
|
+
}
|
|
106
|
+
if (highNum > maxValue) {
|
|
107
|
+
reportLE('high', highAttr, 'max', maxAttr, DEFAULT_MAX);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (optimumAttr && optimumNum !== null) {
|
|
111
|
+
if (minValue > optimumNum) {
|
|
112
|
+
reportLE('min', minAttr, 'optimum', optimumAttr, DEFAULT_MIN);
|
|
113
|
+
}
|
|
114
|
+
if (optimumNum > maxValue) {
|
|
115
|
+
reportLE('optimum', optimumAttr, 'max', maxAttr, DEFAULT_MAX);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (lowAttr && highAttr && lowNum !== null && highNum !== null && lowNum > highNum) {
|
|
119
|
+
reportLE('low', lowAttr, 'high', highAttr, 0);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
});
|
|
@@ -2,7 +2,6 @@ import { createRule, getSpec } from '@markuplint/ml-core';
|
|
|
2
2
|
import { checkingAbstractRole } from '../wai-aria/checkings/abstract-role.js';
|
|
3
3
|
import { defaultOptions } from '../wai-aria/default-options.js';
|
|
4
4
|
import meta from './meta.js';
|
|
5
|
-
/** Warns when an abstract WAI-ARIA role is used directly in content. */
|
|
6
5
|
export default createRule({
|
|
7
6
|
meta,
|
|
8
7
|
defaultOptions,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML LS § the source element: when a `<source>` has a following sibling
|
|
3
|
+
* `<source>` or `<img>` element with a `srcset` attribute specified, it must
|
|
4
|
+
* have a usable `media` and/or `type` attribute, otherwise it "always
|
|
5
|
+
* matches" and shadows the following candidates. Split out of the former
|
|
6
|
+
* `srcset-sizes-constraint` rule's Check 6.
|
|
7
|
+
*
|
|
8
|
+
* Whether the current `<source>` itself has a `srcset` is irrelevant — the
|
|
9
|
+
* requirement is about distinguishing it from what follows, not about its
|
|
10
|
+
* own candidates.
|
|
11
|
+
*/
|
|
12
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
13
|
+
export default _default;
|