Skip to content

Markdown slideshows phase 1: plan-type behavior, deck split, per-slide rendering - #189

Open
HamptonMakes wants to merge 2 commits into
mainfrom
claude/coplan-markdown-slideshows-38c443
Open

Markdown slideshows phase 1: plan-type behavior, deck split, per-slide rendering#189
HamptonMakes wants to merge 2 commits into
mainfrom
claude/coplan-markdown-slideshows-38c443

Conversation

@HamptonMakes

Copy link
Copy Markdown
Collaborator

Phase 1 (foundation) of markdown slideshows. A deck is a rendering convention over the plan's single markdown blob — nothing new is persisted, so versioning, diffs, and comment anchoring keep working unchanged. Design doc: CoPlan plan 01a01696-aad6-762b-ad66-7681bbadd98c (rev 4).

What's here

Plan-type behavior. Plan types gain a behavior column (document / slideshow, string enum + inclusion validator), and Plan#slideshow? delegates to it — retyping a plan is what converts a document into a deck and back. Ships a Slideshow default type (installable via coplan:plan_types:install_defaults) whose template teaches the authoring conventions, plus admin support, a presentation icon, and a seeded showcase deck that exercises every convention.

Slideshows::Split. Splits markdown into slides at top-level --- thematic breaks, AST-driven so a --- inside a code fence, blockquote, or setext heading never splits, and ***/___ stay visible rules. Extracts <!-- notes: ... --> speaker notes and gathers footnote/link-reference definitions as positioned blocks so slides can render in isolation. Link-definition candidates are validated by a parser round-trip (parse the candidate alone; it must be fully consumed), which is what keeps [looks]: like-a-definition prose from being hoisted onto every slide.

SlideshowsHelper#render_slideshow. Renders each slide through the standard document pipeline — same sanitization, mention chips, interactive checkboxes — inside section.deck-slide wrappers. Checkbox data-line stays document-absolute via a new line_offset param on render_markdown (no output change for existing callers; no cache bump needed). Footnote sections are excluded per slide and marks are renumbered to match the document-wide References back matter, including document-mode fnref ids so every ↩ backref resolves.

Notes for reviewers

  • Definitions are prepended per slide, not appended: an unclosed code fence on a slide would swallow an appended block into visible text, and prepending makes the document's first definition of a duplicated key win everywhere, matching document mode.
  • Commonmarker quirk worth knowing: a fragment containing a duplicated footnote definition gets its whole body swallowed into the footnotes section. The per-slide preamble therefore skips footnote keys the slide defines itself (fold-normalized — [^straße]/[^STRASSE] are the same label to the parser), and unreferenced footnote definitions (which the parser prunes from the AST) are never gathered as link blocks.
  • Deck-specific code is deliberately isolated (Slideshows:: services, own helper, deck-* class namespace) with no hooks into document rendering, so the layout engine can be extracted as a standalone spec + stylesheet later.
  • Verified with two adversarial multi-agent review rounds; all 18 confirmed findings are fixed and pinned by regression specs. Full suite: 1628 examples, 0 failures.

Next phases (separate PRs): slide design system + layout classifier, deck view, presenter overlay, agent fit report.

🤖 Generated with Claude Code

…ring

Phase 1 of markdown slideshows (design: CoPlan plan 01a01696-aad6, rev 4).
A deck is a rendering convention over the plan's single markdown blob —
nothing new is persisted, so versioning, diffs, and comment anchors keep
working unchanged.

- PlanType gains a behavior column (document/slideshow); Plan#slideshow?
  delegates to it, so retyping a plan converts it. Ships a Slideshow
  default type (installable via coplan:plan_types:install_defaults) whose
  template teaches the conventions, plus a seeded showcase deck.
- Slideshows::Split turns markdown into slides at top-level `---` breaks
  (AST-driven: fences, blockquotes, setext, `***` never split), extracts
  <!-- notes: --> speaker notes, and gathers footnote/link-reference
  definitions as positioned blocks so slides can render in isolation.
  Candidate definitions are validated by a parser round-trip, so prose
  lookalikes are never hoisted onto other slides.
- render_slideshow renders each slide through the standard document
  pipeline (same sanitization, mentions, checkboxes) inside
  section.deck-slide wrappers. Definitions are prepended per slide
  (skipping footnote keys the slide defines — commonmarker swallows
  fragments containing duplicated footnote definitions), footnote marks
  are renumbered to match the document-wide References back matter, and
  checkbox data-line stays document-absolute via render_markdown's new
  line_offset.

Verified with two adversarial review workflows; every confirmed finding
is pinned by a regression spec.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 40c45e1283

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread engine/app/services/coplan/slideshows/split.rb
Comment thread engine/app/helpers/coplan/slideshows_helper.rb
Codex review of #189 flagged that per-slide rendering restarts both id
generators — comrak heading anchors (intro, intro-1, …) and numbered
section ids (section-1, section-1-2 via unique_dom_id) — so links
written against document mode went dead in the deck.

The document-mode render the deck already uses for footnote ordinals is
now the ground truth for everything numbered per document:

- align_heading_ids copies each body anchor's id+href and each
  heading's id positionally from the document render, gated on equal
  counts and pairwise content fingerprints (text, image sources, link
  destinations, checkbox states) so author HTML left open across a
  slide break — which parses differently per slide than in the
  document (foster-parenting, swallowed siblings) — can only skip the
  pass, never misassign an id.
- mirror_section_link_enhancement makes section preview affordances
  match document mode in both directions: cross-slide links gain them,
  stale per-slide ones (target id lost to an earlier claimant) lose
  them.
- drop_misleading_ids backstops the skips: any deck id whose
  document-mode owner shows different content is dropped rather than
  left pointing at the wrong thing (anchors validate by the heading
  they mark).
- renumber_deck_footnotes no longer counts author elements claiming to
  be a heading anchor and a footnote ref at once, so impostors can't
  shift real references off their back-matter backrefs.

Also pins the other Codex finding as specs: thematic breaks nested in
list items never split (doc.each only walks top-level nodes).

Verified with three adversarial review workflow rounds (9 agents); all
12 confirmed breaks fixed and spec-pinned, and the final round's
33-document mechanical parity sweep found deck output id-for-id
identical to document mode on legitimate content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant