@uuv/a11y
Version:
A javascript lib for running a11y validation based on multiple reference(RGAA, etc)
106 lines (105 loc) • 4.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.table = exports.tableCssSelector = exports.commonCssSelector = exports.siblingElement = exports.informativeContent = void 0;
class SelectorRule {
SELECTOR;
ATTRIBUTES;
constructor(SELECTOR, ATTRIBUTES) {
this.SELECTOR = SELECTOR;
this.ATTRIBUTES = ATTRIBUTES;
this.SELECTOR = SELECTOR;
this.ATTRIBUTES = ATTRIBUTES;
}
buildSelectorWithAttributes() {
const result = this.ATTRIBUTES.map(value => `${this.SELECTOR}[${value}]`);
if (result.length === 0) {
return [this.SELECTOR];
}
return result;
}
}
exports.informativeContent = {
image: new SelectorRule("img", ["title", "aria-labelledby", "aria-label", "alt"]),
area: new SelectorRule("area[href]", ["title", "aria-labelledby", "aria-label", "alt"]),
input: new SelectorRule("input[type=image]", ["title", "aria-labelledby", "aria-label", "alt"]),
object: new SelectorRule("object[type^=image]", ["title", "aria-labelledby", "aria-label"]),
embed: new SelectorRule("embed[type^=image]", ["title", "aria-labelledby", "aria-label"]),
svg: new SelectorRule("svg:not(a svg,button svg)", ["title", "aria-labelledby", "aria-label"]),
canvas: new SelectorRule("canvas:not(:empty)", ["title", "aria-labelledby", "aria-label"]),
};
exports.siblingElement = {
button: new SelectorRule("button", []),
a: new SelectorRule("a[href]", []),
};
/** CSS SELECTOR HELPER *******/
class CssSelectorRule {
attributes;
selector;
role;
constructor(attributes, selector = "", role = selector) {
this.attributes = attributes;
this.selector = selector;
this.role = role;
this.selector = selector;
this.role = role;
this.attributes = attributes;
}
buildSelector(overrideSelector = [], overrideRole = overrideSelector[0]) {
if (overrideSelector && overrideSelector.length === 0 && !overrideRole) {
console.error("selector or role must be provided");
}
const selectors = [];
if (overrideSelector.length > 0) {
selectors.push(...overrideSelector);
}
if (overrideRole) {
selectors.push(`[role=${overrideRole}]`);
}
if (this.attributes.length === 0) {
return selectors;
}
const result = [];
selectors.forEach(selector => {
this.attributes.forEach(attribute => {
result.push(`${selector}${attribute}`);
});
});
return result;
}
}
exports.commonCssSelector = {
ariaDescribedBy: ["[aria-describedby]:not([aria-describedby=''])"],
title: ["[title]:not([title=''])"],
ariaLabelledBy: ["[aria-labelledby]:not([aria-labelledby=''])"],
ariaLabel: ["[aria-label]:not([aria-label=''])"]
};
exports.tableCssSelector = {
complexTh: [":has(tr:not(:first-child) th:first-child)"],
complexRowHeader: [":has([role=row]:not(:first-child) [role=rowheader])"],
complexColumnHeader: [":has([role=row]:not(:first-child) [role=columnheader])"],
};
exports.table = {
selector: {
withFormatting: "table[role=presentation]",
complex: [
...exports.tableCssSelector.complexTh,
...exports.tableCssSelector.complexRowHeader,
...exports.tableCssSelector.complexColumnHeader
].map(value => `table:not([role=presentation])${value}`),
withData: "table:not([role=presentation])"
},
noCaption: new CssSelectorRule([":not(:has(> caption))", ":has(> caption:empty)"]),
caption: new CssSelectorRule(["> caption:not(:empty)"]),
summary: new CssSelectorRule(["[summary]:not([summary=''])"]),
ariaDescribedBy: new CssSelectorRule(exports.commonCssSelector.ariaDescribedBy),
title: new CssSelectorRule(exports.commonCssSelector.title),
ariaLabel: new CssSelectorRule(exports.commonCssSelector.ariaLabel),
ariaLabelledBy: new CssSelectorRule(exports.commonCssSelector.ariaLabelledBy),
thColumnHeader: new CssSelectorRule([" tr:first-child th"]),
thRowHeader: new CssSelectorRule([" tr:not(:first-child) th:first-child"]),
hasComplexHeader: new CssSelectorRule([
...exports.tableCssSelector.complexTh,
...exports.tableCssSelector.complexRowHeader,
...exports.tableCssSelector.complexColumnHeader
])
};