feature: q2-preview (not yet editable)#171
Merged
Merged
Conversation
gordonwoodhull
added a commit
that referenced
this pull request
May 10, 2026
Latest nightly causes rustc to SIGSEGV when compiling tokio for wasm32-unknown-unknown under -Zbuild-std=std,panic_unwind. PR #171 hits this in the "Build WASM module" step on both ubuntu-latest and macos-latest matrix legs of TS Test Suite. Mirrors the equivalent fix on chore/e2e-ci for hub-client-e2e.yml (commits d06e120 + ff51584): pin via the workflow's RUSTUP_TOOLCHAIN env var so rust-toolchain.toml stays as floating "nightly" for local developers, and switch the dtolnay action to @master with a toolchain input (the action no longer accepts @nightly-<date> refs).
gordonwoodhull
added a commit
that referenced
this pull request
May 10, 2026
Latest nightly causes rustc to SIGSEGV when compiling tokio for wasm32-unknown-unknown under -Zbuild-std=std,panic_unwind. PR #171 hits this in the "Build WASM module" step on both ubuntu-latest and macos-latest matrix legs of TS Test Suite. Mirrors the equivalent fix on chore/e2e-ci for hub-client-e2e.yml (commits d06e120, 245cd25, ff51584): - Pin via the workflow's RUSTUP_TOOLCHAIN env var so rust-toolchain.toml stays as floating "nightly" for local developers. - Switch the dtolnay action to @master with a toolchain input (the action no longer accepts @nightly-<date> refs). - Request rust-src and wasm32-unknown-unknown explicitly on the pinned toolchain. Under floating @nightly rustup auto-installed missing components against the active toolchain; once pinned they must be requested for that toolchain or the build:wasm step fails with "library/Cargo.lock does not exist, unable to build with the standard library".
7845516 to
fba1104
Compare
gordonwoodhull
added a commit
that referenced
this pull request
May 11, 2026
Latest nightly causes rustc to SIGSEGV when compiling tokio for wasm32-unknown-unknown under -Zbuild-std=std,panic_unwind. PR #171 hits this in the "Build WASM module" step on both ubuntu-latest and macos-latest matrix legs of TS Test Suite. Mirrors the equivalent fix on chore/e2e-ci for hub-client-e2e.yml (commits d06e120, 245cd25, ff51584): - Pin via the workflow's RUSTUP_TOOLCHAIN env var so rust-toolchain.toml stays as floating "nightly" for local developers. - Switch the dtolnay action to @master with a toolchain input (the action no longer accepts @nightly-<date> refs). - Request rust-src and wasm32-unknown-unknown explicitly on the pinned toolchain. Under floating @nightly rustup auto-installed missing components against the active toolchain; once pinned they must be requested for that toolchain or the build:wasm step fails with "library/Cargo.lock does not exist, unable to build with the standard library".
ac3eb9e to
b09f792
Compare
End-to-end implementation of the q2-preview pipeline in six steps: 1. Factor render_qmd / render_qmd_content into a shared render_single_doc_to_response so future format dispatch has one seam. 2. Pass2Payload enum + RenderResponse.ast_json. Internal API extension only; consumers still see the same HTML envelope. 3. Pipeline definitions + format detection (q2-preview as a format-string-driven pipeline_kind alongside html). 4. Rendering plumbing — entry point, renderer, dispatch. 5. WASM bridge dispatch — q2-preview reachable from JS. 6. hub-client TS — q2-preview reachable from the editor UI; setting `format: q2-preview` in YAML frontmatter routes through the full shortcodes/Lua/sectionize/crossref pipeline and renders into the AstIframe alongside q2-debug. Read-only in v1. Ships alongside the initial drafts of the 8-plan q2-preview epic (plans 1, 2, 3, 4, 6, 7, 7a, 8) sequenced in landing order. Cross-plan contracts pinned: By::is_kind / By::as_filter helpers in Plan 4, is_atomic_custom_node registry in quarto-core per Plan 7, explicit Plan 6 → Plan 4 audit-feeds-builders flow.
…-debug/ Phase 1: carve the q2-debug renderer into framework/ (format-agnostic recursive dispatch, types, typed registry contract) and q2-debug/ (bordered-box leaves, dispatchers, format registry, iframe wrapper, entry point) behind a re-export shim. PandocAST imports consolidated to framework/types; slide-side types unified with the framework. Phase 2: sixteen incremental steps rename and rewire the iframe seam. The iframe route renames from /ast-renderer.html to /q2-debug.html; the iframe component from AstIframe to Q2DebugIframe; the format registry from componentRegistry to q2DebugRegistry. q2-debug/entry.tsx becomes the new entry point. Dead code removed: transpileAndImportTSX, ReactAstRenderer.tsx, ast-renderer-entry.tsx, ast-renderer.html, the Phase-1 shim. The __REACT_AST_DEBUG_RENDERER__ window global is preserved for user-TSX consumers. Behavior preservation verified end-to-end; the bordered Figure no longer renders the literal `// TODO:` placeholder text. MathInline added to the InlineNode union. Bundled plan amendments: Plan 2 split into 2A (iframe foundation) + 2B (builtin components); Plan 2A review applied to plans 1/2A/2B/6; Plan 2pre restructure plan; latent-bug references linked to bd-3gtn; wire-format source-info code-allocation policy; soft-drop atomic semantics across plans 4/7/8.
New q2-preview/ ships parallel to q2-debug/: Q2PreviewIframe, registry skeleton (Block/Inline placeholder dispatchers + PreviewDocument), entry.tsx with module-top message listener and __Q2_PREVIEW_RENDERER__ global, 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. ReactRenderer's combined format branch split into distinct q2-debug / q2-preview branches; render-components gate extended to cover both. Shared utilities added: iframeLinkHandlers.ts (event-delegation extraction), sourceInfo.ts, atomicCustomNodes.ts, artifactPaths.ts. RegistryContext extended with sourceInfoPool? (Plan 2B atomic-aware gate consumer). q2-debug's __REACT_AST_DEBUG_RENDERER__ hoisted to module top. q2-preview pipeline constructed as the HTML pipeline minus exclusions so future drift stays minimal. Two theme fixes: theme_fingerprint is now captured at the pass-2 renderer level (surviving both default-project flush and website merge); theme CSS is written to /.quarto/project-artifacts/styles.css in both single-doc and project mode so the iframe path is stable. Iframe boots empty in 2A — every Pandoc node renders as a muted-gray "(not yet implemented)" placeholder. Plan 2B fills the registry. Bundled plan amendments: convert smoke-gates in plans 2A/2B/live-reload to automated equivalents; revise plans 2A + 2B for Design B (blob-URL asset transport via parent-side walker).
Phase 1 — framework foundation. customNode.ts ships unwrap/rewrap
walks (mirrors the Rust JSON writer/reader for __quarto_custom_node
Div/Span wrappers, structural-sharing pure to preserve subtree
identity for the future Note-numbering WeakMap). Atomic-aware gate
inside framework/dispatch.tsx's Node no-ops setLocalAst for Derived /
atomic Synthetic / atomic CustomNode subtrees. framework/Ast.tsx
accepts a discriminated input (string OR pre-parsed AST), unconditionally
unwraps custom-node wrappers, and fills the RegistryContext.sourceInfoPool
value that Plan 2A had only typed. blockTypes extended from 11 to 19
entries.
Phase 2.1a — extract hub-client/src/utils/vfsPaths.ts.
resolveRelativePath, normalizePath, and guessMimeType had three private
copies; consolidating to one module avoids fanning out further when the
asset walker becomes the fourth consumer.
Phase 2 — asset manifest plumbing. q2-preview/assetWalker.ts walks the
AST for Image nodes, resolves paths via vfsPaths, reads VFS bytes, and
mints (or reuses cached) blob URLs. Cache identity is the base64 content
string itself — synchronous, deterministic, no hash. External URLs
filtered out at walk time. AssetManifestContext distributes the
{origPath → blobUrl} map; Q2PreviewIframe owns the cache (drained on
unmount) and extends UPDATE_AST to carry the manifest alongside the
AST. entry.tsx's setAst callback now rewrapCustomNodes() back to wire
format before posting SET_AST.
Phase 3 — built-in registry of 14 Block + 20 Inline components. Image
is a pure AssetManifestContext consumer (no VFS access in the iframe).
Math is a near-verbatim port of the Elliot Math leaf with 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).
Pipeline: include FootnotesTransform + AppendixStructureTransform in
q2-preview (both produce pure Pandoc primitives that 2B's leaves
render natively).
Phase 5 — verification: smoke-all q2-preview/image-with-attrs fixture
(1×1 PNG sibling) + assetManifestProject.wasm.test.ts mirror of
themeFingerprint.wasm.test.ts that renders a _quarto.yml-rooted project
doc with a project-relative Image. Inline-footnote pipeline output
pinned via quarto-core test.
Bundled plan amendments: Plan 2B post-2A audit (customNode override,
transform inclusions); plans 3+7 transform inclusions + Transparent
enumeration; Plan 2B implementor-detail pass + Note fallback spec
(bd-1kly); explicit `cargo xtask verify --e2e` gate at step 5.5;
monolithic 2B split into Session A (2B) + Session B (2C).
After a pass-2 render the WASM bridge flushed every artifact back to VFS, including empty-content placeholders (Vec::new()) that the render had emitted for already-uploaded user assets. Those zero-byte writes overwrote the real user-uploaded bytes already in VFS. Guard the flush loop to skip empty content. Test added at quarto-core level asserts user-uploaded image bytes survive a q2-preview render.
Phase 4.1: extend quartoClasses.ts with callout/theorem/proof/quarto-xref taxonomy. Phase 4.2: utils.ts → utils.tsx; add theoremEnvs.ts. Phase 4.3: six CustomNode components (Callout, Conjecture, Definition, Proof, Theorem, quarto-xref) + a generic Fallback for unknown type_names. Phase 4.4: CustomBlock and CustomInline dispatchers wire the registry. Phase 5 verification: Phase 5.1 vitest tests cover the six components plus the namespace policy. Phase 5.2 smoke-all fixtures cover multi-element + project + render-components. Phase 5.3 customNodeWireFormatProject.wasm.test.ts pins the wire-format round-trip. Phase 5.5 e2e fixture corrections + IndexedDB polyfill land for the browser leg. Bundled plan amendments: post-2B-implementation amendments to Plan 2C (registry unification under a single CustomNode dispatcher); Plan 2D body-container draft.
q2-preview gains a body-level container plus a title-block component. Plan-2d doc extended with title-block scope + post-2C-landing alignment notes.
Empty strings in the YAML render-components list crashed the parser. Skip empty entries silently rather than erroring.
Migration plan for moving ReactAstSlideRenderer.tsx (SlideAst carousel) and RevealjsReactAstSlideRenderer.tsx (RevealjsSlideAst) into a shared hub-client/src/components/render/q2-slides/ directory, completing the hub-client format-restructure that 2pre started. §2 (two registries sharing leaves) is locked: q2SlidesRegistry and revealjsRegistry both spread the same blocks/inlines modules and differ only on the 'Ast' document-root entry. §1 (iframe boundary), §3 (SlideContext shape), §4 (asset resolution), §5 (editing wiring), and §6 (migration strategy) are open with recommendations. Phased shim approach (Phases 9-13) mirrors 2pre's pattern: build q2-slides/ behind a re-export shim, migrate four consumers (ReactRenderer, RevealjsReactAstSlideRenderer, useCursorToSlide, useSlideThumbnails) one commit at a time, then delete the shim. Depends on Plan 2D Phase 6.0 (framework/meta.ts) landing first.
…ing 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.
b09f792 to
f6206e1
Compare
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.
The major restructuring is done and q2-preview lives alongside q2-debug
q2-debug and q2-preview are refactored as independent react-formats.
There is a draft plan
claude-notes/plans/2026-05-10-q2-preview-plan-2e-q2-slides-migration.mdfor migrating q2-slides and the React revealjs format to the same architecture, but it has many open questions and is out of scope for this PR.Pandoc and custom nodes are all at parity with the html format; a basic page container and title block are also assembled.
Editability is 5 plans away, but we could merge this sooner, as it is safe and independent.