@markuplint/ml-spec 3.0.0-canary.5 → 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 +1 -1
- 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 +6 -6
- package/lib/dom-traverse/get-computed-aria-props.js +4 -2
- package/lib/dom-traverse/get-computed-role.d.ts +6 -1
- package/lib/dom-traverse/get-computed-role.js +41 -10
- package/lib/dom-traverse/get-content-model.d.ts +28 -2
- package/lib/dom-traverse/get-content-model.js +4 -2
- 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 +4 -1
- package/lib/dom-traverse/get-spec.js +3 -1
- package/lib/dom-traverse/has-required-owned-elements.d.ts +8 -2
- package/lib/dom-traverse/has-required-owned-elements.js +14 -8
- package/lib/dom-traverse/is-exposed.d.ts +1 -1
- package/lib/dom-traverse/is-exposed.js +43 -7
- 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 +1 -1
- package/lib/dom-traverse/may-be-focusable.js +3 -1
- package/lib/index.d.ts +4 -0
- package/lib/index.js +4 -0
- package/lib/specs/aria-specs.d.ts +7 -4
- package/lib/specs/content-model-category-to-tag-names.d.ts +4 -1
- package/lib/specs/get-aria.d.ts +8 -1
- package/lib/specs/get-aria.js +8 -2
- package/lib/specs/get-attr-specs.d.ts +6 -2
- 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 +1 -1
- package/lib/specs/get-selectors-by-content-model-category.js +1 -1
- package/lib/specs/get-spec-by-tag-name.d.ts +5 -1
- 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 +8 -4
- package/lib/specs/is-palpable-elements.js +6 -4
- package/lib/specs/is-void-element.js +3 -1
- 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 +149 -114
- package/lib/types/attributes.d.ts +1490 -111
- package/lib/types/index.d.ts +178 -149
- package/lib/types/permitted-structures.d.ts +74 -31
- package/lib/utils/merge-array.d.ts +9 -4
- package/lib/utils/resolve-namespace.d.ts +4 -4
- package/lib/utils/resolve-namespace.js +3 -2
- package/lib/utils/validateAriaVersion.d.ts +2 -0
- package/lib/utils/validateAriaVersion.js +8 -0
- package/package.json +13 -8
- package/{src/dom-traverse/accname-computation.spec.ts → test/dom-traverse/accname-computation.spec.js} +4 -4
- 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/{src/dom-traverse/is-exposed.spec.ts → test/dom-traverse/is-exposed.spec.js} +29 -9
- 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} +2 -2
- package/test/specs/resolve-version.spec.js +34 -0
- package/test/specs/schema-to-spec.spec.js +61 -0
- package/{src/utils/resolve-namespace.spec.ts → test/utils/resolve-namespace.spec.js} +1 -1
- package/lib/types/permitted-structres.d.ts +0 -58
- package/lib/types/permitted-structres.js +0 -8
- package/schemas/aria.schema.json +0 -258
- package/schemas/attributes.schema.json +0 -204
- package/schemas/content-models.schema.json +0 -199
- 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-aria-props.spec.ts +0 -368
- package/src/dom-traverse/get-computed-aria-props.ts +0 -130
- package/src/dom-traverse/get-computed-role.spec.ts +0 -134
- package/src/dom-traverse/get-computed-role.ts +0 -181
- package/src/dom-traverse/get-content-model.ts +0 -32
- 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 -85
- package/src/dom-traverse/is-exposed.ts +0 -196
- package/src/dom-traverse/may-be-focusable.ts +0 -21
- package/src/index.ts +0 -23
- 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 -20
- package/src/specs/is-palpable-elements.ts +0 -55
- package/src/specs/is-presentational.ts +0 -6
- package/src/specs/is-void-element.ts +0 -22
- 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 -153
- package/src/types/attributes.ts +0 -1473
- package/src/types/index.ts +0 -255
- package/src/types/permitted-structres.ts +0 -100
- package/src/types/permitted-structures.ts +0 -96
- package/src/utils/get-ns.ts +0 -18
- package/src/utils/merge-array.ts +0 -35
- package/src/utils/resolve-namespace.ts +0 -40
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { MLMLSpec } from '../types';
|
|
2
|
-
|
|
3
|
-
import { getSelectorsByContentModelCategory } from '../specs/get-selectors-by-content-model-category';
|
|
4
|
-
|
|
5
|
-
export function mayBeFocusable(el: Element, specs: Readonly<MLMLSpec>): boolean {
|
|
6
|
-
return [
|
|
7
|
-
/**
|
|
8
|
-
* Interactive content
|
|
9
|
-
*
|
|
10
|
-
* @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content
|
|
11
|
-
*/
|
|
12
|
-
...getSelectorsByContentModelCategory(specs, '#interactive'),
|
|
13
|
-
/**
|
|
14
|
-
* Interaction
|
|
15
|
-
*
|
|
16
|
-
* @see https://html.spec.whatwg.org/multipage/interaction.html
|
|
17
|
-
*/
|
|
18
|
-
'[tabindex]',
|
|
19
|
-
'[contenteditable]:not([contenteditable="false" i])',
|
|
20
|
-
].some(selector => el.matches(selector));
|
|
21
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export * from './dom-traverse/accname-computation';
|
|
2
|
-
export * from './dom-traverse/get-attr-specs';
|
|
3
|
-
export * from './dom-traverse/get-computed-aria-props';
|
|
4
|
-
export * from './dom-traverse/get-computed-role';
|
|
5
|
-
export * from './dom-traverse/get-content-model';
|
|
6
|
-
export * from './dom-traverse/get-implicit-role';
|
|
7
|
-
export * from './dom-traverse/get-permitted-roles';
|
|
8
|
-
export * from './dom-traverse/get-spec';
|
|
9
|
-
export * from './dom-traverse/has-required-owned-elements';
|
|
10
|
-
export * from './dom-traverse/is-exposed';
|
|
11
|
-
export * from './dom-traverse/may-be-focusable';
|
|
12
|
-
export * from './specs/aria-specs';
|
|
13
|
-
export * from './specs/content-model-category-to-tag-names';
|
|
14
|
-
export * from './specs/get-role-spec';
|
|
15
|
-
export * from './specs/get-spec-by-tag-name';
|
|
16
|
-
export * from './specs/is-palpable-elements';
|
|
17
|
-
export * from './specs/is-void-element';
|
|
18
|
-
export * from './specs/schema-to-spec';
|
|
19
|
-
export * from './types';
|
|
20
|
-
export * from './types/aria';
|
|
21
|
-
export * from './types/attributes';
|
|
22
|
-
export * from './types/permitted-structures';
|
|
23
|
-
export * from './utils/resolve-namespace';
|
package/src/specs/aria-specs.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { MLMLSpec } from '../types';
|
|
2
|
-
import type { Category } from '../types/permitted-structures';
|
|
3
|
-
|
|
4
|
-
const cache = new Map<Category, ReadonlyArray<string>>();
|
|
5
|
-
|
|
6
|
-
export function contentModelCategoryToTagNames(contentModel: Category, def: MLMLSpec['def']): ReadonlyArray<string> {
|
|
7
|
-
const cached = cache.get(contentModel);
|
|
8
|
-
if (cached) {
|
|
9
|
-
return cached;
|
|
10
|
-
}
|
|
11
|
-
const tags: string[] | undefined = def['#contentModels'][contentModel];
|
|
12
|
-
const sortedTag = Object.freeze(tags && Array.isArray(tags) ? tags.sort() : []);
|
|
13
|
-
cache.set(contentModel, sortedTag);
|
|
14
|
-
return sortedTag;
|
|
15
|
-
}
|
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 conditionKeys = Object.keys(conditions);
|
|
25
|
-
let { implicitRole, permittedRoles, implicitProperties, properties, namingProhibited } = aria;
|
|
26
|
-
for (const cond of conditionKeys) {
|
|
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.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-structures';
|
|
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,20 +0,0 @@
|
|
|
1
|
-
import type { ElementSpec } from '../types';
|
|
2
|
-
|
|
3
|
-
import { resolveNamespace } from '../utils/resolve-namespace';
|
|
4
|
-
|
|
5
|
-
const cache = new Map<string, any>();
|
|
6
|
-
|
|
7
|
-
export function getSpecByTagName<K extends keyof ElementSpec = keyof ElementSpec>(
|
|
8
|
-
specs: Readonly<Pick<ElementSpec, 'name' | K>[]>,
|
|
9
|
-
localName: string,
|
|
10
|
-
namespace: string | null,
|
|
11
|
-
) {
|
|
12
|
-
const { localNameWithNS } = resolveNamespace(localName, namespace || undefined);
|
|
13
|
-
let spec: Pick<ElementSpec, 'name' | K> | null | undefined = cache.get(localNameWithNS);
|
|
14
|
-
if (spec !== undefined) {
|
|
15
|
-
return spec;
|
|
16
|
-
}
|
|
17
|
-
spec = specs.find(spec => spec.name === localNameWithNS) || null;
|
|
18
|
-
cache.set(localNameWithNS, spec);
|
|
19
|
-
return spec;
|
|
20
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { MLMLSpec } from '../types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Exposable content models and elements
|
|
5
|
-
*
|
|
6
|
-
* **WARNING**:
|
|
7
|
-
* This implementation is through the author's interpretation.
|
|
8
|
-
* Want a issue request.
|
|
9
|
-
* https://github.com/markuplint/markuplint/issues/new
|
|
10
|
-
*
|
|
11
|
-
* @see https://html.spec.whatwg.org/multipage/indices.html#elements-3
|
|
12
|
-
*/
|
|
13
|
-
const exposableElementsThatAreNoBelongingAModel: string[] = [
|
|
14
|
-
'body',
|
|
15
|
-
'dd',
|
|
16
|
-
'dt',
|
|
17
|
-
'figcaption',
|
|
18
|
-
'html',
|
|
19
|
-
'legend',
|
|
20
|
-
'li',
|
|
21
|
-
'optgroup',
|
|
22
|
-
'option',
|
|
23
|
-
'rp',
|
|
24
|
-
'rt',
|
|
25
|
-
'summary',
|
|
26
|
-
'tbody',
|
|
27
|
-
'td',
|
|
28
|
-
'tfoot',
|
|
29
|
-
'th',
|
|
30
|
-
'thead',
|
|
31
|
-
'tr',
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
export function isPalpableElement(
|
|
35
|
-
el: Element,
|
|
36
|
-
specs: Readonly<MLMLSpec>,
|
|
37
|
-
options?: {
|
|
38
|
-
extendsSvg?: boolean;
|
|
39
|
-
extendsExposableElements?: boolean;
|
|
40
|
-
},
|
|
41
|
-
) {
|
|
42
|
-
const conditions = [specs.def['#contentModels']['#palpable']?.join(',') || ''];
|
|
43
|
-
|
|
44
|
-
if (options?.extendsSvg !== false /* default true */) {
|
|
45
|
-
conditions.push(specs.def['#contentModels']['#SVGRenderable']?.join(',') || '');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (options?.extendsExposableElements /* default false */) {
|
|
49
|
-
conditions.push(exposableElementsThatAreNoBelongingAModel.join(','));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return conditions.some(condition => {
|
|
53
|
-
return el.matches(condition);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @see https://html.spec.whatwg.org/multipage/syntax.html#void-elements
|
|
3
|
-
*/
|
|
4
|
-
const voidElements = [
|
|
5
|
-
'area',
|
|
6
|
-
'base',
|
|
7
|
-
'br',
|
|
8
|
-
'col',
|
|
9
|
-
'embed',
|
|
10
|
-
'hr',
|
|
11
|
-
'img',
|
|
12
|
-
'input',
|
|
13
|
-
'link',
|
|
14
|
-
'meta',
|
|
15
|
-
'source',
|
|
16
|
-
'track',
|
|
17
|
-
'wbr',
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
export function isVoidElement(el: Element) {
|
|
21
|
-
return voidElements.includes(el.localName);
|
|
22
|
-
}
|
|
@@ -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
|
-
});
|