html-validate 8.7.4 → 8.9.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 (74) hide show
  1. package/dist/cjs/browser.js +7 -21
  2. package/dist/cjs/browser.js.map +1 -1
  3. package/dist/cjs/cli.js +483 -451
  4. package/dist/cjs/cli.js.map +1 -1
  5. package/dist/cjs/core-browser.js +9 -20
  6. package/dist/cjs/core-browser.js.map +1 -1
  7. package/dist/cjs/core-nodejs.js +203 -297
  8. package/dist/cjs/core-nodejs.js.map +1 -1
  9. package/dist/cjs/core.js +9735 -10454
  10. package/dist/cjs/core.js.map +1 -1
  11. package/dist/cjs/elements.js +2311 -2296
  12. package/dist/cjs/elements.js.map +1 -1
  13. package/dist/cjs/html-validate.js +148 -169
  14. package/dist/cjs/html-validate.js.map +1 -1
  15. package/dist/cjs/html5.js.map +1 -1
  16. package/dist/cjs/index.js +8 -21
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/jest-diff.js +26 -36
  19. package/dist/cjs/jest-diff.js.map +1 -1
  20. package/dist/cjs/jest.js +8 -8
  21. package/dist/cjs/jest.js.map +1 -1
  22. package/dist/cjs/matcher-utils.js +12 -28
  23. package/dist/cjs/matcher-utils.js.map +1 -1
  24. package/dist/cjs/matchers-jestonly.js +38 -47
  25. package/dist/cjs/matchers-jestonly.js.map +1 -1
  26. package/dist/cjs/matchers.js +196 -196
  27. package/dist/cjs/matchers.js.map +1 -1
  28. package/dist/cjs/meta-helper.js +40 -60
  29. package/dist/cjs/meta-helper.js.map +1 -1
  30. package/dist/cjs/test-utils.js +26 -47
  31. package/dist/cjs/test-utils.js.map +1 -1
  32. package/dist/cjs/tsdoc-metadata.json +1 -1
  33. package/dist/cjs/utils/natural-join.js +10 -23
  34. package/dist/cjs/utils/natural-join.js.map +1 -1
  35. package/dist/cjs/vitest.js +6 -6
  36. package/dist/cjs/vitest.js.map +1 -1
  37. package/dist/es/browser.js +2 -2
  38. package/dist/es/cli.js +482 -454
  39. package/dist/es/cli.js.map +1 -1
  40. package/dist/es/core-browser.js +10 -21
  41. package/dist/es/core-browser.js.map +1 -1
  42. package/dist/es/core-nodejs.js +204 -299
  43. package/dist/es/core-nodejs.js.map +1 -1
  44. package/dist/es/core.js +9730 -10455
  45. package/dist/es/core.js.map +1 -1
  46. package/dist/es/elements.js +2311 -2296
  47. package/dist/es/elements.js.map +1 -1
  48. package/dist/es/html-validate.js +150 -171
  49. package/dist/es/html-validate.js.map +1 -1
  50. package/dist/es/html5.js.map +1 -1
  51. package/dist/es/index.js +3 -3
  52. package/dist/es/jest-diff.js +11 -21
  53. package/dist/es/jest-diff.js.map +1 -1
  54. package/dist/es/jest.js +8 -8
  55. package/dist/es/jest.js.map +1 -1
  56. package/dist/es/matcher-utils.js +12 -28
  57. package/dist/es/matcher-utils.js.map +1 -1
  58. package/dist/es/matchers-jestonly.js +39 -48
  59. package/dist/es/matchers-jestonly.js.map +1 -1
  60. package/dist/es/matchers.js +196 -196
  61. package/dist/es/matchers.js.map +1 -1
  62. package/dist/es/meta-helper.js +40 -60
  63. package/dist/es/meta-helper.js.map +1 -1
  64. package/dist/es/test-utils.js +26 -47
  65. package/dist/es/test-utils.js.map +1 -1
  66. package/dist/es/utils/natural-join.js +10 -23
  67. package/dist/es/utils/natural-join.js.map +1 -1
  68. package/dist/es/vitest.js +6 -6
  69. package/dist/es/vitest.js.map +1 -1
  70. package/dist/schema/elements.json +6 -0
  71. package/dist/tsdoc-metadata.json +1 -1
  72. package/dist/types/browser.d.ts +78 -32
  73. package/dist/types/index.d.ts +105 -34
  74. package/package.json +15 -15
@@ -2,2309 +2,2324 @@
2
2
 
3
3
  var metaHelper = require('./meta-helper.js');
4
4
 
5
- /* eslint-disable sonarjs/no-duplicate-string -- easier to read without constants */
6
- const { allowedIfAttributeIsPresent, allowedIfAttributeIsAbsent, allowedIfAttributeHasValue, allowedIfParentIsPresent, } = metaHelper.metadataHelper;
5
+ const {
6
+ allowedIfAttributeIsPresent,
7
+ allowedIfAttributeIsAbsent,
8
+ allowedIfAttributeHasValue,
9
+ allowedIfParentIsPresent
10
+ } = metaHelper.metadataHelper;
7
11
  const validId = "/\\S+/";
8
12
  const ReferrerPolicy = [
9
- "",
10
- "no-referrer",
11
- "no-referrer-when-downgrade",
12
- "same-origin",
13
- "origin",
14
- "strict-origin",
15
- "origin-when-cross-origin",
16
- "strict-origin-when-cross-origin",
17
- "unsafe-url",
13
+ "",
14
+ "no-referrer",
15
+ "no-referrer-when-downgrade",
16
+ "same-origin",
17
+ "origin",
18
+ "strict-origin",
19
+ "origin-when-cross-origin",
20
+ "strict-origin-when-cross-origin",
21
+ "unsafe-url"
18
22
  ];
19
23
  var html5 = metaHelper.defineMetadata({
20
- "*": {
21
- attributes: {
22
- contenteditable: {
23
- omit: true,
24
- enum: ["true", "false"],
25
- },
26
- contextmenu: {
27
- deprecated: true,
28
- },
29
- dir: {
30
- enum: ["ltr", "rtl", "auto"],
31
- },
32
- draggable: {
33
- enum: ["true", "false"],
34
- },
35
- hidden: {
36
- boolean: true,
37
- },
38
- id: {
39
- enum: [validId],
40
- },
41
- tabindex: {
42
- enum: ["/-?\\d+/"],
43
- },
44
- },
45
- },
46
- a: {
47
- flow: true,
48
- phrasing: true,
49
- interactive: true,
50
- transparent: true,
51
- attributes: {
52
- charset: {
53
- deprecated: true,
54
- },
55
- coords: {
56
- deprecated: true,
57
- },
58
- datafld: {
59
- deprecated: true,
60
- },
61
- datasrc: {
62
- deprecated: true,
63
- },
64
- download: {
65
- allowed: allowedIfAttributeIsPresent("href"),
66
- omit: true,
67
- enum: ["/.+/"],
68
- },
69
- href: {
70
- enum: ["/.*/"],
71
- },
72
- hreflang: {
73
- allowed: allowedIfAttributeIsPresent("href"),
74
- },
75
- itemprop: {
76
- allowed: allowedIfAttributeIsPresent("href"),
77
- },
78
- methods: {
79
- deprecated: true,
80
- },
81
- name: {
82
- deprecated: true,
83
- },
84
- ping: {
85
- allowed: allowedIfAttributeIsPresent("href"),
86
- },
87
- referrerpolicy: {
88
- allowed: allowedIfAttributeIsPresent("href"),
89
- enum: ReferrerPolicy,
90
- },
91
- rel: {
92
- allowed: allowedIfAttributeIsPresent("href"),
93
- },
94
- shape: {
95
- deprecated: true,
96
- },
97
- target: {
98
- allowed: allowedIfAttributeIsPresent("href"),
99
- enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"],
100
- },
101
- type: {
102
- allowed: allowedIfAttributeIsPresent("href"),
103
- },
104
- urn: {
105
- deprecated: true,
106
- },
107
- },
108
- permittedDescendants: [{ exclude: "@interactive" }],
109
- implicitRole(node) {
110
- return node.hasAttribute("href") ? "link" : null;
111
- },
112
- },
113
- abbr: {
114
- flow: true,
115
- phrasing: true,
116
- permittedContent: ["@phrasing"],
117
- },
118
- acronym: {
119
- deprecated: {
120
- message: "use <abbr> instead",
121
- documentation: "`<abbr>` can be used as a replacement.",
122
- source: "html5",
123
- },
124
- },
125
- address: {
126
- flow: true,
127
- implicitRole() {
128
- return "group";
129
- },
130
- permittedContent: ["@flow"],
131
- permittedDescendants: [{ exclude: ["address", "header", "footer", "@heading", "@sectioning"] }],
132
- },
133
- applet: {
134
- deprecated: {
135
- source: "html5",
136
- },
137
- attributes: {
138
- datafld: {
139
- deprecated: true,
140
- },
141
- datasrc: {
142
- deprecated: true,
143
- },
144
- },
145
- },
146
- area: {
147
- flow: ["isDescendant", "map"],
148
- phrasing: ["isDescendant", "map"],
149
- void: true,
150
- attributes: {
151
- alt: {},
152
- coords: {
153
- allowed(node) {
154
- const attr = node.getAttribute("shape");
155
- if (attr === "default") {
156
- return `cannot be used when "shape" attribute is "default"`;
157
- }
158
- else {
159
- return null;
160
- }
161
- },
162
- },
163
- download: {
164
- allowed: allowedIfAttributeIsPresent("href"),
165
- },
166
- nohref: {
167
- deprecated: true,
168
- },
169
- itemprop: {
170
- allowed: allowedIfAttributeIsPresent("href"),
171
- },
172
- ping: {
173
- allowed: allowedIfAttributeIsPresent("href"),
174
- },
175
- referrerpolicy: {
176
- allowed: allowedIfAttributeIsPresent("href"),
177
- enum: ReferrerPolicy,
178
- },
179
- rel: {
180
- allowed: allowedIfAttributeIsPresent("href"),
181
- },
182
- shape: {
183
- allowed(node, attr) {
184
- const shape = attr !== null && attr !== void 0 ? attr : "rect";
185
- switch (shape) {
186
- case "circ":
187
- case "circle":
188
- case "poly":
189
- case "polygon":
190
- case "rect":
191
- case "rectangle":
192
- return allowedIfAttributeIsPresent("coords")(node, attr);
193
- default:
194
- return null;
195
- }
196
- },
197
- enum: ["rect", "circle", "poly", "default"],
198
- },
199
- target: {
200
- allowed: allowedIfAttributeIsPresent("href"),
201
- enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"],
202
- },
203
- },
204
- implicitRole(node) {
205
- return node.hasAttribute("href") ? "link" : null;
206
- },
207
- requiredAncestors: ["map"],
208
- },
209
- article: {
210
- flow: true,
211
- sectioning: true,
212
- permittedContent: ["@flow"],
213
- permittedDescendants: [{ exclude: ["main"] }],
214
- implicitRole() {
215
- return "article";
216
- },
217
- },
218
- aside: {
219
- flow: true,
220
- sectioning: true,
221
- permittedContent: ["@flow"],
222
- permittedDescendants: [{ exclude: ["main"] }],
223
- implicitRole() {
224
- return "complementary";
225
- },
226
- },
227
- audio: {
228
- flow: true,
229
- phrasing: true,
230
- embedded: true,
231
- interactive: ["hasAttribute", "controls"],
232
- transparent: ["@flow"],
233
- attributes: {
234
- crossorigin: {
235
- omit: true,
236
- enum: ["anonymous", "use-credentials"],
237
- },
238
- itemprop: {
239
- allowed: allowedIfAttributeIsPresent("src"),
240
- },
241
- preload: {
242
- omit: true,
243
- enum: ["none", "metadata", "auto"],
244
- },
245
- },
246
- permittedContent: ["@flow", "track", "source"],
247
- permittedDescendants: [{ exclude: ["audio", "video"] }],
248
- permittedOrder: ["source", "track", "@flow"],
249
- },
250
- b: {
251
- flow: true,
252
- phrasing: true,
253
- permittedContent: ["@phrasing"],
254
- },
255
- base: {
256
- metadata: true,
257
- void: true,
258
- permittedParent: ["head"],
259
- },
260
- basefont: {
261
- deprecated: {
262
- message: "use CSS instead",
263
- documentation: "Use CSS `font-size` property instead.",
264
- source: "html4",
265
- },
266
- },
267
- bdi: {
268
- flow: true,
269
- phrasing: true,
270
- permittedContent: ["@phrasing"],
271
- },
272
- bdo: {
273
- flow: true,
274
- phrasing: true,
275
- permittedContent: ["@phrasing"],
276
- },
277
- bgsound: {
278
- deprecated: {
279
- message: "use <audio> instead",
280
- documentation: "Use the `<audio>` element instead but consider accessibility concerns with autoplaying sounds.",
281
- source: "non-standard",
282
- },
283
- },
284
- big: {
285
- deprecated: {
286
- message: "use CSS instead",
287
- documentation: "Use CSS `font-size` property instead.",
288
- source: "html5",
289
- },
290
- },
291
- blink: {
292
- deprecated: {
293
- documentation: "`<blink>` has no direct replacement and blinking text is frowned upon by accessibility standards.",
294
- source: "non-standard",
295
- },
296
- },
297
- blockquote: {
298
- flow: true,
299
- sectioning: true,
300
- implicitRole() {
301
- return "blockquote";
302
- },
303
- permittedContent: ["@flow"],
304
- },
305
- body: {
306
- permittedContent: ["@flow"],
307
- permittedParent: ["html"],
308
- attributes: {
309
- alink: {
310
- deprecated: true,
311
- },
312
- background: {
313
- deprecated: true,
314
- },
315
- bgcolor: {
316
- deprecated: true,
317
- },
318
- link: {
319
- deprecated: true,
320
- },
321
- marginbottom: {
322
- deprecated: true,
323
- },
324
- marginheight: {
325
- deprecated: true,
326
- },
327
- marginleft: {
328
- deprecated: true,
329
- },
330
- marginright: {
331
- deprecated: true,
332
- },
333
- margintop: {
334
- deprecated: true,
335
- },
336
- marginwidth: {
337
- deprecated: true,
338
- },
339
- text: {
340
- deprecated: true,
341
- },
342
- vlink: {
343
- deprecated: true,
344
- },
345
- },
346
- },
347
- br: {
348
- flow: true,
349
- phrasing: true,
350
- void: true,
351
- attributes: {
352
- clear: {
353
- deprecated: true,
354
- },
355
- },
356
- },
357
- button: {
358
- flow: true,
359
- phrasing: true,
360
- interactive: true,
361
- formAssociated: {
362
- listed: true,
363
- },
364
- labelable: true,
365
- attributes: {
366
- autofocus: {
367
- boolean: true,
368
- },
369
- datafld: {
370
- deprecated: true,
371
- },
372
- dataformatas: {
373
- deprecated: true,
374
- },
375
- datasrc: {
376
- deprecated: true,
377
- },
378
- disabled: {
379
- boolean: true,
380
- },
381
- formaction: {
382
- allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
383
- },
384
- formenctype: {
385
- allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
386
- },
387
- formmethod: {
388
- allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
389
- enum: ["get", "post", "dialog"],
390
- },
391
- formnovalidate: {
392
- allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
393
- boolean: true,
394
- },
395
- formtarget: {
396
- allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
397
- enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"],
398
- },
399
- type: {
400
- enum: ["submit", "reset", "button"],
401
- },
402
- },
403
- implicitRole() {
404
- return "button";
405
- },
406
- permittedContent: ["@phrasing"],
407
- permittedDescendants: [{ exclude: ["@interactive"] }],
408
- textContent: "accessible",
409
- },
410
- canvas: {
411
- flow: true,
412
- phrasing: true,
413
- embedded: true,
414
- transparent: true,
415
- },
416
- caption: {
417
- permittedContent: ["@flow"],
418
- permittedDescendants: [{ exclude: ["table"] }],
419
- attributes: {
420
- align: {
421
- deprecated: true,
422
- },
423
- },
424
- },
425
- center: {
426
- deprecated: {
427
- message: "use CSS instead",
428
- documentation: "Use the CSS `text-align` or `margin: auto` properties instead.",
429
- source: "html4",
430
- },
431
- },
432
- cite: {
433
- flow: true,
434
- phrasing: true,
435
- permittedContent: ["@phrasing"],
436
- },
437
- code: {
438
- flow: true,
439
- phrasing: true,
440
- permittedContent: ["@phrasing"],
441
- },
442
- col: {
443
- attributes: {
444
- align: {
445
- deprecated: true,
446
- },
447
- char: {
448
- deprecated: true,
449
- },
450
- charoff: {
451
- deprecated: true,
452
- },
453
- span: {
454
- enum: ["/\\d+/"],
455
- },
456
- valign: {
457
- deprecated: true,
458
- },
459
- width: {
460
- deprecated: true,
461
- },
462
- },
463
- void: true,
464
- },
465
- colgroup: {
466
- implicitClosed: ["colgroup"],
467
- attributes: {
468
- span: {
469
- enum: ["/\\d+/"],
470
- },
471
- },
472
- permittedContent: ["col", "template"],
473
- },
474
- data: {
475
- flow: true,
476
- phrasing: true,
477
- permittedContent: ["@phrasing"],
478
- },
479
- datalist: {
480
- flow: true,
481
- phrasing: true,
482
- implicitRole() {
483
- return "listbox";
484
- },
485
- permittedContent: ["@phrasing", "option"],
486
- },
487
- dd: {
488
- implicitClosed: ["dd", "dt"],
489
- permittedContent: ["@flow"],
490
- requiredAncestors: ["dl > dd", "dl > div > dd"],
491
- },
492
- del: {
493
- flow: true,
494
- phrasing: true,
495
- transparent: true,
496
- },
497
- details: {
498
- flow: true,
499
- sectioning: true,
500
- interactive: true,
501
- attributes: {
502
- open: {
503
- boolean: true,
504
- },
505
- },
506
- implicitRole() {
507
- return "group";
508
- },
509
- permittedContent: ["summary", "@flow"],
510
- permittedOrder: ["summary", "@flow"],
511
- requiredContent: ["summary"],
512
- },
513
- dfn: {
514
- flow: true,
515
- phrasing: true,
516
- implicitRole() {
517
- return "term";
518
- },
519
- permittedContent: ["@phrasing"],
520
- permittedDescendants: [{ exclude: ["dfn"] }],
521
- },
522
- dialog: {
523
- flow: true,
524
- permittedContent: ["@flow"],
525
- attributes: {
526
- open: {
527
- boolean: true,
528
- },
529
- },
530
- implicitRole() {
531
- return "dialog";
532
- },
533
- },
534
- dir: {
535
- deprecated: {
536
- documentation: "The non-standard `<dir>` element has no direct replacement but MDN recommends replacing with `<ul>` and CSS.",
537
- source: "html4",
538
- },
539
- },
540
- div: {
541
- flow: true,
542
- permittedContent: ["@flow", "dt", "dd"],
543
- attributes: {
544
- align: {
545
- deprecated: true,
546
- },
547
- datafld: {
548
- deprecated: true,
549
- },
550
- dataformatas: {
551
- deprecated: true,
552
- },
553
- datasrc: {
554
- deprecated: true,
555
- },
556
- },
557
- },
558
- dl: {
559
- flow: true,
560
- permittedContent: ["@script", "dt", "dd", "div"],
561
- attributes: {
562
- compact: {
563
- deprecated: true,
564
- },
565
- },
566
- },
567
- dt: {
568
- implicitClosed: ["dd", "dt"],
569
- permittedContent: ["@flow"],
570
- permittedDescendants: [{ exclude: ["header", "footer", "@sectioning", "@heading"] }],
571
- requiredAncestors: ["dl > dt", "dl > div > dt"],
572
- },
573
- em: {
574
- flow: true,
575
- phrasing: true,
576
- permittedContent: ["@phrasing"],
577
- },
578
- embed: {
579
- flow: true,
580
- phrasing: true,
581
- embedded: true,
582
- interactive: true,
583
- void: true,
584
- attributes: {
585
- src: {
586
- required: true,
587
- enum: ["/.+/"],
588
- },
589
- title: {
590
- required: true,
591
- },
592
- },
593
- },
594
- fieldset: {
595
- flow: true,
596
- formAssociated: {
597
- listed: true,
598
- },
599
- attributes: {
600
- datafld: {
601
- deprecated: true,
602
- },
603
- disabled: {
604
- boolean: true,
605
- },
606
- },
607
- implicitRole() {
608
- return "group";
609
- },
610
- permittedContent: ["@flow", "legend?"],
611
- permittedOrder: ["legend", "@flow"],
612
- },
613
- figcaption: {
614
- permittedContent: ["@flow"],
615
- },
616
- figure: {
617
- flow: true,
618
- implicitRole() {
619
- return "figure";
620
- },
621
- permittedContent: ["@flow", "figcaption?"],
622
- permittedOrder: ["figcaption", "@flow", "figcaption"],
623
- },
624
- font: {
625
- deprecated: {
626
- message: "use CSS instead",
627
- documentation: "Use CSS font properties instead.",
628
- source: "html4",
629
- },
630
- },
631
- footer: {
632
- flow: true,
633
- implicitRole(node) {
634
- const selectors = [
635
- "article",
636
- "aside",
637
- "main",
638
- "nav",
639
- "section",
640
- '[role="article"]',
641
- '[role="complementary"]',
642
- '[role="main"]',
643
- '[role="navigation"]',
644
- '[role="region"]',
645
- ];
646
- if (node.closest(selectors.join(","))) {
647
- return null;
648
- }
649
- else {
650
- return "contentinfo";
651
- }
652
- },
653
- permittedContent: ["@flow"],
654
- permittedDescendants: [{ exclude: ["header", "footer", "main"] }],
655
- },
656
- form: {
657
- flow: true,
658
- form: true,
659
- attributes: {
660
- action: {
661
- enum: [/^\s*\S+\s*$/],
662
- },
663
- accept: {
664
- deprecated: true,
665
- },
666
- autocomplete: {
667
- enum: ["on", "off"],
668
- },
669
- method: {
670
- enum: ["get", "post", "dialog"],
671
- },
672
- novalidate: {
673
- boolean: true,
674
- },
675
- target: {
676
- enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"],
677
- },
678
- },
679
- implicitRole() {
680
- return "form";
681
- },
682
- permittedContent: ["@flow"],
683
- permittedDescendants: [{ exclude: ["@form"] }],
684
- },
685
- frame: {
686
- deprecated: {
687
- documentation: "The `<frame>` element can be replaced with the `<iframe>` element but a better solution is to remove usage of frames entirely.",
688
- source: "html5",
689
- },
690
- attributes: {
691
- datafld: {
692
- deprecated: true,
693
- },
694
- datasrc: {
695
- deprecated: true,
696
- },
697
- title: {
698
- required: true,
699
- },
700
- },
701
- },
702
- frameset: {
703
- deprecated: {
704
- documentation: "The `<frameset>` element can be replaced with the `<iframe>` element but a better solution is to remove usage of frames entirely.",
705
- source: "html5",
706
- },
707
- },
708
- h1: {
709
- flow: true,
710
- heading: true,
711
- permittedContent: ["@phrasing"],
712
- attributes: {
713
- align: {
714
- deprecated: true,
715
- },
716
- },
717
- implicitRole() {
718
- return "heading";
719
- },
720
- },
721
- h2: {
722
- flow: true,
723
- heading: true,
724
- permittedContent: ["@phrasing"],
725
- attributes: {
726
- align: {
727
- deprecated: true,
728
- },
729
- },
730
- implicitRole() {
731
- return "heading";
732
- },
733
- },
734
- h3: {
735
- flow: true,
736
- heading: true,
737
- permittedContent: ["@phrasing"],
738
- attributes: {
739
- align: {
740
- deprecated: true,
741
- },
742
- },
743
- implicitRole() {
744
- return "heading";
745
- },
746
- },
747
- h4: {
748
- flow: true,
749
- heading: true,
750
- permittedContent: ["@phrasing"],
751
- attributes: {
752
- align: {
753
- deprecated: true,
754
- },
755
- },
756
- implicitRole() {
757
- return "heading";
758
- },
759
- },
760
- h5: {
761
- flow: true,
762
- heading: true,
763
- permittedContent: ["@phrasing"],
764
- attributes: {
765
- align: {
766
- deprecated: true,
767
- },
768
- },
769
- implicitRole() {
770
- return "heading";
771
- },
772
- },
773
- h6: {
774
- flow: true,
775
- heading: true,
776
- permittedContent: ["@phrasing"],
777
- attributes: {
778
- align: {
779
- deprecated: true,
780
- },
781
- },
782
- implicitRole() {
783
- return "heading";
784
- },
785
- },
786
- head: {
787
- permittedContent: ["base?", "title?", "@meta"],
788
- permittedParent: ["html"],
789
- requiredContent: ["title"],
790
- attributes: {
791
- profile: {
792
- deprecated: true,
793
- },
794
- },
795
- },
796
- header: {
797
- flow: true,
798
- implicitRole(node) {
799
- const selectors = [
800
- "article",
801
- "aside",
802
- "main",
803
- "nav",
804
- "section",
805
- '[role="article"]',
806
- '[role="complementary"]',
807
- '[role="main"]',
808
- '[role="navigation"]',
809
- '[role="region"]',
810
- ];
811
- if (node.closest(selectors.join(","))) {
812
- return null;
813
- }
814
- else {
815
- return "banner";
816
- }
817
- },
818
- permittedContent: ["@flow"],
819
- permittedDescendants: [{ exclude: ["header", "footer", "main"] }],
820
- },
821
- hgroup: {
822
- flow: true,
823
- heading: true,
824
- permittedContent: ["p", "@heading?"],
825
- permittedDescendants: [{ exclude: ["hgroup"] }],
826
- requiredContent: ["@heading"],
827
- },
828
- hr: {
829
- flow: true,
830
- void: true,
831
- attributes: {
832
- align: {
833
- deprecated: true,
834
- },
835
- color: {
836
- deprecated: true,
837
- },
838
- noshade: {
839
- deprecated: true,
840
- },
841
- size: {
842
- deprecated: true,
843
- },
844
- width: {
845
- deprecated: true,
846
- },
847
- },
848
- implicitRole() {
849
- return "separator";
850
- },
851
- },
852
- html: {
853
- permittedContent: ["head?", "body?"],
854
- permittedOrder: ["head", "body"],
855
- requiredContent: ["head", "body"],
856
- attributes: {
857
- lang: {
858
- required: true,
859
- },
860
- version: {
861
- deprecated: true,
862
- },
863
- },
864
- implicitRole() {
865
- return "document";
866
- },
867
- },
868
- i: {
869
- flow: true,
870
- phrasing: true,
871
- permittedContent: ["@phrasing"],
872
- },
873
- iframe: {
874
- flow: true,
875
- phrasing: true,
876
- embedded: true,
877
- interactive: true,
878
- attributes: {
879
- align: {
880
- deprecated: true,
881
- },
882
- allowtransparency: {
883
- deprecated: true,
884
- },
885
- datafld: {
886
- deprecated: true,
887
- },
888
- datasrc: {
889
- deprecated: true,
890
- },
891
- frameborder: {
892
- deprecated: true,
893
- },
894
- hspace: {
895
- deprecated: true,
896
- },
897
- marginheight: {
898
- deprecated: true,
899
- },
900
- marginwidth: {
901
- deprecated: true,
902
- },
903
- referrerpolicy: {
904
- enum: ReferrerPolicy,
905
- },
906
- scrolling: {
907
- deprecated: true,
908
- },
909
- src: {
910
- enum: ["/.+/"],
911
- },
912
- title: {
913
- required: true,
914
- },
915
- vspace: {
916
- deprecated: true,
917
- },
918
- },
919
- permittedContent: [],
920
- },
921
- img: {
922
- flow: true,
923
- phrasing: true,
924
- embedded: true,
925
- interactive: ["hasAttribute", "usemap"],
926
- void: true,
927
- attributes: {
928
- align: {
929
- deprecated: true,
930
- },
931
- border: {
932
- deprecated: true,
933
- },
934
- crossorigin: {
935
- omit: true,
936
- enum: ["anonymous", "use-credentials"],
937
- },
938
- datafld: {
939
- deprecated: true,
940
- },
941
- datasrc: {
942
- deprecated: true,
943
- },
944
- decoding: {
945
- enum: ["sync", "async", "auto"],
946
- },
947
- hspace: {
948
- deprecated: true,
949
- },
950
- ismap: {
951
- boolean: true,
952
- },
953
- lowsrc: {
954
- deprecated: true,
955
- },
956
- name: {
957
- deprecated: true,
958
- },
959
- referrerpolicy: {
960
- enum: ReferrerPolicy,
961
- },
962
- src: {
963
- required: true,
964
- enum: ["/.+/"],
965
- },
966
- srcset: {
967
- enum: ["/[^]+/"],
968
- },
969
- vspace: {
970
- deprecated: true,
971
- },
972
- },
973
- implicitRole(node) {
974
- const alt = node.getAttribute("alt");
975
- if (alt === "") {
976
- return "presentation";
977
- }
978
- else {
979
- return "img";
980
- }
981
- },
982
- },
983
- input: {
984
- flow: true,
985
- phrasing: true,
986
- interactive: ["matchAttribute", ["type", "!=", "hidden"]],
987
- void: true,
988
- formAssociated: {
989
- listed: true,
990
- },
991
- labelable: ["matchAttribute", ["type", "!=", "hidden"]],
992
- attributes: {
993
- align: {
994
- deprecated: true,
995
- },
996
- autofocus: {
997
- boolean: true,
998
- },
999
- capture: {
1000
- omit: true,
1001
- enum: ["environment", "user"],
1002
- },
1003
- checked: {
1004
- boolean: true,
1005
- },
1006
- datafld: {
1007
- deprecated: true,
1008
- },
1009
- dataformatas: {
1010
- deprecated: true,
1011
- },
1012
- datasrc: {
1013
- deprecated: true,
1014
- },
1015
- disabled: {
1016
- boolean: true,
1017
- },
1018
- formaction: {
1019
- allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1020
- defaultValue: "submit",
1021
- }),
1022
- },
1023
- formenctype: {
1024
- allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1025
- defaultValue: "submit",
1026
- }),
1027
- },
1028
- formmethod: {
1029
- allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1030
- defaultValue: "submit",
1031
- }),
1032
- enum: ["get", "post", "dialog"],
1033
- },
1034
- formnovalidate: {
1035
- allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1036
- defaultValue: "submit",
1037
- }),
1038
- boolean: true,
1039
- },
1040
- formtarget: {
1041
- allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1042
- defaultValue: "submit",
1043
- }),
1044
- enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"],
1045
- },
1046
- hspace: {
1047
- deprecated: true,
1048
- },
1049
- inputmode: {
1050
- enum: ["none", "text", "decimal", "numeric", "tel", "search", "email", "url"],
1051
- },
1052
- ismap: {
1053
- deprecated: true,
1054
- },
1055
- multiple: {
1056
- boolean: true,
1057
- },
1058
- readonly: {
1059
- boolean: true,
1060
- },
1061
- required: {
1062
- boolean: true,
1063
- },
1064
- spellcheck: {
1065
- enum: ["default", "false", "true"],
1066
- },
1067
- type: {
1068
- required: true,
1069
- enum: [
1070
- "button",
1071
- "checkbox",
1072
- "color",
1073
- "date",
1074
- "datetime-local",
1075
- "email",
1076
- "file",
1077
- "hidden",
1078
- "image",
1079
- "month",
1080
- "number",
1081
- "password",
1082
- "radio",
1083
- "range",
1084
- "reset",
1085
- "search",
1086
- "submit",
1087
- "tel",
1088
- "text",
1089
- "time",
1090
- "url",
1091
- "week",
1092
- ],
1093
- },
1094
- usemap: {
1095
- deprecated: true,
1096
- },
1097
- vspace: {
1098
- deprecated: true,
1099
- },
1100
- },
1101
- /* eslint-disable-next-line complexity -- the standard is complicated */
1102
- implicitRole(node) {
1103
- const list = node.hasAttribute("list");
1104
- if (list) {
1105
- return "combobox";
1106
- }
1107
- const type = node.getAttribute("type");
1108
- switch (type) {
1109
- case "button":
1110
- return "button";
1111
- case "checkbox":
1112
- return "checkbox";
1113
- case "email":
1114
- return "textbox";
1115
- case "image":
1116
- return "button";
1117
- case "number":
1118
- return "spinbutton";
1119
- case "radio":
1120
- return "radio";
1121
- case "range":
1122
- return "slider";
1123
- case "reset":
1124
- return "button";
1125
- case "search":
1126
- return "searchbox";
1127
- case "submit":
1128
- return "button";
1129
- case "tel":
1130
- return "textbox";
1131
- case "text":
1132
- return "textbox";
1133
- case "url":
1134
- return "textbox";
1135
- default:
1136
- return "textbox";
1137
- }
1138
- },
1139
- },
1140
- ins: {
1141
- flow: true,
1142
- phrasing: true,
1143
- transparent: true,
1144
- },
1145
- isindex: {
1146
- deprecated: {
1147
- source: "html4",
1148
- },
1149
- },
1150
- kbd: {
1151
- flow: true,
1152
- phrasing: true,
1153
- permittedContent: ["@phrasing"],
1154
- },
1155
- keygen: {
1156
- flow: true,
1157
- phrasing: true,
1158
- interactive: true,
1159
- void: true,
1160
- labelable: true,
1161
- deprecated: true,
1162
- },
1163
- label: {
1164
- flow: true,
1165
- phrasing: true,
1166
- interactive: true,
1167
- permittedContent: ["@phrasing"],
1168
- permittedDescendants: [{ exclude: ["label"] }],
1169
- attributes: {
1170
- datafld: {
1171
- deprecated: true,
1172
- },
1173
- dataformatas: {
1174
- deprecated: true,
1175
- },
1176
- datasrc: {
1177
- deprecated: true,
1178
- },
1179
- for: {
1180
- enum: [validId],
1181
- },
1182
- },
1183
- },
1184
- legend: {
1185
- permittedContent: ["@phrasing", "@heading"],
1186
- attributes: {
1187
- align: {
1188
- deprecated: true,
1189
- },
1190
- datafld: {
1191
- deprecated: true,
1192
- },
1193
- dataformatas: {
1194
- deprecated: true,
1195
- },
1196
- datasrc: {
1197
- deprecated: true,
1198
- },
1199
- },
1200
- },
1201
- li: {
1202
- implicitClosed: ["li"],
1203
- permittedContent: ["@flow"],
1204
- permittedParent: ["ul", "ol", "menu", "template"],
1205
- attributes: {
1206
- type: {
1207
- deprecated: true,
1208
- },
1209
- },
1210
- implicitRole(node) {
1211
- return node.closest("ul, ol, menu") ? "listitem" : null;
1212
- },
1213
- },
1214
- link: {
1215
- metadata: true,
1216
- void: true,
1217
- attributes: {
1218
- as: {
1219
- allowed: allowedIfAttributeHasValue("rel", ["prefetch", "preload", "modulepreload"]),
1220
- enum: [
1221
- "audio",
1222
- "audioworklet",
1223
- "document",
1224
- "embed",
1225
- "fetch",
1226
- "font",
1227
- "frame",
1228
- "iframe",
1229
- "image",
1230
- "manifest",
1231
- "object",
1232
- "paintworklet",
1233
- "report",
1234
- "script",
1235
- "serviceworker",
1236
- "sharedworker",
1237
- "style",
1238
- "track",
1239
- "video",
1240
- "webidentity",
1241
- "worker",
1242
- "xslt",
1243
- ],
1244
- },
1245
- blocking: {
1246
- allowed: allowedIfAttributeHasValue("rel", ["stylesheet", "preload", "modulepreload"]),
1247
- list: true,
1248
- enum: ["render"],
1249
- },
1250
- charset: {
1251
- deprecated: true,
1252
- },
1253
- crossorigin: {
1254
- omit: true,
1255
- enum: ["anonymous", "use-credentials"],
1256
- },
1257
- disabled: {
1258
- allowed: allowedIfAttributeHasValue("rel", ["stylesheet"]),
1259
- boolean: true,
1260
- },
1261
- href: {
1262
- required: true,
1263
- enum: ["/.+/"],
1264
- },
1265
- integrity: {
1266
- allowed: allowedIfAttributeHasValue("rel", ["stylesheet", "preload", "modulepreload"]),
1267
- enum: ["/.+/"],
1268
- },
1269
- methods: {
1270
- deprecated: true,
1271
- },
1272
- referrerpolicy: {
1273
- enum: ReferrerPolicy,
1274
- },
1275
- target: {
1276
- deprecated: true,
1277
- },
1278
- urn: {
1279
- deprecated: true,
1280
- },
1281
- },
1282
- },
1283
- listing: {
1284
- deprecated: {
1285
- source: "html32",
1286
- },
1287
- },
1288
- main: {
1289
- flow: true,
1290
- implicitRole() {
1291
- return "main";
1292
- },
1293
- },
1294
- map: {
1295
- flow: true,
1296
- phrasing: true,
1297
- transparent: true,
1298
- attributes: {
1299
- name: {
1300
- required: true,
1301
- enum: ["/\\S+/"],
1302
- },
1303
- },
1304
- },
1305
- mark: {
1306
- flow: true,
1307
- phrasing: true,
1308
- permittedContent: ["@phrasing"],
1309
- },
1310
- marquee: {
1311
- deprecated: {
1312
- documentation: "Marked as obsolete by both W3C and WHATWG standards but still implemented in most browsers. Animated text should be avoided for accessibility reasons as well.",
1313
- source: "html5",
1314
- },
1315
- attributes: {
1316
- datafld: {
1317
- deprecated: true,
1318
- },
1319
- dataformatas: {
1320
- deprecated: true,
1321
- },
1322
- datasrc: {
1323
- deprecated: true,
1324
- },
1325
- },
1326
- },
1327
- math: {
1328
- flow: true,
1329
- foreign: true,
1330
- phrasing: true,
1331
- embedded: true,
1332
- attributes: {
1333
- align: {
1334
- deprecated: true,
1335
- },
1336
- dir: {
1337
- enum: ["ltr", "rtl"],
1338
- },
1339
- display: {
1340
- enum: ["block", "inline"],
1341
- },
1342
- hspace: {
1343
- deprecated: true,
1344
- },
1345
- name: {
1346
- deprecated: true,
1347
- },
1348
- overflow: {
1349
- enum: ["linebreak", "scroll", "elide", "truncate", "scale"],
1350
- },
1351
- vspace: {
1352
- deprecated: true,
1353
- },
1354
- },
1355
- implicitRole() {
1356
- return "math";
1357
- },
1358
- },
1359
- menu: {
1360
- flow: true,
1361
- implicitRole() {
1362
- return "list";
1363
- },
1364
- permittedContent: ["@script", "li"],
1365
- },
1366
- meta: {
1367
- flow: ["hasAttribute", "itemprop"],
1368
- phrasing: ["hasAttribute", "itemprop"],
1369
- metadata: true,
1370
- void: true,
1371
- attributes: {
1372
- charset: {
1373
- enum: ["utf-8"],
1374
- },
1375
- content: {
1376
- allowed: allowedIfAttributeIsPresent("name", "http-equiv", "itemprop", "property"),
1377
- },
1378
- itemprop: {
1379
- allowed: allowedIfAttributeIsAbsent("http-equiv", "name"),
1380
- },
1381
- name: {
1382
- allowed: allowedIfAttributeIsAbsent("http-equiv", "itemprop"),
1383
- },
1384
- "http-equiv": {
1385
- allowed: allowedIfAttributeIsAbsent("name", "itemprop"),
1386
- },
1387
- scheme: {
1388
- deprecated: true,
1389
- },
1390
- },
1391
- },
1392
- meter: {
1393
- flow: true,
1394
- phrasing: true,
1395
- labelable: true,
1396
- implicitRole() {
1397
- return "meter";
1398
- },
1399
- permittedContent: ["@phrasing"],
1400
- permittedDescendants: [{ exclude: "meter" }],
1401
- },
1402
- multicol: {
1403
- deprecated: {
1404
- message: "use CSS instead",
1405
- documentation: "Use CSS columns instead.",
1406
- source: "html5",
1407
- },
1408
- },
1409
- nav: {
1410
- flow: true,
1411
- sectioning: true,
1412
- implicitRole() {
1413
- return "navigation";
1414
- },
1415
- permittedContent: ["@flow"],
1416
- permittedDescendants: [{ exclude: "main" }],
1417
- },
1418
- nextid: {
1419
- deprecated: {
1420
- source: "html32",
1421
- },
1422
- },
1423
- nobr: {
1424
- deprecated: {
1425
- message: "use CSS instead",
1426
- documentation: "Use CSS `white-space` property instead.",
1427
- source: "non-standard",
1428
- },
1429
- },
1430
- noembed: {
1431
- deprecated: {
1432
- source: "non-standard",
1433
- },
1434
- },
1435
- noframes: {
1436
- deprecated: {
1437
- source: "html5",
1438
- },
1439
- },
1440
- noscript: {
1441
- metadata: true,
1442
- flow: true,
1443
- phrasing: true,
1444
- transparent: true,
1445
- permittedDescendants: [{ exclude: "noscript" }],
1446
- },
1447
- object: {
1448
- flow: true,
1449
- phrasing: true,
1450
- embedded: true,
1451
- interactive: ["hasAttribute", "usemap"],
1452
- transparent: true,
1453
- formAssociated: {
1454
- listed: true,
1455
- },
1456
- attributes: {
1457
- align: {
1458
- deprecated: true,
1459
- },
1460
- archive: {
1461
- deprecated: true,
1462
- },
1463
- blocking: {
1464
- list: true,
1465
- enum: ["render"],
1466
- },
1467
- border: {
1468
- deprecated: true,
1469
- },
1470
- classid: {
1471
- deprecated: true,
1472
- },
1473
- code: {
1474
- deprecated: true,
1475
- },
1476
- codebase: {
1477
- deprecated: true,
1478
- },
1479
- codetype: {
1480
- deprecated: true,
1481
- },
1482
- data: {
1483
- enum: ["/.+/"],
1484
- required: true,
1485
- },
1486
- datafld: {
1487
- deprecated: true,
1488
- },
1489
- dataformatas: {
1490
- deprecated: true,
1491
- },
1492
- datasrc: {
1493
- deprecated: true,
1494
- },
1495
- declare: {
1496
- deprecated: true,
1497
- },
1498
- hspace: {
1499
- deprecated: true,
1500
- },
1501
- name: {
1502
- enum: ["/[^_].*/"],
1503
- },
1504
- standby: {
1505
- deprecated: true,
1506
- },
1507
- vspace: {
1508
- deprecated: true,
1509
- },
1510
- },
1511
- permittedContent: ["param", "@flow"],
1512
- permittedOrder: ["param", "@flow"],
1513
- },
1514
- ol: {
1515
- flow: true,
1516
- attributes: {
1517
- compact: {
1518
- deprecated: true,
1519
- },
1520
- reversed: {
1521
- boolean: true,
1522
- },
1523
- type: {
1524
- enum: ["a", "A", "i", "I", "1"],
1525
- },
1526
- },
1527
- implicitRole() {
1528
- return "list";
1529
- },
1530
- permittedContent: ["@script", "li"],
1531
- },
1532
- optgroup: {
1533
- implicitClosed: ["optgroup"],
1534
- attributes: {
1535
- disabled: {
1536
- boolean: true,
1537
- },
1538
- },
1539
- implicitRole() {
1540
- return "group";
1541
- },
1542
- permittedContent: ["@script", "option"],
1543
- },
1544
- option: {
1545
- implicitClosed: ["option"],
1546
- attributes: {
1547
- dataformatas: {
1548
- deprecated: true,
1549
- },
1550
- datasrc: {
1551
- deprecated: true,
1552
- },
1553
- disabled: {
1554
- boolean: true,
1555
- },
1556
- name: {
1557
- deprecated: true,
1558
- },
1559
- selected: {
1560
- boolean: true,
1561
- },
1562
- },
1563
- implicitRole() {
1564
- return "option";
1565
- },
1566
- permittedContent: [],
1567
- },
1568
- output: {
1569
- flow: true,
1570
- phrasing: true,
1571
- formAssociated: {
1572
- listed: true,
1573
- },
1574
- labelable: true,
1575
- implicitRole() {
1576
- return "status";
1577
- },
1578
- permittedContent: ["@phrasing"],
1579
- },
1580
- p: {
1581
- flow: true,
1582
- implicitClosed: [
1583
- "address",
1584
- "article",
1585
- "aside",
1586
- "blockquote",
1587
- "div",
1588
- "dl",
1589
- "fieldset",
1590
- "footer",
1591
- "form",
1592
- "h1",
1593
- "h2",
1594
- "h3",
1595
- "h4",
1596
- "h5",
1597
- "h6",
1598
- "header",
1599
- "hgroup",
1600
- "hr",
1601
- "main",
1602
- "nav",
1603
- "ol",
1604
- "p",
1605
- "pre",
1606
- "section",
1607
- "table",
1608
- "ul",
1609
- ],
1610
- permittedContent: ["@phrasing"],
1611
- attributes: {
1612
- align: {
1613
- deprecated: true,
1614
- },
1615
- },
1616
- },
1617
- param: {
1618
- void: true,
1619
- attributes: {
1620
- datafld: {
1621
- deprecated: true,
1622
- },
1623
- type: {
1624
- deprecated: true,
1625
- },
1626
- valuetype: {
1627
- deprecated: true,
1628
- },
1629
- },
1630
- },
1631
- picture: {
1632
- flow: true,
1633
- phrasing: true,
1634
- embedded: true,
1635
- permittedContent: ["@script", "source", "img"],
1636
- permittedOrder: ["source", "img"],
1637
- },
1638
- plaintext: {
1639
- deprecated: {
1640
- message: "use <pre> or CSS instead",
1641
- documentation: "Use the `<pre>` element or use CSS to set a monospace font.",
1642
- source: "html2",
1643
- },
1644
- },
1645
- pre: {
1646
- flow: true,
1647
- permittedContent: ["@phrasing"],
1648
- attributes: {
1649
- width: {
1650
- deprecated: true,
1651
- },
1652
- },
1653
- },
1654
- progress: {
1655
- flow: true,
1656
- phrasing: true,
1657
- labelable: true,
1658
- implicitRole() {
1659
- return "progressbar";
1660
- },
1661
- permittedContent: ["@phrasing"],
1662
- permittedDescendants: [{ exclude: "progress" }],
1663
- },
1664
- q: {
1665
- flow: true,
1666
- phrasing: true,
1667
- permittedContent: ["@phrasing"],
1668
- },
1669
- rb: {
1670
- implicitClosed: ["rb", "rt", "rtc", "rp"],
1671
- permittedContent: ["@phrasing"],
1672
- },
1673
- rp: {
1674
- implicitClosed: ["rb", "rt", "rtc", "rp"],
1675
- permittedContent: ["@phrasing"],
1676
- },
1677
- rt: {
1678
- implicitClosed: ["rb", "rt", "rtc", "rp"],
1679
- permittedContent: ["@phrasing"],
1680
- },
1681
- rtc: {
1682
- implicitClosed: ["rb", "rtc", "rp"],
1683
- permittedContent: ["@phrasing", "rt"],
1684
- },
1685
- ruby: {
1686
- flow: true,
1687
- phrasing: true,
1688
- permittedContent: ["@phrasing", "rb", "rp", "rt", "rtc"],
1689
- },
1690
- s: {
1691
- flow: true,
1692
- phrasing: true,
1693
- permittedContent: ["@phrasing"],
1694
- },
1695
- samp: {
1696
- flow: true,
1697
- phrasing: true,
1698
- permittedContent: ["@phrasing"],
1699
- },
1700
- script: {
1701
- metadata: true,
1702
- flow: true,
1703
- phrasing: true,
1704
- scriptSupporting: true,
1705
- attributes: {
1706
- async: {
1707
- boolean: true,
1708
- },
1709
- crossorigin: {
1710
- omit: true,
1711
- enum: ["anonymous", "use-credentials"],
1712
- },
1713
- defer: {
1714
- boolean: true,
1715
- },
1716
- event: {
1717
- deprecated: true,
1718
- },
1719
- for: {
1720
- deprecated: true,
1721
- },
1722
- integrity: {
1723
- allowed: allowedIfAttributeIsPresent("src"),
1724
- enum: ["/.+/"],
1725
- },
1726
- language: {
1727
- deprecated: true,
1728
- },
1729
- nomodule: {
1730
- boolean: true,
1731
- },
1732
- referrerpolicy: {
1733
- enum: ReferrerPolicy,
1734
- },
1735
- src: {
1736
- enum: ["/.+/"],
1737
- },
1738
- },
1739
- },
1740
- search: {
1741
- flow: true,
1742
- implicitRole() {
1743
- return "search";
1744
- },
1745
- },
1746
- section: {
1747
- flow: true,
1748
- sectioning: true,
1749
- implicitRole() {
1750
- return "region";
1751
- },
1752
- permittedContent: ["@flow"],
1753
- },
1754
- select: {
1755
- flow: true,
1756
- phrasing: true,
1757
- interactive: true,
1758
- formAssociated: {
1759
- listed: true,
1760
- },
1761
- labelable: true,
1762
- attributes: {
1763
- autofocus: {
1764
- boolean: true,
1765
- },
1766
- disabled: {
1767
- boolean: true,
1768
- },
1769
- multiple: {
1770
- boolean: true,
1771
- },
1772
- required: {
1773
- boolean: true,
1774
- },
1775
- size: {
1776
- enum: ["/\\d+/"],
1777
- },
1778
- },
1779
- implicitRole(node) {
1780
- const multiple = node.hasAttribute("multiple");
1781
- if (multiple) {
1782
- return "listbox";
1783
- }
1784
- const size = node.getAttribute("size");
1785
- if (typeof size === "string") {
1786
- const parsed = parseInt(size, 10);
1787
- if (parsed > 1) {
1788
- return "listbox";
1789
- }
1790
- }
1791
- return "combobox";
1792
- },
1793
- permittedContent: ["@script", "datasrc", "datafld", "dataformatas", "option", "optgroup"],
1794
- },
1795
- slot: {
1796
- flow: true,
1797
- phrasing: true,
1798
- transparent: true,
1799
- },
1800
- small: {
1801
- flow: true,
1802
- phrasing: true,
1803
- permittedContent: ["@phrasing"],
1804
- },
1805
- source: {
1806
- void: true,
1807
- attributes: {
1808
- type: {},
1809
- media: {},
1810
- src: {
1811
- allowed: allowedIfParentIsPresent("audio", "video"),
1812
- },
1813
- srcset: {
1814
- allowed: allowedIfParentIsPresent("picture"),
1815
- },
1816
- sizes: {
1817
- allowed: allowedIfParentIsPresent("picture"),
1818
- },
1819
- width: {
1820
- allowed: allowedIfParentIsPresent("picture"),
1821
- enum: ["/\\d+/"],
1822
- },
1823
- height: {
1824
- allowed: allowedIfParentIsPresent("picture"),
1825
- enum: ["/\\d+/"],
1826
- },
1827
- },
1828
- },
1829
- spacer: {
1830
- deprecated: {
1831
- message: "use CSS instead",
1832
- documentation: "Use CSS margin or padding instead.",
1833
- source: "non-standard",
1834
- },
1835
- },
1836
- span: {
1837
- flow: true,
1838
- phrasing: true,
1839
- permittedContent: ["@phrasing"],
1840
- attributes: {
1841
- datafld: {
1842
- deprecated: true,
1843
- },
1844
- dataformatas: {
1845
- deprecated: true,
1846
- },
1847
- datasrc: {
1848
- deprecated: true,
1849
- },
1850
- },
1851
- },
1852
- strike: {
1853
- deprecated: {
1854
- message: "use <del> or <s> instead",
1855
- documentation: "Use the `<del>` or `<s>` element instead.",
1856
- source: "html5",
1857
- },
1858
- },
1859
- strong: {
1860
- flow: true,
1861
- phrasing: true,
1862
- permittedContent: ["@phrasing"],
1863
- },
1864
- style: {
1865
- metadata: true,
1866
- },
1867
- sub: {
1868
- flow: true,
1869
- phrasing: true,
1870
- permittedContent: ["@phrasing"],
1871
- },
1872
- summary: {
1873
- permittedContent: ["@phrasing", "@heading"],
1874
- },
1875
- sup: {
1876
- flow: true,
1877
- phrasing: true,
1878
- permittedContent: ["@phrasing"],
1879
- },
1880
- svg: {
1881
- flow: true,
1882
- foreign: true,
1883
- phrasing: true,
1884
- embedded: true,
1885
- },
1886
- /* while not part of HTML 5 specification these two elements are handled as
1887
- * special cases to allow them as accessible text and to avoid issues with
1888
- * "no-unknown-elements" they are added here */
1889
- "svg:desc": {},
1890
- "svg:title": {},
1891
- table: {
1892
- flow: true,
1893
- permittedContent: ["@script", "caption?", "colgroup", "tbody", "tfoot?", "thead?", "tr"],
1894
- permittedOrder: ["caption", "colgroup", "thead", "tbody", "tr", "tfoot"],
1895
- attributes: {
1896
- align: {
1897
- deprecated: true,
1898
- },
1899
- background: {
1900
- deprecated: true,
1901
- },
1902
- bgcolor: {
1903
- deprecated: true,
1904
- },
1905
- bordercolor: {
1906
- deprecated: true,
1907
- },
1908
- cellpadding: {
1909
- deprecated: true,
1910
- },
1911
- cellspacing: {
1912
- deprecated: true,
1913
- },
1914
- dataformatas: {
1915
- deprecated: true,
1916
- },
1917
- datapagesize: {
1918
- deprecated: true,
1919
- },
1920
- datasrc: {
1921
- deprecated: true,
1922
- },
1923
- frame: {
1924
- deprecated: true,
1925
- },
1926
- rules: {
1927
- deprecated: true,
1928
- },
1929
- summary: {
1930
- deprecated: true,
1931
- },
1932
- width: {
1933
- deprecated: true,
1934
- },
1935
- },
1936
- implicitRole() {
1937
- return "table";
1938
- },
1939
- },
1940
- tbody: {
1941
- implicitClosed: ["tbody", "tfoot"],
1942
- permittedContent: ["@script", "tr"],
1943
- attributes: {
1944
- align: {
1945
- deprecated: true,
1946
- },
1947
- background: {
1948
- deprecated: true,
1949
- },
1950
- char: {
1951
- deprecated: true,
1952
- },
1953
- charoff: {
1954
- deprecated: true,
1955
- },
1956
- valign: {
1957
- deprecated: true,
1958
- },
1959
- },
1960
- implicitRole() {
1961
- return "rowgroup";
1962
- },
1963
- },
1964
- td: {
1965
- flow: true,
1966
- implicitClosed: ["td", "th"],
1967
- attributes: {
1968
- align: {
1969
- deprecated: true,
1970
- },
1971
- axis: {
1972
- deprecated: true,
1973
- },
1974
- background: {
1975
- deprecated: true,
1976
- },
1977
- bgcolor: {
1978
- deprecated: true,
1979
- },
1980
- char: {
1981
- deprecated: true,
1982
- },
1983
- charoff: {
1984
- deprecated: true,
1985
- },
1986
- colspan: {
1987
- enum: ["/\\d+/"],
1988
- },
1989
- height: {
1990
- deprecated: true,
1991
- },
1992
- nowrap: {
1993
- deprecated: true,
1994
- },
1995
- rowspan: {
1996
- enum: ["/\\d+/"],
1997
- },
1998
- scope: {
1999
- deprecated: true,
2000
- },
2001
- valign: {
2002
- deprecated: true,
2003
- },
2004
- width: {
2005
- deprecated: true,
2006
- },
2007
- },
2008
- implicitRole(node) {
2009
- if (node.closest('table[role="grid"], table[role="treegrid"]')) {
2010
- return "gridcell";
2011
- }
2012
- else if (node.closest("table")) {
2013
- return "cell";
2014
- }
2015
- else {
2016
- return null;
2017
- }
2018
- },
2019
- permittedContent: ["@flow"],
2020
- },
2021
- template: {
2022
- metadata: true,
2023
- flow: true,
2024
- phrasing: true,
2025
- scriptSupporting: true,
2026
- },
2027
- textarea: {
2028
- flow: true,
2029
- phrasing: true,
2030
- interactive: true,
2031
- formAssociated: {
2032
- listed: true,
2033
- },
2034
- labelable: true,
2035
- attributes: {
2036
- autocomplete: {
2037
- enum: ["on", "off"],
2038
- },
2039
- autofocus: {
2040
- boolean: true,
2041
- },
2042
- cols: {
2043
- enum: ["/\\d+/"],
2044
- },
2045
- datafld: {
2046
- deprecated: true,
2047
- },
2048
- datasrc: {
2049
- deprecated: true,
2050
- },
2051
- disabled: {
2052
- boolean: true,
2053
- },
2054
- maxlength: {
2055
- enum: ["/\\d+/"],
2056
- },
2057
- minlength: {
2058
- enum: ["/\\d+/"],
2059
- },
2060
- readonly: {
2061
- boolean: true,
2062
- },
2063
- required: {
2064
- boolean: true,
2065
- },
2066
- rows: {
2067
- enum: ["/\\d+/"],
2068
- },
2069
- spellcheck: {
2070
- enum: ["true", "default", "false"],
2071
- },
2072
- wrap: {
2073
- enum: ["hard", "soft"],
2074
- },
2075
- },
2076
- implicitRole() {
2077
- return "textbox";
2078
- },
2079
- permittedContent: [],
2080
- },
2081
- tfoot: {
2082
- implicitClosed: ["tbody"],
2083
- permittedContent: ["@script", "tr"],
2084
- attributes: {
2085
- align: {
2086
- deprecated: true,
2087
- },
2088
- background: {
2089
- deprecated: true,
2090
- },
2091
- char: {
2092
- deprecated: true,
2093
- },
2094
- charoff: {
2095
- deprecated: true,
2096
- },
2097
- valign: {
2098
- deprecated: true,
2099
- },
2100
- },
2101
- implicitRole() {
2102
- return "rowgroup";
2103
- },
2104
- },
2105
- th: {
2106
- flow: true,
2107
- implicitClosed: ["td", "th"],
2108
- attributes: {
2109
- align: {
2110
- deprecated: true,
2111
- },
2112
- axis: {
2113
- deprecated: true,
2114
- },
2115
- background: {
2116
- deprecated: true,
2117
- },
2118
- bgcolor: {
2119
- deprecated: true,
2120
- },
2121
- char: {
2122
- deprecated: true,
2123
- },
2124
- charoff: {
2125
- deprecated: true,
2126
- },
2127
- colspan: {
2128
- enum: ["/\\d+/"],
2129
- },
2130
- height: {
2131
- deprecated: true,
2132
- },
2133
- nowrap: {
2134
- deprecated: true,
2135
- },
2136
- rowspan: {
2137
- enum: ["/\\d+/"],
2138
- },
2139
- scope: {
2140
- enum: ["row", "col", "rowgroup", "colgroup"],
2141
- },
2142
- valign: {
2143
- deprecated: true,
2144
- },
2145
- width: {
2146
- deprecated: true,
2147
- },
2148
- },
2149
- implicitRole(node) {
2150
- var _a;
2151
- const table = node.closest("table");
2152
- if (!table) {
2153
- return null;
2154
- }
2155
- const tableRole = (_a = table.getAttribute("role")) !== null && _a !== void 0 ? _a : "table";
2156
- if (typeof tableRole !== "string" || !["table", "grid", "treegrid"].includes(tableRole)) {
2157
- return null;
2158
- }
2159
- const scope = node.getAttribute("scope");
2160
- switch (scope) {
2161
- case "col":
2162
- return "columnheader";
2163
- case "row":
2164
- return "rowheader";
2165
- default:
2166
- return tableRole === "table" ? "cell" : "gridcell";
2167
- }
2168
- },
2169
- permittedContent: ["@flow"],
2170
- permittedDescendants: [{ exclude: ["header", "footer", "@sectioning", "@heading"] }],
2171
- },
2172
- thead: {
2173
- implicitClosed: ["tbody", "tfoot"],
2174
- permittedContent: ["@script", "tr"],
2175
- attributes: {
2176
- align: {
2177
- deprecated: true,
2178
- },
2179
- background: {
2180
- deprecated: true,
2181
- },
2182
- char: {
2183
- deprecated: true,
2184
- },
2185
- charoff: {
2186
- deprecated: true,
2187
- },
2188
- valign: {
2189
- deprecated: true,
2190
- },
2191
- },
2192
- implicitRole() {
2193
- return "rowgroup";
2194
- },
2195
- },
2196
- time: {
2197
- flow: true,
2198
- phrasing: true,
2199
- implicitRole() {
2200
- return "time";
2201
- },
2202
- permittedContent: ["@phrasing"],
2203
- },
2204
- title: {
2205
- metadata: true,
2206
- permittedContent: [],
2207
- permittedParent: ["head"],
2208
- },
2209
- tr: {
2210
- implicitClosed: ["tr"],
2211
- permittedContent: ["@script", "td", "th"],
2212
- attributes: {
2213
- align: {
2214
- deprecated: true,
2215
- },
2216
- background: {
2217
- deprecated: true,
2218
- },
2219
- bgcolor: {
2220
- deprecated: true,
2221
- },
2222
- char: {
2223
- deprecated: true,
2224
- },
2225
- charoff: {
2226
- deprecated: true,
2227
- },
2228
- valign: {
2229
- deprecated: true,
2230
- },
2231
- },
2232
- implicitRole() {
2233
- return "row";
2234
- },
2235
- },
2236
- track: {
2237
- void: true,
2238
- },
2239
- tt: {
2240
- deprecated: {
2241
- documentation: "Use a more semantically correct element such as `<code>`, `<var>` or `<pre>`.",
2242
- source: "html4",
2243
- },
2244
- },
2245
- u: {
2246
- flow: true,
2247
- phrasing: true,
2248
- permittedContent: ["@phrasing"],
2249
- },
2250
- ul: {
2251
- flow: true,
2252
- permittedContent: ["@script", "li"],
2253
- attributes: {
2254
- compact: {
2255
- deprecated: true,
2256
- },
2257
- type: {
2258
- deprecated: true,
2259
- },
2260
- },
2261
- implicitRole() {
2262
- return "list";
2263
- },
2264
- },
2265
- var: {
2266
- flow: true,
2267
- phrasing: true,
2268
- permittedContent: ["@phrasing"],
2269
- },
2270
- video: {
2271
- flow: true,
2272
- phrasing: true,
2273
- embedded: true,
2274
- interactive: ["hasAttribute", "controls"],
2275
- transparent: ["@flow"],
2276
- attributes: {
2277
- crossorigin: {
2278
- omit: true,
2279
- enum: ["anonymous", "use-credentials"],
2280
- },
2281
- itemprop: {
2282
- allowed: allowedIfAttributeIsPresent("src"),
2283
- },
2284
- preload: {
2285
- omit: true,
2286
- enum: ["none", "metadata", "auto"],
2287
- },
2288
- },
2289
- permittedContent: ["@flow", "track", "source"],
2290
- permittedDescendants: [{ exclude: ["audio", "video"] }],
2291
- permittedOrder: ["source", "track", "@flow"],
2292
- },
2293
- wbr: {
2294
- flow: true,
2295
- phrasing: true,
2296
- void: true,
2297
- },
2298
- xmp: {
2299
- deprecated: {
2300
- documentation: "Use `<pre>` or `<code>` and escape content using HTML entities instead.",
2301
- source: "html32",
2302
- },
2303
- },
24
+ "*": {
25
+ attributes: {
26
+ contenteditable: {
27
+ omit: true,
28
+ enum: ["true", "false"]
29
+ },
30
+ contextmenu: {
31
+ deprecated: true
32
+ },
33
+ dir: {
34
+ enum: ["ltr", "rtl", "auto"]
35
+ },
36
+ draggable: {
37
+ enum: ["true", "false"]
38
+ },
39
+ hidden: {
40
+ boolean: true
41
+ },
42
+ id: {
43
+ enum: [validId]
44
+ },
45
+ tabindex: {
46
+ enum: ["/-?\\d+/"]
47
+ }
48
+ }
49
+ },
50
+ a: {
51
+ flow: true,
52
+ focusable(node) {
53
+ return node.hasAttribute("href");
54
+ },
55
+ phrasing: true,
56
+ interactive: true,
57
+ transparent: true,
58
+ attributes: {
59
+ charset: {
60
+ deprecated: true
61
+ },
62
+ coords: {
63
+ deprecated: true
64
+ },
65
+ datafld: {
66
+ deprecated: true
67
+ },
68
+ datasrc: {
69
+ deprecated: true
70
+ },
71
+ download: {
72
+ allowed: allowedIfAttributeIsPresent("href"),
73
+ omit: true,
74
+ enum: ["/.+/"]
75
+ },
76
+ href: {
77
+ enum: ["/.*/"]
78
+ },
79
+ hreflang: {
80
+ allowed: allowedIfAttributeIsPresent("href")
81
+ },
82
+ itemprop: {
83
+ allowed: allowedIfAttributeIsPresent("href")
84
+ },
85
+ methods: {
86
+ deprecated: true
87
+ },
88
+ name: {
89
+ deprecated: true
90
+ },
91
+ ping: {
92
+ allowed: allowedIfAttributeIsPresent("href")
93
+ },
94
+ referrerpolicy: {
95
+ allowed: allowedIfAttributeIsPresent("href"),
96
+ enum: ReferrerPolicy
97
+ },
98
+ rel: {
99
+ allowed: allowedIfAttributeIsPresent("href")
100
+ },
101
+ shape: {
102
+ deprecated: true
103
+ },
104
+ target: {
105
+ allowed: allowedIfAttributeIsPresent("href"),
106
+ enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"]
107
+ },
108
+ type: {
109
+ allowed: allowedIfAttributeIsPresent("href")
110
+ },
111
+ urn: {
112
+ deprecated: true
113
+ }
114
+ },
115
+ permittedDescendants: [{ exclude: "@interactive" }],
116
+ implicitRole(node) {
117
+ return node.hasAttribute("href") ? "link" : null;
118
+ }
119
+ },
120
+ abbr: {
121
+ flow: true,
122
+ phrasing: true,
123
+ permittedContent: ["@phrasing"]
124
+ },
125
+ acronym: {
126
+ deprecated: {
127
+ message: "use <abbr> instead",
128
+ documentation: "`<abbr>` can be used as a replacement.",
129
+ source: "html5"
130
+ }
131
+ },
132
+ address: {
133
+ flow: true,
134
+ implicitRole() {
135
+ return "group";
136
+ },
137
+ permittedContent: ["@flow"],
138
+ permittedDescendants: [{ exclude: ["address", "header", "footer", "@heading", "@sectioning"] }]
139
+ },
140
+ applet: {
141
+ deprecated: {
142
+ source: "html5"
143
+ },
144
+ attributes: {
145
+ datafld: {
146
+ deprecated: true
147
+ },
148
+ datasrc: {
149
+ deprecated: true
150
+ }
151
+ }
152
+ },
153
+ area: {
154
+ flow: ["isDescendant", "map"],
155
+ focusable(node) {
156
+ return node.hasAttribute("href");
157
+ },
158
+ phrasing: ["isDescendant", "map"],
159
+ void: true,
160
+ attributes: {
161
+ alt: {},
162
+ coords: {
163
+ allowed(node) {
164
+ const attr = node.getAttribute("shape");
165
+ if (attr === "default") {
166
+ return `cannot be used when "shape" attribute is "default"`;
167
+ } else {
168
+ return null;
169
+ }
170
+ }
171
+ },
172
+ download: {
173
+ allowed: allowedIfAttributeIsPresent("href")
174
+ },
175
+ nohref: {
176
+ deprecated: true
177
+ },
178
+ itemprop: {
179
+ allowed: allowedIfAttributeIsPresent("href")
180
+ },
181
+ ping: {
182
+ allowed: allowedIfAttributeIsPresent("href")
183
+ },
184
+ referrerpolicy: {
185
+ allowed: allowedIfAttributeIsPresent("href"),
186
+ enum: ReferrerPolicy
187
+ },
188
+ rel: {
189
+ allowed: allowedIfAttributeIsPresent("href")
190
+ },
191
+ shape: {
192
+ allowed(node, attr) {
193
+ const shape = attr ?? "rect";
194
+ switch (shape) {
195
+ case "circ":
196
+ case "circle":
197
+ case "poly":
198
+ case "polygon":
199
+ case "rect":
200
+ case "rectangle":
201
+ return allowedIfAttributeIsPresent("coords")(node, attr);
202
+ default:
203
+ return null;
204
+ }
205
+ },
206
+ enum: ["rect", "circle", "poly", "default"]
207
+ },
208
+ target: {
209
+ allowed: allowedIfAttributeIsPresent("href"),
210
+ enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"]
211
+ }
212
+ },
213
+ implicitRole(node) {
214
+ return node.hasAttribute("href") ? "link" : null;
215
+ },
216
+ requiredAncestors: ["map"]
217
+ },
218
+ article: {
219
+ flow: true,
220
+ sectioning: true,
221
+ permittedContent: ["@flow"],
222
+ permittedDescendants: [{ exclude: ["main"] }],
223
+ implicitRole() {
224
+ return "article";
225
+ }
226
+ },
227
+ aside: {
228
+ flow: true,
229
+ sectioning: true,
230
+ permittedContent: ["@flow"],
231
+ permittedDescendants: [{ exclude: ["main"] }],
232
+ implicitRole() {
233
+ return "complementary";
234
+ }
235
+ },
236
+ audio: {
237
+ flow: true,
238
+ focusable(node) {
239
+ return node.hasAttribute("controls");
240
+ },
241
+ phrasing: true,
242
+ embedded: true,
243
+ interactive: ["hasAttribute", "controls"],
244
+ transparent: ["@flow"],
245
+ attributes: {
246
+ crossorigin: {
247
+ omit: true,
248
+ enum: ["anonymous", "use-credentials"]
249
+ },
250
+ itemprop: {
251
+ allowed: allowedIfAttributeIsPresent("src")
252
+ },
253
+ preload: {
254
+ omit: true,
255
+ enum: ["none", "metadata", "auto"]
256
+ }
257
+ },
258
+ permittedContent: ["@flow", "track", "source"],
259
+ permittedDescendants: [{ exclude: ["audio", "video"] }],
260
+ permittedOrder: ["source", "track", "@flow"]
261
+ },
262
+ b: {
263
+ flow: true,
264
+ phrasing: true,
265
+ permittedContent: ["@phrasing"]
266
+ },
267
+ base: {
268
+ metadata: true,
269
+ void: true,
270
+ permittedParent: ["head"]
271
+ },
272
+ basefont: {
273
+ deprecated: {
274
+ message: "use CSS instead",
275
+ documentation: "Use CSS `font-size` property instead.",
276
+ source: "html4"
277
+ }
278
+ },
279
+ bdi: {
280
+ flow: true,
281
+ phrasing: true,
282
+ permittedContent: ["@phrasing"]
283
+ },
284
+ bdo: {
285
+ flow: true,
286
+ phrasing: true,
287
+ permittedContent: ["@phrasing"]
288
+ },
289
+ bgsound: {
290
+ deprecated: {
291
+ message: "use <audio> instead",
292
+ documentation: "Use the `<audio>` element instead but consider accessibility concerns with autoplaying sounds.",
293
+ source: "non-standard"
294
+ }
295
+ },
296
+ big: {
297
+ deprecated: {
298
+ message: "use CSS instead",
299
+ documentation: "Use CSS `font-size` property instead.",
300
+ source: "html5"
301
+ }
302
+ },
303
+ blink: {
304
+ deprecated: {
305
+ documentation: "`<blink>` has no direct replacement and blinking text is frowned upon by accessibility standards.",
306
+ source: "non-standard"
307
+ }
308
+ },
309
+ blockquote: {
310
+ flow: true,
311
+ sectioning: true,
312
+ implicitRole() {
313
+ return "blockquote";
314
+ },
315
+ permittedContent: ["@flow"]
316
+ },
317
+ body: {
318
+ permittedContent: ["@flow"],
319
+ permittedParent: ["html"],
320
+ attributes: {
321
+ alink: {
322
+ deprecated: true
323
+ },
324
+ background: {
325
+ deprecated: true
326
+ },
327
+ bgcolor: {
328
+ deprecated: true
329
+ },
330
+ link: {
331
+ deprecated: true
332
+ },
333
+ marginbottom: {
334
+ deprecated: true
335
+ },
336
+ marginheight: {
337
+ deprecated: true
338
+ },
339
+ marginleft: {
340
+ deprecated: true
341
+ },
342
+ marginright: {
343
+ deprecated: true
344
+ },
345
+ margintop: {
346
+ deprecated: true
347
+ },
348
+ marginwidth: {
349
+ deprecated: true
350
+ },
351
+ text: {
352
+ deprecated: true
353
+ },
354
+ vlink: {
355
+ deprecated: true
356
+ }
357
+ }
358
+ },
359
+ br: {
360
+ flow: true,
361
+ phrasing: true,
362
+ void: true,
363
+ attributes: {
364
+ clear: {
365
+ deprecated: true
366
+ }
367
+ }
368
+ },
369
+ button: {
370
+ flow: true,
371
+ focusable: true,
372
+ phrasing: true,
373
+ interactive: true,
374
+ formAssociated: {
375
+ listed: true
376
+ },
377
+ labelable: true,
378
+ attributes: {
379
+ autofocus: {
380
+ boolean: true
381
+ },
382
+ datafld: {
383
+ deprecated: true
384
+ },
385
+ dataformatas: {
386
+ deprecated: true
387
+ },
388
+ datasrc: {
389
+ deprecated: true
390
+ },
391
+ disabled: {
392
+ boolean: true
393
+ },
394
+ formaction: {
395
+ allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" })
396
+ },
397
+ formenctype: {
398
+ allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" })
399
+ },
400
+ formmethod: {
401
+ allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
402
+ enum: ["get", "post", "dialog"]
403
+ },
404
+ formnovalidate: {
405
+ allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
406
+ boolean: true
407
+ },
408
+ formtarget: {
409
+ allowed: allowedIfAttributeHasValue("type", ["submit"], { defaultValue: "submit" }),
410
+ enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"]
411
+ },
412
+ type: {
413
+ enum: ["submit", "reset", "button"]
414
+ }
415
+ },
416
+ implicitRole() {
417
+ return "button";
418
+ },
419
+ permittedContent: ["@phrasing"],
420
+ permittedDescendants: [{ exclude: ["@interactive"] }],
421
+ textContent: "accessible"
422
+ },
423
+ canvas: {
424
+ flow: true,
425
+ phrasing: true,
426
+ embedded: true,
427
+ transparent: true
428
+ },
429
+ caption: {
430
+ permittedContent: ["@flow"],
431
+ permittedDescendants: [{ exclude: ["table"] }],
432
+ attributes: {
433
+ align: {
434
+ deprecated: true
435
+ }
436
+ }
437
+ },
438
+ center: {
439
+ deprecated: {
440
+ message: "use CSS instead",
441
+ documentation: "Use the CSS `text-align` or `margin: auto` properties instead.",
442
+ source: "html4"
443
+ }
444
+ },
445
+ cite: {
446
+ flow: true,
447
+ phrasing: true,
448
+ permittedContent: ["@phrasing"]
449
+ },
450
+ code: {
451
+ flow: true,
452
+ phrasing: true,
453
+ permittedContent: ["@phrasing"]
454
+ },
455
+ col: {
456
+ attributes: {
457
+ align: {
458
+ deprecated: true
459
+ },
460
+ char: {
461
+ deprecated: true
462
+ },
463
+ charoff: {
464
+ deprecated: true
465
+ },
466
+ span: {
467
+ enum: ["/\\d+/"]
468
+ },
469
+ valign: {
470
+ deprecated: true
471
+ },
472
+ width: {
473
+ deprecated: true
474
+ }
475
+ },
476
+ void: true
477
+ },
478
+ colgroup: {
479
+ implicitClosed: ["colgroup"],
480
+ attributes: {
481
+ span: {
482
+ enum: ["/\\d+/"]
483
+ }
484
+ },
485
+ permittedContent: ["col", "template"]
486
+ },
487
+ data: {
488
+ flow: true,
489
+ phrasing: true,
490
+ permittedContent: ["@phrasing"]
491
+ },
492
+ datalist: {
493
+ flow: true,
494
+ phrasing: true,
495
+ implicitRole() {
496
+ return "listbox";
497
+ },
498
+ permittedContent: ["@phrasing", "option"]
499
+ },
500
+ dd: {
501
+ implicitClosed: ["dd", "dt"],
502
+ permittedContent: ["@flow"],
503
+ requiredAncestors: ["dl > dd", "dl > div > dd"]
504
+ },
505
+ del: {
506
+ flow: true,
507
+ phrasing: true,
508
+ transparent: true
509
+ },
510
+ details: {
511
+ flow: true,
512
+ sectioning: true,
513
+ interactive: true,
514
+ attributes: {
515
+ open: {
516
+ boolean: true
517
+ }
518
+ },
519
+ implicitRole() {
520
+ return "group";
521
+ },
522
+ permittedContent: ["summary", "@flow"],
523
+ permittedOrder: ["summary", "@flow"],
524
+ requiredContent: ["summary"]
525
+ },
526
+ dfn: {
527
+ flow: true,
528
+ phrasing: true,
529
+ implicitRole() {
530
+ return "term";
531
+ },
532
+ permittedContent: ["@phrasing"],
533
+ permittedDescendants: [{ exclude: ["dfn"] }]
534
+ },
535
+ dialog: {
536
+ flow: true,
537
+ permittedContent: ["@flow"],
538
+ attributes: {
539
+ open: {
540
+ boolean: true
541
+ }
542
+ },
543
+ implicitRole() {
544
+ return "dialog";
545
+ }
546
+ },
547
+ dir: {
548
+ deprecated: {
549
+ documentation: "The non-standard `<dir>` element has no direct replacement but MDN recommends replacing with `<ul>` and CSS.",
550
+ source: "html4"
551
+ }
552
+ },
553
+ div: {
554
+ flow: true,
555
+ permittedContent: ["@flow", "dt", "dd"],
556
+ attributes: {
557
+ align: {
558
+ deprecated: true
559
+ },
560
+ datafld: {
561
+ deprecated: true
562
+ },
563
+ dataformatas: {
564
+ deprecated: true
565
+ },
566
+ datasrc: {
567
+ deprecated: true
568
+ }
569
+ }
570
+ },
571
+ dl: {
572
+ flow: true,
573
+ permittedContent: ["@script", "dt", "dd", "div"],
574
+ attributes: {
575
+ compact: {
576
+ deprecated: true
577
+ }
578
+ }
579
+ },
580
+ dt: {
581
+ implicitClosed: ["dd", "dt"],
582
+ permittedContent: ["@flow"],
583
+ permittedDescendants: [{ exclude: ["header", "footer", "@sectioning", "@heading"] }],
584
+ requiredAncestors: ["dl > dt", "dl > div > dt"]
585
+ },
586
+ em: {
587
+ flow: true,
588
+ phrasing: true,
589
+ permittedContent: ["@phrasing"]
590
+ },
591
+ embed: {
592
+ flow: true,
593
+ phrasing: true,
594
+ embedded: true,
595
+ interactive: true,
596
+ void: true,
597
+ attributes: {
598
+ src: {
599
+ required: true,
600
+ enum: ["/.+/"]
601
+ },
602
+ title: {
603
+ required: true
604
+ }
605
+ }
606
+ },
607
+ fieldset: {
608
+ flow: true,
609
+ formAssociated: {
610
+ listed: true
611
+ },
612
+ attributes: {
613
+ datafld: {
614
+ deprecated: true
615
+ },
616
+ disabled: {
617
+ boolean: true
618
+ }
619
+ },
620
+ implicitRole() {
621
+ return "group";
622
+ },
623
+ permittedContent: ["@flow", "legend?"],
624
+ permittedOrder: ["legend", "@flow"]
625
+ },
626
+ figcaption: {
627
+ permittedContent: ["@flow"]
628
+ },
629
+ figure: {
630
+ flow: true,
631
+ implicitRole() {
632
+ return "figure";
633
+ },
634
+ permittedContent: ["@flow", "figcaption?"],
635
+ permittedOrder: ["figcaption", "@flow", "figcaption"]
636
+ },
637
+ font: {
638
+ deprecated: {
639
+ message: "use CSS instead",
640
+ documentation: "Use CSS font properties instead.",
641
+ source: "html4"
642
+ }
643
+ },
644
+ footer: {
645
+ flow: true,
646
+ implicitRole(node) {
647
+ const selectors = [
648
+ "article",
649
+ "aside",
650
+ "main",
651
+ "nav",
652
+ "section",
653
+ '[role="article"]',
654
+ '[role="complementary"]',
655
+ '[role="main"]',
656
+ '[role="navigation"]',
657
+ '[role="region"]'
658
+ ];
659
+ if (node.closest(selectors.join(","))) {
660
+ return null;
661
+ } else {
662
+ return "contentinfo";
663
+ }
664
+ },
665
+ permittedContent: ["@flow"],
666
+ permittedDescendants: [{ exclude: ["header", "footer", "main"] }]
667
+ },
668
+ form: {
669
+ flow: true,
670
+ form: true,
671
+ attributes: {
672
+ action: {
673
+ enum: [/^\s*\S+\s*$/]
674
+ },
675
+ accept: {
676
+ deprecated: true
677
+ },
678
+ autocomplete: {
679
+ enum: ["on", "off"]
680
+ },
681
+ method: {
682
+ enum: ["get", "post", "dialog"]
683
+ },
684
+ novalidate: {
685
+ boolean: true
686
+ },
687
+ target: {
688
+ enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"]
689
+ }
690
+ },
691
+ implicitRole() {
692
+ return "form";
693
+ },
694
+ permittedContent: ["@flow"],
695
+ permittedDescendants: [{ exclude: ["@form"] }]
696
+ },
697
+ frame: {
698
+ deprecated: {
699
+ documentation: "The `<frame>` element can be replaced with the `<iframe>` element but a better solution is to remove usage of frames entirely.",
700
+ source: "html5"
701
+ },
702
+ attributes: {
703
+ datafld: {
704
+ deprecated: true
705
+ },
706
+ datasrc: {
707
+ deprecated: true
708
+ },
709
+ title: {
710
+ required: true
711
+ }
712
+ }
713
+ },
714
+ frameset: {
715
+ deprecated: {
716
+ documentation: "The `<frameset>` element can be replaced with the `<iframe>` element but a better solution is to remove usage of frames entirely.",
717
+ source: "html5"
718
+ }
719
+ },
720
+ h1: {
721
+ flow: true,
722
+ heading: true,
723
+ permittedContent: ["@phrasing"],
724
+ attributes: {
725
+ align: {
726
+ deprecated: true
727
+ }
728
+ },
729
+ implicitRole() {
730
+ return "heading";
731
+ }
732
+ },
733
+ h2: {
734
+ flow: true,
735
+ heading: true,
736
+ permittedContent: ["@phrasing"],
737
+ attributes: {
738
+ align: {
739
+ deprecated: true
740
+ }
741
+ },
742
+ implicitRole() {
743
+ return "heading";
744
+ }
745
+ },
746
+ h3: {
747
+ flow: true,
748
+ heading: true,
749
+ permittedContent: ["@phrasing"],
750
+ attributes: {
751
+ align: {
752
+ deprecated: true
753
+ }
754
+ },
755
+ implicitRole() {
756
+ return "heading";
757
+ }
758
+ },
759
+ h4: {
760
+ flow: true,
761
+ heading: true,
762
+ permittedContent: ["@phrasing"],
763
+ attributes: {
764
+ align: {
765
+ deprecated: true
766
+ }
767
+ },
768
+ implicitRole() {
769
+ return "heading";
770
+ }
771
+ },
772
+ h5: {
773
+ flow: true,
774
+ heading: true,
775
+ permittedContent: ["@phrasing"],
776
+ attributes: {
777
+ align: {
778
+ deprecated: true
779
+ }
780
+ },
781
+ implicitRole() {
782
+ return "heading";
783
+ }
784
+ },
785
+ h6: {
786
+ flow: true,
787
+ heading: true,
788
+ permittedContent: ["@phrasing"],
789
+ attributes: {
790
+ align: {
791
+ deprecated: true
792
+ }
793
+ },
794
+ implicitRole() {
795
+ return "heading";
796
+ }
797
+ },
798
+ head: {
799
+ permittedContent: ["base?", "title?", "@meta"],
800
+ permittedParent: ["html"],
801
+ requiredContent: ["title"],
802
+ attributes: {
803
+ profile: {
804
+ deprecated: true
805
+ }
806
+ }
807
+ },
808
+ header: {
809
+ flow: true,
810
+ implicitRole(node) {
811
+ const selectors = [
812
+ "article",
813
+ "aside",
814
+ "main",
815
+ "nav",
816
+ "section",
817
+ '[role="article"]',
818
+ '[role="complementary"]',
819
+ '[role="main"]',
820
+ '[role="navigation"]',
821
+ '[role="region"]'
822
+ ];
823
+ if (node.closest(selectors.join(","))) {
824
+ return null;
825
+ } else {
826
+ return "banner";
827
+ }
828
+ },
829
+ permittedContent: ["@flow"],
830
+ permittedDescendants: [{ exclude: ["header", "footer", "main"] }]
831
+ },
832
+ hgroup: {
833
+ flow: true,
834
+ heading: true,
835
+ permittedContent: ["p", "@heading?"],
836
+ permittedDescendants: [{ exclude: ["hgroup"] }],
837
+ requiredContent: ["@heading"]
838
+ },
839
+ hr: {
840
+ flow: true,
841
+ void: true,
842
+ attributes: {
843
+ align: {
844
+ deprecated: true
845
+ },
846
+ color: {
847
+ deprecated: true
848
+ },
849
+ noshade: {
850
+ deprecated: true
851
+ },
852
+ size: {
853
+ deprecated: true
854
+ },
855
+ width: {
856
+ deprecated: true
857
+ }
858
+ },
859
+ implicitRole() {
860
+ return "separator";
861
+ }
862
+ },
863
+ html: {
864
+ permittedContent: ["head?", "body?"],
865
+ permittedOrder: ["head", "body"],
866
+ requiredContent: ["head", "body"],
867
+ attributes: {
868
+ lang: {
869
+ required: true
870
+ },
871
+ version: {
872
+ deprecated: true
873
+ }
874
+ },
875
+ implicitRole() {
876
+ return "document";
877
+ }
878
+ },
879
+ i: {
880
+ flow: true,
881
+ phrasing: true,
882
+ permittedContent: ["@phrasing"]
883
+ },
884
+ iframe: {
885
+ flow: true,
886
+ phrasing: true,
887
+ embedded: true,
888
+ interactive: true,
889
+ attributes: {
890
+ align: {
891
+ deprecated: true
892
+ },
893
+ allowtransparency: {
894
+ deprecated: true
895
+ },
896
+ datafld: {
897
+ deprecated: true
898
+ },
899
+ datasrc: {
900
+ deprecated: true
901
+ },
902
+ frameborder: {
903
+ deprecated: true
904
+ },
905
+ hspace: {
906
+ deprecated: true
907
+ },
908
+ marginheight: {
909
+ deprecated: true
910
+ },
911
+ marginwidth: {
912
+ deprecated: true
913
+ },
914
+ referrerpolicy: {
915
+ enum: ReferrerPolicy
916
+ },
917
+ scrolling: {
918
+ deprecated: true
919
+ },
920
+ src: {
921
+ enum: ["/.+/"]
922
+ },
923
+ title: {
924
+ required: true
925
+ },
926
+ vspace: {
927
+ deprecated: true
928
+ }
929
+ },
930
+ permittedContent: []
931
+ },
932
+ img: {
933
+ flow: true,
934
+ phrasing: true,
935
+ embedded: true,
936
+ interactive: ["hasAttribute", "usemap"],
937
+ void: true,
938
+ attributes: {
939
+ align: {
940
+ deprecated: true
941
+ },
942
+ border: {
943
+ deprecated: true
944
+ },
945
+ crossorigin: {
946
+ omit: true,
947
+ enum: ["anonymous", "use-credentials"]
948
+ },
949
+ datafld: {
950
+ deprecated: true
951
+ },
952
+ datasrc: {
953
+ deprecated: true
954
+ },
955
+ decoding: {
956
+ enum: ["sync", "async", "auto"]
957
+ },
958
+ hspace: {
959
+ deprecated: true
960
+ },
961
+ ismap: {
962
+ boolean: true
963
+ },
964
+ lowsrc: {
965
+ deprecated: true
966
+ },
967
+ name: {
968
+ deprecated: true
969
+ },
970
+ referrerpolicy: {
971
+ enum: ReferrerPolicy
972
+ },
973
+ src: {
974
+ required: true,
975
+ enum: ["/.+/"]
976
+ },
977
+ srcset: {
978
+ enum: ["/[^]+/"]
979
+ },
980
+ vspace: {
981
+ deprecated: true
982
+ }
983
+ },
984
+ implicitRole(node) {
985
+ const alt = node.getAttribute("alt");
986
+ if (alt === "") {
987
+ return "presentation";
988
+ } else {
989
+ return "img";
990
+ }
991
+ }
992
+ },
993
+ input: {
994
+ flow: true,
995
+ focusable(node) {
996
+ return node.getAttribute("type") !== "hidden";
997
+ },
998
+ phrasing: true,
999
+ interactive: ["matchAttribute", ["type", "!=", "hidden"]],
1000
+ void: true,
1001
+ formAssociated: {
1002
+ listed: true
1003
+ },
1004
+ labelable: ["matchAttribute", ["type", "!=", "hidden"]],
1005
+ attributes: {
1006
+ align: {
1007
+ deprecated: true
1008
+ },
1009
+ autofocus: {
1010
+ boolean: true
1011
+ },
1012
+ capture: {
1013
+ omit: true,
1014
+ enum: ["environment", "user"]
1015
+ },
1016
+ checked: {
1017
+ boolean: true
1018
+ },
1019
+ datafld: {
1020
+ deprecated: true
1021
+ },
1022
+ dataformatas: {
1023
+ deprecated: true
1024
+ },
1025
+ datasrc: {
1026
+ deprecated: true
1027
+ },
1028
+ disabled: {
1029
+ boolean: true
1030
+ },
1031
+ formaction: {
1032
+ allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1033
+ defaultValue: "submit"
1034
+ })
1035
+ },
1036
+ formenctype: {
1037
+ allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1038
+ defaultValue: "submit"
1039
+ })
1040
+ },
1041
+ formmethod: {
1042
+ allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1043
+ defaultValue: "submit"
1044
+ }),
1045
+ enum: ["get", "post", "dialog"]
1046
+ },
1047
+ formnovalidate: {
1048
+ allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1049
+ defaultValue: "submit"
1050
+ }),
1051
+ boolean: true
1052
+ },
1053
+ formtarget: {
1054
+ allowed: allowedIfAttributeHasValue("type", ["submit", "image"], {
1055
+ defaultValue: "submit"
1056
+ }),
1057
+ enum: ["/[^_].*/", "_blank", "_self", "_parent", "_top"]
1058
+ },
1059
+ hspace: {
1060
+ deprecated: true
1061
+ },
1062
+ inputmode: {
1063
+ enum: ["none", "text", "decimal", "numeric", "tel", "search", "email", "url"]
1064
+ },
1065
+ ismap: {
1066
+ deprecated: true
1067
+ },
1068
+ multiple: {
1069
+ boolean: true
1070
+ },
1071
+ readonly: {
1072
+ boolean: true
1073
+ },
1074
+ required: {
1075
+ boolean: true
1076
+ },
1077
+ spellcheck: {
1078
+ enum: ["default", "false", "true"]
1079
+ },
1080
+ type: {
1081
+ required: true,
1082
+ enum: [
1083
+ "button",
1084
+ "checkbox",
1085
+ "color",
1086
+ "date",
1087
+ "datetime-local",
1088
+ "email",
1089
+ "file",
1090
+ "hidden",
1091
+ "image",
1092
+ "month",
1093
+ "number",
1094
+ "password",
1095
+ "radio",
1096
+ "range",
1097
+ "reset",
1098
+ "search",
1099
+ "submit",
1100
+ "tel",
1101
+ "text",
1102
+ "time",
1103
+ "url",
1104
+ "week"
1105
+ ]
1106
+ },
1107
+ usemap: {
1108
+ deprecated: true
1109
+ },
1110
+ vspace: {
1111
+ deprecated: true
1112
+ }
1113
+ },
1114
+ /* eslint-disable-next-line complexity -- the standard is complicated */
1115
+ implicitRole(node) {
1116
+ const list = node.hasAttribute("list");
1117
+ if (list) {
1118
+ return "combobox";
1119
+ }
1120
+ const type = node.getAttribute("type");
1121
+ switch (type) {
1122
+ case "button":
1123
+ return "button";
1124
+ case "checkbox":
1125
+ return "checkbox";
1126
+ case "email":
1127
+ return "textbox";
1128
+ case "image":
1129
+ return "button";
1130
+ case "number":
1131
+ return "spinbutton";
1132
+ case "radio":
1133
+ return "radio";
1134
+ case "range":
1135
+ return "slider";
1136
+ case "reset":
1137
+ return "button";
1138
+ case "search":
1139
+ return "searchbox";
1140
+ case "submit":
1141
+ return "button";
1142
+ case "tel":
1143
+ return "textbox";
1144
+ case "text":
1145
+ return "textbox";
1146
+ case "url":
1147
+ return "textbox";
1148
+ default:
1149
+ return "textbox";
1150
+ }
1151
+ }
1152
+ },
1153
+ ins: {
1154
+ flow: true,
1155
+ phrasing: true,
1156
+ transparent: true
1157
+ },
1158
+ isindex: {
1159
+ deprecated: {
1160
+ source: "html4"
1161
+ }
1162
+ },
1163
+ kbd: {
1164
+ flow: true,
1165
+ phrasing: true,
1166
+ permittedContent: ["@phrasing"]
1167
+ },
1168
+ keygen: {
1169
+ flow: true,
1170
+ phrasing: true,
1171
+ interactive: true,
1172
+ void: true,
1173
+ labelable: true,
1174
+ deprecated: true
1175
+ },
1176
+ label: {
1177
+ flow: true,
1178
+ phrasing: true,
1179
+ interactive: true,
1180
+ permittedContent: ["@phrasing"],
1181
+ permittedDescendants: [{ exclude: ["label"] }],
1182
+ attributes: {
1183
+ datafld: {
1184
+ deprecated: true
1185
+ },
1186
+ dataformatas: {
1187
+ deprecated: true
1188
+ },
1189
+ datasrc: {
1190
+ deprecated: true
1191
+ },
1192
+ for: {
1193
+ enum: [validId]
1194
+ }
1195
+ }
1196
+ },
1197
+ legend: {
1198
+ permittedContent: ["@phrasing", "@heading"],
1199
+ attributes: {
1200
+ align: {
1201
+ deprecated: true
1202
+ },
1203
+ datafld: {
1204
+ deprecated: true
1205
+ },
1206
+ dataformatas: {
1207
+ deprecated: true
1208
+ },
1209
+ datasrc: {
1210
+ deprecated: true
1211
+ }
1212
+ }
1213
+ },
1214
+ li: {
1215
+ implicitClosed: ["li"],
1216
+ permittedContent: ["@flow"],
1217
+ permittedParent: ["ul", "ol", "menu", "template"],
1218
+ attributes: {
1219
+ type: {
1220
+ deprecated: true
1221
+ }
1222
+ },
1223
+ implicitRole(node) {
1224
+ return node.closest("ul, ol, menu") ? "listitem" : null;
1225
+ }
1226
+ },
1227
+ link: {
1228
+ metadata: true,
1229
+ void: true,
1230
+ attributes: {
1231
+ as: {
1232
+ allowed: allowedIfAttributeHasValue("rel", ["prefetch", "preload", "modulepreload"]),
1233
+ enum: [
1234
+ "audio",
1235
+ "audioworklet",
1236
+ "document",
1237
+ "embed",
1238
+ "fetch",
1239
+ "font",
1240
+ "frame",
1241
+ "iframe",
1242
+ "image",
1243
+ "manifest",
1244
+ "object",
1245
+ "paintworklet",
1246
+ "report",
1247
+ "script",
1248
+ "serviceworker",
1249
+ "sharedworker",
1250
+ "style",
1251
+ "track",
1252
+ "video",
1253
+ "webidentity",
1254
+ "worker",
1255
+ "xslt"
1256
+ ]
1257
+ },
1258
+ blocking: {
1259
+ allowed: allowedIfAttributeHasValue("rel", ["stylesheet", "preload", "modulepreload"]),
1260
+ list: true,
1261
+ enum: ["render"]
1262
+ },
1263
+ charset: {
1264
+ deprecated: true
1265
+ },
1266
+ crossorigin: {
1267
+ omit: true,
1268
+ enum: ["anonymous", "use-credentials"]
1269
+ },
1270
+ disabled: {
1271
+ allowed: allowedIfAttributeHasValue("rel", ["stylesheet"]),
1272
+ boolean: true
1273
+ },
1274
+ href: {
1275
+ required: true,
1276
+ enum: ["/.+/"]
1277
+ },
1278
+ integrity: {
1279
+ allowed: allowedIfAttributeHasValue("rel", ["stylesheet", "preload", "modulepreload"]),
1280
+ enum: ["/.+/"]
1281
+ },
1282
+ methods: {
1283
+ deprecated: true
1284
+ },
1285
+ referrerpolicy: {
1286
+ enum: ReferrerPolicy
1287
+ },
1288
+ target: {
1289
+ deprecated: true
1290
+ },
1291
+ urn: {
1292
+ deprecated: true
1293
+ }
1294
+ }
1295
+ },
1296
+ listing: {
1297
+ deprecated: {
1298
+ source: "html32"
1299
+ }
1300
+ },
1301
+ main: {
1302
+ flow: true,
1303
+ implicitRole() {
1304
+ return "main";
1305
+ }
1306
+ },
1307
+ map: {
1308
+ flow: true,
1309
+ phrasing: true,
1310
+ transparent: true,
1311
+ attributes: {
1312
+ name: {
1313
+ required: true,
1314
+ enum: ["/\\S+/"]
1315
+ }
1316
+ }
1317
+ },
1318
+ mark: {
1319
+ flow: true,
1320
+ phrasing: true,
1321
+ permittedContent: ["@phrasing"]
1322
+ },
1323
+ marquee: {
1324
+ deprecated: {
1325
+ documentation: "Marked as obsolete by both W3C and WHATWG standards but still implemented in most browsers. Animated text should be avoided for accessibility reasons as well.",
1326
+ source: "html5"
1327
+ },
1328
+ attributes: {
1329
+ datafld: {
1330
+ deprecated: true
1331
+ },
1332
+ dataformatas: {
1333
+ deprecated: true
1334
+ },
1335
+ datasrc: {
1336
+ deprecated: true
1337
+ }
1338
+ }
1339
+ },
1340
+ math: {
1341
+ flow: true,
1342
+ foreign: true,
1343
+ phrasing: true,
1344
+ embedded: true,
1345
+ attributes: {
1346
+ align: {
1347
+ deprecated: true
1348
+ },
1349
+ dir: {
1350
+ enum: ["ltr", "rtl"]
1351
+ },
1352
+ display: {
1353
+ enum: ["block", "inline"]
1354
+ },
1355
+ hspace: {
1356
+ deprecated: true
1357
+ },
1358
+ name: {
1359
+ deprecated: true
1360
+ },
1361
+ overflow: {
1362
+ enum: ["linebreak", "scroll", "elide", "truncate", "scale"]
1363
+ },
1364
+ vspace: {
1365
+ deprecated: true
1366
+ }
1367
+ },
1368
+ implicitRole() {
1369
+ return "math";
1370
+ }
1371
+ },
1372
+ menu: {
1373
+ flow: true,
1374
+ implicitRole() {
1375
+ return "list";
1376
+ },
1377
+ permittedContent: ["@script", "li"]
1378
+ },
1379
+ meta: {
1380
+ flow: ["hasAttribute", "itemprop"],
1381
+ phrasing: ["hasAttribute", "itemprop"],
1382
+ metadata: true,
1383
+ void: true,
1384
+ attributes: {
1385
+ charset: {
1386
+ enum: ["utf-8"]
1387
+ },
1388
+ content: {
1389
+ allowed: allowedIfAttributeIsPresent("name", "http-equiv", "itemprop", "property")
1390
+ },
1391
+ itemprop: {
1392
+ allowed: allowedIfAttributeIsAbsent("http-equiv", "name")
1393
+ },
1394
+ name: {
1395
+ allowed: allowedIfAttributeIsAbsent("http-equiv", "itemprop")
1396
+ },
1397
+ "http-equiv": {
1398
+ allowed: allowedIfAttributeIsAbsent("name", "itemprop")
1399
+ },
1400
+ scheme: {
1401
+ deprecated: true
1402
+ }
1403
+ }
1404
+ },
1405
+ meter: {
1406
+ flow: true,
1407
+ phrasing: true,
1408
+ labelable: true,
1409
+ implicitRole() {
1410
+ return "meter";
1411
+ },
1412
+ permittedContent: ["@phrasing"],
1413
+ permittedDescendants: [{ exclude: "meter" }]
1414
+ },
1415
+ multicol: {
1416
+ deprecated: {
1417
+ message: "use CSS instead",
1418
+ documentation: "Use CSS columns instead.",
1419
+ source: "html5"
1420
+ }
1421
+ },
1422
+ nav: {
1423
+ flow: true,
1424
+ sectioning: true,
1425
+ implicitRole() {
1426
+ return "navigation";
1427
+ },
1428
+ permittedContent: ["@flow"],
1429
+ permittedDescendants: [{ exclude: "main" }]
1430
+ },
1431
+ nextid: {
1432
+ deprecated: {
1433
+ source: "html32"
1434
+ }
1435
+ },
1436
+ nobr: {
1437
+ deprecated: {
1438
+ message: "use CSS instead",
1439
+ documentation: "Use CSS `white-space` property instead.",
1440
+ source: "non-standard"
1441
+ }
1442
+ },
1443
+ noembed: {
1444
+ deprecated: {
1445
+ source: "non-standard"
1446
+ }
1447
+ },
1448
+ noframes: {
1449
+ deprecated: {
1450
+ source: "html5"
1451
+ }
1452
+ },
1453
+ noscript: {
1454
+ metadata: true,
1455
+ flow: true,
1456
+ phrasing: true,
1457
+ transparent: true,
1458
+ permittedDescendants: [{ exclude: "noscript" }]
1459
+ },
1460
+ object: {
1461
+ flow: true,
1462
+ phrasing: true,
1463
+ embedded: true,
1464
+ interactive: ["hasAttribute", "usemap"],
1465
+ transparent: true,
1466
+ formAssociated: {
1467
+ listed: true
1468
+ },
1469
+ attributes: {
1470
+ align: {
1471
+ deprecated: true
1472
+ },
1473
+ archive: {
1474
+ deprecated: true
1475
+ },
1476
+ blocking: {
1477
+ list: true,
1478
+ enum: ["render"]
1479
+ },
1480
+ border: {
1481
+ deprecated: true
1482
+ },
1483
+ classid: {
1484
+ deprecated: true
1485
+ },
1486
+ code: {
1487
+ deprecated: true
1488
+ },
1489
+ codebase: {
1490
+ deprecated: true
1491
+ },
1492
+ codetype: {
1493
+ deprecated: true
1494
+ },
1495
+ data: {
1496
+ enum: ["/.+/"],
1497
+ required: true
1498
+ },
1499
+ datafld: {
1500
+ deprecated: true
1501
+ },
1502
+ dataformatas: {
1503
+ deprecated: true
1504
+ },
1505
+ datasrc: {
1506
+ deprecated: true
1507
+ },
1508
+ declare: {
1509
+ deprecated: true
1510
+ },
1511
+ hspace: {
1512
+ deprecated: true
1513
+ },
1514
+ name: {
1515
+ enum: ["/[^_].*/"]
1516
+ },
1517
+ standby: {
1518
+ deprecated: true
1519
+ },
1520
+ vspace: {
1521
+ deprecated: true
1522
+ }
1523
+ },
1524
+ permittedContent: ["param", "@flow"],
1525
+ permittedOrder: ["param", "@flow"]
1526
+ },
1527
+ ol: {
1528
+ flow: true,
1529
+ attributes: {
1530
+ compact: {
1531
+ deprecated: true
1532
+ },
1533
+ reversed: {
1534
+ boolean: true
1535
+ },
1536
+ type: {
1537
+ enum: ["a", "A", "i", "I", "1"]
1538
+ }
1539
+ },
1540
+ implicitRole() {
1541
+ return "list";
1542
+ },
1543
+ permittedContent: ["@script", "li"]
1544
+ },
1545
+ optgroup: {
1546
+ implicitClosed: ["optgroup"],
1547
+ attributes: {
1548
+ disabled: {
1549
+ boolean: true
1550
+ }
1551
+ },
1552
+ implicitRole() {
1553
+ return "group";
1554
+ },
1555
+ permittedContent: ["@script", "option"]
1556
+ },
1557
+ option: {
1558
+ implicitClosed: ["option"],
1559
+ attributes: {
1560
+ dataformatas: {
1561
+ deprecated: true
1562
+ },
1563
+ datasrc: {
1564
+ deprecated: true
1565
+ },
1566
+ disabled: {
1567
+ boolean: true
1568
+ },
1569
+ name: {
1570
+ deprecated: true
1571
+ },
1572
+ selected: {
1573
+ boolean: true
1574
+ }
1575
+ },
1576
+ implicitRole() {
1577
+ return "option";
1578
+ },
1579
+ permittedContent: []
1580
+ },
1581
+ output: {
1582
+ flow: true,
1583
+ phrasing: true,
1584
+ formAssociated: {
1585
+ listed: true
1586
+ },
1587
+ labelable: true,
1588
+ implicitRole() {
1589
+ return "status";
1590
+ },
1591
+ permittedContent: ["@phrasing"]
1592
+ },
1593
+ p: {
1594
+ flow: true,
1595
+ implicitClosed: [
1596
+ "address",
1597
+ "article",
1598
+ "aside",
1599
+ "blockquote",
1600
+ "div",
1601
+ "dl",
1602
+ "fieldset",
1603
+ "footer",
1604
+ "form",
1605
+ "h1",
1606
+ "h2",
1607
+ "h3",
1608
+ "h4",
1609
+ "h5",
1610
+ "h6",
1611
+ "header",
1612
+ "hgroup",
1613
+ "hr",
1614
+ "main",
1615
+ "nav",
1616
+ "ol",
1617
+ "p",
1618
+ "pre",
1619
+ "section",
1620
+ "table",
1621
+ "ul"
1622
+ ],
1623
+ permittedContent: ["@phrasing"],
1624
+ attributes: {
1625
+ align: {
1626
+ deprecated: true
1627
+ }
1628
+ }
1629
+ },
1630
+ param: {
1631
+ void: true,
1632
+ attributes: {
1633
+ datafld: {
1634
+ deprecated: true
1635
+ },
1636
+ type: {
1637
+ deprecated: true
1638
+ },
1639
+ valuetype: {
1640
+ deprecated: true
1641
+ }
1642
+ }
1643
+ },
1644
+ picture: {
1645
+ flow: true,
1646
+ phrasing: true,
1647
+ embedded: true,
1648
+ permittedContent: ["@script", "source", "img"],
1649
+ permittedOrder: ["source", "img"]
1650
+ },
1651
+ plaintext: {
1652
+ deprecated: {
1653
+ message: "use <pre> or CSS instead",
1654
+ documentation: "Use the `<pre>` element or use CSS to set a monospace font.",
1655
+ source: "html2"
1656
+ }
1657
+ },
1658
+ pre: {
1659
+ flow: true,
1660
+ permittedContent: ["@phrasing"],
1661
+ attributes: {
1662
+ width: {
1663
+ deprecated: true
1664
+ }
1665
+ }
1666
+ },
1667
+ progress: {
1668
+ flow: true,
1669
+ phrasing: true,
1670
+ labelable: true,
1671
+ implicitRole() {
1672
+ return "progressbar";
1673
+ },
1674
+ permittedContent: ["@phrasing"],
1675
+ permittedDescendants: [{ exclude: "progress" }]
1676
+ },
1677
+ q: {
1678
+ flow: true,
1679
+ phrasing: true,
1680
+ permittedContent: ["@phrasing"]
1681
+ },
1682
+ rb: {
1683
+ implicitClosed: ["rb", "rt", "rtc", "rp"],
1684
+ permittedContent: ["@phrasing"]
1685
+ },
1686
+ rp: {
1687
+ implicitClosed: ["rb", "rt", "rtc", "rp"],
1688
+ permittedContent: ["@phrasing"]
1689
+ },
1690
+ rt: {
1691
+ implicitClosed: ["rb", "rt", "rtc", "rp"],
1692
+ permittedContent: ["@phrasing"]
1693
+ },
1694
+ rtc: {
1695
+ implicitClosed: ["rb", "rtc", "rp"],
1696
+ permittedContent: ["@phrasing", "rt"]
1697
+ },
1698
+ ruby: {
1699
+ flow: true,
1700
+ phrasing: true,
1701
+ permittedContent: ["@phrasing", "rb", "rp", "rt", "rtc"]
1702
+ },
1703
+ s: {
1704
+ flow: true,
1705
+ phrasing: true,
1706
+ permittedContent: ["@phrasing"]
1707
+ },
1708
+ samp: {
1709
+ flow: true,
1710
+ phrasing: true,
1711
+ permittedContent: ["@phrasing"]
1712
+ },
1713
+ script: {
1714
+ metadata: true,
1715
+ flow: true,
1716
+ phrasing: true,
1717
+ scriptSupporting: true,
1718
+ attributes: {
1719
+ async: {
1720
+ boolean: true
1721
+ },
1722
+ crossorigin: {
1723
+ omit: true,
1724
+ enum: ["anonymous", "use-credentials"]
1725
+ },
1726
+ defer: {
1727
+ boolean: true
1728
+ },
1729
+ event: {
1730
+ deprecated: true
1731
+ },
1732
+ for: {
1733
+ deprecated: true
1734
+ },
1735
+ integrity: {
1736
+ allowed: allowedIfAttributeIsPresent("src"),
1737
+ enum: ["/.+/"]
1738
+ },
1739
+ language: {
1740
+ deprecated: true
1741
+ },
1742
+ nomodule: {
1743
+ boolean: true
1744
+ },
1745
+ referrerpolicy: {
1746
+ enum: ReferrerPolicy
1747
+ },
1748
+ src: {
1749
+ enum: ["/.+/"]
1750
+ }
1751
+ }
1752
+ },
1753
+ search: {
1754
+ flow: true,
1755
+ implicitRole() {
1756
+ return "search";
1757
+ }
1758
+ },
1759
+ section: {
1760
+ flow: true,
1761
+ sectioning: true,
1762
+ implicitRole() {
1763
+ return "region";
1764
+ },
1765
+ permittedContent: ["@flow"]
1766
+ },
1767
+ select: {
1768
+ flow: true,
1769
+ focusable: true,
1770
+ phrasing: true,
1771
+ interactive: true,
1772
+ formAssociated: {
1773
+ listed: true
1774
+ },
1775
+ labelable: true,
1776
+ attributes: {
1777
+ autofocus: {
1778
+ boolean: true
1779
+ },
1780
+ disabled: {
1781
+ boolean: true
1782
+ },
1783
+ multiple: {
1784
+ boolean: true
1785
+ },
1786
+ required: {
1787
+ boolean: true
1788
+ },
1789
+ size: {
1790
+ enum: ["/\\d+/"]
1791
+ }
1792
+ },
1793
+ implicitRole(node) {
1794
+ const multiple = node.hasAttribute("multiple");
1795
+ if (multiple) {
1796
+ return "listbox";
1797
+ }
1798
+ const size = node.getAttribute("size");
1799
+ if (typeof size === "string") {
1800
+ const parsed = parseInt(size, 10);
1801
+ if (parsed > 1) {
1802
+ return "listbox";
1803
+ }
1804
+ }
1805
+ return "combobox";
1806
+ },
1807
+ permittedContent: ["@script", "datasrc", "datafld", "dataformatas", "option", "optgroup"]
1808
+ },
1809
+ slot: {
1810
+ flow: true,
1811
+ phrasing: true,
1812
+ transparent: true
1813
+ },
1814
+ small: {
1815
+ flow: true,
1816
+ phrasing: true,
1817
+ permittedContent: ["@phrasing"]
1818
+ },
1819
+ source: {
1820
+ void: true,
1821
+ attributes: {
1822
+ type: {},
1823
+ media: {},
1824
+ src: {
1825
+ allowed: allowedIfParentIsPresent("audio", "video")
1826
+ },
1827
+ srcset: {
1828
+ allowed: allowedIfParentIsPresent("picture")
1829
+ },
1830
+ sizes: {
1831
+ allowed: allowedIfParentIsPresent("picture")
1832
+ },
1833
+ width: {
1834
+ allowed: allowedIfParentIsPresent("picture"),
1835
+ enum: ["/\\d+/"]
1836
+ },
1837
+ height: {
1838
+ allowed: allowedIfParentIsPresent("picture"),
1839
+ enum: ["/\\d+/"]
1840
+ }
1841
+ }
1842
+ },
1843
+ spacer: {
1844
+ deprecated: {
1845
+ message: "use CSS instead",
1846
+ documentation: "Use CSS margin or padding instead.",
1847
+ source: "non-standard"
1848
+ }
1849
+ },
1850
+ span: {
1851
+ flow: true,
1852
+ phrasing: true,
1853
+ permittedContent: ["@phrasing"],
1854
+ attributes: {
1855
+ datafld: {
1856
+ deprecated: true
1857
+ },
1858
+ dataformatas: {
1859
+ deprecated: true
1860
+ },
1861
+ datasrc: {
1862
+ deprecated: true
1863
+ }
1864
+ }
1865
+ },
1866
+ strike: {
1867
+ deprecated: {
1868
+ message: "use <del> or <s> instead",
1869
+ documentation: "Use the `<del>` or `<s>` element instead.",
1870
+ source: "html5"
1871
+ }
1872
+ },
1873
+ strong: {
1874
+ flow: true,
1875
+ phrasing: true,
1876
+ permittedContent: ["@phrasing"]
1877
+ },
1878
+ style: {
1879
+ metadata: true
1880
+ },
1881
+ sub: {
1882
+ flow: true,
1883
+ phrasing: true,
1884
+ permittedContent: ["@phrasing"]
1885
+ },
1886
+ summary: {
1887
+ permittedContent: ["@phrasing", "@heading"]
1888
+ },
1889
+ sup: {
1890
+ flow: true,
1891
+ phrasing: true,
1892
+ permittedContent: ["@phrasing"]
1893
+ },
1894
+ svg: {
1895
+ flow: true,
1896
+ foreign: true,
1897
+ phrasing: true,
1898
+ embedded: true
1899
+ },
1900
+ /* while not part of HTML 5 specification these two elements are handled as
1901
+ * special cases to allow them as accessible text and to avoid issues with
1902
+ * "no-unknown-elements" they are added here */
1903
+ "svg:desc": {},
1904
+ "svg:title": {},
1905
+ table: {
1906
+ flow: true,
1907
+ permittedContent: ["@script", "caption?", "colgroup", "tbody", "tfoot?", "thead?", "tr"],
1908
+ permittedOrder: ["caption", "colgroup", "thead", "tbody", "tr", "tfoot"],
1909
+ attributes: {
1910
+ align: {
1911
+ deprecated: true
1912
+ },
1913
+ background: {
1914
+ deprecated: true
1915
+ },
1916
+ bgcolor: {
1917
+ deprecated: true
1918
+ },
1919
+ bordercolor: {
1920
+ deprecated: true
1921
+ },
1922
+ cellpadding: {
1923
+ deprecated: true
1924
+ },
1925
+ cellspacing: {
1926
+ deprecated: true
1927
+ },
1928
+ dataformatas: {
1929
+ deprecated: true
1930
+ },
1931
+ datapagesize: {
1932
+ deprecated: true
1933
+ },
1934
+ datasrc: {
1935
+ deprecated: true
1936
+ },
1937
+ frame: {
1938
+ deprecated: true
1939
+ },
1940
+ rules: {
1941
+ deprecated: true
1942
+ },
1943
+ summary: {
1944
+ deprecated: true
1945
+ },
1946
+ width: {
1947
+ deprecated: true
1948
+ }
1949
+ },
1950
+ implicitRole() {
1951
+ return "table";
1952
+ }
1953
+ },
1954
+ tbody: {
1955
+ implicitClosed: ["tbody", "tfoot"],
1956
+ permittedContent: ["@script", "tr"],
1957
+ attributes: {
1958
+ align: {
1959
+ deprecated: true
1960
+ },
1961
+ background: {
1962
+ deprecated: true
1963
+ },
1964
+ char: {
1965
+ deprecated: true
1966
+ },
1967
+ charoff: {
1968
+ deprecated: true
1969
+ },
1970
+ valign: {
1971
+ deprecated: true
1972
+ }
1973
+ },
1974
+ implicitRole() {
1975
+ return "rowgroup";
1976
+ }
1977
+ },
1978
+ td: {
1979
+ flow: true,
1980
+ implicitClosed: ["td", "th"],
1981
+ attributes: {
1982
+ align: {
1983
+ deprecated: true
1984
+ },
1985
+ axis: {
1986
+ deprecated: true
1987
+ },
1988
+ background: {
1989
+ deprecated: true
1990
+ },
1991
+ bgcolor: {
1992
+ deprecated: true
1993
+ },
1994
+ char: {
1995
+ deprecated: true
1996
+ },
1997
+ charoff: {
1998
+ deprecated: true
1999
+ },
2000
+ colspan: {
2001
+ enum: ["/\\d+/"]
2002
+ },
2003
+ height: {
2004
+ deprecated: true
2005
+ },
2006
+ nowrap: {
2007
+ deprecated: true
2008
+ },
2009
+ rowspan: {
2010
+ enum: ["/\\d+/"]
2011
+ },
2012
+ scope: {
2013
+ deprecated: true
2014
+ },
2015
+ valign: {
2016
+ deprecated: true
2017
+ },
2018
+ width: {
2019
+ deprecated: true
2020
+ }
2021
+ },
2022
+ implicitRole(node) {
2023
+ if (node.closest('table[role="grid"], table[role="treegrid"]')) {
2024
+ return "gridcell";
2025
+ } else if (node.closest("table")) {
2026
+ return "cell";
2027
+ } else {
2028
+ return null;
2029
+ }
2030
+ },
2031
+ permittedContent: ["@flow"]
2032
+ },
2033
+ template: {
2034
+ metadata: true,
2035
+ flow: true,
2036
+ phrasing: true,
2037
+ scriptSupporting: true
2038
+ },
2039
+ textarea: {
2040
+ flow: true,
2041
+ focusable: true,
2042
+ phrasing: true,
2043
+ interactive: true,
2044
+ formAssociated: {
2045
+ listed: true
2046
+ },
2047
+ labelable: true,
2048
+ attributes: {
2049
+ autocomplete: {
2050
+ enum: ["on", "off"]
2051
+ },
2052
+ autofocus: {
2053
+ boolean: true
2054
+ },
2055
+ cols: {
2056
+ enum: ["/\\d+/"]
2057
+ },
2058
+ datafld: {
2059
+ deprecated: true
2060
+ },
2061
+ datasrc: {
2062
+ deprecated: true
2063
+ },
2064
+ disabled: {
2065
+ boolean: true
2066
+ },
2067
+ maxlength: {
2068
+ enum: ["/\\d+/"]
2069
+ },
2070
+ minlength: {
2071
+ enum: ["/\\d+/"]
2072
+ },
2073
+ readonly: {
2074
+ boolean: true
2075
+ },
2076
+ required: {
2077
+ boolean: true
2078
+ },
2079
+ rows: {
2080
+ enum: ["/\\d+/"]
2081
+ },
2082
+ spellcheck: {
2083
+ enum: ["true", "default", "false"]
2084
+ },
2085
+ wrap: {
2086
+ enum: ["hard", "soft"]
2087
+ }
2088
+ },
2089
+ implicitRole() {
2090
+ return "textbox";
2091
+ },
2092
+ permittedContent: []
2093
+ },
2094
+ tfoot: {
2095
+ implicitClosed: ["tbody"],
2096
+ permittedContent: ["@script", "tr"],
2097
+ attributes: {
2098
+ align: {
2099
+ deprecated: true
2100
+ },
2101
+ background: {
2102
+ deprecated: true
2103
+ },
2104
+ char: {
2105
+ deprecated: true
2106
+ },
2107
+ charoff: {
2108
+ deprecated: true
2109
+ },
2110
+ valign: {
2111
+ deprecated: true
2112
+ }
2113
+ },
2114
+ implicitRole() {
2115
+ return "rowgroup";
2116
+ }
2117
+ },
2118
+ th: {
2119
+ flow: true,
2120
+ implicitClosed: ["td", "th"],
2121
+ attributes: {
2122
+ align: {
2123
+ deprecated: true
2124
+ },
2125
+ axis: {
2126
+ deprecated: true
2127
+ },
2128
+ background: {
2129
+ deprecated: true
2130
+ },
2131
+ bgcolor: {
2132
+ deprecated: true
2133
+ },
2134
+ char: {
2135
+ deprecated: true
2136
+ },
2137
+ charoff: {
2138
+ deprecated: true
2139
+ },
2140
+ colspan: {
2141
+ enum: ["/\\d+/"]
2142
+ },
2143
+ height: {
2144
+ deprecated: true
2145
+ },
2146
+ nowrap: {
2147
+ deprecated: true
2148
+ },
2149
+ rowspan: {
2150
+ enum: ["/\\d+/"]
2151
+ },
2152
+ scope: {
2153
+ enum: ["row", "col", "rowgroup", "colgroup"]
2154
+ },
2155
+ valign: {
2156
+ deprecated: true
2157
+ },
2158
+ width: {
2159
+ deprecated: true
2160
+ }
2161
+ },
2162
+ implicitRole(node) {
2163
+ const table = node.closest("table");
2164
+ if (!table) {
2165
+ return null;
2166
+ }
2167
+ const tableRole = table.getAttribute("role") ?? "table";
2168
+ if (typeof tableRole !== "string" || !["table", "grid", "treegrid"].includes(tableRole)) {
2169
+ return null;
2170
+ }
2171
+ const scope = node.getAttribute("scope");
2172
+ switch (scope) {
2173
+ case "col":
2174
+ return "columnheader";
2175
+ case "row":
2176
+ return "rowheader";
2177
+ default:
2178
+ return tableRole === "table" ? "cell" : "gridcell";
2179
+ }
2180
+ },
2181
+ permittedContent: ["@flow"],
2182
+ permittedDescendants: [{ exclude: ["header", "footer", "@sectioning", "@heading"] }]
2183
+ },
2184
+ thead: {
2185
+ implicitClosed: ["tbody", "tfoot"],
2186
+ permittedContent: ["@script", "tr"],
2187
+ attributes: {
2188
+ align: {
2189
+ deprecated: true
2190
+ },
2191
+ background: {
2192
+ deprecated: true
2193
+ },
2194
+ char: {
2195
+ deprecated: true
2196
+ },
2197
+ charoff: {
2198
+ deprecated: true
2199
+ },
2200
+ valign: {
2201
+ deprecated: true
2202
+ }
2203
+ },
2204
+ implicitRole() {
2205
+ return "rowgroup";
2206
+ }
2207
+ },
2208
+ time: {
2209
+ flow: true,
2210
+ phrasing: true,
2211
+ implicitRole() {
2212
+ return "time";
2213
+ },
2214
+ permittedContent: ["@phrasing"]
2215
+ },
2216
+ title: {
2217
+ metadata: true,
2218
+ permittedContent: [],
2219
+ permittedParent: ["head"]
2220
+ },
2221
+ tr: {
2222
+ implicitClosed: ["tr"],
2223
+ permittedContent: ["@script", "td", "th"],
2224
+ attributes: {
2225
+ align: {
2226
+ deprecated: true
2227
+ },
2228
+ background: {
2229
+ deprecated: true
2230
+ },
2231
+ bgcolor: {
2232
+ deprecated: true
2233
+ },
2234
+ char: {
2235
+ deprecated: true
2236
+ },
2237
+ charoff: {
2238
+ deprecated: true
2239
+ },
2240
+ valign: {
2241
+ deprecated: true
2242
+ }
2243
+ },
2244
+ implicitRole() {
2245
+ return "row";
2246
+ }
2247
+ },
2248
+ track: {
2249
+ void: true
2250
+ },
2251
+ tt: {
2252
+ deprecated: {
2253
+ documentation: "Use a more semantically correct element such as `<code>`, `<var>` or `<pre>`.",
2254
+ source: "html4"
2255
+ }
2256
+ },
2257
+ u: {
2258
+ flow: true,
2259
+ phrasing: true,
2260
+ permittedContent: ["@phrasing"]
2261
+ },
2262
+ ul: {
2263
+ flow: true,
2264
+ permittedContent: ["@script", "li"],
2265
+ attributes: {
2266
+ compact: {
2267
+ deprecated: true
2268
+ },
2269
+ type: {
2270
+ deprecated: true
2271
+ }
2272
+ },
2273
+ implicitRole() {
2274
+ return "list";
2275
+ }
2276
+ },
2277
+ var: {
2278
+ flow: true,
2279
+ phrasing: true,
2280
+ permittedContent: ["@phrasing"]
2281
+ },
2282
+ video: {
2283
+ flow: true,
2284
+ focusable(node) {
2285
+ return node.hasAttribute("controls");
2286
+ },
2287
+ phrasing: true,
2288
+ embedded: true,
2289
+ interactive: ["hasAttribute", "controls"],
2290
+ transparent: ["@flow"],
2291
+ attributes: {
2292
+ crossorigin: {
2293
+ omit: true,
2294
+ enum: ["anonymous", "use-credentials"]
2295
+ },
2296
+ itemprop: {
2297
+ allowed: allowedIfAttributeIsPresent("src")
2298
+ },
2299
+ preload: {
2300
+ omit: true,
2301
+ enum: ["none", "metadata", "auto"]
2302
+ }
2303
+ },
2304
+ permittedContent: ["@flow", "track", "source"],
2305
+ permittedDescendants: [{ exclude: ["audio", "video"] }],
2306
+ permittedOrder: ["source", "track", "@flow"]
2307
+ },
2308
+ wbr: {
2309
+ flow: true,
2310
+ phrasing: true,
2311
+ void: true
2312
+ },
2313
+ xmp: {
2314
+ deprecated: {
2315
+ documentation: "Use `<pre>` or `<code>` and escape content using HTML entities instead.",
2316
+ source: "html32"
2317
+ }
2318
+ }
2304
2319
  });
2305
2320
 
2306
2321
  const bundledElements = {
2307
- html5,
2322
+ html5
2308
2323
  };
2309
2324
 
2310
2325
  var entities = [