intern-a11y
Version:
Intern-a11y. An accessibility testing helper for Intern.
95 lines • 6.28 kB
JavaScript
"use strict";
var path_1 = require("path");
var fs_1 = require("fs");
var A11yReporter = (function () {
function A11yReporter(config) {
this.config = config;
this.filename = this.config.filename;
if (!this.filename) {
this.filename = 'a11y-report';
}
if (/\.html$/.test(this.filename)) {
this.report = [];
}
else {
try {
fs_1.mkdirSync(this.filename);
}
catch (error) {
if (error.code !== 'EEXIST') {
throw error;
}
}
}
}
A11yReporter.prototype.testFail = function (test) {
var error = test.error;
var results = error.a11yResults;
if (results) {
var content = renderResults(results, test.id);
if (this.report) {
this.report.push(content);
}
else {
var filename = path_1.join(this.filename, sanitizeFilename(test.id + '.html'));
fs_1.writeFileSync(filename, renderReport(content));
}
}
};
A11yReporter.prototype.runEnd = function () {
if (this.report) {
fs_1.writeFileSync(this.filename, renderReport(this.report.join('')));
}
};
A11yReporter.writeReport = function (filename, results, id) {
return new Promise(function (resolve, reject) {
var content = renderResults(results, id);
fs_1.writeFile(filename, renderReport(content), function (error) {
if (error) {
reject(error);
}
else {
resolve(results);
}
});
});
};
return A11yReporter;
}());
function escape(str) {
return String(str).replace(/</g, '<');
}
function renderReport(body) {
return "<!DOCTYPE html>\n\t<html lang=\"en\">\n\t\t<head>\n\t\t<title>Accessibility Report</title>\n\t\t\t<style>\n\t\t\t\thtml { font-family:sans-serif; background:#eee; }\n\t\t\t\tbody { width:800px; padding:1em; margin:0 auto; }\n\n\t\t\t\tsection { border:solid 1px #ddd; border-radius:2px; background:white; padding:1em; margin-bottom:1em; overflow:hidden; }\n\t\t\t\tsection:last-of-type { margin-bottom:0; }\n\t\t\t\tsection > * { margin-bottom:1em; }\n\t\t\t\tsection > *:last-child { margin-bottom:0; }\n\n\t\t\t\th1 { margin:0; margin-bottom:0.5em; }\n\t\t\t\th2 { margin:0; margin-bottom:0.25em; font-size:110%; }\n\t\t\t\tpre { border-radius:4px; padding:0.5em; margin:0; overflow:auto; color:#999; }\n\n\t\t\t\t.violation { border:solid 1px #e7e7e7; border-radius:2px; margin-bottom:1em; background:#f7f7f7; overflow:hidden; }\n\t\t\t\t.violation:last-child { margin-bottom:0; }\n\n\t\t\t\t.header > * { margin:1em 0.5em; }\n\t\t\t\t.header > *:first-child { margin-top:0.5em; }\n\n\t\t\t\t.description { color:#444; }\n\n\t\t\t\t.standards ul { margin:0; }\n\n\t\t\t\t.snippet { border-radius:0; background:#eee; }\n\n\t\t\t\tul.meta { padding-left:0; }\n\t\t\t\tul.meta li { list-style-type:none; }\n\t\t\t\tli .label { font-weight:bold; width:5em; display:inline-block; }\n\t\t\t\tli .label:after { content:':'; }\n\n\t\t\t\t.when-open { display:none; }\n\t\t\t\t.when-closed { display:block; }\n\t\t\t\tspan.when-closed { display:inline; }\n\t\t\t\t.open .when-closed { display:none; }\n\t\t\t\t.open .when-open { display:block; }\n\t\t\t\t.open span.when-open { display:inline; }\n\n\t\t\t\t.raw-results pre { padding:0.5em; background:#f5f5f5; color:#444; margin-top:0.5em; }\n\t\t\t</style>\n\t\t\t<script>\n\t\t\t\twindow.addEventListener('load', function () {\n\t\t\t\t\tdocument.body.addEventListener('click', function (event) {\n\t\t\t\t\t\tvar target = event.target;\n\t\t\t\t\t\twhile (target) {\n\t\t\t\t\t\t\tif (target.getAttribute('data-action') === 'toggle-open') {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\ttarget.parentElement.classList.toggle('open');\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttarget = target.parentElement;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t</script>\n\t\t</head>\n\t\t<body>\n\t\t\t" + body + "\n\t\t</body>\n\t</html>";
}
function renderResults(results, id) {
var out = ['<section class="results">'];
out.push("<h1>" + id + "</h1>");
out.push("<ul class=\"meta\">\n\t\t<li><span class=\"label\">Analyzer</span> " + results.analyzer + "</li>\n\t\t<li><span class=\"label\">Source</span> " + results.source + "</li>\n\t</ul>");
if (results.violations.length > 0) {
out = out.concat(results.violations.map(renderViolation));
}
else {
out = out.concat('<p>No violations</p>');
}
out.push("<div class=\"raw-results\">\n\t\t<button data-action=\"toggle-open\"><span class=\"when-open\">Hide</span><span class=\"when-closed\">Show</span> raw results</button>\n\t\t<pre class=\"when-open\">" + escape(JSON.stringify(results.originalResults, null, ' ')) + "</pre>\n\t</div>");
return out.concat('</section>').join('');
}
function renderViolation(violation) {
var target = escape(violation.target);
if (violation.position) {
target += " (" + violation.position.line + ":" + violation.position.column + ")";
}
var standards = '';
if (violation.standards && violation.standards.length > 0) {
standards = "<div class=\"standards\">\n\t\t\t<h2>Standards</h2>\n\t\t\t<ul>\n\t\t\t\t<li>" + violation.standards.join('</li><li>') + "</li>\n\t\t\t</ul>\n\t\t</div>";
}
return "<div class=\"violation\">\n\t\t<div class=\"header\">\n\t\t\t<div class=\"target\"><h2>Target</h2><span class=\"selector\">" + target + "</span></div>\n\t\t\t<div class=\"message\"><h2>Summary</h2><a href=\"" + violation.reference + "\">" + escape(violation.message) + "</a></div>\n\t\t\t<div class=\"description\"><h2>Description</h2>" + escape(violation.description) + "</div>\n\t\t\t" + standards + "\n\t\t</div>\n\t\t<pre class=\"snippet\">" + escape(violation.snippet) + "</pre>\n\t</div>";
}
function sanitizeFilename(filename) {
return filename
.replace(/[/?<>\\:*|"]/g, '_')
.replace(/[.\s]+$/, '');
}
module.exports = A11yReporter;
//# sourceMappingURL=A11yReporter.js.map