kayle
Version:
Extremely fast and accurate accessibility engine built for any headless tool like playwright or puppeteer.
234 lines • 8.43 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.kayle = exports.auditExtension = exports.runActionsList = void 0;
const option_1 = require("./option");
const action_1 = require("./action");
const config_1 = require("./config");
const runner_js_1 = require("./runner-js");
const go_to_page_1 = require("./utils/go-to-page");
const watcher_1 = require("./watcher");
const wasm_1 = require("./wasm");
const smart_check_1 = require("./utils/smart-check");
const audit = async (config) => {
if (config.browserExtension) {
return await (0, exports.auditExtension)(config);
}
if (config._kayleRunner && config.runners.length === 1) {
return {
automateable: null,
documentTitle: "",
issues: [],
meta: {
errorCount: 0,
warningCount: 0,
noticeCount: 0,
accessScore: 0,
},
pageUrl: config.origin,
};
}
return await config.page.evaluate(async (runOptions) => {
if (window.origin === "null" && runOptions.origin) {
window.origin = runOptions.origin;
}
return await window?.__a11y?.run(runOptions);
}, {
hideElements: config.hideElements,
ignore: config.ignore || [],
rootElement: config.rootElement,
rules: config.rules || [],
runners: config.runners,
standard: config.standard,
origin: config.origin,
language: config.language,
clip: config.clip,
});
};
const auditPage = async (config) => {
await Promise.all([(0, exports.runActionsList)(config), injectRunners(config)]);
const results = await audit(config);
if (config._kayleRunner) {
await auditPageInnate(config, results);
}
return results;
};
const runActionsList = async (config) => {
for (const action of config.actions) {
await (0, action_1.runAction)(config.browser, config.page, config, action);
}
};
exports.runActionsList = runActionsList;
const injectRunners = async (config) => {
if (!config.browserExtension) {
return await Promise.allSettled([
config.page.evaluate(runner_js_1.runnersJavascript["kayle"]),
...config.runners.map((r) => config.page.evaluate((0, runner_js_1.getRunner)(config.language, r))),
]);
}
};
const auditExtension = async (config) => {
return await config.page.evaluate((runOptions) => {
return new Promise((resolve) => {
if (runOptions.origin && window.origin === "null") {
window.origin = runOptions.origin;
}
window.addEventListener("kayle_receive", (event) => resolve(event.detail.data));
window.dispatchEvent(new CustomEvent("kayle_send", {
detail: {
name: "kayle",
options: runOptions,
},
}));
});
}, {
hideElements: config.hideElements,
ignore: config.ignore || [],
rootElement: config.rootElement,
rules: config.rules || [],
runners: config.runners,
standard: config.standard,
origin: config.origin,
language: config.language,
clip: config.clip,
});
};
exports.auditExtension = auditExtension;
let kayle_innate;
const auditPageInnate = async (config, results) => {
const html = await config.page.content();
const css = await (0, wasm_1.getAllCss)(config);
if (!kayle_innate) {
kayle_innate = await Promise.resolve().then(() => __importStar(require("kayle_innate")));
}
const innateAudit = await kayle_innate.audit(html, css, config.clip);
for (const innateIssue of innateAudit) {
if (innateIssue.issue_type === "error") {
results.meta.errorCount += innateIssue.recurrence || 1;
}
if (innateIssue.issue_type === "warning") {
results.meta.warningCount += innateIssue.recurrence || 1;
}
if (innateIssue.issue_type === "notice") {
results.meta.noticeCount += innateIssue.recurrence || 1;
}
results.issues.push({
code: innateIssue.code,
type: innateIssue.issue_type,
typeCode: innateIssue.type_code,
message: innateIssue.message,
recurrence: innateIssue.recurrence,
clip: innateIssue.clip,
runner: "kayle",
runnerExtras: innateIssue.runner_extras,
selector: innateIssue.selectors.join(","),
context: innateIssue.context,
});
if (innateIssue.code === "Principle1.Guideline1_1.1_1_1.H37") {
results.automateable.missingAltIndexs.push(results.issues.length - 1);
}
}
};
const kayle = async (o = {}, preventClose) => {
const watcher = new watcher_1.Watcher();
const navigate = o.page?.url() === "about:blank" && (o.origin || o.html);
const config = (0, option_1.extractArgs)(o, watcher);
let validPage = true;
if (o.dialogHandle) {
o.page.on("dialog", async (dialog) => {
try {
if (o.dialogHandle.action === "accept") {
await dialog.accept(o.dialogHandle.promptText);
}
else {
await dialog.dismiss();
}
}
catch (e) {
}
});
}
if (o.smart_check) {
await (0, smart_check_1.smartCheck)(o);
}
if (navigate) {
validPage = await (0, go_to_page_1.goToPage)(o);
}
else if (!o.noIntercept) {
await (0, go_to_page_1.setNetworkInterception)(o);
}
if (validPage) {
const results = await Promise.race([
watcher.watch(config.timeout),
auditPage(config),
]);
clearTimeout(watcher.timer);
if (results && o.clip && o.clip2Base64 && Array.isArray(results.issues)) {
results.issues = await Promise.all(results.issues.map(async (item) => {
if (typeof o.clipMax === "number") {
if (!o.clipMax) {
return item;
}
o.clipMax--;
}
try {
const buffer = await o.page.screenshot({
path: o.clipDir
? `${o.clipDir}${o.clipDir.endsWith("/") ? "" : "/"}${item.selector.trim()}.png`
: undefined,
clip: item.clip,
});
item.clipBase64 = buffer.toString("base64");
}
catch (_) {
item.clipBase64 = "";
}
return item;
}));
}
if (!preventClose && navigate) {
try {
await config.page.close();
}
catch (e) {
config_1._log.enabled && console.error(e);
}
}
return results;
}
else {
if (!preventClose && navigate) {
try {
await config.page.close();
}
catch (e) {
config_1._log.enabled && console.error(e);
}
}
return null;
}
};
exports.kayle = kayle;
//# sourceMappingURL=kayle.js.map