Skip to content

Make the HTML report a single self-contained index.html - #1245

Merged
sferik merged 1 commit into
mainfrom
single-file-html-report
Aug 3, 2026
Merged

Make the HTML report a single self-contained index.html#1245
sferik merged 1 commit into
mainfrom
single-file-html-report

Conversation

@sferik

@sferik sferik commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

The HTML formatter previously wrote index.html plus five sibling files (coverage_data.js, application.js, application.css, and three favicon PNGs). This PR makes the report a single file. The asset build (rake assets:compile) now inlines the viewer's JavaScript and CSS into the compiled template and converts the favicon PNGs to data URIs, and at report time the formatter substitutes the coverage JSON at a marker in the template and writes one index.html. coverage.json is still written alongside as the sanctioned data artifact for downstream tools.

A single file can be mailed, copied anywhere, or uploaded as a non-zipped GitHub Actions run artifact (actions/upload-artifact with archive: false only supports single files) and viewed directly from the run page. It also makes report updates atomic. A reader can no longer catch index.html and coverage_data.js from different runs, because the report is replaced in one rename.

Embedding the data is done safely. Every "<" in the embedded payload is escaped as \u003c, which is valid JSON since "<" can only occur inside strings, so source text containing "</script>" or "<!--" cannot terminate the surrounding script element. The asset build refuses to inline a compiled bundle containing such sequences, rather than emit a template that would truncate at render time.

The pre-1.0 simplecov-html formatter offered inline assets behind the SIMPLECOV_INLINE_ASSETS environment variable, and the 1.0 client-side rendering rewrite dropped that mode. This restores single-file reports as the default and only mode, with no flag or environment variable.

@sferik
sferik force-pushed the single-file-html-report branch from b0c0f1a to e3aab5f Compare August 3, 2026 22:34
@sferik
sferik force-pushed the single-file-html-report branch 3 times, most recently from 245049e to 30e2722 Compare August 3, 2026 22:56
@sferik
sferik force-pushed the single-file-html-report branch 2 times, most recently from 8b2fb15 to 2f28a14 Compare August 3, 2026 23:01
@sferik
sferik force-pushed the single-file-html-report branch 2 times, most recently from 2d797d0 to 0bd758f Compare August 3, 2026 23:19
The HTML formatter previously wrote index.html plus five sibling files
(coverage_data.js, application.js, application.css, and three favicon
PNGs). The compiled template now inlines the viewer's JavaScript and
CSS at build time (rake assets:compile), and the formatter
substitutes the coverage JSON at a marker in the template at report
time, so the whole report is one file. coverage.json is still written
alongside as the sanctioned data artifact.

A single file can be mailed, copied anywhere, or uploaded as a
non-zipped GitHub Actions run artifact (actions/upload-artifact with
archive: false only supports single files) and viewed directly from
the run page. It also makes report updates atomic. A reader can no
longer catch index.html and coverage_data.js from different runs
because the report is replaced in one rename.

Every "<" in the embedded payload is escaped as \u003c (valid JSON,
since "<" can only occur inside strings), so source text containing
"</script>" or "<!--" cannot terminate the surrounding script
element. The asset build refuses to inline a bundle containing such
sequences.

The embedded payload is serialized compactly. Pretty printing puts
every element of every per-line coverage array on its own indented
line, which makes the report roughly a third larger (simplecov's own
dogfood report is 647 KB compact against 947 KB pretty). The sibling
coverage.json stays pretty-printed for human readers.

The asset build also renames the stylesheet's custom properties to
short aliases after minification. The descriptive names repeat at
every use and cost about 3 KB of the compiled template. Properties
that JavaScript reads or writes by name (--bar-sizer-width and the
band colours) are exempt and keep their names.

The favicon (a solid square in the overall coverage band's colour) is
drawn by the viewer on a canvas from the live --green/--red/--yellow
palette values instead of shipping as fixed PNGs, so it matches the
report's colours exactly and follows the light/dark theme, including
the in-page toggle and OS preference changes.

The pre-1.0 simplecov-html formatter offered inline assets behind the
SIMPLECOV_INLINE_ASSETS environment variable. The 1.0 client-side
rendering rewrite dropped that mode. This restores single-file reports
as the default and only mode, with no flag or environment variable.

Resolves #1241.
@sferik
sferik force-pushed the single-file-html-report branch from 0bd758f to d76fa58 Compare August 3, 2026 23:26
@sferik
sferik merged commit 7d95e49 into main Aug 3, 2026
20 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.

1 participant