@markuplint/rules 4.12.0 → 5.0.0-alpha.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 (83) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/lib/attr-check.d.ts +5 -2
  3. package/lib/attr-check.js +13 -3
  4. package/lib/character-reference/index.d.ts +2 -1
  5. package/lib/character-reference/index.js +5 -1
  6. package/lib/correct-aspect-ratio/index.d.ts +5 -0
  7. package/lib/correct-aspect-ratio/index.js +80 -0
  8. package/lib/correct-aspect-ratio/meta.d.ts +4 -0
  9. package/lib/correct-aspect-ratio/meta.js +3 -0
  10. package/lib/correct-aspect-ratio/resolve-image-size.d.ts +24 -0
  11. package/lib/correct-aspect-ratio/resolve-image-size.js +165 -0
  12. package/lib/create-message.d.ts +2 -2
  13. package/lib/create-message.js +4 -1
  14. package/lib/deprecated-element/index.d.ts +2 -4
  15. package/lib/deprecated-element/index.js +4 -6
  16. package/lib/end-tag/index.js +1 -1
  17. package/lib/heading-levels/index.js +0 -1
  18. package/lib/helpers.d.ts +1 -0
  19. package/lib/helpers.js +8 -15
  20. package/lib/index.d.ts +30 -41
  21. package/lib/index.js +12 -0
  22. package/lib/invalid-attr/index.d.ts +12 -28
  23. package/lib/invalid-attr/index.js +50 -116
  24. package/lib/link-types/index.d.ts +10 -0
  25. package/lib/link-types/index.js +180 -0
  26. package/lib/link-types/meta.d.ts +5 -0
  27. package/lib/link-types/meta.js +4 -0
  28. package/lib/neighbor-popovers/index.js +3 -5
  29. package/lib/no-orphaned-end-tag/index.d.ts +2 -2
  30. package/lib/no-orphaned-end-tag/index.js +3 -4
  31. package/lib/no-refer-to-non-existent-id/index.d.ts +1 -1
  32. package/lib/no-refer-to-non-existent-id/index.js +2 -2
  33. package/lib/no-unsupported-features/compat-data.d.ts +71 -0
  34. package/lib/no-unsupported-features/compat-data.js +204 -0
  35. package/lib/no-unsupported-features/index.d.ts +24 -0
  36. package/lib/no-unsupported-features/index.js +139 -0
  37. package/lib/no-unsupported-features/meta.d.ts +5 -0
  38. package/lib/no-unsupported-features/meta.js +4 -0
  39. package/lib/no-unsupported-features/resolve-browsers.d.ts +30 -0
  40. package/lib/no-unsupported-features/resolve-browsers.js +125 -0
  41. package/lib/permitted-contents/choice.js +1 -1
  42. package/lib/permitted-contents/count-pattern.js +1 -1
  43. package/lib/permitted-contents/order.js +1 -1
  44. package/lib/permitted-contents/represent-transparent-nodes.d.ts +26 -1
  45. package/lib/permitted-contents/represent-transparent-nodes.js +96 -13
  46. package/lib/permitted-contents/utils.d.ts +1 -1
  47. package/lib/permitted-contents/utils.js +22 -35
  48. package/lib/redundant-accessible-name/index.d.ts +10 -0
  49. package/lib/redundant-accessible-name/index.js +123 -0
  50. package/lib/redundant-accessible-name/meta.d.ts +5 -0
  51. package/lib/redundant-accessible-name/meta.js +4 -0
  52. package/lib/require-accessible-name/index.d.ts +3 -8
  53. package/lib/require-accessible-name/index.js +6 -5
  54. package/lib/require-dialog-autofocus/index.d.ts +22 -0
  55. package/lib/require-dialog-autofocus/index.js +62 -0
  56. package/lib/require-dialog-autofocus/meta.d.ts +5 -0
  57. package/lib/require-dialog-autofocus/meta.js +4 -0
  58. package/lib/required-attr/index.d.ts +8 -1
  59. package/lib/required-attr/index.js +27 -4
  60. package/lib/required-element/index.js +1 -1
  61. package/lib/srcset-sizes-constraint/index.d.ts +6 -0
  62. package/lib/srcset-sizes-constraint/index.js +108 -0
  63. package/lib/srcset-sizes-constraint/meta.d.ts +5 -0
  64. package/lib/srcset-sizes-constraint/meta.js +4 -0
  65. package/lib/srcset-sizes-constraint/parse-srcset.d.ts +40 -0
  66. package/lib/srcset-sizes-constraint/parse-srcset.js +56 -0
  67. package/lib/table-row-column-alignment/grid.js +22 -29
  68. package/lib/wai-aria/checkings/abstract-role.js +5 -2
  69. package/lib/wai-aria/checkings/disallowed-prop.js +5 -2
  70. package/lib/wai-aria/checkings/implicit-role.js +5 -2
  71. package/lib/wai-aria/checkings/non-existent-role.d.ts +1 -0
  72. package/lib/wai-aria/checkings/non-existent-role.js +9 -2
  73. package/lib/wai-aria/checkings/permitted-roles.js +5 -2
  74. package/lib/wai-aria/checkings/presentational-children.js +3 -2
  75. package/lib/wai-aria/checkings/required-accessibility-parent-role.d.ts +25 -0
  76. package/lib/wai-aria/checkings/required-accessibility-parent-role.js +56 -0
  77. package/lib/wai-aria/checkings/required-owned-elements.d.ts +5 -4
  78. package/lib/wai-aria/checkings/required-owned-elements.js +57 -28
  79. package/lib/wai-aria/checkings/required-prop.js +5 -2
  80. package/lib/wai-aria/index.js +12 -4
  81. package/lib/wai-aria/types.d.ts +9 -2
  82. package/package.json +15 -10
  83. package/schema.json +18 -0
@@ -1,22 +1,23 @@
1
- import { getComputedRole, isRequiredOwnedElement } from '@markuplint/ml-spec';
1
+ import { ARIA_RECOMMENDED_VERSION, getComputedRole, isRequiredOwnedElement, isTransparentForOwnership, } from '@markuplint/ml-spec';
2
2
  /**
3
- * Checks whether an element with a role that requires specific owned elements
4
- * actually contains children with the expected roles.
3
+ * Checks whether an element with a role that has "Allowed Accessibility Child Roles"
4
+ * (called "Required Owned Elements" in ARIA 1.2) actually contains children
5
+ * with the expected roles.
5
6
  *
6
7
  * For example, a `list` role must own at least one element with the `listitem` role.
7
8
  * This checker respects `aria-busy="true"` (which signals that content is still loading),
8
9
  * preprocessor blocks, and mutable children from template engines.
9
10
  *
10
11
  * @see https://w3c.github.io/aria/#mustContain
11
- * @param el - The element node to inspect for required owned elements.
12
- * @param role - The computed ARIA role of the element, which defines required owned elements.
12
+ * @param el - The element node to inspect for allowed accessibility child roles.
13
+ * @param role - The computed ARIA role of the element, which defines allowed accessibility child roles.
13
14
  * @returns A violation if the role requires owned elements and none are found.
14
15
  */
15
16
  export const checkingRequiredOwnedElements = ({ el, role }) => t => {
16
17
  if (!role) {
17
18
  return;
18
19
  }
19
- if (role.requiredOwnedElements.length === 0) {
20
+ if (role.allowedAccessibilityChildRoles.length === 0) {
20
21
  return;
21
22
  }
22
23
  /**
@@ -33,22 +34,8 @@ export const checkingRequiredOwnedElements = ({ el, role }) => t => {
33
34
  return;
34
35
  }
35
36
  // TODO: Needs to resolve `aria-own`
36
- const children = [...el.childNodes].map(child => {
37
- if (child.is(child.ELEMENT_NODE)) {
38
- if (child.matches('[aria-busy="true" i]')) {
39
- return [child, 'BUSY'];
40
- }
41
- const computedChild = getComputedRole(child.ownerMLDocument.specs, child, child.rule.options.version);
42
- if (role.requiredOwnedElements.some(ownedRole => isRequiredOwnedElement(computedChild.el, computedChild.role, ownedRole, child.ownerMLDocument.specs, child.rule.options.version))) {
43
- return [child, 'REQUIRED'];
44
- }
45
- return [child, 'OTHER'];
46
- }
47
- else if (child.is(child.MARKUPLINT_PREPROCESSOR_BLOCK)) {
48
- return [child, 'PB'];
49
- }
50
- return [null, 'NO_ELEMENT'];
51
- });
37
+ const ariaVersion = el.rule.options?.version ?? el.ownerMLDocument.ruleCommonSettings?.ariaVersion ?? ARIA_RECOMMENDED_VERSION;
38
+ const children = classifyChildren(el, role, ariaVersion);
52
39
  if (children.some(([, type]) => type === 'BUSY')) {
53
40
  return;
54
41
  }
@@ -83,16 +70,16 @@ export const checkingRequiredOwnedElements = ({ el, role }) => t => {
83
70
  if (mayBeBeforeCreated(el)) {
84
71
  return {
85
72
  scope: el,
86
- message: t('{0}. Or, {1}', t('{0} requires {1}', t('the {0}', 'child element'), role.requiredOwnedElements.length === 1 && role.requiredOwnedElements[0]
87
- ? t('the "{0*}" {1}', role.requiredOwnedElements[0], 'role')
88
- : t('the {0}', 'roles') + `: ${t(role.requiredOwnedElements)}`), t('require {0}', 'aria-busy="true"')),
73
+ message: t('{0}. Or, {1}', t('{0} requires {1}', t('the {0}', 'child element'), role.allowedAccessibilityChildRoles.length === 1 && role.allowedAccessibilityChildRoles[0]
74
+ ? t('the "{0*}" {1}', role.allowedAccessibilityChildRoles[0], 'role')
75
+ : t('the {0}', 'roles') + `: ${t(role.allowedAccessibilityChildRoles)}`), t('require {0}', 'aria-busy="true"')),
89
76
  };
90
77
  }
91
78
  return {
92
79
  scope: el,
93
- message: t('{0} expects {1}', t('the "{0*}" {1}', role.name, 'role'), role.requiredOwnedElements.length === 1 && role.requiredOwnedElements[0]
94
- ? t('the "{0*}" {1}', role.requiredOwnedElements[0], 'role')
95
- : t('the {0}', 'roles') + `: ${t(role.requiredOwnedElements)}`),
80
+ message: t('{0} expects {1}', t('the "{0*}" {1}', role.name, 'role'), role.allowedAccessibilityChildRoles.length === 1 && role.allowedAccessibilityChildRoles[0]
81
+ ? t('the "{0*}" {1}', role.allowedAccessibilityChildRoles[0], 'role')
82
+ : t('the {0}', 'roles') + `: ${t(role.allowedAccessibilityChildRoles)}`),
96
83
  };
97
84
  };
98
85
  /**
@@ -112,3 +99,45 @@ el) {
112
99
  return ['script', 'template'].includes(child.localName);
113
100
  });
114
101
  }
102
+ /**
103
+ * Classifies the child nodes of an element for "Allowed Accessibility Child Roles" validation.
104
+ *
105
+ * In ARIA 1.3, elements whose computed role is transparent for ownership
106
+ * (e.g., `generic`) are traversed recursively so that their descendants
107
+ * are evaluated as if they were direct children of the owning element.
108
+ *
109
+ * @param el - The parent element whose children to classify.
110
+ * @param role - The ARIA role of the parent, which defines allowed child roles.
111
+ * @param version - The WAI-ARIA version for version-gated transparency behavior.
112
+ * @returns An array of classified child nodes.
113
+ */
114
+ function classifyChildren(
115
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
116
+ el, role, version) {
117
+ const result = [];
118
+ for (const child of el.childNodes) {
119
+ if (child.is(child.ELEMENT_NODE)) {
120
+ if (child.matches('[aria-busy="true" i]')) {
121
+ result.push([child, 'BUSY']);
122
+ continue;
123
+ }
124
+ const computedChild = getComputedRole(child.ownerMLDocument.specs, child, version);
125
+ if (role.allowedAccessibilityChildRoles.some(ownedRole => isRequiredOwnedElement(computedChild.el, computedChild.role, ownedRole, child.ownerMLDocument.specs, version))) {
126
+ result.push([child, 'REQUIRED']);
127
+ continue;
128
+ }
129
+ if (isTransparentForOwnership(computedChild.role?.name, version)) {
130
+ result.push(...classifyChildren(child, role, version));
131
+ continue;
132
+ }
133
+ result.push([child, 'OTHER']);
134
+ }
135
+ else if (child.is(child.MARKUPLINT_PREPROCESSOR_BLOCK)) {
136
+ result.push([child, 'PB']);
137
+ }
138
+ else {
139
+ result.push([null, 'NO_ELEMENT']);
140
+ }
141
+ }
142
+ return result;
143
+ }
@@ -1,4 +1,4 @@
1
- import { getARIA } from '@markuplint/ml-spec';
1
+ import { ARIA_RECOMMENDED_VERSION, getARIA } from '@markuplint/ml-spec';
2
2
  /**
3
3
  * Checks whether all required ARIA properties for the element's computed role are present.
4
4
  *
@@ -27,7 +27,10 @@ export const checkingRequiredProp = ({ el, role, propSpecs }) => t => {
27
27
  });
28
28
  if (!has) {
29
29
  const propSpec = propSpecs.find(p => p.name === requiredProp);
30
- const elAriaSpec = getARIA(el.ownerMLDocument.specs, el.localName, el.namespaceURI, el.rule.options.version, el.matches.bind(el));
30
+ const ariaVersion = el.rule.options?.version ??
31
+ el.ownerMLDocument.ruleCommonSettings?.ariaVersion ??
32
+ ARIA_RECOMMENDED_VERSION;
33
+ const elAriaSpec = getARIA(el.ownerMLDocument.specs, el.localName, el.namespaceURI, ariaVersion, el.matches.bind(el));
31
34
  const alt = elAriaSpec?.properties === false
32
35
  ? null
33
36
  : (elAriaSpec?.properties?.without?.find(p => p.name === requiredProp)?.alt ?? null);
@@ -13,6 +13,7 @@ import { checkingNoGlobalProp } from './checkings/no-global-prop.js';
13
13
  import { checkingNonExistentRole } from './checkings/non-existent-role.js';
14
14
  import { checkingPermittedRoles } from './checkings/permitted-roles.js';
15
15
  import { checkingPresentationalChildren } from './checkings/presentational-children.js';
16
+ import { checkingRequiredAccessibilityParentRole } from './checkings/required-accessibility-parent-role.js';
16
17
  import { checkingRequiredOwnedElements } from './checkings/required-owned-elements.js';
17
18
  import { checkingRequiredProp } from './checkings/required-prop.js';
18
19
  import { checkingValue } from './checkings/value.js';
@@ -34,13 +35,15 @@ export default createRule({
34
35
  checkingDeprecatedRole: true,
35
36
  checkingDeprecatedProps: true,
36
37
  permittedAriaRoles: true,
38
+ checkingAllowedAccessibilityChildRoles: true,
37
39
  checkingRequiredOwnedElements: true,
40
+ checkingRequiredAccessibilityParentRole: true,
38
41
  checkingPresentationalChildren: false,
39
42
  checkingInteractionInHidden: false,
40
43
  disallowSetImplicitRole: true,
41
44
  disallowSetImplicitProps: true,
42
45
  disallowDefaultValue: false,
43
- version: ARIA_RECOMMENDED_VERSION,
46
+ version: undefined,
44
47
  },
45
48
  async verify({ document, report, t }) {
46
49
  await document.walkOn('Element', el => {
@@ -60,8 +63,9 @@ export default createRule({
60
63
  }
61
64
  return;
62
65
  }
63
- const computed = getComputedRole(document.specs, el, el.rule.options.version);
64
- const { props: propSpecs } = ariaSpecs(document.specs, el.rule.options.version);
66
+ const ariaVersion = el.rule.options?.version ?? document.ruleCommonSettings?.ariaVersion ?? ARIA_RECOMMENDED_VERSION;
67
+ const computed = getComputedRole(document.specs, el, ariaVersion);
68
+ const { props: propSpecs } = ariaSpecs(document.specs, ariaVersion);
65
69
  if (roleAttr) {
66
70
  if (report(checkingNonExistentRole({ attr: roleAttr }))) {
67
71
  return;
@@ -69,6 +73,9 @@ export default createRule({
69
73
  if (report(checkingAbstractRole({ attr: roleAttr }))) {
70
74
  return;
71
75
  }
76
+ if (el.rule.options.checkingRequiredAccessibilityParentRole) {
77
+ report(checkingRequiredAccessibilityParentRole({ el, computed }));
78
+ }
72
79
  report(checkingRequiredProp({ el, role: computed.role, propSpecs }));
73
80
  if (el.rule.options.checkingDeprecatedRole) {
74
81
  report(checkingDeprecatedRole({ attr: roleAttr, role: computed.role }));
@@ -104,7 +111,8 @@ export default createRule({
104
111
  report(checkingNoGlobalProp({ attr, propSpecs }));
105
112
  }
106
113
  }
107
- if (el.rule.options.checkingRequiredOwnedElements) {
114
+ if (el.rule.options.checkingAllowedAccessibilityChildRoles &&
115
+ el.rule.options.checkingRequiredOwnedElements) {
108
116
  report(checkingRequiredOwnedElements({ el, role: computed.role }));
109
117
  }
110
118
  if (el.rule.options.checkingPresentationalChildren) {
@@ -14,8 +14,15 @@ export type Options = {
14
14
  checkingDeprecatedRole: boolean;
15
15
  /** Whether to enforce the list of permitted ARIA roles for each element. */
16
16
  permittedAriaRoles: boolean;
17
- /** Whether to verify that roles requiring specific owned elements contain them. */
17
+ /** Whether to verify "Allowed Accessibility Child Roles" (ARIA 1.3 name). */
18
+ checkingAllowedAccessibilityChildRoles: boolean;
19
+ /**
20
+ * @deprecated Use `checkingAllowedAccessibilityChildRoles` instead.
21
+ * Retained for backward compatibility.
22
+ */
18
23
  checkingRequiredOwnedElements: boolean;
24
+ /** Whether to verify "Required Accessibility Parent Role" (ARIA 1.3 name) / "Required Context Role" (ARIA 1.2 name). */
25
+ checkingRequiredAccessibilityParentRole: boolean;
19
26
  /** Whether to warn when ARIA attributes are set on descendants of presentational-children roles. */
20
27
  checkingPresentationalChildren: boolean;
21
28
  /** Whether to warn about focusable interactive elements hidden via `aria-hidden`. */
@@ -27,5 +34,5 @@ export type Options = {
27
34
  /** Whether to disallow explicitly setting an ARIA property to its default value. */
28
35
  disallowDefaultValue: boolean;
29
36
  /** The WAI-ARIA specification version to validate against. */
30
- version: ARIAVersion;
37
+ version?: ARIAVersion;
31
38
  };
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@markuplint/rules",
3
- "version": "4.12.0",
3
+ "version": "5.0.0-alpha.0",
4
4
  "description": "Built-in rules of markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
7
7
  "license": "MIT",
8
+ "engines": {
9
+ "node": ">=22"
10
+ },
8
11
  "type": "module",
9
12
  "exports": {
10
13
  ".": {
@@ -24,18 +27,20 @@
24
27
  "./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
25
28
  },
26
29
  "dependencies": {
27
- "@markuplint/html-spec": "4.17.0",
28
- "@markuplint/ml-core": "4.13.3",
29
- "@markuplint/ml-spec": "4.10.2",
30
- "@markuplint/selector": "4.7.8",
31
- "@markuplint/shared": "4.4.13",
32
- "@markuplint/types": "4.8.2",
30
+ "@markuplint/html-spec": "5.0.0-alpha.0",
31
+ "@markuplint/ml-core": "5.0.0-alpha.0",
32
+ "@markuplint/ml-spec": "5.0.0-alpha.0",
33
+ "@markuplint/selector": "5.0.0-alpha.0",
34
+ "@markuplint/shared": "5.0.0-alpha.0",
35
+ "@markuplint/types": "5.0.0-alpha.0",
36
+ "@mdn/browser-compat-data": "^7.3.2",
33
37
  "@types/debug": "4.1.12",
34
- "@ungap/structured-clone": "1.3.0",
35
38
  "ansi-colors": "4.1.3",
39
+ "browserslist": "^4.28.1",
36
40
  "chrono-node": "2.9.0",
37
41
  "debug": "4.4.3",
38
- "type-fest": "4.41.0"
42
+ "image-size": "^2.0.2",
43
+ "type-fest": "5.4.4"
39
44
  },
40
- "gitHead": "193ee7c1262bbed95424e38efdf1a8e56ff049f4"
45
+ "gitHead": "13dcfc84ec83d87360c720e253383b60767e1b56"
41
46
  }
package/schema.json CHANGED
@@ -24,6 +24,9 @@
24
24
  "class-naming": {
25
25
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/class-naming/schema.json"
26
26
  },
27
+ "correct-aspect-ratio": {
28
+ "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/correct-aspect-ratio/schema.json"
29
+ },
27
30
  "deprecated-attr": {
28
31
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/deprecated-attr/schema.json"
29
32
  },
@@ -57,6 +60,9 @@
57
60
  "landmark-roles": {
58
61
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/landmark-roles/schema.json"
59
62
  },
63
+ "link-types": {
64
+ "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/link-types/schema.json"
65
+ },
60
66
  "neighbor-popovers": {
61
67
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/neighbor-popovers/schema.json"
62
68
  },
@@ -87,6 +93,9 @@
87
93
  "no-refer-to-non-existent-id": {
88
94
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/no-refer-to-non-existent-id/schema.json"
89
95
  },
96
+ "no-unsupported-features": {
97
+ "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/no-unsupported-features/schema.json"
98
+ },
90
99
  "no-use-event-handler-attr": {
91
100
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/no-use-event-handler-attr/schema.json"
92
101
  },
@@ -96,12 +105,18 @@
96
105
  "placeholder-label-option": {
97
106
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/placeholder-label-option/schema.json"
98
107
  },
108
+ "redundant-accessible-name": {
109
+ "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/redundant-accessible-name/schema.json"
110
+ },
99
111
  "require-accessible-name": {
100
112
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/require-accessible-name/schema.json"
101
113
  },
102
114
  "require-datetime": {
103
115
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/require-datetime/schema.json"
104
116
  },
117
+ "require-dialog-autofocus": {
118
+ "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/require-dialog-autofocus/schema.json"
119
+ },
105
120
  "required-attr": {
106
121
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/required-attr/schema.json"
107
122
  },
@@ -111,6 +126,9 @@
111
126
  "required-h1": {
112
127
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/required-h1/schema.json"
113
128
  },
129
+ "srcset-sizes-constraint": {
130
+ "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/srcset-sizes-constraint/schema.json"
131
+ },
114
132
  "table-row-column-alignment": {
115
133
  "$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/table-row-column-alignment/schema.json"
116
134
  },