Skip to content

Commit f6d3989

Browse files
docs(hub-client): consolidate q2-preview branch changelog to user-facing entries
The branch shipped 15+ phase-level entries describing internal architecture (Plan 2pre / 2A / 2B / 2C / 2D sub-phases, the bd-3gtn artifact-flush fix, theme-CSS path corrections) that hub-client users don't see. Replace with two user-facing entries: the new `format: q2-preview` and the render-components mid-type crash fix. Side effect: clears the Q-2-7 parse error in the prior 2026-05-10 entry (bd-1qk5) since the offending text is removed entirely.
1 parent 1b87175 commit f6d3989

1 file changed

Lines changed: 3 additions & 26 deletions

File tree

hub-client/changelog.md

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,9 @@ be in reverse chronological order (latest first).
1515

1616
### 2026-05-10
1717

18-
- [`979982bd`](https://github.com/quarto-dev/q2/commits/979982bd): Custom syntax highlighting now works in Quarto Hub projects (bd-izfv) — user-supplied tree-sitter grammars under `_quarto/grammars/<lang>/` now apply to code blocks even when the qmd file lives under a `_quarto.yml` ancestor, matching the single-file render path.
19-
- [`c8a684bd`](https://github.com/quarto-dev/q2/commits/c8a684bd): Fix bd-3gtn: WASM artifact-flush loop in `wasm-quarto-hub-client/src/lib.rs` was overwriting user-uploaded image bytes with empty content on every render. `ResourceCollectorTransform` produces manifest-only entries via `Artifact::from_path` whose absolute path collapsed via `Path::join`'s absolute-replace rule onto the user's VFS upload location. Both flush loops now skip empty-content artifacts, preserving manifest semantics for downstream consumers while keeping produced bytes (theme CSS, fonts, future engine-generated images) flowing. Discovered during Plan 2A review (2026-05-07) and routed-around by Plan 2B until now; the test in `assetManifestProject.wasm.test.ts` was reverted to its natural lifecycle (binary upload BEFORE render) for a bug-then-fix walk-through.
20-
- [`02da39a5`](https://github.com/quarto-dev/q2/commits/02da39a5): Fix iframe-host crash when typing `render-components:\n -` (empty list bullet) into a document's YAML frontmatter. The path-extraction in `ReactRenderer.tsx`'s `componentPathsKey` useMemo yielded `undefined` for the null entry, which then crashed `resolveComponentPath(undefined, …)` with `Cannot read properties of undefined (reading 'startsWith')` — past the local ErrorBoundary (a descendant, not an ancestor of `ReactRenderer`), so the page went blank and the user couldn't finish typing. Now filters extracted paths to keep only non-empty strings; empty entries are skipped silently. Two regression tests cover the `MetaList c: [null]` and `MetaList c: [{t: 'MetaInlines', c: []}]` mid-type shapes.
21-
- [`3b064478`](https://github.com/quarto-dev/q2/commits/3b064478): Plan 2D q2-preview body container + title block. `PreviewDocument.tsx` now emits the `<div id="quarto-content"><main class="content">` wrapper mirroring `template.rs:185-247`, applies `body-classes` imperatively to `document.body`, and re-implements the Rust `title-block` transform's minimal-mode `<h1>` synthesis React-side (the transform itself stays in `Q2_PREVIEW_TRANSFORM_EXCLUDED`). Iframe `document.title` now tracks `meta.pagetitle ?? meta.title`. New `q2-preview/custom/PreviewTitleBlock.tsx` mirrors `template.rs:211-240` byte-for-byte and is registered under the synthetic `__title_block__` registry key; user TSX overrides can full-replace or compose via the `__Q2_PREVIEW_RENDERER__.PreviewTitleBlock` exposure. Phase 6.0 framework extraction lifts `inlinesToPlainText` / `blocksToPlainText` to `framework/plainText.ts` and adds `framework/meta.ts` (`extractMetaString` / `extractMetaBool` / `extractMetaStringList`); `FormatRegistry` gains typed optional entries for both synthetic keys. The slide renderer's private `extractMetaString` is replaced by the framework helper (deliberate behavior change for inline-markup in slide titles, locked by a regression test); `meta.format` extraction in `ReactRenderer.tsx` and `getQ2Format.ts` consolidates onto the same helper. Tests: 27 framework unit, 18 PreviewDocument integration, 17 PreviewTitleBlock integration (incl. composition idiom), explicit synthetic-key assertion closing a pre-existing `__fallback__` gap; 11 smoke-all q2-preview fixtures (body-container + body-classes + title-block).
22-
- [`c8a684bd`](https://github.com/quarto-dev/q2/commits/c8a684bd): Fix bd-3gtn: WASM artifact-flush loop in `wasm-quarto-hub-client/src/lib.rs` was overwriting user-uploaded image bytes with empty content on every render. `ResourceCollectorTransform` produces manifest-only entries via `Artifact::from_path` whose absolute path collapsed via the absolute-replace rule of `Path::join` onto the user's VFS upload location. Both flush loops now skip empty-content artifacts, preserving manifest semantics for downstream consumers while keeping produced bytes (theme CSS, fonts, future engine-generated images) flowing. Discovered during Plan 2A review (2026-05-07) and routed-around by Plan 2B until now; the test in `assetManifestProject.wasm.test.ts` was reverted to its natural lifecycle (binary upload BEFORE render) for a bug-then-fix walk-through.
23-
- [`d91150c4`](https://github.com/quarto-dev/q2/commits/d91150c4): Plan 2B Phase 5.2 and 5.3: smoke-all `q2-preview/image-with-attrs.qmd` fixture (with a 1x1 PNG sibling) and the `assetManifestProject.wasm.test.ts` WASM-bridge safety net. The smoke fixture asserts the parent-side asset walker mints a blob URL, propagates the width attribute, and round-trips alt text. The WASM test mirrors `themeFingerprint.wasm.test.ts` and renders a `_quarto.yml`-rooted project doc with a project-relative Image, then exercises the walker against the parsed AST and project-relative `currentFilePath`. Catches default-project resolution bugs analogous to the Plan 2A theme path mismatch (commit e6381abd). 82/82 WASM tests pass.
24-
- [`25d98df5`](https://github.com/quarto-dev/q2/commits/25d98df5): Plan 2B Phase 3 and 5.1: built-in registry of Pandoc-base leaves. q2-preview ships 14 Block components and 20 Inline components, replacing the empty Plan 2A registry. Image is a pure AssetManifestContext consumer (no VFS access in the iframe). Math is a near-verbatim port of Elliot Math leaf with two divergences: direct ESM `import katex` (window.katex is only set after LOAD_CUSTOM_COMPONENTS) and an explicit raw-LaTeX fallback on KaTeX error. Note is the JS-side number-with-tooltip-body fallback for `reference-location: block` and `section` (the default `document` configuration runs through FootnotesTransform upstream). New `q2-preview/utils.ts` ships `lookupAssetUrl`, `inlinesToPlainText`, `blocksToPlainText`. New stub `q2-preview/quartoClasses.ts` covers section, footnotes, and appendix constants. The framework dispatch table gains 5 new renderChildrenRegistry entries for Underline, Strikeout, Superscript, Subscript, SmallCaps. Plan 2A empty-registry tests are replaced by 21 new q2-preview integration tests (Pandoc base rendering, gap-fill components, Image edge cases, atomic CustomNode read-only, recursion-contract bypass, class-compatibility); q2-debug gains a parity test for the atomic gate. 688 unit + 112 integration tests pass.
25-
- [`c002ef7d`](https://github.com/quarto-dev/q2/commits/c002ef7d): Plan 2B pipeline change: include FootnotesTransform and AppendixStructureTransform in q2-preview. Removes "footnotes" and "appendix-structure" from `Q2_PREVIEW_TRANSFORM_EXCLUDED`. Both produce pure Pandoc primitives that q2-preview leaves render natively; the original synthesize-with-no-preimage exclusion rationale does not bite for v1 structural rendering. Effects: footnote numbering is automatic, the footnotes section nests inside the appendix container, and license / copyright / citation YAML metadata renders as small section blocks under the appendix container. `TitleBlockTransform` stays excluded (its is_html() gate makes it a no-op for q2-preview today, and making it useful requires a Rust change beyond Plan 2B). bd-1kly tracks the upstream gap for `reference-location: block` and `section`; until that lands, the q2-preview Note tooltip-body fallback handles those configs.
26-
- [`d2a6ca77`](https://github.com/quarto-dev/q2/commits/d2a6ca77): Plan 2B Phase 2: asset manifest plumbing for q2-preview. A new parent-side walker (in `q2-preview/assetWalker.ts`) scans the AST for Image nodes, resolves their paths via the now-shared `vfsPaths.ts`, reads VFS bytes, and mints (or reuses cached) blob URLs. Cache identity is the base64 content string itself: synchronous, deterministic, no hash. External URLs (http, https, data, protocol-relative) are filtered out at walk time. A new `q2-preview/AssetManifestContext.tsx` distributes the manifest to iframe consumers. `Q2PreviewIframe.tsx` owns the cache (drained on unmount) and extends the UPDATE_AST payload to include the manifest alongside the AST. The iframe entry forwards the manifest into a context provider alongside PreviewContext, and the SET_AST callback now rewraps JS-native CustomNodes back to wire format before posting. Walker test suite covers cache hit, content-change eviction, image removal, external skipping, VFS failure, N=100 stress, malformed JSON, and nested-container traversal. Q2PreviewIframe integration test grows a third case for the manifest payload and unmount revocation.
27-
- [`f3c32926`](https://github.com/quarto-dev/q2/commits/f3c32926): Plan 2B Phase 2.1a: extract a shared `utils/vfsPaths.ts`. The helpers `resolveRelativePath`, `normalizePath`, and `guessMimeType` previously had three private copies (in iframePostProcessor, iframeLinkHandlers, and ReactAstSlideRenderer); consolidating to a shared module avoids fanning the duplication out further when the Plan 2B asset walker becomes the fourth consumer. Pure refactor; no behavior change. The new module includes 13 unit tests covering absolute-path passthrough, double-dot traversal, empty segments, the single-leading-slash invariant, past-root traversal swallowing, image and text MIME types, and the octet-stream fallback.
28-
- [`fc784bb2`](https://github.com/quarto-dev/q2/commits/fc784bb2): Plan 2B Phase 1: framework foundation for the q2-preview built-in components. A new `framework/customNode.ts` ships unwrap and rewrap walks that convert between the wire-format `__quarto_custom_node` Div/Span wrappers and JS-native CustomBlockNode and CustomInlineNode shapes. The walks mirror the Rust JSON writer and reader, and are structural-sharing pure so subtree identity is preserved for the future Note-numbering WeakMap. An atomic-aware gate inside `framework/dispatch.tsx` no-ops setLocalAst for Derived, atomic Synthetic, and atomic CustomNode subtrees: both q2-debug and q2-preview pick it up automatically. `framework/Ast.tsx` accepts a discriminated input (string or pre-parsed AST), unconditionally unwraps custom-node wrappers, and fills the RegistryContext sourceInfoPool value (Plan 2A typed the field but did not fill it). New types: Slot, CustomBlockNode, CustomInlineNode, CiteInline, plus block-level gap-fill types. The framework blockTypes array extends from 11 to 19 entries (LineBlock, DefinitionList, Table for the new leaves; CustomBlock as the post-unwrap discriminator; BlockMetadata, NoteDefinitionPara, NoteDefinitionFencedBlock, CaptionBlock defensively routed as blocks). The renderChildrenRegistry gains CustomBlock and CustomInline entries for the generic slot walk consumed by Plan 2C Fallback. Round-trip property tests cover the six in-tree CustomNode type_name strings plus an IncludeExpansion placeholder, in both directions, with explicit cases for the inline-side no-Plain asymmetry and the walker-purity reference-preservation contract.
29-
30-
### 2026-05-09
31-
32-
- [`e6381abd`](https://github.com/quarto-dev/q2/commits/e6381abd): Fix q2-preview theme CSS path mismatch in project mode. The pass-2 renderer now writes a copy of the compiled theme CSS at the stable iframe-readable location `/.quarto/project-artifacts/styles.css` regardless of single-doc vs project layout, honoring Plan 1's contract.
33-
- [`81e48f10`](https://github.com/quarto-dev/q2/commits/81e48f10): Fix `theme_fingerprint` missing on q2-preview renders inside non-website projects. The fingerprint is now captured at the pass-2 renderer level (before `drain_project_scoped`) and stashed on `WasmPassTwoOutput`, so it survives both the default-project flush path and the website-merge path.
34-
- [`fe40973b`](https://github.com/quarto-dev/q2/commits/fe40973b): Plan 2A — q2-preview iframe foundation. New `q2-preview/` directory ships parallel to `q2-debug/` with `Q2PreviewIframe`, registry skeleton (Block/Inline placeholder dispatchers + `PreviewDocument`), `entry.tsx` with module-top message listener and `__Q2_PREVIEW_RENDERER__` global, and `PreviewContext` for `currentFilePath`. Theme CSS flows as blob URLs (parent reads VFS, mints `URL.createObjectURL`, posts URL string via `UPDATE_THEME`; iframe consumes via `<link rel="stylesheet">`). Three-way `themeFingerprint` (`string | null | undefined`) preserves last-good styling across transient render errors. The combined `ReactRenderer` format branch is split into distinct q2-debug / q2-preview branches; the `render-components` gate is extended to cover q2-preview. Shared utilities added: `iframeLinkHandlers.ts` (event-delegation extraction), `sourceInfo.ts`, `atomicCustomNodes.ts`, `artifactPaths.ts`. The framework `RegistryContext` is extended with `sourceInfoPool?` (Plan 2B atomic-aware gate consumer). The q2-debug global `__REACT_AST_DEBUG_RENDERER__` is hoisted to module top. The iframe boots empty in 2A — every Pandoc node renders as a muted-gray "(not yet implemented)" placeholder. Plan 2B fills the registry with real-HTML leaves.
35-
36-
### 2026-05-08
37-
38-
- Plan-2pre carve-up of the q2-debug renderer (Phase 1 + Phase 2). The renderer is split into `framework/` (format-agnostic recursive dispatch, types, typed registry contract) and `q2-debug/` (bordered-box leaves, dispatchers, format registry, iframe wrapper, entry point). The iframe route renamed from `/ast-renderer.html` to `/q2-debug.html`; the iframe component from `AstIframe` to `Q2DebugIframe`; the registry from `componentRegistry` to `q2DebugRegistry`. The `__REACT_AST_DEBUG_RENDERER__` window global is preserved for user-TSX consumers. Bordered Figure no longer renders the literal `// TODO:` placeholder text in the DOM. `MathInline` added to the `InlineNode` union. Phase 1 commit: [`8afa8fae`](https://github.com/quarto-dev/q2/commits/8afa8fae). Phase 2 commits: [`59c8f3f5`](https://github.com/quarto-dev/q2/commits/59c8f3f5), [`f182b957`](https://github.com/quarto-dev/q2/commits/f182b957), [`ee4b05cd`](https://github.com/quarto-dev/q2/commits/ee4b05cd), [`44df8fd3`](https://github.com/quarto-dev/q2/commits/44df8fd3), [`d1d01dd9`](https://github.com/quarto-dev/q2/commits/d1d01dd9), [`9bbbaccb`](https://github.com/quarto-dev/q2/commits/9bbbaccb), [`84d0e919`](https://github.com/quarto-dev/q2/commits/84d0e919), [`0998e72d`](https://github.com/quarto-dev/q2/commits/0998e72d), [`becc7789`](https://github.com/quarto-dev/q2/commits/becc7789), [`eda6e152`](https://github.com/quarto-dev/q2/commits/eda6e152), [`5ced2bc4`](https://github.com/quarto-dev/q2/commits/5ced2bc4), [`c2454356`](https://github.com/quarto-dev/q2/commits/c2454356).
39-
40-
### 2026-05-06
41-
42-
- [`a5e00b20`](https://github.com/quarto-dev/q2/commits/a5e00b20): Setting `format: q2-preview` in a document's YAML frontmatter now drives the live preview through the q2-preview pipeline — full shortcodes, Lua filters, sectionize, crossref, sidebar/navbar metadata, embedded image artifacts — rendered through the AstIframe alongside q2-debug. Read-only in v1: component-driven edits (kanban drag, future comment buttons) silently no-op with a console warning; Plan 7 lifts that guard.
43-
- [`845e8e71`](https://github.com/quarto-dev/q2/commits/845e8e71): Internal API extension for q2-preview Plan 1 — `RenderResult` gains an optional `ast_json?: string` field (paired with the existing `html?`). No user-visible behavior change yet; consumers of `renderQmd` / `renderPageInProject` see the same JSON envelope for HTML responses.
18+
- [`68e5ec24`](https://github.com/quarto-dev/q2/commits/68e5ec24): Custom syntax highlighting now works in Quarto Hub projects (bd-izfv) — user-supplied tree-sitter grammars under `_quarto/grammars/<lang>/` now apply to code blocks even when the qmd file lives under a `_quarto.yml` ancestor, matching the single-file render path.
19+
- [`915f1a3a`](https://github.com/quarto-dev/q2/commits/915f1a3a): New `format: q2-preview` drives the live preview through the q2-preview pipeline — shortcodes, Lua filters, sectionize, crossref, sidebar/navbar metadata, embedded image artifacts, footnote numbering, and appendix structure. Renders through the iframe alongside q2-debug. Read-only in v1: component-driven edits (kanban drag, future comment buttons) silently no-op with a console warning.
20+
- [`eb07797b`](https://github.com/quarto-dev/q2/commits/eb07797b): Fix iframe-host crash when typing `render-components:\n -` (empty list bullet) into a document's YAML frontmatter; empty entries are now skipped silently.
4421

4522
### 2026-05-05
4623

0 commit comments

Comments
 (0)