For this repository, Marp Markdown is best understood as a layered, implementation-defined format rather than a single standalone specification.
CommonMarkprovides the base Markdown model.Marpit Markdownadds slide authoring syntax such as slide separators, directives, extended image syntax, fragmented lists, and theme CSS conventions.Marp Coreadds Marp-specific defaults and extensions such as built-in themes,size, math, emoji, auto-scaling, and safer HTML defaults.Marp CLIand editors such as Marp for VS Code add tooling behavior such as preview, metadata handling, theme loading, and output conversion.
In this repository, when we say Marp Markdown, we mean:
Marpit Markdown plus the Marp-oriented subset that MarpToPptx currently parses and renders.
That distinction matters because MarpToPptx does not implement the full Marp toolchain. It implements a focused parser and editable PPTX renderer for a practical subset.
Use the following structure when documenting syntax or compatibility for this project:
-
Base MarkdownCommonMark-style block and inline Markdown accepted by the parser. -
Slide Authoring SyntaxMarpit concepts such as slide splitting, front matter, directives, and slide backgrounds. -
Marp ExtensionsMarp-specific features that may exist upstream, with explicit notes about whetherMarpToPptxsupports them. -
Tooling And Output BehaviorCLI options, theme CSS loading, template usage, and PPTX rendering behavior. These are implementation details, not core Markdown syntax.
| Layer | Feature | Upstream Meaning | MarpToPptx Status | Notes |
|---|---|---|---|---|
| CommonMark / Markdown | Headings | Standard Markdown headings | Supported | Parsed into HeadingElement. |
| CommonMark / Markdown | Paragraphs | Standard paragraphs | Supported | Parsed into ParagraphElement. |
| CommonMark / Markdown | Bullet and ordered lists | Standard Markdown lists | Supported | Parsed into BulletListElement; nesting depth is preserved numerically. |
| CommonMark / Markdown | Fenced code blocks | Standard fenced code blocks | Supported | Parsed into CodeBlockElement. |
| CommonMark / Markdown | Tables | GFM-style tables | Supported with fallback rendering | Parsed into TableElement, rendered as editable text rather than native PPTX tables. |
| CommonMark / Markdown | Inline emphasis and links | Standard inline formatting | Partially supported | Text content is preserved, but inline styling and hyperlinks are flattened to plain text in the semantic model. |
| CommonMark / Markdown | Raw HTML | CommonMark / Marp HTML behavior | Limited | No explicit HTML element modeling beyond comment directives. |
| Marpit | Slide separator --- |
Splits slides on horizontal rules | Supported subset | SlideTokenizer splits on a line that is exactly ---, except inside fenced code blocks. |
| Marpit | Alternate separators ***, ___, - - - |
Alternate CommonMark rulers that can separate slides | Not supported | Only literal --- is recognized as a slide boundary. |
| Marpit | YAML front matter | Deck-level metadata | Supported subset | Parsed as simple key: value pairs only. |
| Marpit | Directives in HTML comments | Slide and deck directives | Supported subset | Supports theme, paginate, class, backgroundImage, backgroundSize, backgroundColor, color, header, and footer. |
| Marpit | Spot directives with _ prefix |
Apply a local directive to one slide only | Supported | All recognised directive keys work with a _ prefix (e.g. _class, _paginate, _backgroundColor, _color). Spot directives apply to the current slide only and do not carry forward to subsequent slides. |
| Marpit | headingDivider |
Split slides before headings automatically | Supported subset | Parsed from front matter as an integer 1–6; slides are split before headings at or above that level. |
| Marpit | Header / footer directives | Per-slide repeated content | Supported | header and footer string values are stored in SlideStyle and emitted into PPTX text shapes on each slide. |
| Marpit | Extended image syntax | Width, height, filters, bg, split backgrounds |
Partially supported | Normal Markdown images are parsed;  is promoted to a slide background. Marpit width/height/percentage sizing keywords (w:, h:, N%) are parsed and applied. Alignment keywords left/right are parsed and affect image placement within the content frame. Split backgrounds (![bg left], ![bg right]) are supported and render each image in its respective slide half. Other modifiers (filters, bg cover, bg contain, percentage-sized backgrounds) are not yet implemented. |
| Marpit | Background image syntax via image alt text |  and related |
Supported subset |  sets the slide background image (always full-bleed).  and  render the image in the left or right half of the slide respectively (split background layout). A backgroundImage directive on the same slide takes precedence over plain . Other modifiers (bg cover, bg contain, percentage sizing in the alt text) are not yet parsed. See Background Image Precedence below. |
| Marpit | Fragmented lists | Incremental list reveal | Not supported | No fragment model in parser or renderer. |
| Marpit | Theme CSS | CSS-driven slide theming | Supported subset | CSS extraction for fonts, sizes, colors, padding, background, line-height, letter-spacing, text-transform, font-weight, and code style. See the CSS property reference below. |
| Marp Core | Built-in theme names | Themes such as default, gaia, uncover |
Name-only unless CSS is supplied | Theme name is stored, but real styling comes from parsed CSS or defaults. |
| Marp Core | size directive |
Slide size preset selection | Not supported | Renderer uses a fixed 16:9 slide size. |
| Marp Core | Math | MathJax / KaTeX rendering | Not supported | No math parsing or render pipeline. |
| Marp Core | Emoji conversion | Shortcodes and Twemoji behavior | Not supported | Emoji are treated as normal text characters. |
| Marp Core | fit / auto-scaling |
Resize headings and oversized blocks | Not supported | Layout is heuristic, but there is no Marp fit syntax support. |
| Marp Core | Safer HTML defaults | Controlled HTML allowlist | Not explicitly implemented | Behavior comes mostly from Markdig parsing choices, not Marp Core compatibility logic. |
| Marp CLI / tooling | Metadata directives | title, description, author, etc. |
Not supported | Front matter values are preserved generically, but not interpreted as output metadata. |
| Marp CLI / tooling | Theme loading | --theme, theme sets, theme resolution |
Partial equivalent | --theme-css loads a CSS file for minimal theme extraction. |
| Marp CLI / tooling | Template layout selection | Choose named .pptx layouts or a specific template slide from markdown |
Supported | Front matter layout sets the default content layout; layout and _layout comment directives select named template layouts per slide. Template[n] targets an authored template slide directly. Matching a named layout or template slide suppresses theme/class/background/header/footer styling for that slide so the template can dominate. |
| Marp CLI / tooling | Output conversion modes | HTML, PDF, PPTX, images, notes | Not supported | This tool produces editable PPTX only. |
| Marp CLI / tooling | Browser-based rendering behavior | Preview, browser output, local-file rules | Not supported | MarpToPptx does not use a browser renderer. |
| MarpToPptx-specific | PPTX template reuse | Copy masters/themes from an existing deck | Supported | --template copies an existing .pptx before rendering slides. |
Marpit directives can be authored in YAML front matter or as HTML comments inside slide content. MarpToPptx recognises three scopes:
Front matter key-value pairs set deck-level defaults that apply to all slides unless overridden. The following keys are interpreted and mapped to SlideStyle:
| Key | Type | Description |
|---|---|---|
theme |
string | Theme name; used for CSS class-variant lookup |
paginate |
boolean | Enable slide-number rendering |
class |
string | CSS class applied to all slides |
backgroundImage |
string | URL of background image for all slides |
backgroundSize |
string | Background sizing hint (cover, contain, etc.) |
backgroundPosition |
string | Background image position (center, top, bottom, left, right, or two-keyword combinations) |
backgroundColor |
string | Background fill color for all slides |
color |
string | Default text color for slide text shapes |
header |
string | Repeated header text on every slide |
footer |
string | Repeated footer text on every slide |
headingDivider |
integer (1–6) | Split slides before headings at or above that level |
lang |
BCP-47 string | Language tag written to PPTX document metadata |
style |
CSS string | Inline CSS merged with any --theme-css CSS |
transition |
string | Default slide transition for all slides (see Transition Directive) |
diagram-theme |
string | Default DiagramForge theme for all mermaid and diagram fences (see Diagram Theme Directive) |
All other front matter keys are stored in SlideDeck.FrontMatter but not interpreted.
HTML comments of the form <!-- key: value --> inside slide content set a local override for the current slide. The new value carries forward to every subsequent slide unless overridden again. Local directives update the carry-forward style.
<!-- backgroundColor: #102A43 -->
<!-- class: contrast -->
# This slide and all slides after it use the dark backgroundThe same keys listed in the global table above are recognised as local directives.
A leading _ on the key makes a directive a spot directive: it applies only to the current slide and does not carry forward. Spot directives are layered on top of the inherited local style for that slide.
<!-- _paginate: false -->
<!-- _backgroundColor: #FFD700 -->
# This slide only: pagination off, gold backgroundAll recognised directive keys support the _ prefix. The next slide reverts to the inherited carry-forward value.
The transition directive adds a PowerPoint slide transition to the slide that advances into it. It can be set globally in front matter (deck default), as a local directive (carries forward), or as a spot directive (current slide only).
Syntax:
transition: <type> [dir:<direction>] [dur:<milliseconds>]Supported transition types:
| Directive value | PowerPoint transition | Direction supported |
|---|---|---|
fade |
Fade | No |
push |
Push | Yes (left, right, up, down) |
wipe |
Wipe | Yes (left, right, up, down) |
cut |
Cut (instant) | No |
cover |
Cover | Yes (left, right, up, down) |
pull |
Pull (Uncover) | Yes (left, right, up, down) |
random-bar |
Random Bar | horizontal (default), vertical |
morph |
Morph (fallback: fade) | No |
Optional parameters:
dir:<value>— sets the direction for transitions that support it. Ignored otherwise.dur:<ms>— duration in milliseconds. Mapped to thespdattribute bands:≤300ms→ fast,≤700ms→ medium,>700ms→ slow.
Morph note: Morph is an Office 2019+ feature that requires an
mc:AlternateContentwrapper in the PPTX. The current implementation emits afadeas a compatible fallback for all PowerPoint versions. Full morph support is tracked as a follow-up.
Examples:
---
transition: fade
---
# First slide (inherits fade)
---
<!-- transition: push dir:right -->
# Second slide (push right, carries forward)
---
<!-- _transition: wipe dur:500 -->
# Third slide (wipe, spot override — does not carry forward)
---
# Fourth slide (back to push right from slide 2)The diagram-theme front matter directive sets a deck-level preferred DiagramForge theme name for all mermaid and diagram fenced code blocks in the presentation. This lets you apply a consistent diagram look without repeating front matter inside every fence.
Syntax (front matter only):
diagram-theme: <theme-name>Supported DiagramForge theme names include default, prism, dracula, and presentation.
Precedence:
- Fence-level
theme:— atheme:key inside the fenced block's own YAML front matter always wins. - Deck-level
diagram-theme— applied when the fence does not specify its own theme. - Neither set — DiagramForge falls back to its default color mapping derived from the Marp slide theme.
Examples:
Set a deck-wide default:
---
diagram-theme: prism
---Override a single diagram back to a different theme:
```mermaid
---
theme: dracula
---
flowchart LR
A --> B
```In the example above, the Mermaid diagram renders with the dracula theme despite the deck-level prism setting, because the fence-level theme: takes precedence.
HTML comments that do not match the <!-- key: value --> pattern are treated as presenter notes. They are stripped from the slide content and stored in Slide.Notes, then emitted as PPTX speaker notes.
Presenter notes preserve line breaks and support Markdown-style formatting for bold, italic, strikethrough, inline code, and fenced code blocks in the emitted PPTX notes text. Non-directive note text is still captured from HTML comments, not from normal slide Markdown blocks.
Compatibility note: during manual PowerPoint testing, inline-code and fenced-code note text may not consistently honor the requested monospace font face in the notes pane, even though the PPTX run structure is emitted with code-oriented formatting. Treat note code formatting as best-effort PowerPoint compatibility rather than a strict visual guarantee.
<!-- This is a presenter note, not a directive. -->
<!-- **Bold** and *italic* and `code` inside notes. -->
<!--
```csharp
Console.WriteLine("notes code block");
```
-->- YAML front matter with simple
key: valuescalars, plus|literal block scalars (forstyle)lang— sets the BCP-47 language tag for document metadatastyle— inline CSS merged with any external theme CSSdiagram-theme— sets a deck-level preferred DiagramForge theme for allmermaidanddiagramfences
- Slide splitting on literal
--- headingDividerin front matter (integer 1–6) — also splits slides before headings at or above that level- HTML comment directives (local and spot) for:
themepaginateclassbackgroundImagebackgroundSizebackgroundPositionbackgroundColorheaderfootertransition— slide transition type with optionaldir:anddur:parameters
- Spot directives — all of the above keys work with a
_prefix (e.g._class,_paginate); they apply only to the current slide and do not carry forward - Headings
- Paragraphs
- Bullet lists and ordered lists
- Images with local file paths
- Explicit visible captions via Markdown image title attribute:
 - Fenced and indented code blocks
- GFM-style tables at the semantic-model level
- Theme CSS extraction from
section,:root,body,h1-h6,pre, andcode— see the CSS property reference below
- Editable PPTX text boxes for headings, paragraphs, lists, and code blocks
- Editable text fallback for tables
- Local image embedding with aspect-ratio-aware placement
- Explicit visible image captions: use the Markdown image title attribute
to render a visible caption below the image; the caption is styled smaller than body text to distinguish it from regular content; alt text remains as accessibility metadata on the image shape and is not shown visibly - Solid slide background color
- Full-slide background image via directive,
image syntax, or themebackground-image - Line spacing applied from CSS
line-height - Letter spacing applied from CSS
letter-spacing - Text transform applied from CSS
text-transform(uppercase,lowercase,capitalize) - Optional template-copy workflow via
--template - Named template layout selection via front matter
layout, comment directiveslayout/_layout, and authored template-slide selection viaTemplate[n] - Slide transitions via the
transitiondirective (fade,push,wipe,cut,cover,pull,random-bar,morphwith fade fallback); optionaldir:anddur:parameters
modifiers:bg cover,bg contain,bg left,bg right, and percentage sizing (bg 50%) — the image is always rendered full-bleed when using bg syntax- Split-background layouts from multiple
images on one slide (only the first is used) - fragmented lists
- Marp Core
size - math
- Marp
fit - native PPTX table generation
- Marp CLI metadata semantics
- browser-based preview or HTML/PDF/image outputs
- CSS
background-attachment,background-blend-mode,background-origin,background-clip - CSS
font-variant,font-stretch,font-style - CSS
text-shadow,box-shadow - CSS
border,border-radiuson shapes - CSS
opacity,filter - CSS custom properties (
--var-name) andvar()references - CSS nesting, pseudo-classes (
:hover,:first-child, etc.), or combinators - CSS
@media,@keyframes, or other at-rules
When multiple background image sources are present on the same slide, the following precedence applies (highest to lowest):
backgroundImagedirective — a<!-- backgroundImage: url -->comment directive or front-matterbackgroundImagekey on the slide. Directives always win.image syntax — a Markdown image whose alt text is exactlybg(case-insensitive). Applied only if no directive has set a background image for that slide.- Theme
background-image— the background image defined in the active theme CSS. Applied at render time only if neither a directive norsyntax has set a background image.
When multiple  images appear on the same slide, only the first one is used. The others are silently discarded (split-background layouts are not yet supported).
The following table documents every CSS property that MarpToPptx recognises, which selectors it applies to, and what it maps to in the PPTX output.
section, :root, body, h1–h6, pre, code
All other selectors are silently ignored.
| CSS Property | Selectors | PPTX Mapping | Notes |
|---|---|---|---|
font-family |
section, :root, body, h1–h6, pre, code |
Run font (Latin typeface) | First family in the comma-separated list is used. Quotes are stripped. |
font-size |
section, :root, body, h1–h6, pre, code |
Run font size | Accepts px, rem, and unitless pt. 1px = 0.75pt. 1rem = 12pt. |
font-weight |
section, :root, body, h1–h6 |
Run bold flag | bold, bolder, or numeric ≥ 600 → bold. normal, lighter, or numeric < 600 → not bold. |
color |
section, :root, body, h1–h6, pre, code |
Run fill color | Hex or rgb()/rgba() values. |
background-color |
section, :root, body |
Slide background fill | Hex or rgb()/rgba() values. |
background |
section, :root, body, pre, code |
Slide or code background | Color and URL extracted from shorthand. Other shorthand tokens (e.g. no-repeat) are ignored. |
background-image |
section, :root, body |
Theme-level background image | url(...) value. Applied as full-bleed image behind all slides unless overridden per slide. |
background-size |
section, :root, body |
Background image sizing | cover (default) scales the image to fill the slide, cropping as needed. contain scales it to fit within the slide with letterboxing. Other values fall back to cover behavior. |
background-position |
section, :root, body |
Background image position | Supported keyword values: center (default), top, bottom, left, right, and two-keyword combinations such as top left, bottom right, top center. Percentage and length values are not supported and fall back to centered. |
padding |
section, :root, body |
Slide padding inset | 1–4 value shorthand. Accepts px, rem, and unitless pt. |
line-height |
section, :root, body, h1–h6, pre, code |
Paragraph line spacing (percent) | Unitless or % values treated as multipliers. 1.5 and 150% both map to 150 % line spacing. |
letter-spacing |
section, :root, body, h1–h6, pre, code |
Run character spacing | Accepts px, rem, and unitless pt. Converted to pt before storage. |
text-transform |
section, :root, body, h1–h6 |
Text content transform | uppercase, lowercase, and capitalize applied at render time. none or unrecognised values leave text unchanged. |
The following properties are present in many Marp theme files but are silently ignored by the parser.
| CSS Property | Reason Not Supported |
|---|---|
background-attachment |
No PPTX equivalent. |
background-blend-mode |
No PPTX equivalent. |
background-repeat |
Background images are always rendered as full-bleed fills. |
background-clip |
No PPTX equivalent. |
font-style |
Italic run property not yet mapped. |
font-variant |
No PPTX equivalent for small-caps. |
font-stretch |
No PPTX equivalent. |
text-shadow |
No PPTX equivalent. |
box-shadow |
No PPTX equivalent. |
border / border-radius |
Shape borders not modelled per text element. |
opacity |
No PPTX per-shape opacity mapping. |
margin / margin-top / margin-bottom |
Slide layout uses a fixed padding inset, not per-element margins. |
text-decoration |
Underline/strikethrough run property not yet mapped. |
CSS custom properties (--name, var()) |
Variable resolution is not implemented. |
This is the repo-specific map from the documentation model to code.
src/MarpToPptx.Core/Parsing/MarpMarkdownParser.cs- Uses
MarkdigwithUseAdvancedExtensions(). - Converts Markdown blocks into semantic slide elements:
HeadingElementParagraphElementBulletListElementImageElementCodeBlockElementTableElement
Important current behavior:
- Inline emphasis is flattened to text.
- Non-image links keep their visible text but not hyperlink semantics.
- Images inside paragraphs are emitted as separate
ImageElementrecords. - Image alt text is accessibility metadata stored on the picture shape; it is not rendered as visible slide text.
- An explicit visible caption can be added via the Markdown title attribute
; the caption renders below the image in a smaller font size.
src/MarpToPptx.Core/Parsing/FrontMatterParser.cssrc/MarpToPptx.Core/Parsing/SlideTokenizer.cssrc/MarpToPptx.Core/Parsing/MarpDirectiveParser.cs
Important current behavior:
- Front matter is parsed only when it appears first and is delimited by
---. - Front matter parsing is intentionally simple and does not implement full YAML features such as multiline blocks or nested structures.
- Slide splitting ignores
---inside fenced code blocks. headingDividerin front matter splits slides before headings at or above the specified level.- Directive parsing only recognizes HTML comments that match
<!-- key: value -->. - Local directives (no
_prefix) carry forward to subsequent slides. - Spot directives (
_prefix) apply only to the current slide and do not carry forward.
src/MarpToPptx.Core/Themes/MarpThemeParser.cssrc/MarpToPptx.Core/Themes/ThemeDefinition.cs
Important current behavior:
- CSS support is intentionally narrow.
- Only a small set of selectors and declarations are mapped into the PPTX theme model.
- Theme names from front matter are preserved even when no corresponding upstream Marp theme bundle is loaded.
src/MarpToPptx.Core/Models/SlideDeck.cs
The semantic model is the contract between parsing and rendering. It is intentionally simpler than Marpit's HTML-oriented runtime model.
src/MarpToPptx.Pptx/Rendering/OpenXmlPptxRenderer.cs
Important current behavior:
- Slides are rendered into a fixed 16:9 PowerPoint presentation.
- Tables are currently rendered as editable text, not native table shapes.
- Missing images fall back to a visible text placeholder.
- Background images and template reuse are renderer features, not Markdown syntax features.
src/MarpToPptx.Cli/Program.cs
Current CLI options:
- input Markdown path
-o,--output--template--theme-css
These options are intentionally narrower than Marp CLI. They expose only the parts that MarpToPptx currently implements.
Use these terms consistently:
Marp Markdown: the practical authoring format accepted by this toolMarpit syntax: upstream slide-authoring constructs defined by MarpitMarp Core features: upstream Marp-specific extensions that may or may not be implemented hereMarpToPptx compatibility: the exact subset this repository parses and renders today
That wording avoids implying full compatibility when the repository currently implements a targeted subset.