pawpress/office-ppt

office-ppt

通过 UNO 驱动本机安装的 LibreOffice 做 PPT,而不是用 JavaScript 写 OOXML:`lo_build` 用结构化幻灯片真开一份 Impress 文档,再由 LibreOffice 导出可编辑的 PPTX/ODP、PDF 与逐页 PNG;`lo_render` 重新渲染已有的 PPTX/PPT/ODP;`lo_convert` 做 Office 格式互转;`lo_probe` 报告探测到的 soffice 路径、版本与 UNO 桥状态;`lo_config` 修改已保存的配置。需要本机安装 LibreOffice(已在 26.8.1.1 验证),使用其自带 Python,无需系统 Python,并会在两次调用之间保留一个 soffice 热进程。仅在 Windows 上做过完整验证;Linux 上会退回系统 python3,需要 python3-uno。

Uncategorizeddeepseek-harnesslibreofficepowerpoint

office-ppt

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

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

npm 包名 dsh-lo-office(插件 id 同),仓库名 office-ppt,当前版本 v0.2.0。
装法只要一行:github:pawpress/office-ppt#v0.2.0 —— 详见安装。
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.2.0     # 锁定版本(推荐)

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

装完确认:

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 / atelier / noir 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 导出成 `` 后同样依赖对方渲染器。只有「自己量、自己缩」是可控的。

常驻进程

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 / atelier / noir 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(绝对路径)、caption(图注,图文版式与整页图都画)、imageSide(left / right,覆盖版式默认的一侧)、notes(讲者备注)。

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

其中 editorial / kpi / index / hero 是配合 atelier / noir 的高级版式,只在高级主题下生效;基础主题下会按 bullets 渲染,并在结果里给出 warnings 提示。hero 的配图是可选的——不给 image 就用深色渐变底,不会画占位框。

kpi 的数据可以给两种写法,取前 4 组:

  • rows:两列二维数组,第一列是大数字,第二列是说明。[["42%", "效率提升"], ["3.1x", "发布频率"]]
  • bullets:每条写成 数值|标签,全角 | 和半角 | 都认。["42%|效率提升", "3.1x|发布频率"]

两种都不给时,本页只画标题,并在 warnings 里明确说明——不会安静地留一张空白页。

{
  "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 秒生成:

· · · · · ·