1class QuartoAxeReporter { 2 constructor(axeResult, options) { 3 this.axeResult = axeResult; 4 this.options = options; 5 } 6 7 report() { 8 throw new Error("report() is an abstract method"); 9 } 10} 11 12class QuartoAxeJsonReporter extends QuartoAxeReporter { 13 constructor(axeResult, options) { 14 super(axeResult, options); 15 } 16 17 report() { 18 console.log(JSON.stringify(this.axeResult, null, 2)); 19 } 20} 21 22class QuartoAxeConsoleReporter extends QuartoAxeReporter { 23 constructor(axeResult, options) { 24 super(axeResult, options); 25 } 26 27 report() { 28 for (const violation of this.axeResult.violations) { 29 console.log(violation.description); 30 for (const node of violation.nodes) { 31 for (const target of node.target) { 32 console.log(target); 33 console.log(document.querySelector(target)); 34 } 35 } 36 } 37 } 38} 39 40class QuartoAxeDocumentReporter extends QuartoAxeReporter { 41 constructor(axeResult, options) { 42 super(axeResult, options); 43 } 44 45 createViolationElement(violation) { 46 const violationElement = document.createElement("div"); 47 48 const descriptionElement = document.createElement("div"); 49 descriptionElement.className = "quarto-axe-violation-description"; 50 descriptionElement.innerText = `${violation.impact.replace(/^[a-z]/, match => match.toLocaleUpperCase())}: ${violation.description}`; 51 violationElement.appendChild(descriptionElement); 52 53 const helpElement = document.createElement("div"); 54 helpElement.className = "quarto-axe-violation-help"; 55 helpElement.innerText = violation.help; 56 violationElement.appendChild(helpElement); 57 58 const nodesElement = document.createElement("div"); 59 nodesElement.className = "quarto-axe-violation-nodes"; 60 violationElement.appendChild(nodesElement); 61 const nodeElement = document.createElement("div"); 62 nodeElement.className = "quarto-axe-violation-selector"; 63 for (const node of violation.nodes) { 64 for (const target of node.target) { 65 const targetElement = document.createElement("span"); 66 targetElement.className = "quarto-axe-violation-target"; 67 targetElement.innerText = target; 68 nodeElement.appendChild(targetElement); 69 nodeElement.addEventListener("mouseenter", () => { 70 const element = document.querySelector(target); 71 if (element) { 72 element.scrollIntoView({ behavior: "smooth", block: "center" }); 73 element.classList.add("quarto-axe-hover-highlight"); 74 setTimeout(() => { 75 element.style.border = ""; 76 }, 2000); 77 } 78 }); 79 nodeElement.addEventListener("mouseleave", () => { 80 const element = document.querySelector(target); 81 if (element) { 82 element.classList.remove("quarto-axe-hover-highlight"); 83 } 84 }); 85 nodeElement.addEventListener("click", () => { 86 console.log(document.querySelector(target)); 87 }); 88 nodeElement.appendChild(targetElement); 89 } 90 nodesElement.appendChild(nodeElement); 91 } 92 return violationElement; 93 } 94 95 report() { 96 const violations = this.axeResult.violations; 97 const reportElement = document.createElement("div"); 98 reportElement.className = "quarto-axe-report"; 99 if (violations.length === 0) { 100 const noViolationsElement = document.createElement("div"); 101 noViolationsElement.className = "quarto-axe-no-violations"; 102 noViolationsElement.innerText = "No axe-core violations found."; 103 reportElement.appendChild(noViolationsElement); 104 } 105 violations.forEach((violation) => { 106 reportElement.appendChild(this.createViolationElement(violation)); 107 }); 108 document.querySelector("main").appendChild(reportElement); 109 } 110} 111 112const reporters = { 113 json: QuartoAxeJsonReporter, 114 console: QuartoAxeConsoleReporter, 115 document: QuartoAxeDocumentReporter, 116}; 117 118class QuartoAxeChecker { 119 constructor(opts) { 120 this.options = opts; 121 } 122 async init() { 123 const axe = (await import("https://cdn.skypack.dev/pin/[email protected]/mode=imports,min/optimized/axe-core.js")).default; 124 const result = await axe.run({ 125 exclude: [ 126 // https://github.com/microsoft/tabster/issues/288 127 // MS has claimed they won't fix this, so we need to add an exclusion to 128 // all tabster elements 129 "[data-tabster-dummy]" 130 ], 131 preload: { assets: ['cssom'], timeout: 50000 } 132 }); 133 const reporter = this.options === true ? new QuartoAxeConsoleReporter(result) : new reporters[this.options.output](result, this.options); 134 reporter.report(); 135 } 136} 137
138export async function init() { 139 const opts = document.querySelector("#quarto-axe-checker-options"); 140 if (opts) { 141 const jsonOptions = JSON.parse(atob(opts.textContent)); 142 const checker = new QuartoAxeChecker(jsonOptions); 143 await checker.init(); 144 } 145}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.