Skip to content

Commit 75ef6db

Browse files
committed
Merge feature/table-rendering-parity: bd-hir7j
Bring q2 render+preview table output to byte-for-byte parity with Quarto 1 on the daily-log fixture. 8 sub-tasks merged in: Render path: bd-fyb4z (D1) list-table defaults header-rows=1 bd-2c8rg (D2) transform adds caption-top + table classes bd-hixmy (D3) HTML writer suppresses empty <colgroup> bd-12fpz (D4/5) HTML writer emits header/odd/even row classes bd-mtzry (D6) template appends quarto-light to body class Preview path (React mirrors of the above): bd-elgxx (D4/5 react) Table.tsx emits row classes bd-tkamn (D6 react) PreviewDocument.tsx appends quarto-light No-op verifications: bd-dy97y (D7) Bootstrap CSS was already shipped by CompileThemeCssStage; the gap was 100% markup. bd-g18wu (D8) q2-preview SPA bundle already includes Bootstrap rules; same conclusion. Visual verification 2026-05-20: q2 render, q2 preview, and Quarto 1 produce byte-identical computed styles on ~/Desktop/daily-log/2026/05/20/tables.qmd (width 799px, padding 8.5px, font-weight 700, caption-side top, body class fullcontent quarto-light). Parent epic bd-hir7j closed. Plan: claude-notes/plans/2026-05-20-table-default-rendering-parity.md
2 parents deb102d + 8749e06 commit 75ef6db

21 files changed

Lines changed: 1097 additions & 89 deletions

.beads/issues.jsonl

Lines changed: 10 additions & 8 deletions
Large diffs are not rendered by default.

claude-notes/plans/2026-05-20-table-default-rendering-parity.md

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -285,24 +285,64 @@ title: Table test
285285
## Checklist
286286

287287
### Phase 1 — markup parity
288-
- [ ] **bd-fyb4z** D1: list-table default `header-rows: 1` + tests
289-
- [ ] **bd-2c8rg** D2: `quarto-bootstrap-table` transform stage adds
288+
- [x] **bd-fyb4z** D1: list-table default `header-rows: 1` + tests
289+
*(closed 2026-05-20, commit 87b5f236)*
290+
- [x] **bd-2c8rg** D2: `quarto-bootstrap-table` transform stage adds
290291
`table` + `caption-top` classes + tests
291-
- [ ] **bd-hixmy** D3: suppress empty colgroup + tests
292-
- [ ] **bd-12fpz** D4/D5: emit `odd`/`even` body-row classes and
292+
*(closed 2026-05-20, commit 987bdc9f; transform runs in HTML
293+
pipeline finalization phase and also in q2-preview)*
294+
- [x] **bd-hixmy** D3: suppress empty colgroup + tests
295+
*(closed 2026-05-20, commit a91f114a)*
296+
- [x] **bd-12fpz** D4/D5: emit `odd`/`even` body-row classes and
293297
`header` head-row class + tests (bundled — same code path)
294-
- [ ] **bd-mtzry** D6: emit `quarto-light` on `<body>` + template tests
298+
*(closed 2026-05-20, commit c02a405a)*
299+
- [x] **bd-elgxx** D4/D5 react: same row classes in the preview's
300+
React Table component (preview doesn't go through the pampa
301+
writer) *(closed 2026-05-20, commit cad7778c)*
302+
- [x] **bd-mtzry** D6: emit `quarto-light` on `<body>` + template tests
303+
*(closed 2026-05-20, commit 21c8ec04; dark-mode detection deferred
304+
until the pipeline supports light/dark theme configs)*
305+
- [x] **bd-tkamn** D6 react: same `quarto-light` append in the preview
306+
shell's body-class effect (PreviewDocument.tsx)
307+
*(closed 2026-05-20, commit fa21b5c5)*
295308

296309
### Phase 2 — render CSS
297-
- [ ] **bd-dy97y** D7: Bootstrap-derived default stylesheet loaded by
298-
HTML format + end-to-end test against `tables.qmd`
299-
- [ ] D7 follow-up: visually re-verify in Chrome and update plan
300-
with the closing screenshot delta
310+
- [x] **bd-dy97y** D7: Bootstrap-derived default stylesheet loaded by
311+
HTML format
312+
*(already done in the codebase prior to this epic: the
313+
`CompileThemeCssStage` ships the full Bootstrap 5.3.1 bundle as
314+
`_files/styles.css` for default renders. The original gap that
315+
made the table look unstyled was 100% markup-side — the
316+
`<table>` was missing the `caption-top table` class hooks
317+
(D2). Once those landed, the existing CSS styled the table
318+
identically to Q1: computed `padding: 8.5px`, `font-weight:
319+
700`, `caption-side: top`, etc. — confirmed via Chrome DevTools
320+
2026-05-20. Closing without code; verification by inspection.)*
321+
- [x] D7 follow-up: visual re-verify in Chrome
322+
*(done 2026-05-20: q2 render of the daily-log fixture is
323+
visually identical to Quarto 1 — see
324+
`/var/folders/.../T/q2-render-after-phase1.png` vs `q1-render-current.png`.)*
325+
- [x] Edge case for D7: `theme: none` opt-out ships only the minimal
326+
244-line `crates/quarto-core/resources/styles.css` (no `.table`
327+
rules). This is correct — the user explicitly opted out of
328+
Bootstrap. The D2 classes still emit but are inert under
329+
`theme: none`. No action needed.
301330

302331
### Phase 3 — preview CSS
303-
- [ ] **bd-g18wu** D8: align preview-side CSS bundle (coordinate with
304-
k-giyy) + DevTools-driven regression
305-
- [ ] D8 follow-up: visual re-verify in `q2 preview`
332+
- [x] **bd-g18wu** D8: align preview-side CSS bundle
333+
*(already done in the codebase prior to this epic: the
334+
q2-preview SPA's bundled CSS at
335+
`q2-preview-spa/dist/assets/q2-preview-*.css` already contains
336+
Bootstrap's `.table` and `.caption-top` rules. After bd-elgxx
337+
and bd-tkamn landed the markup, the preview's computed table
338+
styles match Q1 byte-for-byte: 799px width, 8.5px padding,
339+
font-weight 700, caption-side top — same as render. The
340+
`coordinate-with-k-giyy` worry in the original plan was based
341+
on the wrong premise.)*
342+
- [x] D8 follow-up: visual re-verify in `q2 preview`
343+
*(done 2026-05-20: preview renders the daily-log fixture
344+
visually identical to render and to Q1 — see
345+
`/var/folders/.../T/q2-preview-after-d6-react.png`.)*
306346

307347
### Wrap-up
308348
- [ ] Update `docs/` user-facing notes if any new defaults are
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
2-
source: crates/quarto-markdown-pandoc/tests/test.rs
3-
assertion_line: 362
2+
source: crates/pampa/tests/test.rs
43
expression: output
54
---
6-
[ Table ( "" , [] , [] ) (Caption Nothing []) [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)] (TableHead ( "" , [] , [] ) []) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,2"]] ] , Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,2"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
5+
[ Table ( "" , [] , [] ) (Caption Nothing []) [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)] (TableHead ( "" , [] , [] ) [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,2"]] ] ]) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,2"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
2-
source: crates/quarto-markdown-pandoc/tests/test.rs
3-
assertion_line: 362
2+
source: crates/pampa/tests/test.rs
43
expression: output
54
---
6-
[ Table ( "" , [] , [] ) (Caption Nothing []) [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)] (TableHead ( "" , [] , [] ) []) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) [Plain [Str "Spans", Space, Str "two", Space, Str "columns"]] ] , Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
5+
[ Table ( "" , [] , [] ) (Caption Nothing []) [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)] (TableHead ( "" , [] , [] ) [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 2) [Plain [Str "Spans", Space, Str "two", Space, Str "columns"]] ] ]) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
2-
source: crates/quarto-markdown-pandoc/tests/test.rs
3-
assertion_line: 362
2+
source: crates/pampa/tests/test.rs
43
expression: output
54
---
6-
[ Table ( "" , [] , [] ) (Caption Nothing []) [(AlignLeft, ColWidthDefault), (AlignCenter, ColWidthDefault), (AlignRight, ColWidthDefault)] (TableHead ( "" , [] , [] ) []) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Left"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Center"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Right"]] ] , Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
5+
[ Table ( "" , [] , [] ) (Caption Nothing []) [(AlignLeft, ColWidthDefault), (AlignCenter, ColWidthDefault), (AlignRight, ColWidthDefault)] (TableHead ( "" , [] , [] ) [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Left"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Center"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Right"]] ] ]) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "A"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "B"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "C"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
2-
source: crates/quarto-markdown-pandoc/tests/test.rs
3-
assertion_line: 362
2+
source: crates/pampa/tests/test.rs
43
expression: output
54
---
6-
[ Table ( "" , [] , [] ) (Caption Nothing [ Para [Str "This", Space, Str "is", Space, Str "the", Space, Str "caption."] ]) [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)] (TableHead ( "" , [] , [] ) []) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,2"]] ] , Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,2"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]
5+
[ Table ( "" , [] , [] ) (Caption Nothing [ Para [Str "This", Space, Str "is", Space, Str "the", Space, Str "caption."] ]) [(AlignDefault, ColWidthDefault), (AlignDefault, ColWidthDefault)] (TableHead ( "" , [] , [] ) [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "1,2"]] ] ]) [TableBody ( "" , [] , [] ) (RowHeadColumns 0) [] [Row ( "" , [] , [] ) [Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,1"]] , Cell ( "" , [] , [] ) AlignDefault (RowSpan 1) (ColSpan 1) [Plain [Str "Cell", Space, Str "2,2"]] ] ]] (TableFoot ( "" , [] , [] ) [] ) ]

crates/pampa/src/pandoc/treesitter_utils/postprocess.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,16 @@ fn transform_list_table_div(div: Div) -> Block {
305305
let source_info = div.source_info.clone();
306306

307307
// Extract attributes from div (LinkedHashMap iteration returns (&String, &String))
308+
//
309+
// bd-fyb4z: default `header-rows` to 1 (not 0) so a bare list-table
310+
// promotes its first row to `<thead>`, matching Quarto 1. Explicit
311+
// `header-rows="0"` opts back into the no-header behavior.
308312
let header_rows: usize = div
309313
.attr
310314
.2
311315
.get("header-rows")
312316
.and_then(|v| v.parse().ok())
313-
.unwrap_or(0);
317+
.unwrap_or(1);
314318

315319
let aligns_str = div.attr.2.get("aligns").map(|v| v.as_str());
316320
let widths_str = div.attr.2.get("widths").map(|v| v.as_str());

0 commit comments

Comments
 (0)