fix(presentations): separate slides with a thematic break - #32
fix(presentations): separate slides with a thematic break#32Ready22Race wants to merge 1 commit into
Conversation
The three presentation parsers concatenate every slide's blocks into one list with nothing between them. A slide's title becomes a heading, so decks that title every slide read correctly by accident — but a slide with no title placeholder contributes no structural block at all, and its content becomes indistinguishable from the previous slide's. Two title-less slides in a row produce two adjacent paragraphs, exactly as if they were two paragraphs of one slide. Bullet lists from different slides merge into one list. This is not the pagination that "Markdown has no pages" rightly refuses. A slide is a container in the source model, not a layout artifact, and losing its boundary loses document structure. Block::Rule is the separator the model already has (emitted for <hr>, rendered as ---), so no new concept is introduced and no page number is implied. Emitted BETWEEN slides only: never leading, and a slide that produces no blocks never yields a doubled or dangling break. Applies to pptx, ppt and odp, which all had the same shape. Core-only: every binding already maps model::Block::Rule (node/src/ document.rs:88, python/src/document.rs:83, wasm/src/document.rs:96) and already declares the `rule` kind (node/index.d.ts:60, python/anydoc/_anydoc.pyi:84, wasm/src/typescript.rs:47), so no binding source or type surface changes.
|
Independent verification, for whatever it's worth — we hit #31 on a Pandoc-authored deck while evaluating anydoc as the conversion engine for our ingestion pipeline, before finding the issue already filed. Checked out
One note for anyone reading along, orthogonal to this PR: on that same deck the remaining structure loss is bullet formatting inherited from the layout ( |
…(independently verified) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Independent verification. We're evaluating anydoc as the extraction layer for a documentation-ingestion pipeline that consumes the document model rather than the Markdown serializer, so slide boundaries are load-bearing for us. In fairness: we tested this PR and #95 against the same deck, and we've posted parallel notes there. Both work; the differences are below. Setup: checked out from
Document model. Baseline v0.1.9 gives 4 top-level blocks with no marker of any kind — The untitled slide 2 separates correctly, exactly as the PR describes, and the never-leading / never-doubled guarantees hold on our fixture. Where it left us short, and why we'd bet on #95. Our output format numbers slides ( The secondary point is that One thing this PR has that #95 does not: ODF coverage. On The two conflict: this applies cleanly to None of this is a knock on the change — it does what it says and the reasoning in the description is sound. Posting the comparison because a maintainer choosing between two competing PRs is better served by it than by a thumbs-up on each. |
Fixes #31.
What
Emits
Block::Rulebetween slides in the three presentation parsers (pptx,ppt,odp), which previously concatenated every slide's blocks with nothing in between.A slide's title becomes a
Heading, so decks that title every slide read correctly by accident. A slide with no title placeholder contributes no structural block, so its content is indistinguishable from a continuation of the previous slide — two untitled slides in a row produce two adjacent paragraphs, and bullet lists from different slides merge into one list.Why a thematic break
No new concept and no page number:
Block::Rulealready exists, is already emitted for<hr>(src/shared/html.rs:432), and already renders as---(src/render/markdown/mod.rs:201).This is deliberately not the pagination #26 declined. That issue settled that a
w:type="page"break is layout and dropping it is correct. A slide is a container in the source model rather than a layout artifact, so its boundary is document structure.Shape of the change
Each parser now accumulates one slide into a local
Vec<Block>and appends it only if non-empty, pushing aRulefirst when output already exists. That gives two guarantees worth stating:---before the first slidepptalready accumulated per slide, so it only needed the guard.Scope: core only, no binding changes
Block::Rulealready exists and every binding already handles it, so nothing outsidesrc/formats/needs to move:model::Block::Rulerulekindnode/src/document.rs:88node/index.d.ts:60python/src/document.rs:83python/anydoc/_anydoc.pyi:84wasm/src/document.rs:96wasm/src/typescript.rs:47No new
Blockvariant, no public API change, no type-surface change. Confirmed end to end through the Python binding on the deck from the issue:Tests
Three unit tests in
src/formats/pptx/mod.rs, building minimal packages in memory in the style of thesheetmodule's tests — they pin the behaviour rather than just the output:untitled_slides_are_separated— the defect itself: two title-less slides must not read as oneseparator_never_leads— a deck must not open with---, and a single slide yields only its own contentempty_slides_leave_no_dangling_separator— a slide contributing no blocks must not add a break, neither doubled between two real slides nor trailingVerification
Snapshot delta is 6 added
---lines and 6 added blank lines across 6 snapshots, with zero removals — no content changed, only separators appeared:Also checked by hand against a deck whose slides 2 and 3 have no title placeholder (the case in the issue) and against
tests/fixtures/ppt/pres.ppt.Note
Happy to take this in a different direction if you would rather the boundary be expressed some other way, or scope it to a subset of the three parsers. The behaviour change is visible in output, so it is your call whether it belongs in a minor bump.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.