@markuplint/ml-spec 2.1.0 → 3.0.0-alpha.0

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 (128) hide show
  1. package/lib/dom-traverse/accname-computation.d.ts +1 -0
  2. package/lib/dom-traverse/accname-computation.js +8 -0
  3. package/lib/dom-traverse/focusability-computation.d.ts +1 -0
  4. package/lib/dom-traverse/focusability-computation.js +8 -0
  5. package/lib/dom-traverse/get-aria.d.ts +9 -0
  6. package/lib/dom-traverse/get-aria.js +54 -0
  7. package/lib/dom-traverse/get-attr-specs.d.ts +2 -0
  8. package/lib/dom-traverse/get-attr-specs.js +8 -0
  9. package/lib/dom-traverse/get-computed-role.d.ts +2 -0
  10. package/lib/dom-traverse/get-computed-role.js +170 -0
  11. package/lib/dom-traverse/get-explicit-role.d.ts +2 -0
  12. package/lib/dom-traverse/get-explicit-role.js +102 -0
  13. package/lib/dom-traverse/get-implicit-role.d.ts +3 -0
  14. package/lib/dom-traverse/get-implicit-role.js +37 -0
  15. package/lib/dom-traverse/get-non-presentational-ancestor.d.ts +5 -0
  16. package/lib/dom-traverse/get-non-presentational-ancestor.js +21 -0
  17. package/lib/dom-traverse/get-permitted-roles.d.ts +5 -0
  18. package/lib/dom-traverse/get-permitted-roles.js +8 -0
  19. package/lib/dom-traverse/get-spec.d.ts +2 -0
  20. package/lib/dom-traverse/get-spec.js +8 -0
  21. package/lib/dom-traverse/has-required-owned-elements.d.ts +3 -0
  22. package/lib/dom-traverse/has-required-owned-elements.js +81 -0
  23. package/lib/dom-traverse/may-be-focusable.d.ts +2 -0
  24. package/lib/dom-traverse/may-be-focusable.js +22 -0
  25. package/lib/index.d.ts +17 -6
  26. package/lib/index.js +17 -6
  27. package/lib/specs/aria-spec.d.ts +5 -0
  28. package/lib/specs/aria-spec.js +12 -0
  29. package/lib/specs/aria-specs.d.ts +6 -0
  30. package/lib/specs/aria-specs.js +8 -0
  31. package/lib/specs/content-model-category-to-tag-names.d.ts +3 -0
  32. package/lib/specs/content-model-category-to-tag-names.js +15 -0
  33. package/lib/specs/get-aria.d.ts +3 -0
  34. package/lib/specs/get-aria.js +71 -0
  35. package/lib/specs/get-attr-specs.d.ts +8 -0
  36. package/lib/{get-attr-specs.js → specs/get-attr-specs.js} +8 -6
  37. package/lib/specs/get-implicit-role.d.ts +2 -0
  38. package/lib/specs/get-implicit-role.js +12 -0
  39. package/lib/specs/get-permitted-roles.d.ts +12 -0
  40. package/lib/specs/get-permitted-roles.js +61 -0
  41. package/lib/specs/get-role-spec.d.ts +5 -0
  42. package/lib/specs/get-role-spec.js +52 -0
  43. package/lib/specs/get-selectors-by-content-model-category.d.ts +3 -0
  44. package/lib/specs/get-selectors-by-content-model-category.js +8 -0
  45. package/lib/specs/get-spec-by-tag-name.d.ts +2 -0
  46. package/lib/specs/get-spec-by-tag-name.js +16 -0
  47. package/lib/{get-spec.d.ts → specs/get-spec.d.ts} +4 -4
  48. package/lib/{get-spec.js → specs/get-spec.js} +1 -1
  49. package/lib/specs/html-spec.d.ts +6 -0
  50. package/lib/specs/html-spec.js +16 -0
  51. package/lib/specs/is-presentational.d.ts +1 -0
  52. package/lib/specs/is-presentational.js +10 -0
  53. package/lib/specs/resolve-namespace.d.ts +9 -0
  54. package/lib/specs/resolve-namespace.js +26 -0
  55. package/lib/specs/resolve-version.d.ts +3 -0
  56. package/lib/specs/resolve-version.js +21 -0
  57. package/lib/specs/schema-to-spec.d.ts +13 -0
  58. package/lib/specs/schema-to-spec.js +93 -0
  59. package/lib/types/aria.d.ts +130 -0
  60. package/lib/{attributes.js → types/aria.js} +0 -0
  61. package/lib/{attributes.d.ts → types/attributes.d.ts} +2 -10
  62. package/lib/{permitted-structres.js → types/attributes.js} +0 -0
  63. package/lib/{types.d.ts → types/index.d.ts} +49 -64
  64. package/lib/{types.js → types/index.js} +0 -0
  65. package/lib/{permitted-structres.d.ts → types/permitted-structres.d.ts} +14 -23
  66. package/lib/types/permitted-structres.js +8 -0
  67. package/lib/utils/cache.d.ts +10 -0
  68. package/lib/utils/cache.js +42 -0
  69. package/lib/utils/get-ns.d.ts +2 -0
  70. package/lib/{get-ns.js → utils/get-ns.js} +3 -0
  71. package/lib/utils/merge-array.d.ts +5 -0
  72. package/lib/utils/merge-array.js +36 -0
  73. package/lib/utils/resolve-namespace.d.ts +9 -0
  74. package/lib/utils/resolve-namespace.js +31 -0
  75. package/lib/utils.d.ts +6 -3
  76. package/lib/utils.js +15 -1
  77. package/package.json +10 -6
  78. package/schemas/aria.schema.json +258 -0
  79. package/schemas/attributes.schema.json +3 -22
  80. package/schemas/{permitted-structures.schema.json → content-models.schema.json} +52 -81
  81. package/schemas/element.schema.json +11 -0
  82. package/src/dom-traverse/accname-computation.spec.ts +69 -0
  83. package/src/dom-traverse/accname-computation.ts +5 -0
  84. package/src/dom-traverse/get-attr-specs.ts +8 -0
  85. package/src/dom-traverse/get-computed-role.spec.ts +134 -0
  86. package/src/dom-traverse/get-computed-role.ts +181 -0
  87. package/src/dom-traverse/get-explicit-role.ts +112 -0
  88. package/src/dom-traverse/get-implicit-role.ts +36 -0
  89. package/src/dom-traverse/get-non-presentational-ancestor.ts +20 -0
  90. package/src/dom-traverse/get-permitted-roles.ts +7 -0
  91. package/src/dom-traverse/get-spec.ts +7 -0
  92. package/src/dom-traverse/has-required-owned-elements.spec.ts +36 -0
  93. package/src/dom-traverse/has-required-owned-elements.ts +85 -0
  94. package/src/dom-traverse/may-be-focusable.ts +21 -0
  95. package/src/index.ts +17 -6
  96. package/src/specs/aria-specs.ts +6 -0
  97. package/src/specs/content-model-category-to-tag-names.ts +15 -0
  98. package/src/specs/get-aria.ts +85 -0
  99. package/src/{get-attr-specs.spec.ts → specs/get-attr-specs.spec.ts} +4 -7
  100. package/src/{get-attr-specs.ts → specs/get-attr-specs.ts} +12 -7
  101. package/src/specs/get-implicit-role.spec.ts +81 -0
  102. package/src/specs/get-implicit-role.ts +17 -0
  103. package/src/specs/get-permitted-roles.spec.ts +420 -0
  104. package/src/specs/get-permitted-roles.ts +87 -0
  105. package/src/specs/get-role-spec.spec.ts +67 -0
  106. package/src/specs/get-role-spec.ts +72 -0
  107. package/src/specs/get-selectors-by-content-model-category.ts +10 -0
  108. package/src/specs/get-spec-by-tag-name.spec.ts +68 -0
  109. package/src/specs/get-spec-by-tag-name.ts +16 -0
  110. package/src/specs/is-presentational.ts +6 -0
  111. package/src/specs/resolve-version.ts +20 -0
  112. package/src/{get-spec.spec.ts → specs/schema-to-spec.spec.ts} +2 -2
  113. package/src/{get-spec.ts → specs/schema-to-spec.ts} +22 -8
  114. package/src/types/aria.ts +147 -0
  115. package/src/{attributes.ts → types/attributes.ts} +2 -12
  116. package/src/{types.ts → types/index.ts} +69 -68
  117. package/src/{permitted-structres.ts → types/permitted-structres.ts} +15 -25
  118. package/src/{get-ns.ts → utils/get-ns.ts} +6 -1
  119. package/src/{utils.ts → utils/merge-array.ts} +0 -0
  120. package/src/utils/resolve-namespace.spec.ts +37 -0
  121. package/src/utils/resolve-namespace.ts +40 -0
  122. package/tsconfig.tsbuildinfo +1 -1
  123. package/lib/get-attr-specs.d.ts +0 -7
  124. package/lib/get-ns.d.ts +0 -1
  125. package/lib/get-spec-by-tag-name.d.ts +0 -2
  126. package/lib/get-spec-by-tag-name.js +0 -31
  127. package/schemas/wai-aria.schema.json +0 -87
  128. package/src/get-spec-by-tag-name.ts +0 -32
@@ -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,6 @@
1
+ export function isPresentational(roleName?: string) {
2
+ if (!roleName) {
3
+ return false;
4
+ }
5
+ return ['presentation', 'none'].includes(roleName);
6
+ }
@@ -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 { getSpec } from './get-spec';
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 = getSpec([
17
+ const mergedSpec = schemaToSpec([
18
18
  htmlSpec,
19
19
  {
20
20
  specs: [
@@ -1,6 +1,6 @@
1
- import type { ElementSpec, ExtendedSpec, MLMLSpec, Attribute } from './types';
1
+ import type { ElementSpec, ExtendedSpec, MLMLSpec, Attribute } from '../types';
2
2
 
3
- import { mergeArray } from './utils';
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 getSpec(schemas: readonly [MLMLSpec, ...ExtendedSpec[]]) {
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['#roles']) {
30
- result.def['#roles'] = [...result.def['#roles'], ...extendedSpec.def['#roles']];
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
  }
@@ -1413,8 +1405,6 @@ export interface Attributes {
1413
1405
  * via the `patternProperty` ".*".
1414
1406
  */
1415
1407
  export interface AttributeJSON {
1416
- _TODO_?: string;
1417
- ref: string;
1418
1408
  type?: AttributeType | [AttributeType, ...AttributeType[]];
1419
1409
  defaultValue?: string;
1420
1410
  deprecated?: boolean;
@@ -1422,7 +1412,7 @@ export interface AttributeJSON {
1422
1412
  requiredEither?: string[];
1423
1413
  noUse?: boolean;
1424
1414
  condition?: AttributeCondition;
1425
- ineffective?: Selectors;
1415
+ ineffective?: AttributeCondition;
1426
1416
  animatable?: boolean;
1427
1417
  experimental?: boolean;
1428
1418
  }
@@ -1,6 +1,7 @@
1
- import type { AttributeJSON } from '.';
2
- import type { AttributeType, GlobalAttributes } from './attributes';
3
- import type { ContentModel, PermittedStructuresSchema } from './permitted-structres';
1
+ import type { ARIA } from './aria';
2
+ import type { AttributeJSON, AttributeType, GlobalAttributes } from './attributes';
3
+ import type { ContentModel, Category } from './permitted-structres';
4
+ import type { NamespaceURI } from '@markuplint/ml-ast';
4
5
 
5
6
  /**
6
7
  * markuplit Markup-language spec
@@ -33,9 +34,17 @@ export type SpecDefs = {
33
34
  '#HTMLGlobalAttrs': Record<string, Partial<Attribute>>;
34
35
  [OtherGlobalAttrs: string]: Record<string, Partial<Attribute>>;
35
36
  }>;
36
- '#ariaAttrs': ARIAAttribute[];
37
- '#roles': ARIRRoleAttribute[];
38
- '#contentModels': { [model in ContentModel]?: string[] };
37
+ '#aria': {
38
+ '1.2': ARIASpec;
39
+ '1.1': ARIASpec;
40
+ };
41
+ '#contentModels': { [model in Category]?: string[] };
42
+ };
43
+
44
+ type ARIASpec = {
45
+ roles: ARIARoleInSchema[];
46
+ graphicsRoles: ARIARoleInSchema[];
47
+ props: ARIAProperty[];
39
48
  };
40
49
 
41
50
  /**
@@ -51,7 +60,7 @@ export type ElementSpec = {
51
60
  * Namespaces in XML
52
61
  * @see https://www.w3.org/TR/xml-names/
53
62
  */
54
- namespace?: 'http://www.w3.org/1999/xhtml' | 'http://www.w3.org/2000/svg' | 'http://www.w3.org/1998/Math/MathML';
63
+ namespace?: NamespaceURI;
55
64
 
56
65
  /**
57
66
  * Reference URL
@@ -90,36 +99,12 @@ export type ElementSpec = {
90
99
  /**
91
100
  * Element cateogries
92
101
  */
93
- categories: ContentModel[];
102
+ categories: Category[];
94
103
 
95
104
  /**
96
105
  * Permitted contents and permitted parents
97
106
  */
98
- permittedStructures: PermittedStructuresSchema;
99
-
100
- /**
101
- * Permitted ARIA roles
102
- */
103
- permittedRoles: {
104
- summary: string;
105
- roles: PermittedRoles;
106
- conditions?: {
107
- condition: string;
108
- roles: PermittedRoles;
109
- }[];
110
- };
111
-
112
- /**
113
- * Implicit ARIA role
114
- */
115
- implicitRole: {
116
- summary: string;
117
- role: ImplicitRole;
118
- conditions?: {
119
- condition: string;
120
- role: ImplicitRole;
121
- }[];
122
- };
107
+ contentModel: ContentModel;
123
108
 
124
109
  /**
125
110
  * Tag omittion
@@ -136,6 +121,11 @@ export type ElementSpec = {
136
121
  */
137
122
  attributes: Record<string, Attribute>;
138
123
 
124
+ /**
125
+ * WAI-ARIA role and properies
126
+ */
127
+ aria: ARIA;
128
+
139
129
  /**
140
130
  * If true, it is possible to add any properties as attributes,
141
131
  * for example, when using a template engine or a view language.
@@ -147,17 +137,6 @@ export type ElementSpec = {
147
137
  possibleToAddProperties?: true;
148
138
  };
149
139
 
150
- /**
151
- * If `false`, this mean is "No corresponding role".
152
- */
153
- type ImplicitRole = string | false;
154
-
155
- /**
156
- * If `true`, this mean is "Any".
157
- * If `false`, this mean is "No".
158
- */
159
- export type PermittedRoles = string[] | boolean;
160
-
161
140
  type ElementSpecOmittion = false | ElementSpecOmittionTags;
162
141
 
163
142
  type ElementSpecOmittionTags = {
@@ -180,31 +159,39 @@ export type Attribute = {
180
159
  nonStandard?: true;
181
160
  } & ExtendableAttributeSpec;
182
161
 
183
- type ExtendableAttributeSpec = Omit<AttributeJSON, 'ref' | '_TODO_' | 'type'>;
162
+ type ExtendableAttributeSpec = Omit<AttributeJSON, 'type'>;
184
163
 
185
- export type ARIRRoleAttribute = {
164
+ export type ARIARole = {
186
165
  name: string;
187
- description: string;
188
- isAbstract?: true;
189
- generalization: string[];
190
- requiredContextRole?: string[];
166
+ isAbstract: boolean;
167
+ requiredContextRole: string[];
168
+ requiredOwnedElements: string[];
191
169
  accessibleNameRequired: boolean;
170
+ accessibleNameFromAuthor: boolean;
192
171
  accessibleNameFromContent: boolean;
193
172
  accessibleNameProhibited: boolean;
194
- ownedAttribute: ARIARoleOwnedPropOrState[];
195
- childrenPresentational?: boolean;
173
+ childrenPresentational: boolean;
174
+ ownedProperties: ARIARoleOwnedProperties[];
175
+ prohibitedProperties: string[];
196
176
  };
197
177
 
198
- export type ARIARoleOwnedPropOrState = {
178
+ export type ARIARoleInSchema = Partial<
179
+ ARIARole & {
180
+ description: string;
181
+ generalization: string[];
182
+ }
183
+ > & {
184
+ name: string;
185
+ };
186
+
187
+ export type ARIARoleOwnedProperties = {
199
188
  name: string;
200
189
  inherited?: true;
201
190
  required?: true;
202
191
  deprecated?: true;
203
- prohibited?: true;
204
- defaultValue?: boolean | string | number;
205
192
  };
206
193
 
207
- export type ARIAAttribute = {
194
+ export type ARIAProperty = {
208
195
  name: string;
209
196
  type: 'property' | 'state';
210
197
  deprecated?: true;
@@ -233,22 +220,36 @@ export type ARIAAttributeValue =
233
220
  | 'token list'
234
221
  | 'URI';
235
222
 
223
+ export type ARIAVersion = '1.1' | '1.2';
224
+
236
225
  export type EquivalentHtmlAttr = {
237
226
  htmlAttrName: string;
238
227
  isNotStrictEquivalent?: true;
239
228
  value: string | null;
240
229
  };
241
230
 
242
- export interface SpecOM {
243
- [tagName: string]: MLDOMElementSpec;
244
- }
231
+ export type Matches = (selector: string) => boolean;
232
+
233
+ export type ComputedRole = {
234
+ el: Element;
235
+ role:
236
+ | (ARIARole & {
237
+ superClassRoles: ARIARoleInSchema[];
238
+ isImplicit?: boolean;
239
+ })
240
+ | null;
241
+ errorType?: RoleComputationError;
242
+ };
245
243
 
246
- export interface MLDOMElementSpec {
247
- experimental: boolean;
248
- obsolete: boolean | string;
249
- deprecated: boolean;
250
- nonStandard: boolean;
251
- categories: ContentModel[];
252
- permittedStructures: PermittedStructuresSchema;
253
- attributes: Attribute[];
254
- }
244
+ export type RoleComputationError =
245
+ | 'ABSTRACT'
246
+ | 'GLOBAL_PROP_MUST_NOT_BE_PRESENTATIONAL'
247
+ | 'IMPLICIT_ROLE_NAMESPACE_ERROR'
248
+ | 'INTERACTIVE_ELEMENT_MUST_NOT_BE_PRESENTATIONAL'
249
+ | 'INVALID_LANDMARK'
250
+ | 'INVALID_REQUIRED_CONTEXT_ROLE'
251
+ | 'NO_EXPLICIT'
252
+ | 'NO_OWNER'
253
+ | 'NO_PERMITTED'
254
+ | 'REQUIRED_OWNED_ELEMENT_MUST_NOT_BE_PRESENTATIONAL'
255
+ | 'ROLE_NO_EXISTS';
@@ -12,9 +12,10 @@ export type PermittedContent =
12
12
  | PermittedContentZeroOrMore
13
13
  | PermittedContentChoice
14
14
  | PermittedContentInterleave;
15
- export type Target = Node | Node[];
16
- export type Node = string | '#text' | ContentModel;
17
- export type ContentModel =
15
+ export type Target = ContentType | ContentType[];
16
+ export type ContentType = string | Category;
17
+ export type Category =
18
+ | '#text'
18
19
  | '#phrasing'
19
20
  | '#flow'
20
21
  | '#interactive'
@@ -47,32 +48,21 @@ export type ContentModel =
47
48
  | '#SVGOtherXMLNamespace';
48
49
  export type PermittedContentSpec = PermittedContent[];
49
50
 
50
- export interface PermittedStructuresSchema {
51
- summary?: string;
52
- tag: string;
51
+ export interface ContentModelsSchema {
52
+ __contentModel?: ContentModel;
53
+ }
54
+ export interface ContentModel {
55
+ contents: PermittedContentSpec | boolean;
56
+ descendantOf?: string;
53
57
  conditional?: {
54
- condition:
55
- | {
56
- hasAttr: string;
57
- }
58
- | {
59
- parent: string;
60
- /**
61
- * Not support yet
62
- */
63
- hasNotAttr?: string;
64
- _TODO_?: string;
65
- _parent?: string;
66
- };
58
+ condition: string;
67
59
  contents: PermittedContentSpec | boolean;
68
60
  }[];
69
- contents: PermittedContentSpec | boolean;
70
- ancestor?: Node;
71
61
  }
72
62
  export interface PermittedContentRequire {
73
63
  require: Target;
74
64
  ignore?: Target;
75
- notAllowedDescendants?: Node[];
65
+ notAllowedDescendants?: ContentType[];
76
66
  max?: number;
77
67
  min?: number;
78
68
  _TODO_?: string;
@@ -80,21 +70,21 @@ export interface PermittedContentRequire {
80
70
  export interface PermittedContentOptional {
81
71
  optional: Target;
82
72
  ignore?: Target;
83
- notAllowedDescendants?: Node[];
73
+ notAllowedDescendants?: ContentType[];
84
74
  max?: number;
85
75
  _TODO_?: string;
86
76
  }
87
77
  export interface PermittedContentOneOrMore {
88
78
  oneOrMore: Target | PermittedContentSpec;
89
79
  ignore?: Target;
90
- notAllowedDescendants?: Node[];
80
+ notAllowedDescendants?: ContentType[];
91
81
  max?: number;
92
82
  _TODO_?: string;
93
83
  }
94
84
  export interface PermittedContentZeroOrMore {
95
85
  zeroOrMore: Target | PermittedContentSpec;
96
86
  ignore?: Target;
97
- notAllowedDescendants?: Node[];
87
+ notAllowedDescendants?: ContentType[];
98
88
  max?: number;
99
89
  _TODO_?: string;
100
90
  }
@@ -1,4 +1,6 @@
1
- export function getNS(namespaceURI: string) {
1
+ import type { Namespace } from '@markuplint/ml-ast';
2
+
3
+ export function getNS(namespaceURI: string | null): Namespace {
2
4
  switch (namespaceURI) {
3
5
  case 'http://www.w3.org/2000/svg': {
4
6
  return 'svg';
@@ -6,6 +8,9 @@ export function getNS(namespaceURI: string) {
6
8
  case 'http://www.w3.org/1998/Math/MathML': {
7
9
  return 'mml';
8
10
  }
11
+ case 'http://www.w3.org/1999/xlink': {
12
+ return 'xlink';
13
+ }
9
14
  default: {
10
15
  return 'html';
11
16
  }
File without changes