Skip to content

Commit 6b553b9

Browse files
cscheidclaude
andcommitted
docs(revealjs): plan for render/preview theme parity (bug 1 done, Level 2 scoped)
Captures the corrected architecture map (the Explore agent wrongly claimed the reveal theme compiles in preview and registers css:theme:* — neither is true) and the Level 2 work to make q2 preview apply the document's compiled reveal theme. Bug 1 (default-font @import) is done; Level 2 (preview convergence) is the remaining multi-part effort. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5b46b50 commit 6b553b9

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Reveal render/preview theme parity
2+
3+
**Strand:** bd-y259zb57
4+
**Found:** 2026-06-16, during e2e testing on `main` (post-#297).
5+
6+
## Problem
7+
8+
Two render/preview divergences, **one root cause**: `q2 render` uses the
9+
*compiled Quarto reveal theme*; `q2 preview` uses *stock vendored `white.css`*.
10+
They diverge in opposite directions:
11+
12+
| | `q2 render` | `q2 preview` |
13+
|---|---|---|
14+
| Theme | compiled Quarto theme | stock `white.css` + `quarto-reveal.css` |
15+
| Text align | left ✓ | center ✗ |
16+
| Headings | none ✓ | uppercase ✗ |
17+
| Font | (was) Helvetica ✗ → now SSP via @import| SSP (white.css embeds it) ✓ |
18+
19+
## Bug 1 — render fonts — DONE (commit 5b46b50e)
20+
21+
The compiled theme named `Source Sans Pro` but loaded nothing → Helvetica.
22+
**Fixed**: the Quarto reveal layer (`resources/scss/revealjs/quarto-revealjs.scss`
23+
`scss:defaults`) now `@import`s Source Sans Pro from Google Fonts (foundry
24+
import, no bundling — user decision, matches Q1's `_brand.yml` font model).
25+
Sass hoists the CSS `@import` to the top. Test:
26+
`default_theme_imports_source_sans_pro_from_google`. E2E: Chrome confirmed the
27+
SSP 400 face loads + applies on render.
28+
29+
## Bug 2 — preview centered + uppercase (Level 2: full per-document parity) — TODO
30+
31+
The q2-slides preview **never applies the Quarto reveal layer**, for *any*
32+
theme/brand. So preview shows reveal's stock defaults (centered, uppercase) and,
33+
once Level 2 lands, must instead compile and apply the document's actual reveal
34+
theme (default / named / custom `.scss` / `_brand.yml`).
35+
36+
### Corrected architecture map (the 2026-06-16 Explore agent got two key things wrong)
37+
38+
- **WRONG (agent):** "the reveal branch in `CompileThemeCssStage` fires for
39+
q2-slides." **Reality:** that branch is gated on
40+
`ctx.format.identifier == FormatIdentifier::Revealjs`
41+
(`compile_theme_css.rs:267`); `q2-slides``("html", preview)`
42+
(`format.rs:125`), so `identifier == Html`. **The preview never compiles the
43+
reveal theme at all.** (The agent confused the `is_revealjs_target()` helper —
44+
true for `q2-slides` — with the identifier check.)
45+
- **WRONG (agent):** "reveal registers `css:theme:<fp>` like HTML." **Reality:**
46+
`register_reveal_assets` uses `css:revealjs:*` keys (`assemble.rs:153`); the
47+
WASM `extract_theme_fingerprint` looks for `css:theme:` (`wasm-…/lib.rs:1463`).
48+
They do not match.
49+
50+
### HTML theme-delivery model to mirror (verified parts)
51+
52+
1. `CompileThemeCssStage` compiles the HTML theme → `store_css` registers
53+
`css:theme:<fingerprint>` (`compile_theme_css.rs`).
54+
2. WASM `render_page_for_preview` (`wasm-quarto-hub-client/src/lib.rs:1188`) →
55+
`extract_theme_fingerprint` (1461) → `RenderResponse.theme_fingerprint`.
56+
3. SPA reads VFS bytes at `DEFAULT_CSS_ARTIFACT_PATH`
57+
(`/.quarto/project-artifacts/styles.css`), mints a blob URL, posts
58+
`UPDATE_THEME` to the iframe (`Q2PreviewIframe.tsx:281`).
59+
4. Iframe applies it.
60+
61+
### WASM reveal compile — AVAILABLE
62+
63+
`compile_reveal_theme_css` is cfg-split: native `grass`
64+
(`quarto-sass/src/compile.rs:373`), WASM dart-sass via the JS bridge (`:575`,
65+
async). So the preview can compile the reveal theme on WASM.
66+
67+
### Work (each TDD; verify through real `q2 preview` + Chrome)
68+
69+
- [ ] **L2.1 (Rust).** Make the preview pipeline compile the document's reveal
70+
theme. The reveal branch must fire for the reveal-preview pseudo-format.
71+
Decide the detection signal (target_format `q2-slides` /
72+
`is_revealjs_target`, vs `ast.meta` `format: revealjs`) since
73+
`format.identifier` is `Html` in preview. Register the compiled theme so
74+
the WASM extractor + VFS flush find it (either reuse `css:theme:<fp>` +
75+
the styles.css artifact path, or extend the extractor for the reveal key).
76+
- [ ] **L2.2 (WASM).** Ensure `render_page_for_preview` surfaces the reveal
77+
theme (fingerprint + bytes flushed to the VFS artifact path the SPA reads).
78+
- [ ] **L2.3 (hub-client).** The preview reveal renderer must consume the theme
79+
(UPDATE_THEME / prop), inject it as a stylesheet, and **drop the static
80+
`white.css` import** (keep reset + reveal core + quarto-reveal). Bundle the
81+
Source Sans Pro `@import` comes along via the compiled theme automatically.
82+
Files: `ts-packages/preview-renderer/src/q2-preview/RevealDeck.tsx`,
83+
`Q2PreviewIframe.tsx`, q2-preview-spa entry. **hub-client change → two-commit
84+
changelog; WASM/SPA rebuild required.**
85+
- [ ] **L2.4.** Tests + E2E parity check (`q2 render` vs `q2 preview` on a deck
86+
with default, a named theme, and `_brand.yml` — all should match).
87+
88+
### Notes / gotchas
89+
90+
- Per-document theme means the SPA can no longer statically import one theme;
91+
it must inject the per-document compiled CSS at runtime (blob/style), like the
92+
HTML path does.
93+
- `q2 preview` embeds the SPA bundle; after hub-client changes, rebuild WASM +
94+
SPA + re-embed (`hub-client npm run build:wasm`, `cargo xtask
95+
build-q2-preview-spa`, `cargo build --bin q2`) — see CLAUDE.md "Verifying Rust
96+
changes in q2 preview".
97+
- Existing related strands: bd-v053sk3s (preview revealjs Tier-1 parity GA
98+
gate), bd-qn8yi1su (golden render↔preview parity test).

0 commit comments

Comments
 (0)