DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

pawpress /

pawpress/office-ppt

Verified

dsh-plugin libreoffice uno pptx deepseek-harness powerpoint presentation

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@42cfad33

office-ppt

让 DSH 直接驱动本机安装的 LibreOffice 做 PPT —— 通过 UNO 真开一份 Impress 文档、真往上画形状,再让 LibreOffice 自己导出 PPTX / ODP / PDF / 逐页 PNG。

不是纯 JS 的 PPTX 写入器:字体、表格、母版、备注页、导出过滤器全走 Impress 那条路,产物和你在桌面上「另存为」得到的是同一种东西。

npm 包名 dsh-lo-office(插件 id 同),仓库名 office-ppt,当前版本 v0.5.1。 装法只要一行:github:pawpress/office-ppt#v0.5.1 —— 详见安装。

lo_build ──▶ python/lo_bridge.py ──▶ UNO socket ──▶ Impress 文档 ──▶ storeToURL
                                                                      ├─ pptx
                                                                      ├─ odp
                                                                      ├─ pdf
                                                                      └─ png × N

English — A DeepSeek Harness plugin that builds presentations by driving the installed LibreOffice over UNO: it opens a real Impress document, draws real shapes, and lets LibreOffice export PPTX / ODP / PDF / per-slide PNG. Not a pure-JS OOXML writer — so fonts, tables, master pages, notes and the export filters are all LibreOffice's own. Five tools: lo_probe, lo_build, lo_render, lo_convert, lo_config. Requires LibreOffice (verified on 26.8.1.1); the bundled Python is used, so no system Python is needed. Ships a settings panel (paths, theme, ratio, formats, timeouts) and keeps one warm soffice process between calls. Package name dsh-lo-office, repository office-ppt. Changelog · MIT

封面

和 dsh-ppt 的区别

dsh-ppt dsh-lo-office
PPTX 由谁生成 纯 JS(@office-kit/pptx) 本机 LibreOffice / Impress
需要装 Office 吗 不需要 需要 LibreOffice
渲染预览 依赖外部渲染引擎 同一套 LibreOffice 直接出 PDF/PNG
强项 零依赖、跨平台、快 真 Impress 文档、格式保真、顺手转任意文档

两个可以并存:要开箱即用选 dsh-ppt,要「交付的就是 LibreOffice 能打开的那个文件」选这个。

要求

  • 本机装有 LibreOffice(Community 版即可)。已在 26.8.1.1 上验证;lo_probe 会告诉你实测结果。
  • 插件自己找 soffice:Windows 先查注册表 HKLM\SOFTWARE\LibreOffice\UNO\InstallPath(含 WOW6432Node),再查常见安装路径,最后看环境变量 DSH_LO_SOFFICE / LO_SOFFICE。
  • Python 用 LibreOffice 自带的那份(<安装目录>/program/python.exe,带 uno 模块),不需要系统 Python。Linux 上会退回 python3,需要 python3-uno。

安装

不需要发行版(Release)。 装插件只要 git 仓库 + 可选的 tag。

方式一:插件管理器(推荐)

在 设置 → 插件 里粘贴下面任一行,或让助手调用 plugin_manager 的 install_bundle:

github:pawpress/office-ppt            # 跟最新 main
github:pawpress/office-ppt#v0.5.1     # 锁定版本(推荐)

两种规格都实测可用(pnpm 11.8,装上版本 0.5.1)。

装完确认:

Select-String -Path "$env:APPDATA\DSH Desktop\logs\host\dsh-*.log" -Pattern 'dsh-lo-office' | Select-Object -Last 3

期望看到 已注册 5 个工具(…)、2 个斜杠命令。

Release 与 Tag 的区别:装插件只需要 Tag(给 commit 打标记)。Release 是 Tag 加更新说明和附件,纯粹给人看,安装用不到。

方式二:npm(等发布后可用)

dsh-lo-office

一行装完,有版本号和更新提示。目前还没发布到 npm。

方式三:本地开发(改代码用)

# 1) 把仓库链进 profile 的 node_modules
cmd /c mklink /J <profile>\node_modules\dsh-lo-office <仓库路径>
// 2) profile 的 package.json
{
  "dependencies": { "dsh-lo-office": "link:D:/dsh1/dsh-lo-office" },
  "dsh": { "profile": { "bundles": [ /* … */, "dsh-lo-office" ] } }
}

bundle 条目由本仓库自带的 cordis.patch.yml 注入,不需要手改 cordis.yml(它是启动时由 bundles 组合出来的生成物,手改会被覆盖):

- insert:
    - id: dsh-lo-office
      name: dsh-lo-office
      config: {}

⚠️ 改配置一律用编辑器或 [System.IO.File]::WriteAllText + UTF8Encoding($false)。PowerShell 5.1 的 Set-Content -Encoding UTF8 会写 BOM,YAML 解析会挂。

⚠️ 插件源码改动由 HMR 热重载代码,但不会刷新斜杠命令的 UI 列表 —— 那要刷新页面或重启 Desktop。

斜杠命令

在输入框敲 / 就能用的两条命令(不经过模型,不消耗 token):

命令 作用
/ppt-config 查看配置
/ppt-config theme=swiss 改一项
/ppt-config theme=swiss autoFit=off pngWidth=2000 改多项
/ppt-config formats=pptx,pdf 数组用逗号
/ppt-config footer="由 LibreOffice 生成" 带空格的值用引号
/ppt-config reset 恢复出厂
/ppt-status 探测 LibreOffice 是否可用

改动写进 profile 的 cordis.patch.yml,重启 Desktop 后生效;要当场生效可以用 lo_config 工具(见下)。

为什么不是设置页

DSH 桌面端(0.1.7)不会给第三方插件渲染设置表单:

  • dsh-settings 里写着「每个表单报告 autoGenerate…目前没有已发布的客户端这样做」
  • 侧边栏里像「演示文稿」那种条目,是 dsh-ppt 自己写 React 组件注册进 settings.section 的结果,不是自动生成
  • 插件的 Config schema 只负责装载时校验,不产出 UI

所以配置面分成两条:给用户的是斜杠命令,给模型的是 lo_config 工具。两者写的是同一份 cordis.patch.yml。

可配置项

字段 默认 说明
soffice 空(自动探测) soffice.exe 完整路径
python 空(用自带的) 带 uno 模块的 python
theme light light / dark / slate / warm / swiss
ratio 16:9 16:9 / 4:3
formats pptx,pdf,png 默认导出格式,可加 odp
pngWidth 1600 逐页 PNG 宽度(320–3840)
footer office-ppt · 由本机 LibreOffice 生成 页脚文字,空字符串=不画
pageNumbers true 是否显示页码
autoFit shrink 自动排版:shrink 缩字号 / off 不干预
minFontSize 12 自动排版最小字号(6–72)
timeoutMs 240000 单次调用超时
keepWarm true 复用常驻 soffice
idleMs 60000 常驻进程空闲回收(毫秒)

任何字段都能被单次工具调用的同名参数覆盖,配置里的值只是默认值。

自动排版

配置里的 autoFit(默认 shrink)解决「文字塞不下」这个最常见的排版事故:文案一长,字就冲出文本框盖住页脚。

做法不是估字宽——估算是排版事故的最大来源——而是让 LibreOffice 自己排一遍:把文本框的 TextAutoGrowHeight 打开、宽度固定、高度设成极小值,再读回 shape.Size.Height,就得到这段文字在给定宽度下需要多高。放不下就用二分法缩小字号重新量,直到塞进去或触到 minFontSize。

所以:

  • 文字放得下 → 一个字都不动;
  • 放不下 → 缩到刚好放下的最大字号(实测 10 行要点从 17pt 缩到 13.9pt);
  • 缩到下限还放不下 → 保持下限字号并计入 fitOverflow,返回结果里会提示「缩到下限仍放不下,请缩短文案」。

每次 lo_build 的结果里都有 autoFit / fitAdjusted / fitOverflow 三个字段,生成后的汇报也会直接告诉你调了几处、有没有溢出。

为什么不用 LibreOffice 自带的 TextFitToSize:实测 PROPORTIONAL 会把文字放大到填满文本框(小框里出现一个字占半页的巨大字形),AUTOFIT 导出成 <a:normAutofit> 后同样依赖对方渲染器。只有「自己量、自己缩」是可控的。

常驻进程

keepWarm 打开时,Node 侧会保持一个 python 桥进程 + 一个无头 soffice(lib/worker.js):

  • 请求串行排队,一次 spawn 之后连续用;
  • 空闲超过 idleMs 自动回收;
  • 进程崩了下次调用自动重起;
  • 插件卸载时(dispose)一起收掉,不留孤儿进程。

关掉它就是每次调用重开一遍 —— 排查「是不是状态没清干净」时有用。

取消

lo_build / lo_render / lo_convert / lo_probe 都接了 DSH 的 abort signal:会话里打断,Node 侧会杀掉整棵子进程树(taskkill /T /F),不会留下跑到一半的 soffice。

五个工具

lo_probe

先跑这个。返回 soffice 路径、版本、自带 Python 版本、uno 能否导入,并真的开一份无头 Impress 文档(只探测不实开是骗人的)。参数:soffice(可选,自动探测失败时指定路径)。

lo_build

给标题 + 结构化 slides,拿可编辑 PPTX(可选 ODP / PDF / 逐页 PNG)。

参数 说明
title 必填。封面与默认文件名
slides 必填。幻灯片数组,见下
theme light(默认)/ dark / slate / warm / swiss
ratio 16:9(默认)/ 4:3
footer 页脚文字,默认取设置里的页脚(出厂值 office-ppt · 由本机 LibreOffice 生成)
pageNumbers 是否显示页码,默认 true
outputDir 输出目录,缺省用会话工作目录
fileName 文件名主干,缺省取标题
formats 默认 ["pptx","pdf","png"],可用 odp
pngWidth 逐页 PNG 宽度,默认 1600
overwrite 覆盖同名旧文件,默认 true

每页字段:layout、title、subtitle、kicker(标题上方小字)、text、bullets、rows(首行为表头的二维数组)、image(绝对路径)、notes(讲者备注)。

版式:cover / section / bullets / statement / quote / table / image / image-left / image-right / closing。缺省 bullets。

{
  "title": "季度回顾",
  "theme": "swiss",
  "slides": [
    { "layout": "cover", "kicker": "Q3 REVIEW", "title": "季度回顾", "subtitle": "增长、成本与下一步" },
    { "layout": "bullets", "title": "三件事", "bullets": ["留存提升", "成本下降", "新渠道跑通"] },
    { "layout": "table", "title": "指标", "rows": [["指标", "本季"], ["留存", "72%"], ["成本", "-18%"]] },
    { "layout": "quote", "text": "把复杂留给自己。", "subtitle": "设计原则" }
  ]
}

lo_render

把已有的 PPTX / PPT / ODP 渲染成 PDF 和/或逐页 PNG —— 用来肉眼验收刚生成的东西。参数:source(必填)、formats、outputDir、pngWidth。

lo_convert

任意格式互转(docx / xlsx / pptx / odt / ods / odp / pdf …),走 soffice --convert-to。参数:source、to(必填)、outputDir。

lo_config

查看与修改本插件配置 —— DSH 桌面端不渲染第三方插件的设置表单,所以这是唯一的改配置通道。参数:action(show / set / reset)、key+value 或 changes(一次改多项)。

lo_config { action: "set", changes: { theme: "swiss", autoFit: "off" } }
→ ✅ 已更新 2 项配置
    theme: light → swiss
    autoFit: shrink → off
  磁盘 patch:D:\dsh1\.dsh\profiles\desktop\cordis.patch.yml
  已在当前进程生效。

写入是幂等的:只把和出厂默认不同的字段写进 patch,重复设同一个值不会产生改动,也不会碰其它插件条目。

样张

同一份 7 页规格(test/sample-build.json)的产物,2.4 秒生成:

封面 要点 表格
陈述 引文 小节

命令行

不经过 DSH 也能用:

node bin/lo-ppt.mjs probe
node bin/lo-ppt.mjs build test/sample-build.json --formats pptx,pdf,png
node bin/lo-ppt.mjs render test/out/sample.pptx
node bin/lo-ppt.mjs convert 报告.docx --to pdf

装成本地依赖后可以直接 lo-ppt probe(bin 字段已声明)。

测试

npm test            # 工具 schema 必须是合法 JSON Schema(不需要 LibreOffice)
npm run test:config # 设置 schema / 归一化兜底 / volatile 容器(不需要 LibreOffice)
npm run test:store  # 14 项:lo_config 的 YAML 解析 / 渲染 / 替换 / 字段校验(不需要 LibreOffice)
npm run test:config-tool # 19 项:lo_config 的 show/set/reset 契约与写盘行为(不需要 LibreOffice)
npm run test:commands # 19 项:斜杠命令的解析 / 注册 / 写盘(不需要 LibreOffice)
npm run test:json   # 返回值必须过 DSH 的 lossless-JSON 校验
npm run test:autofit # 12 项:自动排版真的缩字 / 真的不误报(需要 LibreOffice)
npm run test:smoke  # 28 项:真跑各工具、产物落盘校验

check-json.mjs 优先 import 桌面端自带的 @deepseek-ai/dsh-util-values 校验器(DSH_APP_DIR 可覆盖路径);没有桌面端的机器(CI)自动退回同规则的本地镜像。

CI 见 .github/workflows/ci.yml:三平台跑 schema 检查,Ubuntu 装真 LibreOffice 跑端到端。

性能

7 页 deck(pptx + pdf + 7 张 png)在正常机器上约 2.4–2.6 秒:连接 UNO 0.5s、排版 1.4s、导出累计 2.4s。首次跑要多花 ~10 秒建独立的 LibreOffice 配置目录,之后走缓存。

开了 keepWarm 之后第二次调用起省掉整段 soffice 启动开销 —— 实测同一进程内第二次 build 只要 0.26 秒。

本机实测到过一次异常:某个时刻起 LibreOffice 无论用什么参数、什么 profile,冷启动都卡 32 秒才建 socket(soffice.bin 的 CPU 时间从 t=2s 到 t=22s 一直冻结在 0.39s,说明在等而不是在算;默认用户 profile 也一样)。和本插件无关,是环境侧的问题。常驻进程对这种环境收益最大:第一次 33 秒,之后每次 0.26 秒。

实现里的几个坑(改代码前先看)

  • 逐页 PNG 必须切页。无头模式下 FilterData.PageNumber 会被忽略,直接循环导出会得到 N 张一模一样的图。必须 controller.setCurrentPage(pages.getByIndex(i)) 再 storeToURL。
  • private:factory/simpress 的默认页是 28000×15750,不是 16:9。建完页要逐页把 page.Width/Height 改成目标几何尺寸,否则按 33867×19050 算出来的页脚会掉到页外被裁掉。
  • Windows 路径要转 URL。storeToURL 传原生路径会报 com.sun.star.io.IOException: SfxBaseModel::impl_store … 0x81a(Error Area:Io Class:Parameter Code:26),必须 uno.systemPathToFileUrl()。
  • soffice.exe 是 GUI 子系统程序,不接管道:subprocess.run([soffice,'--version'], capture_output=True) 会挂死。用同目录的 soffice.com,并给 stdin=DEVNULL。
  • 不要用用户的默认配置目录。插件起的是独立 -env:UserInstallation,否则会抢用户正在开的 Impress,或者被用户开的实例挡住。
  • 工具返回值必须是纯 JSON。任何不可枚举的自有属性都会被 DSH 判为 value is not lossless JSON(见 lib/tools.js 里的 renderCwd WeakMap)。
  • 工具的 parameters 是原生 JSON Schema,required 必须写成字符串数组;写成 required: true 会让整个请求报 Invalid schema for function。
  • soffice.exe 的退出码不等于成功。--convert-to 失败时它照样返回 0,必须检查产物文件在不在、字节数是否非零。
  • inject 只能是数组(或「服务名→拦截配置」映射)。写成 { required: [...], optional: [...] } 会被 cordis 当成两个名叫 required/optional 的服务,插件永远卡在 pending (waiting for services),连工具都不会注册。可选服务要用 ctx.inject(['commands'], cb) 子上下文挂。
  • 常驻进程要连带杀掉整个进程树。soffice.exe 会再建一个 soffice.bin,只 kill 父进程会留下孤儿,下次启动被它挡住。Windows 上用 taskkill /T /F /PID。

已知边界

  • 切页动画:TransitionType / Duration 设置后导出 XML 里确实有 <p:transition>,但 LibreOffice 自己回读是 0 —— 导出保住,内部回读不保。
  • 图表:用 OLE2Shape 做容器导出成 graphicFrame,但空图表回读会少一个形状。要图表就喂真数据。
  • SWF 导出:26.8 没有这个过滤器,别试。
  • 备注页在 26.8 里没有 com.sun.star.presentation.NotesShape 服务名,是按「备注页上的 Text 形状」写的。
  • 只在 Windows + LibreOffice 26.8.1.1 上做过完整验证;macOS / Linux 的路径探测和 CI 已就位,但未人工目视验收。
  • 还没有 chart 版式(图表要用 OLE2Shape 喂真数据,见上),也没有「拿现成 pptx 当模板继承」的能力。

排错

  1. 先跑 lo_probe。它失败会直接告诉你缺哪一环。
  2. LibreOffice 装在非常规位置 → 设 DSH_LO_SOFFICE 指向 soffice.exe,或给 lo_probe 传 soffice 参数。
  3. 生成慢或超时 → 检查是不是有别的 soffice 实例占着 socket;插件已经随机端口 + 独立 profile,正常不会撞。
  4. 桌面端日志:%APPDATA%\DSH Desktop\logs\host\dsh-<日期>.log,搜 dsh-lo-office。

仓库信息

  • 仓库:https://github.com/pawpress/office-ppt
  • npm 包名 / 插件 id:dsh-lo-office
  • 安装规格:github:pawpress/office-ppt

克隆并推送到自己的 fork:

git clone https://github.com/pawpress/office-ppt.git
cd office-ppt
npm install          # 只为拿 @deepseek-ai/schemastery(设置 schema)
npm run test:all     # 需要本机装 LibreOffice

许可

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 42cfad3353a6

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout