Blocks like `<details class="bordered-when-open">` with `<summary class="...">` were not recognized because the shape regexes only allowed an optional `open` attribute on <details> and none on <summary>. Such blocks fell back to native rendering, showing the Markdown body as literal text. Widen OPENING_LINE and SUMMARY_LINE to accept any attribute list while still rejecting look-alike tag names (e.g. <detailsfoo>). The native <summary> element is preserved, so its class survives for CSS snippets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| ai_input/auto_load | ||
| docs-internal | ||
| scripts | ||
| src | ||
| test | ||
| test-vault-notes | ||
| .gitignore | ||
| esbuild.config.mjs | ||
| LICENSE | ||
| manifest.json | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| req.md | ||
| styles.css | ||
| tsconfig.json | ||
| versions.json | ||
Details Markdown
An Obsidian plugin that renders Markdown inside native HTML
<details>/<summary>
blocks. Obsidian intentionally does not parse Markdown inside raw HTML blocks, so
headings, lists, tables, internal links, and embeds inside a <details> fold show
as literal text. This plugin fixes that: the body renders as real Markdown, visually
identical to the same content written outside the block.
Scope: Rendering happens in Reading view. Live Preview (the editor) is not yet supported — there, the block shows Obsidian's native output. Support for Live Preview is planned for a future release.
Supported block shape
<details>
<summary>Summary text</summary>
### Any markdown body
- lists, [[internal links]], tables, embeds, code fences
blank lines in the body are supported (incl. inside code fences)
</details>
<details>on its own line; anopenattribute is allowed.<summary>...</summary>is optional and single-line, immediately after<details>.- The body is everything up to
</details>, on its own line. - Unsupported, malformed, or unclosed blocks are left untouched (native behavior).
- Rendering the
<summary>text itself as Markdown is out of scope.
Settings
A single toggle enables or disables the plugin. When off, Obsidian's native (literal) behavior returns with nothing left behind.
Installation
From the Community Plugins directory
Settings → Community plugins → Browse → search for "Details Markdown" → Install → Enable.
Manual
Copy manifest.json, main.js, and styles.css into
<vault>/.obsidian/plugins/details-markdown/, then enable the plugin in
Settings → Community plugins.
Development
npm install
npm test # unit tests (parser)
npm run build # typecheck + bundle -> main.js
npm run dev # watch mode
Manual acceptance tests: test-vault-notes/Details Markdown Acceptance.md.
How it works
Obsidian ends an HTML block at the first blank line, so a <details> body with
blank lines is split across several render sections and its tail "escapes" the
fold. The plugin re-assembles blocks from raw source (never from rendered DOM):
DetailsRangeScannerscans the full note text for supported block line ranges (fence-aware, nesting-aware; unclosed blocks yield no range).SectionRoleClassifierdecides per rendered section: opening (starts a block) → render the whole body viaMarkdownRenderer.renderinto the existing<details>element (native<summary>andopenattribute preserved); fragment (escaped content inside a block) → hidden, but only once its block's opening actually rendered, so content can never be lost.- A
MarkdownRenderChildregistered viactx.addChildties embeds/lifecycles to the note, so nothing leaks when the note closes. A registry reconciles edits: interior edits re-render the fold body in place; deleting a block boundary restores native output.