@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
|
@@ -1,24 +1,45 @@
|
|
|
1
1
|
import { findChildren } from './find-children.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* HTML LS [§4.9.12.1 *Forming a table*](https://html.spec.whatwg.org/multipage/tables.html#forming-a-table)
|
|
4
|
+
* Step 8 clamps `colspan` to the range 1–1000.
|
|
5
|
+
*/
|
|
6
|
+
const MAX_COLSPAN = 1000;
|
|
7
|
+
/**
|
|
8
|
+
* HTML LS [§4.9.12.1 *Forming a table*](https://html.spec.whatwg.org/multipage/tables.html#forming-a-table)
|
|
9
|
+
* Step 9 clamps `rowspan` to the range 0–65534.
|
|
10
|
+
*/
|
|
11
|
+
const MAX_ROWSPAN = 65_534;
|
|
12
|
+
/**
|
|
13
|
+
* Models a `<table>` as the slot grid of HTML LS
|
|
14
|
+
* [§4.9.12.1 *Forming a table*](https://html.spec.whatwg.org/multipage/tables.html#forming-a-table).
|
|
15
|
+
*
|
|
16
|
+
* Shared by `no-table-cell-overlap`, `no-table-span-overflow`, `no-empty-table-track`, and
|
|
17
|
+
* `consistent-table-row-length` — the four rules split out of the former
|
|
18
|
+
* `table-row-column-alignment` rule, one per table model error / diagnostic this class models.
|
|
4
19
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
20
|
+
* The algorithm is followed rather than approximated because every table model error those rules
|
|
21
|
+
* report is defined in terms of it: Step 6 decides which slot a cell is anchored to (a `colspan`
|
|
22
|
+
* after a `rowspan` continuation does *not* start at the cell's ordinal position), Steps 7 and 11
|
|
23
|
+
* decide how wide the table becomes, Step 14 defines cell overlap, and Step 20 defines rows and
|
|
24
|
+
* columns that no cell is anchored to.
|
|
25
|
+
*
|
|
26
|
+
* Two things the spec has no name for are tracked alongside:
|
|
27
|
+
*
|
|
28
|
+
* - **Row width** ({@link Row.slots} length). Rows narrower or wider than the rest of the
|
|
29
|
+
* table are not a table model error — nu-validator reports them as warnings unless column
|
|
30
|
+
* markup fixes the width — but they are `consistent-table-row-length`'s diagnostic and predate
|
|
31
|
+
* the spec-level checks.
|
|
32
|
+
* - **Row group boundaries**. The spec's *ending a row group* algorithm clips a cell to its
|
|
33
|
+
* row group, so slots are covered per group; {@link RowGroup.overflows} keeps the cells that
|
|
34
|
+
* were clipped so `no-table-span-overflow` can report them.
|
|
8
35
|
*/
|
|
9
36
|
export class Grid {
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
/** The
|
|
13
|
-
|
|
14
|
-
/** The
|
|
15
|
-
|
|
16
|
-
/** The `<tr>` elements within `<tbody>`. */
|
|
17
|
-
#tbodyRowElements;
|
|
18
|
-
/** The `<tr>` elements within `<tfoot>`. */
|
|
19
|
-
#tfootRowElements;
|
|
20
|
-
/** The `<tr>` elements within `<thead>`. */
|
|
21
|
-
#theadRowElements;
|
|
37
|
+
/** Column ranges established by `<col>` / `<colgroup>`, in document order. */
|
|
38
|
+
columnMarkup;
|
|
39
|
+
/** The row groups of the table, in document order. */
|
|
40
|
+
rowGroups;
|
|
41
|
+
/** The number of slot columns in the table (spec: xwidth). */
|
|
42
|
+
xwidth;
|
|
22
43
|
/**
|
|
23
44
|
* Constructs a grid model from a `<table>` element.
|
|
24
45
|
*
|
|
@@ -27,238 +48,290 @@ export class Grid {
|
|
|
27
48
|
constructor(
|
|
28
49
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
29
50
|
table) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
* Returns all `<tr>` elements across all table sections in document order.
|
|
42
|
-
*
|
|
43
|
-
* @returns Combined array of row elements from thead, tbody, and tfoot.
|
|
44
|
-
*/
|
|
45
|
-
getAllRowElements() {
|
|
46
|
-
return [...this.#theadRowElements, ...this.#tbodyRowElements, ...this.#tfootRowElements];
|
|
51
|
+
this.columnMarkup = collectColumnMarkup(table);
|
|
52
|
+
// Column markup establishes the initial xwidth (spec: the *processing column groups* step).
|
|
53
|
+
let xwidth = this.columnMarkup.at(-1)?.right ?? 0;
|
|
54
|
+
const rowGroups = [];
|
|
55
|
+
for (const groupElement of findChildren(table, 'thead, tbody, tfoot')) {
|
|
56
|
+
const group = processRowGroup(groupElement, xwidth);
|
|
57
|
+
xwidth = group.xwidth;
|
|
58
|
+
rowGroups.push(group.rowGroup);
|
|
59
|
+
}
|
|
60
|
+
this.rowGroups = rowGroups;
|
|
61
|
+
this.xwidth = xwidth;
|
|
47
62
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
* @returns Combined array of grid rows from thead, tbody, and tfoot, filtered to rows with real cells.
|
|
52
|
-
*/
|
|
53
|
-
getAllRows() {
|
|
54
|
-
return [
|
|
55
|
-
...this.theadGrid.filter(hasElementFilter),
|
|
56
|
-
...this.tbodyGrid.filter(hasElementFilter),
|
|
57
|
-
...this.tfootGrid.filter(hasElementFilter),
|
|
58
|
-
];
|
|
63
|
+
/** @returns Every cell anchored in the table, in document order. */
|
|
64
|
+
getAnchors() {
|
|
65
|
+
return this.rowGroups.flatMap(group => group.anchors);
|
|
59
66
|
}
|
|
60
67
|
/**
|
|
61
|
-
* Determines the expected (base) column count
|
|
68
|
+
* Determines the expected (base) column count that rows are compared against.
|
|
62
69
|
*
|
|
63
|
-
*
|
|
70
|
+
* Rows decide it, preferring `<thead>` then `<tfoot>` since a heading or footing
|
|
71
|
+
* row is the more deliberate declaration. Column markup is deliberately *not*
|
|
72
|
+
* consulted: HTML LS §4.9.12.1 Step 7 grows xwidth to fit a row that is wider
|
|
73
|
+
* than the `<col>` markup, so such a row is not an error (tracked as a
|
|
74
|
+
* nu-validator over-detection in `tests/external/snapshots/excluded-ids.json`).
|
|
75
|
+
* A row narrower than the column markup is caught by the Step 20 column scan
|
|
76
|
+
* instead, which reports the `<col>` that no cell ever starts in.
|
|
64
77
|
*
|
|
65
78
|
* @returns The base number of columns that rows should have.
|
|
66
79
|
*/
|
|
67
80
|
getBaseColLength() {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return getBaseColLength(this.tfootGrid);
|
|
73
|
-
}
|
|
74
|
-
return getBaseColLength(this.tbodyGrid);
|
|
81
|
+
const preferred = this.rowGroups.find(group => group.tagName === 'thead' && group.rows.length > 0) ??
|
|
82
|
+
this.rowGroups.find(group => group.tagName === 'tfoot' && group.rows.length > 0) ??
|
|
83
|
+
this.rowGroups.find(group => group.rows.length > 0);
|
|
84
|
+
return preferred ? getBaseColLength(preferred.rows) : 0;
|
|
75
85
|
}
|
|
76
86
|
/**
|
|
77
|
-
*
|
|
87
|
+
* Collects the columns that no cell is anchored to (spec Step 20), merging
|
|
88
|
+
* neighbouring columns that the same element established into one range so a
|
|
89
|
+
* `colspan` overshooting by four columns is reported once, not four times.
|
|
78
90
|
*
|
|
79
|
-
* @returns
|
|
91
|
+
* @returns The offending ranges, in column order.
|
|
80
92
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
getColumnsWithoutAnchor() {
|
|
94
|
+
const anchors = this.getAnchors();
|
|
95
|
+
const anchored = new Set(anchors.map(anchor => anchor.x));
|
|
96
|
+
const ranges = [];
|
|
97
|
+
for (let x = 0; x < this.xwidth; x++) {
|
|
98
|
+
if (anchored.has(x)) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const source = this.#findColumnSource(x, anchors);
|
|
102
|
+
if (!source) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const last = ranges.at(-1);
|
|
106
|
+
if (last && last.source === source && last.right === x) {
|
|
107
|
+
ranges[ranges.length - 1] = { source, left: last.left, right: x + 1 };
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
ranges.push({ source, left: x, right: x + 1 });
|
|
111
|
+
}
|
|
112
|
+
return ranges;
|
|
113
|
+
}
|
|
114
|
+
/** @returns Every row of the table, in document order. */
|
|
115
|
+
getRows() {
|
|
116
|
+
return this.rowGroups.flatMap(group => group.rows);
|
|
96
117
|
}
|
|
97
118
|
/**
|
|
98
|
-
* Checks whether any
|
|
119
|
+
* Checks whether any slot of the table is covered by more than one cell.
|
|
99
120
|
*
|
|
100
|
-
* @returns `true` if
|
|
121
|
+
* @returns `true` if the table has a Step 14 cell overlap.
|
|
101
122
|
*/
|
|
102
123
|
hasOverlapped() {
|
|
103
|
-
return
|
|
104
|
-
this.tfootGrid.some(row => row.includes('x')) ||
|
|
105
|
-
this.theadGrid.some(row => row.includes('x')));
|
|
124
|
+
return this.rowGroups.some(group => group.hasOverlap);
|
|
106
125
|
}
|
|
107
|
-
/**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Resolves which element is answerable for a column: the column markup that
|
|
128
|
+
* declared it, or else the cell whose `colspan` stretched the table over it.
|
|
129
|
+
*
|
|
130
|
+
* @param x - The column index.
|
|
131
|
+
* @param anchors - The anchors of the table.
|
|
132
|
+
* @returns The element, or `null` when nothing covers the column.
|
|
133
|
+
*/
|
|
134
|
+
#findColumnSource(x, anchors) {
|
|
135
|
+
const markup = this.columnMarkup.find(range => range.left <= x && x < range.right);
|
|
136
|
+
if (markup) {
|
|
137
|
+
return markup.source;
|
|
138
|
+
}
|
|
139
|
+
const spanning = anchors.find(anchor => anchor.x < x && x < anchor.x + anchor.colspan);
|
|
140
|
+
return spanning?.cell ?? null;
|
|
115
141
|
}
|
|
116
142
|
}
|
|
117
143
|
/**
|
|
118
|
-
*
|
|
144
|
+
* Maps each slot of a row to the index of the `<th>` / `<td>` anchored to it
|
|
145
|
+
* (counted among the row's own cells), or `null` for a slot the row does not anchor a cell to.
|
|
119
146
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
147
|
+
* @param slots - The slots of a single row.
|
|
148
|
+
* @returns An array of cell indices or `null` values, one per slot.
|
|
149
|
+
*/
|
|
150
|
+
export function getIndexes(slots) {
|
|
151
|
+
let indexCounter = 0;
|
|
152
|
+
return slots.map(slot => (slot === '●' || slot === '◎' ? indexCounter++ : null));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Collects the column ranges that `<col>` and `<colgroup>` establish.
|
|
122
156
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
157
|
+
* A `<colgroup>` contributes its own `span` only when it has no `<col>` children,
|
|
158
|
+
* mirroring HTML LS §4.9.3: the `span` attribute of a `<colgroup>` "must not be
|
|
159
|
+
* specified if the element contains one or more `col` elements".
|
|
160
|
+
*
|
|
161
|
+
* @param table - The table element.
|
|
162
|
+
* @returns The ranges in document order.
|
|
126
163
|
*/
|
|
127
|
-
|
|
164
|
+
function collectColumnMarkup(
|
|
128
165
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
const rowSpan = spanStartCell.getAttributeNode('rowspan');
|
|
153
|
-
if (!rowSpan) {
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
rowSpan,
|
|
158
|
-
};
|
|
166
|
+
table) {
|
|
167
|
+
const ranges = [];
|
|
168
|
+
let left = 0;
|
|
169
|
+
const append = (
|
|
170
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
171
|
+
source) => {
|
|
172
|
+
const span = parseSpan(source.getAttribute('span'), 1, 1, MAX_COLSPAN);
|
|
173
|
+
ranges.push({ source, left, right: left + span });
|
|
174
|
+
left += span;
|
|
175
|
+
};
|
|
176
|
+
for (const child of findChildren(table, 'colgroup, col')) {
|
|
177
|
+
if (child.localName === 'col') {
|
|
178
|
+
append(child);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const cols = findChildren(child, 'col');
|
|
182
|
+
if (cols.length === 0) {
|
|
183
|
+
append(child);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
for (const col of cols) {
|
|
187
|
+
append(col);
|
|
159
188
|
}
|
|
160
189
|
}
|
|
161
|
-
return
|
|
190
|
+
return ranges;
|
|
162
191
|
}
|
|
163
192
|
/**
|
|
164
|
-
*
|
|
165
|
-
*
|
|
193
|
+
* Calculates the base (expected) column count from the rows of a row group.
|
|
194
|
+
*
|
|
195
|
+
* For groups with 3 or more rows, uses the row width closest to the average so a
|
|
196
|
+
* single malformed row does not become the baseline. Otherwise uses the first row.
|
|
166
197
|
*
|
|
167
|
-
* @param
|
|
168
|
-
* @returns
|
|
198
|
+
* @param rows - The rows of a row group.
|
|
199
|
+
* @returns The base number of columns.
|
|
169
200
|
*/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
201
|
+
function getBaseColLength(rows) {
|
|
202
|
+
if (rows.length < 3) {
|
|
203
|
+
return rows[0]?.slots.length ?? 0;
|
|
204
|
+
}
|
|
205
|
+
let totalCols = 0;
|
|
206
|
+
for (const row of rows) {
|
|
207
|
+
totalCols += row.slots.length;
|
|
208
|
+
}
|
|
209
|
+
const average = Math.round(totalCols / rows.length);
|
|
210
|
+
let closest = rows[0]?.slots.length ?? 0;
|
|
211
|
+
for (const row of rows) {
|
|
212
|
+
if (Math.abs(row.slots.length - average) < Math.abs(closest - average)) {
|
|
213
|
+
closest = row.slots.length;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return closest;
|
|
173
217
|
}
|
|
174
218
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
* average to handle minor variations from spans. Otherwise uses the first row.
|
|
219
|
+
* Parses a `colspan` / `rowspan` / `span` attribute value the way HTML LS does:
|
|
220
|
+
* a value that is missing or fails to parse falls back to the default, and a parsed
|
|
221
|
+
* value is clamped to the range the spec allows.
|
|
179
222
|
*
|
|
180
|
-
* @param
|
|
181
|
-
* @
|
|
223
|
+
* @param value - The raw attribute value.
|
|
224
|
+
* @param fallback - The value to use when the attribute is absent or fails to parse.
|
|
225
|
+
* @param min - The lower bound of the clamp range.
|
|
226
|
+
* @param max - The upper bound of the clamp range.
|
|
227
|
+
* @returns The effective span.
|
|
182
228
|
*/
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const totalCols = grid.reduce((acc, row) => {
|
|
187
|
-
return acc + row.length;
|
|
188
|
-
}, 0);
|
|
189
|
-
const average = Math.round(totalCols / grid.length);
|
|
190
|
-
baseColLength = grid
|
|
191
|
-
// eslint-disable-next-line unicorn/no-array-reduce
|
|
192
|
-
.reduce((closest, row) => {
|
|
193
|
-
return Math.abs(row.length - average) < Math.abs(closest - average) ? row.length : closest;
|
|
194
|
-
}, grid[0]?.length ?? 0);
|
|
229
|
+
function parseSpan(value, fallback, min, max) {
|
|
230
|
+
if (value == null) {
|
|
231
|
+
return fallback;
|
|
195
232
|
}
|
|
196
|
-
|
|
197
|
-
|
|
233
|
+
const digits = /^[\t\n\f\r ]*(\d+)/.exec(value);
|
|
234
|
+
if (!digits?.[1]) {
|
|
235
|
+
return fallback;
|
|
198
236
|
}
|
|
199
|
-
return
|
|
237
|
+
return Math.min(Math.max(Number.parseInt(digits[1], 10), min), max);
|
|
200
238
|
}
|
|
201
239
|
/**
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* Processes each row's `<th>` and `<td>` cells, expanding `colspan` and `rowspan`
|
|
205
|
-
* attributes into the grid. Marks cells with appropriate cell types including
|
|
206
|
-
* span origins, continuations, and overlaps.
|
|
240
|
+
* Runs the spec's *algorithm for processing rows* over one row group.
|
|
207
241
|
*
|
|
208
|
-
* @param
|
|
209
|
-
* @
|
|
242
|
+
* @param groupElement - The `<thead>` / `<tbody>` / `<tfoot>` element.
|
|
243
|
+
* @param initialXwidth - The table's xwidth before this group is processed.
|
|
244
|
+
* @returns The modelled row group and the xwidth the group grew the table to.
|
|
210
245
|
*/
|
|
211
|
-
function
|
|
246
|
+
function processRowGroup(
|
|
212
247
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
248
|
+
groupElement, initialXwidth) {
|
|
249
|
+
const rowElements = findChildren(groupElement, 'tr');
|
|
250
|
+
const rowCount = rowElements.length;
|
|
251
|
+
/** The anchor covering each slot, keyed by `"row:column"`. */
|
|
252
|
+
const covered = new Map();
|
|
253
|
+
/** Slots a second cell tried to cover (spec Step 14). */
|
|
254
|
+
const overlapped = new Set();
|
|
255
|
+
const anchors = [];
|
|
256
|
+
const overflows = [];
|
|
257
|
+
const widths = [];
|
|
258
|
+
const anchorCounts = [];
|
|
259
|
+
let xwidth = initialXwidth;
|
|
260
|
+
for (const [y, rowElement] of rowElements.entries()) {
|
|
261
|
+
let xcurrent = 0;
|
|
262
|
+
let anchorCount = 0;
|
|
263
|
+
for (const cell of findChildren(rowElement, 'th, td')) {
|
|
264
|
+
const colspan = parseSpan(cell.getAttribute('colspan'), 1, 1, MAX_COLSPAN);
|
|
265
|
+
const declaredRowspan = parseSpan(cell.getAttribute('rowspan'), 1, 0, MAX_ROWSPAN);
|
|
266
|
+
const growsDownward = declaredRowspan === 0;
|
|
267
|
+
const rowspan = growsDownward ? Math.max(rowCount - y, 1) : declaredRowspan;
|
|
268
|
+
// Step 6
|
|
269
|
+
while (xcurrent < xwidth && covered.has(`${y}:${xcurrent}`)) {
|
|
270
|
+
xcurrent += 1;
|
|
271
|
+
}
|
|
272
|
+
// Step 7
|
|
273
|
+
if (xcurrent === xwidth) {
|
|
274
|
+
xwidth += 1;
|
|
275
|
+
}
|
|
276
|
+
// Step 11
|
|
277
|
+
xwidth = Math.max(xwidth, xcurrent + colspan);
|
|
278
|
+
const anchor = { cell, x: xcurrent, y, colspan, rowspan, growsDownward };
|
|
279
|
+
anchors.push(anchor);
|
|
280
|
+
anchorCount += 1;
|
|
281
|
+
// Steps 13 and 14. The bottom is clipped to the row group per *ending a row group*.
|
|
282
|
+
const bottom = Math.min(y + rowspan, rowCount);
|
|
283
|
+
for (let cy = y; cy < bottom; cy++) {
|
|
284
|
+
for (let cx = xcurrent; cx < xcurrent + colspan; cx++) {
|
|
285
|
+
const key = `${cy}:${cx}`;
|
|
286
|
+
if (covered.has(key)) {
|
|
287
|
+
overlapped.add(key);
|
|
288
|
+
continue;
|
|
237
289
|
}
|
|
290
|
+
covered.set(key, anchor);
|
|
238
291
|
}
|
|
239
|
-
const addCol = rowSpans.has(key) ? 1 : 0;
|
|
240
|
-
if (matrix[rowNum]?.[colNum] === '↓' && !spanStart && colSpan > 1) {
|
|
241
|
-
// Overlap
|
|
242
|
-
matrix[rowNum][colNum] = 'x';
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
matrix[rowNum][colNum] = spanStart ? '◎' : addCol > 0 ? '↓' : colSpan > 1 ? '→' : '●';
|
|
246
|
-
}
|
|
247
|
-
if (addCol === 1) {
|
|
248
|
-
matrix[rowNum].push('●');
|
|
249
|
-
}
|
|
250
|
-
colNum += 1;
|
|
251
292
|
}
|
|
293
|
+
if (!growsDownward && y + rowspan > rowCount) {
|
|
294
|
+
overflows.push(anchor);
|
|
295
|
+
}
|
|
296
|
+
xcurrent += colspan;
|
|
297
|
+
}
|
|
298
|
+
// The row is as wide as its own cells plus the run of continuing spans that follows them.
|
|
299
|
+
while (covered.has(`${y}:${xcurrent}`)) {
|
|
300
|
+
xcurrent += 1;
|
|
252
301
|
}
|
|
302
|
+
widths[y] = xcurrent;
|
|
303
|
+
anchorCounts[y] = anchorCount;
|
|
253
304
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
305
|
+
const rows = rowElements.map((element, y) => {
|
|
306
|
+
const slots = [];
|
|
307
|
+
for (let x = 0; x < (widths[y] ?? 0); x++) {
|
|
308
|
+
const key = `${y}:${x}`;
|
|
309
|
+
if (overlapped.has(key)) {
|
|
310
|
+
slots.push('x');
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const anchor = covered.get(key);
|
|
314
|
+
if (!anchor) {
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
slots.push(anchor.x === x && anchor.y === y
|
|
318
|
+
? anchor.colspan > 1 || anchor.rowspan > 1
|
|
319
|
+
? '◎'
|
|
320
|
+
: '●'
|
|
321
|
+
: anchor.y === y
|
|
322
|
+
? '→'
|
|
323
|
+
: '↓');
|
|
324
|
+
}
|
|
325
|
+
return { element, slots, anchorCount: anchorCounts[y] ?? 0 };
|
|
326
|
+
});
|
|
327
|
+
return {
|
|
328
|
+
rowGroup: {
|
|
329
|
+
tagName: groupElement.localName,
|
|
330
|
+
rows,
|
|
331
|
+
anchors,
|
|
332
|
+
overflows,
|
|
333
|
+
hasOverlap: overlapped.size > 0,
|
|
334
|
+
},
|
|
335
|
+
xwidth,
|
|
336
|
+
};
|
|
264
337
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
/** A grid cell coordinate key in "row:column" format. */
|
|
2
|
-
export type Key = `${number}:${number}`;
|
|
3
1
|
/**
|
|
4
|
-
* Represents
|
|
2
|
+
* Represents what covers one slot of the table grid.
|
|
5
3
|
*
|
|
6
|
-
* - `'●'` - A
|
|
7
|
-
* - `'◎'` -
|
|
8
|
-
* - `'↓'` -
|
|
9
|
-
* - `'→'` -
|
|
10
|
-
* - `'x'` -
|
|
4
|
+
* - `'●'` - A cell is anchored here and spans nothing else.
|
|
5
|
+
* - `'◎'` - A cell is anchored here and spans further columns and/or rows.
|
|
6
|
+
* - `'↓'` - Covered by a cell anchored in an earlier row.
|
|
7
|
+
* - `'→'` - Covered by a cell anchored earlier in the same row.
|
|
8
|
+
* - `'x'` - Covered by more than one cell (HTML LS §4.9.12.1 Step 14).
|
|
11
9
|
*/
|
|
12
10
|
export type CellType = '●' | '◎' | '↓' | '→' | 'x';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Require the `usemap` attribute on an `<img>` element to be a valid
|
|
3
|
+
* hash-name reference to a `<map>` element. Per HTML LS's definition of
|
|
4
|
+
* "valid hash-name reference": a string consisting of "#" followed by a
|
|
5
|
+
* string that exactly matches the `name` attribute of an element of the
|
|
6
|
+
* referenced type in the same tree — matching is by `name`, not `id`, so
|
|
7
|
+
* `no-refer-to-non-existent-id` (which only tracks `id` references) never
|
|
8
|
+
* covers this attribute.
|
|
9
|
+
*
|
|
10
|
+
* @see https://html.spec.whatwg.org/multipage/image-maps.html#attr-hyperlink-usemap
|
|
11
|
+
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-hash-name-reference
|
|
12
|
+
*/
|
|
13
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, null>>;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createRule } from '@markuplint/ml-core';
|
|
2
|
+
import meta from './meta.js';
|
|
3
|
+
/**
|
|
4
|
+
* Require the `usemap` attribute on an `<img>` element to be a valid
|
|
5
|
+
* hash-name reference to a `<map>` element. Per HTML LS's definition of
|
|
6
|
+
* "valid hash-name reference": a string consisting of "#" followed by a
|
|
7
|
+
* string that exactly matches the `name` attribute of an element of the
|
|
8
|
+
* referenced type in the same tree — matching is by `name`, not `id`, so
|
|
9
|
+
* `no-refer-to-non-existent-id` (which only tracks `id` references) never
|
|
10
|
+
* covers this attribute.
|
|
11
|
+
*
|
|
12
|
+
* @see https://html.spec.whatwg.org/multipage/image-maps.html#attr-hyperlink-usemap
|
|
13
|
+
* @see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-hash-name-reference
|
|
14
|
+
*/
|
|
15
|
+
export default createRule({
|
|
16
|
+
meta: meta,
|
|
17
|
+
defaultValue: true,
|
|
18
|
+
defaultOptions: null,
|
|
19
|
+
async verify({ document, report, t }) {
|
|
20
|
+
await document.walkOn('Element', el => {
|
|
21
|
+
if (el.localName !== 'img')
|
|
22
|
+
return;
|
|
23
|
+
if (el.pretenderContext?.type === 'pretender' && !el.hasAttribute('as'))
|
|
24
|
+
return;
|
|
25
|
+
const usemapAttr = el.getAttributeNode('usemap');
|
|
26
|
+
if (!usemapAttr)
|
|
27
|
+
return;
|
|
28
|
+
if (usemapAttr.isDynamicValue)
|
|
29
|
+
return;
|
|
30
|
+
const value = usemapAttr.value;
|
|
31
|
+
if (!value.startsWith('#') || value.length <= 1)
|
|
32
|
+
return;
|
|
33
|
+
const targetName = value.slice(1);
|
|
34
|
+
const target = [...document.querySelectorAll('map')].find(candidate => candidate.getAttribute('name') === targetName);
|
|
35
|
+
if (!target) {
|
|
36
|
+
report({
|
|
37
|
+
scope: usemapAttr,
|
|
38
|
+
line: usemapAttr.valueNode?.startLine,
|
|
39
|
+
col: usemapAttr.valueNode?.startCol,
|
|
40
|
+
raw: usemapAttr.valueNode?.raw,
|
|
41
|
+
message: t('The "{0}" attribute of the "{1}" element must be a valid hash-name reference to a "{2}" element', 'usemap', 'img', 'map'),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
});
|