@hypothesi/tauri-mcp-server 0.7.0 → 0.8.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.
@@ -0,0 +1,1295 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.aria = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ // https://www.w3.org/TR/wai-aria/#state_prop_def
8
+ const attributes = {
9
+ 'activedescendant': 'id',
10
+ 'atomic': 'bool',
11
+ 'autocomplete': 'token',
12
+ 'braillelabel': 'string',
13
+ 'brailleroledescription': 'string',
14
+ 'busy': 'bool',
15
+ 'checked': 'tristate',
16
+ 'colcount': 'int',
17
+ 'colindex': 'int',
18
+ 'colindextext': 'string',
19
+ 'colspan': 'int',
20
+ 'controls': 'id-list',
21
+ 'current': 'token',
22
+ 'describedby': 'id-list',
23
+ 'description': 'string',
24
+ 'details': 'id',
25
+ 'disabled': 'bool',
26
+ 'dropeffect': 'token-list',
27
+ 'errormessage': 'id',
28
+ 'expanded': 'bool-undefined',
29
+ 'flowto': 'id-list',
30
+ 'grabbed': 'bool-undefined',
31
+ 'haspopup': 'token',
32
+ 'hidden': 'bool-undefined',
33
+ 'invalid': 'token',
34
+ 'keyshortcuts': 'string',
35
+ 'label': 'string',
36
+ 'labelledby': 'id-list',
37
+ 'level': 'int',
38
+ 'live': 'token',
39
+ 'modal': 'bool',
40
+ 'multiline': 'bool',
41
+ 'multiselectable': 'bool',
42
+ 'orientation': 'token',
43
+ 'owns': 'id-list',
44
+ 'placeholder': 'string',
45
+ 'posinset': 'int',
46
+ 'pressed': 'tristate',
47
+ 'readonly': 'bool',
48
+ 'relevant': 'token-list',
49
+ 'required': 'bool',
50
+ 'roledescription': 'string',
51
+ 'rowcount': 'int',
52
+ 'rowindex': 'int',
53
+ 'rowindextext': 'string',
54
+ 'rowspan': 'int',
55
+ 'selected': 'bool-undefined',
56
+ 'setsize': 'int',
57
+ 'sort': 'token',
58
+ 'valuemax': 'number',
59
+ 'valuemin': 'number',
60
+ 'valuenow': 'number',
61
+ 'valuetext': 'string',
62
+ };
63
+
64
+ const attributeStrongMapping = {
65
+ 'disabled': 'disabled',
66
+ 'placeholder': 'placeholder',
67
+ 'readonly': 'readOnly',
68
+ 'required': 'required',
69
+ };
70
+
71
+ const attributeWeakMapping = {
72
+ 'checked': 'checked',
73
+ 'colspan': 'colSpan',
74
+ 'expanded': 'open',
75
+ 'multiselectable': 'multiple',
76
+ 'rowspan': 'rowSpan',
77
+ 'selected': 'selected',
78
+ };
79
+
80
+ // https://www.w3.org/TR/html/dom.html#sectioning-content-2
81
+ const scoped = ['article *', 'aside *', 'nav *', 'section *'].join(',');
82
+
83
+ const svgSelectors = function(selector) {
84
+ return [
85
+ // `${selector}:has(> title:not(:empty))`,
86
+ // `${selector}:has(> desc:not(:empty))`,
87
+ `${selector}[aria-label]`,
88
+ `${selector}[aria-roledescription]`,
89
+ `${selector}[aria-labelledby]`,
90
+ `${selector}[aria-describedby]`,
91
+ `${selector}[tabindex]`,
92
+ `${selector}[role]`,
93
+ ];
94
+ };
95
+
96
+ // https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
97
+ // https://www.w3.org/TR/wai-aria/roles
98
+ const roles = {
99
+ alert: {
100
+ childRoles: ['alertdialog'],
101
+ defaults: {
102
+ 'live': 'assertive',
103
+ 'atomic': true,
104
+ },
105
+ },
106
+ alertdialog: {},
107
+ application: {},
108
+ article: {
109
+ selectors: ['article'],
110
+ childRoles: ['comment'],
111
+ },
112
+ banner: {
113
+ selectors: [`header:not(main *, ${scoped})`],
114
+ },
115
+ blockquote: {
116
+ selectors: ['blockquote'],
117
+ },
118
+ button: {
119
+ selectors: [
120
+ 'button',
121
+ 'input[type="button"]',
122
+ 'input[type="image"]',
123
+ 'input[type="reset"]',
124
+ 'input[type="submit"]',
125
+ 'summary',
126
+ ],
127
+ nameFromContents: true,
128
+ },
129
+ caption: {
130
+ selectors: ['caption', 'figcaption'],
131
+ },
132
+ cell: {
133
+ selectors: ['td', 'td ~ th:not([scope])'],
134
+ childRoles: ['columnheader', 'gridcell', 'rowheader'],
135
+ nameFromContents: true,
136
+ },
137
+ checkbox: {
138
+ selectors: ['input[type="checkbox"]'],
139
+ childRoles: ['switch'],
140
+ nameFromContents: true,
141
+ defaults: {
142
+ 'checked': 'false',
143
+ },
144
+ },
145
+ code: {
146
+ selectors: ['code'],
147
+ },
148
+ columnheader: {
149
+ selectors: ['th[scope="col"]'],
150
+ nameFromContents: true,
151
+ },
152
+ combobox: {
153
+ selectors: [
154
+ 'input:not([type])[list]',
155
+ 'input[type="email"][list]',
156
+ 'input[type="search"][list]',
157
+ 'input[type="tel"][list]',
158
+ 'input[type="text"][list]',
159
+ 'input[type="url"][list]',
160
+ 'select:not([size]):not([multiple])',
161
+ 'select[size="0"]:not([multiple])',
162
+ 'select[size="1"]:not([multiple])',
163
+ ],
164
+ defaults: {
165
+ 'expanded': false,
166
+ 'haspopup': 'listbox',
167
+ },
168
+ },
169
+ command: {
170
+ abstract: true,
171
+ childRoles: ['button', 'link', 'menuitem'],
172
+ },
173
+ comment: {
174
+ nameFromContents: true,
175
+ },
176
+ complementary: {
177
+ selectors: [
178
+ `aside:not(${scoped})`,
179
+ 'aside[aria-label]',
180
+ 'aside[aria-labelledby]',
181
+ 'aside[title]',
182
+ ],
183
+ },
184
+ composite: {
185
+ abstract: true,
186
+ childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
187
+ },
188
+ contentinfo: {
189
+ selectors: [`footer:not(main *, ${scoped})`],
190
+ },
191
+ definition: {
192
+ selectors: ['dd'],
193
+ },
194
+ deletion: {
195
+ selectors: ['del', 's'],
196
+ },
197
+ dialog: {
198
+ selectors: ['dialog'],
199
+ childRoles: ['alertdialog'],
200
+ },
201
+ 'doc-abstract': {},
202
+ 'doc-acknowledgments': {},
203
+ 'doc-afterword': {},
204
+ 'doc-appendix': {},
205
+ 'doc-backlink': {
206
+ nameFromContents: true,
207
+ },
208
+ 'doc-biblioentry': {},
209
+ 'doc-bibliography': {},
210
+ 'doc-biblioref': {
211
+ nameFromContents: true,
212
+ },
213
+ 'doc-chapter': {},
214
+ 'doc-colophon': {},
215
+ 'doc-conclusion': {},
216
+ 'doc-cover': {},
217
+ 'doc-credit': {},
218
+ 'doc-credits': {},
219
+ 'doc-dedication': {},
220
+ 'doc-endnote': {},
221
+ 'doc-endnotes': {},
222
+ 'doc-epilogue': {},
223
+ 'doc-epigraph': {},
224
+ 'doc-errata': {},
225
+ 'doc-example': {},
226
+ 'doc-footnote': {},
227
+ 'doc-foreword': {},
228
+ 'doc-glossary': {},
229
+ 'doc-glossref': {
230
+ nameFromContents: true,
231
+ },
232
+ 'doc-index': {},
233
+ 'doc-introduction': {},
234
+ 'doc-noteref': {
235
+ nameFromContents: true,
236
+ },
237
+ 'doc-notice': {},
238
+ 'doc-pagebreak': {
239
+ nameFromContents: true,
240
+ },
241
+ 'doc-pagefooter': {},
242
+ 'doc-pageheader': {},
243
+ 'doc-pagelist': {},
244
+ 'doc-part': {},
245
+ 'doc-preface': {},
246
+ 'doc-prologue': {},
247
+ 'doc-pullquote': {},
248
+ 'doc-qna': {},
249
+ 'doc-subtitle': {
250
+ nameFromContents: true,
251
+ },
252
+ 'doc-tip': {},
253
+ 'doc-toc': {},
254
+ document: {
255
+ selectors: ['html'],
256
+ childRoles: ['article', 'graphics-document'],
257
+ },
258
+ emphasis: {
259
+ selectors: ['em'],
260
+ },
261
+ feed: {},
262
+ figure: {
263
+ selectors: ['figure'],
264
+ childRoles: ['doc-example'],
265
+ },
266
+ form: {
267
+ selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
268
+ },
269
+ generic: {
270
+ selectors: [
271
+ 'a:not([*|href])',
272
+ 'area:not([*|href])',
273
+ `aside:not(${scoped}):not([aria-label]):not([aria-labelledby]):not([title])`,
274
+ 'b',
275
+ 'bdi',
276
+ 'bdo',
277
+ 'body',
278
+ 'data',
279
+ 'div',
280
+ // footer scoped
281
+ // header scoped
282
+ 'i',
283
+ 'li:not(ul > li):not(ol > li)',
284
+ 'pre',
285
+ 'q',
286
+ 'samp',
287
+ 'section:not([aria-label]):not([aria-labelledby]):not([title])',
288
+ 'small',
289
+ 'span',
290
+ 'u',
291
+ ],
292
+ },
293
+ 'graphics-document': {
294
+ selectors: ['svg'],
295
+ },
296
+ 'graphics-object': {
297
+ selectors: [
298
+ ...svgSelectors('symbol'),
299
+ ...svgSelectors('use'),
300
+ ],
301
+ },
302
+ 'graphics-symbol': {
303
+ selectors: [
304
+ ...svgSelectors('circle'),
305
+ ...svgSelectors('ellipse'),
306
+ ...svgSelectors('line'),
307
+ ...svgSelectors('path'),
308
+ ...svgSelectors('polygon'),
309
+ ...svgSelectors('polyline'),
310
+ ...svgSelectors('rect'),
311
+ ],
312
+ },
313
+ grid: {
314
+ childRoles: ['treegrid'],
315
+ },
316
+ gridcell: {
317
+ childRoles: ['columnheader', 'rowheader'],
318
+ nameFromContents: true,
319
+ },
320
+ group: {
321
+ selectors: [
322
+ 'address',
323
+ 'details',
324
+ 'fieldset',
325
+ 'hgroup',
326
+ 'optgroup',
327
+ ...svgSelectors('foreignObject'),
328
+ ...svgSelectors('g'),
329
+ 'text',
330
+ ...svgSelectors('textPath'),
331
+ ...svgSelectors('tspan'),
332
+ ],
333
+ childRoles: ['row', 'select', 'toolbar', 'graphics-object'],
334
+ },
335
+ heading: {
336
+ selectors: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
337
+ nameFromContents: true,
338
+ defaults: {
339
+ 'level': 2,
340
+ },
341
+ },
342
+ image: {
343
+ selectors: [
344
+ 'img:not([alt=""])',
345
+ 'graphics-symbol',
346
+ ...svgSelectors('image'),
347
+ ...svgSelectors('mesh'),
348
+ ],
349
+ childRoles: ['doc-cover'],
350
+ },
351
+ input: {
352
+ abstract: true,
353
+ childRoles: [
354
+ 'checkbox',
355
+ 'combobox',
356
+ 'option',
357
+ 'radio',
358
+ 'slider',
359
+ 'spinbutton',
360
+ 'textbox',
361
+ ],
362
+ },
363
+ insertion: {
364
+ selectors: ['ins'],
365
+ },
366
+ landmark: {
367
+ abstract: true,
368
+ childRoles: [
369
+ 'banner',
370
+ 'complementary',
371
+ 'contentinfo',
372
+ 'doc-acknowledgments',
373
+ 'doc-afterword',
374
+ 'doc-appendix',
375
+ 'doc-bibliography',
376
+ 'doc-chapter',
377
+ 'doc-conclusion',
378
+ 'doc-credits',
379
+ 'doc-endnotes',
380
+ 'doc-epilogue',
381
+ 'doc-errata',
382
+ 'doc-foreword',
383
+ 'doc-glossary',
384
+ 'doc-introduction',
385
+ 'doc-part',
386
+ 'doc-preface',
387
+ 'doc-prologue',
388
+ 'form',
389
+ 'main',
390
+ 'navigation',
391
+ 'region',
392
+ 'search',
393
+ ],
394
+ },
395
+ link: {
396
+ selectors: ['a[*|href]', 'area[*|href]'],
397
+ childRoles: ['doc-backlink', 'doc-biblioref', 'doc-glossref', 'doc-noteref'],
398
+ nameFromContents: true,
399
+ },
400
+ list: {
401
+ selectors: ['dl', 'ol', 'ul', 'menu'],
402
+ childRoles: ['feed'],
403
+ },
404
+ listbox: {
405
+ selectors: [
406
+ 'datalist',
407
+ 'select[multiple]',
408
+ 'select[size]:not([size="0"]):not([size="1"])',
409
+ ],
410
+ defaults: {
411
+ 'orientation': 'vertical',
412
+ },
413
+ },
414
+ listitem: {
415
+ selectors: ['ol > li', 'ul > li'],
416
+ childRoles: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
417
+ },
418
+ log: {
419
+ defaults: {
420
+ 'live': 'polite',
421
+ },
422
+ },
423
+ main: {
424
+ selectors: ['main'],
425
+ },
426
+ mark: {
427
+ selectors: ['mark'],
428
+ },
429
+ marquee: {},
430
+ math: {
431
+ selectors: ['math'],
432
+ },
433
+ meter: {
434
+ selectors: ['meter'],
435
+ defaults: {
436
+ 'valuemin': 0,
437
+ 'valuemax': 100,
438
+ },
439
+ },
440
+ menu: {
441
+ childRoles: ['menubar'],
442
+ defaults: {
443
+ 'orientation': 'vertical',
444
+ },
445
+ },
446
+ menubar: {
447
+ defaults: {
448
+ 'orientation': 'horizontal',
449
+ },
450
+ },
451
+ menuitem: {
452
+ childRoles: ['menuitemcheckbox', 'menuitemradio'],
453
+ nameFromContents: true,
454
+ },
455
+ menuitemcheckbox: {
456
+ nameFromContents: true,
457
+ defaults: {
458
+ 'checked': 'false',
459
+ },
460
+ },
461
+ menuitemradio: {
462
+ nameFromContents: true,
463
+ defaults: {
464
+ 'checked': 'false',
465
+ },
466
+ },
467
+ navigation: {
468
+ selectors: ['nav'],
469
+ childRoles: ['doc-index', 'doc-pagelist', 'doc-toc'],
470
+ },
471
+ none: {
472
+ selectors: ['img[alt=""]'],
473
+ },
474
+ note: {
475
+ childRoles: ['doc-notice', 'doc-tip'],
476
+ },
477
+ option: {
478
+ selectors: ['option'],
479
+ childRoles: ['treeitem'],
480
+ nameFromContents: true,
481
+ defaults: {
482
+ 'selected': 'false',
483
+ },
484
+ },
485
+ paragraph: {
486
+ selectors: ['p'],
487
+ },
488
+ progressbar: {
489
+ selectors: ['progress'],
490
+ defaults: {
491
+ 'valuemin': 0,
492
+ 'valuemax': 100,
493
+ },
494
+ },
495
+ radio: {
496
+ selectors: ['input[type="radio"]'],
497
+ childRoles: ['menuitemradio'],
498
+ nameFromContents: true,
499
+ defaults: {
500
+ 'checked': 'false',
501
+ },
502
+ },
503
+ radiogroup: {},
504
+ range: {
505
+ abstract: true,
506
+ childRoles: ['meter', 'progressbar', 'scrollbar', 'slider', 'spinbutton'],
507
+ },
508
+ region: {
509
+ selectors: ['section[aria-label]', 'section[aria-labelledby]', 'section[title]'],
510
+ },
511
+ roletype: {
512
+ abstract: true,
513
+ childRoles: ['structure', 'widget', 'window'],
514
+ },
515
+ row: {
516
+ selectors: ['tr'],
517
+ nameFromContents: true,
518
+ },
519
+ rowgroup: {
520
+ selectors: ['tbody', 'thead', 'tfoot'],
521
+ },
522
+ rowheader: {
523
+ selectors: ['th[scope="row"]', 'th:not([scope]):not(td ~ th)'],
524
+ nameFromContents: true,
525
+ },
526
+ scrollbar: {
527
+ defaults: {
528
+ 'orientation': 'vertical',
529
+ 'valuemin': 0,
530
+ 'valuemax': 100,
531
+ },
532
+ },
533
+ search: {
534
+ selectors: ['search'],
535
+ },
536
+ searchbox: {
537
+ selectors: ['input[type="search"]:not([list])'],
538
+ },
539
+ section: {
540
+ abstract: true,
541
+ childRoles: [
542
+ 'alert',
543
+ 'blockquote',
544
+ 'caption',
545
+ 'cell',
546
+ 'code',
547
+ 'definition',
548
+ 'deletion',
549
+ 'doc-abstract',
550
+ 'doc-colophon',
551
+ 'doc-credit',
552
+ 'doc-dedication',
553
+ 'doc-epigraph',
554
+ 'doc-footnote',
555
+ 'doc-pagefooter',
556
+ 'doc-pageheader',
557
+ 'doc-pullquote',
558
+ 'doc-qna',
559
+ 'emphasis',
560
+ 'figure',
561
+ 'group',
562
+ 'image',
563
+ 'insertion',
564
+ 'landmark',
565
+ 'list',
566
+ 'listitem',
567
+ 'log',
568
+ 'mark',
569
+ 'marquee',
570
+ 'math',
571
+ 'note',
572
+ 'paragraph',
573
+ 'status',
574
+ 'strong',
575
+ 'subscript',
576
+ 'suggestion',
577
+ 'superscript',
578
+ 'table',
579
+ 'tabpanel',
580
+ 'term',
581
+ 'time',
582
+ 'tooltip',
583
+ ],
584
+ },
585
+ sectionhead: {
586
+ abstract: true,
587
+ childRoles: [
588
+ 'columnheader',
589
+ 'doc-subtitle',
590
+ 'heading',
591
+ 'rowheader',
592
+ 'tab',
593
+ ],
594
+ nameFromContents: true,
595
+ },
596
+ select: {
597
+ abstract: true,
598
+ childRoles: ['listbox', 'menu', 'radiogroup', 'tree'],
599
+ },
600
+ separator: {
601
+ // assume not focussable because <hr> is not
602
+ selectors: ['hr'],
603
+ childRoles: ['doc-pagebreak'],
604
+ defaults: {
605
+ 'orientation': 'horizontal',
606
+ 'valuemin': 0,
607
+ 'valuemax': 100,
608
+ },
609
+ },
610
+ slider: {
611
+ selectors: ['input[type="range"]'],
612
+ defaults: {
613
+ 'orientation': 'horizontal',
614
+ 'valuemin': 0,
615
+ 'valuemax': 100,
616
+ // FIXME: halfway between actual valuemin and valuemax
617
+ 'valuenow': 50,
618
+ },
619
+ },
620
+ spinbutton: {
621
+ selectors: ['input[type="number"]'],
622
+ defaults: {
623
+ // FIXME: no valuemin/valuemax/valuenow
624
+ },
625
+ },
626
+ status: {
627
+ selectors: ['output'],
628
+ childRoles: ['timer'],
629
+ defaults: {
630
+ 'live': 'polite',
631
+ 'atomic': true,
632
+ },
633
+ },
634
+ strong: {
635
+ selectors: ['strong'],
636
+ },
637
+ structure: {
638
+ abstract: true,
639
+ childRoles: [
640
+ 'application',
641
+ 'document',
642
+ 'none',
643
+ 'generic',
644
+ 'range',
645
+ 'rowgroup',
646
+ 'section',
647
+ 'sectionhead',
648
+ 'separator',
649
+ ],
650
+ },
651
+ suggestion: {},
652
+ subscript: {
653
+ selectors: ['sub'],
654
+ },
655
+ superscript: {
656
+ selectors: ['sup'],
657
+ },
658
+ switch: {
659
+ nameFromContents: true,
660
+ defaults: {
661
+ 'checked': false,
662
+ },
663
+ },
664
+ tab: {
665
+ nameFromContents: true,
666
+ defaults: {
667
+ 'selected': false,
668
+ },
669
+ },
670
+ table: {
671
+ selectors: ['table'],
672
+ childRoles: ['grid'],
673
+ },
674
+ tablist: {
675
+ defaults: {
676
+ 'orientation': 'horizontal',
677
+ },
678
+ },
679
+ tabpanel: {},
680
+ term: {
681
+ selectors: ['dfn', 'dt'],
682
+ },
683
+ textbox: {
684
+ selectors: [
685
+ 'input:not([type]):not([list])',
686
+ 'input[type="email"]:not([list])',
687
+ 'input[type="tel"]:not([list])',
688
+ 'input[type="text"]:not([list])',
689
+ 'input[type="url"]:not([list])',
690
+ 'textarea',
691
+ ],
692
+ childRoles: ['searchbox'],
693
+ },
694
+ time: {
695
+ selectors: ['time'],
696
+ },
697
+ timer: {
698
+ defaults: {
699
+ 'live': 'off',
700
+ },
701
+ },
702
+ toolbar: {
703
+ defaults: {
704
+ 'orientation': 'horizontal',
705
+ },
706
+ },
707
+ tooltip: {
708
+ nameFromContents: true,
709
+ },
710
+ tree: {
711
+ childRoles: ['treegrid'],
712
+ defaults: {
713
+ 'orientation': 'vertical',
714
+ },
715
+ },
716
+ treegrid: {},
717
+ treeitem: {
718
+ nameFromContents: true,
719
+ },
720
+ widget: {
721
+ abstract: true,
722
+ childRoles: [
723
+ 'command',
724
+ 'composite',
725
+ 'gridcell',
726
+ 'input',
727
+ 'progressbar',
728
+ 'row',
729
+ 'scrollbar',
730
+ 'separator',
731
+ 'tab',
732
+ ],
733
+ },
734
+ window: {
735
+ abstract: true,
736
+ childRoles: ['dialog'],
737
+ },
738
+ };
739
+
740
+ const getSubRoles = function(role) {
741
+ const children = (roles[role]).childRoles || [];
742
+ const descendents = children.map(getSubRoles);
743
+
744
+ const result = [role];
745
+
746
+ descendents.forEach(list => {
747
+ list.forEach(r => {
748
+ if (!result.includes(r)) {
749
+ result.push(r);
750
+ }
751
+ });
752
+ });
753
+
754
+ return result;
755
+ };
756
+
757
+ const attrsWithDefaults = [];
758
+
759
+ for (const role in roles) {
760
+ roles[role].subRoles = getSubRoles(role);
761
+ for (const key in roles[role].defaults) {
762
+ if (!attrsWithDefaults.includes(key)) {
763
+ attrsWithDefaults.push(key);
764
+ }
765
+ }
766
+ }
767
+
768
+ const aliases = {
769
+ 'presentation': 'none',
770
+ 'directory': 'list',
771
+ 'img': 'image',
772
+ };
773
+
774
+ const nameFromDescendant = {
775
+ 'figure': 'figcaption',
776
+ 'table': 'caption',
777
+ 'fieldset': 'legend',
778
+ };
779
+
780
+ const nameDefaults = {
781
+ 'input[type="submit"]': 'Submit',
782
+ 'input[type="reset"]': 'Reset',
783
+ 'summary': 'Details',
784
+ };
785
+
786
+ var unique = function(arr) {
787
+ return arr.filter((a, i) => arr.indexOf(a) === i);
788
+ };
789
+
790
+ var flatten = function(arr) {
791
+ return [].concat.apply([], arr);
792
+ };
793
+
794
+ var normalizeRoles = function(roles$1, includeAbstract) {
795
+ return unique(roles$1
796
+ .map(r => aliases[r] || r)
797
+ .filter(r => roles[r])
798
+ .filter(r => includeAbstract || !roles[r].abstract)
799
+ );
800
+ };
801
+
802
+ // candidates can be passed for performance optimization
803
+ const getRoleRaw = function(el, candidates) {
804
+ // TODO: filter out any invalid roles (e.g. name or context required)
805
+ const roles$1 = normalizeRoles(
806
+ (el.getAttribute('role') || '').toLowerCase().split(/\s+/)
807
+ );
808
+
809
+ if (roles$1.length > 1 && candidates) {
810
+ return [roles$1, candidates];
811
+ } else if (roles$1.length) {
812
+ for (const role of roles$1) {
813
+ if (!candidates || candidates.includes(role)) {
814
+ return role;
815
+ }
816
+ }
817
+ } else {
818
+ for (const role of (candidates || Object.keys(roles))) {
819
+ const r = roles[role];
820
+ if (!r.abstract && r.selectors && el.matches(r.selectors.join(','))) {
821
+ return role;
822
+ }
823
+ }
824
+ }
825
+ };
826
+
827
+ const getRole = function(el) {
828
+ return getRoleRaw(el);
829
+ };
830
+
831
+ const hasRole = function(el, roles$1) {
832
+ const subRoles = normalizeRoles(roles$1, true).map(role => {
833
+ return roles[role].subRoles || [role];
834
+ });
835
+ return !!getRoleRaw(el, unique(flatten(subRoles)));
836
+ };
837
+
838
+ const getAttribute = function(el, key) {
839
+ if (attributeStrongMapping.hasOwnProperty(key)) {
840
+ const value = el[attributeStrongMapping[key]];
841
+ if (value) {
842
+ return value;
843
+ }
844
+ }
845
+ if (key === 'readonly' && el.contentEditable) {
846
+ return false;
847
+ } else if (key === 'invalid' && el.checkValidity) {
848
+ return !el.checkValidity();
849
+ } else if (key === 'hidden') {
850
+ // workaround for chromium
851
+ if (el.matches('noscript')) {
852
+ return true;
853
+ }
854
+ if (el.matches('details:not([open]) > :not(summary)')) {
855
+ return true;
856
+ }
857
+ const style = window.getComputedStyle(el);
858
+ if (style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse') {
859
+ return true;
860
+ }
861
+ }
862
+
863
+ const type = attributes[key];
864
+ const raw = el.getAttribute('aria-' + key);
865
+
866
+ if (raw) {
867
+ if (type === 'bool') {
868
+ return raw === 'true';
869
+ } else if (type === 'tristate') {
870
+ return raw === 'true' ? true : raw === 'false' ? false : 'mixed';
871
+ } else if (type === 'bool-undefined') {
872
+ return raw === 'true' ? true : raw === 'false' ? false : undefined;
873
+ } else if (type === 'id-list') {
874
+ return raw.split(/\s+/);
875
+ } else if (type === 'integer') {
876
+ return parseInt(raw, 10);
877
+ } else if (type === 'number') {
878
+ return parseFloat(raw);
879
+ } else if (type === 'token-list') {
880
+ return raw.split(/\s+/);
881
+ } else {
882
+ return raw;
883
+ }
884
+ }
885
+
886
+ // TODO
887
+ // autocomplete
888
+ // contextmenu -> aria-haspopup
889
+ // indeterminate -> aria-checked="mixed"
890
+ // list -> aria-controls
891
+
892
+ if (key === 'level') {
893
+ for (let i = 1; i <= 6; i++) {
894
+ if (el.tagName.toLowerCase() === 'h' + i) {
895
+ return i;
896
+ }
897
+ }
898
+ } else if (attributeWeakMapping.hasOwnProperty(key)) {
899
+ return el[attributeWeakMapping[key]];
900
+ }
901
+
902
+ if (key in attrsWithDefaults) {
903
+ const role = getRole(el);
904
+ const defaults = roles[role].defaults;
905
+ if (defaults && defaults.hasOwnProperty(key)) {
906
+ return defaults[key];
907
+ }
908
+ }
909
+
910
+ if (type === 'bool' || type === 'tristate') {
911
+ return false;
912
+ }
913
+ };
914
+
915
+ const _getOwner = function(node, owners) {
916
+ if (node.nodeType === node.ELEMENT_NODE && node.id) {
917
+ const selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';
918
+ if (owners) {
919
+ for (const owner of owners) {
920
+ if (owner.matches(selector)) {
921
+ return owner;
922
+ }
923
+ }
924
+ } else {
925
+ return document.querySelector(selector);
926
+ }
927
+ }
928
+ };
929
+
930
+ const _getParentNode = function(node, owners) {
931
+ return _getOwner(node, owners) || node.parentNode;
932
+ };
933
+
934
+ const detectLoop = function(node, owners) {
935
+ const seen = [node];
936
+ while ((node = _getParentNode(node, owners))) {
937
+ if (seen.includes(node)) {
938
+ return true;
939
+ }
940
+ seen.push(node);
941
+ }
942
+ };
943
+
944
+ const getOwner = function(node, owners) {
945
+ const owner = _getOwner(node, owners);
946
+ if (owner && !detectLoop(node, owners)) {
947
+ return owner;
948
+ }
949
+ };
950
+
951
+ const getParentNode = function(node, owners) {
952
+ return getOwner(node, owners) || node.parentNode;
953
+ };
954
+
955
+ const isHidden = function(node) {
956
+ return node.nodeType === node.ELEMENT_NODE && getAttribute(node, 'hidden');
957
+ };
958
+
959
+ const getChildNodes = function(node, owners) {
960
+ const childNodes = [];
961
+
962
+ for (let i = 0; i < node.childNodes.length; i++) {
963
+ const child = node.childNodes[i];
964
+ if (!getOwner(child, owners) && !isHidden(child)) {
965
+ childNodes.push(child);
966
+ }
967
+ }
968
+
969
+ if (node.nodeType === node.ELEMENT_NODE) {
970
+ const owns = getAttribute(node, 'owns') || [];
971
+ for (let i = 0; i < owns.length; i++) {
972
+ const child = document.getElementById(owns[i]);
973
+ // double check with getOwner for consistency
974
+ if (child && getOwner(child, owners) === node && !isHidden(child)) {
975
+ childNodes.push(child);
976
+ }
977
+ }
978
+ }
979
+
980
+ return childNodes;
981
+ };
982
+
983
+ const walk = function(root, fn) {
984
+ const owners = document.querySelectorAll('[aria-owns]');
985
+ let queue = [root];
986
+ while (queue.length) {
987
+ const item = queue.shift();
988
+ fn(item);
989
+ queue = getChildNodes(item, owners).concat(queue);
990
+ }
991
+ };
992
+
993
+ const searchUp = function(node, test) {
994
+ const candidate = getParentNode(node);
995
+ if (candidate) {
996
+ if (test(candidate)) {
997
+ return candidate;
998
+ } else {
999
+ return searchUp(candidate, test);
1000
+ }
1001
+ }
1002
+ };
1003
+
1004
+ const matches = function(el, selector) {
1005
+ if (selector.substr(0, 1) === ':') {
1006
+ const attr = selector.substr(1);
1007
+ return getAttribute(el, attr);
1008
+ } else if (selector.substr(0, 1) === '[') {
1009
+ const match = /\[([a-z]+)="(.*)"\]/.exec(selector);
1010
+ const actual = getAttribute(el, match[1]);
1011
+ const rawValue = match[2];
1012
+ return actual.toString() === rawValue;
1013
+ } else {
1014
+ return hasRole(el, selector.split(','));
1015
+ }
1016
+ };
1017
+
1018
+ const _querySelector = function(all) {
1019
+ return function(root, selector) {
1020
+ const results = [];
1021
+ try {
1022
+ walk(root, node => {
1023
+ if (node.nodeType === node.ELEMENT_NODE) {
1024
+ // FIXME: skip hidden elements
1025
+ if (matches(node, selector)) {
1026
+ results.push(node);
1027
+ if (!all) {
1028
+ throw 'StopIteration';
1029
+ }
1030
+ }
1031
+ }
1032
+ });
1033
+ } catch (e) {
1034
+ if (e !== 'StopIteration') {
1035
+ throw e;
1036
+ }
1037
+ }
1038
+ return all ? results : results[0];
1039
+ };
1040
+ };
1041
+
1042
+ const closest = function(el, selector) {
1043
+ return searchUp(el, candidate => {
1044
+ if (candidate.nodeType === candidate.ELEMENT_NODE) {
1045
+ return matches(candidate, selector);
1046
+ }
1047
+ });
1048
+ };
1049
+
1050
+ const querySelector = _querySelector();
1051
+ const querySelectorAll = _querySelector(true);
1052
+
1053
+ const addSpaces = function(text, el, pseudoSelector) {
1054
+ // https://github.com/w3c/accname/issues/3
1055
+ const styles = window.getComputedStyle(el, pseudoSelector);
1056
+ const inline = styles.display === 'inline';
1057
+ return inline ? text : ` ${text} `;
1058
+ };
1059
+
1060
+ const getPseudoContent = function(el, pseudoSelector) {
1061
+ const styles = window.getComputedStyle(el, pseudoSelector);
1062
+ let tail = styles.getPropertyValue('content').trim();
1063
+ let ret = [];
1064
+
1065
+ let match;
1066
+ while (tail.length) {
1067
+ if ((match = tail.match(/^"([^"]*)"/))) {
1068
+ ret.push(match[1]);
1069
+ } else if ((match = tail.match(/^([a-z-]+)\(([^)]*)\)/))) {
1070
+ if (match[1] === 'attr') {
1071
+ ret.push(el.getAttribute(match[2]) || '');
1072
+ }
1073
+ } else if ((match = tail.match(/^([a-z-]+)/))) {
1074
+ if (match[1] === 'open-quote' || match[1] === 'close-quote') {
1075
+ ret.push('"');
1076
+ }
1077
+ } else if ((match = tail.match(/^\//))) {
1078
+ ret = [];
1079
+ } else {
1080
+ // invalid content, ignore
1081
+ return '';
1082
+ }
1083
+ tail = tail.slice(match[0].length).trim();
1084
+ }
1085
+
1086
+ return addSpaces(ret.join(''), el, pseudoSelector);
1087
+ };
1088
+
1089
+ const getContent = function(root, ongoingLabelledBy, visited) {
1090
+ const children = getChildNodes(root);
1091
+
1092
+ let ret = '';
1093
+ for (let i = 0; i < children.length; i++) {
1094
+ const node = children[i];
1095
+ if (node.nodeType === node.TEXT_NODE) {
1096
+ const styles = window.getComputedStyle(node.parentElement);
1097
+ if (styles.textTransform === 'uppercase') {
1098
+ ret += node.textContent.toUpperCase();
1099
+ } else if (styles.textTransform === 'lowercase') {
1100
+ ret += node.textContent.toLowerCase();
1101
+ } else if (styles.textTransform === 'capitalize') {
1102
+ ret += node.textContent.replace(/\b\w/g, c => c.toUpperCase());
1103
+ } else {
1104
+ ret += node.textContent;
1105
+ }
1106
+ } else if (node.nodeType === node.ELEMENT_NODE) {
1107
+ if (node.tagName.toLowerCase() === 'br') {
1108
+ ret += '\n';
1109
+ } else {
1110
+ ret += getNameRaw(node, true, ongoingLabelledBy, visited);
1111
+ }
1112
+ }
1113
+ }
1114
+
1115
+ return ret;
1116
+ };
1117
+
1118
+ const allowNameFromContent = function(el) {
1119
+ const role = getRole(el);
1120
+ if (role) {
1121
+ return roles[role].nameFromContents;
1122
+ }
1123
+ };
1124
+
1125
+ const getNameRaw = function(el, recursive, ongoingLabelledBy, visited, directReference) {
1126
+ let ret = '';
1127
+
1128
+ visited = visited || [];
1129
+ if (visited.includes(el)) {
1130
+ if (!directReference) {
1131
+ return '';
1132
+ }
1133
+ } else {
1134
+ visited.push(el);
1135
+ }
1136
+
1137
+ // A
1138
+ // handled in atree
1139
+
1140
+ // B
1141
+ if (!ongoingLabelledBy && el.matches('[aria-labelledby]')) {
1142
+ const ids = el.getAttribute('aria-labelledby').split(/\s+/);
1143
+ const strings = ids.map(id => {
1144
+ const label = document.getElementById(id);
1145
+ return label ? getNameRaw(label, true, true, visited, true) : '';
1146
+ });
1147
+ ret = strings.join(' ');
1148
+ }
1149
+
1150
+ // E (the current draft has this at this high priority)
1151
+ if (!ret.trim() && recursive) {
1152
+ if (matches(el, 'textbox')) {
1153
+ ret = el.value || el.textContent;
1154
+ } else if (matches(el, 'combobox,listbox')) {
1155
+ const selected = querySelector(el, ':selected') || querySelector(el, 'option');
1156
+ if (selected) {
1157
+ ret = getNameRaw(selected, recursive, ongoingLabelledBy, visited);
1158
+ } else {
1159
+ ret = el.value || '';
1160
+ }
1161
+ } else if (matches(el, 'range')) {
1162
+ ret = '' + (getAttribute(el, 'valuetext') || getAttribute(el, 'valuenow') || el.value);
1163
+ }
1164
+ }
1165
+
1166
+ // C
1167
+ if (!ret.trim() && el.matches('[aria-label]')) {
1168
+ // FIXME: may skip to 2E
1169
+ ret = el.getAttribute('aria-label');
1170
+ }
1171
+
1172
+ // D
1173
+ if (!ret.trim() && !recursive && el.labels) {
1174
+ const strings = Array.prototype.map.call(el.labels, label => {
1175
+ return getNameRaw(label, true, ongoingLabelledBy, visited);
1176
+ });
1177
+ ret = strings.join(' ');
1178
+ }
1179
+ if (!ret.trim()) {
1180
+ ret = el.alt || '';
1181
+ }
1182
+ if (!ret.trim() && el.matches('abbr,acronym') && el.title) {
1183
+ ret = el.title;
1184
+ }
1185
+ if (!ret.trim()) {
1186
+ for (const selector in nameFromDescendant) {
1187
+ if (el.matches(selector)) {
1188
+ const descendant = el.querySelector(nameFromDescendant[selector]);
1189
+ if (descendant) {
1190
+ ret = getNameRaw(descendant, true, ongoingLabelledBy, visited);
1191
+ }
1192
+ }
1193
+ }
1194
+ }
1195
+ if (!ret.trim() && el.matches('svg *')) {
1196
+ const svgTitle = el.querySelector('title');
1197
+ if (svgTitle && svgTitle.parentElement === el) {
1198
+ ret = svgTitle.textContent;
1199
+ }
1200
+ }
1201
+ if (!ret.trim() && el.matches('a')) {
1202
+ ret = el.getAttribute('xlink:title') || '';
1203
+ }
1204
+
1205
+ // F
1206
+ // FIXME: menu is not mentioned in the spec
1207
+ if (!ret.trim() && (recursive || allowNameFromContent(el) || el.closest('label')) && !matches(el, 'menu')) {
1208
+ ret = getContent(el, ongoingLabelledBy, visited);
1209
+ }
1210
+
1211
+ if (!ret.trim() && matches(el, 'button')) {
1212
+ ret = el.value || '';
1213
+ }
1214
+
1215
+ if (!ret.trim()) {
1216
+ for (const selector in nameDefaults) {
1217
+ if (el.matches(selector)) {
1218
+ ret = nameDefaults[selector];
1219
+ }
1220
+ }
1221
+ }
1222
+
1223
+ // G/H
1224
+ // handled in getContent
1225
+
1226
+ // I
1227
+ if (!ret.trim()) {
1228
+ ret = el.title || el.placeholder || '';
1229
+ }
1230
+
1231
+ // FIXME: not exactly sure about this, but it reduces the number of failing
1232
+ // WPT tests. Whitespace is hard.
1233
+ if (!ret.trim()) {
1234
+ ret = ' ';
1235
+ }
1236
+
1237
+ const before = getPseudoContent(el, ':before');
1238
+ const after = getPseudoContent(el, ':after');
1239
+ return addSpaces(before + ret + after, el);
1240
+ };
1241
+
1242
+ const getName = function(el) {
1243
+ return getNameRaw(el)
1244
+ .replace(/[ \n\r\t\f]+/g, ' ')
1245
+ .replace(/^ /, '')
1246
+ .replace(/ $/, '');
1247
+ };
1248
+
1249
+ const getDescription = function(el) {
1250
+ let ret = '';
1251
+
1252
+ if (el.matches('[aria-describedby]')) {
1253
+ const ids = el.getAttribute('aria-describedby').split(/\s+/);
1254
+ const strings = ids.map(id => {
1255
+ const label = document.getElementById(id);
1256
+ return label ? getNameRaw(label, true, true) : '';
1257
+ });
1258
+ ret = strings.join(' ');
1259
+ } else if (el.matches('[aria-description]')) {
1260
+ ret = el.getAttribute('aria-description');
1261
+ } else if (el.matches('svg *')) {
1262
+ const svgDesc = el.querySelector('desc');
1263
+ if (svgDesc && svgDesc.parentElement === el) {
1264
+ ret = svgDesc.textContent;
1265
+ }
1266
+ } else if (el.title) {
1267
+ ret = el.title;
1268
+ }
1269
+ if (!ret.trim() && el.matches('a')) {
1270
+ ret = el.getAttribute('xlink:title') || '';
1271
+ }
1272
+
1273
+ ret = (ret || '').trim().replace(/\s+/g, ' ');
1274
+
1275
+ if (ret === getName(el)) {
1276
+ ret = '';
1277
+ }
1278
+
1279
+ return ret;
1280
+ };
1281
+
1282
+ exports.closest = closest;
1283
+ exports.getAttribute = getAttribute;
1284
+ exports.getChildNodes = getChildNodes;
1285
+ exports.getDescription = getDescription;
1286
+ exports.getName = getName;
1287
+ exports.getParentNode = getParentNode;
1288
+ exports.getRole = getRole;
1289
+ exports.matches = matches;
1290
+ exports.querySelector = querySelector;
1291
+ exports.querySelectorAll = querySelectorAll;
1292
+
1293
+ }));
1294
+
1295
+ window.ariaApi = window.aria;