babelacc

compare different implementations of the text alternative computation  https://p.ce9e.org/babelacc/
git clone https://git.ce9e.org/babelacc.git

commit
e2acd4436dd01ab68ae13ba0842d7e4feb7d85a0
parent
e57c4ca1bdad392a4b225f1d4a983094be5f9f22
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2018-02-03 12:38
install implementations using npm

Diffstat

A .gitignore 1 +
A Makefile 2 ++
D lib/aria-api.js 644 ------------------------------------------------------------
R babel.js -> src/babel.js 9 ++++++---

4 files changed, 9 insertions, 647 deletions


diff --git a/.gitignore b/.gitignore

@@ -0,0 +1 @@
   -1     1 node_modules

diff --git a/Makefile b/Makefile

@@ -0,0 +1,2 @@
   -1     1 babel.js: src/babel.js
   -1     2 	browserify $< -o $@

diff --git a/lib/aria-api.js b/lib/aria-api.js

@@ -1,643 +0,0 @@
    1    -1 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.aria = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
    2    -1 var query = require('./lib/query.js');
    3    -1 var name = require('./lib/name.js');
    4    -1 
    5    -1 module.exports = {
    6    -1 	getRole: query.getRole,
    7    -1 	getAttribute: query.getAttribute,
    8    -1 	getName: name.getName,
    9    -1 	getDescription: name.getDescription,
   10    -1 
   11    -1 	matches: query.matches,
   12    -1 	querySelector: query.querySelector,
   13    -1 	querySelectorAll: query.querySelectorAll,
   14    -1 	closest: query.closest,
   15    -1 };
   16    -1 
   17    -1 },{"./lib/name.js":3,"./lib/query.js":4}],2:[function(require,module,exports){
   18    -1 exports.attributes = {
   19    -1 	// widget
   20    -1 	'autocomplete': 'token',
   21    -1 	'checked': 'tristate',
   22    -1 	'current': 'token',
   23    -1 	'disabled': 'bool',
   24    -1 	'expanded': 'bool-undefined',
   25    -1 	'haspopup': 'token',
   26    -1 	'hidden': 'bool',  // !
   27    -1 	'invalid': 'token',
   28    -1 	'keyshortcuts': 'string',
   29    -1 	'label': 'string',
   30    -1 	'level': 'int',
   31    -1 	'modal': 'bool',
   32    -1 	'multiline': 'bool',
   33    -1 	'multiselectable': 'bool',
   34    -1 	'orientation': 'token',
   35    -1 	'placeholder': 'string',
   36    -1 	'pressed': 'tristate',
   37    -1 	'readonly': 'bool',
   38    -1 	'required': 'bool',
   39    -1 	'roledescription': 'string',
   40    -1 	'selected': 'bool-undefined',
   41    -1 	'valuemax': 'number',
   42    -1 	'valuemin': 'number',
   43    -1 	'valuenow': 'number',
   44    -1 	'valuetext': 'string',
   45    -1 
   46    -1 	// live
   47    -1 	'atomic': 'bool',
   48    -1 	'busy': 'bool',
   49    -1 	'live': 'token',
   50    -1 	'relevant': 'token-list',
   51    -1 
   52    -1 	// dragndrop
   53    -1 	'dropeffect': 'token-list',
   54    -1 	'grabbed': 'bool-undefined',
   55    -1 
   56    -1 	// relationship
   57    -1 	'activedescendant': 'id',
   58    -1 	'colcount': 'int',
   59    -1 	'colindex': 'int',
   60    -1 	'colspan': 'int',
   61    -1 	'controls': 'id-list',
   62    -1 	'describedby': 'id-list',
   63    -1 	'details': 'id',
   64    -1 	'errormessage': 'id',
   65    -1 	'flowto': 'id-list',
   66    -1 	'labelledby': 'id-list',
   67    -1 	'owns': 'id-list',
   68    -1 	'posinset': 'int',
   69    -1 	'rowcount': 'int',
   70    -1 	'rowindex': 'int',
   71    -1 	'rowspan': 'int',
   72    -1 	'setsize': 'int',
   73    -1 	'sort': 'token',
   74    -1 };
   75    -1 
   76    -1 // https://www.w3.org/TR/html-aria/#docconformance
   77    -1 exports.extraSelectors = {
   78    -1 	article: ['article'],
   79    -1 	button: [
   80    -1 		'button',
   81    -1 		'input[type="button"]',
   82    -1 		'input[type="image"]',
   83    -1 		'input[type="reset"]',
   84    -1 		'input[type="submit"]',
   85    -1 		'summary',
   86    -1 	],
   87    -1 	cell: ['td'],
   88    -1 	checkbox: ['input[type="checkbox"]'],
   89    -1 	combobox: [
   90    -1 		'input[type="email"][list]',
   91    -1 		'input[type="search"][list]',
   92    -1 		'input[type="tel"][list]',
   93    -1 		'input[type="text"][list]',
   94    -1 		'input[type="url"][list]',
   95    -1 	],
   96    -1 	complementary: ['aside'],
   97    -1 	definition: ['dd'],
   98    -1 	dialog: ['dialog'],
   99    -1 	document: ['body'],
  100    -1 	figure: ['figure'],
  101    -1 	form: ['form[aria-label]', 'form[aria-labelledby]'],
  102    -1 	group: ['details', 'optgroup'],
  103    -1 	heading: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
  104    -1 	img: ['img:not([alt=""])'],
  105    -1 	link: ['a[href]', 'area[href]', 'link[href]'],
  106    -1 	list: ['dl', 'ol', 'ul'],
  107    -1 	listitem: ['dt', 'ul > li', 'ol > li'],
  108    -1 	main: ['main'],
  109    -1 	math: ['math'],
  110    -1 	menuitemcheckbox: ['menuitem[type="checkbox"]'],
  111    -1 	menuitem: ['menuitem[type="command"]'],
  112    -1 	menuitemradio: ['menuitem[type="radio"]'],
  113    -1 	menu: ['menu[type="context"]'],
  114    -1 	navigation: ['nav'],
  115    -1 	option: ['option'],
  116    -1 	progressbar: ['progress'],
  117    -1 	radio: ['input[type="radio"]'],
  118    -1 	region: ['section'],
  119    -1 	rowgroup: ['tbody', 'thead', 'tfoot'],
  120    -1 	row: ['tr'],
  121    -1 	searchbox: ['input[type="search"]:not([list])'],
  122    -1 	separator: ['hr'],
  123    -1 	slider: ['input[type="range"]'],
  124    -1 	spinbutton: ['input[type="number"]'],
  125    -1 	status: ['output'],
  126    -1 	table: ['table'],
  127    -1 	textbox: [
  128    -1 		'input[type="email"]:not([list])',
  129    -1 		'input[type="tel"]:not([list])',
  130    -1 		'input[type="text"]:not([list])',
  131    -1 		'input[type="url"]:not([list])',
  132    -1 		'textarea',
  133    -1 	],
  134    -1 
  135    -1 	// if scope is missing, it is calculated automatically
  136    -1 	rowheader: ['th[scope="row"]'],
  137    -1 	columnheader: ['th[scope="col"]'],
  138    -1 };
  139    -1 
  140    -1 exports.scoped = [
  141    -1 	'article *', 'aside *', 'main *', 'nav *', 'section *',
  142    -1 ].join(',');
  143    -1 
  144    -1 // https://www.w3.org/TR/wai-aria/roles
  145    -1 var subRoles = {
  146    -1 	cell: ['gridcell', 'rowheader'],
  147    -1 	command: ['button', 'link', 'menuitem'],
  148    -1 	composite: ['grid', 'select', 'spinbutton', 'tablist'],
  149    -1 	img: ['doc-cover'],
  150    -1 	input: ['checkbox', 'option', 'radio', 'slider', 'spinbutton', 'textbox'],
  151    -1 	landmark: [
  152    -1 		'banner',
  153    -1 		'complementary',
  154    -1 		'contentinfo',
  155    -1 		'doc-acknowledgments',
  156    -1 		'doc-afterword',
  157    -1 		'doc-appendix',
  158    -1 		'doc-bibliography',
  159    -1 		'doc-chapter',
  160    -1 		'doc-conclusion',
  161    -1 		'doc-credits',
  162    -1 		'doc-endnotes',
  163    -1 		'doc-epilogue',
  164    -1 		'doc-errata',
  165    -1 		'doc-foreword',
  166    -1 		'doc-glossary',
  167    -1 		'doc-introduction',
  168    -1 		'doc-part',
  169    -1 		'doc-preface',
  170    -1 		'doc-prologue',
  171    -1 		'form',
  172    -1 		'main',
  173    -1 		'navigation',
  174    -1 		'region',
  175    -1 		'search',
  176    -1 	],
  177    -1 	range: ['progressbar', 'scrollbar', 'slider', 'spinbutton'],
  178    -1 	roletype: ['structure', 'widget', 'window'],
  179    -1 	section: [
  180    -1 		'alert',
  181    -1 		'cell',
  182    -1 		'definition',
  183    -1 		'doc-abstract',
  184    -1 		'doc-colophon',
  185    -1 		'doc-credit',
  186    -1 		'doc-dedication',
  187    -1 		'doc-epigraph',
  188    -1 		'doc-example',
  189    -1 		'doc-footnote',
  190    -1 		'doc-qna',
  191    -1 		'figure',
  192    -1 		'group',
  193    -1 		'img',
  194    -1 		'landmark',
  195    -1 		'list',
  196    -1 		'listitem',
  197    -1 		'log',
  198    -1 		'marquee',
  199    -1 		'math',
  200    -1 		'note',
  201    -1 		'status',
  202    -1 		'table',
  203    -1 		'tabpanel',
  204    -1 		'term',
  205    -1 		'tooltip',
  206    -1 	],
  207    -1 	sectionhead: [
  208    -1 		'columnheader',
  209    -1 		'doc-subtitle',
  210    -1 		'heading',
  211    -1 		'rowheader',
  212    -1 		'tab',
  213    -1 	],
  214    -1 	select: ['combobox', 'listbox', 'menu', 'radiogroup', 'tree'],
  215    -1 	separator: ['doc-pagebreak'],
  216    -1 	structure: [
  217    -1 		'application',
  218    -1 		'document',
  219    -1 		'none',
  220    -1 		'presentation',
  221    -1 		'rowgroup',
  222    -1 		'section',
  223    -1 		'sectionhead',
  224    -1 		'separator',
  225    -1 	],
  226    -1 	table: ['grid'],
  227    -1 	textbox: ['searchbox'],
  228    -1 	widget: [
  229    -1 		'command',
  230    -1 		'composite',
  231    -1 		'gridcell',
  232    -1 		'input',
  233    -1 		'range',
  234    -1 		'row',
  235    -1 		'separator',
  236    -1 		'tab',
  237    -1 	],
  238    -1 	window: ['dialog'],
  239    -1 	alert: ['alertdialog'],
  240    -1 	checkbox: ['menuitemcheckbox', 'switch'],
  241    -1 	dialog: ['alertdialog'],
  242    -1 	gridcell: ['columnheader', 'rowheader'],
  243    -1 	menuitem: ['menuitemcheckbox'],
  244    -1 	menuitemcheckbox: ['menuitemradio'],
  245    -1 	option: ['treeitem'],
  246    -1 	radio: ['menuitemradio'],
  247    -1 	status: ['timer'],
  248    -1 	grid: ['treegrid'],
  249    -1 	menu: ['menubar'],
  250    -1 	tree: ['treegrid'],
  251    -1 	document: ['article'],
  252    -1 	group: ['row', 'select', 'toolbar'],
  253    -1 	link: ['doc-backlink', 'doc-biblioref', 'doc-glossref', 'doc-noteref'],
  254    -1 	list: ['directory', 'feed'],
  255    -1 	listitem: ['doc-biblioentry', 'doc-endnote', 'treeitem'],
  256    -1 	navigation: ['doc-index', 'doc-pagelist', 'doc-toc'],
  257    -1 	note: ['doc-notice', 'doc-tip'],
  258    -1 };
  259    -1 
  260    -1 var getSubRoles = function(role) {
  261    -1 	var children = subRoles[role] || [];
  262    -1 	var descendents = children.map(getSubRoles);
  263    -1 
  264    -1 	var result = [role];
  265    -1 
  266    -1 	descendents.forEach(function(list) {
  267    -1 		list.forEach(function(r) {
  268    -1 			if (result.indexOf(r) === -1) {
  269    -1 				result.push(r);
  270    -1 			}
  271    -1 		});
  272    -1 	});
  273    -1 
  274    -1 	return result;
  275    -1 };
  276    -1 
  277    -1 exports.subRoles = {};
  278    -1 for (var role in subRoles) {
  279    -1 	exports.subRoles[role] = getSubRoles(role);
  280    -1 }
  281    -1 exports.subRoles['none'] = ['none', 'presentation'];
  282    -1 exports.subRoles['presentation'] = ['presentation', 'none'];
  283    -1 
  284    -1 exports.nameFromContents = [
  285    -1 	'button',
  286    -1 	'checkbox',
  287    -1 	'columnheader',
  288    -1 	'doc-backlink',
  289    -1 	'doc-biblioref',
  290    -1 	'doc-glossref',
  291    -1 	'doc-noteref',
  292    -1 	'gridcell',
  293    -1 	'heading',
  294    -1 	'link',
  295    -1 	'menuitem',
  296    -1 	'menuitemcheckbox',
  297    -1 	'menuitemradio',
  298    -1 	'option',
  299    -1 	'radio',
  300    -1 	'row',
  301    -1 	'rowgroup',
  302    -1 	'rowheader',
  303    -1 	'sectionhead',
  304    -1 	'tab',
  305    -1 	'tooltip',
  306    -1 	'treeitem',
  307    -1 	'switch',
  308    -1 ];
  309    -1 
  310    -1 exports.labelable = [
  311    -1 	'button',
  312    -1 	'input:not([type="hidden"])',
  313    -1 	'keygen',
  314    -1 	'meter',
  315    -1 	'output',
  316    -1 	'progress',
  317    -1 	'select',
  318    -1 	'textarea',
  319    -1 ];
  320    -1 
  321    -1 },{}],3:[function(require,module,exports){
  322    -1 var constants = require('./constants.js');
  323    -1 var query = require('./query.js');
  324    -1 
  325    -1 var getPseudoContent = function(node, selector) {
  326    -1 	var styles = window.getComputedStyle(node, selector);
  327    -1 	var ret = styles.getPropertyValue('content');
  328    -1 	if (ret === 'none' || ret.substr(0, 4) === '-moz') {
  329    -1 		return '';
  330    -1 	} else {
  331    -1 		return ret
  332    -1 			.replace(/^["']/, '')
  333    -1 			.replace(/["']$/, '');
  334    -1 	}
  335    -1 };
  336    -1 
  337    -1 var getContent = function(root, referenced) {
  338    -1 	var ret = getPseudoContent(root, ':before');
  339    -1 	var node = root.firstChild;
  340    -1 	while (node) {
  341    -1 		if (node.nodeType === node.TEXT_NODE) {
  342    -1 			ret += node.textContent;
  343    -1 		} else if (node.nodeType === node.ELEMENT_NODE) {
  344    -1 			ret += getName(node, true, referenced);
  345    -1 		}
  346    -1 		node = node.nextSibling;
  347    -1 	}
  348    -1 	ret += getPseudoContent(root, ':after');
  349    -1 	return ret;
  350    -1 };
  351    -1 
  352    -1 var allowNameFromContent = function(el) {
  353    -1 	var role = query.getRole(el);
  354    -1 	return !role || constants.nameFromContents.indexOf(role) !== -1;
  355    -1 };
  356    -1 
  357    -1 var isLabelable = function(el) {
  358    -1 	var selector = constants.labelable.join(',');
  359    -1 	return el.matches(selector);
  360    -1 };
  361    -1 
  362    -1 // Control.labels is part of the standard, but not supported in most browsers
  363    -1 var getLabelNode = function(node) {
  364    -1 	if (node.id) {
  365    -1 		var selector = 'label[for="' + node.id + '"]';
  366    -1 		var label = document.querySelector(selector);
  367    -1 		if (label) {
  368    -1 			return label;
  369    -1 		}
  370    -1 	}
  371    -1 
  372    -1 	var p = node.parentElement;
  373    -1 	while (p) {
  374    -1 		if (p.tagName.toLowerCase() === 'label') {
  375    -1 			return p;
  376    -1 		}
  377    -1 		p = p.parentElement;
  378    -1 	}
  379    -1 };
  380    -1 
  381    -1 // http://www.ssbbartgroup.com/blog/how-the-w3c-text-alternative-computation-works/
  382    -1 // https://www.w3.org/TR/accname-aam-1.1/#h-mapping_additional_nd_te
  383    -1 var getName = function(el, recursive, referenced) {
  384    -1 	var ret;
  385    -1 
  386    -1 	if (query.getAttribute(el, 'hidden', referenced)) {
  387    -1 		return '';
  388    -1 	}
  389    -1 	if (query.matches(el, 'presentation')) {
  390    -1 		return getContent(el, referenced);
  391    -1 	}
  392    -1 	if (!recursive && el.matches('[aria-labelledby]')) {
  393    -1 		var ids = el.getAttribute('aria-labelledby').split(/\s+/);
  394    -1 		var strings = ids.map(function(id) {
  395    -1 			var label = document.getElementById(id);
  396    -1 			return getName(label, true, label);
  397    -1 		});
  398    -1 		ret = strings.join(' ');
  399    -1 	}
  400    -1 	if (!ret && el.matches('[aria-label]')) {
  401    -1 		ret = el.getAttribute('aria-label');
  402    -1 	}
  403    -1 	if (!query.matches(el, 'presentation')) {
  404    -1 		if (!ret && isLabelable(el)) {
  405    -1 			var label = getLabelNode(el);
  406    -1 			if (!recursive && label) {
  407    -1 				ret = getName(label, true, label);
  408    -1 			}
  409    -1 		}
  410    -1 		if (!ret) {
  411    -1 			ret = el.getAttribute('placeholder');
  412    -1 		}
  413    -1 		// figcaption
  414    -1 		if (!ret) {
  415    -1 			ret = el.getAttribute('alt');
  416    -1 		}
  417    -1 		// caption
  418    -1 		// table
  419    -1 	}
  420    -1 	// FIXME only if this is embedded in a label
  421    -1 	if (!ret && query.matches(el, 'input')) {
  422    -1 		// combobox
  423    -1 		// button
  424    -1 		if (query.matches(el, 'range')) {
  425    -1 			ret = query.getAttribute(el, 'valuetext') || query.getAttribute(el, 'valuenow') || el.value;
  426    -1 		} else {
  427    -1 			ret = el.value;
  428    -1 		}
  429    -1 		ret = '' + ret;
  430    -1 	}
  431    -1 	if (!ret && (recursive || allowNameFromContent(el))) {
  432    -1 		ret = getContent(el, referenced);
  433    -1 	}
  434    -1 	if (!ret) {
  435    -1 		ret = el.getAttribute('title');
  436    -1 	}
  437    -1 
  438    -1 	return (ret || '').trim().replace(/\s+/g, ' ');
  439    -1 };
  440    -1 
  441    -1 var getDescription = function(el) {
  442    -1 	var ret = '';
  443    -1 
  444    -1 	if (el.matches('[aria-describedby]')) {
  445    -1 		var ids = el.getAttribute('aria-describedby').split(/\s+/);
  446    -1 		var strings = ids.map(function(id) {
  447    -1 			var label = document.getElementById(id);
  448    -1 			return getName(label, true, label);
  449    -1 		});
  450    -1 		ret = strings.join(' ');
  451    -1 	} else if (el.title) {
  452    -1 		ret = el.title;
  453    -1 	} else if (el.placeholder) {
  454    -1 		ret = el.placeholder;
  455    -1 	}
  456    -1 
  457    -1 	return (ret || '').trim().replace(/\s+/g, ' ');
  458    -1 };
  459    -1 
  460    -1 module.exports = {
  461    -1 	getName: getName,
  462    -1 	getDescription: getDescription,
  463    -1 };
  464    -1 
  465    -1 },{"./constants.js":2,"./query.js":4}],4:[function(require,module,exports){
  466    -1 var constants = require('./constants.js');
  467    -1 var util = require('./util.js');
  468    -1 
  469    -1 var getSubRoles = function(roles) {
  470    -1 	return [].concat.apply([], roles.map(function(role) {
  471    -1 		return constants.subRoles[role] || [role];
  472    -1 	}));
  473    -1 };
  474    -1 
  475    -1 // candidates can be passed for performance optimization
  476    -1 var _getRole = function(el, candidates) {
  477    -1 	if (el.hasAttribute('role')) {
  478    -1 		return el.getAttribute('role');
  479    -1 	}
  480    -1 	for (var role in constants.extraSelectors) {
  481    -1 		var selector = constants.extraSelectors[role].join(',');
  482    -1 		if ((!candidates || candidates.indexOf(role) !== -1) && el.matches(selector)) {
  483    -1 			return role;
  484    -1 		}
  485    -1 	}
  486    -1 
  487    -1 	if (!candidates ||
  488    -1 			candidates.indexOf('banner') !== -1 ||
  489    -1 			candidates.indexOf('contentinfo') !== -1) {
  490    -1 		var scoped = el.matches(constants.scoped);
  491    -1 
  492    -1 		if (el.matches('header') && !scoped) {
  493    -1 			return 'banner';
  494    -1 		}
  495    -1 		if (el.matches('footer') && !scoped) {
  496    -1 			return 'contentinfo';
  497    -1 		}
  498    -1 	}
  499    -1 };
  500    -1 
  501    -1 var getAttribute = function(el, key, _hiddenRoot) {
  502    -1 	if (key === 'hidden' && el === _hiddenRoot) {  // used for name calculation
  503    -1 		return false;
  504    -1 	}
  505    -1 
  506    -1 	var type = constants.attributes[key];
  507    -1 	var raw = el.getAttribute('aria-' + key);
  508    -1 
  509    -1 	if (raw) {
  510    -1 		if (type === 'bool') {
  511    -1 			return raw === 'true';
  512    -1 		} else if (type === 'tristate') {
  513    -1 			return raw === 'true' ? true : raw === 'false' ? false : 'mixed';
  514    -1 		} else if (type === 'bool-undefined') {
  515    -1 			return raw === 'true' ? true : raw === 'false' ? false : undefined;
  516    -1 		} else if (type === 'id-list') {
  517    -1 			return raw.split(/\s+/);
  518    -1 		} else if (type === 'integer') {
  519    -1 			return parseInt(raw);
  520    -1 		} else if (type === 'number') {
  521    -1 			return parseFloat(raw);
  522    -1 		} else if (type === 'token-list') {
  523    -1 			return raw.split(/\s+/);
  524    -1 		} else {
  525    -1 			return raw;
  526    -1 		}
  527    -1 	}
  528    -1 
  529    -1 	if (key === 'level') {
  530    -1 		for (var i = 1; i <= 6; i++) {
  531    -1 			if (el.tagName.toLowerCase() === 'h' + i) {
  532    -1 				return i;
  533    -1 			}
  534    -1 		}
  535    -1 	} else if (key === 'disabled') {
  536    -1 		return el.disabled;
  537    -1 	} else if (key === 'placeholder') {
  538    -1 		return el.placeholder;
  539    -1 	} else if (key === 'required') {
  540    -1 		return el.required;
  541    -1 	} else if (key === 'readonly') {
  542    -1 		return el.readOnly && !el.isContentEditable;
  543    -1 	} else if (key === 'hidden') {
  544    -1 		var style = window.getComputedStyle(el);
  545    -1 		if (el.hidden || style.display === 'none' || style.visibility === 'hidden') {
  546    -1 			return true;
  547    -1 		} else if (el.clientHeight === 0) {  // rough check for performance
  548    -1 			return el.parentNode && getAttribute(el.parentNode, 'hidden', _hiddenRoot);
  549    -1 		}
  550    -1 	} else if (key === 'invalid' && el.checkValidity) {
  551    -1 		return el.checkValidity();
  552    -1 	}
  553    -1 
  554    -1 	if (type === 'bool' || type === 'tristate') {
  555    -1 		return false;
  556    -1 	}
  557    -1 };
  558    -1 
  559    -1 var matches = function(el, selector) {
  560    -1 	var actual;
  561    -1 
  562    -1 	if (selector.substr(0, 1) === ':') {
  563    -1 		var attr = selector.substr(1);
  564    -1 		return getAttribute(el, attr);
  565    -1 	} else if (selector.substr(0, 1) === '[') {
  566    -1 		var match = /\[([a-z]+)="(.*)"\]/.exec(selector);
  567    -1 		actual = getAttribute(el, match[1]);
  568    -1 		var rawValue = match[2];
  569    -1 		return actual.toString() == rawValue;
  570    -1 	} else {
  571    -1 		var candidates = getSubRoles(selector.split(','));
  572    -1 		actual = _getRole(el, candidates);
  573    -1 		return candidates.indexOf(actual) !== -1;
  574    -1 	}
  575    -1 };
  576    -1 
  577    -1 var _querySelector = function(all) {
  578    -1 	return function(root, role) {
  579    -1 		var results = [];
  580    -1 		util.walkDOM(root, function(node) {
  581    -1 			if (node.nodeType === node.ELEMENT_NODE) {
  582    -1 				// FIXME: skip hidden elements
  583    -1 				if (matches(node, role)) {
  584    -1 					results.push(node);
  585    -1 					if (!all) {
  586    -1 						return false;
  587    -1 					}
  588    -1 				}
  589    -1 			}
  590    -1 		});
  591    -1 		return all ? results : results[0];
  592    -1 	};
  593    -1 };
  594    -1 
  595    -1 var closest = function(el, selector) {
  596    -1 	return util.searchUp(el, function(candidate) {
  597    -1 		return matches(candidate, selector);
  598    -1 	});
  599    -1 };
  600    -1 
  601    -1 module.exports = {
  602    -1 	getRole: function(el) {
  603    -1 		return _getRole(el);
  604    -1 	},
  605    -1 	getAttribute: getAttribute,
  606    -1 	matches: matches,
  607    -1 	querySelector: _querySelector(),
  608    -1 	querySelectorAll: _querySelector(true),
  609    -1 	closest: closest,
  610    -1 };
  611    -1 
  612    -1 },{"./constants.js":2,"./util.js":5}],5:[function(require,module,exports){
  613    -1 var walkDOM = function(root, fn) {
  614    -1 	if (fn(root) === false) {
  615    -1 		return false;
  616    -1 	}
  617    -1 	var node = root.firstChild;
  618    -1 	while (node) {
  619    -1 		if (walkDOM(node, fn) === false) {
  620    -1 			return false;
  621    -1 		}
  622    -1 		node = node.nextSibling;
  623    -1 	}
  624    -1 };
  625    -1 
  626    -1 var searchUp = function(el, test) {
  627    -1 	var candidate = el.parentElement;
  628    -1 	if (candidate) {
  629    -1 		if (test(candidate)) {
  630    -1 			return candidate;
  631    -1 		} else {
  632    -1 			return searchUp(candidate, test);
  633    -1 		}
  634    -1 	}
  635    -1 };
  636    -1 
  637    -1 module.exports = {
  638    -1 	walkDOM: walkDOM,
  639    -1 	searchUp: searchUp,
  640    -1 };
  641    -1 
  642    -1 },{}]},{},[1])(1)
  643    -1 })
  643    -1 
\ No newline at end of file

diff --git a/babel.js b/src/babel.js

@@ -1,3 +1,6 @@
   -1     1 var ariaApi = require('aria-api');
   -1     2 var accdc = require('../lib/accdc');
   -1     3 
    1     4 var form = document.querySelector('#ba-form');
    2     5 var preview = document.querySelector('#ba-preview');
    3     6 var results = document.querySelector('#ba-results');
@@ -5,11 +8,11 @@ var results = document.querySelector('#ba-results');
    5     8 var implementations = {
    6     9 	'aria-api': function(el) {
    7    10 		return {
    8    -1 			name: aria.getName(el),
    9    -1 			desc: aria.getDescription(el)
   -1    11 			name: ariaApi.getName(el),
   -1    12 			desc: ariaApi.getDescription(el)
   10    13 		};
   11    14 	},
   12    -1 	'accdc': calcNames
   -1    15 	'accdc': accdc.calcNames,
   13    16 };
   14    17 
   15    18 var createTd = function(text) {