mcpField
P
pptx-html-fidelity-audit

pptx-html-fidelity-audit

github.com/nexu-io文档处理104.6k3.2k 次安装今天更新
代码仓库

关于 pptx-html-fidelity-audit

pptx-html-fidelity-audit 提供可重复的工作流,用于对照 HTML 源文件检查 PowerPoint 导出并修正布局偏差,适用于使用 python-pptx 等工具生成演示文稿的审查工作。

主要功能

  1. 01将幻灯片形状和排版信息提取为 JSON
  2. 02按布局边界检查幻灯片内容
  3. 03查找溢出、裁切和样式偏差
  4. 04通过游标布局与居中方案安排内容
  5. 05重新导出后验证几何位置

适用场景

  1. 01对照 HTML 幻灯片源文件审查 PPTX
  2. 02排查页脚重叠和画布外内容
  3. 03检查斜体或样式是否丢失
  4. 04交付前验证修正后的演示文稿

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nexu-io/open-design --skill pptx-html-fidelity-audit

安装后在 Claude Code 中输入/pptx-html-fidelity-audit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
audit-table-template.md
font-discipline.md
layout-discipline.md
scripts/
.gitignore
extract_pptx.py
verify_layout.py

详细介绍

PPTX ↔ HTML 保真度审计

这是一套可重复执行的工作流,用于发现 python-pptx 导出内容相较于 HTML 源文件悄然出现的偏差,并通过布局规范修复问题,避免下次再次出现同样的回归。

适用情形

用户拥有:

  • 一个 HTML 幻灯片源文件(通常是由多个 <section class="slide"> 区块组成的单文件幻灯片):

    <section class="slide light">
      <div class="chrome">2026 · Q2 review</div>
      <span class="kicker">Pillar 03</span>
      <h2 class="h-xl">Shipping <em>velocity</em> doubled</h2>
      <p class="lead">…</p>
      <div class="foot">page 5 / 14</div>
    </section>
    
  • 一个通过 python-pptx(或类似工具)根据该幻灯片生成的 PPTX 文件。

  • 怀疑(或已发现)PPTX 与 HTML 不一致,例如文本溢入页脚、斜体文字变成常规体、主视觉幻灯片未居中、区块被裁切、标签样式丢失。

如果用户只有这两种文件中的一种,则目前不适用此技能——请先生成缺少的文件,或请用户提供该文件。

难点所在(以及技能能提供的帮助)

PPTX 是固定画布、绝对定位的媒介,而 HTML 是流式布局的媒介。简单的 python-pptx 导出会将每个区块固定在手动指定的 (top, left) 坐标上;这对第一个测试幻灯片有效,却会在其他内容固有高度不同的幻灯片上悄然失效。由此产生的最常见偏差有:

  1. 页脚溢出——内容的 top + height 延伸至页脚区域。
  2. 内容超出画布——最后一个区块的底部超出 7.5"(16:9 画布)。
  3. 斜体丢失——HTML 中的 <em> 未被转换为 run.font.italic = True。
  4. 主视觉幻灯片未居中——垂直堆叠的幻灯片使用 MARGIN_TOP,而非计算居中位置。
  5. 文本框边界侵入——文本没有溢出,但形状的边界框尺寸过大,在视觉上越过了分隔线。
  6. 标签/样式丢失——彩色装饰栏、眉题的大写字母间距、等宽字体与衬线字体的指定等悄然恢复为默认值。

这些问题都是布局规范的问题,而非内容问题。采用规范后,这些问题就不会再出现。


工作流

审计分为五个步骤。请勿跳过任何步骤——只有审计能产出实际的问题清单,指导重新导出,规范才会奏效。未经审计就直接修复,往往会遗留一半问题。

步骤 1 — 从 PPTX 提取真实状态

运行 scripts/extract_pptx.py <path-to.pptx> > pptx_dump.json。该脚本会遍历每张幻灯片上的每个形状,并导出文本、位置(top / left)、尺寸(width / height)以及每段文字的排版信息(字体名称、字号 pt、粗体、斜体、颜色)。这是导出文件的实际状态——不要相信导出脚本的意图,要以导出数据为准。

对于 14 张幻灯片的演示文稿,导出文件约为 30–60 KB,且便于阅读。

步骤 2 — 遍历 HTML 结构

阅读 HTML 源文件,并列出所有 <section class="slide"> 区块。对于每个区块,记录:

  • 幻灯片的主题(light / dark / hero light / hero dark)。
  • chrome 行文本(顶部元数据)。
  • kicker(标题上方的小号大写眉题)。
  • 主标题(h-hero / h-xl 等)及任何副标题。
  • 正文文案及任何结构化区块(流程步骤、卡片、支柱、观察卡片)。
  • foot 行(底部元数据)。
  • 任何 <em> 或设为斜体的文本——斜体是容易被忽略的回归问题。

将每张 HTML 幻灯片映射到对应的 PPTX 幻灯片索引。对于遵循“幻灯片 1 = 封面,幻灯片 N = 结尾”惯例的演示文稿,按位置对应即可。

步骤 3 — 构建审计表

对于每张幻灯片,检查导出内容中的形状,并对照预期的布局规则。使用以下确切的表格格式——严重程度列决定修复优先级:

| Slide | Issue | Severity |
|---|---|---|
| 1 cover | meta-row 底端 6.95" 蓋過 footer (6.7") | 🔴 |
| 5 checklist | row B 步驟描述底端 7.2" 切到 footer | 🔴 |
| 8 3E | 收束段落直接坐在 footer 起點 | 🔴 |
| 9 on-day | step 描述底端剛好碰 footer,無安全距 | 🟠 |
| 多處 | em (Playfair italic) 未保留 | 🟡 |

严重程度标准:

  • 🔴 critical — 内容被裁切、文字不可见、与页脚重叠、超出画布。必须修复。
  • 🟠 high — 内容可见,但视觉层级混乱、缺少留白、主视觉未居中。应该修复。
  • 🟡 medium — 缺少斜体 / 强调格式、字体回退错误、颜色偏差。本轮修复。
  • 🟢 low — 轻微的间距 / 对齐问题、亚像素偏移。记录,但不阻塞。

在表格后,撰写一段简短的根因分析:通常 90 % 的问题来自 2–3 个系统性原因(例如“未强制设置页脚轨道”“主视觉内容组固定在 MARGIN_TOP,而不是居中”“斜体从未传递”)。指出系统性原因能让重新导出脚本更精简、更准确。

步骤 4 — 按页脚轨道 + 游标流式布局规范重新导出

这是关键技术。完整规则请参阅 references/layout-discipline.md;概要如下:

为整套幻灯片预先定义轨道,只需定义一次:

from pptx.util import Inches

CANVAS_W       = Inches(13.333)   # 16:9
CANVAS_H       = Inches(7.5)
MARGIN_X       = Inches(0.6)
MARGIN_TOP     = Inches(0.5)
CONTENT_MAX_Y  = Inches(6.70)     # NOTHING in content area may cross this
FOOTER_TOP     = Inches(6.85)     # footer row pinned here, edge-to-edge

自定义轨道。 上述默认值适用于带窄页脚的 16:9 画布。如果你的设计系统使用更宽的页脚或 4:3 画布,请在导出脚本中覆盖这些常量,并通过 --content-max-y / --canvas-h / --canvas-w 向 verify_layout.py 传入相同的值。完整常量表请参阅 references/layout-discipline.md §1。

为内容块使用游标,而不是将每个块固定在绝对 y 坐标上:

class Cursor:
    """Advances down the slide; refuses to cross the footer rail."""
    def __init__(self, y_start, cap=CONTENT_MAX_Y):
        self.y = y_start
        self.cap = cap
    def take(self, h, gap=Inches(0.12)):  # ~1 line of whitespace at 14pt; tighten/loosen per design system
        top = self.y
        self.y = top + h + gap
        if self.y > self.cap:
            raise OverflowError(
                f"cursor at {self.y} exceeds footer rail {self.cap}; "
                f"reduce block height or split slide"
            )
        return top

对于每张幻灯片,实例化 Cursor(MARGIN_TOP),并按照阅读顺序对每个内容块调用 take(height)。如果任何内容块会越过轨道,幻灯片就会拒绝渲染,因此溢出会成为明显的构建错误,而不是悄无声息的视觉问题。

主视觉(垂直居中)幻灯片使用预算,而不是游标:

def hero_layout(blocks):
    """blocks = list of (height, gap_after) tuples in reading order."""
    total = sum(h + g for h, g in blocks)
    y_start = (CANVAS_H - total) / 2
    return Cursor(y_start)

只需这一处更改,就能消除“主视觉幻灯片内容贴顶”这一最常见的主视觉缺陷。

收紧文本框高度,使其适配文本 + 最小内边距。 当形状重叠时,PowerPoint 会显示形状边界(选择光晕、Z 顺序冲突),过大的文本框即使内部文字没有越界,视觉上也可能跨过页脚轨道。根据文本度量值 + 约 0.05 英寸内边距计算文本框高度,不要使用过于宽松的外层容器。

明确保留斜体 / 强调格式:

def add_run(p, text, font, size_pt, italic=False, bold=False, color=None):
    r = p.add_run()
    r.text = text
    r.font.name = font
    r.font.size = Pt(size_pt)
    r.font.italic = italic
    r.font.bold = bold
    if color:
        r.font.color.rgb = color
    return r

遍历 HTML 时,检测 <em> / <i> / 内联样式 font-style: italic,并传入 italic=True。斜体显示文本使用英文字体衬线体(Playfair Display、Source Serif 或备用字体 Georgia)——CJK 衬线体通常没有斜体,尝试将其设为斜体会显得不协调。

对于布局轨道无法捕获的深层字体问题——PowerPoint 会悄悄替换为 Calibri / Microsoft JhengHei 的可变字体陷阱、缺少 <a:ea> 槽位导致 CJK 文本行回退、汉字伪斜体——请阅读 references/font-discipline.md。其中的五个层面涵盖了 verify_layout.py 无法检测的所有问题。

步骤 5 — 导出后验证

写入新的 .pptx 后,运行 scripts/verify_layout.py <path-to.pptx>。该脚本会:

  • 遍历每张幻灯片上的所有形状。
  • 断言内容形状的 top + height ≤ CONTENT_MAX_Y(页脚 / 页码形状可以位于轨道下方)。
  • 断言所有形状的 top + height ≤ CANVAS_H(不得超出画布)。
  • 断言 left + width ≤ CANVAS_W 且 left ≥ 0。
  • 将违规项汇总为一个区块报告:幻灯片索引、形状名称、检测到的底部位置、轨道位置。

违规项为零,是“此次重新导出可交付”的门槛。未经验证器检查,不要声称审计问题已修复——缩小视图时,人眼会漏掉 1–2 毫米的溢出,而脚本不会。

面向用户的输出

第 5 步通过后,报告以下内容:

  1. 审计表——第 3 步中的表格。
  2. 根本原因——用 1 段话说明系统性原因。
  3. 修复清单——简要列出改动及原因(例如:“英雄页幻灯片改用预算居中”“所有内容块均通过 Cursor 布局”“明确将 em 字体设为斜体”)。
  4. 验证结果——“N 张幻灯片中有 0 处边界线违规,文件大小为 X KB”。
  5. 路径——重新导出的 .pptx 的绝对路径。

用户阅读报告有两个目的:确认明显的问题已修复,并确信系统性修复方案正确。两方面都要涵盖。


随附资源

  • scripts/extract_pptx.py——将每张幻灯片上的每个形状导出为 JSON。审计前运行。**重要:**也要在原始导出文件上运行以便比较,并在重新导出的文件上运行以确认。
  • scripts/verify_layout.py——导出后检查边界线。发现违规时返回非零退出代码,必要时可接入 CI 流水线。
  • references/layout-discipline.md——完整的页脚边界线与光标流规则集,包含各种常见幻灯片类型(英雄页、内容页、流程页、双栏页、观察网格)的代码片段。
  • references/font-discipline.md——五层字体审计:映射、存在性、可变字体与静态字体陷阱、三个 XML 语言槽位(latin / ea / cs)、中日韩文字与拉丁文斜体的交互。
  • references/audit-table-template.md——可直接复制粘贴的表格模板,附严重程度说明。

以下情况请阅读参考资料:

  • 幻灯片包含 SKILL.md 未涵盖的类型(多列仪表盘、嵌入图像、图表)→ layout-discipline.md。
  • 审计发现 🟡 排版问题——斜体缺失、中日韩文字回退、XML 中意外出现 Calibri / Microsoft JhengHei → font-discipline.md。
  • 想将审计表直接放入报告或 Markdown 交付文档 → audit-table-template.md。

应避免的反模式

  • 修补单张幻灯片,却不说明系统性原因。 如果你通过将第 5 张幻灯片的内容块下移 0.2" 来修复它,接下来还得修第 9、11 和 14 张幻灯片。应找出导致这四处问题的规则。
  • 相信原始导出脚本的意图。 始终使用提取器检查实际文件。意图与实际结果之间的偏差就是问题所在。
  • 因为“在 PowerPoint 预览中看起来没问题”而跳过验证。 预览中的抗锯齿会掩盖 1–2 mm 的溢出,脚本不会。
  • 将不具备斜体传统的文字系统设为斜体。 中日韩文字、阿拉伯文、希伯来文、天城文、泰文和高棉文在强制设为 italic=True 时都会产生合成倾斜,导致字形机械变形。只将主要文字系统支持斜体的字体运行设为斜体——拉丁文、西里尔文和希腊文。实现方式请参阅 references/font-discipline.md 第 5 层。
  • 在英雄页上使用 MARGIN_TOP。 英雄页需要的是预算居中,而非顶部锚定。这是最常见的英雄页缺陷,也是最容易修复的。

为什么采用基于几何的验证,而非视觉差异比较

本技能的早期版本依赖视觉差异比较——通过 Keynote → PDF → PNG 渲染 .pptx,使用 Chrome 无头模式为 HTML 截图,再用 magick 将两者并排拼接。它虽然有效, 但有三个明显的缺点:

  • 平台锁定。 Keynote AppleScript 仅适用于 macOS;不同操作系统上的 magick 和 字体发现命令各不相同;Linux 上的 CI 流水线无法复现这一流程。
  • 不够精确。 1-2 mm 的溢出会在 PNG 预览中经抗锯齿处理而消失。人眼可能察觉不到, 脚本却能将其检测为明确的数值违规。
  • 配置成本。 每位贡献者都必须安装完整的图形工具链才能进行审核。几何检查只需要 python-pptx。

基于几何的验证放弃了视觉差异比较擅长的一项能力:发现形状位置正确,但渲染出的字形有误的情况(字体回退、字距调整错误、字重缺失)。出现这种情况时,请改为手动检查截图——references/font-discipline.md 中的五层审核涵盖了大多数根本原因。

评论

支持 Markdown