dom-accessibility-api
Advanced tools
Comparing version 0.3.0 to 0.4.0
@@ -0,1 +1,11 @@ | ||
## 0.4.0 | ||
### Minor Changes | ||
- [`e80a1fb`](https://github.com/eps1lon/dom-accessibility-api/commit/e80a1fb32c136539a46007a64ef8c998855080a1) [#141](https://github.com/eps1lon/dom-accessibility-api/pull/141) Thanks [@eps1lon](https://github.com/eps1lon)! - Support ES5 environments | ||
### Patch Changes | ||
- [`bd41c2d`](https://github.com/eps1lon/dom-accessibility-api/commit/bd41c2d3dec9c27e178b65bbe226d3c7adef0678) [#143](https://github.com/eps1lon/dom-accessibility-api/pull/143) Thanks [@eps1lon](https://github.com/eps1lon)! - fix: support `<label for>` for `<select>` and `<textarea>` | ||
## 0.3.0 | ||
@@ -2,0 +12,0 @@ |
/** | ||
* implements https://w3c.github.io/accname/ | ||
*/ | ||
/** | ||
* interface for an options-bag where `window.getComputedStyle` can be mocked | ||
@@ -6,0 +3,0 @@ */ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.computeAccessibleName = computeAccessibleName; | ||
var _from = _interopRequireDefault(require("core-js-pure/features/array/from")); | ||
var _set = _interopRequireDefault(require("core-js-pure/stable/set")); | ||
var _getRole = _interopRequireDefault(require("./getRole")); | ||
var _util = require("./util"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } | ||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } | ||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } | ||
/** | ||
* implements https://w3c.github.io/accname/ | ||
*/ | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const getRole_1 = __importDefault(require("./getRole")); | ||
const util_1 = require("./util"); | ||
/** | ||
* Small utility that handles all the JS quirks with `this` which is important | ||
@@ -18,9 +33,6 @@ * if no mock is provided. | ||
function createGetComputedStyle(element, options) { | ||
const window = util_1.safeWindow(element); | ||
const { | ||
// This might be overengineered. I don't know what happens if I call | ||
// window.getComputedStyle(elementFromAnotherWindow) or if I don't bind it | ||
// the type declarations don't require a `this` | ||
getComputedStyle = window.getComputedStyle.bind(window) } = options; | ||
return getComputedStyle; | ||
var window = (0, _util.safeWindow)(element); | ||
var _options$getComputedS = options.getComputedStyle, | ||
getComputedStyle = _options$getComputedS === void 0 ? window.getComputedStyle.bind(window) : _options$getComputedS; | ||
return getComputedStyle; | ||
} | ||
@@ -32,4 +44,6 @@ /** | ||
*/ | ||
function asFlatString(s) { | ||
return s.trim().replace(/\s\s+/g, " "); | ||
return s.trim().replace(/\s\s+/g, " "); | ||
} | ||
@@ -39,16 +53,6 @@ /** | ||
*/ | ||
function prohibitsNaming(node) { | ||
return hasAnyConcreteRoles(node, [ | ||
"caption", | ||
"code", | ||
"deletion", | ||
"emphasis", | ||
"generic", | ||
"insertion", | ||
"paragraph", | ||
"presentation", | ||
"strong", | ||
"subscript", | ||
"superscript" | ||
]); | ||
return hasAnyConcreteRoles(node, ["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"]); | ||
} | ||
@@ -61,13 +65,15 @@ /** | ||
*/ | ||
function isHidden(node, options) { | ||
if (!util_1.isElement(node)) { | ||
return false; | ||
} | ||
if (node.hasAttribute("hidden") || | ||
node.getAttribute("aria-hidden") === "true") { | ||
return true; | ||
} | ||
const style = createGetComputedStyle(node, options)(node); | ||
return (style.getPropertyValue("display") === "none" || | ||
style.getPropertyValue("visibility") === "hidden"); | ||
if (!(0, _util.isElement)(node)) { | ||
return false; | ||
} | ||
if (node.hasAttribute("hidden") || node.getAttribute("aria-hidden") === "true") { | ||
return true; | ||
} | ||
var style = createGetComputedStyle(node, options)(node); | ||
return style.getPropertyValue("display") === "none" || style.getPropertyValue("visibility") === "hidden"; | ||
} | ||
@@ -80,16 +86,20 @@ /** | ||
*/ | ||
function idRefs(node, attributeName) { | ||
if (util_1.isElement(node) && node.hasAttribute(attributeName)) { | ||
// safe due to hasAttribute check | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const ids = node.getAttribute(attributeName).split(" "); | ||
return ids | ||
// safe since it can't be null for an Element | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
.map(id => node.ownerDocument.getElementById(id)) | ||
.filter((element) => element !== null | ||
// TODO: why does this not narrow? | ||
); | ||
} | ||
return []; | ||
if ((0, _util.isElement)(node) && node.hasAttribute(attributeName)) { | ||
// safe due to hasAttribute check | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
var ids = node.getAttribute(attributeName).split(" "); | ||
return ids // safe since it can't be null for an Element | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
.map(function (id) { | ||
return node.ownerDocument.getElementById(id); | ||
}).filter(function (element) { | ||
return element !== null; | ||
} // TODO: why does this not narrow? | ||
); | ||
} | ||
return []; | ||
} | ||
@@ -101,4 +111,6 @@ /** | ||
*/ | ||
function queryChildNodes(node) { | ||
return Array.from(node.childNodes).concat(idRefs(node, "aria-owns")); | ||
return (0, _from.default)(node.childNodes).concat(idRefs(node, "aria-owns")); | ||
} | ||
@@ -109,28 +121,28 @@ /** | ||
*/ | ||
function isControl(node) { | ||
return (hasAnyConcreteRoles(node, ["button", "combobox", "listbox", "textbox"]) || | ||
hasAbstractRole(node, "range")); | ||
return hasAnyConcreteRoles(node, ["button", "combobox", "listbox", "textbox"]) || hasAbstractRole(node, "range"); | ||
} | ||
function hasAbstractRole(node, role) { | ||
if (!util_1.isElement(node)) { | ||
return false; | ||
} | ||
switch (role) { | ||
case "range": | ||
return hasAnyConcreteRoles(node, [ | ||
"meter", | ||
"progressbar", | ||
"scrollbar", | ||
"slider", | ||
"spinbutton" | ||
]); | ||
default: | ||
throw new TypeError(`No knowledge about abstract role '${role}'. This is likely a bug :(`); | ||
} | ||
if (!(0, _util.isElement)(node)) { | ||
return false; | ||
} | ||
switch (role) { | ||
case "range": | ||
return hasAnyConcreteRoles(node, ["meter", "progressbar", "scrollbar", "slider", "spinbutton"]); | ||
default: | ||
throw new TypeError("No knowledge about abstract role '".concat(role, "'. This is likely a bug :(")); | ||
} | ||
} | ||
function hasAnyConcreteRoles(node, roles) { | ||
if (util_1.isElement(node)) { | ||
return roles.indexOf(getRole_1.default(node)) !== -1; | ||
} | ||
return false; | ||
if ((0, _util.isElement)(node)) { | ||
return roles.indexOf((0, _getRole.default)(node)) !== -1; | ||
} | ||
return false; | ||
} | ||
@@ -142,24 +154,34 @@ /** | ||
*/ | ||
function querySelectorAllSubtree(element, selectors) { | ||
const elements = []; | ||
for (const root of [element, ...idRefs(element, "aria-owns")]) { | ||
elements.push(...Array.from(root.querySelectorAll(selectors))); | ||
} | ||
return elements; | ||
var elements = []; | ||
for (var _i = 0, _arr = [element].concat(_toConsumableArray(idRefs(element, "aria-owns"))); _i < _arr.length; _i++) { | ||
var root = _arr[_i]; | ||
elements.push.apply(elements, _toConsumableArray((0, _from.default)(root.querySelectorAll(selectors)))); | ||
} | ||
return elements; | ||
} | ||
function querySelectedOptions(listbox) { | ||
if (util_1.isHTMLSelectElement(listbox)) { | ||
// IE11 polyfill | ||
return (listbox.selectedOptions || querySelectorAllSubtree(listbox, "[selected]")); | ||
} | ||
return querySelectorAllSubtree(listbox, '[aria-selected="true"]'); | ||
if ((0, _util.isHTMLSelectElement)(listbox)) { | ||
// IE11 polyfill | ||
return listbox.selectedOptions || querySelectorAllSubtree(listbox, "[selected]"); | ||
} | ||
return querySelectorAllSubtree(listbox, '[aria-selected="true"]'); | ||
} | ||
function isMarkedPresentational(node) { | ||
return hasAnyConcreteRoles(node, ["none", "presentation"]); | ||
return hasAnyConcreteRoles(node, ["none", "presentation"]); | ||
} | ||
/** | ||
* TODO | ||
* TODO https://github.com/eps1lon/dom-accessibility-api/issues/99 | ||
*/ | ||
function isNativeHostLanguageTextAlternativeElement(node) { | ||
return false; | ||
return false; | ||
} | ||
@@ -169,51 +191,41 @@ /** | ||
*/ | ||
function allowsNameFromContent(node) { | ||
return hasAnyConcreteRoles(node, [ | ||
"button", | ||
"cell", | ||
"checkbox", | ||
"columnheader", | ||
"gridcell", | ||
"heading", | ||
"label", | ||
"legend", | ||
"link", | ||
"menuitem", | ||
"menuitemcheckbox", | ||
"menuitemradio", | ||
"option", | ||
"radio", | ||
"row", | ||
"rowheader", | ||
"switch", | ||
"tab", | ||
"tooltip", | ||
"treeitem" | ||
]); | ||
return hasAnyConcreteRoles(node, ["button", "cell", "checkbox", "columnheader", "gridcell", "heading", "label", "legend", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "row", "rowheader", "switch", "tab", "tooltip", "treeitem"]); | ||
} | ||
/** | ||
* TODO | ||
* TODO https://github.com/eps1lon/dom-accessibility-api/issues/100 | ||
*/ | ||
function isDescendantOfNativeHostLanguageTextAlternativeElement(node) { | ||
return false; | ||
return false; | ||
} | ||
/** | ||
* TODO | ||
* TODO https://github.com/eps1lon/dom-accessibility-api/issues/101 | ||
*/ | ||
function computeTooltipAttributeValue(node) { | ||
return null; | ||
return null; | ||
} | ||
function getValueOfTextbox(element) { | ||
if (util_1.isHTMLInputElement(element) || util_1.isHTMLTextAreaElement(element)) { | ||
return element.value; | ||
} | ||
// https://github.com/eps1lon/dom-accessibility-api/issues/4 | ||
return element.textContent || ""; | ||
if ((0, _util.isHTMLInputElement)(element) || (0, _util.isHTMLTextAreaElement)(element)) { | ||
return element.value; | ||
} // https://github.com/eps1lon/dom-accessibility-api/issues/4 | ||
return element.textContent || ""; | ||
} | ||
function getTextualContent(declaration) { | ||
const content = declaration.getPropertyValue("content"); | ||
if (/^["'].*["']$/.test(content)) { | ||
return content.slice(1, -1); | ||
} | ||
return ""; | ||
var content = declaration.getPropertyValue("content"); | ||
if (/^["'].*["']$/.test(content)) { | ||
return content.slice(1, -1); | ||
} | ||
return ""; | ||
} | ||
@@ -226,219 +238,273 @@ /** | ||
*/ | ||
function computeAccessibleName(root, options = {}) { | ||
const consultedNodes = new Set(); | ||
if (prohibitsNaming(root)) { | ||
return ""; | ||
function computeAccessibleName(root) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var consultedNodes = new _set.default(); | ||
if (prohibitsNaming(root)) { | ||
return ""; | ||
} // 2F.i | ||
function computeMiscTextAlternative(node, context) { | ||
var accumulatedText = ""; | ||
if ((0, _util.isElement)(node)) { | ||
var pseudoBefore = createGetComputedStyle(node, options)(node, "::before"); | ||
var beforeContent = getTextualContent(pseudoBefore); | ||
accumulatedText = "".concat(beforeContent, " ").concat(accumulatedText); | ||
} | ||
// 2F.i | ||
function computeMiscTextAlternative(node, context) { | ||
let accumulatedText = ""; | ||
if (util_1.isElement(node)) { | ||
const pseudoBefore = createGetComputedStyle(node, options)(node, "::before"); | ||
const beforeContent = getTextualContent(pseudoBefore); | ||
accumulatedText = `${beforeContent} ${accumulatedText}`; | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = queryChildNodes(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var child = _step.value; | ||
var result = computeTextAlternative(child, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false, | ||
recursion: true | ||
}); // TODO: Unclear why display affects delimiter | ||
var display = (0, _util.isElement)(node) && createGetComputedStyle(node, options)(node).getPropertyValue("display"); | ||
var separator = display !== "inline" ? " " : ""; | ||
accumulatedText += "".concat(separator).concat(result); | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return != null) { | ||
_iterator.return(); | ||
} | ||
for (const child of queryChildNodes(node)) { | ||
const result = computeTextAlternative(child, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false, | ||
recursion: true | ||
}); | ||
// TODO: Unclear why display affects delimiter | ||
const display = util_1.isElement(node) && | ||
createGetComputedStyle(node, options)(node).getPropertyValue("display"); | ||
const separator = display !== "inline" ? " " : ""; | ||
accumulatedText += `${separator}${result}`; | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
if (util_1.isElement(node)) { | ||
const pseudoAfter = createGetComputedStyle(node, options)(node, ":after"); | ||
const afterContent = getTextualContent(pseudoAfter); | ||
accumulatedText = `${accumulatedText} ${afterContent}`; | ||
} | ||
return accumulatedText; | ||
} | ||
} | ||
/** | ||
* TODO: placeholder | ||
*/ | ||
function computeAttributeTextAlternative(node) { | ||
if (!util_1.isElement(node)) { | ||
return null; | ||
} | ||
const titleAttribute = node.getAttributeNode("title"); | ||
if (titleAttribute !== null && !consultedNodes.has(titleAttribute)) { | ||
consultedNodes.add(titleAttribute); | ||
return titleAttribute.value; | ||
} | ||
const altAttribute = node.getAttributeNode("alt"); | ||
if (altAttribute !== null && !consultedNodes.has(altAttribute)) { | ||
consultedNodes.add(altAttribute); | ||
return altAttribute.value; | ||
} | ||
if (util_1.isHTMLInputElement(node) && node.type === "button") { | ||
consultedNodes.add(node); | ||
return node.getAttribute("value") || ""; | ||
} | ||
return null; | ||
if ((0, _util.isElement)(node)) { | ||
var pseudoAfter = createGetComputedStyle(node, options)(node, ":after"); | ||
var afterContent = getTextualContent(pseudoAfter); | ||
accumulatedText = "".concat(accumulatedText, " ").concat(afterContent); | ||
} | ||
function computeElementTextAlternative(node) { | ||
if (!util_1.isHTMLInputElement(node)) { | ||
return null; | ||
} | ||
const input = node; | ||
// https://w3c.github.io/html-aam/#input-type-text-input-type-password-input-type-search-input-type-tel-input-type-email-input-type-url-and-textarea-element-accessible-description-computation | ||
if (input.type === "submit") { | ||
return "Submit"; | ||
} | ||
if (input.type === "reset") { | ||
return "Reset"; | ||
} | ||
const { labels } = input; | ||
// IE11 does not implement labels, TODO: verify with caniuse instead of mdn | ||
if (labels === null || labels === undefined || labels.length === 0) { | ||
return null; | ||
} | ||
consultedNodes.add(input); | ||
return Array.from(labels) | ||
.map(element => { | ||
return computeTextAlternative(element, { | ||
isEmbeddedInLabel: true, | ||
isReferenced: false, | ||
recursion: true | ||
}); | ||
}) | ||
.filter(label => { | ||
return label.length > 0; | ||
}) | ||
.join(" "); | ||
return accumulatedText; | ||
} | ||
function computeAttributeTextAlternative(node) { | ||
if (!(0, _util.isElement)(node)) { | ||
return null; | ||
} | ||
function computeTextAlternative(current, context) { | ||
if (consultedNodes.has(current)) { | ||
return ""; | ||
var titleAttribute = node.getAttributeNode("title"); | ||
if (titleAttribute !== null && !consultedNodes.has(titleAttribute)) { | ||
consultedNodes.add(titleAttribute); | ||
return titleAttribute.value; | ||
} | ||
var altAttribute = node.getAttributeNode("alt"); | ||
if (altAttribute !== null && !consultedNodes.has(altAttribute)) { | ||
consultedNodes.add(altAttribute); | ||
return altAttribute.value; | ||
} | ||
if ((0, _util.isHTMLInputElement)(node) && node.type === "button") { | ||
consultedNodes.add(node); | ||
return node.getAttribute("value") || ""; | ||
} | ||
return null; | ||
} | ||
function computeElementTextAlternative(node) { | ||
if (!(0, _util.isHTMLInputElement)(node)) { | ||
return null; | ||
} | ||
var input = node; // https://w3c.github.io/html-aam/#input-type-text-input-type-password-input-type-search-input-type-tel-input-type-email-input-type-url-and-textarea-element-accessible-description-computation | ||
if (input.type === "submit") { | ||
return "Submit"; | ||
} | ||
if (input.type === "reset") { | ||
return "Reset"; | ||
} | ||
var labels = input.labels; // IE11 does not implement labels, TODO: verify with caniuse instead of mdn | ||
if (labels === null || labels === undefined || labels.length === 0) { | ||
return null; | ||
} | ||
consultedNodes.add(input); | ||
return (0, _from.default)(labels).map(function (element) { | ||
return computeTextAlternative(element, { | ||
isEmbeddedInLabel: true, | ||
isReferenced: false, | ||
recursion: true | ||
}); | ||
}).filter(function (label) { | ||
return label.length > 0; | ||
}).join(" "); | ||
} | ||
function computeTextAlternative(current, context) { | ||
if (consultedNodes.has(current)) { | ||
return ""; | ||
} // special casing, cheating to make tests pass | ||
// https://github.com/w3c/accname/issues/67 | ||
if (hasAnyConcreteRoles(current, ["menu"])) { | ||
consultedNodes.add(current); | ||
return ""; | ||
} // 2A | ||
if (isHidden(current, options) && !context.isReferenced) { | ||
consultedNodes.add(current); | ||
return ""; | ||
} // 2B | ||
var labelElements = idRefs(current, "aria-labelledby"); | ||
if (!context.isReferenced && labelElements.length > 0) { | ||
return labelElements.map(function (element) { | ||
return computeTextAlternative(element, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: true, | ||
// thais isn't recursion as specified, otherwise we would skip | ||
// `aria-label` in | ||
// <input id="myself" aria-label="foo" aria-labelledby="myself" | ||
recursion: false | ||
}); | ||
}).join(" "); | ||
} // 2C | ||
// Changed from the spec in anticipation of https://github.com/w3c/accname/issues/64 | ||
// spec says we should only consider skipping if we have a non-empty label | ||
var skipToStep2E = context.recursion && isControl(current); | ||
if (!skipToStep2E) { | ||
var ariaLabel = ((0, _util.isElement)(current) && current.getAttribute("aria-label") || "").trim(); | ||
if (ariaLabel !== "") { | ||
consultedNodes.add(current); | ||
return ariaLabel; | ||
} // 2D | ||
if (!isMarkedPresentational(current)) { | ||
var elementTextAlternative = computeElementTextAlternative(current); | ||
if (elementTextAlternative !== null) { | ||
consultedNodes.add(current); | ||
return elementTextAlternative; | ||
} | ||
// special casing, cheating to make tests pass | ||
// https://github.com/w3c/accname/issues/67 | ||
if (hasAnyConcreteRoles(current, ["menu"])) { | ||
consultedNodes.add(current); | ||
return ""; | ||
var attributeTextAlternative = computeAttributeTextAlternative(current); | ||
if (attributeTextAlternative !== null) { | ||
consultedNodes.add(current); | ||
return attributeTextAlternative; | ||
} | ||
// 2A | ||
if (isHidden(current, options) && !context.isReferenced) { | ||
consultedNodes.add(current); | ||
return ""; | ||
} | ||
} // 2E | ||
if (skipToStep2E || context.isEmbeddedInLabel || context.isReferenced) { | ||
if (hasAnyConcreteRoles(current, ["combobox", "listbox"])) { | ||
consultedNodes.add(current); | ||
var selectedOptions = querySelectedOptions(current); | ||
if (selectedOptions.length === 0) { | ||
// defined per test `name_heading_combobox` | ||
return (0, _util.isHTMLInputElement)(current) ? current.value : ""; | ||
} | ||
// 2B | ||
const labelElements = idRefs(current, "aria-labelledby"); | ||
if (!context.isReferenced && labelElements.length > 0) { | ||
return labelElements | ||
.map(element => computeTextAlternative(element, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: true, | ||
// thais isn't recursion as specified, otherwise we would skip | ||
// `aria-label` in | ||
// <input id="myself" aria-label="foo" aria-labelledby="myself" | ||
recursion: false | ||
})) | ||
.join(" "); | ||
return (0, _from.default)(selectedOptions).map(function (selectedOption) { | ||
return computeTextAlternative(selectedOption, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false, | ||
recursion: true | ||
}); | ||
}).join(" "); | ||
} | ||
if (hasAbstractRole(current, "range")) { | ||
consultedNodes.add(current); | ||
if (current.hasAttribute("aria-valuetext")) { | ||
// safe due to hasAttribute guard | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return current.getAttribute("aria-valuetext"); | ||
} | ||
// 2C | ||
// Changed from the spec in anticipation of https://github.com/w3c/accname/issues/64 | ||
// spec says we should only consider skipping if we have a non-empty label | ||
const skipToStep2E = context.recursion && isControl(current); | ||
if (!skipToStep2E) { | ||
const ariaLabel = ((util_1.isElement(current) && current.getAttribute("aria-label")) || | ||
"").trim(); | ||
if (ariaLabel !== "") { | ||
consultedNodes.add(current); | ||
return ariaLabel; | ||
} | ||
// 2D | ||
if (!isMarkedPresentational(current)) { | ||
const elementTextAlternative = computeElementTextAlternative(current); | ||
if (elementTextAlternative !== null) { | ||
consultedNodes.add(current); | ||
return elementTextAlternative; | ||
} | ||
const attributeTextAlternative = computeAttributeTextAlternative(current); | ||
if (attributeTextAlternative !== null) { | ||
consultedNodes.add(current); | ||
return attributeTextAlternative; | ||
} | ||
} | ||
} | ||
// 2E | ||
if (skipToStep2E || context.isEmbeddedInLabel || context.isReferenced) { | ||
if (hasAnyConcreteRoles(current, ["combobox", "listbox"])) { | ||
consultedNodes.add(current); | ||
const selectedOptions = querySelectedOptions(current); | ||
if (selectedOptions.length === 0) { | ||
// defined per test `name_heading_combobox` | ||
return util_1.isHTMLInputElement(current) ? current.value : ""; | ||
} | ||
return Array.from(selectedOptions) | ||
.map(selectedOption => { | ||
return computeTextAlternative(selectedOption, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false, | ||
recursion: true | ||
}); | ||
}) | ||
.join(" "); | ||
} | ||
if (hasAbstractRole(current, "range")) { | ||
consultedNodes.add(current); | ||
if (current.hasAttribute("aria-valuetext")) { | ||
// safe due to hasAttribute guard | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return current.getAttribute("aria-valuetext"); | ||
} | ||
if (current.hasAttribute("aria-valuenow")) { | ||
// safe due to hasAttribute guard | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return current.getAttribute("aria-valuenow"); | ||
} | ||
// Otherwise, use the value as specified by a host language attribute. | ||
return current.getAttribute("value") || ""; | ||
} | ||
if (hasAnyConcreteRoles(current, ["textbox"])) { | ||
consultedNodes.add(current); | ||
return getValueOfTextbox(current); | ||
} | ||
} | ||
// 2F: https://w3c.github.io/accname/#step2F | ||
if (allowsNameFromContent(current) || | ||
(util_1.isElement(current) && context.isReferenced) || | ||
isNativeHostLanguageTextAlternativeElement(current) || | ||
isDescendantOfNativeHostLanguageTextAlternativeElement(current)) { | ||
consultedNodes.add(current); | ||
return computeMiscTextAlternative(current, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false | ||
}); | ||
} | ||
if (current.nodeType === current.TEXT_NODE) { | ||
consultedNodes.add(current); | ||
return current.textContent || ""; | ||
} | ||
if (context.recursion) { | ||
consultedNodes.add(current); | ||
return computeMiscTextAlternative(current, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false | ||
}); | ||
} | ||
const tooltipAttributeValue = computeTooltipAttributeValue(current); | ||
if (tooltipAttributeValue !== null) { | ||
consultedNodes.add(current); | ||
return tooltipAttributeValue; | ||
} | ||
// TODO should this be reachable? | ||
if (current.hasAttribute("aria-valuenow")) { | ||
// safe due to hasAttribute guard | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
return current.getAttribute("aria-valuenow"); | ||
} // Otherwise, use the value as specified by a host language attribute. | ||
return current.getAttribute("value") || ""; | ||
} | ||
if (hasAnyConcreteRoles(current, ["textbox"])) { | ||
consultedNodes.add(current); | ||
return ""; | ||
return getValueOfTextbox(current); | ||
} | ||
} // 2F: https://w3c.github.io/accname/#step2F | ||
if (allowsNameFromContent(current) || (0, _util.isElement)(current) && context.isReferenced || isNativeHostLanguageTextAlternativeElement(current) || isDescendantOfNativeHostLanguageTextAlternativeElement(current)) { | ||
consultedNodes.add(current); | ||
return computeMiscTextAlternative(current, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false | ||
}); | ||
} | ||
return asFlatString(computeTextAlternative(root, { | ||
isEmbeddedInLabel: false, | ||
isReferenced: false, | ||
recursion: false | ||
})); | ||
if (current.nodeType === current.TEXT_NODE) { | ||
consultedNodes.add(current); | ||
return current.textContent || ""; | ||
} | ||
if (context.recursion) { | ||
consultedNodes.add(current); | ||
return computeMiscTextAlternative(current, { | ||
isEmbeddedInLabel: context.isEmbeddedInLabel, | ||
isReferenced: false | ||
}); | ||
} | ||
var tooltipAttributeValue = computeTooltipAttributeValue(current); | ||
if (tooltipAttributeValue !== null) { | ||
consultedNodes.add(current); | ||
return tooltipAttributeValue; | ||
} // TODO should this be reachable? | ||
consultedNodes.add(current); | ||
return ""; | ||
} | ||
return asFlatString(computeTextAlternative(root, { | ||
isEmbeddedInLabel: false, | ||
isReferenced: false, | ||
recursion: false | ||
})); | ||
} | ||
exports.computeAccessibleName = computeAccessibleName; | ||
//# sourceMappingURL=accessible-name.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = getRole; | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
// https://w3c.github.io/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function getRole(element) { | ||
const explicitRole = getExplicitRole(element); | ||
if (explicitRole !== null) { | ||
return explicitRole; | ||
} | ||
return getImplicitRole(element); | ||
var explicitRole = getExplicitRole(element); | ||
if (explicitRole !== null) { | ||
return explicitRole; | ||
} | ||
return getImplicitRole(element); | ||
} | ||
exports.default = getRole; | ||
const tagToRoleMappings = { | ||
ARTICLE: "article", | ||
ASIDE: "complementary", | ||
BODY: "document", | ||
BUTTON: "button", | ||
DATALIST: "listbox", | ||
DD: "definition", | ||
DETAILS: "group", | ||
DIALOG: "dialog", | ||
DT: "term", | ||
FIELDSET: "group", | ||
FIGURE: "figure", | ||
// WARNING: Only with an accessible name | ||
FORM: "form", | ||
FOOTER: "contentinfo", | ||
H1: "heading", | ||
H2: "heading", | ||
H3: "heading", | ||
H4: "heading", | ||
H5: "heading", | ||
H6: "heading", | ||
HEADER: "banner", | ||
HR: "separator", | ||
LEGEND: "legend", | ||
LI: "listitem", | ||
MATH: "math", | ||
MAIN: "main", | ||
MENU: "list", | ||
NAV: "navigation", | ||
OL: "list", | ||
OPTGROUP: "group", | ||
// WARNING: Only in certain context | ||
OPTION: "option", | ||
OUTPUT: "status", | ||
PROGRESS: "progressbar", | ||
// WARNING: Only with an accessible name | ||
SECTION: "region", | ||
SUMMARY: "button", | ||
TABLE: "table", | ||
TBODY: "rowgroup", | ||
TEXTAREA: "textbox", | ||
TFOOT: "rowgroup", | ||
// WARNING: Only in certain context | ||
TD: "cell", | ||
TH: "columnheader", | ||
THEAD: "rowgroup", | ||
TR: "row", | ||
UL: "list" | ||
var tagToRoleMappings = { | ||
ARTICLE: "article", | ||
ASIDE: "complementary", | ||
BODY: "document", | ||
BUTTON: "button", | ||
DATALIST: "listbox", | ||
DD: "definition", | ||
DETAILS: "group", | ||
DIALOG: "dialog", | ||
DT: "term", | ||
FIELDSET: "group", | ||
FIGURE: "figure", | ||
// WARNING: Only with an accessible name | ||
FORM: "form", | ||
FOOTER: "contentinfo", | ||
H1: "heading", | ||
H2: "heading", | ||
H3: "heading", | ||
H4: "heading", | ||
H5: "heading", | ||
H6: "heading", | ||
HEADER: "banner", | ||
HR: "separator", | ||
LEGEND: "legend", | ||
LI: "listitem", | ||
MATH: "math", | ||
MAIN: "main", | ||
MENU: "list", | ||
NAV: "navigation", | ||
OL: "list", | ||
OPTGROUP: "group", | ||
// WARNING: Only in certain context | ||
OPTION: "option", | ||
OUTPUT: "status", | ||
PROGRESS: "progressbar", | ||
// WARNING: Only with an accessible name | ||
SECTION: "region", | ||
SUMMARY: "button", | ||
TABLE: "table", | ||
TBODY: "rowgroup", | ||
TEXTAREA: "textbox", | ||
TFOOT: "rowgroup", | ||
// WARNING: Only in certain context | ||
TD: "cell", | ||
TH: "columnheader", | ||
THEAD: "rowgroup", | ||
TR: "row", | ||
UL: "list" | ||
}; | ||
function getImplicitRole(element) { | ||
const mappedByTag = tagToRoleMappings[element.tagName]; | ||
if (mappedByTag !== undefined) { | ||
return mappedByTag; | ||
} | ||
switch (element.tagName) { | ||
case "A": | ||
case "AREA": | ||
case "LINK": | ||
if (element.hasAttribute("href")) { | ||
return "link"; | ||
var mappedByTag = tagToRoleMappings[element.tagName]; | ||
if (mappedByTag !== undefined) { | ||
return mappedByTag; | ||
} | ||
switch (element.tagName) { | ||
case "A": | ||
case "AREA": | ||
case "LINK": | ||
if (element.hasAttribute("href")) { | ||
return "link"; | ||
} | ||
break; | ||
case "IMG": | ||
if ((element.getAttribute("alt") || "").length > 0) { | ||
return "img"; | ||
} | ||
break; | ||
case "INPUT": | ||
{ | ||
var _ref = element, | ||
type = _ref.type; | ||
switch (type) { | ||
case "button": | ||
case "image": | ||
case "reset": | ||
case "submit": | ||
return "button"; | ||
case "checkbox": | ||
case "radio": | ||
return type; | ||
case "range": | ||
return "slider"; | ||
case "email": | ||
case "tel": | ||
case "text": | ||
case "url": | ||
if (element.hasAttribute("list")) { | ||
return "combobox"; | ||
} | ||
break; | ||
case "IMG": | ||
if ((element.getAttribute("alt") || "").length > 0) { | ||
return "img"; | ||
return "textbox"; | ||
case "search": | ||
if (element.hasAttribute("list")) { | ||
return "combobox"; | ||
} | ||
break; | ||
case "INPUT": { | ||
const { type } = element; | ||
switch (type) { | ||
case "button": | ||
case "image": | ||
case "reset": | ||
case "submit": | ||
return "button"; | ||
case "checkbox": | ||
case "radio": | ||
return type; | ||
case "range": | ||
return "slider"; | ||
case "email": | ||
case "tel": | ||
case "text": | ||
case "url": | ||
if (element.hasAttribute("list")) { | ||
return "combobox"; | ||
} | ||
return "textbox"; | ||
case "search": | ||
if (element.hasAttribute("list")) { | ||
return "combobox"; | ||
} | ||
return "searchbox"; | ||
default: | ||
return null; | ||
} | ||
return "searchbox"; | ||
default: | ||
return null; | ||
} | ||
case "SELECT": | ||
if (element.hasAttribute("multiple") || | ||
element.size > 1) { | ||
return "listbox"; | ||
} | ||
return "combobox"; | ||
} | ||
return null; | ||
} | ||
case "SELECT": | ||
if (element.hasAttribute("multiple") || element.size > 1) { | ||
return "listbox"; | ||
} | ||
return "combobox"; | ||
} | ||
return null; | ||
} | ||
function getExplicitRole(element) { | ||
if (element.hasAttribute("role")) { | ||
// safe due to hasAttribute check | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const [explicitRole] = element | ||
.getAttribute("role") | ||
.trim() | ||
.split(" "); | ||
if (explicitRole !== undefined && explicitRole.length > 0) { | ||
return explicitRole; | ||
} | ||
if (element.hasAttribute("role")) { | ||
// safe due to hasAttribute check | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
var _trim$split = element.getAttribute("role").trim().split(" "), | ||
_trim$split2 = _slicedToArray(_trim$split, 1), | ||
explicitRole = _trim$split2[0]; | ||
if (explicitRole !== undefined && explicitRole.length > 0) { | ||
return explicitRole; | ||
} | ||
return null; | ||
} | ||
return null; | ||
} | ||
//# sourceMappingURL=getRole.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var accessible_name_1 = require("./accessible-name"); | ||
exports.computeAccessibleName = accessible_name_1.computeAccessibleName; | ||
var getRole_1 = require("./getRole"); | ||
exports.getRole = getRole_1.default; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
Object.defineProperty(exports, "computeAccessibleName", { | ||
enumerable: true, | ||
get: function get() { | ||
return _accessibleName.computeAccessibleName; | ||
} | ||
}); | ||
Object.defineProperty(exports, "getRole", { | ||
enumerable: true, | ||
get: function get() { | ||
return _getRole.default; | ||
} | ||
}); | ||
var _accessibleName = require("./accessible-name"); | ||
var _getRole = _interopRequireDefault(require("./getRole")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.isElement = isElement; | ||
exports.isHTMLInputElement = isHTMLInputElement; | ||
exports.isHTMLSelectElement = isHTMLSelectElement; | ||
exports.isHTMLTextAreaElement = isHTMLTextAreaElement; | ||
exports.safeWindow = safeWindow; | ||
function isElement(node) { | ||
return ( | ||
// @ts-ignore | ||
node !== null && node instanceof node.ownerDocument.defaultView.Element); | ||
return (// @ts-ignore | ||
node !== null && node instanceof node.ownerDocument.defaultView.Element | ||
); | ||
} | ||
exports.isElement = isElement; | ||
function isHTMLInputElement(node) { | ||
return (isElement(node) && | ||
// @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLInputElement); | ||
return isElement(node) && // @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLInputElement; | ||
} | ||
exports.isHTMLInputElement = isHTMLInputElement; | ||
function isHTMLSelectElement(node) { | ||
return (isElement(node) && | ||
// @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLSelectElement); | ||
return isElement(node) && // @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLSelectElement; | ||
} | ||
exports.isHTMLSelectElement = isHTMLSelectElement; | ||
function isHTMLTextAreaElement(node) { | ||
return (isElement(node) && | ||
// @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLTextAreaElement); | ||
return isElement(node) && // @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLTextAreaElement; | ||
} | ||
exports.isHTMLTextAreaElement = isHTMLTextAreaElement; | ||
function safeWindow(node) { | ||
const { defaultView } = node.ownerDocument === null ? node : node.ownerDocument; | ||
if (defaultView === null) { | ||
throw new TypeError("no window available"); | ||
} | ||
return defaultView; | ||
var _ref = node.ownerDocument === null ? node : node.ownerDocument, | ||
defaultView = _ref.defaultView; | ||
if (defaultView === null) { | ||
throw new TypeError("no window available"); | ||
} | ||
return defaultView; | ||
} | ||
exports.safeWindow = safeWindow; | ||
//# sourceMappingURL=util.js.map |
{ | ||
"name": "dom-accessibility-api", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"main": "dist/index.js", | ||
@@ -11,7 +11,14 @@ "types": "dist/index.d.ts", | ||
}, | ||
"dependencies": { | ||
"core-js-pure": "^3.6.4" | ||
}, | ||
"files": [ | ||
".browserslistrc", | ||
"dist/" | ||
], | ||
"scripts": { | ||
"build": "tsc -p tsconfig.json", | ||
"build": "yarn build:clean && yarn build:source && yarn build:types", | ||
"build:clean": "rimraf dist", | ||
"build:source": "babel sources --extensions \".ts\" --ignore \"**/__tests__/**/*\" --out-dir dist/ --source-maps", | ||
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly", | ||
"format": "prettier \"**/*.{json,js,md,ts,yml}\" --write --ignore-path .prettierignore", | ||
@@ -23,2 +30,3 @@ "lint": "eslint --report-unused-disable-directives \"sources/**/*.ts\"", | ||
"test:ci": "jest --ci --config jest.ci.config.js --runInBand", | ||
"test:types": "tsc -p tsconfig.json --noEmit", | ||
"test:wpt:jsdom": "mocha tests/wpt-jsdom/run-wpts.js", | ||
@@ -34,12 +42,14 @@ "test:wpt:browser": "concurrently --success first --kill-others \"yarn test:wpt:browser:run\" \"yarn test:wpt:browser:server\"", | ||
"devDependencies": { | ||
"@babel/core": "^7.8.3", | ||
"@babel/preset-env": "^7.8.3", | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.8.7", | ||
"@babel/preset-env": "^7.8.7", | ||
"@babel/preset-typescript": "^7.8.3", | ||
"@changesets/cli": "^2.5.0", | ||
"@testing-library/dom": "^6.11.0", | ||
"@types/jest": "^24.9.1", | ||
"@typescript-eslint/parser": "^2.17.0", | ||
"@typescript-eslint/eslint-plugin": "^2.17.0", | ||
"concurrently": "^5.0.2", | ||
"cypress": "^3.8.3", | ||
"@changesets/changelog-github": "^0.2.2", | ||
"@changesets/cli": "^2.5.2", | ||
"@testing-library/dom": "^6.15.0", | ||
"@types/jest": "^25.1.4", | ||
"@typescript-eslint/eslint-plugin": "^2.22.0", | ||
"@typescript-eslint/parser": "^2.22.0", | ||
"concurrently": "^5.1.0", | ||
"cypress": "^4.1.0", | ||
"eslint": "^6.8.0", | ||
@@ -51,13 +61,17 @@ "jest": "^25.1.0", | ||
"js-yaml": "^3.13.1", | ||
"jsdom": "^16.0.1", | ||
"jsdom": "^16.2.0", | ||
"minimatch": "^3.0.4", | ||
"mocha": "^7.0.1", | ||
"mocha": "^7.1.0", | ||
"mocha-sugar-free": "^1.4.0", | ||
"prettier": "^1.19.1", | ||
"q": "^1.5.1", | ||
"request": "^2.34", | ||
"request": "^2.88", | ||
"request-promise-native": "^1.0.8", | ||
"rimraf": "^3.0.2", | ||
"serve": "^11.3.0", | ||
"typescript": "^3.7.5" | ||
"typescript": "^3.8.3" | ||
}, | ||
"resolutions": { | ||
"**/minimist": "^1.2.2" | ||
}, | ||
"prettier": { | ||
@@ -64,0 +78,0 @@ "useTabs": true |
@@ -21,2 +21,15 @@ # dom-accessibility-api | ||
## Supported environments | ||
```bash | ||
ie 11 | ||
edge >= 14 | ||
firefox >= 52 | ||
chrome >= 49 | ||
safari >= 10 | ||
node 10.0 | ||
``` | ||
or check the published `.browserslistrc` | ||
## progress | ||
@@ -23,0 +36,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
76413
22
217
1
29
600
+ Addedcore-js-pure@^3.6.4
+ Addedcore-js-pure@3.38.1(transitive)