Help us improve
Share bugs, ideas, or general feedback.
From feishu-deck-h5
Converts .pptx files into a self-contained HTML deck with 100% fidelity (rasterized slides) and editable text overlay. Press E to toggle edit mode, with per-frame text editing, CJK font subsetting, optional FaaS persistence, and browser translation support.
npx claudepluginhub fuqiang/feishu-deck-h5 --plugin feishu-deck-h5How this skill is triggered — by the user, by Claude, or both
Slash command
/feishu-deck-h5:pptx-to-editable-htmlThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> # ⚠️ DEPRECATED / 已退役 — 图片(双背景)路线
references/architecture.mdreferences/backend-persistence.mdreferences/image-quality.mdreferences/manifest-schema.mdreferences/qa-audit.mdreferences/translation.mdscripts/build.pyscripts/extract.pyscripts/extract_media.pyscripts/faas_store.jsscripts/faas_translate.jsscripts/keynote_export.applescriptscripts/make_i18n.pyscripts/make_manifest.pyscripts/qa_audit.jsscripts/recover_colors.pyscripts/render_pdf.swiftscripts/repair_notext_bg.pyscripts/subset_font.pyscripts/upload_to_url.shConverts .pptx files into structured, editable feishu-deck-h5 canvas deck.json via pure python-pptx reconstruction. Decorative elements are approximate; for fully text-editable web decks, not pixel-perfect copies.
Converts PDF or PPTX decks into interactive HTML decks with pixel-faithful page-image mode. Preserves slide count, palette, and typography without redesign.
Generates zero-dependency HTML slide presentations with inline CSS/JS and animations. Use for new decks from scratch, PPT/PPTX conversions, or enhancing existing HTML presentations.
Share bugs, ideas, or general feedback.
⚠️ DEPRECATED / 已退役 — 图片(双背景)路线
本技能(pptx-to-editable-html,含 manifest / 双背景图 / 截图 / 整页渲染图路线)已退役。 按用户「完全不要图」的决定,PPTX 现在统一走:
parser → build_pptx → 结构化
canvasdeck.json(代码重建、无截图)。啃不动的页(原生图表 / SmartArt / OLE)产纯文字占位 + 汇总报告页号,由用户自己重做那几页。 见
skills/feishu-deck-h5/subskills/parser/SKILL.md与skills/pptx-to-deck/assets/build_pptx.py(continuator;旧的pptx-to-html嵌套路径已提升为顶层pptx-to-deck)。代码仍保留(未删除)仅作存档参考;请勿用于新任务。build_pptx 已是 python-pptx 原生 OOXML 抽取,无需从本技能搬运任何抽取能力。
2026-06-04 归档:本目录已
git mv到skills/_deprecated/,从skills/顶层撤出, 不再作为可加载 skill。.pptx的活路径 =pptx-to-deck;.key=keynote-to-html。保留它的唯一理由 = 4 项
pptx-to-deck至今没有、且绑死在双背景架构上的「蓝图能力」, 将来要做「飞书妙搭可翻译 deck」时直接抄这里、不要重新发明:
- CJK 字体子集化 —
scripts/subset_font.py(fonttools+brotli,12MB→~200KB woff2,仅用到的字形)- 离线多语言切换 —
scripts/make_i18n.py+ OpenCC s2tw 繁体 + Larktranslation:textAPI 批处理(3 并发 + 指数退避),可在妙笔 iframe 沙箱内切换(浏览器翻译被禁时仍可用)- FaaS 跨设备共享持久化 —
scripts/faas_store.js(browser↔TOS,绕过 html-box 沙箱禁 localStorage)- 浏览器「网页翻译」模式 —
body.xl可见真文字层 +--fit/--gfit防溢出,专为妙搭顶层渲染这 4 项不可直接移植进 deck.json 模型(需重写),所以归档保留作蓝图,而非搬进 build_pptx。
网页翻译版:在「双背景可编辑」基础上加了一套可见真文字层 + 浏览器翻译模式, 专为发布到飞书妙搭(顶层渲染、能用浏览器/豆包「翻译此页」)而做。详见文末 「部署到妙搭」与「网页翻译版要点」。
给一个 .pptx,产出一个自包含 HTML:看起来和 PPT 一模一样(浏览模式是原始
渲染图),但按 E 就能逐框编辑文字。编辑改动可保存到浏览器、导出成新 HTML。
为什么这样设计:纯结构化重建(把每个文字框用 HTML 重画)永远会在字体、对齐、 自动缩放、自定义形状上失真。双背景架构把"保真"和"可编辑"解耦——浏览永远是 真渲染图,结构化文字层只在编辑时出现,改过的框用无文字底图裁片遮住原文字。
pip install python-pptx)— 解析 pptx 文字结构render_pdf.swift)pip install fonttools brotli)— 字体子集化(可选但强烈推荐)pip install Pillow,可选)— 文字色恢复 / 无文字底图修复(recover_colors.py / repair_notext_bg.py)pip install opencc-python-reimplemented,可选)— 生成繁體译文(make_i18n.py)设 D=deck.pptx,工作目录 W=./work,图床 HOST=https://your-host/deck。
python3 scripts/extract.py "$D" --out "$W"
# → W/texts.json(每页文字框:位置/段落字号/颜色/对齐/内边距/垂直锚点)
# → W/text-stripped.pptx(清空所有文字、保留全部装饰)
占位符标题字号常继承自母版(python-pptx 读不到),若有上一版/keynote 抽的
字号数据可 --fill-sizes prior.json 按文字匹配补全。
# 含文字原图(浏览模式用)
osascript scripts/keynote_export.applescript "$PWD/$D" /tmp/withtext.pdf
swift scripts/render_pdf.swift /tmp/withtext.pdf "$W/bg" 1920
# 无文字底图(编辑模式用)
osascript scripts/keynote_export.applescript "$PWD/$W/text-stripped.pptx" /tmp/notext.pdf
swift scripts/render_pdf.swift /tmp/notext.pdf "$W/notext" 1920
# 体积优化:PNG→JPEG(照片页效果好、加载快)
for f in "$W"/bg/*.png; do sips -s format jpeg -s formatOptions 88 "$f" --out "${f%.png}.jpg" >/dev/null; done
for f in "$W"/notext/*.png; do sips -s format jpeg -s formatOptions 88 "$f" --out "${f%.png}.jpg" >/dev/null; done
python3 scripts/subset_font.py /path/to/Font-Regular.otf "$W/texts.json" "$W/font/reg.woff2"
python3 scripts/subset_font.py /path/to/Font-Bold.otf "$W/texts.json" "$W/font/bold.woff2"
python3 scripts/extract_media.py "$D" --out "$W/media"
# → W/media/files/*, W/media/media-raw.json(含音轨判定的 gif 标记)
# 上传 files/ 后把每条的 "file" 改成 "url",存成 media.json
把 W/bg、W/notext、W/font、W/media/files 传到 HOST 对应路径。
(scripts/upload_to_url.sh 是 TOS 预签名 PUT 的示例,按你的图床改。)
python3 scripts/make_manifest.py "$W/texts.json" --out "$W/manifest.json" \
--img-base "$HOST" \
--bg-pattern 'bg/page-{n:03d}.jpg' --notext-pattern 'notext/page-{n:03d}.jpg' \
--title '我的演示' \
--font-base "$HOST/font" --font-reg reg.woff2 --font-bold bold.woff2 \
--media "$W/media.json" # 可选;--skip 58,60 可删页
python3 scripts/build.py "$W/manifest.json" --out "$W/index.html"
index.html 即成品:本地双击即可用,或部署到任意静态托管 / 妙笔 html-box。
都在 scripts/,各自的「为什么 / 怎么用」详见对应 reference:
1920 改成 2880/3840 重渲 bg 与 notext(两张必须同 width),再 JPEG q88、manifest 指向高清图。见 references/image-quality.md。python3 scripts/recover_colors.py "$W/manifest.json" --out "$W/manifest-colored.json"(python-pptx 抽不到主题色 → null → 白;从 bg/notext 差分反推真实色。在 make_manifest 之后、build 之前跑)。python3 scripts/repair_notext_bg.py "$W/manifest.json"(diff 标记受损页并重建;首选其实是从只剥文字的源重渲,见 image-quality.md)。python3 scripts/make_i18n.py "$W/manifest.json" --out "$W/i18n.json" [--faas-url <faas_translate.js 部署后的 URL>] 生成 {源文:{h,e,j}},再 build.py … --i18n "$W/i18n.json"。三条翻译路径与 --native-text/--xl-default 见 references/translation.md。make_manifest.py --dim '58:0'(第 58 页第 0 个文本框为高亮金句,整页其余文字压暗)。node scripts/qa_audit.js --url "file://$PWD/$W/index.html" --pages 1-99 --out "$W/qa"(CDP 多页截图,截图结论需再核验)。见 references/qa-audit.md。默认改动存浏览器 localStorage(仅本机本浏览器;且妙笔 html-box 的沙箱 iframe 禁用 localStorage,发布后存不住)。要让「改了即存、关了再开还在、发链接给别人 对方看到最新版、还能继续改同一份」,挂一个 FaaS 存储后端(中转 TOS):
# 1) 部署存储函数(用 publish-magic-faas skill,或直接 POST /api/faas)
node <publish-magic-faas>/publish.mjs --token "$MAGIC_TOKEN" \
--file scripts/faas_store.js --name deck_store
# → 拿到 record id,调用地址 = https://magic.solutionsuite.cn/api/faas/<id>
# 2) 生成 HTML 时带上 --faas(也可在 make_manifest 时 --faas 烤进 manifest)
python3 scripts/build.py "$W/manifest.json" --out "$W/index.html" \
--faas "https://magic.solutionsuite.cn/api/faas/<id>"
带了 --faas:浏览器加载时从 FaaS 拉取共享状态,编辑自动保存(防丢)、💾 保存即
写回服务端。不带 --faas:退回 localStorage + 导出 HTML 的本机模式(原行为不变)。
原理与 CORS 细节见 references/backend-persistence.md。
F 全屏#proj(或 #bare/#clean/#kiosk)→ 隐藏底部工具栏(含页码栏),投屏/--app 放映时只剩正文(翻页用方向键)。配 Chrome --app="<url>#proj" --start-fullscreen 即得无浏览器外壳 + 无工具栏的纯幻灯片--i18n 烤进的译文离线、即时、沙箱 iframe(妙笔)里也能切,人人看到同一份。选了内置语言会给 deck 打 translate="no",挡掉浏览器二次翻译。仅在 --i18n 构建时出现。--faas 时写回服务端(所有人可见最新版、跨设备防丢),否则存本浏览器 localStorage(本版无独立保存/导出按钮)妙搭是顶层渲染(不像妙笔 html-box 那样再套 sandbox iframe),所以浏览器「翻译此页」
/ 豆包划词能直接翻整页——这是「网页翻译版」的关键落点。用 lark-apps skill 的 lark-cli 发布:
# 入口文件必须叫 index.html;--path 必须是 cwd 内相对路径
# 首次需飞书授权一次:lark-cli auth login --domain apps(scope 含 spark:app:publish/write)
lark-cli apps +create --name "我的演示" --app-type HTML # 首次:建应用拿 app_xxx
cd <部署目录的父目录> \
&& lark-cli apps +html-publish --app-id app_xxx --path ./<部署目录> --as user
# 返回 {"ok":true,"data":{"url":"https://bytedance.aiforce.cloud/app/app_xxx"}}
--app-id 重发 = 原地更新同一链接,URL 不变(发前先备份 index.html,发错可回滚重发)。accounts.feishu.cn),但
lark-cli 用授权过的 user token 发布不受墙影响——Agent 能发;发完只能靠人在浏览器硬刷新眼检。--i18n 烤进的译文,离线/即时/沙箱 iframe 也能切,原版/繁體/English/日本語,人人看到同一份)是主路径——发妙笔(沙箱 iframe)时浏览器翻译失效,内置是唯一选择;选了内置语言会给 deck 打 translate="no" 防浏览器二次翻译。② 浏览器翻译仅作辅助:切回「原版」后,在顶层环境(妙搭/本地/Pages)可翻长尾小语种,质量取决于观众浏览器、不保存、各看各的。内置译文由 make_i18n.py 生成(OpenCC 繁體 + faas_translate.js 飞书翻译批译),详见 references/translation.md。body.xl;平时显原图(.bg),
xl 态切到无字底图(.bg-notext) + 重建真文字供整页翻译。浏览态靠
body:not(.edit):not(.xl) .tb:not(.dirty):not(.tb-title) .ln{color:transparent} 把重建
文字藏起(只露原图);.tb-title 例外(标题两态都显重建文字、靠 .tb 的 --nt 裁片背景盖原图,无重影)。.ln 字号 = calc(cqw(size) * var(--fit,1) * var(--gfit,1));__deckFit
对非 .tb-title 框测溢出降 --fit(floor 0.65);--gfit 是底栏 A+/A- 全局字号。标题
(.tb-title) 被排除——长标题在重建字体(PingFang 比原字宽)下会换行,需手工调小该框 size 或加宽 width。bg/bg-notext 用 data-src,loadSlideImgs(当前±相邻) 才真加载,防首屏一次性拉全图黑屏。paras 只有单一 color/size,装不下段内
混排强调。要给「122+」这类局部上色/加大,直接往成品 HTML 的 .ln 注
<span style="color:#XX;font-weight:700;font-size:1.3em">…</span>——innerHTML 模型支持、
浏览态被 .ln *{transparent} 一并藏起、只在 xl/编辑态显、无重影;build.py 走 H.escape
不支持,故此法是部署 HTML 级补丁(改完重新 +html-publish)。references/architecture.md — 双背景、三态(高保真/翻译/编辑)、box 编辑、autofit、懒加载、持久化references/manifest-schema.md — manifest 字段(含 dimothers/over、i18n 说明)references/translation.md — 三条翻译路径、--i18n/--native-text/--xl-default、FaaS 与 make_i18n.pyreferences/image-quality.md — 高清重渲(锐化)、recover_colors.py、repair_notext_bg.pyreferences/qa-audit.md — qa_audit.js 发布前多页截图体检references/backend-persistence.md — --faas 共享后端原理与 CORS