hackmd-to-pptx
Use when converting HackMD/Marp markdown slides to PowerPoint presentations, or when merging multiple HackMD/Marp decks into one combined deck.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when converting HackMD/Marp markdown slides to PowerPoint presentations, or when merging multiple HackMD/Marp decks into one combined deck.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | hackmd-to-pptx |
| description | Use when converting HackMD/Marp markdown slides to PowerPoint presentations, or when merging multiple HackMD/Marp decks into one combined deck. |
| license | MIT |
| compatibility | Requires Python 3.9+, uv |
| metadata | {"author":"William Yeh","languages":"python,javascript,java,kotlin,go,rust,ruby,php,sql,bash,yaml,html,cpp"} |
Convert HackMD/Marp-style markdown slides to professional PowerPoint presentations.
# Convert with explicit output name
uv run scripts/convert.py input.md output.pptx
# Output name defaults to input.pptx
uv run scripts/convert.py presentation.md
Combine several HackMD/Marp files into one deck where each input becomes a top-level section (---) and its slides become sub-slides (----):
uv run scripts/merge.py deck1.md deck2.md deck3.md -o merged.md
uv run scripts/merge.py deck1.md deck2.md -o merged.md --title "Combined Deck"
uv run scripts/merge.py deck1.md deck2.md -o merged.md --no-toc
The first input's frontmatter (theme, paginate, etc.) is preserved; --title overrides the title: field. Each deck's first H1 becomes the section title; if absent, the filename stem is used. Internal --- sections inside an input deck are demoted to ---- (PowerPoint sections can't nest).
Table of Contents (default on): A TOC slide is emitted as the first section, listing every deck's title as a bullet. Its heading is the --title value, or deck 1's title if --title is absent. Pass --no-toc to suppress.
Style preservation: If deck 1 has a <style>...</style> block at the top of its body (between frontmatter and first heading), the block is lifted into the merged file's head verbatim. Style blocks in other input decks are discarded (same precedent as frontmatter).
Synthetic cover slides: Every input deck gets a synthetic # Deck Title cover slide prepended, even if the deck already starts with # Title. This guarantees PowerPoint section grouping works correctly regardless of how the input deck's first slide is structured (e.g. # H1 + ## H2).
Input requirements:
--- lines inside fenced code blocks are preserved (they are not treated as slide separators).Place config.json or config.yaml in the same directory as the markdown file:
{
"colors": {
"accent": "0891B2",
"codeBlock": "F1F5F9",
"syntaxKeyword": "7C3AED",
"syntaxString": "059669",
"syntaxComment": "6B7280",
"syntaxNumber": "DC2626",
"syntaxFunction": "2563EB",
"syntaxType": "D97706"
},
"fonts": {
"header": "Trebuchet MS",
"body": "Calibri",
"code": "Consolas"
}
}
Colors: 6-digit hex without #, all keys optional. Fonts: system font names, all keys optional.
<style> blocksA <style>...</style> block placed at the top of the markdown (between frontmatter and the first heading) is translated to PowerPoint run properties. Per-slide <style> blocks deeper in the deck are ignored.
Supported selectors (matched on the trailing token, so .reveal .slides h1 resolves the same as h1):
.reveal .slides — slide-body defaulth1, h2, h3 — slide titlescode, pre — inline code only (fenced code blocks render at a fixed 11pt to fit their auto-sized textbox)p, li, a, blockquote, table — other body elementsSupported properties:
color, background-colorfont-size, font-family, font-weight, font-styletext-align, text-decorationEverything else is silently dropped. Values may use #RRGGBB, #RGB, rgb(...), or common named colors. Font sizes accept px, pt, or em (1em ≈ 16px).
Contrast guard. When a CSS color would fail WCAG AA (4.5:1) against the slide background, it is dropped and the run falls back to its default. The converter targets the default Office white background; if your slide master uses a dark background, set colors.slideBg in config.json so the guard sees the real background.