Markdown to PowerPoint (.pptx) — the CLI tool built for developers.
Write slides in Markdown with syntax-highlighted code and embedded diagrams.
Generate beautiful, fully editable .pptx in seconds.
📖 Table of Contents
- 📑 Markdown to PowerPoint: Convert standard Markdown to editable 16:9 widescreen
.pptxslides. - 🎨 Syntax Highlighting: Token-level code highlighting powered by Shiki (Python, TypeScript, Go, Rust, Java, C++, Bash, SQL, and 20+ languages).
- 📊 Built-in Diagram Rendering (Zero native binary dependencies):
- Mermaid: Flowcharts, sequence diagrams, state diagrams, class diagrams.
- Graphviz / DOT: Network graphs, finite state machines, architecture topologies (via WASM).
- PlantUML: Sequence, class, activity, state, component and use-case diagrams (TeaVM-compiled engine — no JVM required).
- ECharts: Bar charts, line charts, pie charts directly from JSON options (via ECharts SSR).
- 🖼️ Image Embedding: Local file paths, remote URLs (
http:///https://), and base64 Data URIs. - 📐 Automatic Layout Detection: Title slides, section dividers, code spotlights, quotes, and content slides.
- ⚡ Batch Conversion: Convert multiple files with glob support (
mfly *.md).
Requires Node.js 20+.
# Install globally from npm (preferred)
npm install -g markdownfly
# Or run without installing
npx markdownfly@latest slides.mdDevelop from source:
# Clone and install dependencies
git clone https://github.com/Kyvin-Guan/markdownFly.git
cd markdownFly
pnpm install
pnpm buildLink locally for global CLI access:
pnpm link --global# Convert a single file (named after the input: slides.md → slides.pptx)
mfly slides.md
# Specify theme — presets: blue, emerald, gold, slate; color-only: ocean, ocean-dark, forest, champagne, graphite
mfly slides.md -t blue
mfly slides.md -t emerald
mfly slides.md -t ocean-dark
# Specify custom output path
mfly slides.md -t blue -o presentation.pptx
# Free composition (optional advanced): override color / text / layout slots
mfly slides.md -t blue --text kai # blue palette+layout, swap text to kai
mfly slides.md --color forest --text academic --layout golden # full custom mix
mfly slides.md --layout minimal # only the layout, rest default theme blue
# Batch convert multiple Markdown files
mfly docs/*.mdComposition flags:
--color <name>color scheme:ocean, ocean-dark, forest, champagne, graphite--text <name>text scheme:system, academic, kai, source-han-serif--layout <name>layout scheme:legacy, folio, golden, minimal
A composition flag precisely overrides the matching theme slot
(precedence: composition > theme preset > default). When composition flags are
given without -t, the default theme blue is used as the base. An unknown
composition name fails with exit 1 and lists the available names.
If the default output name already exists, a timestamped name is used
(slides-20260907-131500.pptx) instead of overwriting. With -o the target
is overwritten without prompting.
# Machine-readable result (one JSON line on stdout; diagnostics on stderr)
mfly slides.md --json
# Suppress per-file progress lines
mfly docs/*.md --quiet--jsonprints a single JSON object to stdout:{"ok":true,"durationMs":1234,"files":[{"input":"slides.md","output":"C:/abs/slides.pptx","ok":true}]}. Per-file failures setok:falsewith anerrorfield.- Exit code is
0only when every file converts successfully; if any file fails the process exits1(a summary line is printed to stderr). -twith an unknown theme name fails with exit1(unknown theme names in markdown frontmatter fall back to the default themebluewith a warning).- Progress lines go to stderr; errors and warnings always go to stderr.
-t / frontmatter theme: take a theme name. Resolution order:
theme preset → color scheme.
| Theme name | Kind | Color | Text | Layout | Best For |
|---|---|---|---|---|---|
blue (default) |
Preset package | ocean |
academic (SimSun) |
legacy |
Default full theme |
emerald |
Preset package | forest |
system (Microsoft YaHei) |
folio |
Fresh green · editorial layout |
gold |
Preset package | champagne |
kai (KaiTi) |
golden |
Warm gold · golden-ratio layout |
slate |
Preset package | graphite |
source-han-serif (Source Han Serif) |
minimal |
Neutral monochrome · archival layout |
ocean |
Color only | Deep sea ink #1E4A6F / Sea-foam paper #F0F8FF; primary #4F9FD9 / secondary #2D6A9F |
Default system |
Layout pack off | Recolor only |
ocean-dark |
Color only | Light foam #D6E7F5 / Deep sea #0B1C2E; primary #5BAAE8 / secondary #8BBCDD |
Default system |
Layout pack off | Night / dark decks (inverse of ocean) |
forest |
Color only | Deep green ink #2A4A3F / Pale green paper #F0FFF5; primary #5F9A8A / secondary #3F6A5A |
Default system |
Layout pack off | Fresh green decks |
champagne |
Color only | Dark gold ink #CFB53B / Cream paper #FFFCE6; primary #E5CD5F / secondary #F5E08A |
Default system |
Layout pack off | Warm metallic gold decks |
graphite |
Color only | Dark gray ink #4D4D4D / Light gray paper #F8F8F8; primary #D9D9D9 / secondary #A6A6A6 |
Default system |
Layout pack off | Neutral monochrome decks |
- Omitting
-t/themeuses the default themeblue. - A theme preset selects color × text × layout in one name; color-scheme names remain valid for recolor-only use.
ocean-darkis the inverse ofocean(same color family), sharing its default text/layout; not listed as a separate preset.- Free composition: override the theme's color / text / layout slots individually via
--color/--text/--layout(or frontmattercolor_scheme/text_scheme/layout_scheme). - Extend via library APIs
registerThemePreset/registerColorScheme/registerTextScheme/registerLayoutScheme.
---(Horizontal Rule): Primary slide separator.# Heading 1: Creates a new slide with Title (cover) layout.## Heading 2: Creates a new slide with Content or Section layout.
---
theme: blue # Options: blue (default), emerald, gold, slate, ocean, ocean-dark, forest, champagne, graphite
color_scheme: champagne # Optional: color scheme overriding the theme's color (ocean, forest, champagne, graphite...)
text_scheme: kai # Optional: text scheme overriding the theme's text (system, academic, kai, source-han-serif)
layout_scheme: folio # Optional: layout scheme overriding the theme's layout (legacy, folio, golden, minimal)
author: "Your Name"
footer: "Confidential - {page} / {total}" # {page}/{total}/{section}/{title}
resource_dir: ./assets # Base directory for relative image paths
layout: code # Optional default layout for content slides
---Split a slide into columns and rows with standalone lines — no extra markup:
## Architecture Overview
### Architecture Diagram
```mermaid
graph LR
A[Client] --> B[API]
```
<-> <!-- two columns: diagram on the left -->
### Key Points
- Low latency
- Horizontally scalable
- Cost-efficient
=== <!-- stacked rows: what follows starts a new row -->
### Summary
> [!TIP]
> `===` splits a slide into stacked rows — handy for before/after comparisons.<->(standalone line): horizontal separator → columns (side-by-side).===(standalone line): vertical separator → rows (stacked).- Combine both for grids. Markers inside code blocks are never rewritten.
A standalone @(key=value, ...) line at the bottom of a slide sets per-slide options:
## Table to Chart
| Quarter | Orders |
| :--- | :--- |
| Q1 | 320 |
| Q2 | 580 |
@(chart=bar, notes=expand on the Q1-Q2 numbers here)| Directive | Value | Effect |
|---|---|---|
layout |
title / section / content / code / quote / image-single / image-double / image-triple |
Override auto-detected layout |
notes |
text | Speaker notes for this slide |
chart |
bar / line / pie |
Render the first table as a chart |
highlight |
2-4,6 |
Highlight lines in the slide's code block |
background |
URL/path | Slide background image |
steps |
true |
Progressive reveal (reserved) |
> [!NOTE]
> Important point to remember.
> [!TIP]
> Helpful suggestion.
> [!WARNING]
> Watch out for this.Supported variants: NOTE / INFO / TIP / SUCCESS / WARNING / CAUTION / DANGER — rendered as theme-styled accent cards.
You can also give a card a custom title by writing it after the marker: > [!NOTE] Deploy reminder.
- [x] Completed item
- [ ] Upcoming itemA standalone image line renders as a slide element (aspect ratio preserved, centered in its column). Paths are resolved relative to the markdown file, or relative to resource_dir (which itself is resolved relative to the markdown file, never the current working directory); remote URLs (http/https) and base64 data URIs also work. A missing or failed image is skipped with a warning on stderr — the deck is still generated.
{w=6in,align=center}
{w=60%}
{width=120px,height=40mm,align=right}- Keys:
w/width,h/height,align(left/center/right, defaultcenter) - Units:
px(default),pt,cm,mm,in/inch,%(relative to the column; single value preserves aspect ratio) - Invalid params are silently ignored — the image still renders
- Formats:
png,jpg/jpeg,gif,webp,bmp,svg. Alt text carries into the PPTX, sois what a screen reader announces. - ⚠
webpis stored faithfully but not every reader decodes it — PowerPoint for the web and Office 2019 and earlier show a broken image. A warning is printed on stderr. svgis rasterized to a PNG (1200px wide) as it is embedded, so it renders the same in every reader. The author's own framing is kept, including any padding built into the viewBox. The trade-off: the deck carries a raster rather than a vector, so it no longer scales losslessly, and SVG-heavy decks get larger.- ⚠ Security: image paths (
and@(background=...)) are resolved without restrictions — only convert markdown you own or trust.
````typescript
interface User {
id: string;
name: string;
}
function greet(user: User): string {
return `Hello, ${user.name}!`;
}
````````python
def quick_sort(arr): ...
````
@(highlight=1,3-4) <!-- highlight specific lines -->````mermaid
graph TD
A[Client] --> B[API Gateway]
B --> C[Auth Service]
B --> D[Data Service]
````
````dot
digraph Architecture {
rankdir=LR;
node [shape=box, style=filled, fillcolor=lightblue];
Frontend -> Backend -> Database;
}
````
````echarts
{
"xAxis": { "type": "category", "data": ["Q1", "Q2", "Q3", "Q4"] },
"yAxis": { "type": "value" },
"series": [{ "data": [150, 230, 224, 218], "type": "bar" }]
}
````
````plantuml
@startuml
Alice -> Bob : login request
Bob --> Alice : login OK
@enduml
````Accepted diagram languages: mermaid, dot (alias graphviz), echarts, plantuml (alias puml).
Diagram slides follow the presentation theme, including its dark palette.
PlantUML notes:
- The
@startuml/@endumlenvelope is optional — bare source is wrapped for you, and an unclosed@startumlis closed automatically. !themeis not available (the bundled engine ships no theme files); useskinparaminstead. The directive is skipped with a warning rather than failing the diagram.- Set
MFLY_DEBUG=1to forward the PlantUML engine's internal logging to stderr; it is muted by default so it cannot disturb stdout. - Diagram errors do not fail the deck: the affected slide shows a red placeholder and the rest of the presentation is still generated.
A standalone line starting with %% is removed entirely before rendering —
handy for draft notes that never reach the deck. Lines inside fenced code
blocks are never affected.
%% this line will never appear in your slidesThe first cover slide recognizes 作者:… / 日期:… prefix lines (multiple
lines allowed) as cover metadata rather than body paragraphs:
作者:张三
日期:2026-10-04A slide holding 1–3 images with no substantial body text is auto-detected as an
image page (image-single / image-double / image-triple). You can also opt
in explicitly, including via the layout directive:
@(layout=image-single)- A standalone
===always means a row break — setext-style headlines (Title+===) are# Headingsin mfly. - A standalone
<->always means a column break; use***text***for bold italic (the moffee convention of<->bold and italic<->is deliberately not adopted to avoid ambiguity).
# Run all unit and integration tests
pnpm test| Feature | MarkdownFly | Marp | Slidev | reveal.js |
|---|---|---|---|---|
| Output format | ✅ .pptx (editable) |
PDF / HTML | HTML | HTML |
| No browser / headless Chrome needed | ✅ | ❌ | ❌ | ❌ |
| Zero native binary dependencies | ✅ | ❌ | ❌ | ❌ |
| Mermaid / Graphviz / PlantUML / ECharts | ✅ All 4 | Mermaid only | Mermaid only | ❌ |
| CLI-first, CI/CD friendly | ✅ | ✅ | ❌ | |
| Syntax-highlighted code blocks | ✅ Shiki | ✅ | ✅ | |
| Editable slides after export | ✅ | ❌ | ❌ | ❌ |
| In-slide grid layout | ✅ <-> / === |
❌ | ❌ |
TL;DR — MarkdownFly is the only tool that outputs a natively editable
.pptxwith full diagram support and zero native binary dependencies.
MIT License © 2026 MarkdownFly Contributors
Made with ❤️ by MarkdownFly Contributors