Marp Inline Preview

by Sotetsu Koyamada
5
4
3
2
1
Score: 35/100
New Plugin

Description

This plugin has not been manually reviewed by Obsidian staff. Render Marp slide decks inline in edit mode and as full HTML in reading mode.

Reviews

No reviews yet.

Stats

stars
downloads
0
forks
0
days
NaN
days
NaN
days
0
total PRs
0
open PRs
0
closed PRs
0
merged PRs
0
total issues
0
open issues
0
closed issues
0
commits

Latest Version

Invalid date

Changelog

README file from

Github

Marp Inline Preview for Obsidian

Render Marp slide decks directly inside Obsidian — inline beneath each --- slide separator while editing, and as the full deck in reading mode. Works on desktop and mobile.

Mode What you see
Edit / Live Preview A rendered slide widget appears under each slide break. Updates as you type, with a configurable debounce.
Reading The entire page is replaced by the rendered Marp deck.

Only files whose YAML frontmatter contains marp: true are touched. Everything else renders as ordinary Markdown.

Features

  • Marp Core 4 under the hood — same renderer as the official Marp tooling, in pure JavaScript so it works on Obsidian Mobile (iOS & Android).
  • Custom theme support through .marprc.yml (vault-root, with a fallback to the slide file's folder), plus the standard frontmatter theme: directive.
  • KaTeX math is bundled — no network roundtrips, no broken formulae offline.
  • Marp's per-slide CSS is mounted inside Shadow DOM, so it can't leak into Obsidian's own UI.
  • Pluggable: toggle the edit-mode preview, reading-mode preview, math support, and debounce interval from Settings.

Quick start

---
marp: true
theme: default
---

# My deck

- Slide one

---

## Slide two

That's it.

Save the file. Switch between edit and reading mode to see the previews.

Custom themes via .marprc.yml

Place a .marprc.yml at the vault root (preferred) or next to your slide file:

themeSet:
  - themes/my-theme.css
theme: my-theme

Each entry in themeSet is a vault-relative path resolved against the .marprc.yml location. The plugin reads those CSS files via the Obsidian Vault API (no Node fs), so it works on mobile too. Your CSS must have a header comment such as /* @theme my-theme */ to be selectable by name.

Slides can opt in per-file via frontmatter:

---
marp: true
theme: my-theme
---

Settings

  • Inline preview in edit mode — toggle the CodeMirror widget.
  • Full preview in reading mode — toggle the deck render.
  • Math renderingKaTeX (bundled) or Off.

Command palette: Marp Inline Preview: Refresh Marp previews forces a full reload (useful after editing a theme file from outside Obsidian).

Install: build locally and copy into another vault

The plugin ships as three files (main.js, manifest.json, styles.css). You build them once in this repo, then drop them into any vault.

1. Build the plugin

Requires Node.js 18 or newer.

git clone https://github.com/<you>/obsidian-marp-inline-preview-plugin.git
cd obsidian-marp-inline-preview-plugin
npm install
npm run build

After npm run build the repo root contains:

main.js        # bundled plugin code (~1.9 MB, includes Marp Core + KaTeX)
manifest.json  # plugin metadata (checked in)
styles.css     # host-side styles (checked in)

2. Find the target vault's plugin folder

Inside your Obsidian vault there is a hidden .obsidian/ directory. Plugins live under .obsidian/plugins/<plugin-id>/. For this plugin the folder is marp-inline-preview.

Typical full paths:

OS Example path
macOS / Linux /path/to/MyVault/.obsidian/plugins/marp-inline-preview/
Windows C:\Users\you\Documents\MyVault\.obsidian\plugins\marp-inline-preview\
iOS On My iPhone → Obsidian → MyVault → .obsidian → plugins → marp-inline-preview (Files.app, "Show Hidden Files" on)
Android /storage/emulated/0/MyVault/.obsidian/plugins/marp-inline-preview/ (any file manager)

Create the directory if it doesn't exist yet.

3. Copy the three files

From the repo root, with TARGET_VAULT set to your vault directory:

# macOS / Linux
TARGET_VAULT="/path/to/MyVault"
mkdir -p "$TARGET_VAULT/.obsidian/plugins/marp-inline-preview"
cp main.js manifest.json styles.css "$TARGET_VAULT/.obsidian/plugins/marp-inline-preview/"
# Windows PowerShell
$TARGET_VAULT = "C:\Users\you\Documents\MyVault"
New-Item -ItemType Directory -Force -Path "$TARGET_VAULT\.obsidian\plugins\marp-inline-preview" | Out-Null
Copy-Item main.js, manifest.json, styles.css "$TARGET_VAULT\.obsidian\plugins\marp-inline-preview\"

On mobile, sync the three files via iCloud / Obsidian Sync / a USB transfer to the same path. Obsidian Sync replicates .obsidian/plugins/ automatically if you enable it.

4. Enable it in Obsidian

  1. Open the target vault.
  2. Settings → Community plugins. If you see "Restricted mode", turn it off.
  3. Reload the plugin list (the circular-arrow icon next to "Installed plugins"), or run Reload app without saving from the command palette.
  4. Toggle Marp Inline Preview on.

Open a markdown file with marp: true in its frontmatter — you should see slide widgets in edit mode and the full deck in reading mode.

Updating

Re-run npm run build, then re-copy the same three files (step 3) and reload Obsidian.

Uninstalling

Disable the plugin in Settings → Community plugins, then delete <vault>/.obsidian/plugins/marp-inline-preview/.

Development

npm install
npm run dev:vault    # symlinks build outputs into test-vault/ and starts esbuild watch

Then in Obsidian: File → Open vault… and pick the test-vault/ folder in this repo. Enable the plugin and open one of the files in slides/.

npm run build produces a production bundle (~1.9 MB).

Project layout:

src/
├── main.ts              Plugin entry: register processors, settings, events
├── settings.ts          Settings model + PluginSettingTab
├── marp/
│   ├── engine.ts        Marp Core wrapper (themes, render helpers)
│   ├── themes.ts        .marprc.yml discovery and theme registration
│   └── slides.ts        Slide-break detection (frontmatter & fence aware)
├── reading/
│   └── postProcessor.ts MarkdownPostProcessor that replaces the preview section
├── editor/
│   ├── extension.ts     CM6 ViewPlugin that adds block widgets after each break
│   └── widget.ts        WidgetType using Shadow DOM
└── util/
    ├── debounce.ts
    └── shadow.ts        Shadow-root mounting helpers

Mobile notes

  • Everything goes through app.vault.adapter — no Node fs, no Electron-only APIs.
  • mathjax-full is aliased out at bundle time so the plugin stays small.
  • KaTeX fonts are loaded from the bundle, not a CDN. Math works offline.
  • Twemoji is disabled; OS Unicode emoji are used instead, so no CDN fetch.

TODO: Marp CLI parity

  • Rewrite relative URLs emitted in inline styles, especially Marp background images such as ![bg](https://raw.githubusercontent.com/sotetsuk/obsidian-marp-inline-preview-plugin/HEAD/...). Marp Core renders these as background-image:url(...), while the current Obsidian preview only rewrites <img src="https://raw.githubusercontent.com/sotetsuk/obsidian-marp-inline-preview-plugin/HEAD/...">, so images that work in Marp CLI can disappear inside the iframe.
  • Size preview iframes from each rendered SVG's viewBox instead of assuming Marp's default 1280x720 slide. Decks using size: 4:3 or custom theme @size rules can currently be clipped or shown with the wrong aspect ratio compared with Marp CLI output.
  • Rework theme reloads so modified custom theme CSS replaces the existing Marp Core theme registration. The current cache invalidation re-reads CSS, but Marp Core may keep the first registered theme with the same name, leaving edit/reading previews stale after theme edits.
  • Include rendered CSS or a theme revision in the reading-mode render hash. At the moment the hash is based on markdown plus theme name, so a CSS-only theme update can be skipped even after requesting a reading preview rerender.
  • Decide how much of .marprc.yml CLI configuration should be supported beyond theme and themeSet. Options such as html, math, and other Marp CLI/Core settings can make the plugin preview differ from marp command output.
  • Preserve query strings and fragments when rewriting local resource URLs. Paths like image.svg#fragment or image.png?cache=... are resolved by stripping the suffix today, which can change rendered output versus Marp CLI.

Limitations / known issues

  • Mermaid isn't supported — Marp Core itself doesn't ship Mermaid integration.
  • Reading-mode rendering replaces the preview section wholesale, so plugins that mutate that section (e.g. some outline plugins) may not work on Marp files.
  • The CodeMirror plugin uses editor.cm to associate a ViewPlugin with the active TFile; this is an internal property and could break in a future Obsidian release.

License

MIT — see LICENSE.