从markdown生成ppt-软件Marp

用直接写markdown的形式生成 ppt 文件,至此完成了对 office 软件的扬弃。

Marp 的本质是一个 Markdown → HTML/CSS 幻灯片 的转换器(底层是 Marpit 框架)。每一页 ---分隔的内容会被渲染成一个 <section>元素,最终拼成一页页幻灯片。

vscode插件方式

安装 vscode 和 marp 插件

marp 可以单独安装,然后用命令行的方式运行。但是用 VS Code + Marp 插件 来替代命令行方案,会让你体验更好、效率倍增。它就像一个对开发者友好的“PPT 制作工具”,让你直接在 Markdown 里写幻灯片,并能实时看到专业、美观的视觉风格。

  1. 安装 vscode
  2. 安装 markdown 插件:安装 Markdown All in One ,这个插件能提供更强大的 Markdown 编辑辅助功能。
  3. 安装 Marp 插件:在插件市场的搜索框中输入 “Marp for VS Code”,然后点击搜索结果中的 “安装 (Install)” 按钮即可(注意:安装插件要关闭网络VPN代理)。
  4. 安装 “Marp to Editable PPTX” 插件:在 VS Code 的扩展商店中搜索并安装 “Marp to Editable PPTX

设置内容溢出诊断

如果一页内容太多,多出的内容 marp 会自动裁掉。Vs code 有一个选项可以提醒你这一点。

  1. 在 VS Code 里按 Ctrl + ,(或右上角 ⚙️ 管理 → 设置
  2. 顶部搜索框输入: marp overflow或完整键名: markdown.marp.diagnostics.slideContentOverflow
  3. 看到 Markdown › Marp: Diagnostics: Slide Content Overflow 这一项 → 勾选(或把下拉改成 enabled

开了之后你会看到什么

  • **必须打开 Marp Preview(预览窗口)**才会出现波浪线/警告
  • 当某一页内容跑到 <section>的 safe-area(padding 定义的可视区)外面时,Marp 扩展会在预览里标诊断(黄色波浪/Problem 面板提示),意思是:这页可能导出时被裁

试了一下没用

怎么打开 Marp Preview(预览窗口)

① 先确保你打开了那个 .md文件

在 VS Code 里把你的 xxx.md打开(左侧文件树单击就行)。

② 打开命令面板(搜索工具)

按快捷键:

1
Ctrl + Shift + P

顶部会出现一个搜索输入框

③ 在搜索框里输入这几个字之一(挑最容易拼的):

1
Marp: Open Preview

或更长全称:

1
Marp: Open Preview Window

输到 Marp: O一般就会自动补全出来了,用 ↓/↑ 选中:

Marp: Open Preview Window

然后按 Enter

④ 右侧/旁边会弹出一个新窗口,里面就是幻灯片预览

Marp官方导出的pptx的问题

Marp 官方导出的 PPTX 确实不能直接编辑,因为它的原理是把整张幻灯片“拍”成一张背景图。

因为 Marp 官方导出 PPTX 主要依赖 PptxGenJS 库。该库的设计初衷是快速将网页内容“快照”为幻灯片,因此它生成的文件中,文字都是作为静态背景图片的一部分,而不是可独立编辑的文本框。

“Marp to Editable PPTX” 插件可以解决这一问题,它在后台调用 Chrome 浏览器渲染 HTML,再精确提取每个元素的位置、字体、颜色,然后重新构建一个原生 PPTX 文件。

快速上手流程

  1. 新建文件并开启 Marp 功能

    • 在 VS Code 里新建一个文件,保存时文件名以 .md 结尾,例如 my_slides.md

    • 在文件最顶部输入 ---,然后换行再输入 marp: true,最后输入 --- 并换行。这段frontmatter元数据就告诉 VS Code:“请用 Marp 来处理这个 Markdown 文件”。示例如下

      1
      2
      3
      4
      5
      6
      7
      8
      9
      ---
      marp: true
      theme: default
      size: 16:9
      math: mathjax
      paginate: true
      backgroundColor: #ffffff
      ---

      说明如下

      配置项 含义 可选值/说明
      marp: true 启用 Marp 解析 必须写在文件最开头,告诉 VS Code 这个 Markdown 文件要用 Marp 引擎渲染为幻灯片
      theme: default 幻灯片主题 Marp 内置三个主题:default(简洁白底)、gaia(更现代的扁平风格)、uncover(全屏沉浸感)。你也可以自定义 CSS 主题
      size: 16:9 幻灯片宽高比 可选 16:9(宽屏,推荐)或 4:3(传统标屏)
      math: mathjax 公式渲染 声明有 mathjax 渲染公式
      paginate: true 显示页码 在每页幻灯片的右下角自动生成当前页/总页数(如 1/5)
      backgroundColor: #ffffff 背景色 十六进制颜色代码,#ffffff 表示白色。可以改为 #f0f0f0(浅灰)等其他颜色
    • 输入完成后,你可能会在编辑器右上角看到一个 Marp 的小图标(或一个“预览”图标),点击它就能打开实时预览窗口。

  2. 编写幻灯片内容
    现在,你就可以像写 Markdown 文档一样,去写你的幻灯片了。

    • 分页:使用 --- (三个连续的短横线) 来分隔每一页(最后不要写换行符,会多出空白页)。
    • 标题:每页顶部的 # 一级标题 通常会被视为该页幻灯片的大标题。
    • 内容:正常使用 Markdown 语法,像 - 无序列表1. 有序列表**加粗**_斜体_ 等都可以。
  3. 导出为 PPT 文件

    • marp 自带不可编辑格式:打开命令面板 (Ctrl+Shift+P),输入并执行 Marp: Export Slide Deck... 命,选择路径和文件格式。
    • Marp to Editable PPTX” 插件可编辑样式:打开命令面板 (Ctrl+Shift+P),输入并执行 Marp: Export to Editable PPTX命,选择路径和文件格式。

“Marp to Editable PPTX” 插件的问题

我测试了一下,“Marp to Editable PPTX” 插件导出的 PPT 默认是 Yu Gothic UI 字体,这是个日文字体,显示的中文排版很难看。

解决思路:显式定义中文字体

这是最优雅的方法,能让所有输出方式(PDF, HTML, PPTX)都受益。在你的 Marp 文件最顶部 frontmatter 之后,加一段内联 <style>,或者写进外部 CSS 都行。

这里写的 CSS 代码会被 Marp 原样注入到输出 HTML 的样式表里,变成全局生效的 CSS 规则——相当于你手动给"每一页幻灯片"设置了字体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
marp: true
theme: default
size: 16:9
math: mathjax
paginate: true
backgroundColor: #ffffff
---

<style>
/* ===== 全局字体:把中文字体放最前 ===== */
section {
font-family: 'Microsoft YaHei', 'PingFang SC', 'Noto Sans CJK SC', 'SimHei', sans-serif !important;
}

/* 代码块也一起锁(否则代码注释里的中文也可能方块) */
pre,
code,
pre > code {
font-family:
/* 第1层:等宽拉丁(Consolas 有英文字形,没中文→自动跳下一层) */
'Consolas',
/* 第2层:CJK 字形层(接住中文/全角,但它是比例宽度) */
'Microsoft YaHei',
/* 第3层:跨平台 CJK 兜底 */
'Noto Sans CJK SC', 'SimHei',
/* 最终等宽兜底 */
'Courier New', monospace !important;
}
</style>

解释一下这里的 !important : !important = 贴在整条声明末尾的标记,作用是把整条 font-family声明标为 important

正常情况下 CSS 优先级按这条链决胜负:

1
2
3
内联 style=""  >  ID选择器  >  类/属性选择器  >  元素选择器

(特异性越高越赢)

当一个属性值后面加上 !important,它就会无视正常的层叠优先级(如选择器权重、代码顺序),成为该元素该属性的“最终胜者”。!important 会覆盖任何没有 !important 的声明。

这里使用 !important 的原因是:Marp 的 gaia/ uncover主题自身带了:

1
2
3
section {
font-family: 'Roboto', 'Helvetica', sans-serif; /* ← 主题自带的,选择器也是 section */
}

如果没有 !important,两个 section { font-family }同特异性 → 源顺序靠后的赢。如果 Marp 主题样式在你 <style>之后注入(它经常这样干),你的设置就会被无声覆盖,中文变回 Roboto → 方块。

所以 !important在这的本质是:“别管你怎么算优先级,听我的。”

另外,marp 会将下面的代码渲染成下面的 HTML 格式。因此这里也设置了一下字体格式,避免代码出现字体问题。

1
a = a + 1
1
2
3
4
<pre>
<code class="language-python">a = a + 1
</code>
</pre>

图片

普通内联图片

在 Marp 里,当你设置了 size: 16:9size: 4:3 时,整个幻灯片(也就是 section 元素)的实际像素尺寸分别是 1280 x 720960 x 720

正常内联图片设置大小的核心参数是 w(宽),h(高)。我试了一下,只能设置长度单位,不接受百分比,如(设置一个,另一个默认就是 auto

1
![w:200px](1.png)

背景图片 - 占据整个幻灯片

那就将这个图片作为背景即可。

1
![bg contain](1.png)
  • contain : 等比缩放图片到"尽可能大",但保证整张图都装进容器 。

    所以有一边会刚好贴到section的对应边,另一边按比例缩小后 <section对应边,会有留空

contain到底做了什么几何运算?(可视化理解)

假设你 16:9 画布 = 宽 W × 高 H,图片原始 = 宽 w × 高 h

1
2
3
4
scale = min(W/w, H/h)

选"宽度方向能容纳的比例"和"高度方向能容纳的比例"中更小的那个
保证 scaled_w ≤ W 且 scaled_h ≤ H 同时成立

画完之后:

  • 完整可见
  • 多余空间留作上下或左右的留白(letterbox/pillarbox)
  • 绝不会裁掉任何像素

背景图片-图文分栏

上面正常的内联图片和文字是上下顺序。

Marp 的 bg 语法(设置为背景图片)也支持一些高级布局,比如让图片和文字分居两侧(这相当于一个捷径):

1
![bg left:50%](image.jpg)    # 将这张背景图片固定在幻灯片的左侧 50% 位置,右侧留给文字

还需要设置图片大小(不然可能显示不正常),如下例

1
![bg left:50% contain](1.png)

公式的问题

其他 markdown 格式都是 marp 原生支持的。只有 marp 公式是通过 mathjax 渲染的,我看在 PPT 里变成了图片。

因此在 “Marp to Editable PPTX” 插件导出的 PPT 里公式容易乱,特别是行内公式

因此要做到:

  1. 能不用公式,尽量不用公式,例如 $x$ 改成 x

导出为可编辑的pptx

  1. “Marp to Editable PPTX” 插件 : 缺点就是公式容易乱,有的版型也会乱,还得手动调整(就是不想手动调整)。
  2. 邪修做法:marp 导出 pdf, pdf 再转 ppt 。(pdf 转 ppt 目前用的网站 smallpdf ,好像目前可以免费使用2次)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
---
marp: true
theme: default
size: 16:9
math: mathjax
paginate: true
backgroundColor: #ffffff
---

<style>
/* ===== 全局字体:把中文字体放最前 ===== */
section {
font-family: 'Microsoft YaHei', 'PingFang SC', 'Noto Sans CJK SC', 'SimHei', sans-serif !important;
}

/* 代码块也一起锁(否则代码注释里的中文也可能方块) */
pre,
code,
pre > code {
font-family:
/* 第1层:等宽拉丁(Consolas 有英文字形,没中文→自动跳下一层) */
'Consolas',
/* 第2层:CJK 字形层(接住中文/全角,但它是比例宽度) */
'Microsoft YaHei',
/* 第3层:跨平台 CJK 兜底 */
'Noto Sans CJK SC', 'SimHei',
/* 最终等宽兜底 */
'Courier New', monospace !important;
}
</style>

# ← 这行是一页的标题(一级标题 = 整页大字居中)
- 列表项
- 列表项

---

## ← 这是第二页
普通段落文字。

**加粗** / *斜体* / `代码`

---

### 分栏示例(Gaia主题下好用)

<div class="columns">
<div>

**左栏**
- A
- B

</div>
<div>

**右栏**
- X
- Y

</div>
</div>

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2026 Vincere Zhou
  • 访问人数: | 浏览次数:

请我喝杯茶吧~

支付宝
微信