aria-api 0.4.7 → 0.5.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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017 Tobias Bengfort
3
+ Copyright (c) 2017-2023 Tobias Bengfort
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -106,11 +106,11 @@ That said, this is what I think it could also be used for:
106
106
 
107
107
  # Implemented standards
108
108
 
109
- - [Accessible Rich Internet Applications 1.1](https://www.w3.org/TR/wai-aria-1.1/)
110
- - [Core Accessibility API Mappings 1.1](https://www.w3.org/TR/core-aam-1.1/)
109
+ - [Accessible Rich Internet Applications 1.2](https://www.w3.org/TR/wai-aria-1.2/)
111
110
  - [HTML Accessibility API Mappings 1.0](https://www.w3.org/TR/html-aam-1.0/)
111
+ - [SVG Accessibility API Mappings](https://www.w3.org/TR/svg-aam-1.0/) (very incomplete)
112
112
  - [WAI-ARIA Graphics Module 1.0](https://www.w3.org/TR/graphics-aria-1.0/)
113
- - [Digital Publishing WAI-ARIA Module 1.0](https://www.w3.org/TR/dpub-aria-1.0/)
113
+ - [Digital Publishing WAI-ARIA Module 1.1](https://www.w3.org/TR/dpub-aria-1.1/)
114
114
  - [Accessible Name and Description Computation 1.1](https://www.w3.org/TR/accname-1.1/)
115
115
 
116
116
  I try to update the code whenever a new version of these specs becomes a
@@ -135,7 +135,7 @@ recommendation.
135
135
 
136
136
  # Related projects
137
137
 
138
- - [Visual ARIA Bookmarklet](http://whatsock.com/training/matrices/visual-aria.htm):
138
+ - [Visual ARIA Bookmarklet](https://whatsock.github.io/visual-aria/github-bookmarklet/visual-aria.htm):
139
139
  Displays role, name, and description in any website. Maintained by one of
140
140
  the editors of the [accname]() spec.
141
141
  - [axe-core](https://github.com/dequelabs/axe-core/) and
package/dist/aria.js CHANGED
@@ -123,22 +123,26 @@ var constants = require('./constants.js');
123
123
  // candidates can be passed for performance optimization
124
124
  var getRole = function(el, candidates) {
125
125
  if (el.hasAttribute('role')) {
126
- var role = el.getAttribute('role');
127
- if (!candidates || candidates.includes(role)) {
128
- return role;
129
- } else {
130
- return;
126
+ var roles = el.getAttribute('role').toLowerCase().split(/\s+/);
127
+ if (roles.length > 1 && candidates) {
128
+ return [roles, candidates];
131
129
  }
132
- }
133
- var roles = candidates ? candidates : Object.keys(constants.roles);
134
- for (var role of roles) {
135
- var r = constants.roles[role];
136
- if (r) {
137
- var selector = (r.selectors || []).join(',');
138
- if (selector && el.matches(selector)) {
130
+ for (var role of roles) {
131
+ if (!candidates || candidates.includes(role)) {
139
132
  return role;
140
133
  }
141
134
  }
135
+ } else {
136
+ var roles = candidates ? candidates : Object.keys(constants.roles);
137
+ for (var role of roles) {
138
+ var r = constants.roles[role];
139
+ if (r) {
140
+ var selector = (r.selectors || []).join(',');
141
+ if (selector && el.matches(selector)) {
142
+ return role;
143
+ }
144
+ }
145
+ }
142
146
  }
143
147
  };
144
148
 
@@ -301,13 +305,8 @@ exports.attributeWeakMapping = {
301
305
  'selected': 'selected',
302
306
  };
303
307
 
304
- var scoped = [
305
- 'main *',
306
- // https://www.w3.org/TR/html/dom.html#sectioning-content-2
307
- 'article *', 'aside *', 'nav *', 'section *',
308
- // https://www.w3.org/TR/html/sections.html#sectioning-roots
309
- 'blockquote *', 'details *', 'dialog *', 'fieldset *', 'figure *', 'td *',
310
- ].join(',');
308
+ // https://www.w3.org/TR/html/dom.html#sectioning-content-2
309
+ var scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
311
310
 
312
311
  // https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
313
312
  // https://www.w3.org/TR/wai-aria/roles
@@ -323,7 +322,10 @@ exports.roles = {
323
322
  selectors: ['article'],
324
323
  },
325
324
  banner: {
326
- selectors: ['header:not(' + scoped + ')'],
325
+ selectors: [`header:not(main *, ${scoped})`],
326
+ },
327
+ blockquote: {
328
+ selectors: ['blockquote'],
327
329
  },
328
330
  button: {
329
331
  selectors: [
@@ -336,26 +338,32 @@ exports.roles = {
336
338
  ],
337
339
  nameFromContents: true,
338
340
  },
341
+ caption: {
342
+ selectors: ['caption', 'figcaption'],
343
+ },
339
344
  cell: {
340
- selectors: ['td'],
341
- childRoles: ['gridcell', 'rowheader'],
345
+ selectors: ['td', 'th:not([scope])'],
346
+ childRoles: ['columnheader', 'gridcell', 'rowheader'],
342
347
  nameFromContents: true,
343
348
  },
344
349
  checkbox: {
345
350
  selectors: ['input[type="checkbox"]'],
346
- childRoles: ['menuitemcheckbox', 'switch'],
351
+ childRoles: ['switch'],
347
352
  nameFromContents: true,
348
353
  defaults: {
349
354
  'checked': 'false',
350
355
  },
351
356
  },
357
+ code: {
358
+ selectors: ['code'],
359
+ },
352
360
  columnheader: {
353
361
  selectors: ['th[scope="col"]'],
354
362
  nameFromContents: true,
355
363
  },
356
364
  combobox: {
357
365
  selectors: [
358
- 'input:not([type])[list]',
366
+ 'input:not([type])[list]',
359
367
  'input[type="email"][list]',
360
368
  'input[type="search"][list]',
361
369
  'input[type="tel"][list]',
@@ -374,17 +382,25 @@ exports.roles = {
374
382
  childRoles: ['button', 'link', 'menuitem'],
375
383
  },
376
384
  complementary: {
377
- selectors: ['aside'],
385
+ selectors: [
386
+ `aside:not(${scoped})`,
387
+ 'aside[aria-label]',
388
+ 'aside[aria-labelledby]',
389
+ 'aside[title]',
390
+ ],
378
391
  },
379
392
  composite: {
380
393
  childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
381
394
  },
382
395
  contentinfo: {
383
- selectors: ['footer:not(' + scoped + ')'],
396
+ selectors: [`footer:not(main *, ${scoped})`],
384
397
  },
385
398
  definition: {
386
399
  selectors: ['dd'],
387
400
  },
401
+ deletion: {
402
+ selectors: ['del', 's'],
403
+ },
388
404
  dialog: {
389
405
  selectors: ['dialog'],
390
406
  childRoles: ['alertdialog'],
@@ -401,16 +417,32 @@ exports.roles = {
401
417
  'doc-noteref': {
402
418
  nameFromContents: true,
403
419
  },
420
+ 'doc-pagebreak': {
421
+ nameFromContents: true,
422
+ },
423
+ 'doc-subtitle': {
424
+ nameFromContents: true,
425
+ },
404
426
  document: {
405
- selectors: ['body'],
427
+ selectors: ['html'],
406
428
  childRoles: ['article', 'graphics-document'],
407
429
  },
430
+ emphasis: {
431
+ selectors: ['em'],
432
+ },
408
433
  figure: {
409
434
  selectors: ['figure'],
435
+ childRoles: ['doc-example'],
410
436
  },
411
437
  form: {
412
438
  selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
413
439
  },
440
+ generic: {
441
+ // too many selectors to list
442
+ },
443
+ 'graphics-document': {
444
+ selectors: ['svg'],
445
+ },
414
446
  grid: {
415
447
  childRoles: ['treegrid'],
416
448
  },
@@ -419,7 +451,14 @@ exports.roles = {
419
451
  nameFromContents: true,
420
452
  },
421
453
  group: {
422
- selectors: ['details', 'optgroup'],
454
+ selectors: [
455
+ 'address',
456
+ 'details',
457
+ 'fieldset',
458
+ 'hgroup',
459
+ 'optgroup',
460
+ 'text',
461
+ ],
423
462
  childRoles: ['row', 'select', 'toolbar', 'graphics-object'],
424
463
  },
425
464
  heading: {
@@ -434,7 +473,18 @@ exports.roles = {
434
473
  childRoles: ['doc-cover'],
435
474
  },
436
475
  input: {
437
- childRoles: ['checkbox', 'option', 'radio', 'slider', 'spinbutton', 'textbox'],
476
+ childRoles: [
477
+ 'checkbox',
478
+ 'combobox',
479
+ 'option',
480
+ 'radio',
481
+ 'slider',
482
+ 'spinbutton',
483
+ 'textbox',
484
+ ],
485
+ },
486
+ insertion: {
487
+ selectors: ['ins'],
438
488
  },
439
489
  landmark: {
440
490
  childRoles: [
@@ -465,16 +515,17 @@ exports.roles = {
465
515
  ],
466
516
  },
467
517
  link: {
468
- selectors: ['a[href]', 'area[href]', 'link[href]'],
518
+ selectors: ['a[href]', 'area[href]'],
469
519
  childRoles: ['doc-backlink', 'doc-biblioref', 'doc-glossref', 'doc-noteref'],
470
520
  nameFromContents: true,
471
521
  },
472
522
  list: {
473
- selectors: ['dl', 'ol', 'ul'],
523
+ selectors: ['dl', 'ol', 'ul', 'menu'],
474
524
  childRoles: ['directory', 'feed'],
475
525
  },
476
526
  listbox: {
477
527
  selectors: [
528
+ 'datalist',
478
529
  'select[multiple]',
479
530
  'select[size]:not([size="0"]):not([size="1"])',
480
531
  ],
@@ -483,7 +534,7 @@ exports.roles = {
483
534
  },
484
535
  },
485
536
  listitem: {
486
- selectors: ['dt', 'ul > li', 'ol > li'],
537
+ selectors: ['li'],
487
538
  childRoles: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
488
539
  },
489
540
  log: {
@@ -497,8 +548,14 @@ exports.roles = {
497
548
  math: {
498
549
  selectors: ['math'],
499
550
  },
551
+ meter: {
552
+ selectors: ['meter'],
553
+ defaults: {
554
+ 'valuemin': 0,
555
+ 'valuemax': 100,
556
+ },
557
+ },
500
558
  menu: {
501
- selectors: ['menu[type="context"]'],
502
559
  childRoles: ['menubar'],
503
560
  defaults: {
504
561
  'orientation': 'vertical',
@@ -510,12 +567,10 @@ exports.roles = {
510
567
  },
511
568
  },
512
569
  menuitem: {
513
- selectors: ['menuitem[type="command"]'],
514
570
  childRoles: ['menuitemcheckbox'],
515
571
  nameFromContents: true,
516
572
  },
517
573
  menuitemcheckbox: {
518
- selectors: ['menuitem[type="checkbox"]'],
519
574
  childRoles: ['menuitemradio'],
520
575
  nameFromContents: true,
521
576
  defaults: {
@@ -523,7 +578,6 @@ exports.roles = {
523
578
  },
524
579
  },
525
580
  menuitemradio: {
526
- selectors: ['menuitem[type="radio"]'],
527
581
  nameFromContents: true,
528
582
  defaults: {
529
583
  'checked': 'false',
@@ -544,11 +598,18 @@ exports.roles = {
544
598
  'selected': 'false',
545
599
  },
546
600
  },
601
+ paragraph: {
602
+ selectors: ['p'],
603
+ },
547
604
  presentation: {
548
605
  selectors: ['img[alt=""]'],
549
606
  },
550
607
  progressbar: {
551
608
  selectors: ['progress'],
609
+ defaults: {
610
+ 'valuemin': 0,
611
+ 'valuemax': 100,
612
+ },
552
613
  },
553
614
  radio: {
554
615
  selectors: ['input[type="radio"]'],
@@ -559,7 +620,7 @@ exports.roles = {
559
620
  },
560
621
  },
561
622
  range: {
562
- childRoles: ['progressbar', 'scrollbar', 'slider', 'spinbutton'],
623
+ childRoles: ['meter', 'progressbar', 'scrollbar', 'slider', 'spinbutton'],
563
624
  },
564
625
  region: {
565
626
  selectors: ['section[aria-label]', 'section[aria-labelledby]', 'section[title]'],
@@ -573,7 +634,6 @@ exports.roles = {
573
634
  },
574
635
  rowgroup: {
575
636
  selectors: ['tbody', 'thead', 'tfoot'],
576
- nameFromContents: true,
577
637
  },
578
638
  rowheader: {
579
639
  selectors: ['th[scope="row"]'],
@@ -584,29 +644,38 @@ exports.roles = {
584
644
  'orientation': 'vertical',
585
645
  'valuemin': 0,
586
646
  'valuemax': 100,
587
- // FIXME: halfway between actual valuemin and valuemax
588
- 'valuenow': 50,
589
647
  },
590
648
  },
649
+ search: {
650
+ selectors: ['search'],
651
+ },
591
652
  searchbox: {
592
653
  selectors: ['input[type="search"]:not([list])'],
593
654
  },
594
655
  section: {
595
656
  childRoles: [
596
657
  'alert',
658
+ 'blockquote',
659
+ 'caption',
597
660
  'cell',
661
+ 'code',
598
662
  'definition',
663
+ 'deletion',
599
664
  'doc-abstract',
600
665
  'doc-colophon',
601
666
  'doc-credit',
602
667
  'doc-dedication',
603
668
  'doc-epigraph',
604
- 'doc-example',
605
669
  'doc-footnote',
670
+ 'doc-pagefooter',
671
+ 'doc-pageheader',
672
+ 'doc-pullquote',
606
673
  'doc-qna',
674
+ 'emphasis',
607
675
  'figure',
608
676
  'group',
609
677
  'img',
678
+ 'insertion',
610
679
  'landmark',
611
680
  'list',
612
681
  'listitem',
@@ -614,10 +683,15 @@ exports.roles = {
614
683
  'marquee',
615
684
  'math',
616
685
  'note',
686
+ 'paragraph',
617
687
  'status',
688
+ 'strong',
689
+ 'subscript',
690
+ 'superscript',
618
691
  'table',
619
692
  'tabpanel',
620
693
  'term',
694
+ 'time',
621
695
  'tooltip',
622
696
  ],
623
697
  },
@@ -632,7 +706,7 @@ exports.roles = {
632
706
  nameFromContents: true,
633
707
  },
634
708
  select: {
635
- childRoles: ['combobox', 'listbox', 'menu', 'radiogroup', 'tree'],
709
+ childRoles: ['listbox', 'menu', 'radiogroup', 'tree'],
636
710
  },
637
711
  separator: {
638
712
  // assume not focussable because <hr> is not
@@ -640,6 +714,8 @@ exports.roles = {
640
714
  childRoles: ['doc-pagebreak'],
641
715
  defaults: {
642
716
  'orientation': 'horizontal',
717
+ 'valuemin': 0,
718
+ 'valuemax': 100,
643
719
  },
644
720
  },
645
721
  slider: {
@@ -655,8 +731,7 @@ exports.roles = {
655
731
  spinbutton: {
656
732
  selectors: ['input[type="number"]'],
657
733
  defaults: {
658
- // FIXME: no valuemin/valuemax
659
- 'valuenow': 0,
734
+ // FIXME: no valuemin/valuemax/valuenow
660
735
  },
661
736
  },
662
737
  status: {
@@ -667,18 +742,29 @@ exports.roles = {
667
742
  'atomic': true,
668
743
  },
669
744
  },
745
+ strong: {
746
+ selectors: ['strong'],
747
+ },
670
748
  structure: {
671
749
  childRoles: [
672
750
  'application',
673
751
  'document',
674
752
  'none',
753
+ 'generic',
675
754
  'presentation',
755
+ 'range',
676
756
  'rowgroup',
677
757
  'section',
678
758
  'sectionhead',
679
759
  'separator',
680
760
  ],
681
761
  },
762
+ subscript: {
763
+ selectors: ['sub'],
764
+ },
765
+ superscript: {
766
+ selectors: ['sup'],
767
+ },
682
768
  switch: {
683
769
  nameFromContents: true,
684
770
  defaults: {
@@ -714,6 +800,14 @@ exports.roles = {
714
800
  ],
715
801
  childRoles: ['searchbox'],
716
802
  },
803
+ time: {
804
+ selectors: ['time'],
805
+ },
806
+ timer: {
807
+ defaults: {
808
+ 'live': 'off',
809
+ },
810
+ },
717
811
  toolbar: {
718
812
  defaults: {
719
813
  'orientation': 'horizontal',
@@ -737,8 +831,10 @@ exports.roles = {
737
831
  'composite',
738
832
  'gridcell',
739
833
  'input',
740
- 'range',
834
+ 'progressbar',
741
835
  'row',
836
+ 'scrollbar',
837
+ 'separator',
742
838
  'tab',
743
839
  ],
744
840
  },
@@ -905,6 +1001,12 @@ var getName = function(el, recursive, visited, directReference) {
905
1001
  }
906
1002
  }
907
1003
  }
1004
+ if (!ret.trim() && el.matches('svg *')) {
1005
+ var svgTitle = el.querySelector('title');
1006
+ if (svgTitle && svgTitle.parentElement === el) {
1007
+ ret = svgTitle.textContent;
1008
+ }
1009
+ }
908
1010
 
909
1011
  // E
910
1012
  if (!ret.trim() && (recursive || isInLabelForOtherWidget(el) || query.matches(el, 'button'))) {
@@ -972,10 +1074,15 @@ var getDescription = function(el) {
972
1074
  return label ? getName(label, true) : '';
973
1075
  });
974
1076
  ret = strings.join(' ');
1077
+ } else if (el.matches('[aria-description]')) {
1078
+ ret = el.getAttribute('aria-description');
1079
+ } else if (el.matches('svg *')) {
1080
+ var svgDesc = el.querySelector('desc');
1081
+ if (svgDesc && svgDesc.parentElement === el) {
1082
+ ret = svgDesc.textContent;
1083
+ }
975
1084
  } else if (el.title) {
976
1085
  ret = el.title;
977
- } else if (el.placeholder) {
978
- ret = el.placeholder;
979
1086
  }
980
1087
 
981
1088
  ret = (ret || '').trim().replace(/\s+/g, ' ');
package/lib/attrs.js CHANGED
@@ -3,22 +3,26 @@ var constants = require('./constants.js');
3
3
  // candidates can be passed for performance optimization
4
4
  var getRole = function(el, candidates) {
5
5
  if (el.hasAttribute('role')) {
6
- var role = el.getAttribute('role');
7
- if (!candidates || candidates.includes(role)) {
8
- return role;
9
- } else {
10
- return;
6
+ var roles = el.getAttribute('role').toLowerCase().split(/\s+/);
7
+ if (roles.length > 1 && candidates) {
8
+ return [roles, candidates];
11
9
  }
12
- }
13
- var roles = candidates ? candidates : Object.keys(constants.roles);
14
- for (var role of roles) {
15
- var r = constants.roles[role];
16
- if (r) {
17
- var selector = (r.selectors || []).join(',');
18
- if (selector && el.matches(selector)) {
10
+ for (var role of roles) {
11
+ if (!candidates || candidates.includes(role)) {
19
12
  return role;
20
13
  }
21
14
  }
15
+ } else {
16
+ var roles = candidates ? candidates : Object.keys(constants.roles);
17
+ for (var role of roles) {
18
+ var r = constants.roles[role];
19
+ if (r) {
20
+ var selector = (r.selectors || []).join(',');
21
+ if (selector && el.matches(selector)) {
22
+ return role;
23
+ }
24
+ }
25
+ }
22
26
  }
23
27
  };
24
28
 
package/lib/constants.js CHANGED
@@ -66,13 +66,8 @@ exports.attributeWeakMapping = {
66
66
  'selected': 'selected',
67
67
  };
68
68
 
69
- var scoped = [
70
- 'main *',
71
- // https://www.w3.org/TR/html/dom.html#sectioning-content-2
72
- 'article *', 'aside *', 'nav *', 'section *',
73
- // https://www.w3.org/TR/html/sections.html#sectioning-roots
74
- 'blockquote *', 'details *', 'dialog *', 'fieldset *', 'figure *', 'td *',
75
- ].join(',');
69
+ // https://www.w3.org/TR/html/dom.html#sectioning-content-2
70
+ var scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
76
71
 
77
72
  // https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
78
73
  // https://www.w3.org/TR/wai-aria/roles
@@ -88,7 +83,10 @@ exports.roles = {
88
83
  selectors: ['article'],
89
84
  },
90
85
  banner: {
91
- selectors: ['header:not(' + scoped + ')'],
86
+ selectors: [`header:not(main *, ${scoped})`],
87
+ },
88
+ blockquote: {
89
+ selectors: ['blockquote'],
92
90
  },
93
91
  button: {
94
92
  selectors: [
@@ -101,26 +99,32 @@ exports.roles = {
101
99
  ],
102
100
  nameFromContents: true,
103
101
  },
102
+ caption: {
103
+ selectors: ['caption', 'figcaption'],
104
+ },
104
105
  cell: {
105
- selectors: ['td'],
106
- childRoles: ['gridcell', 'rowheader'],
106
+ selectors: ['td', 'th:not([scope])'],
107
+ childRoles: ['columnheader', 'gridcell', 'rowheader'],
107
108
  nameFromContents: true,
108
109
  },
109
110
  checkbox: {
110
111
  selectors: ['input[type="checkbox"]'],
111
- childRoles: ['menuitemcheckbox', 'switch'],
112
+ childRoles: ['switch'],
112
113
  nameFromContents: true,
113
114
  defaults: {
114
115
  'checked': 'false',
115
116
  },
116
117
  },
118
+ code: {
119
+ selectors: ['code'],
120
+ },
117
121
  columnheader: {
118
122
  selectors: ['th[scope="col"]'],
119
123
  nameFromContents: true,
120
124
  },
121
125
  combobox: {
122
126
  selectors: [
123
- 'input:not([type])[list]',
127
+ 'input:not([type])[list]',
124
128
  'input[type="email"][list]',
125
129
  'input[type="search"][list]',
126
130
  'input[type="tel"][list]',
@@ -139,17 +143,25 @@ exports.roles = {
139
143
  childRoles: ['button', 'link', 'menuitem'],
140
144
  },
141
145
  complementary: {
142
- selectors: ['aside'],
146
+ selectors: [
147
+ `aside:not(${scoped})`,
148
+ 'aside[aria-label]',
149
+ 'aside[aria-labelledby]',
150
+ 'aside[title]',
151
+ ],
143
152
  },
144
153
  composite: {
145
154
  childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
146
155
  },
147
156
  contentinfo: {
148
- selectors: ['footer:not(' + scoped + ')'],
157
+ selectors: [`footer:not(main *, ${scoped})`],
149
158
  },
150
159
  definition: {
151
160
  selectors: ['dd'],
152
161
  },
162
+ deletion: {
163
+ selectors: ['del', 's'],
164
+ },
153
165
  dialog: {
154
166
  selectors: ['dialog'],
155
167
  childRoles: ['alertdialog'],
@@ -166,16 +178,32 @@ exports.roles = {
166
178
  'doc-noteref': {
167
179
  nameFromContents: true,
168
180
  },
181
+ 'doc-pagebreak': {
182
+ nameFromContents: true,
183
+ },
184
+ 'doc-subtitle': {
185
+ nameFromContents: true,
186
+ },
169
187
  document: {
170
- selectors: ['body'],
188
+ selectors: ['html'],
171
189
  childRoles: ['article', 'graphics-document'],
172
190
  },
191
+ emphasis: {
192
+ selectors: ['em'],
193
+ },
173
194
  figure: {
174
195
  selectors: ['figure'],
196
+ childRoles: ['doc-example'],
175
197
  },
176
198
  form: {
177
199
  selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
178
200
  },
201
+ generic: {
202
+ // too many selectors to list
203
+ },
204
+ 'graphics-document': {
205
+ selectors: ['svg'],
206
+ },
179
207
  grid: {
180
208
  childRoles: ['treegrid'],
181
209
  },
@@ -184,7 +212,14 @@ exports.roles = {
184
212
  nameFromContents: true,
185
213
  },
186
214
  group: {
187
- selectors: ['details', 'optgroup'],
215
+ selectors: [
216
+ 'address',
217
+ 'details',
218
+ 'fieldset',
219
+ 'hgroup',
220
+ 'optgroup',
221
+ 'text',
222
+ ],
188
223
  childRoles: ['row', 'select', 'toolbar', 'graphics-object'],
189
224
  },
190
225
  heading: {
@@ -199,7 +234,18 @@ exports.roles = {
199
234
  childRoles: ['doc-cover'],
200
235
  },
201
236
  input: {
202
- childRoles: ['checkbox', 'option', 'radio', 'slider', 'spinbutton', 'textbox'],
237
+ childRoles: [
238
+ 'checkbox',
239
+ 'combobox',
240
+ 'option',
241
+ 'radio',
242
+ 'slider',
243
+ 'spinbutton',
244
+ 'textbox',
245
+ ],
246
+ },
247
+ insertion: {
248
+ selectors: ['ins'],
203
249
  },
204
250
  landmark: {
205
251
  childRoles: [
@@ -230,16 +276,17 @@ exports.roles = {
230
276
  ],
231
277
  },
232
278
  link: {
233
- selectors: ['a[href]', 'area[href]', 'link[href]'],
279
+ selectors: ['a[href]', 'area[href]'],
234
280
  childRoles: ['doc-backlink', 'doc-biblioref', 'doc-glossref', 'doc-noteref'],
235
281
  nameFromContents: true,
236
282
  },
237
283
  list: {
238
- selectors: ['dl', 'ol', 'ul'],
284
+ selectors: ['dl', 'ol', 'ul', 'menu'],
239
285
  childRoles: ['directory', 'feed'],
240
286
  },
241
287
  listbox: {
242
288
  selectors: [
289
+ 'datalist',
243
290
  'select[multiple]',
244
291
  'select[size]:not([size="0"]):not([size="1"])',
245
292
  ],
@@ -248,7 +295,7 @@ exports.roles = {
248
295
  },
249
296
  },
250
297
  listitem: {
251
- selectors: ['dt', 'ul > li', 'ol > li'],
298
+ selectors: ['li'],
252
299
  childRoles: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
253
300
  },
254
301
  log: {
@@ -262,8 +309,14 @@ exports.roles = {
262
309
  math: {
263
310
  selectors: ['math'],
264
311
  },
312
+ meter: {
313
+ selectors: ['meter'],
314
+ defaults: {
315
+ 'valuemin': 0,
316
+ 'valuemax': 100,
317
+ },
318
+ },
265
319
  menu: {
266
- selectors: ['menu[type="context"]'],
267
320
  childRoles: ['menubar'],
268
321
  defaults: {
269
322
  'orientation': 'vertical',
@@ -275,12 +328,10 @@ exports.roles = {
275
328
  },
276
329
  },
277
330
  menuitem: {
278
- selectors: ['menuitem[type="command"]'],
279
331
  childRoles: ['menuitemcheckbox'],
280
332
  nameFromContents: true,
281
333
  },
282
334
  menuitemcheckbox: {
283
- selectors: ['menuitem[type="checkbox"]'],
284
335
  childRoles: ['menuitemradio'],
285
336
  nameFromContents: true,
286
337
  defaults: {
@@ -288,7 +339,6 @@ exports.roles = {
288
339
  },
289
340
  },
290
341
  menuitemradio: {
291
- selectors: ['menuitem[type="radio"]'],
292
342
  nameFromContents: true,
293
343
  defaults: {
294
344
  'checked': 'false',
@@ -309,11 +359,18 @@ exports.roles = {
309
359
  'selected': 'false',
310
360
  },
311
361
  },
362
+ paragraph: {
363
+ selectors: ['p'],
364
+ },
312
365
  presentation: {
313
366
  selectors: ['img[alt=""]'],
314
367
  },
315
368
  progressbar: {
316
369
  selectors: ['progress'],
370
+ defaults: {
371
+ 'valuemin': 0,
372
+ 'valuemax': 100,
373
+ },
317
374
  },
318
375
  radio: {
319
376
  selectors: ['input[type="radio"]'],
@@ -324,7 +381,7 @@ exports.roles = {
324
381
  },
325
382
  },
326
383
  range: {
327
- childRoles: ['progressbar', 'scrollbar', 'slider', 'spinbutton'],
384
+ childRoles: ['meter', 'progressbar', 'scrollbar', 'slider', 'spinbutton'],
328
385
  },
329
386
  region: {
330
387
  selectors: ['section[aria-label]', 'section[aria-labelledby]', 'section[title]'],
@@ -338,7 +395,6 @@ exports.roles = {
338
395
  },
339
396
  rowgroup: {
340
397
  selectors: ['tbody', 'thead', 'tfoot'],
341
- nameFromContents: true,
342
398
  },
343
399
  rowheader: {
344
400
  selectors: ['th[scope="row"]'],
@@ -349,29 +405,38 @@ exports.roles = {
349
405
  'orientation': 'vertical',
350
406
  'valuemin': 0,
351
407
  'valuemax': 100,
352
- // FIXME: halfway between actual valuemin and valuemax
353
- 'valuenow': 50,
354
408
  },
355
409
  },
410
+ search: {
411
+ selectors: ['search'],
412
+ },
356
413
  searchbox: {
357
414
  selectors: ['input[type="search"]:not([list])'],
358
415
  },
359
416
  section: {
360
417
  childRoles: [
361
418
  'alert',
419
+ 'blockquote',
420
+ 'caption',
362
421
  'cell',
422
+ 'code',
363
423
  'definition',
424
+ 'deletion',
364
425
  'doc-abstract',
365
426
  'doc-colophon',
366
427
  'doc-credit',
367
428
  'doc-dedication',
368
429
  'doc-epigraph',
369
- 'doc-example',
370
430
  'doc-footnote',
431
+ 'doc-pagefooter',
432
+ 'doc-pageheader',
433
+ 'doc-pullquote',
371
434
  'doc-qna',
435
+ 'emphasis',
372
436
  'figure',
373
437
  'group',
374
438
  'img',
439
+ 'insertion',
375
440
  'landmark',
376
441
  'list',
377
442
  'listitem',
@@ -379,10 +444,15 @@ exports.roles = {
379
444
  'marquee',
380
445
  'math',
381
446
  'note',
447
+ 'paragraph',
382
448
  'status',
449
+ 'strong',
450
+ 'subscript',
451
+ 'superscript',
383
452
  'table',
384
453
  'tabpanel',
385
454
  'term',
455
+ 'time',
386
456
  'tooltip',
387
457
  ],
388
458
  },
@@ -397,7 +467,7 @@ exports.roles = {
397
467
  nameFromContents: true,
398
468
  },
399
469
  select: {
400
- childRoles: ['combobox', 'listbox', 'menu', 'radiogroup', 'tree'],
470
+ childRoles: ['listbox', 'menu', 'radiogroup', 'tree'],
401
471
  },
402
472
  separator: {
403
473
  // assume not focussable because <hr> is not
@@ -405,6 +475,8 @@ exports.roles = {
405
475
  childRoles: ['doc-pagebreak'],
406
476
  defaults: {
407
477
  'orientation': 'horizontal',
478
+ 'valuemin': 0,
479
+ 'valuemax': 100,
408
480
  },
409
481
  },
410
482
  slider: {
@@ -420,8 +492,7 @@ exports.roles = {
420
492
  spinbutton: {
421
493
  selectors: ['input[type="number"]'],
422
494
  defaults: {
423
- // FIXME: no valuemin/valuemax
424
- 'valuenow': 0,
495
+ // FIXME: no valuemin/valuemax/valuenow
425
496
  },
426
497
  },
427
498
  status: {
@@ -432,18 +503,29 @@ exports.roles = {
432
503
  'atomic': true,
433
504
  },
434
505
  },
506
+ strong: {
507
+ selectors: ['strong'],
508
+ },
435
509
  structure: {
436
510
  childRoles: [
437
511
  'application',
438
512
  'document',
439
513
  'none',
514
+ 'generic',
440
515
  'presentation',
516
+ 'range',
441
517
  'rowgroup',
442
518
  'section',
443
519
  'sectionhead',
444
520
  'separator',
445
521
  ],
446
522
  },
523
+ subscript: {
524
+ selectors: ['sub'],
525
+ },
526
+ superscript: {
527
+ selectors: ['sup'],
528
+ },
447
529
  switch: {
448
530
  nameFromContents: true,
449
531
  defaults: {
@@ -479,6 +561,14 @@ exports.roles = {
479
561
  ],
480
562
  childRoles: ['searchbox'],
481
563
  },
564
+ time: {
565
+ selectors: ['time'],
566
+ },
567
+ timer: {
568
+ defaults: {
569
+ 'live': 'off',
570
+ },
571
+ },
482
572
  toolbar: {
483
573
  defaults: {
484
574
  'orientation': 'horizontal',
@@ -502,8 +592,10 @@ exports.roles = {
502
592
  'composite',
503
593
  'gridcell',
504
594
  'input',
505
- 'range',
595
+ 'progressbar',
506
596
  'row',
597
+ 'scrollbar',
598
+ 'separator',
507
599
  'tab',
508
600
  ],
509
601
  },
package/lib/name.js CHANGED
@@ -111,6 +111,12 @@ var getName = function(el, recursive, visited, directReference) {
111
111
  }
112
112
  }
113
113
  }
114
+ if (!ret.trim() && el.matches('svg *')) {
115
+ var svgTitle = el.querySelector('title');
116
+ if (svgTitle && svgTitle.parentElement === el) {
117
+ ret = svgTitle.textContent;
118
+ }
119
+ }
114
120
 
115
121
  // E
116
122
  if (!ret.trim() && (recursive || isInLabelForOtherWidget(el) || query.matches(el, 'button'))) {
@@ -178,10 +184,15 @@ var getDescription = function(el) {
178
184
  return label ? getName(label, true) : '';
179
185
  });
180
186
  ret = strings.join(' ');
187
+ } else if (el.matches('[aria-description]')) {
188
+ ret = el.getAttribute('aria-description');
189
+ } else if (el.matches('svg *')) {
190
+ var svgDesc = el.querySelector('desc');
191
+ if (svgDesc && svgDesc.parentElement === el) {
192
+ ret = svgDesc.textContent;
193
+ }
181
194
  } else if (el.title) {
182
195
  ret = el.title;
183
- } else if (el.placeholder) {
184
- ret = el.placeholder;
185
196
  }
186
197
 
187
198
  ret = (ret || '').trim().replace(/\s+/g, ' ');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aria-api",
3
- "version": "0.4.7",
3
+ "version": "0.5.0",
4
4
  "description": "Access ARIA information from JavaScript",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -14,8 +14,8 @@
14
14
  "brfs": "^2.0.0",
15
15
  "browserify": "^17.0.0",
16
16
  "expect": "^1.20.2",
17
- "mocha": "^9.0.1",
18
- "mocha-headless-chrome": "^3.1.0"
17
+ "mocha": "^10.2.0",
18
+ "mocha-headless-chrome": "^4.0.0"
19
19
  },
20
20
  "files": [
21
21
  "index.js",