🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

dom-accessibility-api

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dom-accessibility-api - npm Package Compare versions

Comparing version

to
0.2.0

dist/util.d.ts

22

CHANGELOG.md
# [0.1.0](https://github.com/eps1lon/dom-accessibility-api/compare/v0.0.1...v0.1.0) (2019-11-05)
## 0.2.0
### Minor Changes
- eb86842: Add option to mock window.getComputedStyle
This option has two use cases in mind:
1. fake the style and assume everything is visible.
This increases performance (window.getComputedStyle) is expensive) by not distinguishing between various levels of visual impairments. If one can't see the name with a screen reader then neither will a sighted user
2. Wrap a cache provider around `window.getComputedStyle`. We don't implement any because the returned `CSSStyleDeclaration` is only live in a browser. `jsdom` does not implement live declarations.
### Bug Fixes
* Fix test name_heading-combobox ([#16](https://github.com/eps1lon/dom-accessibility-api/issues/16)) ([e969395](https://github.com/eps1lon/dom-accessibility-api/commit/e969395d8da637862993aeee0b86f379342d56f2))
- Fix test name_heading-combobox ([#16](https://github.com/eps1lon/dom-accessibility-api/issues/16)) ([e969395](https://github.com/eps1lon/dom-accessibility-api/commit/e969395d8da637862993aeee0b86f379342d56f2))
### Features
* **name:** Consider prohibited naming ([#19](https://github.com/eps1lon/dom-accessibility-api/issues/19)) ([6692d6b](https://github.com/eps1lon/dom-accessibility-api/commit/6692d6bd86030da9b340b0895f623394b21e2656))
* Consider all cases of "name from content" ([#13](https://github.com/eps1lon/dom-accessibility-api/issues/13)) ([835cb76](https://github.com/eps1lon/dom-accessibility-api/commit/835cb76e7c1dd577af1fa891ad849385e58fcd56))
* Consider content from before and after pseudo elements ([#5](https://github.com/eps1lon/dom-accessibility-api/issues/5)) ([0987426](https://github.com/eps1lon/dom-accessibility-api/commit/0987426734cc7b980a8edf39435820a24ea2a162))
* Fork elementToRole from aria-query ([#7](https://github.com/eps1lon/dom-accessibility-api/issues/7)) ([fe4fab5](https://github.com/eps1lon/dom-accessibility-api/commit/fe4fab57786324705c4ac4434de8aabd3e7bbc09))
- **name:** Consider prohibited naming ([#19](https://github.com/eps1lon/dom-accessibility-api/issues/19)) ([6692d6b](https://github.com/eps1lon/dom-accessibility-api/commit/6692d6bd86030da9b340b0895f623394b21e2656))
- Consider all cases of "name from content" ([#13](https://github.com/eps1lon/dom-accessibility-api/issues/13)) ([835cb76](https://github.com/eps1lon/dom-accessibility-api/commit/835cb76e7c1dd577af1fa891ad849385e58fcd56))
- Consider content from before and after pseudo elements ([#5](https://github.com/eps1lon/dom-accessibility-api/issues/5)) ([0987426](https://github.com/eps1lon/dom-accessibility-api/commit/0987426734cc7b980a8edf39435820a24ea2a162))
- Fork elementToRole from aria-query ([#7](https://github.com/eps1lon/dom-accessibility-api/issues/7)) ([fe4fab5](https://github.com/eps1lon/dom-accessibility-api/commit/fe4fab57786324705c4ac4434de8aabd3e7bbc09))

@@ -5,9 +5,15 @@ /**

/**
* interface for an options-bag where `window.getComputedStyle` can be mocked
*/
interface GetComputedStyleOptions {
getComputedStyle?: typeof window.getComputedStyle;
}
/**
* implements https://w3c.github.io/accname/#mapping_additional_nd_te
* @param root
* @param context
* @param [options]
* @parma [options.getComputedStyle] - mock window.getComputedStyle. Needs `content`, `display` and `visibility`
*/
export declare function computeAccessibleName(root: Element, context?: {
isReferenced?: boolean;
}): string;
export declare function computeAccessibleName(root: Element, options?: GetComputedStyleOptions): string;
export {};
//# sourceMappingURL=accessible-name.d.ts.map

@@ -10,3 +10,19 @@ "use strict";

const getRole_1 = __importDefault(require("./getRole"));
const util_1 = require("./util");
/**
* Small utility that handles all the JS quirks with `this` which is important
* if no mock is provided.
* @param element
* @param options - These are not optional to prevent accidentally calling it without options in `computeAccessibleName`
*/
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;
}
/**
*

@@ -20,41 +36,27 @@ * @param {string} string -

/**
* TODO
* https://w3c.github.io/aria/#namefromprohibited
*/
function prohibitsNaming(node) {
return false;
return hasAnyConcreteRoles(node, [
"caption",
"code",
"deletion",
"emphasis",
"generic",
"insertion",
"paragraph",
"presentation",
"strong",
"subscript",
"superscript"
]);
}
function isElement(node) {
return (
// @ts-ignore
node !== null && node instanceof node.ownerDocument.defaultView.Element);
}
function isHTMLInputElement(node) {
return (isElement(node) &&
// @ts-ignore
node instanceof node.ownerDocument.defaultView.HTMLInputElement);
}
function isHTMLSelectElement(node) {
return (isElement(node) &&
// @ts-ignore
node instanceof node.ownerDocument.defaultView.HTMLSelectElement);
}
function isHTMLTextAreaElement(node) {
return (isElement(node) &&
// @ts-ignore
node instanceof node.ownerDocument.defaultView.HTMLTextAreaElement);
}
function safeWindow(node) {
const { defaultView } = node.ownerDocument === null ? node : node.ownerDocument;
if (defaultView === null) {
throw new TypeError("no window available");
}
return defaultView;
}
/**
*
* @param {Node} node -
* @param node -
* @param options - These are not optional to prevent accidentally calling it without options in `computeAccessibleName`
* @returns {boolean} -
*/
function isHidden(node) {
if (!isElement(node)) {
function isHidden(node, options) {
if (!util_1.isElement(node)) {
return false;

@@ -66,3 +68,3 @@ }

}
const style = safeWindow(node).getComputedStyle(node);
const style = createGetComputedStyle(node, options)(node);
return (style.getPropertyValue("display") === "none" ||

@@ -78,5 +80,9 @@ style.getPropertyValue("visibility") === "hidden");

function idRefs(node, attributeName) {
if (isElement(node) && node.hasAttribute(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))

@@ -106,3 +112,3 @@ .filter((element) => element !== null

function hasAbstractRole(node, role) {
if (!isElement(node)) {
if (!util_1.isElement(node)) {
return false;

@@ -124,3 +130,3 @@ }

function hasAnyConcreteRoles(node, roles) {
if (isElement(node)) {
if (util_1.isElement(node)) {
return roles.indexOf(getRole_1.default(node)) !== -1;

@@ -143,3 +149,3 @@ }

function querySelectedOptions(listbox) {
if (isHTMLSelectElement(listbox)) {
if (util_1.isHTMLSelectElement(listbox)) {
// IE11 polyfill

@@ -199,3 +205,3 @@ return (listbox.selectedOptions || querySelectorAllSubtree(listbox, "[selected]"));

function getValueOfTextbox(element) {
if (isHTMLInputElement(element) || isHTMLTextAreaElement(element)) {
if (util_1.isHTMLInputElement(element) || util_1.isHTMLTextAreaElement(element)) {
return element.value;

@@ -216,14 +222,8 @@ }

* @param root
* @param context
* @param [options]
* @parma [options.getComputedStyle] - mock window.getComputedStyle. Needs `content`, `display` and `visibility`
*/
function computeAccessibleName(root, context = {}) {
/**
* @type {Set<Node>}
*/
function computeAccessibleName(root, options = {}) {
const consultedNodes = new Set();
/**
* @type {FlatString}
*/
let totalAccumulatedText = "";
if (prohibitsNaming(root) && !context.isReferenced) {
if (prohibitsNaming(root)) {
return "";

@@ -234,4 +234,4 @@ }

let accumulatedText = "";
if (isElement(node)) {
const pseudoBefore = safeWindow(node).getComputedStyle(node, "::before");
if (util_1.isElement(node)) {
const pseudoBefore = createGetComputedStyle(node, options)(node, "::before");
const beforeContent = getTextualContent(pseudoBefore);

@@ -247,11 +247,9 @@ accumulatedText = `${beforeContent} ${accumulatedText}`;

// TODO: Unclear why display affects delimiter
const display = isElement(node) &&
safeWindow(node)
.getComputedStyle(node)
.getPropertyValue("display");
const display = util_1.isElement(node) &&
createGetComputedStyle(node, options)(node).getPropertyValue("display");
const separator = display !== "inline" ? " " : "";
accumulatedText += `${separator}${result}`;
}
if (isElement(node)) {
const pseudoAfter = safeWindow(node).getComputedStyle(node, ":after");
if (util_1.isElement(node)) {
const pseudoAfter = createGetComputedStyle(node, options)(node, ":after");
const afterContent = getTextualContent(pseudoAfter);

@@ -266,3 +264,3 @@ accumulatedText = `${accumulatedText} ${afterContent}`;

function computeAttributeTextAlternative(node) {
if (!isElement(node)) {
if (!util_1.isElement(node)) {
return null;

@@ -280,3 +278,3 @@ }

}
if (isHTMLInputElement(node) && node.type === "button") {
if (util_1.isHTMLInputElement(node) && node.type === "button") {
consultedNodes.add(node);

@@ -288,3 +286,3 @@ return node.getAttribute("value") || "";

function computeElementTextAlternative(node) {
if (!isHTMLInputElement(node)) {
if (!util_1.isHTMLInputElement(node)) {
return null;

@@ -324,2 +322,3 @@ }

// special casing, cheating to make tests pass
// https://github.com/w3c/accname/issues/67
if (hasAnyConcreteRoles(current, ["menu"])) {

@@ -330,3 +329,3 @@ consultedNodes.add(current);

// 2A
if (isHidden(current) && !context.isReferenced) {
if (isHidden(current, options) && !context.isReferenced) {
consultedNodes.add(current);

@@ -350,5 +349,7 @@ return "";

// 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 = ((isElement(current) && current.getAttribute("aria-label")) ||
const ariaLabel = ((util_1.isElement(current) && current.getAttribute("aria-label")) ||
"").trim();

@@ -360,3 +361,3 @@ if (ariaLabel !== "") {

// 2D
if (!hasAnyConcreteRoles(current, ["none", "presentation"])) {
if (!isMarkedPresentational(current)) {
const elementTextAlternative = computeElementTextAlternative(current);

@@ -381,3 +382,3 @@ if (elementTextAlternative !== null) {

// defined per test `name_heading_combobox`
return isHTMLInputElement(current) ? current.value : "";
return util_1.isHTMLInputElement(current) ? current.value : "";
}

@@ -397,5 +398,9 @@ return Array.from(selectedOptions)

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");

@@ -411,5 +416,5 @@ }

}
// 2F
// 2F: https://w3c.github.io/accname/#step2F
if (allowsNameFromContent(current) ||
(isElement(current) && context.isReferenced) ||
(util_1.isElement(current) && context.isReferenced) ||
isNativeHostLanguageTextAlternativeElement(current) ||

@@ -416,0 +421,0 @@ isDescendantOfNativeHostLanguageTextAlternativeElement(current)) {

@@ -73,2 +73,3 @@ "use strict";

}
break;
case "IMG":

@@ -78,3 +79,4 @@ if ((element.getAttribute("alt") || "").length > 0) {

}
case "INPUT":
break;
case "INPUT": {
const { type } = element;

@@ -108,2 +110,3 @@ switch (type) {

}
}
case "SELECT":

@@ -120,2 +123,4 @@ if (element.hasAttribute("multiple") ||

if (element.hasAttribute("role")) {
// safe due to hasAttribute check
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const [explicitRole] = element

@@ -122,0 +127,0 @@ .getAttribute("role")

{
"name": "dom-accessibility-api",
"version": "0.1.0",
"version": "0.2.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/eps1lon/dom-accessibility-api.git"
},
"files": [

@@ -14,2 +18,4 @@ "dist/"

"lint": "eslint --report-unused-disable-directives \"sources/**/*.ts\"",
"release:prepare": "yarn changeset version",
"release": "yarn changeset publish",
"test": "jest",

@@ -27,32 +33,28 @@ "test:ci": "jest --ci --config jest.ci.config.js --runInBand",

"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/preset-env": "^7.6.2",
"@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",
"@babel/core": "^7.7.4",
"@babel/preset-env": "^7.7.4",
"@babel/preset-typescript": "^7.7.4",
"@changesets/cli": "^2.4.0",
"@testing-library/dom": "^6.10.1",
"@types/jest": "^24.0.23",
"@typescript-eslint/parser": "^2.9.0",
"@typescript-eslint/eslint-plugin": "^2.9.0",
"concurrently": "^5.0.0",
"cypress": "^3.4.1",
"eslint": "^6.6.0",
"cypress": "^3.6.1",
"eslint": "^6.7.1",
"jest": "^24.9.0",
"jest-diff": "^24.9.0",
"jest-environment-jsdom-thirteen": "^1.0.1",
"jest-junit": "^8.0.0",
"jest-junit": "^9.0.0",
"js-yaml": "^3.13.1",
"jsdom": "^15.1.1",
"jsdom": "^15.2.1",
"minimatch": "^3.0.4",
"mocha": "^6.2.1",
"mocha": "^6.2.2",
"mocha-sugar-free": "^1.4.0",
"prettier": "^1.18.2",
"prettier": "^1.19.1",
"q": "^1.5.1",
"request": "^2.34",
"request-promise-native": "^1.0.7",
"semantic-release": "^15.13.30",
"request-promise-native": "^1.0.8",
"serve": "^11.2.0",
"typescript": "^3.6.3"
"typescript": "^3.7.2"
},

@@ -62,9 +64,10 @@ "prettier": {

},
"dependencies": {
"@typescript-eslint/parser": "^2.5.0"
},
"repository": {
"type": "git",
"url": "https://github.com/eps1lon/dom-accessibility-api.git"
"keywords": [
"accessibility",
"ARIA",
"accname"
],
"publishConfig": {
"access": "public"
}
}

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