Nest markdown inside raw-HTML blocks separated by blank lines (#433)#686
Merged
Nest markdown inside raw-HTML blocks separated by blank lines (#433)#686
Conversation
…nk lines
CommonMark "type 6" HTML blocks (e.g. `<details>`) end at the next blank
line, so
<details>
**bold** content
</details>
reaches the renderer as three blocks: a `RawBlock` for `<details>\n`,
a `Para` for the markdown, another `RawBlock` for `</details>\n`. The
existing `<rawhtml>` wrapper trapped the open and close inside their
own elements, leaving the markdown paragraph a sibling of the (now
empty) details element instead of its child.
Fixed upstream in srid/heist-extra by a new `groupRawHtmlBlocks` AST
pass that walks every block list and rewrites orphan opener/closer
triplets into a `B.Div` with the tag in its `tag` attribute. The
existing Div renderer turns that into the named element, so the
markdown content lands as a real DOM child.
Pointing flake.lock at the heist-extra branch carrying the fix.
Closes #433.
Mirrors the #119 pattern: a fixture (tests/fixtures/notebook/rawhtml-details.md) exercises the issue's exact shape (a <details> tag with markdown content between blank lines) and a smoke scenario asserts the marker inside has a <details> ancestor in the rendered HTML. Without the heist-extra groupRawHtmlBlocks pass the marker would be a sibling of an empty <details>.
Owner
Author
…e bug)
The first cut of this scenario asserted closest('details') on the
parsed DOM. Browser HTML5 parsers recover the broken master output
into a DOM that *does* nest the marker under <details>, so a DOM-level
check passes either way. The bug is in the emitted HTML, not in the
recovered DOM.
Switch to fetching the raw HTTP response and verifying that the
opener and closer <details> tags have no immediately-adjacent
<rawhtml> wrapper. Confirmed: regex matches the broken pattern on
master (`<rawhtml ...><details>` + `<rawhtml ...></details>`),
fails to match on the fix.
Owner
Author
|
| Step | Status | Duration | Verification |
|---|---|---|---|
| sync | ✓ | 0s | git fetch ok; forge=github |
| research | ✓ | 11m 43s | Issue #433: orphan RawBlock html pairs in Pandoc AST get wrapped individually by heist-extra's rawNode. Fix belongs upstream in heist-extra. |
| branch | ✓ | 15s | Working on existing empty-group branch; created group-orphan-rawhtml-blocks in heist-extra for the dependency fix. |
| implement | ✓ | 7m 34s | Wrote groupRawHtmlBlocks pass in heist-extra (RawHtmlGroup module) + dropTagAttr fix in Render Div arm; 12 unit + 1 integration test. Updated emanote flake to point at it. |
| check | ✓ | 9s | cabal build all green. |
| docs | ✓ | 18s | Bug-fix entry under Unreleased in CHANGELOG. |
| fmt | ✓ | 1m 12s | just fmt clean on emanote; hlint+fourmolu also clean on heist-extra. |
| commit | ✓ | 39s | Heist-extra 970c9a3 pushed; emanote 8bca7a37 pushed. |
| hickey+lowy | ✓ | 9m 41s | 1 Hickey fix + 1 hoist (defer flipped); 1 Lowy fix + 3 hoist/doc (defers flipped). 3 follow-up commits on heist-extra. |
| police | ✓ | 10m 46s | All 3 passes clean after applying: extracted parseTagAfterPrefix, rehomed tag-directive helpers, trimmed comments. |
| test | ✓ | 53s | Emanote unit tests: 47/47. Heist-extra: 54 tests pinning AST + rendering. |
| create-pr | ✓ | 2m 25s | heist-extra#16 + emanote#686 (drafts); Hickey/Lowy analysis on the upstream PR. |
| ci | ✓ | 2m 32s | vira ci PASSED on aarch64-darwin + x86_64-linux. E2e-static/live/morph all green. |
| evidence | ✓ | 10m 3s | Before/after screenshots + emitted-HTML diff posted. Tightened e2e regression to fetch raw HTTP and verify no <rawhtml> adjacent to <details> (confirmed it fails on master, passes on fix). |
| Total | 58m 27s |
Slowest step: research (11m 43s)
Optimization suggestions
- Research dominated (20% of wall time). Most of that was reading the heist-extra
Render.hs/Render/Internal.hsto understand thegetTag-as-directive convention before designing the grouping pass. For future bug fixes that touch a downstream library, pre-reading the relevant module(s) before invoking/dowould shave the initial map step. - Evidence step ran two sequential
nix builds (master + this PR). The sub-agent could parallelise them (master build runs while feature build cache-hits), reclaiming roughly 2-3 minutes on bug-fix evidence captures. - Police's elegance pass landed two real refactors (extract
parseTagAfterPrefix, rehome the tag-directive helpers) that the initial draft missed. Worth running/simplify(or its equivalent) earlier inimplementfor non-trivial new modules — would catch the same findings before the first commit, avoiding the police-phase rework cycle. - Re-running
vira ciafter the evidence-driven test tightening added ~3 minutes. For follow-up runs on the same branch where only test code changed,/do --from ci-onlyskips research → police and goes straight to CI.
Workflow completed at 2026-04-28 21:50 UTC.
… .agency/do.md The fix in this PR makes <details> blocks separated by blank lines work as a disclosure widget with parsed markdown inside. Add a Raw HTML section to docs/guide/markdown.md showing the live syntax (and pointing back to callouts for the Emanote-native foldable variant), then update .agency/do.md so future Markdown-syntax features land their demo in the same file as a matter of convention.
Now that the upstream PR has landed, drop the branch ref so flake.nix tracks heist-extra master again. The locked rev advances from 3bd7aba to f496d0c (same tree — the merge was a fast-forward).
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.


Markdown content between two blank-line-separated raw HTML tags now nests inside the surrounding element instead of escaping to be its sibling. Pandoc emits CommonMark "type 6" HTML blocks like
<details>… markdown …</details>as three separate AST blocks (openerRawBlock,Para, closerRawBlock); without grouping, each raw blob ends up wrapped in its own element and the markdown paragraph drifts outside.The actual fix is upstream in srid/heist-extra#16, which adds a
groupRawHtmlBlocksAST-preprocess pass that rewrites those orphan triplets into aB.Divcarrying the tag in a directive attribute — the existingDivrenderer turns it into the named element with the markdown content as a real DOM child.This PR pins emanote to that branch and notes the fix under the
Bug fixessection of the unreleased changelog.Try it locally
Generated by
/doon Claude Code (modelclaude-opus-4-7).