@diegovelasquezweb/a11y-engine 0.11.9 → 0.11.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.mjs +86 -28
- package/src/reports/pdf.mjs +28 -3
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -852,10 +852,33 @@ export async function getPDFReport(payload, options = {}) {
|
|
|
852
852
|
buildPdfAuditLimitations,
|
|
853
853
|
} = await import("./reports/renderers/pdf.mjs");
|
|
854
854
|
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
(
|
|
858
|
-
|
|
855
|
+
const deriveConformanceLevel = () => {
|
|
856
|
+
const tags = payload?.metadata?.testingMethodology?.axe_tags || payload?.axeTags || [];
|
|
857
|
+
if (Array.isArray(tags)) {
|
|
858
|
+
if (tags.includes("wcag2aaa")) return "AAA";
|
|
859
|
+
if (tags.includes("wcag2aa") || tags.includes("wcag21aa") || tags.includes("wcag22aa")) return "AA";
|
|
860
|
+
if (tags.includes("wcag2a") || tags.includes("wcag21a") || tags.includes("wcag22a")) return "A";
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
const level = payload?.metadata?.testingMethodology?.conformance_level;
|
|
864
|
+
if (level === "A" || level === "AA" || level === "AAA") return level;
|
|
865
|
+
return "AA";
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
const filterByConformance = (finding, conformanceLevel) => {
|
|
869
|
+
const wcag = finding.wcagClassification;
|
|
870
|
+
if (wcag === "Best Practice") return false;
|
|
871
|
+
if (conformanceLevel === "A") return wcag !== "AA" && wcag !== "AAA";
|
|
872
|
+
if (conformanceLevel === "AA") return wcag !== "AAA";
|
|
873
|
+
return true;
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
const conformanceLevel = deriveConformanceLevel();
|
|
877
|
+
const args = {
|
|
878
|
+
baseUrl: options.baseUrl || "",
|
|
879
|
+
target: options.target || `WCAG 2.2 ${conformanceLevel}`,
|
|
880
|
+
};
|
|
881
|
+
const findings = normalizeForReports(payload).filter((f) => filterByConformance(f, conformanceLevel));
|
|
859
882
|
|
|
860
883
|
const totals = buildSummary(findings);
|
|
861
884
|
const score = computeComplianceScore(totals);
|
|
@@ -943,7 +966,6 @@ export async function getChecklist(options = {}) {
|
|
|
943
966
|
<nav aria-label="Checklist header">
|
|
944
967
|
<div class="max-w-4xl mx-auto px-4 h-16 flex justify-between items-center">
|
|
945
968
|
<div class="flex items-center gap-3">
|
|
946
|
-
<div class="px-3 h-10 rounded-lg bg-slate-900 text-white font-bold text-base font-mono flex items-center justify-center shadow-md">a11y</div>
|
|
947
969
|
<h1 class="text-xl font-bold">Manual <span class="text-slate-500">Checklist</span></h1>
|
|
948
970
|
</div>
|
|
949
971
|
<span class="text-sm text-slate-500 font-medium">${escapeHtml(siteLabel)}</span>
|
|
@@ -957,9 +979,6 @@ export async function getChecklist(options = {}) {
|
|
|
957
979
|
</div>
|
|
958
980
|
<div class="flex flex-wrap items-center gap-3 mb-8">
|
|
959
981
|
<div class="flex items-center gap-1.5 text-sm font-semibold"><span class="inline-block w-3 h-3 rounded-full bg-slate-300"></span><span id="count-total">${TOTAL}</span> Total</div>
|
|
960
|
-
<div class="flex items-center gap-1.5 text-sm font-semibold text-emerald-600"><span class="inline-block w-3 h-3 rounded-full bg-emerald-400"></span><span id="count-pass">0</span> Pass</div>
|
|
961
|
-
<div class="flex items-center gap-1.5 text-sm font-semibold text-rose-600"><span class="inline-block w-3 h-3 rounded-full bg-rose-400"></span><span id="count-fail">0</span> Fail</div>
|
|
962
|
-
<div class="flex items-center gap-1.5 text-sm font-semibold text-amber-600"><span class="inline-block w-3 h-3 rounded-full bg-amber-400"></span><span id="count-na">0</span> N/A</div>
|
|
963
982
|
<div class="ml-auto flex items-center gap-2">
|
|
964
983
|
<select id="level-filter" class="${selectClasses}">
|
|
965
984
|
<option value="all">All levels</option>
|
|
@@ -972,28 +991,67 @@ export async function getChecklist(options = {}) {
|
|
|
972
991
|
<div id="checklist-items" class="space-y-4">${cards}</div>
|
|
973
992
|
</main>
|
|
974
993
|
<script>
|
|
975
|
-
const items = document.querySelectorAll('
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
994
|
+
const items = [...document.querySelectorAll('.manual-card')];
|
|
995
|
+
|
|
996
|
+
function toggleCard(button) {
|
|
997
|
+
const card = button.closest('.manual-card');
|
|
998
|
+
if (!card) return;
|
|
999
|
+
const body = card.querySelector('.card-body');
|
|
1000
|
+
const chevron = card.querySelector('.card-chevron');
|
|
1001
|
+
const expanded = card.dataset.collapsed === 'false';
|
|
1002
|
+
const nextExpanded = !expanded;
|
|
1003
|
+
card.dataset.collapsed = nextExpanded ? 'false' : 'true';
|
|
1004
|
+
button.setAttribute('aria-expanded', nextExpanded ? 'true' : 'false');
|
|
1005
|
+
if (body) body.style.gridTemplateRows = nextExpanded ? '1fr' : '0fr';
|
|
1006
|
+
if (chevron) chevron.style.transform = nextExpanded ? 'rotate(180deg)' : 'rotate(0deg)';
|
|
982
1007
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1008
|
+
|
|
1009
|
+
function updateCardStateUI(card) {
|
|
1010
|
+
const state = card.dataset.state || '';
|
|
1011
|
+
const verifiedBtn = card.querySelector('.manual-verified-btn');
|
|
1012
|
+
const naBtn = card.querySelector('.manual-na-btn');
|
|
1013
|
+
if (verifiedBtn) {
|
|
1014
|
+
verifiedBtn.setAttribute('aria-pressed', state === 'verified' ? 'true' : 'false');
|
|
1015
|
+
verifiedBtn.classList.toggle('border-emerald-500', state === 'verified');
|
|
1016
|
+
verifiedBtn.classList.toggle('bg-emerald-100', state === 'verified');
|
|
1017
|
+
verifiedBtn.classList.toggle('text-emerald-800', state === 'verified');
|
|
1018
|
+
verifiedBtn.classList.toggle('border-slate-200', state !== 'verified');
|
|
1019
|
+
verifiedBtn.classList.toggle('bg-white', state !== 'verified');
|
|
1020
|
+
verifiedBtn.classList.toggle('text-slate-500', state !== 'verified');
|
|
1021
|
+
}
|
|
1022
|
+
if (naBtn) {
|
|
1023
|
+
naBtn.setAttribute('aria-pressed', state === 'na' ? 'true' : 'false');
|
|
1024
|
+
naBtn.classList.toggle('border-slate-500', state === 'na');
|
|
1025
|
+
naBtn.classList.toggle('bg-slate-200', state === 'na');
|
|
1026
|
+
naBtn.classList.toggle('text-slate-800', state === 'na');
|
|
1027
|
+
naBtn.classList.toggle('border-slate-200', state !== 'na');
|
|
1028
|
+
naBtn.classList.toggle('bg-white', state !== 'na');
|
|
1029
|
+
naBtn.classList.toggle('text-slate-500', state !== 'na');
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
function setManualState(criterion, newState) {
|
|
1034
|
+
const card = document.getElementById('manual-' + criterion.replace(/\./g, '-'));
|
|
1035
|
+
if (!card) return;
|
|
1036
|
+
const current = card.dataset.state || '';
|
|
1037
|
+
card.dataset.state = current === newState ? '' : newState;
|
|
1038
|
+
updateCardStateUI(card);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
function applyFilter() {
|
|
1042
|
+
const select = document.getElementById('level-filter');
|
|
1043
|
+
const value = select ? select.value : 'all';
|
|
1044
|
+
items.forEach((card) => {
|
|
1045
|
+
card.style.display = value === 'all' || card.dataset.level === value ? '' : 'none';
|
|
994
1046
|
});
|
|
995
|
-
}
|
|
996
|
-
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
window.toggleCard = toggleCard;
|
|
1050
|
+
window.setManualState = setManualState;
|
|
1051
|
+
items.forEach(updateCardStateUI);
|
|
1052
|
+
const levelFilter = document.getElementById('level-filter');
|
|
1053
|
+
if (levelFilter) levelFilter.addEventListener('change', applyFilter);
|
|
1054
|
+
applyFilter();
|
|
997
1055
|
<\/script>
|
|
998
1056
|
</body>
|
|
999
1057
|
</html>`;
|
package/src/reports/pdf.mjs
CHANGED
|
@@ -76,6 +76,29 @@ function parseArgs(argv) {
|
|
|
76
76
|
return args;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
function deriveConformanceLevelFromPayload(payload) {
|
|
80
|
+
const tags = payload?.metadata?.testingMethodology?.axe_tags || payload?.axeTags || [];
|
|
81
|
+
if (Array.isArray(tags)) {
|
|
82
|
+
if (tags.includes("wcag2aaa")) return "AAA";
|
|
83
|
+
if (tags.includes("wcag2aa") || tags.includes("wcag21aa") || tags.includes("wcag22aa")) return "AA";
|
|
84
|
+
if (tags.includes("wcag2a") || tags.includes("wcag21a") || tags.includes("wcag22a")) return "A";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const level = payload?.metadata?.testingMethodology?.conformance_level;
|
|
88
|
+
if (level === "A" || level === "AA" || level === "AAA") return level;
|
|
89
|
+
return "AA";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function filterByConformance(findings, conformanceLevel) {
|
|
93
|
+
return findings.filter((finding) => {
|
|
94
|
+
const wcag = finding.wcagClassification;
|
|
95
|
+
if (wcag === "Best Practice") return false;
|
|
96
|
+
if (conformanceLevel === "A") return wcag !== "AA" && wcag !== "AAA";
|
|
97
|
+
if (conformanceLevel === "AA") return wcag !== "AAA";
|
|
98
|
+
return true;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
79
102
|
/**
|
|
80
103
|
* Constructs the HTML structure specifically tailored for PDF rendering.
|
|
81
104
|
* @param {Object} args - The parsed CLI arguments.
|
|
@@ -215,9 +238,11 @@ async function main() {
|
|
|
215
238
|
process.exit(1);
|
|
216
239
|
}
|
|
217
240
|
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
241
|
+
const conformanceLevel = deriveConformanceLevelFromPayload(inputPayload);
|
|
242
|
+
if (!args.target || args.target === DEFAULTS.complianceTarget) {
|
|
243
|
+
args.target = `WCAG 2.2 ${conformanceLevel}`;
|
|
244
|
+
}
|
|
245
|
+
const findings = filterByConformance(normalizeFindings(inputPayload), conformanceLevel);
|
|
221
246
|
const html = buildPdfHtml(args, findings);
|
|
222
247
|
|
|
223
248
|
log.info("Generating professional PDF report...");
|