Skip to content

Show markdown fences rendered, with a Source toggle - #330

Open
rnc505 wants to merge 5 commits into
block:mainfrom
rnc505:morty/markdown-fence-toggle
Open

rnc505 wants to merge 5 commits into
block:mainfrom
rnc505:morty/markdown-fence-toggle

Conversation

@rnc505

@rnc505 rnc505 commented Nov 13, 2026 •

Copy link
Copy Markdown

What changed and why

A plan often holds a draft written in Markdown, such as a project update or a release note, inside a ```markdown fence. The reading view shows that draft as raw code, so readers cannot see how it will look when it is posted.

In the reading view, a fence tagged markdown or md now shows its body rendered, with a Rendered / Source toggle in the block header, where the markdown label used to be.

  • Each page load starts on Rendered. A choice made on the page survives live updates until the next navigation, including edits to the block itself. A per-user default view comes in a stacked follow-up PR.
  • The rendered body is read-only. Task boxes do not toggle. Headings stay out of the outline and get no ids. Footnotes are scoped to the block and shown inside it. Tables retain the existing expander and signed cell comments. Click a cell to browse; C or Comment opens its discussion.
  • Only a fence the parser produced qualifies. Like math, the <pre> must sit at the unique position of a markdown/md code block in the AST, so authored HTML cannot imitate one.
  • Scope is the reading view only. Decks, editor previews, and comment bodies still show the fence as code.

Comments work in both views

The hidden source <pre> stays in the DOM in both views, and it stays the text that anchors count and match. The rendered pane and toolbar are kept out of the anchor text model. So occurrence numbering for the whole document is the same in either view, and the server's anchor resolution is unchanged.

  • The server stamps rendered elements with body-relative offsets from nested sourcepos (data-markdown-from/data-markdown-to). The browser aligns each rendered text node with parser-backed visible text and complete source spans inside that range. It reuses MarkdownTextExtractor, including entity and escape handling.
  • A selection in Rendered is mapped to the matching source range and stored as raw source text. For example, selecting across a link stores release notes](https://example.com/r/42) for details.
  • Expanded-table comments use existing signed table_cell targets translated into full-plan offsets; Source shows the same cell discussion.
  • A comment made in either view is highlighted in both. When Rendered shows, highlights that fall in the hidden source are drawn over the matching rendered text.

Known limits

  • A selection that covers only text with no source counterpart (footnote numbers) offers no comment.
  • Writing provenance highlights the source view only.
  • Keep rendered diagram source inline, with the skill that edits it #323 also touches markdown_helper.rb, text_selection_controller.js, and markdown.css. The changes do not overlap in purpose, but one of the two will need a rebase.

docs/SOURCE_COMMENTS.md and the served Markdown guide describe the behavior. The demo library has a new example, Markdown blocks: rendered drafts, with a seeded comment thread.

Evidence

Rendered, light

Rendered, light

Rendered, dark

Rendered, dark

Source, light

Source, light

Source, dark

Source, dark

How to try it

Use the shared demo setup and sign in as hampton@example.com. Open /hampton/demo-library and choose Markdown blocks: rendered drafts.

  1. Expect the project update draft rendered, with Rendered pressed. The seeded comment on "The November rollout is done." is highlighted over the rendered text.
  2. Choose Source. Expect the raw fence with the same comment highlighted. Choose Rendered to go back.
  3. In Rendered, select text across a link or bold text, press c, and comment. Expect the highlight in both views.
  4. Double-click a table cell, press C, and post a comment. Switch that block to Source and expect the correct cell highlighted.
  5. Reload. Expect the block back on Rendered.

Testing

  • spec/system/markdown_blocks_spec.rb: the toggle and outline exclusion, a rendered selection stored as source and highlighted in both views, a source comment shown over rendered text, repeated text anchored to the selected copy, text after formatting mapped to the following copy, emoji offsets and footnote numbers, and the view kept through live updates that add a block or edit this one.
  • spec/helpers/slideshows_helper_spec.rb: block structure and offsets, read-only body, scoped footnotes, md fences, untouched text fences and decks, the forgery guard, and no output for non-interactive renders.
  • spec/lib/development_seed_spec.rb: the demo example and its comment thread.
  • Full local CI: bin/ci --jobs 6 --browser-jobs 3 on 914f6d6. Codex fixes in 67bd344 pass the markdown block and helper specs. All spec, browser, and seed jobs pass. gem-audit (action_text-trix advisories in the existing lockfile) and brakeman (version check) fail locally for reasons outside this change. This PR does not touch the lockfile.

🤖 Generated with Claude Code

Review fixes generated with Codex.

In the reading view, a fence tagged markdown or md shows its body
rendered, with a Rendered / Source toggle in the block header. Each page
load starts on Rendered. A choice made on the page survives live updates.

The hidden source <pre> stays the anchor text model in both views, so
occurrence counting and the server's anchor resolution are unchanged.
Rendered elements carry body-relative UTF-16 offsets from nested
sourcepos. The browser maps a rendered selection to its source range,
and draws source highlights over the rendered text when Rendered shows.
Only fences at a unique AST code-block position qualify, like math.

Adds a demo library example with a seeded thread, the served Markdown
guide paragraph, and docs in SOURCE_COMMENTS.md.

Co-authored-by: Morty <c46e15f3155e21a9867573fedb70ce905ff1ec43f80f234e6ad56dafae0fb88c@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rnc505
rnc505 requested a review from HamptonMakes as a code owner November 13, 2026 20:16
@HamptonMakes

Copy link
Copy Markdown
Collaborator

🤖 @codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: 🔄 Running

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-11-13T21:01:14.406139Z 0a865e1 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 914f6d6335

ℹ️ 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".

Codex review on block#330:

- Text after a formatted child now searches past it. Each mapped run
  advances its ancestors' cursors, so " bar" in "**foo bar** bar" maps
  to the second copy, not inside the bold phrase.
- A block's view survives an edit to its own text. Its choice falls back
  to the block's position while the number of blocks is unchanged.
- Tables in a draft render plain. The table expander has no way to
  comment on a draft's cells, so selection in the pane stays the path.

Co-authored-by: Morty <c46e15f3155e21a9867573fedb70ce905ff1ec43f80f234e6ad56dafae0fb88c@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@HamptonMakes

Copy link
Copy Markdown
Collaborator

🤖 I am preparing this PR in an isolated checkout. I saw and fetched 67bd344 and will preserve that commit and its regression coverage before publishing anything. My additional checks found entity-span mapping gaps (© / © and &), a deck-position forgery case, and authored ID collisions. I also have signed draft-table targets wired through the existing table comment/OT path so expanded tables retain Comment/C, plus a live-update position mapping check for identical drafts. I will reconcile the overlapping fixes, run focused checks, and post the exercised preview/evidence. No approval or merge.

Signed-off-by: Hampton Lintorn-Catlin <hampton@squareup.com>
@HamptonMakes

Copy link
Copy Markdown
Collaborator

🤖 @codex review

@HamptonMakes

HamptonMakes commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

🤖 Review preparation for 0a865e1d (preserves Robby’s 67bd3444):

  • Reused parser-backed source spans for exact text/entity/escape mapping; added guards for borrowed deck positions and authored IDs.
  • Kept expanded-table Comment/C through the existing signed cell-target path. The same discussion highlights in Source and survives unrelated edits. Source view also survives draft edits and insertion of an identical draft through the existing live-update swap/shared diff.
  • Latest fixes also map dictated draft quotes back to source, exclude invisible image-alt/generated-footnote candidates, route j/k to the visible pane, and highlight empty-cell delimiters.
  • Passed 74 source-mapping/draft-browser checks and 149 source-comment/navigation/voice/rendering checks on the latest code; the earlier full focused group passed 250 examples and editor/table integration passed 66. Voice recognition/interpretation was simulated, without a real microphone test. Light/dark, 390px viewport, keyboard toggle, and an actual expanded-table comment were exercised. Exact-head CI and Codex re-review are running; the centralized review of 1d5c5d4 is still pending; no approval or merge performed.
  • Recommendation: accept this reading-view feature once the current checks/review are clean. It makes embedded drafts readable while preserving the source/comment workflow. Maintenance cost is concentrated in the source mapping; the fixes reuse existing parsing, signed targets, diff, viewport, cache, and browser synchronization. Add a read-only Preview mode to the document editor #329 and preferences remain separate.
  • Integration: a branch-comparison check against Keep rendered diagram source inline, with the skill that edits it #323 found conflicts in markdown_helper.rb and writing_provenance_controller.js. No branches were combined. Preserve both sets of text exclusions and renderer hooks when the landing order is decided.

TRY THIS: running local demo. Sign in as hampton@example.com (no password), or start at /hampton/demo-library → Markdown blocks: rendered drafts. Toggle Rendered/Source; select text and press C; double-click the Web retry-budget cell and press C. The posted preview discussion is also highlighted on that exact source cell. The isolated server and database remain available for Hampton’s tryout.

Exercised screenshots

Rendered, light:
Rendered light

Source, dark:
Source dark

390px viewport, dark:
Mobile dark

Expanded table with keyboard-focused comment composer:
Expanded table comment

@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: 1d5c5d4884

ℹ️ 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".

Signed-off-by: Hampton Lintorn-Catlin <hampton@squareup.com>
Signed-off-by: Hampton Lintorn-Catlin <hampton@squareup.com>
@HamptonMakes

Copy link
Copy Markdown
Collaborator

🤖 @codex review

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.

2 participants