HTML title-block parity with Quarto 1 (bd-gx9cic8z)#396
Merged
Conversation
Phase 0 of the HTML title-block parity epic (bd-gx9cic8z, strand
bd-xj96vafq). Plan: claude-notes/plans/2026-07-15-html-title-block-parity.md
- smoke-all corpus at crates/quarto/tests/smoke-all/title-block/ (7
fixtures: simple-default, rich-authors, metadata-grid, banner-true,
label-overrides, style-plain, style-none) with current-truth
ensureHtmlElements assertions, to be strengthened phase by phase.
- crates/quarto-core/tests/integration/title_block_pipeline.rs renders
through ProjectPipeline/RenderToFileOptions (the q2-render
orchestrator path) and pins the #title-block-header subtree.
- Research note claude-notes/research/2026-07-15-title-block-q1-q2-dom-diff.md
records the Q1 DOM extracts, reproduction procedure, and the 11-row
divergence table mapping each gap to its phase.
Snapshot changes: 8 NEW insta snapshots (no existing snapshots
modified): title_block_{simple,rich_authors,metadata_grid,banner_true,
banner_true_main_tag,label_overrides,style_plain,style_none}. They
deliberately pin today's imperfect output — structured authors render
as 'truetrue' (bd-8v34zny5); banner/style/label-override options are
ignored — so each parity phase surfaces as a reviewed snapshot diff.
Verified: full workspace suite green (10004 tests); real-binary render
of simple-default.qmd matches the insta baseline byte-for-byte.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 1 of the HTML title-block parity epic (bd-gx9cic8z, strand bd-tezzk9vp). Plan: claude-notes/plans/2026-07-15-html-title-block-parity.md Rust side: - New AuthorsNormalizeTransform (authors.lua counterpart): derives by-author, labels (with author-title/published-title/abstract-title/ modified-title/doi-title/description-title overrides + Author/Authors pluralization), author-meta (one head <meta name="author"> per author), and rendered.has-title-block into document metadata. Typed name parsing (literal/given/family/particles) in new quarto-core/src/metadata/authors.rs. - FULL_HTML_TEMPLATE's inline title block replaced by built-in doctemplate partials (title-block / title-metadata, each also under a .html alias). User template-partials shadow them Q1-style; custom templates resolve them as a final fallback (new blanket &T PartialResolver impl in quarto-doctemplate). - Q1-parity markup: p.subtitle.lead, bare-div meta grid cells, <p>-wrapped authors, p.date, abstract as div > div.abstract > div.block-title with real <p> paragraphs (block-context rendering); the quarto-title-meta grid is emitted whenever the title block renders (empty allowed, Q1 parity). - Fixes: bd-8v34zny5 (structured authors rendered as 'truetrue'); date-without-author now renders its Published cell; a document with authors but no title now renders the header (gated on rendered.has-title-block, not title). Preview lockstep (plan decision Q9): - PreviewTitleBlock.tsx rewritten to the same markup, consuming the same derived metadata; its vitest integration suite rewritten; the five smoke-all/q2-preview/title-block-*.qmd fixtures updated. Tests: smoke-all title-block corpus strengthened to Q1-parity selectors (RED first, then green); new fixtures two-authors.qmd and date-no-author.qmd. Snapshot changes (9 modified, 0 added/removed): - 7 title_block_pipeline baselines: the intended P1 markup changes (subtitle lead, bare-div cells, p wrappers, block-title, label overrides honored, authors pluralized, truetrue replaced by names). - attribution_off_baseline: whitespace-only (one extra blank line from the partial call site). - phase5-single-doc-baseline expected_hashes.txt re-captured per its documented convention: doc.html gains the (empty) Q1-parity quarto-title-meta grid + partial whitespace; styles.css unchanged. Verification: cargo nextest workspace green (10,020); preview-renderer vitest 532+519 green; hub-client build:all + test:ci green; Playwright smoke-all title-block sweep 14/14 in a real browser; real-binary q2 render output inspected for simple/two-authors/label-overrides and a metadata-less doc (no empty header). cargo xtask verify passed all Rust + hub-client legs; its quarto-hub-mcp test leg failed on 20 timeouts contacting wss://sync.automerge.org, which is returning 502 from this network (same outage braid reports all session) — unrelated to this change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Port Quarto 1's authors.lua normalization to a typed Rust model and render its full display surface in the HTML title block: - metadata/authors.rs grows into the full Q1 author schema: structured names (given/family/particles; BibTeX-heuristic split of literals, documented deviation from Q1's bibtex round-trip), degrees, orcid, email, url, phone, fax, acknowledgements, notes (globally numbered), attribute flags (direct keys + attributes: list/map), CRediT roles (aliases + vocab decoration), affiliation schema with state->region / affiliation-url->url aliases and metadata bucketing, inline + ref: + top-level affiliations: block with dedup and ref remapping, and funding normalization (schema only, decision Q7). Undefined refs warn-and-drop instead of Q1's hard abort. - AuthorsNormalizeTransform emits the Q1 meta shapes: authors (refs), affiliations, by-author (denormalized), by-affiliation, funding, labels (+ affiliations single/plural + affiliation-title override); normalization problems surface as render diagnostics. - Built-in title-metadata partial gains Q1's two-column .quarto-title-meta-author grid ($if(by-affiliation)$/$elseif$ split); new _title-meta-author partial renders url-linked names with degrees inside the anchor, an email icon, and an ORCID badge — both inline SVGs (decision Q8; envelope from bootstrap-icons upstream, ORCID glyph in brand green). title-block.scss sizes the SVGs (documented deviation: svg joined img in the orcid rule). - doctemplate: the bare-partial external scanner now accepts underscore-leading names ($_title-meta-author()$ — required for Q1 template-partials compatibility); corpus + evaluator tests added. - DocumentProfile v7: new authors_structured: Vec<ProfileAuthor> field (+ ProfileAffiliation); flat authors now derives from the same normalization. Contract doc change log updated (incl. retroactive v6 entry). Fixes the Phase-0 deferred-author-model note. - Preview lockstep (Q9): PreviewTitleBlock.tsx renders the two-column grid and author decorations from the same derived meta; also fixes the P1-noted multi-paragraph-abstract gap (one <p> per paragraph). Vitest suite grown to 26 tests; new q2-preview smoke fixture title-block-rich-authors.qmd (Playwright sweep 15/15 green). Snapshot/baseline changes (2 files, both reviewed): - title_block_rich_authors.snap re-captured: the intended P2 DOM (two- column grid, decorated authors) replacing the P1 single-column list. - phase5 expected_hashes.txt: doc_files/styles.css hash re-captured for the title-block.scss svg-sizing rules (entry documents the delta; doc.html hash unchanged). Verification: TDD red-first on the strengthened rich-authors smoke fixture and new vitest/doctemplate tests; full workspace green (10,056 tests); smoke-all 191/191; hub-client build:all + test:ci green; preview-renderer 519 unit + 539 integration tests green; end-to-end `q2 render` output inspected and browser-screenshot checked (grid layout, ORCID/envelope icons render correctly). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Complete the Q1-parity metadata grid in the HTML title block: - TITLE_METADATA_PARTIAL: Modified cell (p.date-modified), Doi cell (p.doi > a linked to doi.org), trailing keywords block (div.keywords > div.block-title + comma-joined <p>), Q1-verbatim. - TITLE_BLOCK_PARTIAL: category chips (div.quarto-categories > div.quarto-category) inside div.quarto-title, gated on Q1's quarto-template-params.title-block-categories (written by AuthorsNormalizeTransform unless title-block-categories: false, so Q1-ported custom template-partials keep working); description block with the hide-description gate ported verbatim (inert in Q2 until a project pipeline sets the flag — design decision Q11). - description now renders rich (joins RICH_TITLE_BLOCK_FIELDS); the head <meta name="description"> switches to the plain-text description-meta derived by MetadataNormalizeTransform (the same description/description-meta split Pandoc's HTML writer and Q1's html.template use; an explicit description-meta wins). Head keywords meta now joins list values with ", " ($for/$sep$). - has_title_block_content counts the new fields (date-modified, doi, keywords, description, categories), so a document with only grid metadata still gets its header. - Q9 lockstep: PreviewTitleBlock.tsx renders the same chips / description / Modified / Doi / keywords from the derived meta; vitest integration suite +7 tests (547 pass); Playwright title-block sweep green (17 tests) against rebuilt WASM. Snapshot changes (2): title_block_metadata_grid.snap updated with the intended new grid markup (chips, description, Modified, linked Doi, keywords — reviewed, matches Q1's DOM shape); title_block_metadata_grid_no_categories.snap added (chips suppressed, header intact). Phase5 expected_hashes.txt deliberately not re-captured: its fixture has none of the new metadata, and the byte-identity test passes unchanged. New fixtures: smoke-all/title-block/categories-disabled.qmd, smoke-all/q2-preview/title-block-metadata-grid.qmd; strengthened smoke-all/title-block/metadata-grid.qmd assertions (TDD red first, 6 checks failing before the fix). Verified end-to-end via `cargo run --bin q2 -- render` with markdown in the description: <em> in the body block, plain text in the head meta. Full workspace tests (10061) and `cargo xtask verify --skip-hub-mcp-tests` green; the skipped leg's 20 failures are the known live-test timeouts against the dead wss://sync.automerge.org, present on the baseline. Plan: claude-notes/plans/2026-07-15-html-title-block-parity.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Port Q1's title-block banner without a DOM postprocessor: - New TitleBannerTransform (Normalization phase, format-html only — deliberately not revealjs, which has a title slide): derives rendered.title-block-banner from title-block-banner (true | CSS color | image path, Q1's isBannerImage detection via the injected SystemRuntime so the probe also sees /project/ VFS files in WASM renders — a bare Path::is_file() failed the Playwright banner-image sweep); generates the Q5 include-in-header <style> for explicit colors/images (title-block-banner-color body/body-bg = theme default, per Q1's titleColor()), appended to the canonical rendered.includes.header list via the favicon transform's append_to_rendered_header (now pub(crate)) so it reaches both the native $header-includes$ and the q2-preview head injector; pushes a ResourceCopyIntent so image banners land in the output tree. - TITLE_BLOCK_PARTIAL branches internally on the flag (one partial name preserves Q1's template-partials override semantics in both modes): banner branch is Q1's banner/title-block.html — title/subtitle/description/categories inside div.quarto-title-banner > div.quarto-title.column-body, meta grid below, no hide-description gate, page-columns page-full baked into header + banner div (Q1 gets these from its bootstrap grid DOM postprocessor). FULL_HTML_TEMPLATE emits the header above #quarto-content and gives <main> quarto-banner-title-block via template conditionals — the placements Q1 does with DOM surgery. - Deferred, documented (module doc + plan): #quarto-header.quarto-banner (Q2 has no #quarto-header element; the class's only Q1 consumer is website secondary-nav styling) and the toc-left banner-header-class producer (Q2 has no toc-location option; the template hook is ported and inert). - Q9 lockstep: PreviewTitleBlock banner branch (shared TitleMetaGrids fragment = Q1's shared title-metadata partial); PreviewDocument hoists the title block above #quarto-content + <main> class. +6 vitest cases (553 pass); Playwright title-block sweep green (20 tests). Snapshot changes (5): title_block_banner_true.snap updated to the banner markup (reviewed — matches the P0 research doc's captured Q1 banner DOM); title_block_banner_true_main_tag.snap gains quarto-banner-title-block; new title_block_banner_color.snap, title_block_banner_color_style.snap, title_block_banner_image_style.snap (generated style blocks, Q1's documentTitleIncludeInHeader shape). Non-banner output is byte-identical — the phase5 expected_hashes byte-identity test passed unchanged. New fixtures: banner-color.qmd, banner-image.qmd + committed 1x1 banner.png, q2-preview/title-block-banner.qmd; banner-true.qmd assertions strengthened (TDD red first: 5 checks failing). Verified end-to-end: q2 render on an output-dir project copies _site/banner.png and emits the background-image style; browser screenshots (chrome-devtools MCP) of Q1 (dev quarto binary) vs Q2 banner pages are visually identical apart from P4 date formatting; explicit #FFDDFF/#111111 banner beats the theme as designed. Full workspace tests (10073) and cargo xtask verify --skip-hub-mcp-tests green (skipped leg = known dead-sync-server timeouts). Plan: claude-notes/plans/2026-07-15-html-title-block-parity.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
…itle-block-parity # Conflicts: # hub-client/changelog.md
Implement Q1's title-block-style option surface (manuscript deliberately unsupported per design decision Q6 — silent fallback to default, the AppendixStyle convention): - New TitleBlockStyle enum in transforms/config.rs (default | plain | none, with `false` as Q1's boolean spelling of none). Q2 has no YAML-schema validation layer, so the typed enum IS the "schema entry", matching AppendixStyle/ReferenceLocation. - `none`: Q1 renders Pandoc's own fallback title block (formats/html/pandoc/title-block.html) — the TITLE_BLOCK_PARTIAL gains that branch, gated on the derived `rendered.title-block-none` (bare header without quarto classes, h1.title, p.subtitle without `lead`, one p.author per normalized author name, p.date, div.abstract > div.abstract-title using $labels.abstract$ where Pandoc uses its own $abstract-title$ variable — documented deviation, the abstract-title override keeps working). TitleBannerTransform skips none (Q1 emits no banner partials for none/false) — covered by a new pipeline test (none + banner: header stays in <main>, no banner markup). - `plain` (and `none`): drop the title-block SCSS layer from the compiled CSS, Q1's documentTitleScssLayer. ThemeConfig gains `title_block_layer` (read from title-block-style; quarto-sass-local reader documented as a deliberate duplicate of quarto-core's TitleBlockStyle, both matrix-tested). Honored in assemble_theme_scss and BOTH compile_with_doc_vars variants (native grass + WASM dart-sass bridge). The shared default-CSS fast path additionally requires the flag, so default docs stay byte-identical and cache-shared; a plain/none doc takes the fingerprinted path with the flag in its cache key. - Found while testing: one responsive .quarto-title-banner margin rule lives in the *bootstrap* layer (in Q1 too, _bootstrap-rules.scss:1916) and correctly survives plain/none; the CSS assertions target selectors only the title-block layer produces (.quarto-title-meta-heading, .quarto-title-author-orcid). - Q9 lockstep: PreviewTitleBlock.tsx none-branch renders the Pandoc fallback from the same derived meta (+2 vitest, 555 pass); new q2-preview fixture title-block-style-none.qmd; Playwright title-block sweep green (21 tests, incl. the html style fixtures under the WASM runner — the WASM sass path honors the flag). Snapshot changes (1): title_block_style_none.snap re-baselined from the styled block to the Pandoc fallback markup (reviewed — the intended P6 behavior; plain changes no markup by design, so title_block_style_plain.snap is untouched). Fixtures: style-none.qmd / style-plain.qmd assertions strengthened (TDD red first: 5 element checks + CSS negatives failing), new q2-preview/title-block-style-none.qmd. Verified end-to-end via cargo run --bin q2 -- render: none emits the fallback header; plain and none CSS carry 0 quarto-title-meta-heading rules vs 1 in a default-doc control. Full workspace tests (10158) and cargo xtask verify --skip-hub-mcp-tests green (skipped leg = known dead-sync-server timeouts). Plan: claude-notes/plans/2026-07-15-html-title-block-parity.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ancillary design doc for the shared date helper: study of Q1's date subsystem (core/date.ts, pandoc.ts pre-render rewrite, listing record pre-formatting, documentTitleMetadata's forced long, setDateLocale) and the quarto-web dates reference, plus a proposed familiar-not- byte-compatible Q2 design. Key finding: Q1 formats every date before templating — EJS never formats — so doctemplates being logic-less is no obstacle; a Normalization-phase transform is structurally Q1's own position. Design draft only; execution awaits approval. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ISO-week tokens (W WW GGGG) join the day-one subset (time provides iso_week without locale data); locale-week (w ww wo gggg) and named-timezone (z zzz) tokens stay deferred with diagnostics. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Implement the approved date design (claude-notes/plans/
2026-07-17-date-formatting-design.md). Key architectural point,
from the design study: Q1 formats every date BEFORE templating (its
EJS never formats — records are pre-formatted in TS, and pandoc.ts
rewrites date/date-modified in metadata pre-Pandoc), so Q2's
logic-less doctemplates need no new capability; a Normalization
transform is structurally Q1's own position.
- New crates/quarto-core/src/dates.rs: Q1's parse-form list
(MM/DD/YYYY et al + ISO timestamps; NO guessing tail — a
diagnostic names the accepted forms instead of Q1's moment-guess),
named styles full/long/medium/short/iso (English-only per epic Q3;
locale joins the localization design), and a day.js token
formatter with [...] escapes. Token scope per Carlos: everything
without i18n design cost — includes ISO-week W/WW/GGGG; deferred
with warnings: locale-week w/ww/wo/gggg and named-tz z/zzz (tz
database). Non-token characters pass through literally (day.js
semantics, e.g. the T in YYYY-MM-DDTHH:mm:ssZ). Unit matrix
mirrors Q1's docs-page examples table.
- New DateNormalizeTransform (Normalization, before
AuthorsNormalize): resolves today/now (UTC via the WASM-safe
SystemRuntime::unix_timestamp — documented deviation from Q1's
local time) and last-modified (VFS-aware runtime mtime); writes
ISO date-meta/date-modified-meta (explicit value wins, the
description-meta precedent) and replaces date/date-modified in
place with the formatted string. Precedence: field-local
{value,format} > date-format > default, where the default is
`long` for the styled HTML title block (Q1's
documentTitleMetadata) and `iso` otherwise/for all formats. The
head's dcterms.date switches to $date-meta$ — the machine slot
stays ISO even under date-format (deliberate deviation; Q1 leaks
the pretty string there). Parse failures diagnose and preserve
the raw value.
- Listings: date-typed item fields are formatted at record-build
(finally consuming the parsed-but-unused ListingConfig::date_format;
doc date-format fallback; Q1's `medium` default); feeds' RFC-2822
path now parses via the shared module (drift hole closed).
- Preview lockstep (Q9): zero TSX changes by design — the preview
pipeline runs the transform, so PreviewTitleBlock receives
formatted strings through its existing meta reads.
Snapshot changes (4, all reviewed): title_block_simple,
title_block_metadata_grid, title_block_banner_true,
title_block_label_overrides re-baselined with formatted dates
(2026-07-01 → "July 1, 2026", 2026-07-10 → "July 10, 2026") —
matching the Q1 extracts captured in the P0 research doc verbatim;
this closes the last visible Q1-vs-Q2 delta from the P0/P5
comparisons. Listing pipeline test pins updated to "Jan 15, 2026".
New fixtures: smoke-all/title-block/date-format.qmd (token format +
ISO dcterms + negative on raw ISO in the body) and
date-default-long.qmd (forced long) — TDD red first (5 regex checks
failing). Playwright title-block sweep green (23 tests; the date
fixtures run under the WASM runner).
Verified end-to-end: `date: today` with
date-format "dddd MMM Do, YYYY" renders
<p class="date">Friday Jul 17th, 2026</p> and
<meta name="dcterms.date" content="2026-07-17T00:00:00+00:00">.
Full workspace tests (10167) and cargo xtask verify
--skip-hub-mcp-tests green (skipped leg = known dead-sync-server
timeouts).
Plan: claude-notes/plans/2026-07-17-date-formatting-design.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two user-facing docs pages, rendered with q2 and modeled on quarto-web's structure and style (content adjusted to Q2's supported surface; prose written with the Gopen & Swan reader-expectations methodology): - docs/guides/authoring/title-blocks.qmd — overview, the three title-block-style options (with a callout that Q1's manuscript style is unsupported), structured authors + ref: affiliations, banners with custom backgrounds/foreground color, categories, dates, the label-override table (Q2's actual defaults, incl. auto-pluralization), and the template-partials escape hatch (Q1-compatible partial names). - docs/guides/authoring/dates.qmd — parse forms (+ the no-guessing warning behavior), date keywords (+ UTC callout), named styles, the supported day.js token table with the deferred locale-week/named-tz tokens called out, bracket escaping, and a "Where Formatting Applies" section covering the title block, listings, and the always-ISO machine slots (dcterms, feeds). Both pages registered in the docs sidebar; `cargo run --bin q2 -- render docs/` emits zero warnings for the new pages (Q1's definition-list syntax is unsupported in qmd, so the style list uses bullets); rendered output inspected in the browser — the pages dogfood the title-block features they document. Follow-up strands filed for every deferred item (discovered-from bd-y71ga2l8): bd-45tfp790 localization design (labels, date locales, locale-week tokens, local-tz keywords), bd-4j4okt4o manuscript style (Q6), bd-e2kpwy7n toc-location (unlocks the inert banner toc-left hook), bd-xva3f8uy quarto-header quarto-banner (needs secondary-nav), bd-6reut449 citation/scholar meta tags (Q10), bd-a949e2zu editable React title block (Q9). Epic plan marked COMPLETE (P0–P7). Workspace tests green (10175). Plan: claude-notes/plans/2026-07-15-html-title-block-parity.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cscheid
marked this pull request as ready for review
July 17, 2026 15:18
cscheid
added a commit
that referenced
this pull request
Jul 17, 2026
…e title-block labels via compute_labels (bd-llhlzd7p) PR #396 landed a partial-based title block whose labels.* metadata is computed by AuthorsNormalizeTransform::compute_labels with per-document *-title overrides. That supersedes this branch's template-context labels helper (removed): compute_labels is now term-aware instead, with precedence per label: *-title override > language term > English literal. Terms wired: title-block-author-single/plural, -affiliation-single/plural, -published, -modified, -keywords, section-title-abstract. doi and description keep English literals (no Q1 term key exists — Q1 hardcodes them too). Post-merge: quarto-core suite (2579), localization smoke fixtures, and full workspace (10207) green; Spanish end-to-end render re-inspected (Autor/a, Fecha de publicación, Resumen through the new partials). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Brings Q2's HTML title block to DOM parity with Quarto 1's (epic bd-gx9cic8z). All phases (P0–P7) are now complete on this branch; the epic and all its strands are closed, with follow-up strands filed for every deliberately deferred item.
Plan:
claude-notes/plans/2026-07-15-html-title-block-parity.md. Guiding principle: match Q1's element nesting and class names exactly inside#title-block-header(the already-ported SCSS and third-party extensions keep working), don't chase template whitespace.What's implemented
crates/quarto/tests/smoke-all/title-block/), insta baselines of the#title-block-headersubtree driven through the realq2 renderorchestrator path, Q1-vs-Q2 DOM diff research note.FULL_HTML_TEMPLATEbecame built-in doctemplate partials (title-block/title-metadata/_title-meta-author), shadowable Q1-style viatemplate-partials; Q1 markup shapes (subtitle lead,p.date,block-title, bare-div grid cells);AuthorsNormalizeTransformderivesby-author, pluralized/overridablelabels,author-meta; fixed bd-8v34zny5 (structured authors rendering astruetrue).metadata/authors.rs): structured names, degrees, ORCID/email/URL, affiliations withref:resolution, funding schema (Q7); two-column Authors/Affiliations grid; inline-SVG email + ORCID decorations (Q8);DocumentProfilev7 with structured authors.quarto-template-params.title-block-categories(default true);descriptionrenders rich in the body while the head meta uses a derived plain-textdescription-meta(the Pandoc/Q1 split).TitleBannerTransformderives the banner flag and generates the include-in-header<style>for explicit colors/images (Q5); image banners are resource-copied to the output tree; header placement above#quarto-contentand thequarto-banner-title-blockclass on<main>are template conditionals — no DOM postprocessor, per the project rule;page-columns page-fullbaked into the markup. VFS-aware file probe so image detection works in WASM/preview renders.PreviewTitleBlock.tsx/PreviewDocument.tsxmirror every markup/placement change; vitest integration suites + Playwright smoke-all sweep (20 title-block tests) green.Documented deviations from Q1
#quarto-header.quarto-bannernot ported: Q2 has no#quarto-headerwrapper element, and the class's only Q1 consumer styles the website secondary nav, which Q2 doesn't have yet.toc-leftbanner header class has no producer yet (Q2 has notoc-locationoption); the template hook is ported and inert.2026-07-01vs Q1's forceddate-format: long) — that's P4 on this branch.*-titleoverrides (Q3);manuscriptstyle skipped (Q6); citation/scholar meta tags out of scope (Q10).Verification
cargo nextest run --workspacegreen (10073 tests); phase5 byte-identity baseline unchanged (non-banner output byte-identical).cargo xtask verify --skip-hub-mcp-testsgreen (the skipped leg's 20 failures are pre-existing live-test timeouts against the currently-downwss://sync.automerge.org, unrelated to this branch).cargo run --bin q2 -- render, including an output-dir project exercising the banner-image resource copy).Completed since the draft opened
title-block-style: plain/none(bd-vkiwhcny): typedTitleBlockStyleoption, Pandoc-fallback block fornone, and the title-block SCSS layer dropped from the per-document CSS compile forplain/none(native + WASM paths, cache-key-isolated; default docs stay byte-identical).claude-notes/plans/2026-07-17-date-formatting-design.md):dates.rs(Q1 parse forms, English named styles, day.js tokens incl. ISO-week; locale-week/named-tz deferred with warnings),DateNormalizeTransform(keywords via WASM-safe runtime clock/mtime, ISOdate-metafor machine slots, in-place formatted replacement with Q1's precedence incl. forcedlong), listings consumingdate-formatat record-build, feeds sharing the parser. Closes the last visible Q1-vs-Q2 delta (unformatted dates).docs/guides/authoring/title-blocks.qmd+dates.qmd, rendered with q2, modeled on quarto-web's structure/style, sidebar-registered. Follow-up strands filed: bd-45tfp790 (localization design), bd-4j4okt4o (manuscript), bd-e2kpwy7n (toc-location), bd-xva3f8uy (quarto-banner/secondary-nav), bd-6reut449 (citation meta tags), bd-a949e2zu (editable preview title block).Ready to come out of draft.
🤖 Generated with Claude Code