claude可以画ppt,做csv了

538 阅读23分钟

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/ - 图片与其他媒体文件
字体与颜色抽取

当需要临摹某个示例设计时:请先按以下方法分析其字体与配色:

  1. 读取主题文件:检查 ppt/theme/theme1.xml 中的颜色(<a:clrScheme>)与字体(<a:fontScheme>
  2. 抽样幻灯片内容:查看 ppt/slides/slide1.xml 中的实际字体使用(<a:rPr>)与颜色
  3. 搜索模式:使用 grep 在所有 XML 文件中查找颜色(<a:solidFill><a:srgbClr>)与字体引用

不使用模板的情况下新建 PowerPoint 演示文档

从零创建新演示文档时,使用 html2pptx 工作流,将 HTML 幻灯片高保真地转换为 PowerPoint(含精准定位)。

设计原则

关键:开始创建任何演示文档前,先分析内容并选择合适的设计要素:

  1. 考虑主题:这个演示的主题是什么?它暗示何种基调、行业或氛围?
  2. 检查品牌:若用户提及公司/组织,请考虑其品牌色与识别体系
  3. 让配色匹配内容:选择能反映主题的颜色
  4. 先说明你的方法:在写代码前,先解释你的设计选择

要求

  • ✅ 在写代码之前,先陈述基于内容的设计方案
  • ✅ 仅使用 web-safe fonts:Arial、Helvetica、Times New Roman、Georgia、Courier New、Verdana、Tahoma、Trebuchet MS、Impact
  • ✅ 通过字号、字重与颜色建立清晰的信息层级
  • ✅ 确保可读性:强对比、合适字号、整洁对齐
  • ✅ 保持一致:在幻灯片间复用间距、样式与视觉语言
配色选择

有创意地选色

  • 别停留在默认:选择真正贴合主题的颜色,避免“自动驾驶”
  • 多维思考:主题、行业、情绪能量、目标受众、(若有)品牌身份
  • 敢于尝试:医疗不必一定是绿色,金融也不必一定是藏蓝
  • 构建你的调色板:挑选 3–5 个彼此协调的颜色(主色 + 辅助色 + 点缀色)
  • 保证对比:文字必须在背景上清晰可读

示例调色板(可用作灵感——任选其一、改造或自创):

  1. Classic Blue:Deep navy (#1C2833), slate gray (#2E4053), silver (#AAB7B8), off-white (#F4F6F6)
  2. Teal & Coral:Teal (#5EA8A7), deep teal (#277884), coral (#FE4447), white (#FFFFFF)
  3. Bold Red:Red (#C0392B), bright red (#E74C3C), orange (#F39C12), yellow (#F1C40F), green (#2ECC71)
  4. Warm Blush:Mauve (#A49393), blush (#EED6D3), rose (#E8B4B8), cream (#FAF7F2)
  5. Burgundy Luxury:Burgundy (#5D1D2E), crimson (#951233), rust (#C15937), gold (#997929)
  6. Deep Purple & Emerald:Purple (#B165FB), dark blue (#181B24), emerald (#40695B), white (#FFFFFF)
  7. Cream & Forest Green:Cream (#FFE1C7), forest green (#40695B), white (#FCFCFC)
  8. Pink & Purple:Pink (#F8275B), coral (#FF574A), rose (#FF737D), purple (#3D2F68)
  9. Lime & Plum:Lime (#C5DE82), plum (#7C3A5F), coral (#FD8C6E), blue-gray (#98ACB5)
  10. Black & Gold:Gold (#BF9A4A), black (#000000), cream (#F4F6F6)
  11. Sage & Terracotta:Sage (#87A96B), terracotta (#E07A5F), cream (#F4F1DE), charcoal (#2C2C2C)
  12. Charcoal & Red:Charcoal (#292929), red (#E33737), light gray (#CCCBCB)
  13. Vibrant Orange:Orange (#F96D00), light gray (#F2F2F2), charcoal (#222831)
  14. Forest Green:Black (#191A19), green (#4E9F3D), dark green (#1E5128), white (#FFFFFF)
  15. Retro Rainbow:Purple (#722880), pink (#D72D51), orange (#EB5C18), amber (#F08800), gold (#DEB600)
  16. Vintage Earthy:Mustard (#E3B448), sage (#CBD18F), forest green (#3A6B35), cream (#F4F1DE)
  17. Coastal Rose:Old rose (#AD7670), beaver (#B49886), eggshell (#F3ECDC), ash gray (#BFD5BE)
  18. 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%)来优化空间分配。
  • 全幅布局:让图表/表格占据整页以获得最大可读性与冲击力
  • 切勿垂直堆叠:不要将图表/表格放在文字下方形成单列——这会导致可读性差与布局问题

工作流

  1. 强制步骤 - 通读整份文件:完整阅读 html2pptx.md读取该文件时绝对不要设置范围限制。 按顺序读完以掌握语法、关键格式规则和最佳实践,再开始制作演示文档。

  2. 为每张幻灯片创建一个 HTML 文件,并设置恰当尺寸(例如 16:9 使用 720pt × 405pt)

    • 所有文本使用 <p><h1>-<h6><ul><ol>
    • 可视化占位区域使用 class="placeholder"(渲染为灰色背景以便识别)
    • 关键:先将渐变与图标光栅化为 PNG(用 Sharp),再在 HTML 中引用
    • 布局:对于包含图表/表格/图片的幻灯片,优先使用“全幅”或“两栏”布局以提升可读性
  3. 使用 html2pptx.js 的库创建并运行 JavaScript,将 HTML 幻灯片转换为 PowerPoint 并保存

    • 使用 html2pptx() 处理每个 HTML 文件
    • 用 PptxGenJS API 在占位区域添加图表与表格
    • 使用 pptx.writeFile() 保存演示文档
  4. 视觉校验:生成缩略图并检查布局问题

    • 生成缩略图网格:python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4

    • 认真检查缩略图是否存在:

      • 文字截断:被页眉条、形状或页面边缘截断
      • 文字重叠:文字之间或与形状之间相互遮挡
      • 定位问题:内容离边界过近或彼此过近
      • 对比不足:文字与背景的对比不够
    • 若发现问题,调整 HTML 的边距/间距/颜色并重新生成

    • 重复直到所有幻灯片视觉正确

编辑现有 PowerPoint 演示文档

编辑已有幻灯片时,需要直接操作 Office Open XML(OOXML)格式。这包括:解包 .pptx、编辑 XML、再打包。

工作流

  1. 强制步骤 - 通读整份文件:完整阅读 ooxml.md(约 500 行)。读取该文件时绝对不要设置范围限制。 在进行任何编辑前,先掌握 OOXML 结构与编辑流程。
  2. 解包演示文档:python ooxml/scripts/unpack.py <office_file> <output_dir>
  3. 编辑 XML 文件(主要是 ppt/slides/slide{N}.xml 及其相关文件)
  4. 关键:每次编辑后立刻验证并修复错误:python ooxml/scripts/validate.py <dir> --original <file>
  5. 打包最终演示文档:python ooxml/scripts/pack.py <input_directory> <office_file>

使用模板新建 PowerPoint 演示文档

当需要按照既有模板的设计来创建演示文档时,你需要先复制与重排模板中的幻灯片,再替换占位内容。

工作流

  1. 同时抽取模板文本并生成缩略图网格

    • 抽取文本:python -m markitdown template.pptx > template-content.md
    • 阅读 template-content.md:通读整个文件理解模板内容。读取时不要设置任何范围限制。
    • 生成缩略图网格:python scripts/thumbnail.py template.pptx
    • 参见 Creating Thumbnail Grids 了解详情
  2. 分析模板并将清单保存到文件

    • 视觉分析:查看缩略图网格,理解幻灯片布局、设计模式与视觉结构

    • 创建并保存模板清单 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 ...]
      
    • 使用缩略图网格:识别以下内容:

      • 布局模式(标题页、正文布局、分节页)
      • 图片占位的位置与数量
      • 幻灯片组间的设计一致性
      • 信息层级与结构
    • 该清单用于下一步选择合适的模板

  3. 基于模板清单创建演示文档大纲

    • 回顾步骤 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)
      ]
      
  4. 使用 rearrange.py 复制、重排与删除幻灯片

    • 使用脚本按所需顺序生成新演示文档:

      python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52
      
    • 脚本会自动完成重复页复制、删除未用页、重排序

    • 幻灯片索引从 0 开始

  5. 使用 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_beforespace_afterline_spacing(仅在设置时包含,单位 pt)
      • 颜色color(RGB,如 "FF0000"),theme_color(主题色,如 "DARK_1")
      • 属性输出:仅输出非默认值
  6. 生成替换文本并保存为 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
    • 正文:通常无需特殊属性
    • 引用:可能有特殊对齐或字体属性
  7. 使用 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 inventory
    
    ERROR: 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.jpgthumbnails-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

将幻灯片转换为图片

为了进行视觉分析,可采用两步法将幻灯片转为图片:

  1. 将 PPTX 转为 PDF

    soffice --headless --convert-to pdf template.pptx
    
  2. 将 PDF 页面转为 JPEG

    pdftoppm -jpeg -r 150 template.pdf slide
    

    这会生成类似 slide-1.jpgslide-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 相关的代码时:

  • 代码要精炼
  • 避免冗长的变量名与重复操作
  • 避免不必要的打印

依赖

所需依赖(应已安装):

  • markitdownpip install "markitdown[pptx]"(用于从演示文档提取文本)
  • pptxgenjsnpm install -g pptxgenjs(通过 html2pptx 创建演示文档)
  • playwrightnpm install -g playwright(用于 html2pptx 的 HTML 渲染)
  • react-iconsnpm install -g react-icons react react-dom(用于图标)
  • sharpnpm install -g sharp(用于 SVG 光栅化与图像处理)
  • LibreOfficesudo apt-get install libreoffice(用于 PDF 转换)
  • Popplersudo apt-get install poppler-utils(用于 pdftoppm 将 PDF 转图像)
  • defusedxmlpip install defusedxml(安全的 XML 解析)

html2ppt.md提示词

HTML 转 PowerPoint 指南

使用 html2pptx.js 库,将 HTML 幻灯片高精度(位置准确)转换为 PowerPoint 演示文档。

目录

  1. 创建 HTML 幻灯片
  2. 使用 html2pptx 库
  3. 使用 PptxGenJS

创建 HTML 幻灯片

每一张 HTML 幻灯片都必须设置正确的 body 尺寸:

布局尺寸

  • 16:9(默认):width: 720pt; height: 405pt
  • 4:3width: 720pt; height: 540pt
  • 16:10width: 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: boldfont-style: italictext-decoration: underlinecolor: #rrggbb
    • <span> 不支持:marginpadding(PowerPoint 文本 run 不支持)
    • 示例:<span style="font-weight: bold; color: #667eea;">Bold blue text</span>
  • 支持 Flexbox —— 位置由渲染布局计算
  • CSS 颜色请使用带 # 前缀的十六进制
  • 文本对齐:必要时使用 text-align(如 centerright)作为 PptxGenJS 的格式提示(当文本长度略有偏差时)

形状样式(仅适用于 DIV 元素)

重要:背景、边框与阴影仅对 <div> 生效,文本元素(<p><h1>-<h6><ul><ol>)不支持。

  • 背景:在 <div> 上使用 backgroundbackground-color
    • 示例:<div style="background: #f0f0f0;"> —— 生成带背景的形状
  • 边框:在 <div> 上的 border 会转换为 PowerPoint 形状边框
    • 支持统一边框:border: 2px solid #333333
    • 支持单侧边框:border-leftborder-rightborder-topborder-bottom(转换为线条形状)
    • 示例:<div style="border-left: 8pt solid #E76F51;">
  • 圆角:在 <div> 上使用 border-radius
    • border-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-gradientradial-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 库

依赖

以下库已全局安装,可直接使用:

  • pptxgenjs
  • playwright
  • sharp

基本用法

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 },
        ...
    ]
}

校验

该库会自动收集所有错误后再一次性抛出:

  1. HTML 尺寸必须与演示布局一致 —— 不一致会报告尺寸差异
  2. 内容不得溢出 body —— 一旦溢出会报告并给出精确值
  3. CSS 渐变 —— 报告不支持的渐变用法
  4. 文本元素样式 —— 报告为文本元素设置了背景/边框/阴影(这些仅允许用于 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 —— 内容溢出时自动分页新建幻灯片