Nested Markdown in HTML
unlistedby ByteAssembler
Render Obsidian Markdown and MathJax inside safe HTML container elements in Reading View and Live Preview.
Nested Markdown in HTML for Obsidian
Nested Markdown in HTML makes selected raw HTML containers Markdown-aware while deliberately keeping Obsidian's own Markdown pipeline.
It is built for notes where HTML is useful for styling or semantics, but the content inside that HTML should still support Markdown, MathJax, wikilinks, embeds, callouts, tables, and other Obsidian syntax.
[!IMPORTANT] This project is currently alpha software (0.1.x). It has extensive automated and real-runtime tests, but it is not yet published in Obsidian's Community Plugins directory. Back up important vaults and report reproducible edge cases.
The problem
Obsidian intentionally does not normally parse Markdown inside raw HTML elements. That means this source:
<mark>**bold** + $x^2$ + [[A note]]</mark>
can render the Markdown markers literally instead of producing formatted content.
This plugin turns supported containers into a bridge back into Obsidian's native renderer.
What it enables
<mark style="background:#d9f7be">
**bold**, *italic*, `code`, [[Wikilink]], and $x^2$
</mark>
<div class="theorem">
### Theorem
For **every** $x \in A$:
$$
f(x)=x^2
$$
> [!NOTE]
> Callouts, [[wikilinks]], and ![[embeds]] remain Obsidian-native.
</div>
<details open>
<summary>**Proof** with $\forall x$</summary>
1. Markdown lists
2. **Formatting** and $\LaTeX$
</details>
It supports both Reading View and Live Preview. In Live Preview, placing the cursor inside a rendered HTML range reveals its original source so it can be edited normally.
Why this approach
The plugin does not ship a second Markdown parser or a second TeX engine.
Instead it:
- scans source for properly nested, explicitly supported HTML containers;
- lets Obsidian create/sanitize the outer HTML element;
- recursively passes the container body through
MarkdownRenderer.render(); - uses a CodeMirror 6 replacement decoration for the equivalent Live Preview behavior.
This keeps Obsidian-specific syntax such as [[wikilinks]], ![[embeds]], callouts, MathJax, and registered Markdown post-processors in the normal rendering pipeline.
See Architecture for the implementation details and safety model.
Supported HTML
The default allowlist focuses on formatting and container elements, including examples such as:
mark, span, div, details, summary, blockquote, section, headings, table elements, sup, sub, u, font, and similar semantic containers.
Raw/literal or executable elements are intentionally not made Markdown-aware, including:
script, style, pre, code, textarea, and form/media raw-content elements.
Malformed or crossed supported tags are left to Obsidian instead of being guessed or repaired.
Important grammar boundary
This project solves Markdown and MathJax inside HTML:
<mark>**Result:** $x+y$</mark>
It does not redefine TeX so that arbitrary HTML becomes valid inside a math expression:
$x + <mark>y</mark>$
The latter remains a TeX/MathJax grammar problem by design.
Installation
From a GitHub release
- Download
main.js,manifest.json, andstyles.cssfrom the latest release. - Create
<vault>/.obsidian/plugins/nested-markdown-html/. - Copy the three files into that directory.
- Restart Obsidian or reload the app.
- Enable Nested Markdown in HTML under Settings → Community plugins.
Development install
Requirements: Node.js 20+ and npm.
git clone https://github.com/ByteAssembler/obsidian-nested-markdown-html.git
cd obsidian-nested-markdown-html
npm ci
npm run check
npm run install:local -- /path/to/your/vault
install:local validates the target as an Obsidian vault, runs the full test/build check, backs up any existing plugin installation, and then installs the runtime files.
Development
npm ci
npm test
npm run build
npm run check
npm test— unit tests for scanning and source transformation.npm run build— TypeScript check + production esbuild bundle.npm run check— full local CI equivalent.npm run dev— watch build for plugin development.
The source is in src/, with tests in test/.
Tested behavior
The implementation has been exercised in a real Obsidian 1.12.7 Electron runtime for:
- inline HTML + bold/italic/code + MathJax + wikilinks;
- Markdown formatting spanning across an HTML container;
- nested HTML containers;
- multi-paragraph block HTML;
<details>/<summary>;- callouts and Markdown tables inside HTML;
![[embeds]]inside HTML;- display MathJax inside HTML;
- Hilo highlight-plugin interoperability;
- click-to-reveal source editing in Live Preview;
- internal-link navigation from Live Preview widgets;
- stale Reading View block updates after interior edits;
- clean enable/disable fallback to native Obsidian behavior.
Contributing
Bug reports, reduced test cases, compatibility reports, and pull requests are welcome. Please read CONTRIBUTING.md before submitting a change.
For security-sensitive reports, see SECURITY.md.
License
MIT © ByteAssembler
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.