Fix #1: Decompose build pipeline into collect/preprocess/render/index - #26
Fix #1: Decompose build pipeline into collect/preprocess/render/index#26AlexMikhalev wants to merge 3 commits into
Conversation
Phase 1 (disciplined-research) and Phase 2 (disciplined-design) for bringing md-book to contract parity with mdBook. Key finding: md-book has no SUMMARY.md parser. Structure is inferred from a path-sorted walkdir with sections named after parent directories, which accounts for 11 of 13 structural gaps and makes previous/next incorrect. Two output defects rank above missing features: absolute asset paths (breaks sub-path deployment) and CDN-loaded Shoelace (breaks offline viewing). Parity is scoped as the authored book contract, not mdBook internals; local decisions (Pagefind, Tera, Web Components, markdown crate, twelf, jiff, WASM) are retained and recorded as N/A rather than gaps. Five sequenced increments tracked as terraphim/md-book #1-#5. Refs #1, Refs #2, Refs #3, Refs #4, Refs #5 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three rounds of specification interview on the SUMMARY.md book model. Two decisions went against the drafted recommendation and change the API: - create-missing is honoured with mdBook's default of true, so the build writes stub files into src/; created paths are returned so the watcher can suppress the resulting events and avoid a rebuild loop. - Summary errors are collected in one pass and reported together rather than failing fast, so migrating a large book takes one build round-trip. parse_summary now returns SummaryErrors. The security dimension surfaced a requirement absent from the plan: path containment. SUMMARY.md names files to read and republish, which in CI can be untrusted PR input, so any path canonicalising outside src/ -- symlinks included -- is refused. The accessibility decision (nested <ul>, aria-current, disabled draft entries) is incompatible with a flat depth-tagged list because Tera macros cannot recurse; NavEntry gains open_lists/close_lists deltas so a single template loop emits correct hierarchy. Refs #2 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Extract the monolithic build_sync_impl_sync into named stages so later mdBook-parity increments target one stage each. Zero behaviour change: output is byte-identical to the pre-A baseline (72/72 assets). - src/pipeline: collect, run_sync, async index, identity preprocess seam - src/render: markdown (mdast+syntect) and html (Tera/assets) modules - src/core: Args + build orchestration only - Tests relocated with their code; preprocess identity covered Refs #1
AlexMikhalev
left a comment
There was a problem hiding this comment.
Dual review — Increment A (structural + pi openai-codex/gpt-5.5)
Structural PR Review (orchestrator)
Summary
Increment A extracts the monolithic build_sync_impl_sync into pipeline + render modules with zero behaviour change. Preprocess is an identity seam; directory-walk collection and the hard-coded "Guide" section are intentionally preserved for B.
Done well: clear stage boundaries, tests moved with their code, identity preprocess covered, byte-identical gate met (72/72).
No structural findings from local equivalence scan (preprocess on every chapter + index path; index still async-only under search+tokio).
Confidence Score: 5/5
- Safe to merge with minimal risk.
- Byte-identical output + full test suite + clean dual review. No P0/P1/P2.
- No files require special attention.
Important Files Changed
| Filename | Overview |
|---|---|
src/pipeline/mod.rs |
Stage orchestration; directory collect preserved |
src/pipeline/preprocess.rs |
Identity seam; unit tested |
src/render/markdown.rs |
mdast + syntect extracted intact |
src/render/html.rs |
Tera + assets extracted intact |
src/core.rs |
Thin Args + build orchestration |
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
build --> run_sync
run_sync --> collect
collect --> preprocess
preprocess --> render_md[render_markdown]
render_md --> render_page
run_sync --> index{search+tokio?}
index -->|yes| pagefind
index -->|no| skip
Inline Findings
No P0/P1/P2 findings.
Last reviewed commit: 06d3362 | Reviews (1) | Reviewer: structural-pr-review (orchestrator)
pi openai-codex / gpt-5.5 review
Summary
Increment A is a clean structural extraction of the former monolithic build path into the intended pipeline shape:
collectinsrc/pipeline/mod.rs- identity
preprocessinsrc/pipeline/preprocess.rs - markdown and HTML rendering in
src/render/markdown.rsandsrc/render/html.rs - async-only Pagefind indexing retained behind
search + tokio
The patch appears aligned with the stated constraints: no SUMMARY.md handling, no CLI changes, no path_to_root, no theme work, and preprocessing is explicitly identity today. The old build orchestration is preserved semantically: synchronous generation still happens first, and Pagefind indexing still only runs on the async tokio + search path after HTML generation.
I did not identify any P0/P1/P2 structural-semantic issues from the supplied diff. The main behavioural seams to keep covered in validation are golden-output equivalence across feature combinations, especially syntax-highlighting on/off and search on/off.
Confidence Score: 4/5
Confidence is high based on diff review: the moved functions appear equivalent, feature gates look coherent, preprocessing is invoked on page and index markdown, and Pagefind error swallowing remains behaviourally compatible with the old path. Confidence is not 5/5 because this review is based on the attached patch rather than running the full matrix locally.
Important Files Changed
| File | Role in Increment A | Review Notes |
|---|---|---|
src/core.rs |
CLI args and high-level build orchestration | Correctly delegates sync generation to pipeline::run_sync; keeps async Pagefind indexing gated on search + tokio. |
src/lib.rs |
Public module exports | Exposes new pipeline and render modules. |
src/pipeline/mod.rs |
Pipeline orchestration and collection stage | Implements collect → preprocess → render; keeps indexing separate and async-only. Directory-walk collection appears equivalent to previous behaviour. |
src/pipeline/preprocess.rs |
Preprocess stage seam | Identity implementation with tests; correctly returns original markdown content unchanged. |
src/render/markdown.rs |
Markdown-to-HTML fragment rendering | Extracts markdown options, link rewriting, and optional syntax highlighting from old core.rs; behaviour appears preserved. |
src/render/html.rs |
Tera setup, static assets, page/index rendering | Extracts template loading, asset copying, syntax CSS writing, and page/index assembly; behaviour appears equivalent. |
src/render/mod.rs |
Rendering module facade | Re-exports expected rendering APIs. |
Diagram
flowchart TD
A["core::build / build_impl"] --> B["pipeline::run_sync"]
B --> C["collect(input_dir)"]
C --> D["CollectedPages<br/>entries + all_pages + sections"]
D --> E["for each markdown page"]
E --> F["preprocess(md)<br/>identity today"]
F --> G["render_markdown"]
G --> H["render_page"]
D --> I["index.md present?"]
I -->|yes| J["preprocess(index.md)<br/>identity today"]
J --> K["render_markdown"]
K --> L["render_index"]
I -->|no| L
H --> M["HTML output files"]
L --> M
M --> N{"features: search + tokio?"}
N -->|yes, async path only| O["pipeline::index<br/>PagefindBuilder"]
N -->|no| P["skip indexing message"]
Inline Findings
No P0/P1/P2 findings.
Last reviewed commit: 06d3362 | Reviews (1) | Reviewer: pi openai-codex/gpt-5.5
🚀 Deployment PreviewYour changes have been deployed to Cloudflare Pages! 🔗 Preview URL: https://preview-26.md-book.pages.dev The deployment will be updated automatically when you push new changes to this PR. |
Summary
Increment A of mdBook feature parity (
docs/plans/mdbook-parity-implementation-plan.md).Pure refactor with zero behaviour change: the monolithic
build_sync_impl_syncis split into named pipeline stages so B–E each target one stage.Changes
src/pipeline/— collect → preprocess → render sequencing; async indexsrc/pipeline/preprocess.rs— identity seam for future P2 directivessrc/render/markdown.rs— mdast + syntect +.md→.htmllink rewritesrc/render/html.rs— Tera init, page/index writers, static assetssrc/core.rs— Args + build() orchestration onlyGate evidence
-D warningsgreentest_book_mdbook: 0.86 s (debug; Pagefind CLI absent)Docs
docs/verification/verification-report-mdbook-parity-a.mddocs/validation/validation-report-mdbook-parity-a.mddocs/plans/review-mdbook-parity-a.mdOut of scope
Refs #1