Community编程与开发github.com

html-to-pptx

将HTML幻灯片(每个.slide div 1280x720)转换为原生、完全可编辑的PowerPoint文件——包含真实的矩形、圆角盒、胶囊、圆形、线条、箭头、自由形状、项目符号、曲线文本和文本框,而非幻灯片图片。

html-to-pptx 是什么?

该技能旨在将HTML幻灯片(每个幻灯片对应一个 `.slide` div,尺寸 1280x720 像素)转换为原生、完全可编辑的 PowerPoint 演示文稿 (.pptx)。它通过 Playwright 结合浏览器计算布局渲染页面,并利用 python-pptx 在精确坐标上生成真实形状,确保所有元素(方块、条形、圆点、胶囊、线条、文本块)均为可移动、可更改颜色和重输入文本的 PowerPoint 对象,而非图片。支持的平台包括任何可运行 Python 的环境,需要安装 requirements.txt 和 Chromium。该技能适用于用户要求“将HTML转换为PowerPoint”、“制作可编辑的PPT”或避免仅在PPT中粘贴图片的场景。它处理多种HTML元素到PPTX形状的映射,如div过渡为矩形/圆角矩形、列表过渡为项目符号、SVG路径过渡为自由形状等,并包含大量经过验证的排版和布局校准规则(如Arial/ Arial Black 字体的文本定位),输出前还需通过 PowerPoint 或 LibreOffice 渲染对比验证。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ImperaBusinessServices/html-to-pptx/tree/HEAD

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

HTML 幻灯片 -> 原生可编辑 PPTX

该技能强制执行的核心规则:绝不要将幻灯片图片粘贴到 PowerPoint 中。 每个方块、条形、圆点、胶囊、线条和文本块都必须是用户可移动、可重新着色和可重新输入文本的真正的 PowerPoint 对象。转换器读取渲染后的页面(Playwright + 浏览器自身的计算布局),而不是重新猜测 CSS,然后在精确相同的坐标上写 python-pptx 形状。

运行

python scripts/html_to_pptx.py <deck.html> <out.pptx> [all | 1,3,5]

需要:pip install -r requirements.txt 和 playwright install chromium。 幻灯片是匹配 .slide 的元素(1280x720 px)。将 .html 放在某个位置,其中的图片可以是内联的(data: URI)或在磁盘上与其并列。examples/sample-deck.html 是一个小型演示文稿,可先尝试。

页面在被捕获时需要处于以下状态(脚本会自动完成这些操作):从 <html> 中移除 anim 类,关闭 CSS 动画/过渡,触发 window beforeprint(演示文稿通常在打印时显示图表),使用打印媒体,缩放为 1,隐藏具有类 .mode 或 .jump 的元素(主题切换、幻灯片导航器)。带有亮/暗主题切换的演示文稿会在当前显示的主题下转换——请确保这是用户想要的主题。

什么变成什么

在 HTML 中在 PPTX 中
带有背景、边框、圆角的 div / 卡片矩形 / 圆角矩形(圆角 -> 角调整)
线性渐变背景原生渐变填充
单边边框(强调条纹)细矩形;发丝/虚线边框 -> 真实线条
border-radius:999px 胶囊、圆形胶囊 / 椭圆
文本(任何块,带有粗体/颜色区段、<br>、链接)每块一个文本框,区段保留,超链接保留
<li>真实的 PowerPoint 项目符号(标记颜色保留)
内联 SVG rect/circle/line/polyline/path/text矩形、椭圆、连接线(箭头保留)、带真实贝塞尔曲线的自由形状、文本框
SVG <textPath>(曲线上的文本)PowerPoint 曲线文本(向上/向下拱形扭曲)
CSS clip-path: polygon(...)(V形、对角切割)自由形状;内部的照片被裁剪成多边形
<img>、照片、图标 PNG图片(它们是位图——这是预期的)
text-transform、letter-spacing、strikethrough、opacity/alpha应用于区段/填充
双视图切换(带有 data-view=code 和 data-view=time 按钮的 .vtog)另一个视图的第二个幻灯片
JS 动画仅最终静止状态

来之不易的规则(每条都耗费了实际时间——请保留)

  1. 文本位置是校准过的,不要凭肉眼“修正”。 PowerPoint 100% 行间距 = 1.2 x 字号(Arial 和 Arial Black 都一样)。文本框必须放置在 top = rangeTop + (ascent-cap)*fs - lineHeight + K*fs 处,其中对于 Arial,(ascent-cap, K) = (0.189, 0.95),对于 Arial Black,(0.385, 1.0),且 line_spacing = cssLineHeight / (1.2*fs)。单行文本使用 100% 间距和 wrap=none,并留有一定余量,使其永远不会重新换行。
  2. Windows 上的 Chrome 将 font-family: Arial 并以权重 800/900 渲染为 ARIAL BLACK。 转换器将其映射为 Arial Black(而非粗体)。没有这一条,每个粗标题看起来都太细且宽度不对。
  3. 绝不要将 inline-block 子元素吞并到文本块中。 只有 display:inline 子元素合并到一个文本框中;inline-block/flex 子元素单独处理。
  4. 就地测量文本节点(对节点使用 Range)。将节点包裹在临时 <span> 中会改变网格/弹性布局。
  5. 在 PowerPoint 中打开结果以证明其有效。 python-pptx 会愉快地写出 PowerPoint 拒绝的文件(“PowerPoint 无法打开文件”)。已知原因:负值/NaN 形状尺寸(钳制,丢弃 NaN 点),以及 clip-path 内部的 calc()(求值)。通过以一半一半的方式删除形状并重新打开来二分定位问题。
  6. 带有自定义几何形状的图片会填充其路径的边界框,而不是其框架。 要将照片裁剪为多边形,将图片大小设置为多边形边界框大小,并设置源裁剪 (srcRect) 以处理剩余部分。
  7. 不要截图捕获形状(“将奇怪的形状光栅化”)。相反,将标识的 SVG 路径和 clip-path 多边形转换为自由形状。raster 分支是最后的手段。
  8. 跳过被裁剪的幽灵文本(被其卡片截断的大号淡色数字)——PowerPoint 无法裁剪文本框。
  9. PowerPoint 的 a:ln 在 spPr 中位于填充之后;删除主题的 p:style,否则形状会拾取阴影。
  10. 永远不要覆盖用户已打开的 .pptx——相反,写入一个新的文件名。

验证(始终进行——绝不发布未经检查的内容)

在安装了 PowerPoint 的 Windows 上:

powershell -NoProfile -File scripts/render_pptx.ps1 -pptx <out.pptx> -outdir <png_dir>     # PowerPoint 导出为 PNG
python scripts/compare.py <deck.html> <png_dir> 1,2,3 <out.png>                           # HTML | PPTX 并排比较
python scripts/compare.py <deck.html> <png_dir> 6:6,7:8 <out.png>                          # 当幻灯片编号不同时:html:pptx

render_pptx.ps1 如果用户已打开 PowerPoint,则会保持其运行。如果没有 PowerPoint,通过其他方法(例如 LibreOffice 无头模式)将 .pptx 渲染为 PNG 到 s1.png、s2.png... 并运行 compare.py。

阅读比较 PNG,修复,重新构建。运行后典型的清理工作:PowerPoint 中的文本稍微宽一点(字距调整),没有结构性问题。

已知限制(告知用户)

  • 文本位置针对 Arial 和 Arial Black 进行了校准。其他字体会转换,但文本可能偏高或偏低几个像素,直到该字体被校准(在 PowerPoint 中测量大写字母高度和行间距)。
  • 作为位图提供的照片、图标和标志会保持为图片。文本位于其卡片顶部的独立框中(未分组)。
  • 动画/切换被扁平化为一个帧(切换的第二个视图成为额外的幻灯片)。
  • 径向渐变和逐角半径是近似的;box-shadow 被丢弃。
  • 幻灯片尺寸固定为 1280x720 px -> 13.333 x 7.5 英寸。

致谢

由 Impera Business Services 构建。MIT 许可证——参见 LICENSE。

相关技能