@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
@@ -1,85 +0,0 @@
1
- import type { ARIAVersion, Matches, MLMLSpec } from '../types';
2
- import type { ARIA, PermittedRoles } from '../types/aria';
3
-
4
- import { getSpecByTagName } from './get-spec-by-tag-name';
5
- import { resolveVersion } from './resolve-version';
6
-
7
- const cache = new Map<string, Omit<ARIA, ARIAVersion> | null>();
8
-
9
- export function getARIA(
10
- specs: Readonly<MLMLSpec>,
11
- localName: string,
12
- namespace: string | null,
13
- version: ARIAVersion,
14
- matches: Matches,
15
- ): Omit<ARIA, ARIAVersion | 'conditions'> | null {
16
- const aria = getVersionResolvedARIA(specs, localName, namespace, version);
17
- if (!aria) {
18
- return null;
19
- }
20
- const conditions = aria.conditions;
21
- if (!conditions) {
22
- return aria;
23
- }
24
- const conds = Object.keys(conditions);
25
- let { implicitRole, permittedRoles, implicitProperties, properties, namingProhibited } = aria;
26
- for (const cond of conds) {
27
- if (!matches(cond)) {
28
- continue;
29
- }
30
- const condARIA = conditions[cond];
31
- implicitRole = condARIA.implicitRole ?? implicitRole;
32
- permittedRoles = condARIA.permittedRoles ?? permittedRoles;
33
- implicitProperties = condARIA.implicitProperties ?? implicitProperties;
34
- properties = condARIA.properties ?? properties;
35
- namingProhibited = condARIA.namingProhibited ?? namingProhibited;
36
- }
37
- return {
38
- implicitRole,
39
- permittedRoles,
40
- implicitProperties,
41
- properties,
42
- namingProhibited,
43
- };
44
- }
45
-
46
- function getVersionResolvedARIA(
47
- specs: Readonly<MLMLSpec>,
48
- localName: string,
49
- namespace: string | null,
50
- version: ARIAVersion,
51
- ) {
52
- const key = localName + namespace + version;
53
- let aria = cache.get(key);
54
- if (aria !== undefined) {
55
- return aria;
56
- }
57
- const spec = getSpecByTagName(specs, localName, namespace)?.aria;
58
- if (!spec) {
59
- cache.set(key, null);
60
- return null;
61
- }
62
- aria = resolveVersion(spec, version);
63
- if (aria.permittedRoles) {
64
- aria.permittedRoles = optimizePermittedRoles(aria.permittedRoles);
65
- }
66
- cache.set(key, aria);
67
- return aria;
68
- }
69
-
70
- function optimizePermittedRoles(permittedRoles: PermittedRoles) {
71
- if (!Array.isArray(permittedRoles)) {
72
- return permittedRoles;
73
- }
74
- const unique = new Set(permittedRoles);
75
-
76
- // https://www.w3.org/TR/wai-aria-1.2/#note-regarding-the-aria-1-1-none-role
77
- if (unique.has('presentation')) {
78
- unique.add('none');
79
- }
80
- if (unique.has('none')) {
81
- unique.add('presentation');
82
- }
83
-
84
- return Array.from(unique).sort();
85
- }
@@ -1,116 +0,0 @@
1
- import type { MLMLSpec, Attribute } from '../types';
2
- import type { NamespaceURI } from '@markuplint/ml-ast';
3
-
4
- import { resolveNamespace } from '../utils/resolve-namespace';
5
-
6
- const cacheMap = new Map<string, Attribute[] | null>();
7
- const schemaCache = new WeakSet<MLMLSpec>();
8
-
9
- export function getAttrSpecs(localName: string, namespace: NamespaceURI | null, schema: MLMLSpec) {
10
- if (!schemaCache.has(schema)) {
11
- cacheMap.clear();
12
- }
13
-
14
- const { localNameWithNS } = resolveNamespace(localName, namespace || undefined);
15
-
16
- const cache = cacheMap.get(localNameWithNS);
17
-
18
- if (cache !== undefined) {
19
- return cache;
20
- }
21
-
22
- schemaCache.add(schema);
23
-
24
- const elSpec = schema.specs.find(spec => spec.name === localNameWithNS);
25
- if (!elSpec) {
26
- cacheMap.set(localNameWithNS, null);
27
- return null;
28
- }
29
-
30
- const globalAttrs = schema.def['#globalAttrs'];
31
- let attrs: Record<string, Partial<Attribute>> = {};
32
-
33
- for (const catName in elSpec.globalAttrs) {
34
- // @ts-ignore
35
- const catAttrs: boolean | string[] = elSpec.globalAttrs[catName];
36
- if (!catAttrs) {
37
- continue;
38
- }
39
- if (typeof catAttrs === 'boolean') {
40
- const global = globalAttrs[catName];
41
- attrs = {
42
- ...attrs,
43
- ...global,
44
- };
45
- continue;
46
- }
47
- if (Array.isArray(catAttrs)) {
48
- const global = globalAttrs[catName];
49
- if (!global) {
50
- continue;
51
- }
52
- catAttrs.forEach(selectedName => {
53
- const selected = global[selectedName];
54
- attrs[selectedName] = {
55
- ...attrs[selectedName],
56
- ...selected,
57
- };
58
- });
59
- continue;
60
- }
61
- }
62
-
63
- for (const attrName in elSpec.attributes) {
64
- const attr = elSpec.attributes[attrName];
65
- if (!attr) {
66
- continue;
67
- }
68
-
69
- const current = attrs[attrName] as Omit<Attribute, 'name'> | undefined;
70
-
71
- attrs[attrName] = {
72
- description: '',
73
- ...current,
74
- ...attr,
75
- };
76
- }
77
-
78
- const attrList: Attribute[] = Object.keys(attrs).map<Attribute>(name => {
79
- const attr = attrs[name];
80
- return { name, type: 'Any', ...attr };
81
- });
82
-
83
- for (const attr of attrList) {
84
- if (!attr.type) {
85
- throw new Error(
86
- `The type is empty in the ${attr.name} attribute of the ${localName} element,
87
- 'packages',
88
- '@markuplint',
89
- 'html-spec',
90
- 'src',
91
- 'attributes',
92
- nameWithNS.replace(':', '_') + '.json',
93
- )})`,
94
- );
95
- }
96
- }
97
-
98
- attrList.sort(nameCompare);
99
-
100
- cacheMap.set(localNameWithNS, attrList);
101
- return attrList;
102
- }
103
-
104
- type HasName = { name: string };
105
-
106
- export function nameCompare(a: HasName | string, b: HasName | string) {
107
- const nameA = typeof a === 'string' ? a : a.name.toUpperCase();
108
- const nameB = typeof b === 'string' ? b : b.name.toUpperCase();
109
- if (nameA < nameB) {
110
- return -1;
111
- }
112
- if (nameA > nameB) {
113
- return 1;
114
- }
115
- return 0;
116
- }
@@ -1,17 +0,0 @@
1
- import type { ARIAVersion, Matches, MLMLSpec } from '../types';
2
-
3
- import { getARIA } from './get-aria';
4
-
5
- export function getImplicitRole(
6
- specs: Readonly<MLMLSpec>,
7
- localName: string,
8
- namespace: string | null,
9
- version: ARIAVersion,
10
- matches: Matches,
11
- ) {
12
- const aria = getARIA(specs, localName, namespace, version, matches);
13
- if (!aria) {
14
- return false;
15
- }
16
- return aria.implicitRole;
17
- }
@@ -1,87 +0,0 @@
1
- import type { ARIAVersion, Matches, MLMLSpec } from '../types';
2
-
3
- import { mergeArray } from '../utils/merge-array';
4
-
5
- import { ariaSpecs } from './aria-specs';
6
- import { getARIA } from './get-aria';
7
-
8
- /**
9
- * Getting permitted ARIA roles.
10
- *
11
- * - If an array, it is role list.
12
- * - If `true`, this mean is "Any".
13
- * - If `false`, this mean is "No".
14
- */
15
- export function getPermittedRoles(
16
- specs: Readonly<MLMLSpec>,
17
- localName: string,
18
- namespace: string | null,
19
- version: ARIAVersion,
20
- matches: Matches,
21
- ): { name: string; deprecated?: boolean }[] {
22
- const aria = getARIA(specs, localName, namespace, version, matches);
23
- if (!aria) {
24
- return [];
25
- }
26
- const { implicitRole, permittedRoles } = aria;
27
- const { roles, graphicsRoles } = ariaSpecs(specs, version);
28
-
29
- let permittedRoleList: { name: string }[] = [];
30
-
31
- if (permittedRoles === true) {
32
- permittedRoleList = mergeArray(
33
- permittedRoleList,
34
- roles
35
- .filter(role => !role.isAbstract)
36
- .map(role => ({
37
- name: role.name,
38
- })),
39
- );
40
- }
41
-
42
- if (Array.isArray(permittedRoles)) {
43
- permittedRoleList = mergeArray(
44
- permittedRoleList,
45
- permittedRoles.map(role => {
46
- if (typeof role === 'string') {
47
- return {
48
- name: role,
49
- };
50
- }
51
- return role;
52
- }),
53
- );
54
- } else if (!(typeof permittedRoles === 'boolean')) {
55
- if (permittedRoles['core-aam']) {
56
- permittedRoleList = mergeArray(
57
- permittedRoleList,
58
- roles
59
- .filter(role => !role.isAbstract)
60
- .map(role => ({
61
- name: role.name,
62
- })),
63
- );
64
- }
65
- if (permittedRoles['graphics-aam']) {
66
- permittedRoleList = mergeArray(
67
- permittedRoleList,
68
- graphicsRoles
69
- .filter(role => !role.isAbstract)
70
- .map(role => ({
71
- name: role.name,
72
- })),
73
- );
74
- }
75
- }
76
-
77
- if (implicitRole) {
78
- const implicitRoles =
79
- implicitRole === 'presentation' || implicitRole === 'none' ? ['none', 'presentation'] : [implicitRole];
80
- return mergeArray(
81
- implicitRoles.map(r => ({ name: r })),
82
- permittedRoleList,
83
- );
84
- }
85
-
86
- return permittedRoleList;
87
- }
@@ -1,72 +0,0 @@
1
- import type { ARIAVersion, ARIARoleInSchema, MLMLSpec, ARIARole } from '../types';
2
- import type { NamespaceURI } from '@markuplint/ml-ast';
3
-
4
- import { ariaSpecs } from './aria-specs';
5
-
6
- export function getRoleSpec(
7
- specs: Readonly<MLMLSpec>,
8
- roleName: string,
9
- namespace: NamespaceURI,
10
- version: ARIAVersion,
11
- ): (ARIARole & { superClassRoles: ARIARoleInSchema[] }) | null {
12
- const role = getRoleByName(specs, roleName, namespace, version);
13
- if (!role) {
14
- return null;
15
- }
16
- const superClassRoles = recursiveTraverseSuperClassRoles(specs, roleName, namespace, version);
17
- return {
18
- name: role.name,
19
- isAbstract: !!role.isAbstract,
20
- requiredContextRole: role.requiredContextRole ?? [],
21
- requiredOwnedElements: role.requiredOwnedElements ?? [],
22
- accessibleNameRequired: !!role.accessibleNameRequired,
23
- accessibleNameFromAuthor: !!role.accessibleNameFromAuthor,
24
- accessibleNameFromContent: !!role.accessibleNameFromContent,
25
- accessibleNameProhibited: !!role.accessibleNameProhibited,
26
- childrenPresentational: !!role.childrenPresentational,
27
- ownedProperties: role.ownedProperties ?? [],
28
- prohibitedProperties: role.prohibitedProperties ?? [],
29
- superClassRoles,
30
- };
31
- }
32
-
33
- function recursiveTraverseSuperClassRoles(
34
- specs: Readonly<MLMLSpec>,
35
- roleName: string,
36
- namespace: NamespaceURI,
37
- version: ARIAVersion,
38
- ) {
39
- const roles: ARIARoleInSchema[] = [];
40
- const superClassRoles = getSuperClassRoles(specs, roleName, namespace, version);
41
- if (superClassRoles) {
42
- roles.push(...superClassRoles);
43
- for (const superClassRole of superClassRoles) {
44
- const ancestorRoles = recursiveTraverseSuperClassRoles(specs, superClassRole.name, namespace, version);
45
- roles.push(...ancestorRoles);
46
- }
47
- }
48
- return roles;
49
- }
50
-
51
- function getSuperClassRoles(
52
- specs: Readonly<MLMLSpec>,
53
- roleName: string,
54
- namespace: NamespaceURI,
55
- version: ARIAVersion,
56
- ) {
57
- const role = getRoleByName(specs, roleName, namespace, version);
58
- return (
59
- role?.generalization
60
- ?.map(roleName => getRoleByName(specs, roleName, namespace, version))
61
- .filter((role): role is ARIARoleInSchema => !!role) || null
62
- );
63
- }
64
-
65
- function getRoleByName(specs: Readonly<MLMLSpec>, roleName: string, namespace: NamespaceURI, version: ARIAVersion) {
66
- const { roles, graphicsRoles } = ariaSpecs(specs, version);
67
- let role = roles.find(r => r.name === roleName);
68
- if (!role && namespace === 'http://www.w3.org/2000/svg') {
69
- role = graphicsRoles.find(r => r.name === roleName);
70
- }
71
- return role;
72
- }
@@ -1,10 +0,0 @@
1
- import type { MLMLSpec } from '../types';
2
- import type { Category } from '../types/permitted-structres';
3
-
4
- export function getSelectorsByContentModelCategory(
5
- specs: Readonly<MLMLSpec>,
6
- category: Category,
7
- ): ReadonlyArray<string> {
8
- const selectors = specs.def['#contentModels'][category];
9
- return selectors || [];
10
- }
@@ -1,16 +0,0 @@
1
- import type { ElementSpec, MLMLSpec } from '../types';
2
-
3
- import { resolveNamespace } from '../utils/resolve-namespace';
4
-
5
- const cache = new Map<string, ElementSpec | null>();
6
-
7
- export function getSpecByTagName(specs: Readonly<MLMLSpec>, localName: string, namespace: string | null) {
8
- const { localNameWithNS } = resolveNamespace(localName, namespace || undefined);
9
- let spec = cache.get(localNameWithNS);
10
- if (spec !== undefined) {
11
- return spec;
12
- }
13
- spec = specs.specs.find(spec => spec.name === localNameWithNS) || null;
14
- cache.set(localNameWithNS, spec);
15
- return spec;
16
- }
@@ -1,6 +0,0 @@
1
- export function isPresentational(roleName?: string) {
2
- if (!roleName) {
3
- return false;
4
- }
5
- return ['presentation', 'none'].includes(roleName);
6
- }
@@ -1,20 +0,0 @@
1
- import type { ARIAVersion } from '../types';
2
- import type { ARIA } from '../types/aria';
3
-
4
- export function resolveVersion(aria: ARIA, version: ARIAVersion): Omit<ARIA, ARIAVersion> {
5
- const implicitRole = aria[version]?.implicitRole ?? aria.implicitRole;
6
- const permittedRoles = aria[version]?.permittedRoles ?? aria.permittedRoles;
7
- const implicitProperties = aria[version]?.implicitProperties ?? aria.implicitProperties;
8
- const properties = aria[version]?.properties ?? aria.properties;
9
- const namingProhibited =
10
- version === '1.2' ? aria[version]?.namingProhibited ?? aria.namingProhibited : aria.namingProhibited;
11
- const conditions = aria[version]?.conditions ?? aria.conditions;
12
- return {
13
- implicitRole,
14
- permittedRoles,
15
- implicitProperties,
16
- properties,
17
- namingProhibited,
18
- conditions,
19
- };
20
- }
@@ -1,39 +0,0 @@
1
- import htmlSpec from '@markuplint/html-spec';
2
-
3
- import { schemaToSpec } from './schema-to-spec';
4
-
5
- describe('getSpec', () => {
6
- test('Overriding', () => {
7
- const exAttr = {
8
- ref: 'N/A',
9
- type: 'Boolean',
10
- description: 'For the unit test.',
11
- } as const;
12
- const exAttr2 = {
13
- ref: 'N/A',
14
- type: 'Boolean',
15
- description: 'For the unit test. Override.',
16
- } as const;
17
- const mergedSpec = schemaToSpec([
18
- htmlSpec,
19
- {
20
- specs: [
21
- {
22
- name: 'a',
23
- attributes: { 'extended-attr': exAttr },
24
- },
25
- ],
26
- },
27
- {
28
- specs: [
29
- {
30
- name: 'a',
31
- attributes: { 'extended-attr': exAttr2 },
32
- },
33
- ],
34
- },
35
- ]);
36
- const aElAttrs = mergedSpec.specs.find(el => el.name === 'a')!.attributes;
37
- expect(aElAttrs['extended-attr']).toStrictEqual(exAttr2);
38
- });
39
- });
@@ -1,103 +0,0 @@
1
- import type { ElementSpec, ExtendedSpec, MLMLSpec, Attribute } from '../types';
2
-
3
- import { mergeArray } from '../utils/merge-array';
4
-
5
- /**
6
- * Merging HTML-spec schema and extended spec schemas
7
- *
8
- * Ex: `@markuplint/html-spec` + `{ specs: ["@markuplint/vue-spec"] }` in cofigure files.
9
- *
10
- * @param schemas `MLDocument.schemas`
11
- */
12
- export function schemaToSpec(schemas: readonly [MLMLSpec, ...ExtendedSpec[]]) {
13
- const [main, ...extendedSpecs] = schemas;
14
- const result = { ...main };
15
- for (const extendedSpec of extendedSpecs) {
16
- if (extendedSpec.cites) {
17
- result.cites = [...result.cites, ...extendedSpec.cites];
18
- }
19
- if (extendedSpec.def) {
20
- if (extendedSpec.def['#globalAttrs']?.['#extends']) {
21
- result.def['#globalAttrs']['#HTMLGlobalAttrs'] = {
22
- ...(result.def['#globalAttrs']?.['#HTMLGlobalAttrs'] || {}),
23
- ...(extendedSpec.def['#globalAttrs']?.['#extends'] || {}),
24
- };
25
- }
26
- if (extendedSpec.def['#aria']) {
27
- result.def['#aria'] = {
28
- '1.1': {
29
- roles: mergeArray(result.def['#aria']['1.1'].roles, extendedSpec.def['#aria']['1.1'].roles),
30
- props: mergeArray(result.def['#aria']['1.1'].props, extendedSpec.def['#aria']['1.1'].props),
31
- graphicsRoles: mergeArray(
32
- result.def['#aria']['1.1'].graphicsRoles,
33
- extendedSpec.def['#aria']['1.1'].graphicsRoles,
34
- ),
35
- },
36
- '1.2': {
37
- roles: mergeArray(result.def['#aria']['1.2'].roles, extendedSpec.def['#aria']['1.2'].roles),
38
- props: mergeArray(result.def['#aria']['1.2'].props, extendedSpec.def['#aria']['1.2'].props),
39
- graphicsRoles: mergeArray(
40
- result.def['#aria']['1.2'].graphicsRoles,
41
- extendedSpec.def['#aria']['1.2'].graphicsRoles,
42
- ),
43
- },
44
- };
45
- }
46
- if (extendedSpec.def['#contentModels']) {
47
- const keys = new Set([
48
- ...Object.keys(result.def['#contentModels']),
49
- ...Object.keys(extendedSpec.def['#contentModels']),
50
- ]) as Set<keyof typeof result.def['#contentModels']>;
51
- for (const modelName of keys) {
52
- const mainModel = result.def['#contentModels'][modelName];
53
- const exModel = extendedSpec.def['#contentModels'][modelName];
54
- result.def['#contentModels'][modelName] = [...(mainModel || []), ...(exModel || [])];
55
- }
56
- }
57
- }
58
- if (extendedSpec.specs) {
59
- const exSpecs = extendedSpec.specs.slice();
60
- const specs: ElementSpec[] = [];
61
- for (const elSpec of result.specs) {
62
- const tagName = elSpec.name.toLowerCase();
63
- const index = exSpecs.findIndex(spec => spec.name.toLowerCase() === tagName);
64
- if (index === -1) {
65
- specs.push(elSpec);
66
- continue;
67
- }
68
- const exSpec = exSpecs.splice(index, 1)[0];
69
- specs.push({
70
- ...elSpec,
71
- ...exSpec,
72
- globalAttrs: {
73
- ...elSpec.globalAttrs,
74
- ...exSpec.globalAttrs,
75
- },
76
- attributes: mergeAttrSpec(elSpec.attributes, exSpec.attributes),
77
- categories: mergeArray(elSpec.categories, exSpec.categories),
78
- });
79
- }
80
-
81
- result.specs = specs;
82
- }
83
- }
84
-
85
- return result;
86
- }
87
-
88
- function mergeAttrSpec(
89
- std: Record<string, Attribute>,
90
- ex: Record<string, Partial<Attribute>> = {},
91
- ): Record<string, Attribute> {
92
- const result: Record<string, Attribute> = {};
93
- const keys = Array.from(new Set([...Object.keys(std), ...Object.keys(ex)]));
94
- for (const key of keys) {
95
- const _std = std[key];
96
- const _ex = ex[key];
97
- result[key] = {
98
- ..._std,
99
- ..._ex,
100
- };
101
- }
102
- return result;
103
- }