@markuplint/ml-spec 3.0.0-alpha.82 → 3.0.0-dev.176

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 (138) hide show
  1. package/README.md +8 -3
  2. package/lib/constant/aria-version.d.ts +2 -0
  3. package/lib/constant/aria-version.js +5 -0
  4. package/lib/dom-traverse/accname-computation.js +3 -1
  5. package/lib/dom-traverse/get-attr-specs.d.ts +1 -1
  6. package/lib/dom-traverse/get-attr-specs.js +3 -1
  7. package/lib/dom-traverse/get-computed-aria-props.d.ts +12 -0
  8. package/lib/dom-traverse/get-computed-aria-props.js +108 -0
  9. package/lib/dom-traverse/get-computed-role.d.ts +6 -1
  10. package/lib/dom-traverse/get-computed-role.js +54 -35
  11. package/lib/dom-traverse/get-content-model.d.ts +29 -0
  12. package/lib/dom-traverse/get-content-model.js +30 -0
  13. package/lib/dom-traverse/get-explicit-role.js +9 -4
  14. package/lib/dom-traverse/get-implicit-role.d.ts +6 -2
  15. package/lib/dom-traverse/get-implicit-role.js +6 -2
  16. package/lib/dom-traverse/get-non-presentational-ancestor.d.ts +10 -4
  17. package/lib/dom-traverse/get-non-presentational-ancestor.js +10 -2
  18. package/lib/dom-traverse/get-permitted-roles.d.ts +7 -3
  19. package/lib/dom-traverse/get-permitted-roles.js +3 -1
  20. package/lib/dom-traverse/get-spec.d.ts +5 -2
  21. package/lib/dom-traverse/get-spec.js +4 -2
  22. package/lib/dom-traverse/has-required-owned-elements.d.ts +8 -2
  23. package/lib/dom-traverse/has-required-owned-elements.js +26 -8
  24. package/lib/dom-traverse/is-exposed.d.ts +11 -0
  25. package/lib/dom-traverse/is-exposed.js +217 -0
  26. package/lib/dom-traverse/matches-context-role.d.ts +7 -0
  27. package/lib/dom-traverse/matches-context-role.js +27 -0
  28. package/lib/dom-traverse/may-be-focusable.d.ts +2 -0
  29. package/lib/dom-traverse/may-be-focusable.js +24 -0
  30. package/lib/index.d.ts +11 -1
  31. package/lib/index.js +11 -1
  32. package/lib/specs/aria-specs.d.ts +7 -4
  33. package/lib/specs/content-model-category-to-tag-names.d.ts +5 -2
  34. package/lib/specs/content-model-category-to-tag-names.js +2 -2
  35. package/lib/specs/get-aria.d.ts +8 -1
  36. package/lib/specs/get-aria.js +11 -5
  37. package/lib/specs/get-attr-specs.d.ts +7 -3
  38. package/lib/specs/get-attr-specs.js +2 -14
  39. package/lib/specs/get-implicit-role.d.ts +7 -1
  40. package/lib/specs/get-permitted-roles.d.ts +9 -3
  41. package/lib/specs/get-permitted-roles.js +19 -15
  42. package/lib/specs/get-role-spec.d.ts +10 -3
  43. package/lib/specs/get-role-spec.js +2 -2
  44. package/lib/specs/get-selectors-by-content-model-category.d.ts +2 -2
  45. package/lib/specs/get-selectors-by-content-model-category.js +1 -1
  46. package/lib/specs/get-spec-by-tag-name.d.ts +6 -2
  47. package/lib/specs/get-spec-by-tag-name.js +3 -2
  48. package/lib/specs/is-nothing-content-model.d.ts +5 -0
  49. package/lib/specs/is-nothing-content-model.js +14 -0
  50. package/lib/specs/is-palpable-elements.d.ts +9 -0
  51. package/lib/specs/is-palpable-elements.js +49 -0
  52. package/lib/specs/is-void-element.d.ts +1 -0
  53. package/lib/specs/is-void-element.js +27 -0
  54. package/lib/specs/resolve-version.d.ts +5 -1
  55. package/lib/specs/resolve-version.js +1 -1
  56. package/lib/specs/schema-to-spec.d.ts +4 -4
  57. package/lib/specs/schema-to-spec.js +29 -18
  58. package/lib/types/aria.d.ts +150 -109
  59. package/lib/types/attributes.d.ts +1507 -73
  60. package/lib/types/index.d.ts +195 -166
  61. package/{src/types/permitted-structres.ts → lib/types/permitted-structures.d.ts} +24 -35
  62. package/lib/utils/get-ns.d.ts +2 -1
  63. package/lib/utils/get-ns.js +3 -0
  64. package/lib/utils/merge-array.d.ts +9 -4
  65. package/lib/utils/resolve-namespace.d.ts +7 -7
  66. package/lib/utils/resolve-namespace.js +19 -13
  67. package/lib/utils/validateAriaVersion.d.ts +2 -0
  68. package/lib/utils/validateAriaVersion.js +8 -0
  69. package/package.json +13 -8
  70. package/schema.json +6 -6
  71. package/{src/dom-traverse/accname-computation.spec.ts → test/dom-traverse/accname-computation.spec.js} +8 -8
  72. package/test/dom-traverse/get-computed-aria-props.spec.js +758 -0
  73. package/test/dom-traverse/get-computed-role.spec.js +294 -0
  74. package/test/dom-traverse/get-implicit-role.spec.js +40 -0
  75. package/{src/dom-traverse/has-required-owned-elements.spec.ts → test/dom-traverse/has-required-owned-elements.spec.js} +7 -9
  76. package/test/dom-traverse/is-exposed.spec.js +70 -0
  77. package/test/dom-traverse/matches-context-role.spec.js +60 -0
  78. package/{src/specs/get-attr-specs.spec.ts → test/specs/get-attr-specs.spec.js} +2 -8
  79. package/{src/specs/get-implicit-role.spec.ts → test/specs/get-implicit-role.spec.js} +9 -11
  80. package/{src/specs/get-permitted-roles.spec.ts → test/specs/get-permitted-roles.spec.js} +8 -10
  81. package/{src/specs/get-role-spec.spec.ts → test/specs/get-role-spec.spec.js} +4 -4
  82. package/{src/specs/get-spec-by-tag-name.spec.ts → test/specs/get-spec-by-tag-name.spec.js} +11 -11
  83. package/test/specs/resolve-version.spec.js +34 -0
  84. package/test/specs/schema-to-spec.spec.js +61 -0
  85. package/test/utils/resolve-namespace.spec.js +37 -0
  86. package/lib/dom-traverse/focusability-computation.d.ts +0 -1
  87. package/lib/dom-traverse/focusability-computation.js +0 -8
  88. package/lib/dom-traverse/get-aria.d.ts +0 -9
  89. package/lib/dom-traverse/get-aria.js +0 -54
  90. package/lib/specs/aria-spec.d.ts +0 -5
  91. package/lib/specs/aria-spec.js +0 -12
  92. package/lib/specs/get-spec.d.ts +0 -13
  93. package/lib/specs/get-spec.js +0 -85
  94. package/lib/specs/html-spec.d.ts +0 -6
  95. package/lib/specs/html-spec.js +0 -16
  96. package/lib/specs/resolve-namespace.d.ts +0 -9
  97. package/lib/specs/resolve-namespace.js +0 -26
  98. package/lib/types/permitted-structres.d.ts +0 -64
  99. package/lib/utils.d.ts +0 -8
  100. package/lib/utils.js +0 -50
  101. package/schemas/aria.schema.json +0 -258
  102. package/schemas/attributes.schema.json +0 -204
  103. package/schemas/content-models.schema.json +0 -215
  104. package/schemas/element.schema.json +0 -11
  105. package/schemas/global-attributes.schema.json +0 -761
  106. package/src/dom-traverse/accname-computation.ts +0 -5
  107. package/src/dom-traverse/get-attr-specs.ts +0 -8
  108. package/src/dom-traverse/get-computed-role.spec.ts +0 -134
  109. package/src/dom-traverse/get-computed-role.ts +0 -193
  110. package/src/dom-traverse/get-explicit-role.ts +0 -112
  111. package/src/dom-traverse/get-implicit-role.ts +0 -36
  112. package/src/dom-traverse/get-non-presentational-ancestor.ts +0 -20
  113. package/src/dom-traverse/get-permitted-roles.ts +0 -7
  114. package/src/dom-traverse/get-spec.ts +0 -7
  115. package/src/dom-traverse/has-required-owned-elements.ts +0 -72
  116. package/src/index.ts +0 -17
  117. package/src/specs/aria-specs.ts +0 -6
  118. package/src/specs/content-model-category-to-tag-names.ts +0 -15
  119. package/src/specs/get-aria.ts +0 -85
  120. package/src/specs/get-attr-specs.ts +0 -116
  121. package/src/specs/get-implicit-role.ts +0 -17
  122. package/src/specs/get-permitted-roles.ts +0 -87
  123. package/src/specs/get-role-spec.ts +0 -72
  124. package/src/specs/get-selectors-by-content-model-category.ts +0 -10
  125. package/src/specs/get-spec-by-tag-name.ts +0 -16
  126. package/src/specs/is-presentational.ts +0 -6
  127. package/src/specs/resolve-version.ts +0 -20
  128. package/src/specs/schema-to-spec.spec.ts +0 -39
  129. package/src/specs/schema-to-spec.ts +0 -103
  130. package/src/types/aria.ts +0 -147
  131. package/src/types/attributes.ts +0 -1418
  132. package/src/types/index.ts +0 -255
  133. package/src/utils/get-ns.ts +0 -13
  134. package/src/utils/merge-array.ts +0 -35
  135. package/src/utils/resolve-namespace.ts +0 -36
  136. package/tsconfig.test.json +0 -3
  137. package/tsconfig.tsbuildinfo +0 -1
  138. /package/lib/types/{permitted-structres.js → permitted-structures.js} +0 -0
package/README.md CHANGED
@@ -1,13 +1,18 @@
1
1
  # @markuplint/ml-spec
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40markuplint%2Fml-spec.svg)](https://www.npmjs.com/package/@markuplint/ml-spec)
4
- [![Build Status](https://travis-ci.org/markuplint/markuplint.svg?branch=main)](https://travis-ci.org/markuplint/markuplint)
5
- [![Coverage Status](https://coveralls.io/repos/github/markuplint/markuplint/badge.svg?branch=main)](https://coveralls.io/github/markuplint/markuplint?branch=main)
6
4
 
7
5
  ## Install
8
6
 
9
- ```sh
7
+ [`markuplint`](https://www.npmjs.com/package/markuplint) package includes this package.
8
+
9
+ <details>
10
+ <summary>If you are installing purposely, how below:</summary>
11
+
12
+ ```shell
10
13
  $ npm install @markuplint/ml-spec
11
14
 
12
15
  $ yarn add @markuplint/ml-spec
13
16
  ```
17
+
18
+ </details>
@@ -0,0 +1,2 @@
1
+ export declare const ariaVersions: readonly ['1.1', '1.2', '1.3'];
2
+ export declare const ARIA_RECOMMENDED_VERSION: '1.2';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ARIA_RECOMMENDED_VERSION = exports.ariaVersions = void 0;
4
+ exports.ariaVersions = ['1.1', '1.2', '1.3'];
5
+ exports.ARIA_RECOMMENDED_VERSION = '1.2';
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAccname = void 0;
4
4
  const dom_accessibility_api_1 = require("dom-accessibility-api");
5
- function getAccname(el) {
5
+ function getAccname(
6
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
7
+ el) {
6
8
  return (0, dom_accessibility_api_1.computeAccessibleName)(el);
7
9
  }
8
10
  exports.getAccname = getAccname;
@@ -1,2 +1,2 @@
1
1
  import type { MLMLSpec } from '../types';
2
- export declare function getAttrSpecs(el: Element, schema: MLMLSpec): import("../types").Attribute[] | null;
2
+ export declare function getAttrSpecs(el: Element, schema: MLMLSpec): readonly import('../types').Attribute[] | null;
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAttrSpecs = void 0;
4
4
  const get_attr_specs_1 = require("../specs/get-attr-specs");
5
- function getAttrSpecs(el, schema) {
5
+ function getAttrSpecs(
6
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
7
+ el, schema) {
6
8
  return (0, get_attr_specs_1.getAttrSpecs)(el.localName, el.namespaceURI, schema);
7
9
  }
8
10
  exports.getAttrSpecs = getAttrSpecs;
@@ -0,0 +1,12 @@
1
+ import type { ARIAVersion, MLMLSpec } from '../types';
2
+ type ARIAProps = Record<string, ARIAProp>;
3
+ type ARIAProp = {
4
+ name: string;
5
+ value: string | undefined;
6
+ required: boolean;
7
+ deprecated: boolean;
8
+ from: ARIAPropReferenceType;
9
+ };
10
+ type ARIAPropReferenceType = 'default' | 'html-attr' | 'aria-attr';
11
+ export declare function getComputedAriaProps(specs: MLMLSpec, el: Element, version: ARIAVersion): ARIAProps;
12
+ export {};
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getComputedAriaProps = void 0;
4
+ const aria_specs_1 = require("../specs/aria-specs");
5
+ const get_computed_role_1 = require("./get-computed-role");
6
+ function getComputedAriaProps(specs,
7
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
+ el, version) {
9
+ const ariaSpecs = (0, aria_specs_1.ariaSpecs)(specs, version);
10
+ const { role } = (0, get_computed_role_1.getComputedRole)(specs, el, version);
11
+ if (!role) {
12
+ return {};
13
+ }
14
+ const props = {};
15
+ role.ownedProperties.forEach(ownedProp => {
16
+ var _a;
17
+ const spec = ariaSpecs.props.find(propSpec => propSpec.name === ownedProp.name);
18
+ if (!spec) {
19
+ return;
20
+ }
21
+ if (el.hasAttribute(spec.name)) {
22
+ const attrValue = el.getAttribute(spec.name);
23
+ if (attrValue && isValidAriaValue(spec, role.name, attrValue, spec.enum)) {
24
+ props[ownedProp.name] = {
25
+ name: ownedProp.name,
26
+ value: attrValue,
27
+ deprecated: !!spec.deprecated,
28
+ required: !!ownedProp.required,
29
+ from: 'aria-attr',
30
+ };
31
+ return;
32
+ }
33
+ }
34
+ const equivalentHtmlAttr = (_a = spec.equivalentHtmlAttrs) === null || _a === void 0 ? void 0 : _a[0];
35
+ if (equivalentHtmlAttr && el.hasAttribute(equivalentHtmlAttr.htmlAttrName)) {
36
+ const value = equivalentHtmlAttr.value === null
37
+ ? el.getAttribute(equivalentHtmlAttr.htmlAttrName)
38
+ : equivalentHtmlAttr.value;
39
+ if (value != null) {
40
+ props[ownedProp.name] = {
41
+ name: ownedProp.name,
42
+ value,
43
+ deprecated: !!spec.deprecated,
44
+ required: !!ownedProp.required,
45
+ from: 'html-attr',
46
+ };
47
+ return;
48
+ }
49
+ }
50
+ let defaultValue = spec.defaultValue;
51
+ /**
52
+ * @see https://www.w3.org/TR/html-aria/#el-h1-h6
53
+ */
54
+ if (ownedProp.name === 'aria-level' && /^H[1-6]$/.test(el.nodeName)) {
55
+ defaultValue = el.nodeName.replace('H', '');
56
+ }
57
+ props[ownedProp.name] = {
58
+ name: ownedProp.name,
59
+ value: defaultValue,
60
+ deprecated: !!spec.deprecated,
61
+ required: !!ownedProp.required,
62
+ from: 'default',
63
+ };
64
+ });
65
+ return props;
66
+ }
67
+ exports.getComputedAriaProps = getComputedAriaProps;
68
+ function isValidAriaValue(spec, role, value, enumList) {
69
+ let type = spec.value;
70
+ if (spec.conditionalValue) {
71
+ for (const cond of spec.conditionalValue) {
72
+ if (cond.role.includes(role)) {
73
+ type = cond.value;
74
+ }
75
+ }
76
+ }
77
+ value = (value !== null && value !== void 0 ? value : '').trim();
78
+ switch (type) {
79
+ case 'string': {
80
+ return true;
81
+ }
82
+ case 'ID reference':
83
+ case 'ID reference list':
84
+ case 'URI': {
85
+ return !!value;
86
+ }
87
+ case 'integer':
88
+ case 'number': {
89
+ return !isNaN(parseFloat(value));
90
+ }
91
+ case 'token':
92
+ case 'token list': {
93
+ if (enumList.length === 0) {
94
+ throw new Error('Need an enum list in token and token list types');
95
+ }
96
+ return enumList.includes(value.toLowerCase());
97
+ }
98
+ case 'tristate': {
99
+ return ['true', 'false', 'mixed'].includes(value.toLowerCase());
100
+ }
101
+ case 'true/false': {
102
+ return ['true', 'false'].includes(value.toLowerCase());
103
+ }
104
+ case 'true/false/undefined': {
105
+ return ['true', 'false', 'undefined'].includes(value.toLowerCase());
106
+ }
107
+ }
108
+ }
@@ -1,2 +1,7 @@
1
1
  import type { ARIAVersion, ComputedRole, MLMLSpec } from '../types';
2
- export declare function getComputedRole(specs: Readonly<MLMLSpec>, el: Element, version: ARIAVersion): ComputedRole;
2
+ export declare function getComputedRole(
3
+ specs: MLMLSpec,
4
+ el: Element,
5
+ version: ARIAVersion,
6
+ assumeSingleNode?: boolean,
7
+ ): ComputedRole;
@@ -2,18 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getComputedRole = void 0;
4
4
  const aria_specs_1 = require("../specs/aria-specs");
5
- const get_selectors_by_content_model_category_1 = require("../specs/get-selectors-by-content-model-category");
6
5
  const is_presentational_1 = require("../specs/is-presentational");
7
6
  const get_attr_specs_1 = require("./get-attr-specs");
8
7
  const get_explicit_role_1 = require("./get-explicit-role");
9
8
  const get_implicit_role_1 = require("./get-implicit-role");
10
9
  const get_non_presentational_ancestor_1 = require("./get-non-presentational-ancestor");
11
10
  const has_required_owned_elements_1 = require("./has-required-owned-elements");
12
- function getComputedRole(specs, el, version) {
13
- var _a, _b, _c, _d;
11
+ const matches_context_role_1 = require("./matches-context-role");
12
+ const may_be_focusable_1 = require("./may-be-focusable");
13
+ function getComputedRole(specs,
14
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
15
+ el, version, assumeSingleNode = false) {
16
+ var _a, _b;
14
17
  const implicitRole = (0, get_implicit_role_1.getImplicitRole)(specs, el, version);
15
18
  const explicitRole = (0, get_explicit_role_1.getExplicitRole)(specs, el, version);
16
- const computedRole = explicitRole.role ? explicitRole : implicitRole;
19
+ const computedRole = explicitRole.role
20
+ ? explicitRole
21
+ : {
22
+ ...implicitRole,
23
+ errorType: explicitRole.errorType === 'NO_EXPLICIT' ? undefined : explicitRole.errorType,
24
+ };
25
+ if (assumeSingleNode) {
26
+ return {
27
+ ...computedRole,
28
+ errorType: 'NO_OWNER',
29
+ };
30
+ }
17
31
  /**
18
32
  * Presentational Roles Conflict Resolution
19
33
  *
@@ -39,7 +53,20 @@ function getComputedRole(specs, el, version) {
39
53
  * However, the presentational role behaves transparently
40
54
  * according to the sample code in WAI-ARIA specification.
41
55
  */
42
- if ((_a = computedRole.role) === null || _a === void 0 ? void 0 : _a.requiredContextRole.length) {
56
+ if (computedRole.role && computedRole.role.requiredContextRole.length > 0) {
57
+ /**
58
+ * An element fragment that serves as the root without a parent element
59
+ * cannot satisfy the "Required Context Role" condition.
60
+ * Therefore, under normal circumstances, the `role` will disappear.
61
+ * However, in this specific case, it will fall back to both explicit
62
+ * and implicit roles. Note that the explicit role takes precedence.
63
+ */
64
+ if (el.parentElement === null) {
65
+ return {
66
+ ...computedRole,
67
+ errorType: 'NO_OWNER',
68
+ };
69
+ }
43
70
  const nonPresentationalAncestor = (0, get_non_presentational_ancestor_1.getNonPresentationalAncestor)(el, specs, version);
44
71
  if (!nonPresentationalAncestor.role) {
45
72
  return {
@@ -48,7 +75,7 @@ function getComputedRole(specs, el, version) {
48
75
  errorType: 'NO_OWNER',
49
76
  };
50
77
  }
51
- if (!((_b = computedRole.role) === null || _b === void 0 ? void 0 : _b.requiredContextRole.includes(nonPresentationalAncestor.role.name))) {
78
+ if (!(0, matches_context_role_1.matchesContextRole)(computedRole.role.requiredContextRole, el, specs, version)) {
52
79
  return {
53
80
  el,
54
81
  role: null,
@@ -72,38 +99,26 @@ function getComputedRole(specs, el, version) {
72
99
  */
73
100
  if (
74
101
  /**
75
- * Interactive element
102
+ * If interactive element
103
+ *
104
+ * 1. It may be focusable
105
+ *
106
+ * THIS CONDITION IS ALMOST MEANINGLESS.
107
+ * Because it has already been determined that
108
+ * the interactive elements can not specify the presentational role
109
+ * in the previous processing that computes the permitted role (`getExplicitRole`).
76
110
  */
77
- [
78
- /**
79
- * Interactive content
80
- *
81
- * THIS CONDITION(SELECTORS) IS ALMOST MEANINGLESS.
82
- * Because it has already been determined that
83
- * the interactive elements can not specify the presentational role
84
- * in the previous processing that computes the permitted role (`getExplicitRole`).
85
- *
86
- * @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content
87
- */
88
- ...(0, get_selectors_by_content_model_category_1.getSelectorsByContentModelCategory)(specs, '#interactive'),
89
- /**
90
- * Interaction
91
- *
92
- * @see https://html.spec.whatwg.org/multipage/interaction.html
93
- */
94
- '[tabindex]',
95
- '[contenteditable]:not([contenteditable="false" i])',
96
- ].some(selector => el.matches(selector)) &&
111
+ (0, may_be_focusable_1.mayBeFocusable)(el, specs) &&
97
112
  /**
98
- * No disabled
113
+ * 2. No disabled
99
114
  */
100
115
  !someAncestors(el, p => isEnabledAttr(p, specs, 'disabled')) &&
101
116
  /**
102
- * No inert
117
+ * 3. No inert
103
118
  */
104
119
  !someAncestors(el, p => isEnabledAttr(p, specs, 'inert')) &&
105
120
  /**
106
- * No hidden
121
+ * 4. No hidden
107
122
  */
108
123
  !someAncestors(el, p => isEnabledAttr(p, specs, 'hidden'))) {
109
124
  return {
@@ -123,12 +138,12 @@ function getComputedRole(specs, el, version) {
123
138
  */
124
139
  if (explicitRole.role) {
125
140
  const nonPresentationalAncestor = (0, get_non_presentational_ancestor_1.getNonPresentationalAncestor)(el, specs, version);
126
- if ((_c = nonPresentationalAncestor.role) === null || _c === void 0 ? void 0 : _c.requiredOwnedElements.length) {
141
+ if (nonPresentationalAncestor.role && ((_a = nonPresentationalAncestor.role) === null || _a === void 0 ? void 0 : _a.requiredOwnedElements.length) > 0) {
127
142
  if (nonPresentationalAncestor.role.requiredOwnedElements.some(expected => {
128
143
  // const ancestor = nonPresentationalAncestor.el;
129
144
  // const ancestorImplicitRole = getImplicitRole(specs, ancestor, version);
130
145
  // console.log({ nonPresentationalAncestor, ancestorImplicitRole });
131
- return (0, has_required_owned_elements_1.isRequiredOwnedElement)(implicitRole, expected, specs, version);
146
+ return (0, has_required_owned_elements_1.isRequiredOwnedElement)(implicitRole.el, implicitRole.role, expected, specs, version);
132
147
  })) {
133
148
  return {
134
149
  ...implicitRole,
@@ -149,7 +164,7 @@ function getComputedRole(specs, el, version) {
149
164
  */
150
165
  const { props } = (0, aria_specs_1.ariaSpecs)(specs, version);
151
166
  for (const attr of Array.from(el.attributes)) {
152
- if ((_d = props.find(p => p.name === attr.name)) === null || _d === void 0 ? void 0 : _d.isGlobal) {
167
+ if ((_b = props.find(p => p.name === attr.name)) === null || _b === void 0 ? void 0 : _b.isGlobal) {
153
168
  return {
154
169
  ...implicitRole,
155
170
  errorType: 'GLOBAL_PROP_MUST_NOT_BE_PRESENTATIONAL',
@@ -163,7 +178,9 @@ exports.getComputedRole = getComputedRole;
163
178
  * The attribute is available in its owner element,
164
179
  * it has the attribute.
165
180
  */
166
- function isEnabledAttr(el, specs, attrName) {
181
+ function isEnabledAttr(
182
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
183
+ el, specs, attrName) {
167
184
  const attrs = (0, get_attr_specs_1.getAttrSpecs)(el, specs);
168
185
  const attr = attrs === null || attrs === void 0 ? void 0 : attrs.find(attr => attr.name === attrName);
169
186
  return !!attr && el.hasAttribute(attrName);
@@ -171,7 +188,9 @@ function isEnabledAttr(el, specs, attrName) {
171
188
  /**
172
189
  * Determines whether some ancestors match the condition that the specified callback function.
173
190
  */
174
- function someAncestors(el, predicate) {
191
+ function someAncestors(
192
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
193
+ el, predicate) {
175
194
  const list = [];
176
195
  let current = el;
177
196
  while (current) {
@@ -0,0 +1,29 @@
1
+ import type { ElementSpec } from '../types';
2
+ type Specs = readonly Pick<ElementSpec, 'name' | 'contentModel'>[];
3
+ export declare function getContentModel(
4
+ el: Element,
5
+ specs: Specs,
6
+ ):
7
+ | boolean
8
+ | readonly (
9
+ | import('type-fest/source/readonly-deep').ReadonlyObjectDeep<
10
+ import('../types/permitted-structures').PermittedContentRequire
11
+ >
12
+ | import('type-fest/source/readonly-deep').ReadonlyObjectDeep<
13
+ import('../types/permitted-structures').PermittedContentOptional
14
+ >
15
+ | import('type-fest/source/readonly-deep').ReadonlyObjectDeep<
16
+ import('../types/permitted-structures').PermittedContentOneOrMore
17
+ >
18
+ | import('type-fest/source/readonly-deep').ReadonlyObjectDeep<
19
+ import('../types/permitted-structures').PermittedContentZeroOrMore
20
+ >
21
+ | import('type-fest/source/readonly-deep').ReadonlyObjectDeep<
22
+ import('../types/permitted-structures').PermittedContentChoice
23
+ >
24
+ | import('type-fest/source/readonly-deep').ReadonlyObjectDeep<
25
+ import('../types/permitted-structures').PermittedContentTransparent
26
+ >
27
+ )[]
28
+ | null;
29
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getContentModel = void 0;
4
+ const get_spec_1 = require("./get-spec");
5
+ const cachesBySpecs = new Map();
6
+ function getContentModel(
7
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
+ el, specs) {
9
+ var _a, _b;
10
+ const cacheByEl = (_a = cachesBySpecs.get(specs)) !== null && _a !== void 0 ? _a : new Map();
11
+ const cached = cacheByEl.get(el);
12
+ if (cached !== undefined) {
13
+ return cached;
14
+ }
15
+ const spec = (0, get_spec_1.getSpec)(el, specs);
16
+ if (!spec) {
17
+ cacheByEl.set(el, null);
18
+ return null;
19
+ }
20
+ const conditions = (_b = spec.contentModel.conditional) !== null && _b !== void 0 ? _b : [];
21
+ for (const cond of conditions) {
22
+ if (el.matches(cond.condition)) {
23
+ cacheByEl.set(el, cond.contents);
24
+ return cond.contents;
25
+ }
26
+ }
27
+ cacheByEl.set(el, spec.contentModel.contents);
28
+ return spec.contentModel.contents;
29
+ }
30
+ exports.getContentModel = getContentModel;
@@ -4,16 +4,19 @@ exports.getExplicitRole = void 0;
4
4
  const get_role_spec_1 = require("../specs/get-role-spec");
5
5
  const resolve_namespace_1 = require("../utils/resolve-namespace");
6
6
  const get_permitted_roles_1 = require("./get-permitted-roles");
7
- function getExplicitRole(specs, el, version) {
7
+ function getExplicitRole(specs,
8
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
9
+ el, version) {
10
+ var _a;
8
11
  const roleValue = el.getAttribute('role');
9
- const roleNames = (roleValue === null || roleValue === void 0 ? void 0 : roleValue.toLowerCase().trim().split(/\s+/g)) || [];
12
+ const roleNames = (_a = roleValue === null || roleValue === void 0 ? void 0 : roleValue.toLowerCase().trim().split(/\s+/g)) !== null && _a !== void 0 ? _a : [];
10
13
  const permittedRoles = (0, get_permitted_roles_1.getPermittedRoles)(el, version, specs);
11
14
  const { namespaceURI } = (0, resolve_namespace_1.resolveNamespace)(el.localName, el.namespaceURI);
12
15
  let error = 'NO_EXPLICIT';
13
16
  /**
14
17
  * Resolve from values and **Handling Author Errors**
15
18
  *
16
- * @see https://w3c.github.io/aria/#document-handling_author-errors_roles
19
+ * @see https://w3c.github.io/aria/#document-handling_author-errors
17
20
  */
18
21
  for (const roleName of roleNames) {
19
22
  const spec = (0, get_role_spec_1.getRoleSpec)(specs, roleName, namespaceURI, version);
@@ -83,7 +86,9 @@ exports.getExplicitRole = getExplicitRole;
83
86
  function isLandmarkRole(role) {
84
87
  return role === null || role === void 0 ? void 0 : role.superClassRoles.some(su => su.name === 'landmark');
85
88
  }
86
- function isValidLandmarkRole(el, role) {
89
+ function isValidLandmarkRole(
90
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
91
+ el, role) {
87
92
  if (!role.accessibleNameRequired) {
88
93
  return true;
89
94
  }
@@ -1,3 +1,7 @@
1
1
  import type { ARIAVersion, ComputedRole, MLMLSpec } from '../types';
2
- export declare function getImplicitRole(specs: Readonly<MLMLSpec>, el: Element, version: ARIAVersion): ComputedRole;
3
- export declare function getImplicitRoleName(el: Element, version: ARIAVersion, specs: Readonly<MLMLSpec>): import("..").ImplicitRole;
2
+ export declare function getImplicitRole(specs: MLMLSpec, el: Element, version: ARIAVersion): ComputedRole;
3
+ export declare function getImplicitRoleName(
4
+ el: Element,
5
+ version: ARIAVersion,
6
+ specs: MLMLSpec,
7
+ ): import('..').ImplicitRole;
@@ -4,7 +4,9 @@ exports.getImplicitRoleName = exports.getImplicitRole = void 0;
4
4
  const get_implicit_role_1 = require("../specs/get-implicit-role");
5
5
  const get_role_spec_1 = require("../specs/get-role-spec");
6
6
  const resolve_namespace_1 = require("../utils/resolve-namespace");
7
- function getImplicitRole(specs, el, version) {
7
+ function getImplicitRole(specs,
8
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
9
+ el, version) {
8
10
  const implicitRole = getImplicitRoleName(el, version, specs);
9
11
  if (implicitRole === false) {
10
12
  // No Corresponding Role
@@ -31,7 +33,9 @@ function getImplicitRole(specs, el, version) {
31
33
  };
32
34
  }
33
35
  exports.getImplicitRole = getImplicitRole;
34
- function getImplicitRoleName(el, version, specs) {
36
+ function getImplicitRoleName(
37
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
38
+ el, version, specs) {
35
39
  return (0, get_implicit_role_1.getImplicitRole)(specs, el.localName, el.namespaceURI, version, el.matches.bind(el));
36
40
  }
37
41
  exports.getImplicitRoleName = getImplicitRoleName;
@@ -1,5 +1,11 @@
1
1
  import type { ARIAVersion, MLMLSpec } from '../types';
2
- export declare function getNonPresentationalAncestor(el: Element, specs: MLMLSpec, version: ARIAVersion): import("../types").ComputedRole | {
3
- el: null;
4
- role: null;
5
- };
2
+ export declare function getNonPresentationalAncestor(
3
+ el: Element,
4
+ specs: MLMLSpec,
5
+ version: ARIAVersion,
6
+ ):
7
+ | import('../types').ComputedRole
8
+ | {
9
+ el: null;
10
+ role: null;
11
+ };
@@ -3,11 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getNonPresentationalAncestor = void 0;
4
4
  const is_presentational_1 = require("../specs/is-presentational");
5
5
  const get_computed_role_1 = require("./get-computed-role");
6
- function getNonPresentationalAncestor(el, specs, version) {
6
+ function getNonPresentationalAncestor(
7
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
+ el, specs, version) {
7
9
  var _a;
8
10
  let ancestor = el.parentElement;
11
+ /**
12
+ * In ARIA 1.1 and 1.2, the role of an element is not affected by the role of its ancestor elements.
13
+ *
14
+ * It is due to implementation considerations in Markuplint.
15
+ */
16
+ const assumeSingleNode = version !== '1.1' && version !== '1.2';
9
17
  while (ancestor) {
10
- const ancestorRole = (0, get_computed_role_1.getComputedRole)(specs, ancestor, version);
18
+ const ancestorRole = (0, get_computed_role_1.getComputedRole)(specs, ancestor, version, assumeSingleNode);
11
19
  if (!(0, is_presentational_1.isPresentational)((_a = ancestorRole.role) === null || _a === void 0 ? void 0 : _a.name)) {
12
20
  return ancestorRole;
13
21
  }
@@ -1,5 +1,9 @@
1
1
  import type { ARIAVersion, MLMLSpec } from '../types';
2
- export declare function getPermittedRoles(el: Element, version: ARIAVersion, specs: Readonly<MLMLSpec>): {
3
- name: string;
4
- deprecated?: boolean | undefined;
2
+ export declare function getPermittedRoles(
3
+ el: Element,
4
+ version: ARIAVersion,
5
+ specs: MLMLSpec,
6
+ ): readonly {
7
+ readonly name: string;
8
+ readonly deprecated?: boolean | undefined;
5
9
  }[];
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPermittedRoles = void 0;
4
4
  const get_permitted_roles_1 = require("../specs/get-permitted-roles");
5
- function getPermittedRoles(el, version, specs) {
5
+ function getPermittedRoles(
6
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
7
+ el, version, specs) {
6
8
  return (0, get_permitted_roles_1.getPermittedRoles)(specs, el.localName, el.namespaceURI, version, el.matches.bind(el));
7
9
  }
8
10
  exports.getPermittedRoles = getPermittedRoles;
@@ -1,2 +1,5 @@
1
- import type { MLMLSpec } from '../types';
2
- export declare function getSpec(el: Element, schema: MLMLSpec): import("../types").ElementSpec | null;
1
+ import type { ElementSpec } from '../types';
2
+ export declare function getSpec<K extends keyof ElementSpec>(
3
+ el: Element,
4
+ specs: readonly Pick<ElementSpec, 'name' | K>[],
5
+ ): Pick<ElementSpec, 'name' | K> | null;
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSpec = void 0;
4
4
  const get_spec_by_tag_name_1 = require("../specs/get-spec-by-tag-name");
5
- function getSpec(el, schema) {
6
- return (0, get_spec_by_tag_name_1.getSpecByTagName)(schema, el.localName, el.namespaceURI);
5
+ function getSpec(
6
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
7
+ el, specs) {
8
+ return (0, get_spec_by_tag_name_1.getSpecByTagName)(specs, el.localName, el.namespaceURI);
7
9
  }
8
10
  exports.getSpec = getSpec;
@@ -1,3 +1,9 @@
1
1
  import type { ARIAVersion, ComputedRole, MLMLSpec } from '../types';
2
- export declare function hasRequiredOwnedElement(el: Element, specs: Readonly<MLMLSpec>, version: ARIAVersion): boolean;
3
- export declare function isRequiredOwnedElement(owned: ComputedRole, query: string, specs: MLMLSpec, version: ARIAVersion): boolean;
2
+ export declare function hasRequiredOwnedElement(el: Element, specs: MLMLSpec, version: ARIAVersion): boolean;
3
+ export declare function isRequiredOwnedElement(
4
+ el: Element,
5
+ role: ComputedRole['role'],
6
+ query: string,
7
+ specs: MLMLSpec,
8
+ version: ARIAVersion,
9
+ ): boolean;
@@ -5,14 +5,28 @@ const is_presentational_1 = require("../specs/is-presentational");
5
5
  const get_computed_role_1 = require("./get-computed-role");
6
6
  const get_explicit_role_1 = require("./get-explicit-role");
7
7
  const get_implicit_role_1 = require("./get-implicit-role");
8
- function hasRequiredOwnedElement(el, specs, version) {
8
+ function hasRequiredOwnedElement(
9
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
10
+ el, specs, version) {
11
+ /**
12
+ * The element has aria-owns which means it may have owned elements.
13
+ *
14
+ * THIS CONDITION IS PARTIAL SUPPORT.
15
+ */
16
+ if (el.hasAttribute('aria-owns')) {
17
+ // FIXME
18
+ return true;
19
+ }
20
+ /**
21
+ * Otherwise, traverses descendants to find owned elements.
22
+ */
9
23
  const computed = (0, get_computed_role_1.getComputedRole)(specs, el, version);
10
24
  if (!computed.role || computed.role.requiredOwnedElements.length === 0) {
11
25
  return true;
12
26
  }
13
27
  for (const expectRole of computed.role.requiredOwnedElements) {
14
28
  for (const owned of getClosestNonPresentationalDescendants(el, specs, version)) {
15
- if (isRequiredOwnedElement(owned, expectRole, specs, version)) {
29
+ if (isRequiredOwnedElement(owned.el, owned.role, expectRole, specs, version)) {
16
30
  return true;
17
31
  }
18
32
  }
@@ -20,17 +34,19 @@ function hasRequiredOwnedElement(el, specs, version) {
20
34
  return false;
21
35
  }
22
36
  exports.hasRequiredOwnedElement = hasRequiredOwnedElement;
23
- function isRequiredOwnedElement(owned, query, specs, version) {
24
- var _a, _b;
37
+ function isRequiredOwnedElement(
38
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
39
+ el, role, query, specs, version) {
40
+ var _a;
25
41
  const [baseRole, owningRole] = query.split(' > ');
26
- if (((_a = owned.role) === null || _a === void 0 ? void 0 : _a.name) !== baseRole) {
42
+ if ((role === null || role === void 0 ? void 0 : role.name) !== baseRole) {
27
43
  return false;
28
44
  }
29
45
  if (!owningRole) {
30
46
  return true;
31
47
  }
32
- for (const owning of getClosestNonPresentationalDescendants(owned.el, specs, version)) {
33
- if (((_b = owning.role) === null || _b === void 0 ? void 0 : _b.name) === owningRole) {
48
+ for (const owning of getClosestNonPresentationalDescendants(el, specs, version)) {
49
+ if (((_a = owning.role) === null || _a === void 0 ? void 0 : _a.name) === owningRole) {
34
50
  return true;
35
51
  }
36
52
  }
@@ -52,7 +68,9 @@ exports.isRequiredOwnedElement = isRequiredOwnedElement;
52
68
  * However, the presentational role behaves transparently
53
69
  * according to the sample code in WAI-ARIA specification.
54
70
  */
55
- function getClosestNonPresentationalDescendants(el, specs, version) {
71
+ function getClosestNonPresentationalDescendants(
72
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
73
+ el, specs, version) {
56
74
  var _a;
57
75
  const owned = [];
58
76
  for (const child of Array.from(el.children)) {