Color mode

Marp

Render Marp slide decks at build time. A note whose YAML frontmatter contains marp: true is rendered as a whole-document deck, and marp fenced code blocks render as inline decks.

日本語

Usage

ts
import { defineConfig } from "@riebeckite/core";
import { marp } from "@riebeckite/plugin-marp";
 
export default defineConfig({
  // ...
  plugins: [
    marp({
      theme: "default",
      allowHtml: true,
      math: true,
      caption: true,
    }),
  ],
});

Obsidian vault compatibility

The Obsidian plugins Marp and Marp Slides treat the entire note as a Marp deck and never store marp code fences. In Obsidian, activation is plugin-level: opening the slide preview or exporting renders the whole file of the active note, and neither plugin reads a per-note marker. Riebeckite instead activates per document using the canonical marp: true frontmatter flag — the same signal Marp CLI and the VS Code extension use — so notes written for those plugins are detected as:

markdown
---
marp: true
theme: gaia
paginate: true
---
 
# First slide
 
---
 
# Second slide

The whole document (frontmatter included, so directives such as theme and paginate apply) is rendered as one <figure class="rb-marp"> deck that replaces the page body. Slide separators are --- / ===, exactly like Marp. Notes without the flag or any marp code block are left untouched.

Activation contract. Riebeckite is not activated the way the Obsidian plugins are. A note that showed as slides in Obsidian (because you opened the slide preview for it) will not render as a deck here unless marp: true is present in its frontmatter. Adding that one line is the only change such a vault needs — the deck body (separators, theme / paginate and other directives, standard Marp syntax) is used exactly as stored. In other words, the output follows Marp semantics, while the plugins' zero-config, plugin-level activation is not reproduced. Treat this as content-compatible, not fully drop-in.

Inline decks

In a note, write a fenced code block whose info string is marp. Slides are separated by ---, exactly like Marp. Setting the code block title renders a caption.

markdown
```marp title="Intro deck"
# First slide
 
- a bullet
 
---
 
# Second slide
```

How it renders

The plugin dynamically imports @marp-team/marp-core at build time and calls Marp#render. Marp Core never enters the client bundle. Each code block becomes:

html
<figure class="rb-marp" role="group" data-marp data-marp-slides="2">
  <style>/* CSS generated at build time, scoped under .rb-marp */</style>
  <figcaption class="rb-marp__caption">…</figcaption>
  <div class="rb-marp__deck">
    <svg data-marpit-svg>…</svg>
    …
  </div>
  <details class="rb-marp__fallback">
    <summary>Marp source</summary>
    <pre><code>…original Markdown…</code></pre>
  </details>
</figure>

CSS scoping and inlining

Plugins cannot inject into <head>, so the CSS generated by Marp is inlined into the <figure class="rb-marp"> as a <style> element. To keep it from leaking, the plugin:

  • fixes Marp's container option to the rb-marp__deck class so every generated selector stays under that container;
  • constrains the container selector to a .rb-marp descendant (for example .rb-marp div.rb-marp__deck > svg > foreignObject > section);
  • removes the global @page rule and rewrites html, body inside @media print to .rb-marp.

When several decks on one page use the same theme their generated CSS is identical, so the <style> element is emitted only once.

Build-time rendering

  • Rendering uses script: false, so a deck never ships client JavaScript. SVG slide sizing is handled by style.css;
  • captions come from the code block title;
  • data-marp-slides carries the slide count and data-marp marks the deck.

Options

Option Default Description
theme "default" A theme name registered in Marp Core ("default", "gaia", "uncover", …)
allowHtml true Allow raw HTML in the Marp Markdown
math true Enable Marp math support
inlineSVG unset Marp's inlineSVG option. When unset, SVG slides are emitted
caption true Show the code block title as a caption
className "rb-marp" Wrapper class name

An unknown theme falls back to the default theme and emits a diagnostic with source: "@riebeckite/plugin-marp". A render failure keeps the original code block and emits the same kind of diagnostic.

Limitations

  • No client-side slide editing or paging UI; this only produces static HTML/CSS at build time.
  • Only themes registered in Marp Core are available; loading arbitrary theme CSS is not supported.
  • inlineSVG: false emits bare <section> elements without the SVG wrapper, and the generated CSS changes to match that structure.
  • Whole-document decks bypass the normal Markdown pipeline, so Obsidian ![[image]] image embeds are not resolved inside slides. Use regular Markdown image syntax with paths that exist on the published site, mirroring how Marp Slides itself does not support wiki links.

Exports

  • marp(options?) / marpPlugin(options?) — plugin factory
  • isMarpDocument(matter?) — frontmatter marp: true detection helper
  • Types: MarpOptions, MarpDeck, MarpBuildRenderResult

See also

History

1 changesCollapseExpand
1 + <!-- Generated from packages/plugins/marp/README.md. Do not edit this page directly; edit the package README and run `pnpm docs:sync`. -->
2 +
3 + # Marp
4 +
5 + Render Marp slide decks at build time. A note whose YAML frontmatter contains `marp: true` is rendered as a whole-document deck, and `marp` fenced code blocks render as inline decks.
6 +
7 + [日本語](./marp.md)
8 +
9 + ## Usage
10 +
11 + ```ts
12 + import { defineConfig } from "@riebeckite/core";
13 + import { marp } from "@riebeckite/plugin-marp";
14 +
15 + export default defineConfig({
16 + // ...
17 + plugins: [
18 + marp({
19 + theme: "default",
20 + allowHtml: true,
21 + math: true,
22 + caption: true,
23 + }),
24 + ],
25 + });
26 + ```
27 +
28 + ## Obsidian vault compatibility
29 +
30 + The Obsidian plugins [Marp](https://github.com/jichoup/obsidian-marp-plugin) and [Marp Slides](https://github.com/samuele-cozzi/obsidian-marp-slides) treat the entire note as a Marp deck and never store `marp` code fences. In Obsidian, activation is plugin-level: opening the slide preview or exporting renders the whole file of the active note, and neither plugin reads a per-note marker. Riebeckite instead activates per document using the canonical `marp: true` frontmatter flag — the same signal Marp CLI and the VS Code extension use — so notes written for those plugins are detected as:
31 +
32 + ````markdown
33 + ---
34 + marp: true
35 + theme: gaia
36 + paginate: true
37 + ---
38 +
39 + # First slide
40 +
41 + ---
42 +
43 + # Second slide
44 + ````
45 +
46 + The whole document (frontmatter included, so directives such as `theme` and `paginate` apply) is rendered as one `<figure class="rb-marp">` deck that replaces the page body. Slide separators are `---` / `===`, exactly like Marp. Notes without the flag or any `marp` code block are left untouched.
47 +
48 + > **Activation contract.** Riebeckite is not activated the way the Obsidian plugins are. A note that showed as slides in Obsidian (because you opened the slide preview for it) will **not** render as a deck here unless `marp: true` is present in its frontmatter. Adding that one line is the only change such a vault needs — the deck body (separators, `theme` / `paginate` and other directives, standard Marp syntax) is used exactly as stored. In other words, the output follows Marp semantics, while the plugins' zero-config, plugin-level activation is not reproduced. Treat this as content-compatible, not fully drop-in.
49 +
50 + ## Inline decks
51 +
52 + In a note, write a fenced code block whose info string is `marp`. Slides are separated by `---`, exactly like Marp. Setting the code block `title` renders a caption.
53 +
54 + ````markdown
55 + ```marp title="Intro deck"
56 + # First slide
57 +
58 + - a bullet
59 +
60 + ---
61 +
62 + # Second slide
63 + ```
64 + ````
65 +
66 + ## How it renders
67 +
68 + The plugin dynamically imports `@marp-team/marp-core` at build time and calls `Marp#render`. Marp Core never enters the client bundle. Each code block becomes:
69 +
70 + ```html
71 + <figure class="rb-marp" role="group" data-marp data-marp-slides="2">
72 + <style>/* CSS generated at build time, scoped under .rb-marp */</style>
73 + <figcaption class="rb-marp__caption">…</figcaption>
74 + <div class="rb-marp__deck">
75 + <svg data-marpit-svg>…</svg>
76 + …
77 + </div>
78 + <details class="rb-marp__fallback">
79 + <summary>Marp source</summary>
80 + <pre><code>…original Markdown…</code></pre>
81 + </details>
82 + </figure>
83 + ```
84 +
85 + ### CSS scoping and inlining
86 +
87 + Plugins cannot inject into `<head>`, so the CSS generated by Marp is inlined into the `<figure class="rb-marp">` as a `<style>` element. To keep it from leaking, the plugin:
88 +
89 + - fixes Marp's `container` option to the `rb-marp__deck` class so every generated selector stays under that container;
90 + - constrains the container selector to a `.rb-marp` descendant (for example `.rb-marp div.rb-marp__deck > svg > foreignObject > section`);
91 + - removes the global `@page` rule and rewrites `html, body` inside `@media print` to `.rb-marp`.
92 +
93 + When several decks on one page use the same theme their generated CSS is identical, so the `<style>` element is emitted only once.
94 +
95 + ### Build-time rendering
96 +
97 + - Rendering uses `script: false`, so a deck never ships client JavaScript. SVG slide sizing is handled by `style.css`;
98 + - captions come from the code block `title`;
99 + - `data-marp-slides` carries the slide count and `data-marp` marks the deck.
100 +
101 + ## Options
102 +
103 + | Option | Default | Description |
104 + | --- | --- | --- |
105 + | `theme` | `"default"` | A theme name registered in Marp Core (`"default"`, `"gaia"`, `"uncover"`, …) |
106 + | `allowHtml` | `true` | Allow raw HTML in the Marp Markdown |
107 + | `math` | `true` | Enable Marp math support |
108 + | `inlineSVG` | unset | Marp's `inlineSVG` option. When unset, SVG slides are emitted |
109 + | `caption` | `true` | Show the code block `title` as a caption |
110 + | `className` | `"rb-marp"` | Wrapper class name |
111 +
112 + An unknown theme falls back to the default theme and emits a diagnostic with `source: "@riebeckite/plugin-marp"`. A render failure keeps the original code block and emits the same kind of diagnostic.
113 +
114 + ## Limitations
115 +
116 + - No client-side slide editing or paging UI; this only produces static HTML/CSS at build time.
117 + - Only themes registered in Marp Core are available; loading arbitrary theme CSS is not supported.
118 + - `inlineSVG: false` emits bare `<section>` elements without the SVG wrapper, and the generated CSS changes to match that structure.
119 + - Whole-document decks bypass the normal Markdown pipeline, so Obsidian `![[image]]` image embeds are not resolved inside slides. Use regular Markdown image syntax with paths that exist on the published site, mirroring how Marp Slides itself does not support wiki links.
120 +
121 + ## Exports
122 +
123 + - `marp(options?)` / `marpPlugin(options?)` — plugin factory
124 + - `isMarpDocument(matter?)` — frontmatter `marp: true` detection helper
125 + - Types: `MarpOptions`, `MarpDeck`, `MarpBuildRenderResult`
126 +
127 + ## See also
128 +
129 + - [Plugin guide](../reference/plugin-api.en.md)
130 +