accessibility-checker 4.0.31 → 4.0.32
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/README.md +29 -0
- package/cjs/lib/common/config/ACConfigManager.js +15 -1
- package/cjs/lib/common/config/ACConfigManager.js.map +1 -1
- package/cjs/lib/common/config/ACConstants.js +4 -4
- package/cjs/lib/common/config/ACConstants.js.map +1 -1
- package/cjs/lib/common/report/ACReporterXLSX.d.ts +2 -2
- package/cjs/lib/common/report/ACReporterXLSX.js +408 -649
- package/cjs/lib/common/report/ACReporterXLSX.js.map +1 -1
- package/cjs/lib/common/report/genReport.js +2 -2
- package/cjs/lib/common/report/genReport.js.map +1 -1
- package/lib/common/config/ACConfigManager.js +15 -1
- package/lib/common/config/ACConfigManager.js.map +1 -1
- package/lib/common/config/ACConstants.js +4 -4
- package/lib/common/config/ACConstants.js.map +1 -1
- package/lib/common/report/ACReporterXLSX.d.ts +2 -2
- package/lib/common/report/ACReporterXLSX.js +408 -649
- package/lib/common/report/ACReporterXLSX.js.map +1 -1
- package/lib/common/report/genReport.js +2 -2
- package/lib/common/report/genReport.js.map +1 -1
- package/mjs/lib/common/config/ACConfigManager.js +15 -1
- package/mjs/lib/common/config/ACConfigManager.js.map +1 -1
- package/mjs/lib/common/config/ACConstants.js +4 -4
- package/mjs/lib/common/config/ACConstants.js.map +1 -1
- package/mjs/lib/common/report/ACReporterXLSX.d.ts +2 -2
- package/mjs/lib/common/report/ACReporterXLSX.js +421 -650
- package/mjs/lib/common/report/ACReporterXLSX.js.map +1 -1
- package/mjs/lib/common/report/genReport.js +2 -2
- package/mjs/lib/common/report/genReport.js.map +1 -1
- package/package.json +4 -11
|
@@ -62,23 +62,22 @@ const IConfig_js_1 = require("../config/IConfig.js");
|
|
|
62
62
|
const IGuideline_js_1 = require("../engine/IGuideline.js");
|
|
63
63
|
const IRule_js_1 = require("../engine/IRule.js");
|
|
64
64
|
const ReporterManager_js_1 = require("./ReporterManager.js");
|
|
65
|
-
// Lazy
|
|
66
|
-
let
|
|
67
|
-
let
|
|
68
|
-
function
|
|
69
|
-
if (!
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.catch(e => null);
|
|
65
|
+
// Lazy-load write-excel-file — will be null if not installed
|
|
66
|
+
let writeExcelLoadPromise = null;
|
|
67
|
+
let writeExcelWarningShown = false;
|
|
68
|
+
function loadWriteExcel() {
|
|
69
|
+
if (!writeExcelLoadPromise) {
|
|
70
|
+
const moduleName = "write-excel-file/node";
|
|
71
|
+
writeExcelLoadPromise = Promise.resolve(`${moduleName}`).then(s => __importStar(require(s))).then(module => { var _a; return (_a = module.default) !== null && _a !== void 0 ? _a : module; })
|
|
72
|
+
.catch(() => null);
|
|
74
73
|
}
|
|
75
|
-
return
|
|
74
|
+
return writeExcelLoadPromise;
|
|
76
75
|
}
|
|
77
|
-
function
|
|
78
|
-
if (!
|
|
79
|
-
|
|
80
|
-
console.warn("Warning:
|
|
81
|
-
console.warn("To enable XLSX reports, install
|
|
76
|
+
function showWriteExcelWarning() {
|
|
77
|
+
if (!writeExcelWarningShown) {
|
|
78
|
+
writeExcelWarningShown = true;
|
|
79
|
+
console.warn("Warning: write-excel-file is not installed. XLSX report generation is disabled.");
|
|
80
|
+
console.warn("To enable XLSX reports, install write-excel-file: npm install write-excel-file");
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
function dropDupes(arr) {
|
|
@@ -92,6 +91,109 @@ function dropDupes(arr) {
|
|
|
92
91
|
}
|
|
93
92
|
});
|
|
94
93
|
}
|
|
94
|
+
// Convert ExcelJS-style ARGB (FFRRGGBB) to 6-digit hex (#RRGGBB)
|
|
95
|
+
function argbToHex(argb) {
|
|
96
|
+
if (!argb || argb.length < 6)
|
|
97
|
+
return "#000000";
|
|
98
|
+
// Strip leading alpha if 8 chars
|
|
99
|
+
const rgb = argb.length === 8 ? argb.slice(2) : argb;
|
|
100
|
+
return `#${rgb}`;
|
|
101
|
+
}
|
|
102
|
+
// Helper: cell with dark purple header style
|
|
103
|
+
function headerCell(value, columnSpan) {
|
|
104
|
+
const cell = {
|
|
105
|
+
value,
|
|
106
|
+
backgroundColor: "#403151",
|
|
107
|
+
textColor: "#FFFFFF",
|
|
108
|
+
fontFamily: "Calibri",
|
|
109
|
+
fontSize: 16,
|
|
110
|
+
alignVertical: "center",
|
|
111
|
+
align: "left",
|
|
112
|
+
height: 36,
|
|
113
|
+
};
|
|
114
|
+
if (columnSpan && columnSpan > 1)
|
|
115
|
+
cell.columnSpan = columnSpan;
|
|
116
|
+
return cell;
|
|
117
|
+
}
|
|
118
|
+
// Helper: standard data cell
|
|
119
|
+
function dataCell(value, opts) {
|
|
120
|
+
return Object.assign({ value, fontFamily: "Calibri", fontSize: 12, textColor: "#000000" }, opts);
|
|
121
|
+
}
|
|
122
|
+
// Helper: bordered cell
|
|
123
|
+
function borderedCell(value, opts) {
|
|
124
|
+
return Object.assign({ value, fontFamily: "Calibri", fontSize: 12, textColor: "#000000", borderColor: "#A6A6A6", borderStyle: "thin" }, opts);
|
|
125
|
+
}
|
|
126
|
+
// ─── XLSX table injection ──────────────────────────────────────────────────────
|
|
127
|
+
// write-excel-file has no native Excel table API. We post-process the output
|
|
128
|
+
// file: unzip it with Node's built-in zlib, inject the table definition XML,
|
|
129
|
+
// wire the sheet to reference it, and re-zip.
|
|
130
|
+
//
|
|
131
|
+
// The Issues sheet is always sheet index 3 (0-based) → sheetId "4".
|
|
132
|
+
// TableStyleMedium2 + showRowStripes matches the original ExcelJS output.
|
|
133
|
+
const ISSUES_SHEET_ID = "4";
|
|
134
|
+
const ISSUES_TABLE_ID = "1";
|
|
135
|
+
const ISSUES_COL_COUNT = 14;
|
|
136
|
+
const ISSUES_COL_NAMES = [
|
|
137
|
+
"Page title", "Page URL", "Scan label", "Issue ID", "Issue type",
|
|
138
|
+
"Toolkit level", "Checkpoint", "WCAG level", "Rule", "Issue",
|
|
139
|
+
"Element", "Code", "Xpath", "Help",
|
|
140
|
+
];
|
|
141
|
+
function buildTableXml(rowCount) {
|
|
142
|
+
const lastCol = "ABCDEFGHIJKLMN"[ISSUES_COL_COUNT - 1];
|
|
143
|
+
const ref = `A1:${lastCol}${rowCount}`;
|
|
144
|
+
const cols = ISSUES_COL_NAMES.map((name, i) => `<tableColumn id="${i + 1}" name="${name}"/>`).join("");
|
|
145
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
146
|
+
`<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"` +
|
|
147
|
+
` id="${ISSUES_TABLE_ID}" name="IssuesTable" displayName="IssuesTable" ref="${ref}" headerRowCount="1">` +
|
|
148
|
+
`<autoFilter ref="${ref}"/>` +
|
|
149
|
+
`<tableColumns count="${ISSUES_COL_COUNT}">${cols}</tableColumns>` +
|
|
150
|
+
`<tableStyleInfo name="TableStyleMedium2" showFirstColumn="0"` +
|
|
151
|
+
` showLastColumn="0" showRowStripes="1" showColumnStripes="0"/>` +
|
|
152
|
+
`</table>`;
|
|
153
|
+
}
|
|
154
|
+
function injectTableIntoFile(filePath, issueRowCount) {
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
let AdmZip;
|
|
157
|
+
try {
|
|
158
|
+
// webpackIgnore prevents Cypress/webpack from trying to bundle this Node-only module.
|
|
159
|
+
// The try/catch ensures graceful degradation if adm-zip is not installed.
|
|
160
|
+
AdmZip = require(/* webpackIgnore: true */ "adm-zip");
|
|
161
|
+
}
|
|
162
|
+
catch (_a) {
|
|
163
|
+
// adm-zip not available — skip table injection gracefully
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const zip = new AdmZip(filePath);
|
|
167
|
+
// 1. Add xl/tables/table1.xml
|
|
168
|
+
const tableXml = buildTableXml(issueRowCount);
|
|
169
|
+
zip.addFile(`xl/tables/table${ISSUES_TABLE_ID}.xml`, Buffer.from(tableXml, "utf8"));
|
|
170
|
+
// 2. Patch xl/worksheets/_rels/sheet4.xml.rels
|
|
171
|
+
const relsPath = `xl/worksheets/_rels/sheet${ISSUES_SHEET_ID}.xml.rels`;
|
|
172
|
+
const relsEntry = zip.getEntry(relsPath);
|
|
173
|
+
const tableRel = `<Relationship Id="rIdTbl"` +
|
|
174
|
+
` Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"` +
|
|
175
|
+
` Target="../tables/table${ISSUES_TABLE_ID}.xml"/>`;
|
|
176
|
+
if (relsEntry) {
|
|
177
|
+
const existing = relsEntry.getData().toString("utf8");
|
|
178
|
+
zip.updateFile(relsPath, Buffer.from(existing.replace("</Relationships>", tableRel + "</Relationships>"), "utf8"));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
zip.addFile(relsPath, Buffer.from(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>` +
|
|
182
|
+
`<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">` +
|
|
183
|
+
tableRel + `</Relationships>`, "utf8"));
|
|
184
|
+
}
|
|
185
|
+
// 3. Patch xl/worksheets/sheet4.xml — add <tableParts> before </worksheet>
|
|
186
|
+
const sheetPath = `xl/worksheets/sheet${ISSUES_SHEET_ID}.xml`;
|
|
187
|
+
const sheetXml = zip.getEntry(sheetPath).getData().toString("utf8");
|
|
188
|
+
zip.updateFile(sheetPath, Buffer.from(sheetXml.replace("</worksheet>", `<tableParts count="1"><tablePart r:id="rIdTbl"/></tableParts></worksheet>`), "utf8"));
|
|
189
|
+
// 4. Patch [Content_Types].xml
|
|
190
|
+
const ctPath = "[Content_Types].xml";
|
|
191
|
+
const ctXml = zip.getEntry(ctPath).getData().toString("utf8");
|
|
192
|
+
zip.updateFile(ctPath, Buffer.from(ctXml.replace("</Types>", `<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"` +
|
|
193
|
+
` PartName="/xl/tables/table${ISSUES_TABLE_ID}.xml"/></Types>`), "utf8"));
|
|
194
|
+
zip.writeZip(filePath);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
95
197
|
class ACReporterXLSX {
|
|
96
198
|
name() {
|
|
97
199
|
return "xlsx";
|
|
@@ -119,7 +221,6 @@ class ACReporterXLSX {
|
|
|
119
221
|
policyInfo[ruleId].tkLevels = dropDupes(policyInfo[ruleId].tkLevels);
|
|
120
222
|
policyInfo[ruleId].tkLevels.sort();
|
|
121
223
|
}
|
|
122
|
-
// const buffer: any = await workbook.xlsx.writeBuffer();
|
|
123
224
|
let startScan = new Date(storedReport.engineReport.summary.startScan);
|
|
124
225
|
let reportFilename = `results_${startScan.toISOString().replace(/:/g, "-")}.xlsx`;
|
|
125
226
|
if (config.outputFilenameTimestamp === false) {
|
|
@@ -128,35 +229,34 @@ class ACReporterXLSX {
|
|
|
128
229
|
return {
|
|
129
230
|
summaryPath: reportFilename,
|
|
130
231
|
summary: (filename) => __awaiter(this, void 0, void 0, function* () {
|
|
131
|
-
const
|
|
132
|
-
if (!
|
|
133
|
-
|
|
232
|
+
const writeExcelFile = yield loadWriteExcel();
|
|
233
|
+
if (!writeExcelFile) {
|
|
234
|
+
showWriteExcelWarning();
|
|
134
235
|
return;
|
|
135
236
|
}
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
237
|
+
const issuesSheet = ACReporterXLSX.createIssuesSheet(config, policyInfo, summaryData);
|
|
238
|
+
const issueRowCount = issuesSheet._issueRowCount;
|
|
239
|
+
delete issuesSheet._issueRowCount;
|
|
240
|
+
const sheets = [
|
|
241
|
+
ACReporterXLSX.createOverviewSheet(config, summaryData),
|
|
242
|
+
ACReporterXLSX.createScanSummarySheet(config, summaryData),
|
|
243
|
+
ACReporterXLSX.createIssueSummarySheet(config, policyInfo, summaryData),
|
|
244
|
+
issuesSheet,
|
|
245
|
+
ACReporterXLSX.createDefinitionsSheet(),
|
|
246
|
+
];
|
|
247
|
+
yield writeExcelFile(sheets).toFile(filename);
|
|
248
|
+
yield injectTableIntoFile(filename, issueRowCount);
|
|
145
249
|
})
|
|
146
250
|
};
|
|
147
251
|
});
|
|
148
252
|
}
|
|
149
|
-
static createOverviewSheet(config, compressedScans
|
|
253
|
+
static createOverviewSheet(config, compressedScans) {
|
|
150
254
|
let violations = 0;
|
|
151
255
|
let needsReviews = 0;
|
|
152
256
|
let recommendations = 0;
|
|
153
257
|
let archived = 0;
|
|
154
258
|
let totalIssues = 0;
|
|
155
259
|
let startScan = 0;
|
|
156
|
-
// BIG QUESTION: is report
|
|
157
|
-
// 1. for current scan (from menu)
|
|
158
|
-
// 2. all stored scans (from menu)
|
|
159
|
-
// 3. selected stored scans (from scan manager)
|
|
160
260
|
for (const compressedScan of compressedScans) {
|
|
161
261
|
let storedScan = ReporterManager_js_1.ReporterManager.uncompressReport(compressedScan);
|
|
162
262
|
if (startScan === 0)
|
|
@@ -168,311 +268,147 @@ class ACReporterXLSX {
|
|
|
168
268
|
archived += counts.ignored;
|
|
169
269
|
}
|
|
170
270
|
totalIssues = violations + needsReviews + recommendations + archived;
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
cellA1.value = "Accessibility Scan Report";
|
|
178
|
-
cellA1.alignment = { vertical: "middle", horizontal: "left" };
|
|
179
|
-
cellA1.font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 16 };
|
|
180
|
-
cellA1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
181
|
-
// what are column widths - can't get it till you set it
|
|
182
|
-
const colWidthData = [
|
|
183
|
-
{ col: 'A', width: 15.1 },
|
|
184
|
-
{ col: 'B', width: 15.9 },
|
|
185
|
-
{ col: 'C', width: 16.23 },
|
|
186
|
-
{ col: 'D', width: 19.4 },
|
|
271
|
+
const columns = [
|
|
272
|
+
{ width: 15.1 },
|
|
273
|
+
{ width: 15.9 },
|
|
274
|
+
{ width: 16.23 },
|
|
275
|
+
{ width: 19.4 },
|
|
276
|
+
{ width: 15 },
|
|
187
277
|
];
|
|
188
|
-
for (let i = 0; i < 4; i++) {
|
|
189
|
-
worksheet.getColumn(colWidthData[i].col).width = colWidthData[i].width;
|
|
190
|
-
}
|
|
191
|
-
// note except for Report Date this is the same for all scans
|
|
192
278
|
const rowData = [
|
|
193
279
|
{ key1: 'Tool:', key2: 'IBM Equal Access Accessibility Checker' },
|
|
194
|
-
// {key1: 'Version:', key2: "chrome.runtime.getManifest().version"},
|
|
195
280
|
{ key1: 'Version:', key2: config.toolID },
|
|
196
|
-
//@ts-ignore
|
|
197
|
-
// {key1: 'Rule set:', key2: (theCurrentScan.ruleSet === "Latest Deployment") ? archives[1].name : theCurrentScan.ruleSet },
|
|
198
281
|
{ key1: 'Rule set:', key2: config.ruleArchiveLabel },
|
|
199
282
|
{ key1: 'Guidelines:', key2: config.policies.join(", ") },
|
|
200
|
-
{ key1: 'Report date:', key2: new Date(startScan).toLocaleString() },
|
|
201
|
-
{ key1: 'Scans:', key2: "" + compressedScans.length },
|
|
202
|
-
// { key1: 'Pages:', key2: "" }
|
|
283
|
+
{ key1: 'Report date:', key2: new Date(startScan).toLocaleString() },
|
|
284
|
+
{ key1: 'Scans:', key2: "" + compressedScans.length },
|
|
203
285
|
];
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
worksheet.getRow(i).getCell(2).value = rowData[i - 2].key2;
|
|
218
|
-
}
|
|
219
|
-
// Summary Title
|
|
220
|
-
worksheet.mergeCells('A11', "E11");
|
|
221
|
-
const summaryRow = worksheet.getRow(11);
|
|
222
|
-
summaryRow.height = 27;
|
|
223
|
-
const cellA11 = worksheet.getCell('A11');
|
|
224
|
-
cellA11.value = "Summary";
|
|
225
|
-
cellA11.alignment = { vertical: "middle", horizontal: "left" };
|
|
226
|
-
cellA11.font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 16 };
|
|
227
|
-
cellA11.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
228
|
-
// Scans info Headers
|
|
229
|
-
worksheet.getRow(12).height = 16; // actual height is
|
|
230
|
-
const cellA12 = worksheet.getCell('A12');
|
|
231
|
-
cellA12.value = "Total issues";
|
|
232
|
-
const cellB12 = worksheet.getCell('B12');
|
|
233
|
-
cellB12.value = "Violations";
|
|
234
|
-
const cellC12 = worksheet.getCell('C12');
|
|
235
|
-
cellC12.value = "Needs review";
|
|
236
|
-
const cellD12 = worksheet.getCell('D12');
|
|
237
|
-
cellD12.value = "Recommendations";
|
|
238
|
-
const cellE12 = worksheet.getCell('E12');
|
|
239
|
-
cellE12.value = "Archived";
|
|
240
|
-
const cellObjects1 = [cellA12, cellB12, cellC12, cellD12, cellE12];
|
|
241
|
-
for (let i = 0; i < cellObjects1.length; i++) {
|
|
242
|
-
cellObjects1[i].alignment = { vertical: "middle", horizontal: "center" };
|
|
243
|
-
if (i == 1 || i == 2 || i == 3 || i === 4) {
|
|
244
|
-
cellObjects1[i].font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
cellObjects1[i].font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 12 };
|
|
248
|
-
}
|
|
249
|
-
// cellObjects1[i].fill = { type: 'pattern', pattern: 'solid', fgColor:{argb:'FFC65911'} };
|
|
250
|
-
cellObjects1[i].border = {
|
|
251
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
252
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
253
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
254
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
cellA12.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF000000' } };
|
|
258
|
-
cellB12.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE4AAAF' } };
|
|
259
|
-
cellC12.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF4E08A' } };
|
|
260
|
-
cellD12.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF96A9D7' } };
|
|
261
|
-
// Scans info Values
|
|
262
|
-
worksheet.getRow(13).height = 27; // actual height is
|
|
263
|
-
const cellA13 = worksheet.getCell('A13');
|
|
264
|
-
cellA13.value = totalIssues;
|
|
265
|
-
const cellB13 = worksheet.getCell('B13');
|
|
266
|
-
cellB13.value = violations;
|
|
267
|
-
const cellC13 = worksheet.getCell('C13');
|
|
268
|
-
cellC13.value = needsReviews;
|
|
269
|
-
const cellD13 = worksheet.getCell('D13');
|
|
270
|
-
cellD13.value = recommendations;
|
|
271
|
-
const cellE13 = worksheet.getCell('E13');
|
|
272
|
-
cellE13.value = archived;
|
|
273
|
-
const cellObjects2 = [cellA13, cellB13, cellC13, cellD13, cellE13];
|
|
274
|
-
for (let i = 0; i < cellObjects2.length; i++) {
|
|
275
|
-
cellObjects2[i].alignment = { vertical: "middle", horizontal: "center" };
|
|
276
|
-
cellObjects2[i].font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
277
|
-
// cellObjects2[i].fill = { type: 'pattern', pattern: 'solid', fgColor:{argb:'FFf8cbad'} };
|
|
278
|
-
cellObjects2[i].border = {
|
|
279
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
280
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
281
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
282
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
283
|
-
};
|
|
286
|
+
const data = [];
|
|
287
|
+
// Row 1: Title spanning 5 cols
|
|
288
|
+
data.push([
|
|
289
|
+
{ value: "Accessibility Scan Report", backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "left", height: 27, columnSpan: 5 },
|
|
290
|
+
null, null, null, null
|
|
291
|
+
]);
|
|
292
|
+
// Rows 2–7: metadata key/value pairs
|
|
293
|
+
for (const row of rowData) {
|
|
294
|
+
data.push([
|
|
295
|
+
dataCell(row.key1, { align: "left", height: 12 }),
|
|
296
|
+
{ value: row.key2, fontFamily: "Calibri", fontSize: 12, textColor: "#000000", align: "left", columnSpan: 4 },
|
|
297
|
+
null, null, null
|
|
298
|
+
]);
|
|
284
299
|
}
|
|
300
|
+
// Row 8: blank spacer
|
|
301
|
+
data.push([null]);
|
|
302
|
+
// Row 9: blank spacer
|
|
303
|
+
data.push([null]);
|
|
304
|
+
// Row 10: blank spacer
|
|
305
|
+
data.push([null]);
|
|
306
|
+
// Row 11: "Summary" title spanning 5 cols
|
|
307
|
+
data.push([
|
|
308
|
+
{ value: "Summary", backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "left", height: 27, columnSpan: 5 },
|
|
309
|
+
null, null, null, null
|
|
310
|
+
]);
|
|
311
|
+
// Row 12: column headers
|
|
312
|
+
data.push([
|
|
313
|
+
borderedCell("Total issues", { align: "center", alignVertical: "center", backgroundColor: "#000000", textColor: "#FFFFFF", height: 16 }),
|
|
314
|
+
borderedCell("Violations", { align: "center", alignVertical: "center", backgroundColor: "#E4AAAF", textColor: "#000000" }),
|
|
315
|
+
borderedCell("Needs review", { align: "center", alignVertical: "center", backgroundColor: "#F4E08A", textColor: "#000000" }),
|
|
316
|
+
borderedCell("Recommendations", { align: "center", alignVertical: "center", backgroundColor: "#96A9D7", textColor: "#000000" }),
|
|
317
|
+
borderedCell("Archived", { align: "center", alignVertical: "center", backgroundColor: "#FFFFFF", textColor: "#000000" }),
|
|
318
|
+
]);
|
|
319
|
+
// Row 13: values
|
|
320
|
+
data.push([
|
|
321
|
+
borderedCell(totalIssues, { align: "center", alignVertical: "center", height: 27 }),
|
|
322
|
+
borderedCell(violations, { align: "center", alignVertical: "center" }),
|
|
323
|
+
borderedCell(needsReviews, { align: "center", alignVertical: "center" }),
|
|
324
|
+
borderedCell(recommendations, { align: "center", alignVertical: "center" }),
|
|
325
|
+
borderedCell(archived, { align: "center", alignVertical: "center" }),
|
|
326
|
+
]);
|
|
327
|
+
return { data, sheet: "Overview", columns };
|
|
285
328
|
}
|
|
286
|
-
static createScanSummarySheet(config, compressedScans
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
{
|
|
292
|
-
{
|
|
293
|
-
{
|
|
294
|
-
{
|
|
295
|
-
{
|
|
296
|
-
{
|
|
297
|
-
{ col: 'G', width: 17.17 },
|
|
298
|
-
{ col: 'H', width: 17.17 },
|
|
299
|
-
{ col: 'I', width: 17.17 },
|
|
329
|
+
static createScanSummarySheet(config, compressedScans) {
|
|
330
|
+
const columns = [
|
|
331
|
+
{ width: 27.0 },
|
|
332
|
+
{ width: 46.0 },
|
|
333
|
+
{ width: 20.17 },
|
|
334
|
+
{ width: 18.5 },
|
|
335
|
+
{ width: 17.17 },
|
|
336
|
+
{ width: 17.17 },
|
|
337
|
+
{ width: 17.17 },
|
|
338
|
+
{ width: 17.17 },
|
|
339
|
+
{ width: 17.17 },
|
|
300
340
|
];
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
317
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
318
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
319
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
const cellD1 = worksheet.getCell('D1');
|
|
323
|
-
cellD1.value = "Violations";
|
|
324
|
-
const cellE1 = worksheet.getCell('E1');
|
|
325
|
-
cellE1.value = "Needs review";
|
|
326
|
-
const cellF1 = worksheet.getCell('F1');
|
|
327
|
-
cellF1.value = "Recommendations";
|
|
328
|
-
const cellG1 = worksheet.getCell('G1');
|
|
329
|
-
cellG1.value = "Archived";
|
|
330
|
-
const cellH1 = worksheet.getCell('H1');
|
|
331
|
-
cellH1.value = "% elements without violations";
|
|
332
|
-
const cellI1 = worksheet.getCell('I1');
|
|
333
|
-
cellI1.value = "% elements without violations or items to review";
|
|
334
|
-
const cellObjects2 = [cellD1, cellE1, cellF1, cellG1, cellH1, cellI1];
|
|
335
|
-
for (let i = 0; i < cellObjects2.length; i++) {
|
|
336
|
-
cellObjects2[i].alignment = { vertical: "middle", horizontal: "center", wrapText: true };
|
|
337
|
-
if (i == 0 || i == 1 || i == 2 || i == 3) {
|
|
338
|
-
cellObjects2[i].font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
cellObjects2[i].font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 12 };
|
|
342
|
-
}
|
|
343
|
-
// cellObjects2[i].fill = { type: 'pattern', pattern: 'solid', fgColor:{argb:'FFC65911'} };
|
|
344
|
-
cellObjects2[i].border = {
|
|
345
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
346
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
347
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
348
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
cellD1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFE4AAAF' } };
|
|
352
|
-
cellE1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF4E08A' } };
|
|
353
|
-
cellF1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF96A9D7' } };
|
|
354
|
-
cellG1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFFFFFFF' } };
|
|
355
|
-
cellH1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF000000' } };
|
|
356
|
-
cellI1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF000000' } };
|
|
341
|
+
const headerStyle = { backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 12, borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", height: 39 };
|
|
342
|
+
const countHeaderStyle = Object.assign(Object.assign({}, headerStyle), { align: "center", wrap: true });
|
|
343
|
+
const data = [];
|
|
344
|
+
// Row 1: header row
|
|
345
|
+
data.push([
|
|
346
|
+
Object.assign(Object.assign({ value: "Page title" }, headerStyle), { align: "left" }),
|
|
347
|
+
Object.assign(Object.assign({ value: "Page url" }, headerStyle), { align: "left" }),
|
|
348
|
+
Object.assign(Object.assign({ value: "Scan label" }, headerStyle), { align: "left" }),
|
|
349
|
+
Object.assign(Object.assign({ value: "Violations" }, countHeaderStyle), { backgroundColor: "#E4AAAF", textColor: "#000000" }),
|
|
350
|
+
Object.assign(Object.assign({ value: "Needs review" }, countHeaderStyle), { backgroundColor: "#F4E08A", textColor: "#000000" }),
|
|
351
|
+
Object.assign(Object.assign({ value: "Recommendations" }, countHeaderStyle), { backgroundColor: "#96A9D7", textColor: "#000000" }),
|
|
352
|
+
Object.assign(Object.assign({ value: "Archived" }, countHeaderStyle), { backgroundColor: "#FFFFFF", textColor: "#000000" }),
|
|
353
|
+
Object.assign({ value: "% elements without violations" }, countHeaderStyle),
|
|
354
|
+
Object.assign({ value: "% elements without violations or items to review" }, countHeaderStyle),
|
|
355
|
+
]);
|
|
357
356
|
for (const compressedScan of compressedScans) {
|
|
358
357
|
let storedScan = ReporterManager_js_1.ReporterManager.uncompressReport(compressedScan);
|
|
359
358
|
let counts = storedScan.engineReport.summary.counts;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
storedScan.
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
counts.
|
|
368
|
-
(
|
|
369
|
-
(
|
|
359
|
+
const textStyle = { fontFamily: "Calibri", fontSize: 12, textColor: "#000000", alignVertical: "center", height: 37, wrap: true };
|
|
360
|
+
const numStyle = Object.assign(Object.assign({}, textStyle), { align: "center", borderColor: "#A6A6A6", borderStyle: "thin" });
|
|
361
|
+
data.push([
|
|
362
|
+
Object.assign(Object.assign({ value: storedScan.pageTitle }, textStyle), { align: "left" }),
|
|
363
|
+
Object.assign(Object.assign({ value: storedScan.engineReport.summary.URL }, textStyle), { align: "left" }),
|
|
364
|
+
Object.assign(Object.assign({ value: storedScan.label }, textStyle), { align: "left" }),
|
|
365
|
+
Object.assign({ value: counts.violation }, numStyle),
|
|
366
|
+
Object.assign({ value: counts.potentialviolation + counts.manual }, numStyle),
|
|
367
|
+
Object.assign({ value: counts.recommendation + counts.potentialrecommendation }, numStyle),
|
|
368
|
+
Object.assign({ value: counts.ignored }, numStyle),
|
|
369
|
+
Object.assign({ value: counts.elements > 0 ? parseFloat((100 * (counts.elements - counts.elementsViolation) / counts.elements).toFixed(0)) : 0 }, numStyle),
|
|
370
|
+
Object.assign({ value: counts.elements > 0 ? parseFloat((100 * (counts.elements - counts.elementsViolationReview) / counts.elements).toFixed(0)) : 0 }, numStyle),
|
|
370
371
|
]);
|
|
371
|
-
row.height = 37; // actual height is
|
|
372
|
-
for (let i = 1; i < 4; i++) {
|
|
373
|
-
row.getCell(i).alignment = { vertical: "middle", horizontal: "left", wrapText: true };
|
|
374
|
-
row.getCell(i).font = { name: "Calibri", color: { argb: "00000000" }, size: 12 };
|
|
375
|
-
}
|
|
376
|
-
for (let i = 4; i < 10; i++) {
|
|
377
|
-
row.getCell(i).alignment = { vertical: "middle", horizontal: "center", wrapText: true };
|
|
378
|
-
row.getCell(i).font = { name: "Calibri", color: { argb: "00000000" }, size: 12 };
|
|
379
|
-
// row.getCell(i).fill = { type: 'pattern', pattern: 'solid', fgColor:{argb:'FFf8cbad'} };
|
|
380
|
-
row.getCell(i).border = {
|
|
381
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
382
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
383
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
384
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
row.commit();
|
|
388
372
|
}
|
|
389
|
-
|
|
373
|
+
return { data, sheet: "Scan summary", columns };
|
|
390
374
|
}
|
|
391
|
-
static
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
level1ViolationRow.getCell(1).border = {
|
|
401
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
402
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
403
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
404
|
-
// right: {style:'thin', color: {argb: 'FFA6A6A6'}}
|
|
405
|
-
};
|
|
406
|
-
const cellB6 = level1ViolationRow.getCell(2);
|
|
407
|
-
cellB6.value = levelCount; // total level violations
|
|
408
|
-
cellB6.alignment = { vertical: "middle", horizontal: "right" };
|
|
409
|
-
cellB6.font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
410
|
-
cellB6.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: fillColor } };
|
|
411
|
-
level1ViolationRow.getCell(2).border = {
|
|
412
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
413
|
-
// left: {style:'thin', color: {argb: 'FFA6A6A6'}},
|
|
414
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
415
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
416
|
-
};
|
|
417
|
-
// Level 1 Violation Rows
|
|
418
|
-
// build rows
|
|
419
|
-
let rowArray = [];
|
|
420
|
-
// let row:any =[];
|
|
375
|
+
static buildIssueSummaryLevelRows(fillColor, textColor, title, levelCount, levelrowValues) {
|
|
376
|
+
const rows = [];
|
|
377
|
+
// Level type title row (e.g. "Violations")
|
|
378
|
+
rows.push([
|
|
379
|
+
{ value: ` ${title}`, backgroundColor: fillColor, textColor, fontFamily: "Calibri", fontSize: 12, borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", align: "left", height: 18 },
|
|
380
|
+
{ value: levelCount, backgroundColor: fillColor, textColor, fontFamily: "Calibri", fontSize: 12, borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", align: "right" },
|
|
381
|
+
]);
|
|
382
|
+
// Individual issue message rows, sorted descending by count
|
|
383
|
+
const rowArray = [];
|
|
421
384
|
for (const property in levelrowValues) {
|
|
422
|
-
|
|
423
|
-
];
|
|
424
|
-
rowArray.push(row);
|
|
385
|
+
rowArray.push([" " + property, parseInt(`${levelrowValues[property]}`)]);
|
|
425
386
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
row.getCell(1).alignment = { vertical: "middle", horizontal: "left" };
|
|
433
|
-
row.getCell(2).alignment = { vertical: "middle", horizontal: "right" };
|
|
434
|
-
row.font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
435
|
-
// row.getCell(1).fill = { type: 'pattern', pattern: 'solid', fgColor:{argb:'FFf8cbad'} };
|
|
436
|
-
// row.getCell(2).fill = { type: 'pattern', pattern: 'solid', fgColor:{argb:'FFf8cbad'} };
|
|
437
|
-
row.getCell(1).border = {
|
|
438
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
439
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
440
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
441
|
-
// right: {style:'thin', color: {argb: 'FFA6A6A6'}}
|
|
442
|
-
};
|
|
443
|
-
row.getCell(2).border = {
|
|
444
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
445
|
-
// left: {style:'thin', color: {argb: 'FFA6A6A6'}},
|
|
446
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
447
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
448
|
-
};
|
|
449
|
-
row.commit();
|
|
387
|
+
rowArray.sort((a, b) => b[1] - a[1]);
|
|
388
|
+
for (const [msg, count] of rowArray) {
|
|
389
|
+
rows.push([
|
|
390
|
+
{ value: msg, fontFamily: "Calibri", fontSize: 12, textColor: "#000000", borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", align: "left", height: 14 },
|
|
391
|
+
{ value: count, fontFamily: "Calibri", fontSize: 12, textColor: "#000000", borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", align: "right" },
|
|
392
|
+
]);
|
|
450
393
|
}
|
|
394
|
+
return rows;
|
|
451
395
|
}
|
|
452
|
-
static
|
|
453
|
-
|
|
454
|
-
//
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
cellA5.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
463
|
-
const cellB5 = level1Row.getCell(2);
|
|
464
|
-
cellB5.value = levelCounts[0]; // total Level 1 issues
|
|
465
|
-
cellB5.alignment = { vertical: "middle", horizontal: "right" };
|
|
466
|
-
cellB5.font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 16 };
|
|
467
|
-
cellB5.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
468
|
-
ACReporterXLSX.buildIssueSummaryLevel(worksheet, "FFE4AAAF", "Violation", levelCounts[1], levelVrowValues);
|
|
469
|
-
ACReporterXLSX.buildIssueSummaryLevel(worksheet, "FFF4E08A", "Needs review", levelCounts[2], levelNRrowValues);
|
|
470
|
-
ACReporterXLSX.buildIssueSummaryLevel(worksheet, "FF96A9D7", "Recommendation", levelCounts[3], levelRrowValues);
|
|
396
|
+
static buildIssueSummaryTKLevelRows(title, levelCounts, levelVrowValues, levelNRrowValues, levelRrowValues, levelArowValues) {
|
|
397
|
+
const rows = [];
|
|
398
|
+
// Level title row (e.g. "Level 1 - the most essential...")
|
|
399
|
+
rows.push([
|
|
400
|
+
{ value: title, backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "left", height: 27 },
|
|
401
|
+
{ value: levelCounts[0], backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "right" },
|
|
402
|
+
]);
|
|
403
|
+
rows.push(...ACReporterXLSX.buildIssueSummaryLevelRows("#E4AAAF", "#000000", "Violation", levelCounts[1], levelVrowValues));
|
|
404
|
+
rows.push(...ACReporterXLSX.buildIssueSummaryLevelRows("#F4E08A", "#000000", "Needs review", levelCounts[2], levelNRrowValues));
|
|
405
|
+
rows.push(...ACReporterXLSX.buildIssueSummaryLevelRows("#96A9D7", "#000000", "Recommendation", levelCounts[3], levelRrowValues));
|
|
471
406
|
if (levelCounts[4] > 0) {
|
|
472
|
-
ACReporterXLSX.
|
|
407
|
+
rows.push(...ACReporterXLSX.buildIssueSummaryLevelRows("#CCCCCC", "#000000", "Archived", levelCounts[4], levelArowValues));
|
|
473
408
|
}
|
|
409
|
+
return rows;
|
|
474
410
|
}
|
|
475
|
-
static createIssueSummarySheet(config, policyInfo, compressedScans
|
|
411
|
+
static createIssueSummarySheet(config, policyInfo, compressedScans) {
|
|
476
412
|
let violations = 0;
|
|
477
413
|
let needsReviews = 0;
|
|
478
414
|
let recommendations = 0;
|
|
@@ -487,8 +423,7 @@ class ACReporterXLSX {
|
|
|
487
423
|
archive += counts.ignored;
|
|
488
424
|
}
|
|
489
425
|
totalIssues = violations + needsReviews + recommendations;
|
|
490
|
-
|
|
491
|
-
let level1Counts = [0, 0, 0, 0, 0]; // level 1 total issues, violations, needs reviews, recommendations
|
|
426
|
+
let level1Counts = [0, 0, 0, 0, 0];
|
|
492
427
|
let level2Counts = [0, 0, 0, 0, 0];
|
|
493
428
|
let level3Counts = [0, 0, 0, 0, 0];
|
|
494
429
|
let level4Counts = [0, 0, 0, 0, 0];
|
|
@@ -512,10 +447,7 @@ class ACReporterXLSX {
|
|
|
512
447
|
let scan = ReporterManager_js_1.ReporterManager.uncompressReport(compressedScan);
|
|
513
448
|
for (const issue of scan.engineReport.results) {
|
|
514
449
|
if (!(issue.ruleId in policyInfo)) {
|
|
515
|
-
policyInfo[issue.ruleId] = {
|
|
516
|
-
tkLevels: [],
|
|
517
|
-
cps: []
|
|
518
|
-
};
|
|
450
|
+
policyInfo[issue.ruleId] = { tkLevels: [], cps: [] };
|
|
519
451
|
}
|
|
520
452
|
let levelCounts, levelV, levelNR, levelR, levelA;
|
|
521
453
|
const issuePolicyInfo = policyInfo[issue.ruleId];
|
|
@@ -569,111 +501,69 @@ class ACReporterXLSX {
|
|
|
569
501
|
}
|
|
570
502
|
}
|
|
571
503
|
// @ts-ignore
|
|
572
|
-
let level1VrowValues =
|
|
504
|
+
let level1VrowValues = ACReporterXLSX.countDuplicatesInArray(level1V);
|
|
573
505
|
// @ts-ignore
|
|
574
|
-
let level1NRrowValues =
|
|
506
|
+
let level1NRrowValues = ACReporterXLSX.countDuplicatesInArray(level1NR);
|
|
575
507
|
// @ts-ignore
|
|
576
|
-
let level1RrowValues =
|
|
508
|
+
let level1RrowValues = ACReporterXLSX.countDuplicatesInArray(level1R);
|
|
577
509
|
// @ts-ignore
|
|
578
|
-
let level1ArowValues =
|
|
510
|
+
let level1ArowValues = ACReporterXLSX.countDuplicatesInArray(level1A);
|
|
579
511
|
// @ts-ignore
|
|
580
|
-
let level2VrowValues =
|
|
512
|
+
let level2VrowValues = ACReporterXLSX.countDuplicatesInArray(level2V);
|
|
581
513
|
// @ts-ignore
|
|
582
|
-
let level2NRrowValues =
|
|
514
|
+
let level2NRrowValues = ACReporterXLSX.countDuplicatesInArray(level2NR);
|
|
583
515
|
// @ts-ignore
|
|
584
|
-
let level2RrowValues =
|
|
516
|
+
let level2RrowValues = ACReporterXLSX.countDuplicatesInArray(level2R);
|
|
585
517
|
// @ts-ignore
|
|
586
|
-
let level2ArowValues =
|
|
518
|
+
let level2ArowValues = ACReporterXLSX.countDuplicatesInArray(level2A);
|
|
587
519
|
// @ts-ignore
|
|
588
|
-
let level3VrowValues =
|
|
520
|
+
let level3VrowValues = ACReporterXLSX.countDuplicatesInArray(level3V);
|
|
589
521
|
// @ts-ignore
|
|
590
|
-
let level3NRrowValues =
|
|
522
|
+
let level3NRrowValues = ACReporterXLSX.countDuplicatesInArray(level3NR);
|
|
591
523
|
// @ts-ignore
|
|
592
|
-
let level3RrowValues =
|
|
524
|
+
let level3RrowValues = ACReporterXLSX.countDuplicatesInArray(level3R);
|
|
593
525
|
// @ts-ignore
|
|
594
|
-
let level3ArowValues =
|
|
526
|
+
let level3ArowValues = ACReporterXLSX.countDuplicatesInArray(level3A);
|
|
595
527
|
// @ts-ignore
|
|
596
|
-
let level4VrowValues =
|
|
528
|
+
let level4VrowValues = ACReporterXLSX.countDuplicatesInArray(level4V);
|
|
597
529
|
// @ts-ignore
|
|
598
|
-
let level4NRrowValues =
|
|
530
|
+
let level4NRrowValues = ACReporterXLSX.countDuplicatesInArray(level4NR);
|
|
599
531
|
// @ts-ignore
|
|
600
|
-
let level4RrowValues =
|
|
532
|
+
let level4RrowValues = ACReporterXLSX.countDuplicatesInArray(level4R);
|
|
601
533
|
// @ts-ignore
|
|
602
|
-
let level4ArowValues =
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
// 2. for each level sort by V, NR and R
|
|
607
|
-
// 3. for each V, NR, and R in a level get issue dup counts
|
|
608
|
-
// 4. build the rows
|
|
609
|
-
// build Issue summary title
|
|
610
|
-
worksheet.mergeCells('A1', "B1");
|
|
611
|
-
const titleRow = worksheet.getRow(1);
|
|
612
|
-
titleRow.height = 27; // actual is 36
|
|
613
|
-
const cellA1 = worksheet.getCell('A1');
|
|
614
|
-
cellA1.value = "Issue summary";
|
|
615
|
-
cellA1.alignment = { vertical: "middle", horizontal: "left" };
|
|
616
|
-
cellA1.font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 16 };
|
|
617
|
-
cellA1.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
618
|
-
const colWidthData = [
|
|
619
|
-
{ col: 'A', width: 155.51 }, // note .84 added to actual width
|
|
620
|
-
{ col: 'B', width: 21.16 },
|
|
534
|
+
let level4ArowValues = ACReporterXLSX.countDuplicatesInArray(level4A);
|
|
535
|
+
const columns = [
|
|
536
|
+
{ width: 155.51 },
|
|
537
|
+
{ width: 21.16 },
|
|
621
538
|
];
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
//
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
// build Number of issues title
|
|
649
|
-
const numberOfIssuesRow = worksheet.getRow(4);
|
|
650
|
-
numberOfIssuesRow.height = 20.25; // actual is 27
|
|
651
|
-
const cellA4 = worksheet.getCell("A4");
|
|
652
|
-
// no value
|
|
653
|
-
cellA4.alignment = { vertical: "middle", horizontal: "left" };
|
|
654
|
-
cellA4.border = {
|
|
655
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
656
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
657
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
658
|
-
right: { style: 'thin', color: { argb: 'FFFFFFFF' } }
|
|
659
|
-
};
|
|
660
|
-
const cellB4 = worksheet.getCell("B4");
|
|
661
|
-
cellB4.value = "Number of issues";
|
|
662
|
-
cellB4.alignment = { vertical: "middle", horizontal: "right" };
|
|
663
|
-
cellB4.font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
664
|
-
cellB4.border = {
|
|
665
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
666
|
-
left: { style: 'thin', color: { argb: 'FFFFFFFF' } },
|
|
667
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
668
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
669
|
-
};
|
|
670
|
-
ACReporterXLSX.buildIssueSummaryTKLevel(worksheet, "Level 1 - the most essential issues to address", level1Counts, level1VrowValues, level1NRrowValues, level1RrowValues, level1ArowValues);
|
|
671
|
-
ACReporterXLSX.buildIssueSummaryTKLevel(worksheet, "Level 2 - the next most important issues", level2Counts, level2VrowValues, level2NRrowValues, level2RrowValues, level2ArowValues);
|
|
672
|
-
ACReporterXLSX.buildIssueSummaryTKLevel(worksheet, "Level 3 - necessary to meet requirements", level3Counts, level3VrowValues, level3NRrowValues, level3RrowValues, level3ArowValues);
|
|
673
|
-
ACReporterXLSX.buildIssueSummaryTKLevel(worksheet, "Level 4 - further recommended improvements to accessibility", level4Counts, level4VrowValues, level4NRrowValues, level4RrowValues, level4ArowValues);
|
|
674
|
-
worksheet.commit();
|
|
539
|
+
const data = [];
|
|
540
|
+
// Row 1: "Issue summary" title spanning 2 cols
|
|
541
|
+
data.push([
|
|
542
|
+
{ value: "Issue summary", backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "left", height: 27, columnSpan: 2 },
|
|
543
|
+
null
|
|
544
|
+
]);
|
|
545
|
+
// Row 2: description spanning 2 cols
|
|
546
|
+
data.push([
|
|
547
|
+
{ value: " In the IBM Equal Access Toolkit, issues are divided into three levels (1-3). Tackle the levels in order to address some of the most impactful issues first.", fontFamily: "Calibri", fontSize: 12, textColor: "#000000", alignVertical: "center", align: "left", height: 20, columnSpan: 2 },
|
|
548
|
+
null
|
|
549
|
+
]);
|
|
550
|
+
// Row 3: "Total issues found:" with value
|
|
551
|
+
data.push([
|
|
552
|
+
{ value: "Total issues found:", backgroundColor: "#000000", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "left", height: 27 },
|
|
553
|
+
{ value: totalIssues, backgroundColor: "#000000", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "right" },
|
|
554
|
+
]);
|
|
555
|
+
// Row 4: "Number of issues" label
|
|
556
|
+
data.push([
|
|
557
|
+
{ value: null, borderColor: "#A6A6A6", borderStyle: "thin", height: 20 },
|
|
558
|
+
{ value: "Number of issues", fontFamily: "Calibri", fontSize: 12, textColor: "#000000", borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", align: "right" },
|
|
559
|
+
]);
|
|
560
|
+
data.push(...ACReporterXLSX.buildIssueSummaryTKLevelRows("Level 1 - the most essential issues to address", level1Counts, level1VrowValues, level1NRrowValues, level1RrowValues, level1ArowValues));
|
|
561
|
+
data.push(...ACReporterXLSX.buildIssueSummaryTKLevelRows("Level 2 - the next most important issues", level2Counts, level2VrowValues, level2NRrowValues, level2RrowValues, level2ArowValues));
|
|
562
|
+
data.push(...ACReporterXLSX.buildIssueSummaryTKLevelRows("Level 3 - necessary to meet requirements", level3Counts, level3VrowValues, level3NRrowValues, level3RrowValues, level3ArowValues));
|
|
563
|
+
data.push(...ACReporterXLSX.buildIssueSummaryTKLevelRows("Level 4 - further recommended improvements to accessibility", level4Counts, level4VrowValues, level4NRrowValues, level4RrowValues, level4ArowValues));
|
|
564
|
+
return { data, sheet: "Issue summary", columns };
|
|
675
565
|
}
|
|
676
|
-
static createIssuesSheet(config, policyInfo, compressedScans
|
|
566
|
+
static createIssuesSheet(config, policyInfo, compressedScans) {
|
|
677
567
|
const valueMap = {
|
|
678
568
|
"VIOLATION": {
|
|
679
569
|
"POTENTIAL": "Needs review",
|
|
@@ -694,17 +584,48 @@ class ACReporterXLSX {
|
|
|
694
584
|
"MANUAL": "Recommendation"
|
|
695
585
|
}
|
|
696
586
|
};
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
587
|
+
const columns = [
|
|
588
|
+
{ width: 18.0 },
|
|
589
|
+
{ width: 20.5 },
|
|
590
|
+
{ width: 21.0 },
|
|
591
|
+
{ width: 18.5 },
|
|
592
|
+
{ width: 17.0 },
|
|
593
|
+
{ width: 17.17 },
|
|
594
|
+
{ width: 17.17 },
|
|
595
|
+
{ width: 17.17 },
|
|
596
|
+
{ width: 17.17 },
|
|
597
|
+
{ width: 17.17 },
|
|
598
|
+
{ width: 14.00 },
|
|
599
|
+
{ width: 17.17 },
|
|
600
|
+
{ width: 43.00 },
|
|
601
|
+
{ width: 17.17 },
|
|
602
|
+
];
|
|
603
|
+
// Header and data row colors are intentionally omitted — the Excel table
|
|
604
|
+
// (TableStyleMedium2 + showRowStripes) applied by injectTableIntoFile() provides all coloring.
|
|
605
|
+
const hStyle = { fontFamily: "Calibri", fontSize: 12, align: "center", alignVertical: "center", wrap: true, height: 24 };
|
|
606
|
+
const data = [];
|
|
607
|
+
// Header row
|
|
608
|
+
data.push([
|
|
609
|
+
Object.assign({ value: "Page title" }, hStyle),
|
|
610
|
+
Object.assign({ value: "Page URL" }, hStyle),
|
|
611
|
+
Object.assign({ value: "Scan label" }, hStyle),
|
|
612
|
+
Object.assign({ value: "Issue ID" }, hStyle),
|
|
613
|
+
Object.assign({ value: "Issue type" }, hStyle),
|
|
614
|
+
Object.assign({ value: "Toolkit level" }, hStyle),
|
|
615
|
+
Object.assign({ value: "Checkpoint" }, hStyle),
|
|
616
|
+
Object.assign({ value: "WCAG level" }, hStyle),
|
|
617
|
+
Object.assign({ value: "Rule" }, hStyle),
|
|
618
|
+
Object.assign({ value: "Issue" }, hStyle),
|
|
619
|
+
Object.assign({ value: "Element" }, hStyle),
|
|
620
|
+
Object.assign({ value: "Code" }, hStyle),
|
|
621
|
+
Object.assign({ value: "Xpath" }, hStyle),
|
|
622
|
+
Object.assign({ value: "Help" }, hStyle),
|
|
623
|
+
]);
|
|
700
624
|
for (const compressedScan of compressedScans) {
|
|
701
625
|
let storedScan = ReporterManager_js_1.ReporterManager.uncompressReport(compressedScan);
|
|
702
626
|
for (const item of storedScan.engineReport.results) {
|
|
703
627
|
if (!(item.ruleId in policyInfo)) {
|
|
704
|
-
policyInfo[item.ruleId] = {
|
|
705
|
-
tkLevels: [],
|
|
706
|
-
cps: []
|
|
707
|
-
};
|
|
628
|
+
policyInfo[item.ruleId] = { tkLevels: [], cps: [] };
|
|
708
629
|
}
|
|
709
630
|
let polInfo = policyInfo[item.ruleId];
|
|
710
631
|
let cps = polInfo.cps.filter(cp => {
|
|
@@ -715,195 +636,37 @@ class ACReporterXLSX {
|
|
|
715
636
|
wcagLevels.sort();
|
|
716
637
|
let cpStrs = dropDupes(cps.map(cp => `${cp.num} ${cp.name}`));
|
|
717
638
|
cpStrs.sort();
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
storedScan.
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
item.snippet
|
|
731
|
-
item.
|
|
732
|
-
item.
|
|
733
|
-
item.
|
|
734
|
-
|
|
735
|
-
];
|
|
736
|
-
// let row = [myStoredData[i][0], myStoredData[i][1], storedScans[j].label,
|
|
737
|
-
// myStoredData[i][3], myStoredData[i][4], Number.isNaN(myStoredData[i][5]) ? "n/a" : myStoredData[i][5],
|
|
738
|
-
// myStoredData[i][6], Number.isNaN(myStoredData[i][5]) ? "n/a" : myStoredData[i][7], myStoredData[i][8],
|
|
739
|
-
// myStoredData[i][9], myStoredData[i][10], myStoredData[i][11],
|
|
740
|
-
// myStoredData[i][12], myStoredData[i][13]
|
|
741
|
-
// ];
|
|
742
|
-
rowArray.push(row);
|
|
639
|
+
const dStyle = { fontFamily: "Calibri", fontSize: 12, height: 14 };
|
|
640
|
+
data.push([
|
|
641
|
+
Object.assign(Object.assign({ value: storedScan.pageTitle }, dStyle), { align: "left", alignVertical: "center" }),
|
|
642
|
+
Object.assign(Object.assign({ value: storedScan.engineReport.summary.URL }, dStyle), { align: "left", alignVertical: "center" }),
|
|
643
|
+
Object.assign(Object.assign({ value: storedScan.label }, dStyle), { align: "center", alignVertical: "center" }),
|
|
644
|
+
Object.assign(Object.assign({ value: ACReporterXLSX.stringHash(item.ruleId + item.path.dom) }, dStyle), { align: "left", alignVertical: "center" }),
|
|
645
|
+
Object.assign(Object.assign({ value: `${valueMap[item.value[0]][item.value[1]]}${item.ignored ? ` (Archived)` : ``}` }, dStyle), { align: "center", alignVertical: "center" }),
|
|
646
|
+
Object.assign(Object.assign({ value: polInfo.tkLevels.join(", ") }, dStyle), { align: "center", alignVertical: "center" }),
|
|
647
|
+
Object.assign(Object.assign({ value: cpStrs.join("; ") }, dStyle), { align: "left", alignVertical: "center" }),
|
|
648
|
+
Object.assign(Object.assign({ value: wcagLevels.join(", ") }, dStyle), { align: "center", alignVertical: "center" }),
|
|
649
|
+
Object.assign(Object.assign({ value: item.ruleId }, dStyle), { align: "left", alignVertical: "center" }),
|
|
650
|
+
Object.assign(Object.assign({ value: item.message.substring(0, 32767) }, dStyle), { align: "left", alignVertical: "center" }),
|
|
651
|
+
Object.assign(Object.assign({ value: ACReporterXLSX.get_element(item.snippet) }, dStyle), { align: "center", alignVertical: "center" }),
|
|
652
|
+
Object.assign(Object.assign({ value: item.snippet.substring(0, 32767) }, dStyle), { align: "left", alignVertical: "center" }),
|
|
653
|
+
Object.assign(Object.assign({ value: item.path.dom }, dStyle), { align: "left", alignVertical: "center" }),
|
|
654
|
+
Object.assign(Object.assign({ value: item.help }, dStyle), { align: "left", alignVertical: "center" }),
|
|
655
|
+
]);
|
|
743
656
|
}
|
|
744
657
|
}
|
|
745
|
-
|
|
746
|
-
const colWidthData = [
|
|
747
|
-
{ col: 'A', width: 18.0, alignment: { vertical: "middle", horizontal: "left" } },
|
|
748
|
-
{ col: 'B', width: 20.5, alignment: { vertical: "middle", horizontal: "left" } },
|
|
749
|
-
{ col: 'C', width: 21.0, alignment: { vertical: "middle", horizontal: "center" } },
|
|
750
|
-
{ col: 'D', width: 18.5, alignment: { vertical: "middle", horizontal: "left" } },
|
|
751
|
-
{ col: 'E', width: 17.0, alignment: { vertical: "middle", horizontal: "center" } },
|
|
752
|
-
{ col: 'F', width: 17.17, alignment: { vertical: "middle", horizontal: "center" } },
|
|
753
|
-
{ col: 'G', width: 17.17, alignment: { vertical: "middle", horizontal: "left" } },
|
|
754
|
-
{ col: 'H', width: 17.17, alignment: { vertical: "middle", horizontal: "center" } },
|
|
755
|
-
{ col: 'I', width: 17.17, alignment: { vertical: "middle", horizontal: "left" } },
|
|
756
|
-
{ col: 'J', width: 17.17, alignment: { vertical: "middle", horizontal: "left" } },
|
|
757
|
-
{ col: 'K', width: 14.00, alignment: { vertical: "middle", horizontal: "center" } },
|
|
758
|
-
{ col: 'L', width: 17.17, alignment: { vertical: "middle", horizontal: "left" } },
|
|
759
|
-
{ col: 'M', width: 43.00, alignment: { vertical: "middle", horizontal: "left" } },
|
|
760
|
-
{ col: 'N', width: 17.17, alignment: { vertical: "middle", horizontal: "fill" } },
|
|
761
|
-
];
|
|
762
|
-
for (let i = 0; i < 14; i++) {
|
|
763
|
-
worksheet.getColumn(colWidthData[i].col).width = colWidthData[i].width;
|
|
764
|
-
worksheet.getColumn(colWidthData[i].col).alignment = colWidthData[i].alignment;
|
|
765
|
-
}
|
|
766
|
-
// add table to a sheet
|
|
767
|
-
let headRow = worksheet.addRow([
|
|
768
|
-
"Page title",
|
|
769
|
-
"Page URL",
|
|
770
|
-
"Scan label",
|
|
771
|
-
"Issue ID",
|
|
772
|
-
"Issue type",
|
|
773
|
-
"Toolkit level",
|
|
774
|
-
"Checkpoint",
|
|
775
|
-
"WCAG level",
|
|
776
|
-
"Rule",
|
|
777
|
-
"Issue",
|
|
778
|
-
"Element",
|
|
779
|
-
"Code",
|
|
780
|
-
"Xpath",
|
|
781
|
-
"Help",
|
|
782
|
-
""
|
|
783
|
-
]);
|
|
784
|
-
// set font and alignment for the header cells
|
|
785
|
-
for (let i = 1; i < 15; i++) {
|
|
786
|
-
headRow.getCell(i).alignment = { vertical: "middle", horizontal: "center", wrapText: true };
|
|
787
|
-
headRow.getCell(i).font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 12 };
|
|
788
|
-
headRow.getCell(i).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
789
|
-
headRow.getCell(i).border = {
|
|
790
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
791
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
792
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
793
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
// height for header row
|
|
797
|
-
headRow.height = 24;
|
|
798
|
-
headRow.commit();
|
|
799
|
-
for (const rowInfo of rowArray) {
|
|
800
|
-
const row = worksheet.addRow(rowInfo);
|
|
801
|
-
row.height = 14;
|
|
802
|
-
for (let j = 1; j <= 14; j++) {
|
|
803
|
-
row.getCell(j).border = {
|
|
804
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
805
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
806
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
807
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
row.commit();
|
|
811
|
-
}
|
|
812
|
-
for (const key in worksheet) {
|
|
813
|
-
if (typeof worksheet[key] === "function") {
|
|
814
|
-
console.log(key);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
// worksheet.addTable({
|
|
818
|
-
// name: 'MyTable',
|
|
819
|
-
// ref: 'A1',
|
|
820
|
-
// headerRow: true,
|
|
821
|
-
// // totalsRow: true,
|
|
822
|
-
// style: {
|
|
823
|
-
// theme: 'TableStyleMedium2',
|
|
824
|
-
// showRowStripes: true,
|
|
825
|
-
// },
|
|
826
|
-
// columns: [
|
|
827
|
-
// { name: 'Page title', filterButton: true },
|
|
828
|
-
// { name: 'Page URL', filterButton: true },
|
|
829
|
-
// { name: 'Scan label', filterButton: true },
|
|
830
|
-
// { name: 'Issue ID', filterButton: true },
|
|
831
|
-
// { name: 'Issue type', filterButton: true },
|
|
832
|
-
// { name: 'Toolkit level', filterButton: true },
|
|
833
|
-
// { name: 'Checkpoint', filterButton: true },
|
|
834
|
-
// { name: 'WCAG level', filterButton: true },
|
|
835
|
-
// { name: 'Rule', filterButton: true },
|
|
836
|
-
// { name: 'Issue', filterButton: true },
|
|
837
|
-
// { name: 'Element', filterButton: true },
|
|
838
|
-
// { name: 'Code', filterButton: true },
|
|
839
|
-
// { name: 'Xpath', filterButton: true },
|
|
840
|
-
// { name: 'Help', filterButton: true },
|
|
841
|
-
// ],
|
|
842
|
-
// rows: rowArray
|
|
843
|
-
// });
|
|
844
|
-
// for (let i = 2; i <= rowArray.length + 1; i++) {
|
|
845
|
-
// worksheet.getRow(i).height = 14;
|
|
846
|
-
// for (let j = 1; j <= 14; j++) {
|
|
847
|
-
// worksheet.getRow(i).getCell(j).border = {
|
|
848
|
-
// top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
849
|
-
// left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
850
|
-
// bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
851
|
-
// right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
852
|
-
// }
|
|
853
|
-
// }
|
|
854
|
-
// worksheet.getRow(i).commit();
|
|
855
|
-
// }
|
|
856
|
-
worksheet.commit();
|
|
658
|
+
return { data, sheet: "Issues", columns, stickyRowsCount: 1, _issueRowCount: data.length };
|
|
857
659
|
}
|
|
858
|
-
static createDefinitionsSheet(
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
const titleRow = worksheet.getRow(1);
|
|
863
|
-
titleRow.height = 36; // actual is 48
|
|
864
|
-
titleRow.getCell(1).value = "Definition of fields";
|
|
865
|
-
titleRow.getCell(1).alignment = { vertical: "middle", horizontal: "left" };
|
|
866
|
-
titleRow.getCell(1).font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: "20" };
|
|
867
|
-
titleRow.getCell(1).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
868
|
-
const colWidthData = [
|
|
869
|
-
{ col: 'A', width: '41.51' }, // note .84 added to actual width
|
|
870
|
-
{ col: 'B', width: '119.51' },
|
|
660
|
+
static createDefinitionsSheet() {
|
|
661
|
+
const columns = [
|
|
662
|
+
{ width: 41.51 },
|
|
663
|
+
{ width: 119.51 },
|
|
871
664
|
];
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
const blankRow = worksheet.getRow(2);
|
|
878
|
-
blankRow.height = 12; // actual is 16
|
|
879
|
-
// "Scan summary and Issue summary" title
|
|
880
|
-
worksheet.mergeCells('A3', "B3");
|
|
881
|
-
const summaryRow = worksheet.getRow(3);
|
|
882
|
-
summaryRow.height = 20; // actual is 26.75
|
|
883
|
-
summaryRow.getCell(1).value = "Scan summary and Issue summary";
|
|
884
|
-
summaryRow.getCell(1).alignment = { vertical: "middle", horizontal: "left" };
|
|
885
|
-
summaryRow.getCell(1).font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 16 };
|
|
886
|
-
summaryRow.getCell(1).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
887
|
-
// row 4 Field / Definition
|
|
888
|
-
const row4 = worksheet.getRow(4);
|
|
889
|
-
row4.height = 16; // actual is
|
|
890
|
-
row4.getCell(1).value = "Field";
|
|
891
|
-
row4.getCell(2).value = "Definition";
|
|
892
|
-
row4.getCell(1).alignment = row4.getCell(2).alignment = { vertical: "middle", horizontal: "left" };
|
|
893
|
-
row4.getCell(1).font = row4.getCell(2).font = { name: "Calibri", color: { argb: "FF000000" }, size: 16 };
|
|
894
|
-
row4.getCell(1).fill = row4.getCell(2).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFCCC0DA' } };
|
|
895
|
-
row4.getCell(1).border = row4.getCell(2).border = {
|
|
896
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
897
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
898
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
899
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
900
|
-
};
|
|
901
|
-
// rows 5-13
|
|
902
|
-
// set row height for rows 5-13
|
|
903
|
-
for (let i = 5; i < 14; i++) {
|
|
904
|
-
worksheet.getRow(i).height = 12; // results in a row height of 16
|
|
905
|
-
}
|
|
906
|
-
let rowData = [
|
|
665
|
+
const titleStyle = { backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 20, alignVertical: "center", align: "left" };
|
|
666
|
+
const sectionStyle = { backgroundColor: "#403151", textColor: "#FFFFFF", fontFamily: "Calibri", fontSize: 16, alignVertical: "center", align: "left" };
|
|
667
|
+
const subHeaderStyle = { backgroundColor: "#CCC0DA", textColor: "#000000", fontFamily: "Calibri", fontSize: 16, borderColor: "#A6A6A6", borderStyle: "thin", alignVertical: "center", align: "left" };
|
|
668
|
+
const dataStyle = { fontFamily: "Calibri", fontSize: 12, textColor: "#000000", align: "left", height: 12 };
|
|
669
|
+
const summaryRowData = [
|
|
907
670
|
{ key1: 'Page', key2: 'Identifies the page or html file that was scanned.' },
|
|
908
671
|
{ key1: 'Scan label', key2: 'Label for the scan. Default values can be edited in the Accessibility Checker before saving this report, or programmatically assigned in automated testing.' },
|
|
909
672
|
{ key1: 'Violations', key2: 'Accessibility failures that need to be corrected.' },
|
|
@@ -913,43 +676,7 @@ class ACReporterXLSX {
|
|
|
913
676
|
{ key1: '% elements without violations or items to review', key2: 'Percentage of elements on the page that had no violations found and no items to review.' },
|
|
914
677
|
{ key1: 'Level 1,2,3', key2: 'Priority level defined by the IBM Equal Access Toolkit. See https://www.ibm.com/able/toolkit/plan/overview#pace-of-completion for details.' }
|
|
915
678
|
];
|
|
916
|
-
|
|
917
|
-
worksheet.getRow(i).getCell(1).font = worksheet.getRow(i).getCell(2).font = { name: "Calibri", color: { argb: "FF000000" }, size: 12 };
|
|
918
|
-
worksheet.getRow(i).getCell(1).alignment = worksheet.getRow(i).getCell(2).alignment = { horizontal: "left" };
|
|
919
|
-
}
|
|
920
|
-
for (let i = 5; i < rowData.length + 5; i++) {
|
|
921
|
-
worksheet.getRow(i).getCell(1).value = rowData[i - 5].key1;
|
|
922
|
-
worksheet.getRow(i).getCell(2).value = rowData[i - 5].key2;
|
|
923
|
-
}
|
|
924
|
-
// "Scan summary and Issue summary" title
|
|
925
|
-
worksheet.mergeCells('A14', "B14");
|
|
926
|
-
const issuesRow = worksheet.getRow(14);
|
|
927
|
-
issuesRow.height = 20; // actual is 26.75
|
|
928
|
-
issuesRow.getCell(1).value = "Issues";
|
|
929
|
-
issuesRow.getCell(1).alignment = { vertical: "middle", horizontal: "left" };
|
|
930
|
-
issuesRow.getCell(1).font = { name: "Calibri", color: { argb: "FFFFFFFF" }, size: 16 };
|
|
931
|
-
issuesRow.getCell(1).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF403151' } };
|
|
932
|
-
// row 15 Field / Definition
|
|
933
|
-
const row15 = worksheet.getRow(15);
|
|
934
|
-
row15.height = 16; // actual is
|
|
935
|
-
row15.getCell(1).value = "Field";
|
|
936
|
-
row15.getCell(2).value = "Definition";
|
|
937
|
-
row15.getCell(1).alignment = row15.getCell(2).alignment = { vertical: "middle", horizontal: "left" };
|
|
938
|
-
row15.getCell(1).font = row15.getCell(2).font = { name: "Calibri", color: { argb: "FF000000" }, size: 16 };
|
|
939
|
-
row15.getCell(1).fill = row15.getCell(2).fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFCCC0DA' } };
|
|
940
|
-
row15.getCell(1).border = row15.getCell(2).border = {
|
|
941
|
-
top: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
942
|
-
left: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
943
|
-
bottom: { style: 'thin', color: { argb: 'FFA6A6A6' } },
|
|
944
|
-
right: { style: 'thin', color: { argb: 'FFA6A6A6' } }
|
|
945
|
-
};
|
|
946
|
-
// rows 16-28
|
|
947
|
-
// set row height for rows 16-28
|
|
948
|
-
for (let i = 16; i < 29; i++) {
|
|
949
|
-
worksheet.getRow(i).height = 12; // results in a row height of 16
|
|
950
|
-
}
|
|
951
|
-
rowData = [];
|
|
952
|
-
rowData = [
|
|
679
|
+
const issuesRowData = [
|
|
953
680
|
{ key1: 'Page', key2: 'Identifies the page or html file that was scanned.' },
|
|
954
681
|
{ key1: 'Scan label', key2: 'Label for the scan. Default values can be edited in the Accessibility Checker before saving this report, or programmatically assigned in automated testing.' },
|
|
955
682
|
{ key1: 'Issue ID', key2: 'Identifier for this issue within this page. Rescanning the same page will produce the same issue ID. ' },
|
|
@@ -964,19 +691,54 @@ class ACReporterXLSX {
|
|
|
964
691
|
{ key1: 'Xpath', key2: 'Xpath of the HTML element where the issue is found.' },
|
|
965
692
|
{ key1: 'Help', key2: 'Link to a more detailed description of the issue and suggested solutions.' },
|
|
966
693
|
];
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
694
|
+
const data = [];
|
|
695
|
+
// Row 1: "Definition of fields" title spanning 2 cols
|
|
696
|
+
data.push([
|
|
697
|
+
Object.assign(Object.assign({ value: "Definition of fields" }, titleStyle), { height: 36, columnSpan: 2 }),
|
|
698
|
+
null
|
|
699
|
+
]);
|
|
700
|
+
// Row 2: blank
|
|
701
|
+
data.push([{ value: null, height: 12, columnSpan: 2 }, null]);
|
|
702
|
+
// Row 3: "Scan summary and Issue summary" section header
|
|
703
|
+
data.push([
|
|
704
|
+
Object.assign(Object.assign({ value: "Scan summary and Issue summary" }, sectionStyle), { height: 20, columnSpan: 2 }),
|
|
705
|
+
null
|
|
706
|
+
]);
|
|
707
|
+
// Row 4: "Field / Definition" subheader
|
|
708
|
+
data.push([
|
|
709
|
+
Object.assign(Object.assign({ value: "Field" }, subHeaderStyle), { height: 16 }),
|
|
710
|
+
Object.assign({ value: "Definition" }, subHeaderStyle),
|
|
711
|
+
]);
|
|
712
|
+
// Rows 5–12: scan summary definitions
|
|
713
|
+
for (const row of summaryRowData) {
|
|
714
|
+
data.push([
|
|
715
|
+
Object.assign({ value: row.key1 }, dataStyle),
|
|
716
|
+
Object.assign({ value: row.key2 }, dataStyle),
|
|
717
|
+
]);
|
|
970
718
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
719
|
+
// Row 13: blank (separator between sections) — kept simple
|
|
720
|
+
data.push([{ value: null, height: 12, columnSpan: 2 }, null]);
|
|
721
|
+
// Row 14: "Issues" section header
|
|
722
|
+
data.push([
|
|
723
|
+
Object.assign(Object.assign({ value: "Issues" }, sectionStyle), { height: 20, columnSpan: 2 }),
|
|
724
|
+
null
|
|
725
|
+
]);
|
|
726
|
+
// Row 15: "Field / Definition" subheader
|
|
727
|
+
data.push([
|
|
728
|
+
Object.assign(Object.assign({ value: "Field" }, subHeaderStyle), { height: 16 }),
|
|
729
|
+
Object.assign({ value: "Definition" }, subHeaderStyle),
|
|
730
|
+
]);
|
|
731
|
+
// Rows 16–28: issues definitions
|
|
732
|
+
for (const row of issuesRowData) {
|
|
733
|
+
data.push([
|
|
734
|
+
Object.assign({ value: row.key1 }, dataStyle),
|
|
735
|
+
Object.assign({ value: row.key2 }, dataStyle),
|
|
736
|
+
]);
|
|
974
737
|
}
|
|
975
|
-
|
|
738
|
+
return { data, sheet: "Definition of fields", columns };
|
|
976
739
|
}
|
|
977
740
|
static countDuplicatesInArray(array) {
|
|
978
741
|
let count = {};
|
|
979
|
-
// let result = [];
|
|
980
742
|
array.forEach(item => {
|
|
981
743
|
if (count[item]) {
|
|
982
744
|
//@ts-ignore
|
|
@@ -1010,9 +772,6 @@ class ACReporterXLSX {
|
|
|
1010
772
|
while (i) {
|
|
1011
773
|
hash = (hash * 33) ^ str.charCodeAt(--i);
|
|
1012
774
|
}
|
|
1013
|
-
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
|
|
1014
|
-
* integers. Since we want the results to be always positive, convert the
|
|
1015
|
-
* signed int to an unsigned by doing an unsigned bitshift. */
|
|
1016
775
|
return hash >>> 0;
|
|
1017
776
|
}
|
|
1018
777
|
}
|