Skip to content

chore(all): Replace exceljs with write-excel-file - #2628

Merged
tombrunet merged 12 commits into
main-4.xfrom
exceljs-replace
Sep 1, 2026
Merged

chore(all): Replace exceljs with write-excel-file#2628
tombrunet merged 12 commits into
main-4.xfrom
exceljs-replace

Conversation

@tombrunet

@tombrunet tombrunet commented Aug 28, 2026

Copy link
Copy Markdown
Member

Summary

Replace the peer dependency (unmaintained) with across all packages. The XLSX report output is functionally equivalent — same five sheets, same column widths, same colour coding and cell styling.

Motivation

exceljs has not received meaningful maintenance. Switching to write-excel-file removes the dependency on an unmaintained library and eliminates the 'use strict' patching workaround that was required in the browser extension's preprocess.js.

Changes

Core logic — common/module/src/report/ACReporterXLSX.ts

  • Full rewrite from ExcelJS's imperative workbook/worksheet/cell API to write-excel-file's data-array model.
  • Each sheet builder now returns a { data, sheet, columns } object; all sheets are passed to writeExcelFile(sheets).toFile(filename) in one call.
  • Cell colours converted from ExcelJS ARGB format ("FF403151") to standard 6-digit hex ("#403151").
  • Lazy-load guard updated: dynamic import now targets write-excel-file/node; warning message updated accordingly.
  • worksheet.commit() / workbook.commit() calls removed (not needed by the new library).

Extension — accessibility-checker-extension/

  • package.json: replaced exceljs direct dependency with write-excel-file.
  • preprocess.js: removed the sed commands that stripped 'use strict' from the exceljs bundle (no longer needed).
  • jest.config.js: removed stale comment referencing exceljs.

E2E test helper — accessibility-checker-extension/test/

  • support/steps/steps_excel.ts: replaced exceljs Workbook reader with read-excel-file/node; updated cell-address parsing to use the library's row/column array model.
  • package.json: replaced exceljs with read-excel-file.

package.json peer / direct dependency updates

All packages that declared exceljs as a peer or direct dependency have been updated to declare write-excel-file@^4.1.1 instead:

  • accessibility-checker/package.json
  • accessibility-checker/src/package.json
  • cypress-accessibility-checker/package.json + package/package.json
  • vitest-accessibility-checker/package.json + src/package.json + package/package.json
  • karma-accessibility-checker/package.json
  • common/module/package.json

Pre-built JS artefacts regenerated

All committed copies of ACReporterXLSX.js (CJS + MJS outputs across accessibility-checker, cypress-accessibility-checker, vitest-accessibility-checker, karma-accessibility-checker) were rebuilt from the new TypeScript source and committed.


Testing checklist

Confirm these scenarios before merging.

XLSX report output (accessibility-checker Node.js)

  • Run accessibility-checker against a page with violations and confirm a .xlsx file is written to disk.
  • Open the generated file — verify 5 sheets are present: Overview, Scan summary, Issue summary, Issues, Definition of fields.
  • Overview sheet: confirm title row background is dark purple (#403151), summary counts (Violations / Needs review / Recommendations / Archived) are correct, and column widths are reasonable.
  • Scan summary sheet: confirm one data row per scan, all 9 columns populated, numeric columns (Violations, Needs review, …) are right-aligned with borders.
  • Issue summary sheet: confirm Level 1–4 sections are present with correct counts; rows within each level are sorted descending by count.
  • Issues sheet: confirm one row per issue, all 14 columns populated, header row has dark purple background.
  • Definition of fields sheet: confirm both the Scan summary and Issues definition tables are present.
  • Run a scan with outputFilenameTimestamp: false and confirm the output file is named results.xlsx (not timestamped).
  • Confirm that if write-excel-file is not installed the warning "Warning: write-excel-file is not installed…" is printed and the process does not crash.

Browser extension (accessibility-checker-extension)

  • Build the extension (npm run build:dev) — confirm it compiles without errors (no exceljs webpack error or 'use strict' conflict).
  • Load the extension in Chrome/Firefox and generate an XLSX report from the UI — confirm the file downloads and opens correctly in Excel / LibreOffice.
  • Confirm preprocess.js no longer modifies any node_modules files on build.

E2E tests (accessibility-checker-extension/test)

  • Run npm test in accessibility-checker-extension/test — the Cucumber step Excel Sheet "…" Cell "…" is "…" should pass using read-excel-file.

Downstream packages

  • cypress-accessibility-checker: run npm run test and confirm XLSX output is produced correctly.
  • vitest-accessibility-checker: run npm run test and confirm XLSX output is produced correctly.
  • karma-accessibility-checker: run npm run build with no errors.

- accessibility-checker: mocha test calling ACReporterXLSX.generateSummary()
  directly (no rule server needed); validates all 5 sheets and key cells
- vitest-accessibility-checker: parallel Node forks test using same approach;
  vitest.node.config.mjs replaces the .js version (poolOptions removed for v4)
- cypress-accessibility-checker: Cypress e2e test + adm-zip tasks in
  cypress.config.js; adds outputFilenameTimestamp: false to .achecker.yml

Fix XLSX XML parser helpers in all three tests:
- Sheet name lookup: extract r:id and name attrs independently (write-excel-file
  emits r:id before name, opposite of the old regex assumption)
- Cell parsing: use attribute-order-independent regex that handles both
  self-closing <c .../> and full <c ...>...</c> forms; index rows by actual
  Excel row number (sparse array) so merged/skipped rows don't shift indices

CI (test.yml): add mocha XLSX + vitest test:node steps to both Linux and
Windows basic jobs; add npm install write-excel-file before each step
counts.elements can be 0 (or undefined) when a page has no elements to
check. Dividing by zero produces NaN which write-excel-file writes as
<v>NaN</v> — illegal OOXML that triggers Excel's corruption-repair dialog.

Guard both percentage columns: return 0 when counts.elements is 0.
…n missing file

- test.yml: add 'npm install write-excel-file' step for cypress-accessibility-checker
  (peerDependencies are not auto-installed by npm install)
- cypress.config.js: guard readXlsxCell and xlsxSheetExists tasks against
  missing file so tests fail with a clear message instead of ADM-ZIP crash
achecker-xlsx.test.js imports ACReporterXLSX (CJS) and adm-zip — both
Node-only. The default include pattern was picking it up in the Chromium
browser run causing 'does not provide an export named ACReporterXLSX'.

Explicitly exclude it from vitest.config.js; it runs separately via
vitest.node.config.mjs (pool: forks).
… packages

peerDependencies are not auto-installed by npm install, causing
'write-excel-file is not installed' warnings in CI for cypress and vitest.

Move write-excel-file to regular dependencies in:
- accessibility-checker
- cypress-accessibility-checker
- vitest-accessibility-checker

Remove the now-redundant explicit 'npm install write-excel-file' CI steps.
…EADMEs

Move write-excel-file (and adm-zip in common/module) from peerDependencies
to regular dependencies in all remaining packages:
- common/module
- accessibility-checker/src (published package manifest)
- vitest-accessibility-checker/src (published package manifest)
- karma-accessibility-checker

Update all four READMEs to remove the 'Optional: XLSX Report Format'
install instructions — XLSX is now included automatically.
@tombrunet
tombrunet marked this pull request as ready for review August 31, 2026 19:00
@nam-singh
nam-singh self-requested a review September 1, 2026 12:18
nam-singh
nam-singh previously approved these changes Sep 1, 2026
"cypress": "^13.2.0 || ^15"
},
"devDependencies": {
"adm-zip": "^0.5.9",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tombrunet I have not explored cypress and karma package in detail, but should adm-zip be in direct dependencies, if we are generating report similar to extension, not sure about this though.
I used bob to check where it is used it gave back following result
karma-accessibility-checker — adm-zip is used only inside ACReporterXLSX.js at line 160. That file ships in the published package and runs when a user generates a report. adm-zip must be in dependencies. There are no test files in this package that use it independently.

cypress-accessibility-checker — adm-zip is used in two places:

src/lib/common/report/ACReporterXLSX.js — runtime report generation → needs dependencies
test/cypress.config.js — reading XLSX cells during tests → needs devDependencies

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I think this is a leftover. It was originally a peer dependency because of the security vulnerabilities but we can move them now to regular dependencies

@tombrunet
tombrunet merged commit e5a3e7f into main-4.x Sep 1, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants