@markuplint/rules 5.1.1 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/CLAUDE.md +19 -19
  3. package/lib/aria-prop-requires-role/index.js +2 -1
  4. package/lib/attr-check.js +6 -12
  5. package/lib/attr-eligibility.d.ts +15 -8
  6. package/lib/attr-eligibility.js +19 -10
  7. package/lib/attr-order/index.js +24 -18
  8. package/lib/case-sensitive-attr-name/index.js +24 -5
  9. package/lib/class-naming/index.js +6 -0
  10. package/lib/debug.d.ts +8 -1
  11. package/lib/debug.js +8 -1
  12. package/lib/element-supports-aria-prop/index.js +2 -1
  13. package/lib/form-attr-references-form/index.d.ts +6 -3
  14. package/lib/form-attr-references-form/index.js +6 -3
  15. package/lib/helpers.d.ts +111 -1
  16. package/lib/helpers.js +212 -2
  17. package/lib/input-list-references-datalist/index.d.ts +8 -6
  18. package/lib/input-list-references-datalist/index.js +8 -6
  19. package/lib/label-for-references-labelable/index.d.ts +8 -5
  20. package/lib/label-for-references-labelable/index.js +8 -5
  21. package/lib/landmark-roles/roles.js +14 -2
  22. package/lib/map-id-name-match/index.d.ts +3 -3
  23. package/lib/map-id-name-match/index.js +3 -3
  24. package/lib/no-ambiguous-navigable-target-names/index.js +2 -1
  25. package/lib/no-aria-hidden-on-hidden-until-found/index.d.ts +9 -6
  26. package/lib/no-aria-hidden-on-hidden-until-found/index.js +9 -6
  27. package/lib/no-aria-hidden-on-hidden-until-found/meta.d.ts +1 -1
  28. package/lib/no-aria-hidden-on-hidden-until-found/meta.js +1 -1
  29. package/lib/no-aria-on-unsupported-element/index.js +2 -2
  30. package/lib/no-aria-on-unsupported-element/meta.d.ts +1 -1
  31. package/lib/no-aria-on-unsupported-element/meta.js +1 -1
  32. package/lib/no-boolean-attr-value/index.js +2 -2
  33. package/lib/no-content-after-body/index.d.ts +2 -2
  34. package/lib/no-content-after-body/index.js +2 -2
  35. package/lib/no-contradictory-aria-prop/index.js +2 -1
  36. package/lib/no-default-aria-value/index.js +2 -1
  37. package/lib/no-default-value/index.js +2 -2
  38. package/lib/no-deprecated-aria-prop/index.js +2 -1
  39. package/lib/no-deprecated-attr/index.js +2 -1
  40. package/lib/no-disallowed-attr/index.d.ts +7 -1
  41. package/lib/no-disallowed-attr/index.js +13 -20
  42. package/lib/no-duplicate-attr/index.js +1 -2
  43. package/lib/no-duplicate-autofocus/index.js +2 -2
  44. package/lib/no-duplicate-h1/index.d.ts +1 -1
  45. package/lib/no-duplicate-h1/index.js +1 -1
  46. package/lib/no-empty-table-track/index.d.ts +6 -2
  47. package/lib/no-empty-table-track/index.js +6 -2
  48. package/lib/no-experimental-features/index.d.ts +5 -1
  49. package/lib/no-experimental-features/index.js +6 -8
  50. package/lib/no-hardcoded-id/index.js +1 -1
  51. package/lib/no-ineffective-attr/index.js +2 -2
  52. package/lib/no-input-file-value/index.d.ts +10 -4
  53. package/lib/no-input-file-value/index.js +10 -4
  54. package/lib/no-invalid-aria-prop-value/index.js +2 -1
  55. package/lib/no-invalid-attr-value/index.d.ts +3 -0
  56. package/lib/no-invalid-attr-value/index.js +9 -24
  57. package/lib/no-nonstandard-features/index.d.ts +5 -1
  58. package/lib/no-nonstandard-features/index.js +6 -8
  59. package/lib/no-obsolete-attr/index.js +3 -3
  60. package/lib/no-prohibited-naming/index.js +2 -1
  61. package/lib/no-redundant-accessible-name/index.js +17 -1
  62. package/lib/no-redundant-aria-prop/index.js +2 -1
  63. package/lib/no-refer-to-non-existent-id/index.js +4 -4
  64. package/lib/no-restricted-attr/index.d.ts +4 -0
  65. package/lib/no-restricted-attr/index.js +5 -22
  66. package/lib/no-stray-head-or-body-tag/index.d.ts +6 -4
  67. package/lib/no-stray-head-or-body-tag/index.js +11 -6
  68. package/lib/no-unknown-attr/index.d.ts +7 -1
  69. package/lib/no-unknown-attr/index.js +11 -25
  70. package/lib/no-unpaired-srcset-sizes/index.d.ts +3 -2
  71. package/lib/no-unpaired-srcset-sizes/index.js +23 -17
  72. package/lib/no-unsupported-browser-features/compat-data.d.ts +15 -2
  73. package/lib/no-unsupported-browser-features/compat-data.js +48 -3
  74. package/lib/no-unsupported-browser-features/index.d.ts +5 -1
  75. package/lib/no-unsupported-browser-features/index.js +6 -7
  76. package/lib/permitted-contents/choice.js +19 -8
  77. package/lib/permitted-contents/content-model.d.ts +24 -1
  78. package/lib/permitted-contents/content-model.js +56 -9
  79. package/lib/permitted-contents/count-pattern.js +36 -13
  80. package/lib/permitted-contents/debug.browser.d.ts +18 -0
  81. package/lib/permitted-contents/debug.browser.js +27 -0
  82. package/lib/permitted-contents/debug.d.ts +18 -0
  83. package/lib/permitted-contents/debug.js +27 -0
  84. package/lib/permitted-contents/index.js +2 -2
  85. package/lib/permitted-contents/matches-selector.js +40 -18
  86. package/lib/permitted-contents/order.js +23 -11
  87. package/lib/permitted-contents/represent-transparent-nodes.js +3 -1
  88. package/lib/permitted-contents/transparent.js +6 -2
  89. package/lib/placeholder-label-option/index.d.ts +3 -3
  90. package/lib/placeholder-label-option/index.js +163 -37
  91. package/lib/progress-value-bounds/index.d.ts +1 -1
  92. package/lib/progress-value-bounds/index.js +1 -1
  93. package/lib/require-attr/index.d.ts +6 -1
  94. package/lib/require-attr/index.js +13 -5
  95. package/lib/require-h1/index.d.ts +1 -1
  96. package/lib/require-h1/index.js +1 -1
  97. package/lib/role-supports-aria-prop/index.js +2 -1
  98. package/lib/sizes-auto-requires-lazy-loading/index.d.ts +3 -1
  99. package/lib/sizes-auto-requires-lazy-loading/index.js +30 -16
  100. package/lib/srcset-sizes-constraint/parse-srcset.d.ts +6 -5
  101. package/lib/srcset-sizes-constraint/parse-srcset.js +8 -7
  102. package/lib/srcset-sizes-constraint/sibling-helpers.d.ts +31 -0
  103. package/lib/srcset-sizes-constraint/sibling-helpers.js +58 -0
  104. package/lib/valid-speculation-rules/index.js +1 -1
  105. package/lib/wai-aria/checkings/contradictory-aria-prop.js +3 -5
  106. package/lib/wai-aria/checkings/default-value.js +1 -1
  107. package/lib/wai-aria/checkings/deprecated-props.js +2 -2
  108. package/lib/wai-aria/checkings/element-supports-aria-prop.js +5 -4
  109. package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +1 -1
  110. package/lib/wai-aria/checkings/interaction-in-hidden.js +1 -1
  111. package/lib/wai-aria/checkings/no-global-prop.js +1 -1
  112. package/lib/wai-aria/checkings/presentational-children.d.ts +4 -4
  113. package/lib/wai-aria/checkings/presentational-children.js +6 -5
  114. package/lib/wai-aria/checkings/prohibited-naming.js +5 -4
  115. package/lib/wai-aria/checkings/redundant-aria-prop.js +3 -5
  116. package/lib/wai-aria/checkings/required-prop.js +1 -4
  117. package/lib/wai-aria/checkings/role-supports-aria-prop.js +4 -3
  118. package/lib/wai-aria/checkings/tab-requires-tabpanel.d.ts +3 -2
  119. package/lib/wai-aria/checkings/tab-requires-tabpanel.js +3 -2
  120. package/lib/wai-aria/checkings/value.d.ts +1 -1
  121. package/lib/wai-aria/checkings/value.js +2 -2
  122. package/package.json +19 -19
@@ -13,7 +13,7 @@ export const checkingDefaultValue = ({ attr, propSpecs }) => t => {
13
13
  if (attr.isDynamicValue) {
14
14
  return;
15
15
  }
16
- const propSpec = propSpecs.find(p => p.name === attr.name);
16
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
17
17
  const value = attr.value.trim().toLowerCase();
18
18
  if (propSpec?.defaultValue != null && propSpec.defaultValue === value) {
19
19
  return {
@@ -13,9 +13,9 @@ export const checkingDeprecatedProps = ({ attr, role, propSpecs }) => t => {
13
13
  if (!role) {
14
14
  return;
15
15
  }
16
- const props = role.ownedProperties.find(p => p.name === attr.name);
16
+ const props = role.ownedProperties.find(p => p.name === attr.nameKey);
17
17
  if (props?.deprecated) {
18
- const propSpec = propSpecs.find(p => p.name === attr.name);
18
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
19
19
  return {
20
20
  scope: attr,
21
21
  message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec?.type ?? 'property'}`), 'deprecated'), t('the "{0*}" {1}', role.name, 'role')),
@@ -1,3 +1,4 @@
1
+ import { isAriaAttr } from '../../helpers.js';
1
2
  import { ARIA_RECOMMENDED_VERSION, getARIA } from '@markuplint/ml-spec';
2
3
  /**
3
4
  * Checks the ARIA in HTML element-specific `aria-*` restrictions: spec data
@@ -13,13 +14,13 @@ import { ARIA_RECOMMENDED_VERSION, getARIA } from '@markuplint/ml-spec';
13
14
  * @returns A violation if the element-specific restriction disallows the property.
14
15
  */
15
16
  export const checkingElementSupportsAriaProp = ({ attr, role, propSpecs }) => t => {
16
- if (!/^aria-/i.test(attr.name)) {
17
+ if (!isAriaAttr(attr)) {
17
18
  return;
18
19
  }
19
20
  const ariaVersion = attr.rule.options?.version ??
20
21
  attr.ownerMLDocument.ruleCommonSettings?.ariaVersion ??
21
22
  ARIA_RECOMMENDED_VERSION;
22
- const propSpec = propSpecs.find(p => p.name === attr.name);
23
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
23
24
  const elAriaSpec = getARIA(attr.ownerMLDocument.specs, attr.ownerElement.localName, attr.ownerElement.namespaceURI, ariaVersion, attr.ownerElement.matches.bind(attr.ownerElement));
24
25
  // Spec data may set `properties: false` to forbid every aria-* attribute on
25
26
  // elements that have no implicit role and accept no explicit role
@@ -47,7 +48,7 @@ export const checkingElementSupportsAriaProp = ({ attr, role, propSpecs }) => t
47
48
  // already implemented in the `properties.without` branch below.
48
49
  if (elAriaSpec?.properties !== false && elAriaSpec?.properties?.only) {
49
50
  const onlyNames = elAriaSpec.properties.only.map(o => (typeof o === 'string' ? o : o.name));
50
- if (!onlyNames.includes(attr.name)) {
51
+ if (!onlyNames.includes(attr.nameKey)) {
51
52
  return {
52
53
  scope: attr,
53
54
  message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec?.type ?? 'property'}`), 'disallowed'), t('the "{0*}" {1}', attr.ownerElement.localName, 'element')),
@@ -56,7 +57,7 @@ export const checkingElementSupportsAriaProp = ({ attr, role, propSpecs }) => t
56
57
  }
57
58
  if (elAriaSpec?.properties !== false && elAriaSpec?.properties?.without) {
58
59
  for (const ignore of elAriaSpec.properties.without) {
59
- if (ignore.name === attr.name) {
60
+ if (ignore.name === attr.nameKey) {
60
61
  const hasNativeAttr = ignore.alt?.method === 'set-attr' && attr.ownerElement.hasAttribute(ignore.alt.target);
61
62
  return {
62
63
  scope: attr,
@@ -6,7 +6,7 @@ import type { ElementChecker } from '@markuplint/ml-core';
6
6
  * Including Elements in the Accessibility Tree
7
7
  *
8
8
  * @see https://w3c.github.io/aria/#tree_inclusion
9
- * > Elements that are not hidden and may fire an accessibility API event, including:
9
+ * > Elements that are not hidden and can fire an accessibility API event, including:
10
10
  * > - Elements that are currently focused, even if the element or one of its ancestor elements has its aria-hidden attribute set to true.
11
11
  * > - Elements that are a valid target of an aria-activedescendant attribute.
12
12
  *
@@ -5,7 +5,7 @@ import { mayBeFocusable } from '@markuplint/ml-spec';
5
5
  * Including Elements in the Accessibility Tree
6
6
  *
7
7
  * @see https://w3c.github.io/aria/#tree_inclusion
8
- * > Elements that are not hidden and may fire an accessibility API event, including:
8
+ * > Elements that are not hidden and can fire an accessibility API event, including:
9
9
  * > - Elements that are currently focused, even if the element or one of its ancestor elements has its aria-hidden attribute set to true.
10
10
  * > - Elements that are a valid target of an aria-activedescendant attribute.
11
11
  *
@@ -9,7 +9,7 @@
9
9
  * @returns A violation if the property is not a global ARIA property.
10
10
  */
11
11
  export const checkingNoGlobalProp = ({ attr, propSpecs }) => t => {
12
- const propSpec = propSpecs.find(prop => prop.name === attr.name);
12
+ const propSpec = propSpecs.find(prop => prop.name === attr.nameKey);
13
13
  if (propSpec && !propSpec.isGlobal) {
14
14
  return {
15
15
  scope: attr,
@@ -6,14 +6,14 @@ import type { ElementChecker } from '@markuplint/ml-core';
6
6
  *
7
7
  * Presentational Children
8
8
  *
9
- * @see https://www.w3.org/TR/wai-aria/#childrenArePresentational
9
+ * @see https://w3c.github.io/aria/#childrenArePresentational
10
10
  * @see https://w3c.github.io/aria/#childrenArePresentational
11
11
  *
12
- * > The DOM descendants are presentational.
12
+ * > Indicates whether DOM descendants are presentational.
13
13
  * > user agents SHOULD NOT expose descendants of
14
14
  * > this element through the platform accessibility API.
15
15
  * > If user agents do not hide the descendant nodes,
16
- * > some information may be read twice.
16
+ * > some information might be read twice.
17
17
  *
18
18
  * @see https://w3c.github.io/aria/#tree_exclusion
19
19
  *
@@ -26,7 +26,7 @@ import type { ElementChecker } from '@markuplint/ml-core';
26
26
  * @see https://w3c.github.io/aria/#tree_inclusion
27
27
  *
28
28
  * > Text equivalents for hidden referenced objects
29
- * > may still be used in the name and description computation
29
+ * > can still be used in the name and description computation
30
30
  * > even when not included in the accessibility tree.
31
31
  *
32
32
  * @param el - The element node to inspect for presentational ancestor context.
@@ -1,3 +1,4 @@
1
+ import { isAriaAttr } from '../../helpers.js';
1
2
  import { ARIA_RECOMMENDED_VERSION, getComputedRole } from '@markuplint/ml-spec';
2
3
  /**
3
4
  * Checks whether ARIA attributes are applied to descendants of an element whose
@@ -5,14 +6,14 @@ import { ARIA_RECOMMENDED_VERSION, getComputedRole } from '@markuplint/ml-spec';
5
6
  *
6
7
  * Presentational Children
7
8
  *
8
- * @see https://www.w3.org/TR/wai-aria/#childrenArePresentational
9
+ * @see https://w3c.github.io/aria/#childrenArePresentational
9
10
  * @see https://w3c.github.io/aria/#childrenArePresentational
10
11
  *
11
- * > The DOM descendants are presentational.
12
+ * > Indicates whether DOM descendants are presentational.
12
13
  * > user agents SHOULD NOT expose descendants of
13
14
  * > this element through the platform accessibility API.
14
15
  * > If user agents do not hide the descendant nodes,
15
- * > some information may be read twice.
16
+ * > some information might be read twice.
16
17
  *
17
18
  * @see https://w3c.github.io/aria/#tree_exclusion
18
19
  *
@@ -25,7 +26,7 @@ import { ARIA_RECOMMENDED_VERSION, getComputedRole } from '@markuplint/ml-spec';
25
26
  * @see https://w3c.github.io/aria/#tree_inclusion
26
27
  *
27
28
  * > Text equivalents for hidden referenced objects
28
- * > may still be used in the name and description computation
29
+ * > can still be used in the name and description computation
29
30
  * > even when not included in the accessibility tree.
30
31
  *
31
32
  * @param el - The element node to inspect for presentational ancestor context.
@@ -39,7 +40,7 @@ export const checkingPresentationalChildren = ({ el }) => t => {
39
40
  if (!ancestor.role) {
40
41
  return;
41
42
  }
42
- const hasAriaAttr = [...el.attributes].some(attr => /^aria-|^role$/i.test(attr.name));
43
+ const hasAriaAttr = [...el.attributes].some(attr => isAriaAttr(attr) || attr.nameKey === 'role');
43
44
  if (!hasAriaAttr) {
44
45
  return;
45
46
  }
@@ -1,9 +1,10 @@
1
+ import { isAriaAttr } from '../../helpers.js';
1
2
  import { ARIA_RECOMMENDED_VERSION, getARIA } from '@markuplint/ml-spec';
2
3
  /**
3
4
  * ARIA naming attributes subject to the "naming prohibition" constraint
4
5
  * defined by ARIA in HTML.
5
6
  *
6
- * @see https://w3c.github.io/html-aria/#dfn-naming-prohibited
7
+ * @see https://www.w3.org/TR/html-aria/#dfn-naming-prohibited
7
8
  */
8
9
  const NAMING_ATTRS = new Set(['aria-label', 'aria-labelledby', 'aria-braillelabel']);
9
10
  /**
@@ -35,10 +36,10 @@ const NAMING_ATTRS = new Set(['aria-label', 'aria-labelledby', 'aria-braillelabe
35
36
  * @returns A violation if a naming attribute is used on a naming-prohibited element.
36
37
  */
37
38
  export const checkingProhibitedNaming = ({ attr, role, propSpecs }) => t => {
38
- if (!/^aria-/i.test(attr.name)) {
39
+ if (!isAriaAttr(attr)) {
39
40
  return;
40
41
  }
41
- if (!NAMING_ATTRS.has(attr.name)) {
42
+ if (!NAMING_ATTRS.has(attr.nameKey)) {
42
43
  return;
43
44
  }
44
45
  if (role) {
@@ -56,7 +57,7 @@ export const checkingProhibitedNaming = ({ attr, role, propSpecs }) => t => {
56
57
  if (elAriaSpec?.namingProhibited !== true && !isAutonomousCustomElement) {
57
58
  return;
58
59
  }
59
- const propSpec = propSpecs.find(p => p.name === attr.name);
60
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
60
61
  return {
61
62
  scope: attr,
62
63
  message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec?.type ?? 'property'}`), 'prohibited'), t('the "{0*}" {1}', attr.ownerElement.localName, 'element')),
@@ -22,20 +22,18 @@ export const checkingRedundantAriaProp = ({ attr, propSpecs, attrSpecs }) => t =
22
22
  if (attr.isDynamicValue) {
23
23
  return;
24
24
  }
25
- const propSpec = propSpecs.find(p => p.name === attr.name);
25
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
26
26
  if (!propSpec?.equivalentHtmlAttrs) {
27
27
  return;
28
28
  }
29
29
  for (const equivalentHtmlAttr of propSpec.equivalentHtmlAttrs) {
30
30
  const eligibility = resolveAttrEligibility(equivalentHtmlAttr.htmlAttrName, attr.ownerElement, attrSpecs);
31
31
  // Skip only when the native attribute doesn't apply to this element at all
32
- // (unknown name, case mismatch, or an unmet condition) — mirrors the old
32
+ // (unknown name or an unmet condition) — mirrors the old
33
33
  // `invalidType === 'non-existent'` check. `noUse` still proceeds: an
34
34
  // explicitly-forbidden native attribute can still be "implicit" for
35
35
  // equivalence purposes.
36
- if (eligibility.status === 'unknown' ||
37
- eligibility.status === 'case-mismatch' ||
38
- eligibility.status === 'condition-not-met') {
36
+ if (eligibility.status === 'unknown' || eligibility.status === 'condition-not-met') {
39
37
  continue;
40
38
  }
41
39
  if (!attr.ownerElement.hasAttribute(equivalentHtmlAttr.htmlAttrName)) {
@@ -34,10 +34,7 @@ export const checkingRequiredProp = ({ el, role, propSpecs }) => t => {
34
34
  return true;
35
35
  });
36
36
  for (const { name: requiredProp } of requiredProps) {
37
- const has = el.attributes.some(attr => {
38
- const attrName = attr.name.toLowerCase();
39
- return attrName === requiredProp;
40
- });
37
+ const has = el.attributes.some(attr => attr.nameKey === requiredProp);
41
38
  if (!has) {
42
39
  const propSpec = propSpecs.find(p => p.name === requiredProp);
43
40
  const ariaVersion = el.rule.options?.version ??
@@ -1,3 +1,4 @@
1
+ import { isAriaAttr } from '../../helpers.js';
1
2
  /**
2
3
  * Checks whether an ARIA property or state is supported by the element's
3
4
  * computed role, per the role's WAI-ARIA definition (`ownedProperties`).
@@ -12,17 +13,17 @@
12
13
  * @returns A violation if the property is not supported by the given role.
13
14
  */
14
15
  export const checkingRoleSupportsAriaProp = ({ attr, role, propSpecs }) => t => {
15
- if (!/^aria-/i.test(attr.name)) {
16
+ if (!isAriaAttr(attr)) {
16
17
  return;
17
18
  }
18
19
  if (!role) {
19
20
  return;
20
21
  }
21
- const statesAndProp = role.ownedProperties.find(p => p.name === attr.name);
22
+ const statesAndProp = role.ownedProperties.find(p => p.name === attr.nameKey);
22
23
  if (statesAndProp) {
23
24
  return;
24
25
  }
25
- const propSpec = propSpecs.find(p => p.name === attr.name);
26
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
26
27
  return {
27
28
  scope: attr,
28
29
  message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0*}" {1}', attr.name, `ARIA ${propSpec?.type ?? 'property'}`), 'disallowed'), t('the "{0*}" {1}', role.name, 'role')),
@@ -8,8 +8,9 @@ import type { ARIARole } from '@markuplint/ml-spec';
8
8
  * express it: the tab's `aria-controls` idref list points to a `tabpanel`, or some
9
9
  * `tabpanel` element's `aria-labelledby` idref list points back at the tab's own `id`.
10
10
  *
11
- * @see https://www.w3.org/TR/wai-aria-1.3/#tab — "Authors MUST ensure that if a tab
12
- * is active, a corresponding tabpanel that represents the active tab is rendered."
11
+ * > Authors MUST ensure that if a tab is active, a corresponding tabpanel that represents the active tab is rendered.
12
+ *
13
+ * @see https://w3c.github.io/aria/#tab
13
14
  * @param el - The element node to inspect.
14
15
  * @param role - The computed ARIA role of the element.
15
16
  * @returns A violation if the active tab has no corresponding tabpanel.
@@ -6,8 +6,9 @@ import { ARIA_RECOMMENDED_VERSION, getComputedRole } from '@markuplint/ml-spec';
6
6
  * express it: the tab's `aria-controls` idref list points to a `tabpanel`, or some
7
7
  * `tabpanel` element's `aria-labelledby` idref list points back at the tab's own `id`.
8
8
  *
9
- * @see https://www.w3.org/TR/wai-aria-1.3/#tab — "Authors MUST ensure that if a tab
10
- * is active, a corresponding tabpanel that represents the active tab is rendered."
9
+ * > Authors MUST ensure that if a tab is active, a corresponding tabpanel that represents the active tab is rendered.
10
+ *
11
+ * @see https://w3c.github.io/aria/#tab
11
12
  * @param el - The element node to inspect.
12
13
  * @param role - The computed ARIA role of the element.
13
14
  * @returns A violation if the active tab has no corresponding tabpanel.
@@ -26,7 +26,7 @@ export declare const checkingValue: AttrChecker<boolean, Options, {
26
26
  * Supports token, token list, string, ID reference, true/false, tristate,
27
27
  * true/false/undefined, integer, and number value types.
28
28
  *
29
- * @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
29
+ * @see https://w3c.github.io/aria/#propcharacteristic_value
30
30
  * @param type - The ARIA value type (e.g., `"token"`, `"true/false"`, `"integer"`).
31
31
  * @param value - The raw attribute value to validate.
32
32
  * @param tokenEnum - The list of allowed token values for token-based types.
@@ -16,7 +16,7 @@ export const checkingValue = ({ attr, role, propSpecs, booleanish }) => t => {
16
16
  if (attr.isDynamicValue) {
17
17
  return;
18
18
  }
19
- const propSpec = propSpecs.find(p => p.name === attr.name);
19
+ const propSpec = propSpecs.find(p => p.name === attr.nameKey);
20
20
  const result = checkAria(propSpec, attr.value, role?.name, booleanish);
21
21
  if (result.isValid) {
22
22
  return;
@@ -68,7 +68,7 @@ function checkAria(propSpec, currentValue, role, booleanish) {
68
68
  * Supports token, token list, string, ID reference, true/false, tristate,
69
69
  * true/false/undefined, integer, and number value types.
70
70
  *
71
- * @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
71
+ * @see https://w3c.github.io/aria/#propcharacteristic_value
72
72
  * @param type - The ARIA value type (e.g., `"token"`, `"true/false"`, `"integer"`).
73
73
  * @param value - The raw attribute value to validate.
74
74
  * @param tokenEnum - The list of allowed token values for token-based types.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/rules",
3
- "version": "5.1.1",
3
+ "version": "5.3.0",
4
4
  "description": "Built-in rules of markuplint",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,8 +15,8 @@
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": {
18
- "import": "./lib/index.js",
19
- "types": "./lib/index.d.ts"
18
+ "types": "./lib/index.d.ts",
19
+ "default": "./lib/index.js"
20
20
  }
21
21
  },
22
22
  "publishConfig": {
@@ -31,21 +31,21 @@
31
31
  "./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
32
32
  },
33
33
  "dependencies": {
34
- "@markuplint/html-spec": "5.1.1",
35
- "@markuplint/ml-config": "5.1.1",
36
- "@markuplint/ml-core": "5.1.1",
37
- "@markuplint/ml-spec": "5.1.1",
38
- "@markuplint/selector": "5.1.1",
39
- "@markuplint/shared": "5.1.1",
40
- "@markuplint/types": "5.1.1",
41
- "@mdn/browser-compat-data": "^7.3.2",
42
- "@types/debug": "4.1.13",
43
- "ansi-colors": "4.1.3",
44
- "browserslist": "^4.28.1",
45
- "chrono-node": "2.9.0",
46
- "debug": "4.4.3",
47
- "image-size": "^2.0.2",
48
- "type-fest": "5.6.0"
34
+ "@markuplint/html-spec": "5.3.0",
35
+ "@markuplint/ml-config": "5.3.0",
36
+ "@markuplint/ml-core": "5.3.0",
37
+ "@markuplint/ml-spec": "5.3.0",
38
+ "@markuplint/selector": "5.3.0",
39
+ "@markuplint/shared": "5.3.0",
40
+ "@markuplint/types": "5.3.0",
41
+ "@mdn/browser-compat-data": "^8.1.5",
42
+ "@types/debug": "^4.1.13",
43
+ "ansi-colors": "^4.1.3",
44
+ "browserslist": "^4.29.3",
45
+ "chrono-node": "^2.10.3",
46
+ "debug": "^4.4.3",
47
+ "image-size": "^2.0.4",
48
+ "type-fest": "^5.10.0"
49
49
  },
50
- "gitHead": "a940c8526e971d590d97395ce924910221208820"
50
+ "gitHead": "f587cf0206c8426e57369a48d6d5fb22306eafde"
51
51
  }