@markuplint/ml-spec 3.0.0-dev.25 → 3.0.0-dev.40

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 (59) hide show
  1. package/lib/dom-traverse/is-exposed.js +8 -0
  2. package/lib/types/attributes.d.ts +1 -1
  3. package/package.json +4 -4
  4. package/schemas/aria.schema.json +0 -258
  5. package/schemas/attributes.schema.json +0 -204
  6. package/schemas/content-models.schema.json +0 -199
  7. package/schemas/element.schema.json +0 -11
  8. package/schemas/global-attributes.schema.json +0 -761
  9. package/src/dom-traverse/accname-computation.spec.ts +0 -69
  10. package/src/dom-traverse/accname-computation.ts +0 -5
  11. package/src/dom-traverse/get-attr-specs.ts +0 -8
  12. package/src/dom-traverse/get-computed-aria-props.spec.ts +0 -368
  13. package/src/dom-traverse/get-computed-aria-props.ts +0 -130
  14. package/src/dom-traverse/get-computed-role.spec.ts +0 -134
  15. package/src/dom-traverse/get-computed-role.ts +0 -181
  16. package/src/dom-traverse/get-content-model.ts +0 -32
  17. package/src/dom-traverse/get-explicit-role.ts +0 -112
  18. package/src/dom-traverse/get-implicit-role.ts +0 -36
  19. package/src/dom-traverse/get-non-presentational-ancestor.ts +0 -20
  20. package/src/dom-traverse/get-permitted-roles.ts +0 -7
  21. package/src/dom-traverse/get-spec.ts +0 -7
  22. package/src/dom-traverse/has-required-owned-elements.spec.ts +0 -36
  23. package/src/dom-traverse/has-required-owned-elements.ts +0 -85
  24. package/src/dom-traverse/is-exposed.spec.ts +0 -50
  25. package/src/dom-traverse/is-exposed.ts +0 -196
  26. package/src/dom-traverse/may-be-focusable.ts +0 -21
  27. package/src/index.ts +0 -24
  28. package/src/specs/aria-specs.ts +0 -6
  29. package/src/specs/content-model-category-to-tag-names.ts +0 -15
  30. package/src/specs/get-aria.ts +0 -85
  31. package/src/specs/get-attr-specs.spec.ts +0 -47
  32. package/src/specs/get-attr-specs.ts +0 -116
  33. package/src/specs/get-implicit-role.spec.ts +0 -81
  34. package/src/specs/get-implicit-role.ts +0 -17
  35. package/src/specs/get-permitted-roles.spec.ts +0 -420
  36. package/src/specs/get-permitted-roles.ts +0 -87
  37. package/src/specs/get-role-spec.spec.ts +0 -67
  38. package/src/specs/get-role-spec.ts +0 -72
  39. package/src/specs/get-selectors-by-content-model-category.ts +0 -10
  40. package/src/specs/get-spec-by-tag-name.spec.ts +0 -68
  41. package/src/specs/get-spec-by-tag-name.ts +0 -20
  42. package/src/specs/is-nothing-content-model.ts +0 -9
  43. package/src/specs/is-palpable-elements.ts +0 -55
  44. package/src/specs/is-presentational.ts +0 -6
  45. package/src/specs/is-void-element.ts +0 -22
  46. package/src/specs/resolve-version.ts +0 -20
  47. package/src/specs/schema-to-spec.spec.ts +0 -39
  48. package/src/specs/schema-to-spec.ts +0 -103
  49. package/src/types/aria.ts +0 -153
  50. package/src/types/attributes.ts +0 -1524
  51. package/src/types/index.ts +0 -255
  52. package/src/types/permitted-structres.ts +0 -100
  53. package/src/types/permitted-structures.ts +0 -96
  54. package/src/utils/get-ns.ts +0 -18
  55. package/src/utils/merge-array.ts +0 -35
  56. package/src/utils/resolve-namespace.spec.ts +0 -37
  57. package/src/utils/resolve-namespace.ts +0 -40
  58. package/tsconfig.test.json +0 -3
  59. package/tsconfig.tsbuildinfo +0 -1
@@ -1,420 +0,0 @@
1
- import type { ARIAVersion } from '../types';
2
-
3
- import specs from '@markuplint/html-spec';
4
- import { createSelector } from '@markuplint/selector';
5
- import { createJSDOMElement } from '@markuplint/test-tools';
6
-
7
- import { getPermittedRoles } from './get-permitted-roles';
8
-
9
- function c(html: string, version: ARIAVersion, selector?: string) {
10
- const el = createJSDOMElement(html, selector);
11
- const roles = getPermittedRoles(
12
- specs,
13
- el.localName,
14
- el.namespaceURI,
15
- version,
16
- selector => !!createSelector(selector, specs).match(el),
17
- );
18
- if (Array.isArray(roles)) {
19
- return roles.map(r => r.name);
20
- }
21
- return roles;
22
- }
23
-
24
- const coreRoles = [
25
- 'alert',
26
- 'alertdialog',
27
- 'application',
28
- 'article',
29
- 'banner',
30
- 'blockquote',
31
- 'button',
32
- 'caption',
33
- 'cell',
34
- 'checkbox',
35
- 'code',
36
- 'columnheader',
37
- 'combobox',
38
- 'complementary',
39
- 'contentinfo',
40
- 'definition',
41
- 'deletion',
42
- 'dialog',
43
- 'directory',
44
- 'document',
45
- 'emphasis',
46
- 'feed',
47
- 'figure',
48
- 'form',
49
- 'generic',
50
- 'grid',
51
- 'gridcell',
52
- 'group',
53
- 'heading',
54
- 'img',
55
- 'insertion',
56
- 'link',
57
- 'list',
58
- 'listbox',
59
- 'listitem',
60
- 'log',
61
- 'main',
62
- 'marquee',
63
- 'math',
64
- 'menu',
65
- 'menubar',
66
- 'menuitem',
67
- 'menuitemcheckbox',
68
- 'menuitemradio',
69
- 'meter',
70
- 'navigation',
71
- 'none',
72
- 'note',
73
- 'option',
74
- 'paragraph',
75
- 'presentation',
76
- 'progressbar',
77
- 'radio',
78
- 'radiogroup',
79
- 'region',
80
- 'row',
81
- 'rowgroup',
82
- 'rowheader',
83
- 'scrollbar',
84
- 'search',
85
- 'searchbox',
86
- 'separator',
87
- 'slider',
88
- 'spinbutton',
89
- 'status',
90
- 'strong',
91
- 'subscript',
92
- 'superscript',
93
- 'switch',
94
- 'tab',
95
- 'table',
96
- 'tablist',
97
- 'tabpanel',
98
- 'term',
99
- 'textbox',
100
- 'time',
101
- 'timer',
102
- 'toolbar',
103
- 'tooltip',
104
- 'tree',
105
- 'treegrid',
106
- 'treeitem',
107
- ];
108
-
109
- describe('getPermittedRoles', () => {
110
- test('the a element', () => {
111
- expect(c('<a></a>', '1.2')).toStrictEqual(coreRoles);
112
- expect(c('<a href="path/to"></a>', '1.2')).toStrictEqual([
113
- 'link',
114
- 'button',
115
- 'checkbox',
116
- 'menuitem',
117
- 'menuitemcheckbox',
118
- 'menuitemradio',
119
- 'option',
120
- 'radio',
121
- 'switch',
122
- 'tab',
123
- 'treeitem',
124
- ]);
125
- });
126
-
127
- test('the area element', () => {
128
- expect(c('<area></area>', '1.2')).toStrictEqual(['button', 'link']);
129
- expect(c('<area></area>', '1.1')).toStrictEqual([]);
130
- expect(c('<area href="path/to"></area>', '1.2')).toStrictEqual(['link']);
131
- });
132
-
133
- test('the figure element', () => {
134
- expect(c('<figure></figure>', '1.2')).toStrictEqual(coreRoles);
135
- expect(c('<figure><figcaption></figcaption></figure>', '1.2')).toStrictEqual(['figure']);
136
- });
137
-
138
- test('the img element', () => {
139
- expect(c('<img>', '1.2')).toStrictEqual(['img']);
140
- expect(c('<img alt="">', '1.2')).toStrictEqual(['none', 'presentation']);
141
- expect(c('<img alt="photo: something">', '1.2')).toStrictEqual([
142
- 'img',
143
- 'button',
144
- 'checkbox',
145
- 'link',
146
- 'menuitem',
147
- 'menuitemcheckbox',
148
- 'menuitemradio',
149
- 'option',
150
- 'progressbar',
151
- 'radio',
152
- 'scrollbar',
153
- 'separator',
154
- 'slider',
155
- 'switch',
156
- 'tab',
157
- 'treeitem',
158
- ]);
159
- expect(c('<img alt="photo: something">', '1.1')).toStrictEqual([
160
- 'img',
161
- 'button',
162
- 'checkbox',
163
- 'link',
164
- 'menuitem',
165
- 'menuitemcheckbox',
166
- 'menuitemradio',
167
- 'option',
168
- 'progressbar',
169
- 'scrollbar',
170
- 'separator',
171
- 'slider',
172
- 'switch',
173
- 'tab',
174
- 'treeitem',
175
- ]);
176
- });
177
-
178
- test('the input element', () => {
179
- expect(c('<input>', '1.2')).toStrictEqual(['textbox', 'combobox', 'searchbox', 'spinbutton']);
180
- expect(c('<input>', '1.1')).toStrictEqual(['textbox', 'combobox', 'searchbox', 'spinbutton']);
181
- expect(c('<input type="button">', '1.2')).toStrictEqual([
182
- 'button',
183
- 'checkbox',
184
- 'combobox',
185
- 'link',
186
- 'menuitem',
187
- 'menuitemcheckbox',
188
- 'menuitemradio',
189
- 'option',
190
- 'radio',
191
- 'switch',
192
- 'tab',
193
- ]);
194
- expect(c('<input type="button">', '1.1')).toStrictEqual([
195
- 'button',
196
- 'link',
197
- 'menuitem',
198
- 'menuitemcheckbox',
199
- 'menuitemradio',
200
- 'option',
201
- 'radio',
202
- 'switch',
203
- 'tab',
204
- ]);
205
- expect(c('<input type="checkbox" aria-pressed="true">', '1.2')).toStrictEqual(['checkbox', 'button']);
206
- });
207
-
208
- test('the img element', () => {
209
- const imgPermitted = [
210
- 'img',
211
- 'button',
212
- 'checkbox',
213
- 'link',
214
- 'menuitem',
215
- 'menuitemcheckbox',
216
- 'menuitemradio',
217
- 'option',
218
- 'progressbar',
219
- 'radio',
220
- 'scrollbar',
221
- 'separator',
222
- 'slider',
223
- 'switch',
224
- 'tab',
225
- 'treeitem',
226
- ];
227
- expect(c('<img />', '1.2')).toStrictEqual(['img']);
228
- expect(c('<img alt />', '1.2')).toStrictEqual(['none', 'presentation']);
229
- expect(c('<img alt="" />', '1.2')).toStrictEqual(['none', 'presentation']);
230
- expect(c('<img alt="foo" />', '1.2')).toStrictEqual(imgPermitted);
231
- expect(c('<img aria-label="foo" />', '1.2')).toStrictEqual(imgPermitted);
232
- });
233
-
234
- test('the form element', () => {
235
- expect(c('<form></form>', '1.2')).toStrictEqual(['form', 'none', 'presentation', 'search']);
236
- expect(c('<form></form>', '1.1')).toStrictEqual(['none', 'presentation', 'search']);
237
- expect(c('<form aria-label="foo"></form>', '1.2')).toStrictEqual(['form', 'none', 'presentation', 'search']);
238
- expect(c('<form aria-label="foo"></form>', '1.1')).toStrictEqual(['form', 'none', 'presentation', 'search']);
239
- });
240
-
241
- test('the svg element', () => {
242
- expect(c('<svg></svg>', '1.2')).toStrictEqual([
243
- 'alert',
244
- 'alertdialog',
245
- 'application',
246
- 'article',
247
- 'banner',
248
- 'blockquote',
249
- 'button',
250
- 'caption',
251
- 'cell',
252
- 'checkbox',
253
- 'code',
254
- 'columnheader',
255
- 'combobox',
256
- 'complementary',
257
- 'contentinfo',
258
- 'definition',
259
- 'deletion',
260
- 'dialog',
261
- 'directory',
262
- 'document',
263
- 'emphasis',
264
- 'feed',
265
- 'figure',
266
- 'form',
267
- 'generic',
268
- 'grid',
269
- 'gridcell',
270
- 'group',
271
- 'heading',
272
- 'img',
273
- 'insertion',
274
- 'link',
275
- 'list',
276
- 'listbox',
277
- 'listitem',
278
- 'log',
279
- 'main',
280
- 'marquee',
281
- 'math',
282
- 'menu',
283
- 'menubar',
284
- 'menuitem',
285
- 'menuitemcheckbox',
286
- 'menuitemradio',
287
- 'meter',
288
- 'navigation',
289
- 'none',
290
- 'note',
291
- 'option',
292
- 'paragraph',
293
- 'presentation',
294
- 'progressbar',
295
- 'radio',
296
- 'radiogroup',
297
- 'region',
298
- 'row',
299
- 'rowgroup',
300
- 'rowheader',
301
- 'scrollbar',
302
- 'search',
303
- 'searchbox',
304
- 'separator',
305
- 'slider',
306
- 'spinbutton',
307
- 'status',
308
- 'strong',
309
- 'subscript',
310
- 'superscript',
311
- 'switch',
312
- 'tab',
313
- 'table',
314
- 'tablist',
315
- 'tabpanel',
316
- 'term',
317
- 'textbox',
318
- 'time',
319
- 'timer',
320
- 'toolbar',
321
- 'tooltip',
322
- 'tree',
323
- 'treegrid',
324
- 'treeitem',
325
- 'graphics-document',
326
- 'graphics-object',
327
- 'graphics-symbol',
328
- ]);
329
- });
330
-
331
- test('the rect element', () => {
332
- expect(c('<svg><rect></rect></svg>', '1.2')).toStrictEqual([
333
- 'alert',
334
- 'alertdialog',
335
- 'application',
336
- 'article',
337
- 'banner',
338
- 'blockquote',
339
- 'button',
340
- 'caption',
341
- 'cell',
342
- 'checkbox',
343
- 'code',
344
- 'columnheader',
345
- 'combobox',
346
- 'complementary',
347
- 'contentinfo',
348
- 'definition',
349
- 'deletion',
350
- 'dialog',
351
- 'directory',
352
- 'document',
353
- 'emphasis',
354
- 'feed',
355
- 'figure',
356
- 'form',
357
- 'generic',
358
- 'grid',
359
- 'gridcell',
360
- 'group',
361
- 'heading',
362
- 'img',
363
- 'insertion',
364
- 'link',
365
- 'list',
366
- 'listbox',
367
- 'listitem',
368
- 'log',
369
- 'main',
370
- 'marquee',
371
- 'math',
372
- 'menu',
373
- 'menubar',
374
- 'menuitem',
375
- 'menuitemcheckbox',
376
- 'menuitemradio',
377
- 'meter',
378
- 'navigation',
379
- 'none',
380
- 'note',
381
- 'option',
382
- 'paragraph',
383
- 'presentation',
384
- 'progressbar',
385
- 'radio',
386
- 'radiogroup',
387
- 'region',
388
- 'row',
389
- 'rowgroup',
390
- 'rowheader',
391
- 'scrollbar',
392
- 'search',
393
- 'searchbox',
394
- 'separator',
395
- 'slider',
396
- 'spinbutton',
397
- 'status',
398
- 'strong',
399
- 'subscript',
400
- 'superscript',
401
- 'switch',
402
- 'tab',
403
- 'table',
404
- 'tablist',
405
- 'tabpanel',
406
- 'term',
407
- 'textbox',
408
- 'time',
409
- 'timer',
410
- 'toolbar',
411
- 'tooltip',
412
- 'tree',
413
- 'treegrid',
414
- 'treeitem',
415
- 'graphics-document',
416
- 'graphics-object',
417
- 'graphics-symbol',
418
- ]);
419
- });
420
- });
@@ -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,67 +0,0 @@
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
- });
@@ -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
- }