Skip to content

Releases: cnkids/dsh-office-toolkit

v0.3.24

Choose a tag to compare

@github-actions github-actions released this 12 Sep 15:54

Full Changelog: v0.3.23...v0.3.24

v0.3.23

Choose a tag to compare

@github-actions github-actions released this 12 Sep 15:50

Full Changelog: v0.3.22...v0.3.23

v0.3.22 — 精简更新说明

Choose a tag to compare

@cnkids cnkids released this 12 Sep 15:05

更新方式(重要)

更新请用带版本号的直链

dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/download/v0.3.22/dsh-office-toolkit-0.3.22.tgz

releases/latest/download/... 的内容会随发版变化,pnpm 可能复用缓存不刷新(pnpm < 11.10 尤其明显)。若要用它,请先确认 pnpm -v ≥ 11.10;拉不到新版时也可以直接下 -offline.zip 解压后用 link: 安装。

装完确认版本:DSH 启动日志里的 [dsh-office-toolkit] v0.3.22 …,或 profile 里那份 package.jsonversion

本次改动(纯文档)

  • README「更新」只保留结论与命令,删掉排查过程叙述
  • docs/usage.md 删掉与 README 重复的小节
  • docs/changelog.md 近期条目压成一行一条

无代码变更;112 项测试全过;离线包三道门禁通过。

v0.3.21 — 更新装不到新版的根因与彻底解法

Choose a tag to compare

@cnkids cnkids released this 12 Sep 15:02

更新方式

更新请用带版本号的直链;releases/latest/download/... 的内容会随发版变化,pnpm 可能复用缓存不刷新(pnpm < 11.10 尤其明显)。装完可用启动日志或 profile 里 package.jsonversion 确认。

详见 README「安装 / 更新」。

本次为纯文档改动,无代码变更。

v0.3.20 — 主部件按包关系解析 · 版本号进日志 · 修正更新指引

Choose a tag to compare

@cnkids cnkids released this 12 Sep 14:29

先说结论:你机器上装的是 0.3.7,不是最新版

reused 174, downloaded 0 就是证据 —— pnpm 按 URL 复用了本地缓存,没有真正下载。releases/latest/download/... 这个地址永远不变,所以 pnpm 认为「还是同一份」,命令显示成功、版本却没变。这台机器从来没拿到过任何读取修复,这才是同一份文件一直报 Could not find main document part 的原因。

立刻可用(带版本号的直链,URL 每次发版都不同,不会被缓存复用)

dsh plugin --profile web remove dsh-office-toolkit
dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/download/v0.3.20/dsh-office-toolkit-0.3.20.tgz

装完务必确认版本(这次新增了启动日志,一眼可见):

(Get-Content "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-office-toolkit\package.json" | ConvertFrom-Json).version
# 或看 dsh web 启动日志:[dsh-office-toolkit] v0.3.20 已注册 6 个 Office 工具

这一版的内容

1. 主文档部件按「包关系」解析

以前只按规范名 word/document.xml 找主部件。现在与真正的 OOXML 读取器一致:先读 _rels/.rels 里的 officeDocument 关系拿到 Target,再退回规范名,最后退回「以 document.xml 结尾」的容忍查找。主部件放在非规范路径(如 word/main.xml)的合法文件也能读;格式嗅探同样改成关系优先(此前只看规范名,会把这类文件误判成 BAD_CONTAINER)。顺带收紧兜底:不再把 word/styles.xml 之类误当主部件。

2. 版本号进日志与报错

  • 启动日志:[dsh-office-toolkit] v0.3.20 已注册 6 个 Office 工具
  • 读取失败的诊断:插件版本 + zip 条目数 + 主部件路径 + 修正条目数
  • 无法识别的容器:列出实际条目名 + 插件版本

以后再出问题,把报错原文发来就能直接定位(也能立刻看出跑的是哪一版)。

3. 修正文档里错误的更新指引

README 的「更新」已重写:说清 latest 直链的缓存陷阱,推荐带版本号的直链,并给出确认版本的命令;FAQ 增补「更新后版本没变 / reused … downloaded 0」条目。发版步骤也补了「带版本号的资产才是可靠更新通道」。

质量

112 项测试全过(新增:主部件按关系解析、非规范路径端到端读取、损坏容器诊断);npm audit 0 条;Sonar 0 缺陷 / 0 漏洞 / 0 代码异味 / 0 安全热点,质量门通过(Sonar 服务端本次多次 TLS 握手失败,重试 5 次后成功);离线包三道门禁全部通过。

v0.3.19 — 非标准 zip:条目名与引用一起改 + 读不出时兜底

Choose a tag to compare

@cnkids cnkids released this 12 Sep 14:06

安装 / 更新(建议更新:这次针对的正是「读不出来」)

dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/latest/download/dsh-office-toolkit.tgz

重跑这一条就是更新。装完重启 dsh web 并新建会话。

为什么 0.3.17 / 0.3.18 还是读不出来

0.3.17 只把 zip 条目名改成规范写法,没有同步改引用它的部件。当文件里 _rels/.rels[Content_Types].xml 的 Target 也写成反斜杠(或不同大小写)时,改名后两边反而对不上,于是照样报:

Could not find main document part. Are you sure this is a valid .docx file?

这一版的做法

lib/core/ooxml.js 重写

  • 条目名原地按字节改名:直接改中央目录与本地文件头的名字字段,不解压任何条目。反斜杠→斜杠、大小写归一化都不改变名字字节长度,正好适用;顺带避免了大文件重新压缩的开销。
  • 同步改写引用部件[Content_Types].xml 与各 *.rels(共 4 个已知小部件),大小写不敏感匹配,覆盖 /pathpath\path/path 四种写法。
  • 名字长度会变的少见情形(如 word//document.xml)不做字节改写,交给读取侧的容忍查找。

lib/core/word.js 解析兜底:mammoth 认不出(找不到主文档部件 / 没有 body)时,用内置解析器word/document.xml 取正文,并在 meta.reader 里标明用了哪种读法 —— 保证「能开 zip 就读得出字」,而不是整条读取失败。

验证:四种真实写法全部读通

变体 结果
条目 + rels 均为反斜杠 ✅ 自动修正 17 处
条目反斜杠 + rels 正斜杠 ✅ 自动修正 17 处
条目 + rels 均为大写(Word/ ✅ 自动修正 9 处
大小写 + 反斜杠混合

这四种都进了回归测试(含此前失败的两种)。

顺带

Sonar 报了一个新安全热点,查出来是测试里用 Math.random() 生成临时文件名(S2245),已改为确定性编号;顺手修掉 S3776 / S6557。现在 security_hotspots = 0

质量

109 项测试全过(核心 57 · 跨平台 16 · 插件 36);npm audit 0 条;Sonar 0 缺陷 / 0 漏洞 / 0 代码异味 / 0 安全热点,质量门通过;离线包三道门禁(依赖自包含 145 处 / 112 包、核心自测、插件冒烟)全部通过。

v0.3.18 — 热修:读取非标准文件不再崩

Choose a tag to compare

@cnkids cnkids released this 12 Sep 13:49

安装 / 更新(这是一次热修,建议尽快更新)

dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/latest/download/dsh-office-toolkit.tgz

重跑这一条就是更新。装完重启 dsh web 并新建会话。

修 0.3.17 引入的回归

实测报错:

Error: Cannot add property containerNote, object is not extensible

0.3.17 为了在读取结果里提示「已自动修正 N 个非标准 zip 条目名」,直接往调用方的参数对象上写了一个属性 —— 而 DSH 宿主传入的参数是冻结的,赋值即抛。

最讽刺的是它的触发条件:只有需要修复的非标准文件才会加这条提示,所以普通文件一切正常,而反斜杠 zip、改过后缀的文件 100% 直接崩 —— 恰好是 0.3.17 想帮的那一类。

修法:需要加注时新建对象({ ...opts, containerNote }),不再改动调用方参数。全库审计确认这是唯一一处改写调用方参数(io 均为新建对象,ops / data 从未被改写)。

把这个 bug 类别钉死在 CI 里

  • 契约测试:8 条调用(含带注的非标准 zip、withFormatting)全部用 Object.freeze 传参,必须正常执行;并断言调用方参数未被改写
  • 假宿主改为冻结参数plugin-smoke 现在像真实宿主一样冻结每次工具调用的参数对象,26 项冒烟(所有工具 × 各种参数组合)都在冻结条件下跑。

也就是说,以后任何「往宿主参数上写属性」的改法都会在测试里立刻失败。

质量

107 项测试全过(核心 55 · 跨平台 16 · 插件 36);npm audit 0 条;Sonar 0 缺陷 / 0 漏洞 / 0 代码异味 / 0 安全热点,质量门通过;离线包三道门禁(依赖自包含 145 处 / 112 包、核心自测、插件冒烟)全部通过。

v0.3.17 — 保证 Word/Excel 都能正常读取

Choose a tag to compare

@cnkids cnkids released this 12 Sep 13:38

安装 / 更新

dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/latest/download/dsh-office-toolkit.tgz

重跑这一条就是更新。装完重启 dsh web 并新建会话。

这一版只做一件事:保证文件真的读得出来

修掉了那个「读不出来」的真因

有一类 Word 文件的 zip 条目名用的是反斜杠(word\document.xml)—— 部分国产工具、或在 Windows 上手工重打包过的文件会这样。mammoth / ExcelJS 按 word/document.xml 去找,找不到就报:

Could not find main document part. Are you sure this is a valid .docx file?

现在读取前会自动修正条目名,并在结果里提示修正了几个。此问题已在本机复现并加入回归测试。

不只信扩展名,按文件真实内容判断

文件的样子 现在的行为
zip 条目名带反斜杠 自动修正后正常读取
后缀 .doc,内容其实是 .docx 按 docx 读,并提示「文件内容其实是 .docx」
后缀 .docx,内容其实是老的 OLE .doc 按老格式读,不再报「docx 无法解压」
后缀 .xlsx,内容其实是 CSV / TSV 文本 按分隔符文本读,并提示实际格式
zip 里没有 Office 主文档 BAD_CONTAINER,并列出实际条目名,便于判断文件真身

错误语义保持不变:文件不存在 → NOT_FOUND,传入目录 → NOT_A_FILE,不支持的后缀 → UNSUPPORTED_FORMAT

顺带修一个真 bug

0.3.16 引入的默认样式解析有错:attrOf 对「属性不存在」和「属性为空」都返回空串,导致每个样式都被当成 w:default="1",所有段落都套用了最后一个样式(字体字号因此全错)。改用 attrIn 区分「不存在」后,默认样式与主题字体解析正确。

验证

  • 真实文件普查:桌面 / 文档 / 下载 / 项目里共 26 个 Word 文件,全部读取成功;21 个 .docx 的格式提取 21/21 通过。
  • 新增 4 项兼容性测试(反斜杠条目名、改后缀的 docx / CSV / TSV、OLE 伪装、损坏 zip)。
  • 测试 106 项全过;npm audit 0 条;Sonar 0 缺陷 / 0 漏洞 / 0 代码异味 / 0 安全热点,质量门通过;离线包三道门禁(依赖自包含 145 处 / 112 包、核心自测、插件冒烟)全部通过。

说明

上一轮试做的「公文规则检查」工具已按反馈移除 —— 规则不写进插件。office_readwithFormatting 保留:它只负责把字体、字号、行距、首行缩进、对齐、页面页边距读出来,规则怎么判由你自己决定。

v0.3.16 — 读出 Word 排版格式(字体/字号/行距/缩进)

Choose a tag to compare

@cnkids cnkids released this 12 Sep 13:09

安装 / 更新

dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/latest/download/dsh-office-toolkit.tgz

重跑这一条就是更新。装完重启 dsh web 并新建会话。

新能力:读出 Word 的排版格式

office_read.docxwithFormatting: true,正文之后会附一份格式报告,结构化数据在 meta.formatting。用于把文档与行文规则逐条比对(例如「正文三号仿宋、行距固定值 28.8 磅、首行缩进 2 字符」)。

{ "path": "通知.docx", "withFormatting": true }

每段给出:中/西文字体、字号、行距、首行缩进、悬挂缩进、左缩进、对齐、样式名、是否在表格内;另有纸张尺寸与页边距文档默认字体/字号/行距,以及两份便于比对的汇总:

  • 格式分布 —— 字体 / 字号 / 行距 / 缩进 / 对齐各自的出现次数,主流值即比对基准
  • 偏离主流格式的段落 —— 逐条列出,直接定位不合规处

取值按 Word 的真实优先级合并:docDefaults隐式默认样式w:default="1",Word 会套到没写 w:pStyle 的段落上)→ basedOn 样式链 → 段落直接格式(w:ind / w:spacing / w:jc)→ run 级覆盖(取覆盖文字最多的 run)。主题字体也会解析:Word 默认模板用 w:eastAsiaTheme="minorEastAsia" 这类引用而不是字体名,插件会读 word/theme/theme1.xml 并按 <a:font script="Hans"> 取出中文实际字体。

真实文件验证

文件 读出结果
附件1:公文格式规范说明.docx 仿宋_GB2312 ×24、黑体 ×6、方正小标宋简体 ×1;字号 16pt(三号) ×30、22pt ×1;页边距 上35/下35/左28/右25 mm
市场调查技术试卷.docx 修复前 75 段读不出字体(主题字体未解析),现在正确读出 宋体 ×75、黑体 ×5,12pt ×79
中级经济基础口诀(56条).docx 284 段、微软雅黑 ×247,页面 210×280 mm

限制:格式提取目前只支持 .docx.doc / .rtf / .odt 会返回一行提示)。

顺带

按 SonarQube 规则重构了新增模块(拆开超复杂度函数、消除嵌套模板字面量与连续 push);并把文本尾部 trim 从回溯正则 /\s+$/u 改为线性扫描 —— 后者正是本次新出现的那个安全热点,与项目一贯的「不用回溯正则」保持一致。

质量

102 项测试全过(核心 50 · 跨平台 16 · 插件 36);npm audit 0 条;Sonar 0 缺陷 / 0 漏洞 / 0 代码异味 / 0 安全热点,新代码覆盖率 91.3%,质量门通过。离线包三道上线门禁(依赖自包含 145 处 / 112 包、核心自测、插件冒烟)全部通过。

v0.3.15 — 离线包验过完整 · 缺依赖报错说人话

Choose a tag to compare

@cnkids cnkids released this 12 Sep 12:27

安装 / 更新

dsh plugin --profile web add https://github.com/cnkids/dsh-office-toolkit/releases/latest/download/dsh-office-toolkit.tgz

重跑这一条就是更新。装完重启 dsh web 并新建会话。

离线包这次是「验过」的

离线安装要开箱即用,就必须自带完整且自包含的依赖 —— 不能靠 profile 目录兜底,否则到了别人机器上就是运行时缺包。本版新增发布门禁 test/offline-check.mjs,在隔离目录里逐包核对:本包声明的每个依赖、以及包内每个依赖包声明的依赖,都必须解析到包目录以内;同时要求依赖树里没有任何安装脚本。

本版 -offline.zip 的实测结果:

门禁 结果
依赖完整性(隔离目录、禁止借用外部目录) 145 处依赖 / 112 个包 全部落在包内
依赖树安装脚本 0 个dsh plugin add 不会被 pnpm 构建脚本审批打断)
核心自测 47/47
插件层冒烟(真实读写每个工具) 36/36

npm run verify:offline 已写入发版流程,任一条不过就不发版。

依赖装不全时不再「猜」

起因:profile 里依赖只装了一半时,插件抛的是原始 ERR_MODULE_NOT_FOUND,智能体看不懂就自己退化成写文本 —— 于是「创建的 Excel」变成了 TSV 内容。现在:

  • 重依赖改为懒加载:插件本身始终能加载,只有真正用到该模块的工具会失败,其它工具照常可用。已实测:只缺 docx 时读 .xlsx 正常,只缺 @wekanteam/exceljs 时读 .docx 正常。
  • 报错点名缺少依赖 @wekanteam/exceljs(用于:读写 .xlsx)。依赖安装不完整,请重跑下面这条命令补全,然后重启 dsh web: …,并保留原始报错。
  • 加载即自检:缺哪个包直接写进 DSH 日志,不用等用户撞上。

二进制输出自检

写入 .xlsx / .docx / .odt 时校验输出必须是真正的 OOXML(PK 头),否则中止并报 BAD_OUTPUT_FORMAT —— 插件不再可能留下「扩展名是 Office、内容却是文本」的假文件。

顺带修复

  • .tsv 转换此前误用逗号分隔(SheetJS 没有 tsv bookType,改为 csv + FS: '\t')。
  • 同格式复制的分支引用了未定义变量。

质量

99 项测试全过(核心 47 · 跨平台 16 · 插件 36);npm audit 0 条;Sonar 0 缺陷 / 0 漏洞 / 0 代码异味 / 0 安全热点,质量门通过。