@markuplint/ml-spec 2.0.1 → 3.0.0-alpha.82
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/lib/dom-traverse/accname-computation.d.ts +1 -0
- package/lib/dom-traverse/accname-computation.js +8 -0
- package/lib/dom-traverse/focusability-computation.d.ts +1 -0
- package/lib/dom-traverse/focusability-computation.js +8 -0
- package/lib/dom-traverse/get-aria.d.ts +9 -0
- package/lib/dom-traverse/get-aria.js +54 -0
- package/lib/dom-traverse/get-attr-specs.d.ts +2 -0
- package/lib/dom-traverse/get-attr-specs.js +8 -0
- package/lib/dom-traverse/get-computed-role.d.ts +2 -0
- package/lib/dom-traverse/get-computed-role.js +182 -0
- package/lib/dom-traverse/get-explicit-role.d.ts +2 -0
- package/lib/dom-traverse/get-explicit-role.js +102 -0
- package/lib/dom-traverse/get-implicit-role.d.ts +3 -0
- package/lib/dom-traverse/get-implicit-role.js +37 -0
- package/lib/dom-traverse/get-non-presentational-ancestor.d.ts +5 -0
- package/lib/dom-traverse/get-non-presentational-ancestor.js +21 -0
- package/lib/dom-traverse/get-permitted-roles.d.ts +5 -0
- package/lib/dom-traverse/get-permitted-roles.js +8 -0
- package/lib/dom-traverse/get-spec.d.ts +2 -0
- package/lib/dom-traverse/get-spec.js +8 -0
- package/lib/dom-traverse/has-required-owned-elements.d.ts +3 -0
- package/lib/dom-traverse/has-required-owned-elements.js +69 -0
- package/lib/index.d.ts +16 -6
- package/lib/index.js +17 -7
- package/lib/specs/aria-spec.d.ts +5 -0
- package/lib/specs/aria-spec.js +12 -0
- package/lib/specs/aria-specs.d.ts +6 -0
- package/lib/specs/aria-specs.js +8 -0
- package/lib/specs/content-model-category-to-tag-names.d.ts +3 -0
- package/lib/specs/content-model-category-to-tag-names.js +15 -0
- package/lib/specs/get-aria.d.ts +3 -0
- package/lib/specs/get-aria.js +71 -0
- package/lib/specs/get-attr-specs.d.ts +8 -0
- package/lib/{get-attr-specs.js → specs/get-attr-specs.js} +8 -6
- package/lib/specs/get-implicit-role.d.ts +2 -0
- package/lib/specs/get-implicit-role.js +12 -0
- package/lib/specs/get-permitted-roles.d.ts +12 -0
- package/lib/specs/get-permitted-roles.js +61 -0
- package/lib/specs/get-role-spec.d.ts +5 -0
- package/lib/specs/get-role-spec.js +52 -0
- package/lib/specs/get-selectors-by-content-model-category.d.ts +3 -0
- package/lib/specs/get-selectors-by-content-model-category.js +8 -0
- package/lib/specs/get-spec-by-tag-name.d.ts +2 -0
- package/lib/specs/get-spec-by-tag-name.js +16 -0
- package/lib/{get-spec.d.ts → specs/get-spec.d.ts} +4 -4
- package/lib/{get-spec.js → specs/get-spec.js} +1 -1
- package/lib/specs/html-spec.d.ts +6 -0
- package/lib/specs/html-spec.js +16 -0
- package/lib/specs/is-presentational.d.ts +1 -0
- package/lib/specs/is-presentational.js +10 -0
- package/lib/specs/resolve-namespace.d.ts +9 -0
- package/lib/specs/resolve-namespace.js +26 -0
- package/lib/specs/resolve-version.d.ts +3 -0
- package/lib/specs/resolve-version.js +21 -0
- package/lib/specs/schema-to-spec.d.ts +13 -0
- package/lib/specs/schema-to-spec.js +93 -0
- package/lib/types/aria.d.ts +130 -0
- package/lib/{attributes.js → types/aria.js} +0 -0
- package/lib/{attributes.d.ts → types/attributes.d.ts} +5 -12
- package/lib/{permitted-structres.js → types/attributes.js} +0 -0
- package/lib/{types.d.ts → types/index.d.ts} +50 -65
- package/lib/{types.js → types/index.js} +0 -0
- package/lib/{permitted-structres.d.ts → types/permitted-structres.d.ts} +14 -23
- package/lib/types/permitted-structres.js +8 -0
- package/lib/utils/get-ns.d.ts +1 -0
- package/lib/{get-ns.js → utils/get-ns.js} +0 -0
- package/lib/utils/merge-array.d.ts +5 -0
- package/lib/utils/merge-array.js +36 -0
- package/lib/utils/resolve-namespace.d.ts +9 -0
- package/lib/utils/resolve-namespace.js +26 -0
- package/lib/utils.d.ts +6 -3
- package/lib/utils.js +15 -1
- package/package.json +10 -6
- package/schemas/aria.schema.json +258 -0
- package/schemas/attributes.schema.json +5 -23
- package/schemas/{permitted-structures.schema.json → content-models.schema.json} +52 -81
- package/schemas/element.schema.json +11 -0
- package/schemas/global-attributes.schema.json +6 -2
- package/src/dom-traverse/accname-computation.spec.ts +69 -0
- package/src/dom-traverse/accname-computation.ts +5 -0
- package/src/dom-traverse/get-attr-specs.ts +8 -0
- package/src/dom-traverse/get-computed-role.spec.ts +134 -0
- package/src/dom-traverse/get-computed-role.ts +193 -0
- package/src/dom-traverse/get-explicit-role.ts +112 -0
- package/src/dom-traverse/get-implicit-role.ts +36 -0
- package/src/dom-traverse/get-non-presentational-ancestor.ts +20 -0
- package/src/dom-traverse/get-permitted-roles.ts +7 -0
- package/src/dom-traverse/get-spec.ts +7 -0
- package/src/dom-traverse/has-required-owned-elements.spec.ts +36 -0
- package/src/dom-traverse/has-required-owned-elements.ts +72 -0
- package/src/index.ts +16 -6
- package/src/specs/aria-specs.ts +6 -0
- package/src/specs/content-model-category-to-tag-names.ts +15 -0
- package/src/specs/get-aria.ts +85 -0
- package/src/{get-attr-specs.spec.ts → specs/get-attr-specs.spec.ts} +9 -6
- package/src/{get-attr-specs.ts → specs/get-attr-specs.ts} +12 -7
- package/src/specs/get-implicit-role.spec.ts +81 -0
- package/src/specs/get-implicit-role.ts +17 -0
- package/src/specs/get-permitted-roles.spec.ts +420 -0
- package/src/specs/get-permitted-roles.ts +87 -0
- package/src/specs/get-role-spec.spec.ts +67 -0
- package/src/specs/get-role-spec.ts +72 -0
- package/src/specs/get-selectors-by-content-model-category.ts +10 -0
- package/src/specs/get-spec-by-tag-name.spec.ts +68 -0
- package/src/specs/get-spec-by-tag-name.ts +16 -0
- package/src/specs/is-presentational.ts +6 -0
- package/src/specs/resolve-version.ts +20 -0
- package/src/{get-spec.spec.ts → specs/schema-to-spec.spec.ts} +2 -2
- package/src/{get-spec.ts → specs/schema-to-spec.ts} +22 -8
- package/src/types/aria.ts +147 -0
- package/src/{attributes.ts → types/attributes.ts} +5 -12
- package/src/{types.ts → types/index.ts} +70 -69
- package/src/{permitted-structres.ts → types/permitted-structres.ts} +15 -25
- package/src/{get-ns.ts → utils/get-ns.ts} +1 -1
- package/src/{utils.ts → utils/merge-array.ts} +0 -0
- package/src/utils/resolve-namespace.ts +36 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/lib/get-attr-specs.d.ts +0 -7
- package/lib/get-ns.d.ts +0 -1
- package/lib/get-spec-by-tag-name.d.ts +0 -2
- package/lib/get-spec-by-tag-name.js +0 -31
- package/schemas/wai-aria.schema.json +0 -87
- package/src/get-spec-by-tag-name.ts +0 -32
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import specs from '@markuplint/html-spec';
|
|
2
|
+
|
|
3
|
+
import { getRoleSpec } from './get-role-spec';
|
|
4
|
+
|
|
5
|
+
describe('getRoleSpec', () => {
|
|
6
|
+
test('the button role', () => {
|
|
7
|
+
const role = getRoleSpec(specs, 'button', 'http://www.w3.org/1999/xhtml', '1.2')!;
|
|
8
|
+
const superClassRoles = role.superClassRoles.map(r => r.name);
|
|
9
|
+
expect(role.ownedProperties.map(p => p.name + (p.deprecated ? ':deprecated' : ''))).toStrictEqual([
|
|
10
|
+
'aria-atomic',
|
|
11
|
+
'aria-busy',
|
|
12
|
+
'aria-controls',
|
|
13
|
+
'aria-current',
|
|
14
|
+
'aria-describedby',
|
|
15
|
+
'aria-details',
|
|
16
|
+
'aria-disabled',
|
|
17
|
+
'aria-dropeffect',
|
|
18
|
+
'aria-errormessage:deprecated',
|
|
19
|
+
'aria-expanded',
|
|
20
|
+
'aria-flowto',
|
|
21
|
+
'aria-grabbed',
|
|
22
|
+
'aria-haspopup',
|
|
23
|
+
'aria-hidden',
|
|
24
|
+
'aria-invalid:deprecated',
|
|
25
|
+
'aria-keyshortcuts',
|
|
26
|
+
'aria-label',
|
|
27
|
+
'aria-labelledby',
|
|
28
|
+
'aria-live',
|
|
29
|
+
'aria-owns',
|
|
30
|
+
'aria-pressed',
|
|
31
|
+
'aria-relevant',
|
|
32
|
+
'aria-roledescription',
|
|
33
|
+
]);
|
|
34
|
+
expect(role.isAbstract).toBe(false);
|
|
35
|
+
expect(superClassRoles).toStrictEqual(['command', 'widget', 'roletype']);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('the roletype role', () => {
|
|
39
|
+
const role = getRoleSpec(specs, 'roletype', 'http://www.w3.org/1999/xhtml', '1.2')!;
|
|
40
|
+
const superClassRoles = role.superClassRoles.map(r => r.name);
|
|
41
|
+
expect(role.ownedProperties.map(p => p.name + (p.deprecated ? ':deprecated' : ''))).toStrictEqual([
|
|
42
|
+
'aria-atomic',
|
|
43
|
+
'aria-busy',
|
|
44
|
+
'aria-controls',
|
|
45
|
+
'aria-current',
|
|
46
|
+
'aria-describedby',
|
|
47
|
+
'aria-details',
|
|
48
|
+
'aria-disabled:deprecated',
|
|
49
|
+
'aria-dropeffect',
|
|
50
|
+
'aria-errormessage:deprecated',
|
|
51
|
+
'aria-flowto',
|
|
52
|
+
'aria-grabbed',
|
|
53
|
+
'aria-haspopup:deprecated',
|
|
54
|
+
'aria-hidden',
|
|
55
|
+
'aria-invalid:deprecated',
|
|
56
|
+
'aria-keyshortcuts',
|
|
57
|
+
'aria-label',
|
|
58
|
+
'aria-labelledby',
|
|
59
|
+
'aria-live',
|
|
60
|
+
'aria-owns',
|
|
61
|
+
'aria-relevant',
|
|
62
|
+
'aria-roledescription',
|
|
63
|
+
]);
|
|
64
|
+
expect(role.isAbstract).toBe(true);
|
|
65
|
+
expect(superClassRoles).toStrictEqual([]);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import specs from '@markuplint/html-spec';
|
|
2
|
+
|
|
3
|
+
import { getSpecByTagName } from './get-spec-by-tag-name';
|
|
4
|
+
|
|
5
|
+
const divSpec = {
|
|
6
|
+
conditional: [
|
|
7
|
+
{
|
|
8
|
+
condition: 'dl > div',
|
|
9
|
+
contents: [
|
|
10
|
+
{
|
|
11
|
+
zeroOrMore: '#script-supporting',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
oneOrMore: 'dt',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
zeroOrMore: '#script-supporting',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
oneOrMore: 'dd',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
zeroOrMore: '#script-supporting',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
contents: [
|
|
29
|
+
{
|
|
30
|
+
zeroOrMore: '#flow',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
test('html:div', () => {
|
|
36
|
+
expect(getSpecByTagName(specs, 'div', null)?.contentModel).toStrictEqual(divSpec);
|
|
37
|
+
expect(getSpecByTagName(specs, 'div', 'unknown-namespace')?.contentModel).toStrictEqual(divSpec);
|
|
38
|
+
expect(getSpecByTagName(specs, 'div', 'http://www.w3.org/1999/xhtml')?.contentModel).toStrictEqual(divSpec);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('svg:svg', () => {
|
|
42
|
+
expect(getSpecByTagName(specs, 'svg', 'http://www.w3.org/2000/svg')?.contentModel).toStrictEqual({
|
|
43
|
+
contents: [
|
|
44
|
+
{
|
|
45
|
+
zeroOrMore: [
|
|
46
|
+
'#SVGAnimation',
|
|
47
|
+
'#SVGDescriptive',
|
|
48
|
+
'#SVGPaintServer',
|
|
49
|
+
'#SVGShape',
|
|
50
|
+
'#SVGStructural',
|
|
51
|
+
'svg|a',
|
|
52
|
+
'svg|clipPath',
|
|
53
|
+
'svg|filter',
|
|
54
|
+
'svg|foreignObject',
|
|
55
|
+
'svg|image',
|
|
56
|
+
'svg|marker',
|
|
57
|
+
'svg|mask',
|
|
58
|
+
'svg|script',
|
|
59
|
+
'svg|style',
|
|
60
|
+
'svg|switch',
|
|
61
|
+
'svg|text',
|
|
62
|
+
'svg|view',
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
expect(getSpecByTagName(specs, 'svg', null)).toBe(null);
|
|
68
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import htmlSpec from '@markuplint/html-spec';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { schemaToSpec } from './schema-to-spec';
|
|
4
4
|
|
|
5
5
|
describe('getSpec', () => {
|
|
6
6
|
test('Overriding', () => {
|
|
@@ -14,7 +14,7 @@ describe('getSpec', () => {
|
|
|
14
14
|
type: 'Boolean',
|
|
15
15
|
description: 'For the unit test. Override.',
|
|
16
16
|
} as const;
|
|
17
|
-
const mergedSpec =
|
|
17
|
+
const mergedSpec = schemaToSpec([
|
|
18
18
|
htmlSpec,
|
|
19
19
|
{
|
|
20
20
|
specs: [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ElementSpec, ExtendedSpec, MLMLSpec, Attribute } from '
|
|
1
|
+
import type { ElementSpec, ExtendedSpec, MLMLSpec, Attribute } from '../types';
|
|
2
2
|
|
|
3
|
-
import { mergeArray } from '
|
|
3
|
+
import { mergeArray } from '../utils/merge-array';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Merging HTML-spec schema and extended spec schemas
|
|
@@ -9,7 +9,7 @@ import { mergeArray } from './utils';
|
|
|
9
9
|
*
|
|
10
10
|
* @param schemas `MLDocument.schemas`
|
|
11
11
|
*/
|
|
12
|
-
export function
|
|
12
|
+
export function schemaToSpec(schemas: readonly [MLMLSpec, ...ExtendedSpec[]]) {
|
|
13
13
|
const [main, ...extendedSpecs] = schemas;
|
|
14
14
|
const result = { ...main };
|
|
15
15
|
for (const extendedSpec of extendedSpecs) {
|
|
@@ -17,17 +17,31 @@ export function getSpec(schemas: readonly [MLMLSpec, ...ExtendedSpec[]]) {
|
|
|
17
17
|
result.cites = [...result.cites, ...extendedSpec.cites];
|
|
18
18
|
}
|
|
19
19
|
if (extendedSpec.def) {
|
|
20
|
-
if (extendedSpec.def['#ariaAttrs']) {
|
|
21
|
-
result.def['#ariaAttrs'] = [...result.def['#ariaAttrs'], ...extendedSpec.def['#ariaAttrs']];
|
|
22
|
-
}
|
|
23
20
|
if (extendedSpec.def['#globalAttrs']?.['#extends']) {
|
|
24
21
|
result.def['#globalAttrs']['#HTMLGlobalAttrs'] = {
|
|
25
22
|
...(result.def['#globalAttrs']?.['#HTMLGlobalAttrs'] || {}),
|
|
26
23
|
...(extendedSpec.def['#globalAttrs']?.['#extends'] || {}),
|
|
27
24
|
};
|
|
28
25
|
}
|
|
29
|
-
if (extendedSpec.def['#
|
|
30
|
-
result.def['#
|
|
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
|
+
};
|
|
31
45
|
}
|
|
32
46
|
if (extendedSpec.def['#contentModels']) {
|
|
33
47
|
const keys = new Set([
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* If `false`, this mean is "No corresponding role".
|
|
10
|
+
*/
|
|
11
|
+
export type ImplicitRole = false | string;
|
|
12
|
+
/**
|
|
13
|
+
* If `true`, this mean is "Any". If `false`, this mean is "No".
|
|
14
|
+
*/
|
|
15
|
+
export type PermittedRoles =
|
|
16
|
+
| boolean
|
|
17
|
+
| (
|
|
18
|
+
| string
|
|
19
|
+
| {
|
|
20
|
+
name: string;
|
|
21
|
+
deprecated?: true;
|
|
22
|
+
[k: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
)[]
|
|
25
|
+
| {
|
|
26
|
+
'core-aam'?: true;
|
|
27
|
+
'graphics-aam'?: true;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* If set false:
|
|
31
|
+
* > No role or aria-* attributes
|
|
32
|
+
*/
|
|
33
|
+
export type PermittedARIAProperties =
|
|
34
|
+
| false
|
|
35
|
+
| {
|
|
36
|
+
global?: true;
|
|
37
|
+
/**
|
|
38
|
+
* Set true if the spec says "and any aria-* attributes applicable to the allowed roles."
|
|
39
|
+
*/
|
|
40
|
+
role?: true | string | [string, ...string[]];
|
|
41
|
+
only?: [
|
|
42
|
+
(
|
|
43
|
+
| string
|
|
44
|
+
| {
|
|
45
|
+
name: string;
|
|
46
|
+
value?: string;
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
...(
|
|
50
|
+
| string
|
|
51
|
+
| {
|
|
52
|
+
name: string;
|
|
53
|
+
value?: string;
|
|
54
|
+
}
|
|
55
|
+
)[],
|
|
56
|
+
];
|
|
57
|
+
whithout?: [
|
|
58
|
+
{
|
|
59
|
+
type: 'not-recommended' | 'should-not' | 'must-not';
|
|
60
|
+
name: string;
|
|
61
|
+
value?: string;
|
|
62
|
+
alt?: {
|
|
63
|
+
method: 'remove-attr' | 'set-attr';
|
|
64
|
+
target: string;
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
...{
|
|
68
|
+
type: 'not-recommended' | 'should-not' | 'must-not';
|
|
69
|
+
name: string;
|
|
70
|
+
value?: string;
|
|
71
|
+
alt?: {
|
|
72
|
+
method: 'remove-attr' | 'set-attr';
|
|
73
|
+
target: string;
|
|
74
|
+
};
|
|
75
|
+
}[],
|
|
76
|
+
];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export interface AriaSchema {
|
|
80
|
+
_?: ARIA;
|
|
81
|
+
[k: string]: unknown;
|
|
82
|
+
}
|
|
83
|
+
export interface ARIA {
|
|
84
|
+
implicitRole: ImplicitRole;
|
|
85
|
+
permittedRoles: PermittedRoles;
|
|
86
|
+
namingProhibited?: true;
|
|
87
|
+
implicitProperties?: ImplicitProperties;
|
|
88
|
+
properties?: PermittedARIAProperties;
|
|
89
|
+
conditions?: {
|
|
90
|
+
/**
|
|
91
|
+
* This interface was referenced by `undefined`'s JSON-Schema definition
|
|
92
|
+
* via the `patternProperty` ".+".
|
|
93
|
+
*/
|
|
94
|
+
[k: string]: {
|
|
95
|
+
implicitRole?: ImplicitRole;
|
|
96
|
+
permittedRoles?: PermittedRoles;
|
|
97
|
+
namingProhibited?: true;
|
|
98
|
+
implicitProperties?: ImplicitProperties;
|
|
99
|
+
properties?: PermittedARIAProperties;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
'1.2'?: {
|
|
103
|
+
implicitRole?: ImplicitRole;
|
|
104
|
+
permittedRoles?: PermittedRoles;
|
|
105
|
+
namingProhibited?: true;
|
|
106
|
+
implicitProperties?: ImplicitProperties;
|
|
107
|
+
properties?: PermittedARIAProperties;
|
|
108
|
+
conditions?: {
|
|
109
|
+
/**
|
|
110
|
+
* This interface was referenced by `undefined`'s JSON-Schema definition
|
|
111
|
+
* via the `patternProperty` ".+".
|
|
112
|
+
*/
|
|
113
|
+
[k: string]: {
|
|
114
|
+
implicitRole?: ImplicitRole;
|
|
115
|
+
permittedRoles?: PermittedRoles;
|
|
116
|
+
namingProhibited?: true;
|
|
117
|
+
implicitProperties?: ImplicitProperties;
|
|
118
|
+
properties?: PermittedARIAProperties;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
'1.1'?: {
|
|
123
|
+
implicitRole?: ImplicitRole;
|
|
124
|
+
permittedRoles?: PermittedRoles;
|
|
125
|
+
implicitProperties?: ImplicitProperties;
|
|
126
|
+
properties?: PermittedARIAProperties;
|
|
127
|
+
conditions?: {
|
|
128
|
+
/**
|
|
129
|
+
* This interface was referenced by `undefined`'s JSON-Schema definition
|
|
130
|
+
* via the `patternProperty` ".+".
|
|
131
|
+
*/
|
|
132
|
+
[k: string]: {
|
|
133
|
+
implicitRole?: ImplicitRole;
|
|
134
|
+
permittedRoles?: PermittedRoles;
|
|
135
|
+
implicitProperties?: ImplicitProperties;
|
|
136
|
+
properties?: PermittedARIAProperties;
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export interface ImplicitProperties {
|
|
142
|
+
/**
|
|
143
|
+
* This interface was referenced by `ImplicitProperties`'s JSON-Schema definition
|
|
144
|
+
* via the `patternProperty` "^aria-.+".
|
|
145
|
+
*/
|
|
146
|
+
[k: string]: string;
|
|
147
|
+
}
|
|
@@ -1118,18 +1118,10 @@ export type AttributeType =
|
|
|
1118
1118
|
lte?: number;
|
|
1119
1119
|
clampable?: boolean;
|
|
1120
1120
|
};
|
|
1121
|
-
export type AttributeCondition =
|
|
1122
|
-
| {
|
|
1123
|
-
ancestor: Selectors;
|
|
1124
|
-
}
|
|
1125
|
-
| {
|
|
1126
|
-
self: Selectors;
|
|
1127
|
-
};
|
|
1128
|
-
export type Selectors = string | [string, string, ...string[]];
|
|
1121
|
+
export type AttributeCondition = string | [string, string, ...string[]];
|
|
1129
1122
|
|
|
1130
1123
|
export interface AttributesSchema {
|
|
1131
1124
|
tag: string;
|
|
1132
|
-
ref: string;
|
|
1133
1125
|
global?: GlobalAttributes;
|
|
1134
1126
|
attributes: Attributes;
|
|
1135
1127
|
}
|
|
@@ -1141,6 +1133,7 @@ export interface GlobalAttributes {
|
|
|
1141
1133
|
| 'onabort'
|
|
1142
1134
|
| 'onauxclick'
|
|
1143
1135
|
| 'onbeforeinput'
|
|
1136
|
+
| 'onbeforematch'
|
|
1144
1137
|
| 'onblur'
|
|
1145
1138
|
| 'oncancel'
|
|
1146
1139
|
| 'oncanplay'
|
|
@@ -1228,6 +1221,7 @@ export interface GlobalAttributes {
|
|
|
1228
1221
|
| 'rel'
|
|
1229
1222
|
| 'target'
|
|
1230
1223
|
| 'type'
|
|
1224
|
+
| 'fetchpriority'
|
|
1231
1225
|
)[];
|
|
1232
1226
|
'#HTMLEmbededAndMediaContentAttrs'?: (
|
|
1233
1227
|
| 'autoplay'
|
|
@@ -1411,8 +1405,6 @@ export interface Attributes {
|
|
|
1411
1405
|
* via the `patternProperty` ".*".
|
|
1412
1406
|
*/
|
|
1413
1407
|
export interface AttributeJSON {
|
|
1414
|
-
_TODO_?: string;
|
|
1415
|
-
ref: string;
|
|
1416
1408
|
type?: AttributeType | [AttributeType, ...AttributeType[]];
|
|
1417
1409
|
defaultValue?: string;
|
|
1418
1410
|
deprecated?: boolean;
|
|
@@ -1420,6 +1412,7 @@ export interface AttributeJSON {
|
|
|
1420
1412
|
requiredEither?: string[];
|
|
1421
1413
|
noUse?: boolean;
|
|
1422
1414
|
condition?: AttributeCondition;
|
|
1423
|
-
ineffective?:
|
|
1415
|
+
ineffective?: AttributeCondition;
|
|
1424
1416
|
animatable?: boolean;
|
|
1417
|
+
experimental?: boolean;
|
|
1425
1418
|
}
|