dom-accessibility-api
Advanced tools
Comparing version 0.0.1 to 0.1.0
/** | ||
* implements https://w3c.github.io/accname/ | ||
*/ | ||
/** | ||
* implements https://w3c.github.io/accname/#mapping_additional_nd_te | ||
@@ -3,0 +6,0 @@ * @param root |
"use strict"; | ||
/** | ||
* 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")); | ||
/** | ||
@@ -11,17 +18,2 @@ * | ||
} | ||
function isEmpty(s) { | ||
return s == null || s.length === 0; | ||
} | ||
function appendResultWithoutSpace(result, x) { | ||
return `${x}${result}`; | ||
} | ||
function appendResultWithSpace(result, x) { | ||
return `${x} ${result}`; | ||
} | ||
function prependResultWithoutSpace(result, x = "") { | ||
return `${result}${x}`; | ||
} | ||
function prepenResultWithSpace(result, x = "") { | ||
return `${result} ${x}`; | ||
} | ||
/** | ||
@@ -48,7 +40,13 @@ * TODO | ||
} | ||
function isHTMLTextAreaElement(node) { | ||
return (isElement(node) && | ||
// @ts-ignore | ||
node instanceof node.ownerDocument.defaultView.HTMLTextAreaElement); | ||
} | ||
function safeWindow(node) { | ||
if (node.isConnected === false) { | ||
throw new TypeError(`Can't reach window from disconnected node`); | ||
const { defaultView } = node.ownerDocument === null ? node : node.ownerDocument; | ||
if (defaultView === null) { | ||
throw new TypeError("no window available"); | ||
} | ||
return node.ownerDocument.defaultView; | ||
return defaultView; | ||
} | ||
@@ -98,8 +96,8 @@ /** | ||
/** | ||
* | ||
* @param {Node} node - | ||
* @returns {boolean} - | ||
* @returns {boolean} - As defined in step 2E of https://w3c.github.io/accname/#mapping_additional_nd_te | ||
*/ | ||
function isEmbeddedControl(node) { | ||
return false; | ||
function isControl(node) { | ||
return (hasAnyConcreteRoles(node, ["button", "combobox", "listbox", "textbox"]) || | ||
hasAbstractRole(node, "range")); | ||
} | ||
@@ -119,6 +117,2 @@ function hasAbstractRole(node, role) { | ||
]); | ||
case "textbox": | ||
return (node.tagName === "TEXTAREA" || | ||
(isHTMLInputElement(node) && | ||
["search", "text"].indexOf(node.type) !== -1)); | ||
default: | ||
@@ -130,26 +124,3 @@ throw new TypeError(`No knowledge about abstract role '${role}'. This is likely a bug :(`); | ||
if (isElement(node)) { | ||
if (node.hasAttribute("role")) { | ||
return node | ||
.getAttribute("role") | ||
.split(" ") | ||
.some(role => roles.indexOf(role) !== -1); | ||
} | ||
// https://w3c.github.io/html-aria/ | ||
switch (node.tagName) { | ||
case "A": | ||
return roles.indexOf("link") !== -1; | ||
case "BUTTON": | ||
return roles.indexOf("button") !== -1; | ||
case "H1": | ||
case "H2": | ||
case "H3": | ||
case "H4": | ||
case "H5": | ||
case "H6": | ||
return roles.indexOf("heading") !== -1; | ||
case "SELECT": | ||
return roles.indexOf("listbox") !== -1; | ||
case "OPTION": | ||
return roles.indexOf("option") !== -1; | ||
} | ||
return roles.indexOf(getRole_1.default(node)) !== -1; | ||
} | ||
@@ -187,6 +158,27 @@ return false; | ||
/** | ||
* TODO https://w3c.github.io/aria/#namefromcontent | ||
* https://w3c.github.io/aria/#namefromcontent | ||
*/ | ||
function allowsNameFromContent(node) { | ||
return hasAnyConcreteRoles(node, ["option", "heading", "link", "button"]); | ||
return hasAnyConcreteRoles(node, [ | ||
"button", | ||
"cell", | ||
"checkbox", | ||
"columnheader", | ||
"gridcell", | ||
"heading", | ||
"label", | ||
"legend", | ||
"link", | ||
"menuitem", | ||
"menuitemcheckbox", | ||
"menuitemradio", | ||
"option", | ||
"radio", | ||
"row", | ||
"rowheader", | ||
"switch", | ||
"tab", | ||
"tooltip", | ||
"treeitem" | ||
]); | ||
} | ||
@@ -205,2 +197,16 @@ /** | ||
} | ||
function getValueOfTextbox(element) { | ||
if (isHTMLInputElement(element) || 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 ""; | ||
} | ||
/** | ||
@@ -227,5 +233,5 @@ * implements https://w3c.github.io/accname/#mapping_additional_nd_te | ||
if (isElement(node)) { | ||
const pseudoBefore = safeWindow(node).getComputedStyle(node, ":before"); | ||
const beforeContent = pseudoBefore.getPropertyValue("content"); | ||
accumulatedText = prependResultWithoutSpace(accumulatedText, beforeContent); | ||
const pseudoBefore = safeWindow(node).getComputedStyle(node, "::before"); | ||
const beforeContent = getTextualContent(pseudoBefore); | ||
accumulatedText = `${beforeContent} ${accumulatedText}`; | ||
} | ||
@@ -248,4 +254,4 @@ for (const child of queryChildNodes(node)) { | ||
const pseudoAfter = safeWindow(node).getComputedStyle(node, ":after"); | ||
const afterContent = pseudoAfter.getPropertyValue("content"); | ||
accumulatedText = appendResultWithoutSpace(accumulatedText, afterContent); | ||
const afterContent = getTextualContent(pseudoAfter); | ||
accumulatedText = `${accumulatedText} ${afterContent}`; | ||
} | ||
@@ -329,3 +335,6 @@ return accumulatedText; | ||
isReferenced: true, | ||
recursion: 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 | ||
})) | ||
@@ -335,26 +344,26 @@ .join(" "); | ||
// 2C | ||
const ariaLabel = ((isElement(current) && current.getAttribute("aria-label")) || | ||
"").trim(); | ||
if (ariaLabel !== "") { | ||
consultedNodes.add(current); | ||
if (context.recursion && isEmbeddedControl(current)) { | ||
throw new Error("Not implemented"); | ||
} | ||
return ariaLabel; | ||
} | ||
// 2D | ||
if (!hasAnyConcreteRoles(current, ["none", "presentation"])) { | ||
const attributeTextAlternative = computeAttributeTextAlternative(current); | ||
if (attributeTextAlternative !== null) { | ||
const skipToStep2E = context.recursion && isControl(current); | ||
if (!skipToStep2E) { | ||
const ariaLabel = ((isElement(current) && current.getAttribute("aria-label")) || | ||
"").trim(); | ||
if (ariaLabel !== "") { | ||
consultedNodes.add(current); | ||
return attributeTextAlternative; | ||
return ariaLabel; | ||
} | ||
const elementTextAlternative = computeElementTextAlternative(current); | ||
if (elementTextAlternative !== null) { | ||
consultedNodes.add(current); | ||
return elementTextAlternative; | ||
// 2D | ||
if (!hasAnyConcreteRoles(current, ["none", "presentation"])) { | ||
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 (context.isReferenced || context.isEmbeddedInLabel) { | ||
if (skipToStep2E || context.isEmbeddedInLabel || context.isReferenced) { | ||
if (hasAnyConcreteRoles(current, ["combobox", "listbox"])) { | ||
@@ -364,3 +373,4 @@ consultedNodes.add(current); | ||
if (selectedOptions.length === 0) { | ||
return ""; | ||
// defined per test `name_heading_combobox` | ||
return isHTMLInputElement(current) ? current.value : ""; | ||
} | ||
@@ -388,5 +398,5 @@ return Array.from(selectedOptions) | ||
} | ||
if (hasAbstractRole(current, "textbox")) { | ||
if (hasAnyConcreteRoles(current, ["textbox"])) { | ||
consultedNodes.add(current); | ||
return current.getAttribute("value") || ""; | ||
return getValueOfTextbox(current); | ||
} | ||
@@ -393,0 +403,0 @@ } |
export { computeAccessibleName } from "./accessible-name"; | ||
export { default as getRole } from "./getRole"; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -5,2 +5,4 @@ "use strict"; | ||
exports.computeAccessibleName = accessible_name_1.computeAccessibleName; | ||
var getRole_1 = require("./getRole"); | ||
exports.getRole = getRole_1.default; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "dom-accessibility-api", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"main": "dist/index.js", | ||
@@ -12,8 +12,14 @@ "types": "dist/index.d.ts", | ||
"build": "tsc -p tsconfig.json", | ||
"format": "prettier \"**/*.{json,js,md,ts}\" --write --ignore-path .prettierignore", | ||
"format": "prettier \"**/*.{json,js,md,ts,yml}\" --write --ignore-path .prettierignore", | ||
"lint": "eslint --report-unused-disable-directives \"sources/**/*.ts\"", | ||
"test": "jest", | ||
"test-wpt": "mocha tests/run-wpts.js", | ||
"init-wpt": "git submodule update --init --recursive", | ||
"reset-wpt": "rimraf ./tests/wpt && yarn init-wpt", | ||
"update-wpt": "git submodule update --recursive --remote && cd tests/wpt && python wpt.py manifest --path ../wpt-manifest.json" | ||
"test:ci": "jest --ci --config jest.ci.config.js --runInBand", | ||
"test:wpt:jsdom": "mocha tests/wpt-jsdom/run-wpts.js", | ||
"test:wpt:browser": "concurrently --success first --kill-others \"yarn test:wpt:browser:run\" \"yarn test:wpt:browser:server\"", | ||
"test:wpt:browser:run": "cypress run --project tests", | ||
"test:wpt:browser:server": "serve tests/wpt", | ||
"test:wpt:browser:open": "cypress open --project tests", | ||
"wpt:init": "git submodule update --init --recursive", | ||
"wpt:reset": "rimraf ./tests/wpt && yarn init-wpt", | ||
"wpt:update": "git submodule update --recursive --remote && cd tests/wpt && python wpt.py manifest --path ../wpt-jsdom/wpt-manifest.json" | ||
}, | ||
@@ -24,7 +30,17 @@ "devDependencies": { | ||
"@babel/preset-typescript": "^7.6.0", | ||
"@semantic-release/changelog": "^3.0.5", | ||
"@semantic-release/commit-analyzer": "^6.3.2", | ||
"@semantic-release/git": "^7.0.18", | ||
"@semantic-release/npm": "^5.3.4", | ||
"@semantic-release/release-notes-generator": "^7.3.2", | ||
"@testing-library/dom": "^6.6.0", | ||
"@types/jest": "^24.0.18", | ||
"@typescript-eslint/eslint-plugin": "^2.5.0", | ||
"concurrently": "^5.0.0", | ||
"cypress": "^3.4.1", | ||
"eslint": "^6.6.0", | ||
"jest": "^24.9.0", | ||
"jest-diff": "^24.9.0", | ||
"jest-environment-jsdom-thirteen": "^1.0.1", | ||
"jest-junit": "^8.0.0", | ||
"js-yaml": "^3.13.1", | ||
@@ -39,2 +55,4 @@ "jsdom": "^15.1.1", | ||
"request-promise-native": "^1.0.7", | ||
"semantic-release": "^15.13.30", | ||
"serve": "^11.2.0", | ||
"typescript": "^3.6.3" | ||
@@ -44,3 +62,10 @@ }, | ||
"useTabs": true | ||
}, | ||
"dependencies": { | ||
"@typescript-eslint/parser": "^2.5.0" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/eps1lon/dom-accessibility-api.git" | ||
} | ||
} |
# dom-accessibility-api | ||
https://w3c.github.io/accname/ for jsdom | ||
[![npm version](https://badge.fury.io/js/dom-accessibility-api.svg)](https://badge.fury.io/js/dom-accessibility-api) | ||
[![Build Status](https://dev.azure.com/silbermannsebastian/dom-accessibility-api/_apis/build/status/eps1lon.dom-accessibility-api?branchName=master)](https://dev.azure.com/silbermannsebastian/dom-accessibility-api/_build/latest?definitionId=6&branchName=master) | ||
![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/silbermannsebastian/dom-accessibility-api/6) | ||
Computes the accessible name of a given DOM Element. | ||
https://w3c.github.io/accname/ implemented in JavaScript for testing. | ||
```bash | ||
@@ -13,18 +18,21 @@ $ yarn add dom-accessibility-api | ||
I wrote this down in 12 hours to get a quick overview | ||
how complex a full implementation would be. | ||
I'm not an editor of any of the referenced specs (nor very experience with using them) so if you got any insights, something catches | ||
your eye please open an issue. | ||
I'm very new to working with specs so if you got any insights, something catches | ||
your eye feel free to let me know. DMs are open. | ||
## progress | ||
Using https://github.com/web-platform-tests/wpt. Be sure to init submodules when | ||
cloning. | ||
cloning. See [the test readme](/tests/README.md) for more info about the test setup. | ||
### browser (Chrome) | ||
136/144 of which 5 are due to missing whitespace. | ||
### jsdom | ||
<details> | ||
<summary>report 124/159 passing of which 16 are due to jsdom, 14 are accessible desc, 9 are pathological </summary> | ||
<summary>report 126/159 passing of which 16 are due `::before { content }`, 14 are accessible desc, 7 are pathological </summary> | ||
```bash | ||
web-platform-tests | ||
web-platform-tests | ||
accname | ||
@@ -72,3 +80,3 @@ ✓ [expected fail] description_1.0_combobox-focusable-manual.html | ||
✓ name_from_content_of_labelledby_elements_one_of_which_is_hidden-manual.html | ||
✓ [expected fail] name_heading-combobox-focusable-alternative-manual.html | ||
✓ name_heading-combobox-focusable-alternative-manual.html | ||
✓ name_image-title-manual.html | ||
@@ -128,3 +136,3 @@ ✓ name_link-mixed-content-manual.html | ||
✓ name_test_case_609-manual.html | ||
✓ [expected fail] name_test_case_610-manual.html | ||
✓ name_test_case_610-manual.html | ||
✓ name_test_case_611-manual.html | ||
@@ -131,0 +139,0 @@ ✓ name_test_case_612-manual.html |
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
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
46030
15
574
204
0
1
30
+ Added@babel/code-frame@7.24.7(transitive)
+ Added@babel/helper-validator-identifier@7.24.7(transitive)
+ Added@babel/highlight@7.24.7(transitive)
+ Added@types/eslint-visitor-keys@1.0.0(transitive)
+ Added@types/json-schema@7.0.15(transitive)
+ Added@typescript-eslint/experimental-utils@2.34.0(transitive)
+ Added@typescript-eslint/parser@2.34.0(transitive)
+ Added@typescript-eslint/typescript-estree@2.34.0(transitive)
+ Addedacorn@7.4.1(transitive)
+ Addedacorn-jsx@5.3.2(transitive)
+ Addedajv@6.12.6(transitive)
+ Addedansi-escapes@4.3.2(transitive)
+ Addedansi-regex@4.1.15.0.1(transitive)
+ Addedansi-styles@3.2.14.3.0(transitive)
+ Addedargparse@1.0.10(transitive)
+ Addedastral-regex@1.0.0(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedcallsites@3.1.0(transitive)
+ Addedchalk@2.4.24.1.2(transitive)
+ Addedchardet@0.7.0(transitive)
+ Addedcli-cursor@3.1.0(transitive)
+ Addedcli-width@3.0.0(transitive)
+ Addedcolor-convert@1.9.32.0.1(transitive)
+ Addedcolor-name@1.1.31.1.4(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedcross-spawn@6.0.5(transitive)
+ Addeddebug@4.3.5(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addeddoctrine@3.0.0(transitive)
+ Addedemoji-regex@7.0.38.0.0(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedeslint@6.8.0(transitive)
+ Addedeslint-scope@5.1.1(transitive)
+ Addedeslint-utils@1.4.32.1.0(transitive)
+ Addedeslint-visitor-keys@1.3.0(transitive)
+ Addedespree@6.2.1(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedesquery@1.6.0(transitive)
+ Addedesrecurse@4.3.0(transitive)
+ Addedestraverse@4.3.05.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedexternal-editor@3.1.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfigures@3.2.0(transitive)
+ Addedfile-entry-cache@5.0.1(transitive)
+ Addedflat-cache@2.0.1(transitive)
+ Addedflatted@2.0.2(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfunctional-red-black-tree@1.0.1(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedglob-parent@5.1.2(transitive)
+ Addedglobals@12.4.0(transitive)
+ Addedhas-flag@3.0.04.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedignore@4.0.6(transitive)
+ Addedimport-fresh@3.3.0(transitive)
+ Addedimurmurhash@0.1.4(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedinquirer@7.3.3(transitive)
+ Addedis-extglob@2.1.1(transitive)
+ Addedis-fullwidth-code-point@2.0.03.0.0(transitive)
+ Addedis-glob@4.0.3(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stable-stringify-without-jsonify@1.0.1(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedms@2.1.2(transitive)
+ Addedmute-stream@0.0.8(transitive)
+ Addednatural-compare@1.4.0(transitive)
+ Addednice-try@1.0.5(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedonetime@5.1.2(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedos-tmpdir@1.0.2(transitive)
+ Addedparent-module@1.0.1(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpath-key@2.0.1(transitive)
+ Addedpicocolors@1.0.1(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedprogress@2.0.3(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedregexpp@2.0.1(transitive)
+ Addedresolve-from@4.0.0(transitive)
+ Addedrestore-cursor@3.1.0(transitive)
+ Addedrimraf@2.6.3(transitive)
+ Addedrun-async@2.4.1(transitive)
+ Addedrxjs@6.6.7(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsemver@5.7.26.3.17.6.2(transitive)
+ Addedshebang-command@1.2.0(transitive)
+ Addedshebang-regex@1.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedslice-ansi@2.1.0(transitive)
+ Addedsprintf-js@1.0.3(transitive)
+ Addedstring-width@3.1.04.2.3(transitive)
+ Addedstrip-ansi@5.2.06.0.1(transitive)
+ Addedstrip-json-comments@3.1.1(transitive)
+ Addedsupports-color@5.5.07.2.0(transitive)
+ Addedtable@5.4.6(transitive)
+ Addedtext-table@0.2.0(transitive)
+ Addedthrough@2.3.8(transitive)
+ Addedtmp@0.0.33(transitive)
+ Addedtslib@1.14.1(transitive)
+ Addedtsutils@3.21.0(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addedtype-fest@0.21.30.8.1(transitive)
+ Addedtypescript@5.5.3(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedv8-compile-cache@2.4.0(transitive)
+ Addedwhich@1.3.1(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedwrite@1.0.3(transitive)