Claude新出了Code execution and file creation这个experimental feature,不过和原来的Anylysis tool是互斥的,开启“文件创作模式”时,系统会自动关闭“Analysis tool”。因为这是两个并行的的沙箱环境。
Claude可以在受控沙箱里运行代码→处理数据→生成并编辑文件(如表格、PPT、PDF、数据报告、图片等)。产物会显示在右侧的Artifact窗格,可继续对话修改再生成。
代码在隔离环境中执行;默认只能访问你上传到会话的文件和沙箱内生成的文件。不会直接读取你电脑磁盘。
资源限制的话,单个文件最大 30 MB,单次代码执行时长限制了2–3 分钟的 command timed out
机制
以生成pptx为例,看看执行过程,以了解实际的机制。
实际上就是准备了一些md文档,指导这个agent系统如何生成制品。也就是一个特化版的Claude Code了。。
第二个md文档出现。
执行过程还会遇到很多问题。
结果也出不来
看来是 真 · 实验feature了。可以定义为,给非程序员准备的,在遇到问题时无法排查无法修复的,低门槛claude code。。
总结一下,就是一个很少投入的产品feature,而且主要以“吃社区”为主,不算原创。都怀疑是不是会成为正式feature。
不过呢,提示词我给套出来了,如下:
skill.md提示词
name: pptx description: "创建、编辑与分析演示文档。当需要处理 .pptx 文件以完成:(1)新建演示文档,(2)修改或编辑内容,(3)处理布局,(4)添加批注或演讲者备注,或其他与演示相关的任务时使用"
PPTX 的创建、编辑与分析
概览
用户可能会要求你创建、编辑或分析一个 .pptx 文件。一个 .pptx 本质上是包含 XML 文件和其他资源的 ZIP 压缩包。针对不同任务,你可以采用不同的工具与工作流。
读取与分析内容
文本抽取
如果你只需要读取演示文档中的文字内容,应将文档转换为 Markdown:
# Convert document to markdown
python -m markitdown path-to-file.pptx
原始 XML 访问
当涉及批注、演讲者备注、幻灯片布局、动画、设计元素和复杂格式时,需要访问原始 XML。处理这些特性时,你需要解包演示文档并阅读其原始 XML 内容。
解包文件
python ooxml/scripts/unpack.py <office_file> <output_dir>
注意:unpack.py 位于项目根目录相对路径 skills/pptx/ooxml/scripts/unpack.py。如果该脚本不在此路径,可使用 find . -name "unpack.py" 定位。
关键文件结构
ppt/presentation.xml- 演示文档主元数据与幻灯片引用ppt/slides/slide{N}.xml- 各张幻灯片内容(如 slide1.xml、slide2.xml)ppt/notesSlides/notesSlide{N}.xml- 每张幻灯片的演讲者备注ppt/comments/modernComment_*.xml- 指定幻灯片的批注ppt/slideLayouts/- 幻灯片布局模板ppt/slideMasters/- 母版幻灯片模板ppt/theme/- 主题与样式信息ppt/media/- 图片与其他媒体文件
字体与颜色抽取
当需要临摹某个示例设计时:请先按以下方法分析其字体与配色:
- 读取主题文件:检查
ppt/theme/theme1.xml中的颜色(<a:clrScheme>)与字体(<a:fontScheme>) - 抽样幻灯片内容:查看
ppt/slides/slide1.xml中的实际字体使用(<a:rPr>)与颜色 - 搜索模式:使用 grep 在所有 XML 文件中查找颜色(
<a:solidFill>、<a:srgbClr>)与字体引用
在不使用模板的情况下新建 PowerPoint 演示文档
从零创建新演示文档时,使用 html2pptx 工作流,将 HTML 幻灯片高保真地转换为 PowerPoint(含精准定位)。
设计原则
关键:开始创建任何演示文档前,先分析内容并选择合适的设计要素:
- 考虑主题:这个演示的主题是什么?它暗示何种基调、行业或氛围?
- 检查品牌:若用户提及公司/组织,请考虑其品牌色与识别体系
- 让配色匹配内容:选择能反映主题的颜色
- 先说明你的方法:在写代码前,先解释你的设计选择
要求:
- ✅ 在写代码之前,先陈述基于内容的设计方案
- ✅ 仅使用 web-safe fonts:Arial、Helvetica、Times New Roman、Georgia、Courier New、Verdana、Tahoma、Trebuchet MS、Impact
- ✅ 通过字号、字重与颜色建立清晰的信息层级
- ✅ 确保可读性:强对比、合适字号、整洁对齐
- ✅ 保持一致:在幻灯片间复用间距、样式与视觉语言
配色选择
有创意地选色:
- 别停留在默认:选择真正贴合主题的颜色,避免“自动驾驶”
- 多维思考:主题、行业、情绪能量、目标受众、(若有)品牌身份
- 敢于尝试:医疗不必一定是绿色,金融也不必一定是藏蓝
- 构建你的调色板:挑选 3–5 个彼此协调的颜色(主色 + 辅助色 + 点缀色)
- 保证对比:文字必须在背景上清晰可读
示例调色板(可用作灵感——任选其一、改造或自创):
- Classic Blue:Deep navy (#1C2833), slate gray (#2E4053), silver (#AAB7B8), off-white (#F4F6F6)
- Teal & Coral:Teal (#5EA8A7), deep teal (#277884), coral (#FE4447), white (#FFFFFF)
- Bold Red:Red (#C0392B), bright red (#E74C3C), orange (#F39C12), yellow (#F1C40F), green (#2ECC71)
- Warm Blush:Mauve (#A49393), blush (#EED6D3), rose (#E8B4B8), cream (#FAF7F2)
- Burgundy Luxury:Burgundy (#5D1D2E), crimson (#951233), rust (#C15937), gold (#997929)
- Deep Purple & Emerald:Purple (#B165FB), dark blue (#181B24), emerald (#40695B), white (#FFFFFF)
- Cream & Forest Green:Cream (#FFE1C7), forest green (#40695B), white (#FCFCFC)
- Pink & Purple:Pink (#F8275B), coral (#FF574A), rose (#FF737D), purple (#3D2F68)
- Lime & Plum:Lime (#C5DE82), plum (#7C3A5F), coral (#FD8C6E), blue-gray (#98ACB5)
- Black & Gold:Gold (#BF9A4A), black (#000000), cream (#F4F6F6)
- Sage & Terracotta:Sage (#87A96B), terracotta (#E07A5F), cream (#F4F1DE), charcoal (#2C2C2C)
- Charcoal & Red:Charcoal (#292929), red (#E33737), light gray (#CCCBCB)
- Vibrant Orange:Orange (#F96D00), light gray (#F2F2F2), charcoal (#222831)
- Forest Green:Black (#191A19), green (#4E9F3D), dark green (#1E5128), white (#FFFFFF)
- Retro Rainbow:Purple (#722880), pink (#D72D51), orange (#EB5C18), amber (#F08800), gold (#DEB600)
- Vintage Earthy:Mustard (#E3B448), sage (#CBD18F), forest green (#3A6B35), cream (#F4F1DE)
- Coastal Rose:Old rose (#AD7670), beaver (#B49886), eggshell (#F3ECDC), ash gray (#BFD5BE)
- Orange & Turquoise:Light orange (#FC993E), grayish turquoise (#667C6F), white (#FCFCFC)
视觉细节可选项
几何图形玩法:
- 用对角分割代替水平分割
- 不对称列宽(30/70、40/60、25/75)
- 标题文本旋转 90° 或 270°
- 图像采用圆形/六边形框
- 角落使用三角形点缀
- 叠加形状制造层次
边框与框架处理:
- 单侧加粗色块边(10–20pt)
- 双线边框并用对比色
- 用角括号替代完整边框
- L 形边(上+左或下+右)
- 标题下方加粗下划线(3–5pt)
排版处理:
- 夸张的字号对比(如 72pt 标题 vs 11pt 正文)
- 全大写标题并拉宽字距
- 用超大号数字标识编号节
- 数据/技术内容可用等宽字体(Courier New)
- 信息密度大时可用窄体(Arial Narrow)
- 关键强调可用描边字
图表与数据样式:
- 单色图表 + 单一强调色突出关键数据
- 优先水平条形图
- 以点图(dot plot)替代柱状图
- 最小化网格线,甚至无网格线
- 直接在元素上显示数据标签(避免图例)
- 用超大数字显示关键指标
版式创新:
- 全出血图片 + 文字叠加
- 侧边栏(20–30% 宽度)用于导航/上下文
- 模块化网格(3×3、4×4)
- Z 型或 F 型视线路径
- 彩色形状上悬浮文本框
- 类杂志的多栏布局
背景处理:
- 40–60% 面积的实色块
- 渐变填充(仅竖直或对角)
- 分割背景(两色,竖直或对角)
- 边到边的彩色带
- 以留白为设计元素
布局建议
当制作包含图表或表格的幻灯片时:
- 优先两栏布局:标题占全宽,下方两栏——一栏放文字/要点,另一栏放图表/表格。这样更平衡、可读性更佳。使用不等宽(如 40%/60%)来优化空间分配。
- 全幅布局:让图表/表格占据整页以获得最大可读性与冲击力
- 切勿垂直堆叠:不要将图表/表格放在文字下方形成单列——这会导致可读性差与布局问题
工作流
-
强制步骤 - 通读整份文件:完整阅读
html2pptx.md。读取该文件时绝对不要设置范围限制。 按顺序读完以掌握语法、关键格式规则和最佳实践,再开始制作演示文档。 -
为每张幻灯片创建一个 HTML 文件,并设置恰当尺寸(例如 16:9 使用 720pt × 405pt)
- 所有文本使用
<p>、<h1>-<h6>、<ul>、<ol> - 可视化占位区域使用
class="placeholder"(渲染为灰色背景以便识别) - 关键:先将渐变与图标光栅化为 PNG(用 Sharp),再在 HTML 中引用
- 布局:对于包含图表/表格/图片的幻灯片,优先使用“全幅”或“两栏”布局以提升可读性
- 所有文本使用
-
使用
html2pptx.js的库创建并运行 JavaScript,将 HTML 幻灯片转换为 PowerPoint 并保存- 使用
html2pptx()处理每个 HTML 文件 - 用 PptxGenJS API 在占位区域添加图表与表格
- 使用
pptx.writeFile()保存演示文档
- 使用
-
视觉校验:生成缩略图并检查布局问题
-
生成缩略图网格:
python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4 -
认真检查缩略图是否存在:
- 文字截断:被页眉条、形状或页面边缘截断
- 文字重叠:文字之间或与形状之间相互遮挡
- 定位问题:内容离边界过近或彼此过近
- 对比不足:文字与背景的对比不够
-
若发现问题,调整 HTML 的边距/间距/颜色并重新生成
-
重复直到所有幻灯片视觉正确
-
编辑现有 PowerPoint 演示文档
编辑已有幻灯片时,需要直接操作 Office Open XML(OOXML)格式。这包括:解包 .pptx、编辑 XML、再打包。
工作流
- 强制步骤 - 通读整份文件:完整阅读
ooxml.md(约 500 行)。读取该文件时绝对不要设置范围限制。 在进行任何编辑前,先掌握 OOXML 结构与编辑流程。 - 解包演示文档:
python ooxml/scripts/unpack.py <office_file> <output_dir> - 编辑 XML 文件(主要是
ppt/slides/slide{N}.xml及其相关文件) - 关键:每次编辑后立刻验证并修复错误:
python ooxml/scripts/validate.py <dir> --original <file> - 打包最终演示文档:
python ooxml/scripts/pack.py <input_directory> <office_file>
使用模板新建 PowerPoint 演示文档
当需要按照既有模板的设计来创建演示文档时,你需要先复制与重排模板中的幻灯片,再替换占位内容。
工作流
-
同时抽取模板文本并生成缩略图网格:
- 抽取文本:
python -m markitdown template.pptx > template-content.md - 阅读
template-content.md:通读整个文件理解模板内容。读取时不要设置任何范围限制。 - 生成缩略图网格:
python scripts/thumbnail.py template.pptx - 参见 Creating Thumbnail Grids 了解详情
- 抽取文本:
-
分析模板并将清单保存到文件:
-
视觉分析:查看缩略图网格,理解幻灯片布局、设计模式与视觉结构
-
创建并保存模板清单
template-inventory.md,内容类似:# Template Inventory Analysis **Total Slides: [count]** **IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)** ## [Category Name] - Slide 0: [Layout code if available] - Description/purpose - Slide 1: [Layout code] - Description/purpose - Slide 2: [Layout code] - Description/purpose [... EVERY slide must be listed individually with its index ...] -
使用缩略图网格:识别以下内容:
- 布局模式(标题页、正文布局、分节页)
- 图片占位的位置与数量
- 幻灯片组间的设计一致性
- 信息层级与结构
-
该清单用于下一步选择合适的模板
-
-
基于模板清单创建演示文档大纲:
-
回顾步骤 2 中可用的模板
-
为首页选择引导/标题模板,通常选前几页之一
-
其他页面优先选择稳妥的文字类布局
-
关键:让布局结构匹配真实内容:
- 单列布局:适合单一叙事或单一主题
- 两列布局:仅在你确实有“两项”并列内容时使用
- 三列布局:仅在你确实有“三项”并列内容时使用
- 图文混排布局:仅在你确实有要插入的图片时使用
- 引用型布局:只用于真实人物的引言(带署名),不要为了强调而滥用
- 切勿使用占位数量超过内容数量的布局
- 有 2 项内容时,不要硬塞进三列布局
- 若有 4+ 项,考虑拆成多页或使用列表形式
-
先统计你的实际内容,再选布局
-
确认所选布局的每个占位都会被“有意义的内容”填充
-
选择最合适的布局映射到每个内容段
-
将内容与模板映射保存为
outline.md -
模板映射示例:
# Template slides to use (0-based indexing) # WARNING: Verify indices are within range! Template with 73 slides has indices 0-72 # Mapping: slide numbers from outline -> template slide indices template_mapping = [ 0, # Use slide 0 (Title/Cover) 34, # Use slide 34 (B1: Title and body) 34, # Use slide 34 again (duplicate for second B1) 50, # Use slide 50 (E1: Quote) 54, # Use slide 54 (F2: Closing + Text) ]
-
-
使用
rearrange.py复制、重排与删除幻灯片:-
使用脚本按所需顺序生成新演示文档:
python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52 -
脚本会自动完成重复页复制、删除未用页、重排序
-
幻灯片索引从 0 开始
-
-
使用
inventory.py提取所有文本:-
运行清单提取:
python scripts/inventory.py working.pptx text-inventory.json -
阅读
text-inventory.json:通读整份 JSON,理解所有形状及属性。读取时不要设置任何范围限制。 -
清单 JSON 结构:
{ "slide-0": { "shape-0": { "placeholder_type": "TITLE", // or null for non-placeholders "left": 1.5, // position in inches "top": 2.0, "width": 7.5, "height": 1.2, "paragraphs": [ { "text": "Paragraph text", // Optional properties (only included when non-default): "bullet": true, // explicit bullet detected "level": 0, // only included when bullet is true "alignment": "CENTER", // CENTER, RIGHT (not LEFT) "space_before": 10.0, // space before paragraph in points "space_after": 6.0, // space after paragraph in points "line_spacing": 22.4, // line spacing in points "font_name": "Arial", // from first run "font_size": 14.0, // in points "bold": true, "italic": false, "underline": false, "color": "FF0000" // RGB color } ] } } } -
关键特性:
- Slides:命名为 "slide-0"、"slide-1" 等
- Shapes:按视觉顺序(自上而下、从左到右)命名为 "shape-0"、"shape-1" 等
- placeholder_type:TITLE、CENTER_TITLE、SUBTITLE、BODY、OBJECT 或 null
- 默认字号:从布局占位提取的
default_font_size(若可用),单位为 pt - 幻灯片编号过滤:SLIDE_NUMBER 类型的形状会被自动排除
- 项目符号:当
bullet: true时,始终包含level(即便为 0) - 间距:
space_before、space_after、line_spacing(仅在设置时包含,单位 pt) - 颜色:
color(RGB,如 "FF0000"),theme_color(主题色,如 "DARK_1") - 属性输出:仅输出非默认值
-
-
生成替换文本并保存为 JSON
基于上一步的文本清单:-
关键:先确认清单中实际存在的形状——只引用真实存在的形状
-
校验:
replace.py会校验你在 JSON 中引用的所有形状是否存在- 若引用了不存在的形状,会报错并列出可用形状
- 若引用了不存在的幻灯片,同样会报错
- 所有校验错误会一次性展示,然后脚本退出
-
重要:
replace.py内部会调用inventory.py识别全部文本形状 -
自动清空:清单里的所有文本形状都会被清空,除非你在 JSON 里为其提供了
"paragraphs" -
需要填充内容的形状添加
"paragraphs"字段(不要用"replacement_paragraphs") -
在替换 JSON 未出现的形状会被自动清空
-
当
"bullet": true时段落会自动左对齐;此时不要设定alignment -
为占位文本生成合适的替换内容
-
根据形状尺寸决定合适的内容长度
-
关键:保留原清单中的段落属性——不要只给纯文本
-
重要:当
bullet: true时,文本中不要包含项目符号(•、-、*),脚本会自动添加 -
基本格式规则:
- 标题/头应通常带
"bold": true - 列表项应有
"bullet": true, "level": 0(有 bullet 就必须给 level) - 保留对齐属性(例如居中的
"alignment": "CENTER") - 当与默认不同,包含字体属性(如
"font_size": 14.0、"font_name": "Lora") - 颜色:RGB 用
"color": "FF0000",主题色用"theme_color": "DARK_1" - 替换脚本需要格式完整的段落对象,而非裸字符串
- 重叠形状:优先选择
default_font_size更大或placeholder_type更合适的形状
- 标题/头应通常带
-
将带替换内容的清单保存为
replacement-text.json -
警告:不同模板布局的形状数量不同——在创建替换数据前务必确认实际清单
示例
paragraphs字段(正确格式):"paragraphs": [ { "text": "New presentation title text", "alignment": "CENTER", "bold": true }, { "text": "Section Header", "bold": true }, { "text": "First bullet point without bullet symbol", "bullet": true, "level": 0 }, { "text": "Red colored text", "color": "FF0000" }, { "text": "Theme colored text", "theme_color": "DARK_1" }, { "text": "Regular paragraph text without special formatting" } ]未在替换 JSON 出现的形状会被自动清空:
{ "slide-0": { "shape-0": { "paragraphs": [...] // This shape gets new text } // shape-1 and shape-2 from inventory will be cleared automatically } }演示中的常见格式模式:
- 标题页:加粗文本,常居中
- 幻灯片内分节标题:加粗文本
- 项目符号列表:每条都应
"bullet": true, "level": 0 - 正文:通常无需特殊属性
- 引用:可能有特殊对齐或字体属性
-
-
使用
replace.py应用替换python scripts/replace.py working.pptx replacement-text.json output.pptx脚本将会:
- 先用
inventory.py提取全部文本形状作为清单 - 校验替换 JSON 中的所有形状是否存在
- 清空清单中所有形状的文本
- 仅对替换 JSON 中提供了
"paragraphs"的形状写入新文本 - 保留段落属性(bullet、对齐、字体、颜色等)
- 保存更新后的演示文档
可能的校验错误示例:
ERROR: Invalid shapes in replacement JSON: - Shape 'shape-99' not found on 'slide-0'. Available shapes: shape-0, shape-1, shape-4 - Slide 'slide-999' not found in inventoryERROR: Replacement text made overflow worse in these shapes: - slide-0/shape-2: overflow worsened by 1.25" (was 0.00", now 1.25") - 先用
生成缩略图网格(Thumbnail Grids)
要快速分析与参考 PowerPoint 幻灯片,生成可视化缩略图网格:
python scripts/thumbnail.py template.pptx [output_prefix]
特性:
-
生成:
thumbnails.jpg(若页数较多则为thumbnails-1.jpg、thumbnails-2.jpg等) -
默认:5 列,每张网格最多 30 页(5×6)
-
自定义前缀:
python scripts/thumbnail.py template.pptx my-grid- 注意:若需输出到特定目录,前缀应包含路径(例如
workspace/my-grid)
- 注意:若需输出到特定目录,前缀应包含路径(例如
-
调整列数:
--cols 4(范围 3–6,会影响每张网格的幻灯片数) -
网格容量:3 列=12 页、4 列=20 页、5 列=30 页、6 列=42 页
-
幻灯片使用零基索引(Slide 0、Slide 1 等)
使用场景:
- 模板分析:快速理解布局与设计模式
- 内容复核:对整份演示的可视化总览
- 导航参考:根据视觉外观定位特定页面
- 质量检查:核对所有页面格式是否正确
示例:
# Basic usage
python scripts/thumbnail.py presentation.pptx
# Combine options: custom name, columns
python scripts/thumbnail.py template.pptx analysis --cols 4
将幻灯片转换为图片
为了进行视觉分析,可采用两步法将幻灯片转为图片:
-
将 PPTX 转为 PDF:
soffice --headless --convert-to pdf template.pptx -
将 PDF 页面转为 JPEG:
pdftoppm -jpeg -r 150 template.pdf slide这会生成类似
slide-1.jpg、slide-2.jpg的文件。
可选项:
-r 150:设置分辨率为 150 DPI(可根据质量/体积平衡调整)-jpeg:输出 JPEG(如需 PNG 则用-png)-f N:起始页-l N:结束页slide:输出文件前缀
仅转换特定范围示例:
pdftoppm -jpeg -r 150 -f 2 -l 5 template.pdf slide # Converts only pages 2-5
代码风格指南
重要:在生成与 PPTX 相关的代码时:
- 代码要精炼
- 避免冗长的变量名与重复操作
- 避免不必要的打印
依赖
所需依赖(应已安装):
- markitdown:
pip install "markitdown[pptx]"(用于从演示文档提取文本) - pptxgenjs:
npm install -g pptxgenjs(通过 html2pptx 创建演示文档) - playwright:
npm install -g playwright(用于 html2pptx 的 HTML 渲染) - react-icons:
npm install -g react-icons react react-dom(用于图标) - sharp:
npm install -g sharp(用于 SVG 光栅化与图像处理) - LibreOffice:
sudo apt-get install libreoffice(用于 PDF 转换) - Poppler:
sudo apt-get install poppler-utils(用于 pdftoppm 将 PDF 转图像) - defusedxml:
pip install defusedxml(安全的 XML 解析)
html2ppt.md提示词
HTML 转 PowerPoint 指南
使用 html2pptx.js 库,将 HTML 幻灯片高精度(位置准确)转换为 PowerPoint 演示文档。
目录
创建 HTML 幻灯片
每一张 HTML 幻灯片都必须设置正确的 body 尺寸:
布局尺寸
- 16:9(默认):
width: 720pt; height: 405pt - 4:3:
width: 720pt; height: 540pt - 16:10:
width: 720pt; height: 450pt
支持的元素
<p>,<h1>-<h6>—— 可带样式的文字<ul>,<ol>—— 列表(不要手动使用 •、-、* 等符号)<b>,<strong>—— 粗体(行内格式)<i>,<em>—— 斜体(行内格式)<u>—— 下划线(行内格式)<span>—— 通过 CSS 设置行内格式(粗体、斜体、下划线、颜色)<br>—— 换行- 具有背景/边框的
<div>—— 将被转换为形状(shape) <img>—— 图片class="placeholder"—— 预留图表区域(返回{ id, x, y, w, h })
关键文本规则
所有文本必须置于 <p>、<h1>-<h6>、<ul> 或 <ol> 标签内:
- ✅ 正确示例:
<div><p>Text here</p></div> - ❌ 错误示例:
<div>Text here</div>—— 在 PowerPoint 中不会显示 - ❌ 错误示例:
<span>Text</span>—— 在 PowerPoint 中不会显示 - 位于
<div>或<span>内、但不在文本标签中的文本会被静默忽略
绝不要使用手动项目符号(•、-、* 等)——请使用 <ul> 或 <ol>。
仅使用通用可用的 web-safe fonts:
- ✅ web-safe fonts:
Arial,Helvetica,Times New Roman,Georgia,Courier New,Verdana,Tahoma,Trebuchet MS,Impact,Comic Sans MS - ❌ 错误:
'Segoe UI','SF Pro','Roboto'或自定义字体 —— 可能导致渲染问题
样式
- 在
body上使用display: flex,可防止 margin 折叠破坏溢出校验 - 用
margin控制间距(padding 计入尺寸) - 行内格式:使用
<b>、<i>、<u>或带样式的<span><span>支持:font-weight: bold、font-style: italic、text-decoration: underline、color: #rrggbb<span>不支持:margin、padding(PowerPoint 文本 run 不支持)- 示例:
<span style="font-weight: bold; color: #667eea;">Bold blue text</span>
- 支持 Flexbox —— 位置由渲染布局计算
- CSS 颜色请使用带
#前缀的十六进制 - 文本对齐:必要时使用
text-align(如center、right)作为 PptxGenJS 的格式提示(当文本长度略有偏差时)
形状样式(仅适用于 DIV 元素)
重要:背景、边框与阴影仅对 <div> 生效,文本元素(<p>、<h1>-<h6>、<ul>、<ol>)不支持。
- 背景:在
<div>上使用background或background-color- 示例:
<div style="background: #f0f0f0;">—— 生成带背景的形状
- 示例:
- 边框:在
<div>上的border会转换为 PowerPoint 形状边框- 支持统一边框:
border: 2px solid #333333 - 支持单侧边框:
border-left、border-right、border-top、border-bottom(转换为线条形状) - 示例:
<div style="border-left: 8pt solid #E76F51;">
- 支持统一边框:
- 圆角:在
<div>上使用border-radiusborder-radius: 50%或更高会生成圆形- 小于 50% 的百分比按较小边计算
- 支持 px 与 pt(如
border-radius: 8pt;、border-radius: 12px;) - 示例:在 100×200px 盒子上
border-radius: 25%→ 以 100px 计算,半径 25px
- 阴影:
box-shadow会转换为 PowerPoint 外阴影- 仅支持外阴影(为避免损坏,忽略 inset 内阴影)
- 示例:
<div style="box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);"> - 说明:PowerPoint 不支持内阴影,故会跳过
图标与渐变
- 关键:不要使用 CSS 渐变(
linear-gradient、radial-gradient)——这不会被转换到 PowerPoint - 必须先用 Sharp 将渐变/图标生成 PNG,再在 HTML 中引用
- 渐变:先将 SVG 光栅化为 PNG 作为背景图
- 图标:将 react-icons 的 SVG 光栅化为 PNG
- 所有视觉效果在 HTML 渲染前都应预先光栅化为位图
使用 Sharp 光栅化图标:
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const sharp = require('sharp');
const { FaHome } = require('react-icons/fa');
async function rasterizeIconPng(IconComponent, color, size = "256", filename) {
const svgString = ReactDOMServer.renderToStaticMarkup(
React.createElement(IconComponent, { color: `#${color}`, size: size })
);
// Convert SVG to PNG using Sharp
await sharp(Buffer.from(svgString))
.png()
.toFile(filename);
return filename;
}
// Usage: Rasterize icon before using in HTML
const iconPath = await rasterizeIconPng(FaHome, "4472c4", "256", "home-icon.png");
// Then reference in HTML: <img src="home-icon.png" style="width: 40pt; height: 40pt;">
使用 Sharp 光栅化渐变:
const sharp = require('sharp');
async function createGradientBackground(filename) {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="562.5">
<defs>
<linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#COLOR1"/>
<stop offset="100%" style="stop-color:#COLOR2"/>
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#g)"/>
</svg>`;
await sharp(Buffer.from(svg))
.png()
.toFile(filename);
return filename;
}
// Usage: Create gradient background before HTML
const bgPath = await createGradientBackground("gradient-bg.png");
// Then in HTML: <body style="background-image: url('gradient-bg.png');">
示例
<!DOCTYPE html>
<html>
<head>
<style>
html { background: #ffffff; }
body {
width: 720pt; height: 405pt; margin: 0; padding: 0;
background: #f5f5f5; font-family: Arial, sans-serif;
display: flex;
}
.content { margin: 30pt; padding: 40pt; background: #ffffff; border-radius: 8pt; }
h1 { color: #2d3748; font-size: 32pt; }
.box {
background: #70ad47; padding: 20pt; border: 3px solid #5a8f37;
border-radius: 12pt; box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.25);
}
</style>
</head>
<body>
<div class="content">
<h1>Recipe Title</h1>
<ul>
<li><b>Item:</b> Description</li>
</ul>
<p>Text with <b>bold</b>, <i>italic</i>, <u>underline</u>.</p>
<div id="chart" class="placeholder" style="width: 350pt; height: 200pt;"></div>
<!-- Text MUST be in <p> tags -->
<div class="box">
<p>5</p>
</div>
</div>
</body>
</html>
使用 html2pptx 库
依赖
以下库已全局安装,可直接使用:
pptxgenjsplaywrightsharp
基本用法
const pptxgen = require('pptxgenjs');
const html2pptx = require('./html2pptx');
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_16x9'; // Must match HTML body dimensions
const { slide, placeholders } = await html2pptx('slide1.html', pptx);
// Add chart to placeholder area
if (placeholders.length > 0) {
slide.addChart(pptx.charts.LINE, chartData, placeholders[0]);
}
await pptx.writeFile('output.pptx');
API 参考
函数签名
await html2pptx(htmlFile, pres, options)
参数
-
htmlFile(string):HTML 文件路径(绝对或相对) -
pres(pptxgen):已设置好布局的 PptxGenJS 演示文档实例 -
options(object,可选):tmpDir(string):生成文件的临时目录(默认:process.env.TMPDIR || '/tmp')slide(object):复用的已存在幻灯片(默认:新建一页)
返回值
{
slide: pptxgenSlide, // 新建/复用的幻灯片
placeholders: [ // 占位区域数组
{ id: string, x: number, y: number, w: number, h: number },
...
]
}
校验
该库会自动收集所有错误后再一次性抛出:
- HTML 尺寸必须与演示布局一致 —— 不一致会报告尺寸差异
- 内容不得溢出 body —— 一旦溢出会报告并给出精确值
- CSS 渐变 —— 报告不支持的渐变用法
- 文本元素样式 —— 报告为文本元素设置了背景/边框/阴影(这些仅允许用于 div)
(继续下一部分……)
使用 PptxGenJS
添加图表
柱状图(Bar Chart)
// CORRECT: Single series with all labels
slide.addChart(pptx.charts.BAR, [{
name: "Sales 2024",
labels: ["Q1", "Q2", "Q3", "Q4"],
values: [4500, 5500, 6200, 7100]
}], {
...placeholders[0], // Use placeholder position
barDir: 'col', // 'col' = vertical bars, 'bar' = horizontal
showTitle: true,
title: 'Quarterly Sales',
showLegend: false, // No legend needed for single series
// Required axis labels
showCatAxisTitle: true,
catAxisTitle: 'Quarter',
showValAxisTitle: true,
valAxisTitle: 'Sales ($000s)',
// Optional: Control scaling
valAxisMaxVal: 8000,
valAxisMinVal: 0,
valAxisMajorUnit: 2000,
catAxisLabelRotate: 45,
dataLabelPosition: 'outEnd',
dataLabelColor: '000000',
// Use single color for single-series charts
chartColors: ["4472C4"]
});
散点图(Scatter Chart)
重要:散点图数据格式较特殊——第一条 series 放 X 轴值:
const data1 = [{ x: 10, y: 20 }, { x: 15, y: 25 }, { x: 20, y: 30 }];
const data2 = [{ x: 12, y: 18 }, { x: 18, y: 22 }];
const allXValues = [...data1.map(d => d.x), ...data2.map(d => d.x)];
slide.addChart(pptx.charts.SCATTER, [
{ name: 'X-Axis', values: allXValues },
{ name: 'Series 1', values: data1.map(d => d.y) },
{ name: 'Series 2', values: data2.map(d => d.y) }
], {
x: 1, y: 1, w: 8, h: 4,
lineSize: 0,
lineDataSymbol: 'circle',
lineDataSymbolSize: 6,
showCatAxisTitle: true,
catAxisTitle: 'X Axis',
showValAxisTitle: true,
valAxisTitle: 'Y Axis',
chartColors: ["4472C4", "ED7D31"]
});
折线图(Line Chart)
slide.addChart(pptx.charts.LINE, [{
name: "Temperature",
labels: ["Jan", "Feb", "Mar", "Apr"],
values: [32, 35, 42, 55]
}], {
x: 1, y: 1, w: 8, h: 4,
lineSize: 4,
lineSmooth: true,
showCatAxisTitle: true,
catAxisTitle: 'Month',
showValAxisTitle: true,
valAxisTitle: 'Temperature (°F)',
valAxisMinVal: 0,
valAxisMaxVal: 60,
valAxisMajorUnit: 20,
chartColors: ["4472C4", "ED7D31", "A5A5A5"]
});
饼图(Pie Chart)
关键:饼图要求单一数据 series:
slide.addChart(pptx.charts.PIE, [{
name: "Market Share",
labels: ["Product A", "Product B", "Other"],
values: [35, 45, 20]
}], {
x: 2, y: 1, w: 6, h: 4,
showPercent: true,
showLegend: true,
legendPos: 'r',
chartColors: ["4472C4", "ED7D31", "A5A5A5"]
});
图表配色
关键:颜色必须使用不带 # 前缀的十六进制 —— 带 # 会导致文件损坏。
// Correct
const chartColors = ["16A085", "FF6B9D", "2C3E50"];
// Wrong - will cause corruption
const chartColors = ["#16A085", "#FF6B9D", "#2C3E50"];
添加表格
基础表格
slide.addTable([
["Header 1", "Header 2", "Header 3"],
["Row 1, Col 1", "Row 1, Col 2", "Row 1, Col 3"],
["Row 2, Col 1", "Row 2, Col 2", "Row 2, Col 3"]
], {
x: 0.5,
y: 1,
w: 9,
h: 3,
border: { pt: 1, color: "999999" },
fill: { color: "F1F1F1" }
});
自定义格式表格
const tableData = [
[
{ text: "Product", options: { fill: { color: "4472C4" }, color: "FFFFFF", bold: true } },
{ text: "Revenue", options: { fill: { color: "4472C4" }, color: "FFFFFF", bold: true } },
{ text: "Growth", options: { fill: { color: "4472C4" }, color: "FFFFFF", bold: true } }
],
["Product A", "$50M", "+15%"],
["Product B", "$35M", "+22%"],
["Product C", "$28M", "+8%"]
];
slide.addTable(tableData, {
x: 1,
y: 1.5,
w: 8,
h: 3,
colW: [3, 2.5, 2.5],
rowH: [0.5, 0.6, 0.6, 0.6],
border: { pt: 1, color: "CCCCCC" },
align: "center",
valign: "middle",
fontSize: 14
});
表格常用选项
常见表格参数:
x, y, w, h—— 位置与尺寸colW—— 各列宽度数组(英寸)rowH—— 各行高度数组(英寸)border—— 边框样式:如{ pt: 1, color: "999999" }fill—— 背景色(不带#前缀)align—— 水平对齐:"left"、"center"、"right"valign—— 垂直对齐:"top"、"middle"、"bottom"fontSize—— 字号autoPage—— 内容溢出时自动分页新建幻灯片