@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.
- package/README.md +8 -3
- package/lib/constant/aria-version.d.ts +2 -0
- package/lib/constant/aria-version.js +5 -0
- package/lib/dom-traverse/accname-computation.js +3 -1
- package/lib/dom-traverse/get-attr-specs.d.ts +1 -1
- package/lib/dom-traverse/get-attr-specs.js +3 -1
- package/lib/dom-traverse/get-computed-aria-props.d.ts +12 -0
- package/lib/dom-traverse/get-computed-aria-props.js +108 -0
- package/lib/dom-traverse/get-computed-role.d.ts +6 -1
- package/lib/dom-traverse/get-computed-role.js +54 -35
- package/lib/dom-traverse/get-content-model.d.ts +29 -0
- package/lib/dom-traverse/get-content-model.js +30 -0
- package/lib/dom-traverse/get-explicit-role.js +9 -4
- package/lib/dom-traverse/get-implicit-role.d.ts +6 -2
- package/lib/dom-traverse/get-implicit-role.js +6 -2
- package/lib/dom-traverse/get-non-presentational-ancestor.d.ts +10 -4
- package/lib/dom-traverse/get-non-presentational-ancestor.js +10 -2
- package/lib/dom-traverse/get-permitted-roles.d.ts +7 -3
- package/lib/dom-traverse/get-permitted-roles.js +3 -1
- package/lib/dom-traverse/get-spec.d.ts +5 -2
- package/lib/dom-traverse/get-spec.js +4 -2
- package/lib/dom-traverse/has-required-owned-elements.d.ts +8 -2
- package/lib/dom-traverse/has-required-owned-elements.js +26 -8
- package/lib/dom-traverse/is-exposed.d.ts +11 -0
- package/lib/dom-traverse/is-exposed.js +217 -0
- package/lib/dom-traverse/matches-context-role.d.ts +7 -0
- package/lib/dom-traverse/matches-context-role.js +27 -0
- package/lib/dom-traverse/may-be-focusable.d.ts +2 -0
- package/lib/dom-traverse/may-be-focusable.js +24 -0
- package/lib/index.d.ts +11 -1
- package/lib/index.js +11 -1
- package/lib/specs/aria-specs.d.ts +7 -4
- package/lib/specs/content-model-category-to-tag-names.d.ts +5 -2
- package/lib/specs/content-model-category-to-tag-names.js +2 -2
- package/lib/specs/get-aria.d.ts +8 -1
- package/lib/specs/get-aria.js +11 -5
- package/lib/specs/get-attr-specs.d.ts +7 -3
- package/lib/specs/get-attr-specs.js +2 -14
- package/lib/specs/get-implicit-role.d.ts +7 -1
- package/lib/specs/get-permitted-roles.d.ts +9 -3
- package/lib/specs/get-permitted-roles.js +19 -15
- package/lib/specs/get-role-spec.d.ts +10 -3
- package/lib/specs/get-role-spec.js +2 -2
- package/lib/specs/get-selectors-by-content-model-category.d.ts +2 -2
- package/lib/specs/get-selectors-by-content-model-category.js +1 -1
- package/lib/specs/get-spec-by-tag-name.d.ts +6 -2
- package/lib/specs/get-spec-by-tag-name.js +3 -2
- package/lib/specs/is-nothing-content-model.d.ts +5 -0
- package/lib/specs/is-nothing-content-model.js +14 -0
- package/lib/specs/is-palpable-elements.d.ts +9 -0
- package/lib/specs/is-palpable-elements.js +49 -0
- package/lib/specs/is-void-element.d.ts +1 -0
- package/lib/specs/is-void-element.js +27 -0
- package/lib/specs/resolve-version.d.ts +5 -1
- package/lib/specs/resolve-version.js +1 -1
- package/lib/specs/schema-to-spec.d.ts +4 -4
- package/lib/specs/schema-to-spec.js +29 -18
- package/lib/types/aria.d.ts +150 -109
- package/lib/types/attributes.d.ts +1507 -73
- package/lib/types/index.d.ts +195 -166
- package/{src/types/permitted-structres.ts → lib/types/permitted-structures.d.ts} +24 -35
- package/lib/utils/get-ns.d.ts +2 -1
- package/lib/utils/get-ns.js +3 -0
- package/lib/utils/merge-array.d.ts +9 -4
- package/lib/utils/resolve-namespace.d.ts +7 -7
- package/lib/utils/resolve-namespace.js +19 -13
- package/lib/utils/validateAriaVersion.d.ts +2 -0
- package/lib/utils/validateAriaVersion.js +8 -0
- package/package.json +13 -8
- package/schema.json +6 -6
- package/{src/dom-traverse/accname-computation.spec.ts → test/dom-traverse/accname-computation.spec.js} +8 -8
- package/test/dom-traverse/get-computed-aria-props.spec.js +758 -0
- package/test/dom-traverse/get-computed-role.spec.js +294 -0
- package/test/dom-traverse/get-implicit-role.spec.js +40 -0
- package/{src/dom-traverse/has-required-owned-elements.spec.ts → test/dom-traverse/has-required-owned-elements.spec.js} +7 -9
- package/test/dom-traverse/is-exposed.spec.js +70 -0
- package/test/dom-traverse/matches-context-role.spec.js +60 -0
- package/{src/specs/get-attr-specs.spec.ts → test/specs/get-attr-specs.spec.js} +2 -8
- package/{src/specs/get-implicit-role.spec.ts → test/specs/get-implicit-role.spec.js} +9 -11
- package/{src/specs/get-permitted-roles.spec.ts → test/specs/get-permitted-roles.spec.js} +8 -10
- package/{src/specs/get-role-spec.spec.ts → test/specs/get-role-spec.spec.js} +4 -4
- package/{src/specs/get-spec-by-tag-name.spec.ts → test/specs/get-spec-by-tag-name.spec.js} +11 -11
- package/test/specs/resolve-version.spec.js +34 -0
- package/test/specs/schema-to-spec.spec.js +61 -0
- package/test/utils/resolve-namespace.spec.js +37 -0
- package/lib/dom-traverse/focusability-computation.d.ts +0 -1
- package/lib/dom-traverse/focusability-computation.js +0 -8
- package/lib/dom-traverse/get-aria.d.ts +0 -9
- package/lib/dom-traverse/get-aria.js +0 -54
- package/lib/specs/aria-spec.d.ts +0 -5
- package/lib/specs/aria-spec.js +0 -12
- package/lib/specs/get-spec.d.ts +0 -13
- package/lib/specs/get-spec.js +0 -85
- package/lib/specs/html-spec.d.ts +0 -6
- package/lib/specs/html-spec.js +0 -16
- package/lib/specs/resolve-namespace.d.ts +0 -9
- package/lib/specs/resolve-namespace.js +0 -26
- package/lib/types/permitted-structres.d.ts +0 -64
- package/lib/utils.d.ts +0 -8
- package/lib/utils.js +0 -50
- package/schemas/aria.schema.json +0 -258
- package/schemas/attributes.schema.json +0 -204
- package/schemas/content-models.schema.json +0 -215
- package/schemas/element.schema.json +0 -11
- package/schemas/global-attributes.schema.json +0 -761
- package/src/dom-traverse/accname-computation.ts +0 -5
- package/src/dom-traverse/get-attr-specs.ts +0 -8
- package/src/dom-traverse/get-computed-role.spec.ts +0 -134
- package/src/dom-traverse/get-computed-role.ts +0 -193
- package/src/dom-traverse/get-explicit-role.ts +0 -112
- package/src/dom-traverse/get-implicit-role.ts +0 -36
- package/src/dom-traverse/get-non-presentational-ancestor.ts +0 -20
- package/src/dom-traverse/get-permitted-roles.ts +0 -7
- package/src/dom-traverse/get-spec.ts +0 -7
- package/src/dom-traverse/has-required-owned-elements.ts +0 -72
- package/src/index.ts +0 -17
- package/src/specs/aria-specs.ts +0 -6
- package/src/specs/content-model-category-to-tag-names.ts +0 -15
- package/src/specs/get-aria.ts +0 -85
- package/src/specs/get-attr-specs.ts +0 -116
- package/src/specs/get-implicit-role.ts +0 -17
- package/src/specs/get-permitted-roles.ts +0 -87
- package/src/specs/get-role-spec.ts +0 -72
- package/src/specs/get-selectors-by-content-model-category.ts +0 -10
- package/src/specs/get-spec-by-tag-name.ts +0 -16
- package/src/specs/is-presentational.ts +0 -6
- package/src/specs/resolve-version.ts +0 -20
- package/src/specs/schema-to-spec.spec.ts +0 -39
- package/src/specs/schema-to-spec.ts +0 -103
- package/src/types/aria.ts +0 -147
- package/src/types/attributes.ts +0 -1418
- package/src/types/index.ts +0 -255
- package/src/utils/get-ns.ts +0 -13
- package/src/utils/merge-array.ts +0 -35
- package/src/utils/resolve-namespace.ts +0 -36
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
- /package/lib/types/{permitted-structres.js → permitted-structures.js} +0 -0
package/src/specs/get-aria.ts
DELETED
|
@@ -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,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
|
-
}
|