aria-api

access ARIA information from JavaScript
git clone https://git.ce9e.org/aria-api.git

commit
82413ff1410bdd9a0feda13d7a9325a544f25dc5
parent
523ef9886f37ad70581454e5447e7e5b6281fa68
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-06-07 14:07
bump version to 0.5.0

Diffstat

M CHANGES.md 12 ++++++++++++
M dist/aria.js 201 ++++++++++++++++++++++++++++++++++++++++++++++---------------
M package.json 2 +-

3 files changed, 167 insertions, 48 deletions


diff --git a/CHANGES.md b/CHANGES.md

@@ -1,3 +1,15 @@
   -1     1 0.5.0 (2023-06-07)
   -1     2 ------------------
   -1     3 
   -1     4 -	add support for WAI-ARIA 1.2
   -1     5 -	add support for Digital Publishing WAI-ARIA Module 1.1
   -1     6 -	add support for `aria-description`
   -1     7 -	add incomplete support for SVG Accessibility API Mappings
   -1     8 -	update HTML Accessibility API Mappings to the latest working draft
   -1     9 -	fix parsing of the `role` attribute is it contains more than one entry
   -1    10 -	do not consider `placeholder` for description
   -1    11 
   -1    12 
    1    13 0.4.7 (2023-01-12)
    2    14 ------------------
    3    15 

diff --git a/dist/aria.js b/dist/aria.js

@@ -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    -1 		var role = el.getAttribute('role');
  127    -1 		if (!candidates || candidates.includes(role)) {
  128    -1 			return role;
  129    -1 		} else {
  130    -1 			return;
   -1   126 		var roles = el.getAttribute('role').toLowerCase().split(/\s+/);
   -1   127 		if (roles.length > 1 && candidates) {
   -1   128 			return [roles, candidates];
  131   129 		}
  132    -1 	}
  133    -1 	var roles = candidates ? candidates : Object.keys(constants.roles);
  134    -1 	for (var role of roles) {
  135    -1 		var r = constants.roles[role];
  136    -1 		if (r) {
  137    -1 			var selector = (r.selectors || []).join(',');
  138    -1 			if (selector && el.matches(selector)) {
   -1   130 		for (var role of roles) {
   -1   131 			if (!candidates || candidates.includes(role)) {
  139   132 				return role;
  140   133 			}
  141   134 		}
   -1   135 	} else {
   -1   136 		var roles = candidates ? candidates : Object.keys(constants.roles);
   -1   137 		for (var role of roles) {
   -1   138 			var r = constants.roles[role];
   -1   139 			if (r) {
   -1   140 				var selector = (r.selectors || []).join(',');
   -1   141 				if (selector && el.matches(selector)) {
   -1   142 					return role;
   -1   143 				}
   -1   144 			}
   -1   145 		}
  142   146 	}
  143   147 };
  144   148 
@@ -301,13 +305,8 @@ exports.attributeWeakMapping = {
  301   305 	'selected': 'selected',
  302   306 };
  303   307 
  304    -1 var scoped = [
  305    -1 	'main *',
  306    -1 	// https://www.w3.org/TR/html/dom.html#sectioning-content-2
  307    -1 	'article *', 'aside *', 'nav *', 'section *',
  308    -1 	// https://www.w3.org/TR/html/sections.html#sectioning-roots
  309    -1 	'blockquote *', 'details *', 'dialog *', 'fieldset *', 'figure *', 'td *',
  310    -1 ].join(',');
   -1   308 // https://www.w3.org/TR/html/dom.html#sectioning-content-2
   -1   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    -1 		selectors: ['header:not(' + scoped + ')'],
   -1   325 		selectors: [`header:not(main *, ${scoped})`],
   -1   326 	},
   -1   327 	blockquote: {
   -1   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 	},
   -1   341 	caption: {
   -1   342 		selectors: ['caption', 'figcaption'],
   -1   343 	},
  339   344 	cell: {
  340    -1 		selectors: ['td'],
  341    -1 		childRoles: ['gridcell', 'rowheader'],
   -1   345 		selectors: ['td', 'th:not([scope])'],
   -1   346 		childRoles: ['columnheader', 'gridcell', 'rowheader'],
  342   347 		nameFromContents: true,
  343   348 	},
  344   349 	checkbox: {
  345   350 		selectors: ['input[type="checkbox"]'],
  346    -1 		childRoles: ['menuitemcheckbox', 'switch'],
   -1   351 		childRoles: ['switch'],
  347   352 		nameFromContents: true,
  348   353 		defaults: {
  349   354 			'checked': 'false',
  350   355 		},
  351   356 	},
   -1   357 	code: {
   -1   358 		selectors: ['code'],
   -1   359 	},
  352   360 	columnheader: {
  353   361 		selectors: ['th[scope="col"]'],
  354   362 		nameFromContents: true,
  355   363 	},
  356   364 	combobox: {
  357   365 		selectors: [
  358    -1 		'input:not([type])[list]',
   -1   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    -1 		selectors: ['aside'],
   -1   385 		selectors: [
   -1   386 			`aside:not(${scoped})`,
   -1   387 			'aside[aria-label]',
   -1   388 			'aside[aria-labelledby]',
   -1   389 			'aside[title]',
   -1   390 		],
  378   391 	},
  379   392 	composite: {
  380   393 		childRoles: ['grid', 'select', 'spinbutton', 'tablist'],
  381   394 	},
  382   395 	contentinfo: {
  383    -1 		selectors: ['footer:not(' + scoped + ')'],
   -1   396 		selectors: [`footer:not(main *, ${scoped})`],
  384   397 	},
  385   398 	definition: {
  386   399 		selectors: ['dd'],
  387   400 	},
   -1   401 	deletion: {
   -1   402 		selectors: ['del', 's'],
   -1   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 	},
   -1   420 	'doc-pagebreak': {
   -1   421 		nameFromContents: true,
   -1   422 	},
   -1   423 	'doc-subtitle': {
   -1   424 		nameFromContents: true,
   -1   425 	},
  404   426 	document: {
  405    -1 		selectors: ['body'],
   -1   427 		selectors: ['html'],
  406   428 		childRoles: ['article', 'graphics-document'],
  407   429 	},
   -1   430 	emphasis: {
   -1   431 		selectors: ['em'],
   -1   432 	},
  408   433 	figure: {
  409   434 		selectors: ['figure'],
   -1   435 		childRoles: ['doc-example'],
  410   436 	},
  411   437 	form: {
  412   438 		selectors: ['form[aria-label]', 'form[aria-labelledby]', 'form[title]'],
  413   439 	},
   -1   440 	generic: {
   -1   441 		// too many selectors to list
   -1   442 	},
   -1   443 	'graphics-document': {
   -1   444 		selectors: ['svg'],
   -1   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    -1 		selectors: ['details', 'optgroup'],
   -1   454 		selectors: [
   -1   455 			'address',
   -1   456 			'details',
   -1   457 			'fieldset',
   -1   458 			'hgroup',
   -1   459 			'optgroup',
   -1   460 			'text',
   -1   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    -1 		childRoles: ['checkbox', 'option', 'radio', 'slider', 'spinbutton', 'textbox'],
   -1   476 		childRoles: [
   -1   477 			'checkbox',
   -1   478 			'combobox',
   -1   479 			'option',
   -1   480 			'radio',
   -1   481 			'slider',
   -1   482 			'spinbutton',
   -1   483 			'textbox',
   -1   484 		],
   -1   485 	},
   -1   486 	insertion: {
   -1   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    -1 		selectors: ['a[href]', 'area[href]', 'link[href]'],
   -1   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    -1 		selectors: ['dl', 'ol', 'ul'],
   -1   523 		selectors: ['dl', 'ol', 'ul', 'menu'],
  474   524 		childRoles: ['directory', 'feed'],
  475   525 	},
  476   526 	listbox: {
  477   527 		selectors: [
   -1   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    -1 		selectors: ['dt', 'ul > li', 'ol > li'],
   -1   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 	},
   -1   551 	meter: {
   -1   552 		selectors: ['meter'],
   -1   553 		defaults: {
   -1   554 			'valuemin': 0,
   -1   555 			'valuemax': 100,
   -1   556 		},
   -1   557 	},
  500   558 	menu: {
  501    -1 		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    -1 		selectors: ['menuitem[type="command"]'],
  514   570 		childRoles: ['menuitemcheckbox'],
  515   571 		nameFromContents: true,
  516   572 	},
  517   573 	menuitemcheckbox: {
  518    -1 		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    -1 		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 	},
   -1   601 	paragraph: {
   -1   602 		selectors: ['p'],
   -1   603 	},
  547   604 	presentation: {
  548   605 		selectors: ['img[alt=""]'],
  549   606 	},
  550   607 	progressbar: {
  551   608 		selectors: ['progress'],
   -1   609 		defaults: {
   -1   610 			'valuemin': 0,
   -1   611 			'valuemax': 100,
   -1   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    -1 		childRoles: ['progressbar', 'scrollbar', 'slider', 'spinbutton'],
   -1   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    -1 		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    -1 			// FIXME: halfway between actual valuemin and valuemax
  588    -1 			'valuenow': 50,
  589   647 		},
  590   648 	},
   -1   649 	search: {
   -1   650 		selectors: ['search'],
   -1   651 	},
  591   652 	searchbox: {
  592   653 		selectors: ['input[type="search"]:not([list])'],
  593   654 	},
  594   655 	section: {
  595   656 		childRoles: [
  596   657 			'alert',
   -1   658 			'blockquote',
   -1   659 			'caption',
  597   660 			'cell',
   -1   661 			'code',
  598   662 			'definition',
   -1   663 			'deletion',
  599   664 			'doc-abstract',
  600   665 			'doc-colophon',
  601   666 			'doc-credit',
  602   667 			'doc-dedication',
  603   668 			'doc-epigraph',
  604    -1 			'doc-example',
  605   669 			'doc-footnote',
   -1   670 			'doc-pagefooter',
   -1   671 			'doc-pageheader',
   -1   672 			'doc-pullquote',
  606   673 			'doc-qna',
   -1   674 			'emphasis',
  607   675 			'figure',
  608   676 			'group',
  609   677 			'img',
   -1   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',
   -1   686 			'paragraph',
  617   687 			'status',
   -1   688 			'strong',
   -1   689 			'subscript',
   -1   690 			'superscript',
  618   691 			'table',
  619   692 			'tabpanel',
  620   693 			'term',
   -1   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    -1 		childRoles: ['combobox', 'listbox', 'menu', 'radiogroup', 'tree'],
   -1   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',
   -1   717 			'valuemin': 0,
   -1   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    -1 			// FIXME: no valuemin/valuemax
  659    -1 			'valuenow': 0,
   -1   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 	},
   -1   745 	strong: {
   -1   746 		selectors: ['strong'],
   -1   747 	},
  670   748 	structure: {
  671   749 		childRoles: [
  672   750 			'application',
  673   751 			'document',
  674   752 			'none',
   -1   753 			'generic',
  675   754 			'presentation',
   -1   755 			'range',
  676   756 			'rowgroup',
  677   757 			'section',
  678   758 			'sectionhead',
  679   759 			'separator',
  680   760 		],
  681   761 	},
   -1   762 	subscript: {
   -1   763 		selectors: ['sub'],
   -1   764 	},
   -1   765 	superscript: {
   -1   766 		selectors: ['sup'],
   -1   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 	},
   -1   803 	time: {
   -1   804 		selectors: ['time'],
   -1   805 	},
   -1   806 	timer: {
   -1   807 		defaults: {
   -1   808 			'live': 'off',
   -1   809 		},
   -1   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    -1 			'range',
   -1   834 			'progressbar',
  741   835 			'row',
   -1   836 			'scrollbar',
   -1   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 	}
   -1  1004 	if (!ret.trim() && el.matches('svg *')) {
   -1  1005 		var svgTitle = el.querySelector('title');
   -1  1006 		if (svgTitle && svgTitle.parentElement === el) {
   -1  1007 			ret = svgTitle.textContent;
   -1  1008 		}
   -1  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(' ');
   -1  1077 	} else if (el.matches('[aria-description]')) {
   -1  1078 		ret = el.getAttribute('aria-description');
   -1  1079 	} else if (el.matches('svg *')) {
   -1  1080 		var svgDesc = el.querySelector('desc');
   -1  1081 		if (svgDesc && svgDesc.parentElement === el) {
   -1  1082 			ret = svgDesc.textContent;
   -1  1083 		}
  975  1084 	} else if (el.title) {
  976  1085 		ret = el.title;
  977    -1 	} else if (el.placeholder) {
  978    -1 		ret = el.placeholder;
  979  1086 	}
  980  1087 
  981  1088 	ret = (ret || '').trim().replace(/\s+/g, ' ');

diff --git a/package.json b/package.json

@@ -1,6 +1,6 @@
    1     1 {
    2     2   "name": "aria-api",
    3    -1   "version": "0.4.7",
   -1     3   "version": "0.5.0",
    4     4   "description": "Access ARIA information from JavaScript",
    5     5   "main": "index.js",
    6     6   "keywords": [