Skip to content

feat(export): extract CSS/JS to shared _assets/ + thread --filter (REQ-087, REQ-088)#319

Merged
avrabe merged 1 commit into
mainfrom
feat/req-087-088-html-export-fixes
May 24, 2026
Merged

feat(export): extract CSS/JS to shared _assets/ + thread --filter (REQ-087, REQ-088)#319
avrabe merged 1 commit into
mainfrom
feat/req-087-088-html-export-fixes

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 24, 2026

Summary

Two HTML-export fixes from the v0.11.1 audit findings (PR #317
captured them as REQ-087 and REQ-088).

REQ-088 — kill the 13 GB. Per-page emission was
`<style>{fonts_css}{css}</style><script>{mermaid_js}</script>` with
`MERMAID_JS = include_str!("../assets/mermaid.min.js")` (~3MB), so a
5000-artifact project produced ~13 GB of mostly-identical bytes. Now
the exporter writes one shared `/_assets/styles.css` +
`_assets/mermaid.min.js` and each page emits
`<link rel="stylesheet" href="…">` + `<script src="…">`.
The wrap_page closure takes the page's `rel_path` and computes a
depth-adjusted prefix (`""`, `"../"`, `"../../"`) so
root / depth-1 / depth-2 pages all resolve assets and nav hrefs
correctly — clears latent nav-relativity bugs as a side-effect.

Verified on the rivet dogfood corpus:

Before After
~3MB per page ~7-10 KB per page
Multi-GB total 9.7 MB for 871 pages

REQ-087 — `--filter` actually narrows. `cmd_export` accepted
`--filter` for HTML format but never threaded it into
`cmd_export_html`. Result: a filtered HTML export silently emitted
every artifact — the F2 silent-failure class
(REQ-078..082's family). Now threaded through and applied at the
per-artifact loop using the existing
`sexpr_eval::matches_filter_with_store` (same pattern
`cmd_export_zola` already uses).

Smoke: unfiltered emits 788 per-artifact pages; `--filter` with an
unmatching clause emits 1 (just the index shell) — proving the wire
works.

Test plan

  • Two new integration tests in `rivet-cli/tests/export_html.rs`
    drive the real binary against the rivet corpus and assert:
    `_assets/` exists, pages reference it, no inlined mermaid
    signature, per-page < 100KB; `--filter` strictly narrows
    from the unfiltered baseline. Both pass locally.
  • Full `cargo test -p rivet-cli` green.
  • `cargo clippy -p rivet-cli` clean (only pre-existing
    MSRV-config noise).
  • CI green.

🤖 Generated with Claude Code

…Q-087, REQ-088)

REQ-088 — HTML exporter no longer embeds the full CSS/JS framework
into every page. Per-page emission was
`<style>{fonts_css}{css}</style><script>{mermaid_js}</script>` with
`MERMAID_JS = include_str!("../assets/mermaid.min.js")` (~3MB), so a
5000-artifact project produced ~13 GB of mostly-identical bytes. Now
the exporter writes `<out>/_assets/styles.css` + `_assets/mermaid.min.js`
ONCE and each page emits `<link rel="stylesheet" href="…">` and
`<script src="…">`. Verified on the rivet dogfood corpus: 871 pages,
total export 9.7 MB (was multi-GB), per-page ~7-10 KB.

The wrap_page closure now takes the page's `rel_path` and computes a
depth-adjusted prefix (`""`, `"../"`, `"../../"`) so root-level,
depth-1, and depth-2 pages all resolve assets and nav hrefs correctly
— this also clears latent nav-relativity bugs in the previous fixed
`../path` strings (root index.html's "Overview" link, depth-2
help/schema/* pages, the inconsistent stpa/ vs ../path navs).

REQ-087 — `rivet export --filter <s-expr>` now actually narrows the
per-artifact page set. `cmd_export` accepted `--filter` for HTML but
never threaded it into `cmd_export_html`, so a filtered HTML export
silently emitted every artifact — the F2 silent-failure class. Now
threaded through and applied at the per-artifact loop using the
existing `sexpr_eval::matches_filter_with_store` (same pattern as
`cmd_export_zola`).

Adds `rivet-cli/tests/export_html.rs` with two integration tests
driving the real binary against the rivet corpus:
`export_html_extracts_shared_assets` asserts `_assets/` exists, pages
reference it, the inlined library signature is gone, and per-page
HTML is < 100KB; `export_html_filter_narrows_per_artifact_pages`
asserts a filter set strictly narrows from the unfiltered baseline.

Implements: REQ-087, REQ-088
Verifies: REQ-087, REQ-088
@github-actions
Copy link
Copy Markdown

📐 Rivet artifact delta

No artifact changes in this PR. Code-only changes (renderer, CLI wiring, tests) don't touch the artifact graph.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Rivet Criterion Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: 6e743a9 Previous: 86bf482 Ratio
validate/10000 17690146 ns/iter (± 2447873) 13963257 ns/iter (± 521263) 1.27

This comment was automatically generated by workflow using github-action-benchmark.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe avrabe merged commit 6d72f03 into main May 24, 2026
20 of 39 checks passed
@avrabe avrabe deleted the feat/req-087-088-html-export-fixes branch May 24, 2026 05:55
avrabe added a commit that referenced this pull request May 24, 2026
…#322)

REQ-090 — Release attaches the audit-deliverable bundle (multi-page
HTML + ReqIF + generic-yaml + README) instead of the navigation-shell
HTML. Compliance action gains opt-in `include-data-formats` (default
false, backward-compatible); release.yml's build-compliance sets
`single-page: false` + `include-data-formats: true`. Multi-page
emission is ~50 MB thanks to REQ-088's shared-assets fix (#319).

Implements: REQ-090
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