← 返回列表
未验证
在 DSH Web 界面的 better-sidebar 侧边栏里直接打开并编辑 .docx 文件 —— 由…
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/1 · 已提供中文文档
DSH Web 插件:通过 SuperDoc 在 better-sidebar 中打开并编辑 .docx —— 自托管、支持离线、原子保存
综合分
28.2
GitHub 分
28.2
用户评分
—
★ Stars
0
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/chendefine/dsh-sidebar-superdoc-docx.git数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-sidebar-superdoc-docx
在 DSH Web 界面的 better-sidebar 侧边栏里直接打开并编辑 .docx 文件 —— 由 SuperDoc 驱动的浏览器原生 DOCX 编辑器,直接读写真实 OOXML,无需任何服务端文档服务。
依赖:本插件向 dsh-better-sidebar(>= 0.13.0)注册文件查看器,它是必选 peer 依赖 —— 不安装它,查看器不会出现。请先(或一并)安装。
⚠️ 许可:本插件自身代码为 MIT,但运行时集成了 AGPL-3.0 的 superdoc 与专有许可的 @superdoc/docx-engine,安装即表示接受相应条款。详见文末许可证与 THIRD-PARTY-NOTICES.md。
功能简介
- 浏览器原生 DOCX 编辑 —— 在侧边栏里查看、编辑 .docx,支持批注与修订痕迹(tracked changes),三种打开模式可在设置页切换:编辑 / 修订 / 查看。
- 保存写回磁盘 —— 「保存」按钮把编辑后的文档导出为 DOCX,经专用路由原子覆盖原文件(临时文件 + rename),不会产生半写状态;未保存修改以 ● 圆点提示。
- 跟随外部修改 —— 每 3 秒轮询磁盘:编辑器干净时自动原地换入新版本(replaceFile);有未保存修改时只显示提示条并提供手动「重新加载」,绝不静默丢弃你的编辑。
- 完全自托管、可离线 —— SuperDoc 编辑器构建与 DOCX 引擎(含其 web worker)从本包 node_modules 经同源路由下发:无 CDN 流量、无第三方文档服务、默认关闭遥测。pnpm install 之后全程可离线。
- 下载兜底 —— 所有界面(包括全部错误态)都保留普通下载链接。
- 侧栏自适应 —— 工具栏随面板宽度折叠进「…」溢出菜单,页面按面板宽度自动缩放(fit-to-pane),亮 / 暗主题均可读。
适用场景
- 人机协同编辑同一份 Word 文档:AI 代理在会话里改了 .docx,你在侧栏几秒内看到新版并继续人工润色;保存后 AI 的下一轮编辑又基于最新版本 —— 双向往返不打断。
- 内网 / 离线 / 合规环境:不允许出网到 jsdelivr 等 CDN,或不允许接入 SaaS 文档服务的部署;所有资产同源自托管。
- 不想为编辑 Word 部署服务端:相比 OnlyOffice / Collabora 需要单独的 Document Server,本插件零服务依赖,装上即用。
- 文档评审流程:以「修订」模式打开,批注与建议以修订痕迹记录,适合审阅-回评的协作。
- 快速预览:替代内置的代码 / 下载查看器,侧栏点击 .docx 即见排版后的文档,随时可另存下载。
如何安装
前提
- Node.js >= 20;
- DSH Web 界面及其 web profile;
- 同一 profile 内已安装 dsh-better-sidebar >= 0.13.0(见顶部依赖说明)。
从 npm 安装(推荐)
包已发布到 npmjs,包名 dsh-sidebar-superdoc-docx:
dsh plugin --profile web add dsh-better-sidebar dsh-sidebar-superdoc-docx
或手工编辑 profile 的 package.json(如 ~/.dsh/profiles/web/package.json),加入两个 npm
依赖与 bundle 条目,然后在 profile 目录执行 pnpm install:
{
"dependencies": {
"dsh-better-sidebar": ">=0.13.0",
"dsh-sidebar-superdoc-docx": "^0.1.0"
},
"dsh": { "profile": { "bundles": ["…", "dsh-better-sidebar", "dsh-sidebar-superdoc-docx"] } }
}
最后重启 dsh web(host 半需重新加载),浏览器硬刷新(Ctrl/Cmd+Shift+R)。
从 GitHub 源码安装(开发用)
dsh plugin --profile web add github:chendefine/dsh-sidebar-superdoc-docx
本地开发:克隆、构建、link:
git clone https://github.com/chendefine/dsh-sidebar-superdoc-docx
cd dsh-sidebar-superdoc-docx
pnpm install
pnpm build # → lib/index.js + lib/client.js + lib/types
然后在 profile 的 package.json 里把依赖指向克隆目录,并在 profile 目录执行 pnpm install:
{
"dependencies": {
"dsh-sidebar-superdoc-docx": "link:/绝对路径/dsh-sidebar-superdoc-docx"
}
}
插件配置(profile 的 cordis.patch.yml)
- id: dsh-sidebar-superdoc-docx
config:
fileLimitMb: 100 # 保存路由的大小上限(MB),默认 100
allowOutsideWorkspace: false # 允许保存解析后会话工作目录之外的文件,默认 false
如何使用
打开文档
侧栏文件树点击任意 .docx —— 将以 DOCX(SuperDoc 编辑) 查看器打开(而不是内置的代码 / 下载查看器)。
切换打开模式
设置 → 侧边卡片 → 文件预览 → DOCX(SuperDoc 编辑) 的齿轮里,把「打开模式」设为 编辑 / 修订 / 查看。选择持久化在 pluginSettings['superdoc:docx'].mode,切换后编辑器以新模式重新挂载,即时生效;「查看」模式同时隐藏保存按钮。
编辑与保存
- 顶部工具栏为 SuperDoc 原生工具栏(加粗、列表、批注等),随面板宽度自动折叠;
- 修改后标题行出现 ● 有未保存修改,点击 保存 导出并原子写回原路径;
- 状态机:保存中… → 已保存 / 保存失败(失败会带原因,可重试);保存进行中再做的编辑会继续保持「未保存」提示,可再次保存。
跟随外部修改(例如 AI 代理编辑了该文件)
- 编辑器干净时:3 秒轮询发现磁盘变化 → 自动重新拉取并以 replaceFile 原地换到新版本,并重新适配缩放;
- 编辑器有未保存修改时:仅显示「文件已在磁盘上被修改」提示条,由你决定是否点「重新加载」(重载会丢弃当前未保存编辑)。
与其他查看器共存
| 查看器 | id | priority |
|---|---|---|
| 内置代码查看器 | code | -100 |
| 内置下载查看器 | binary-download | -50 |
| office 预览插件 | docx | 0 |
| OnlyOffice 插件 | onlyoffice:docx | 10 |
| 本插件 | superdoc:docx | 10 |
同优先级(如与 OnlyOffice)按注册顺序取胜。每个查看器都可在「设置 → 侧边卡片 → 文件预览」单独停用,互不影响。
技术架构
双端架构
浏览器(client 半,极小 CJS bundle,经 window.__ModuleLoader__ 注册)
└─ ctx.betterSidebar.registerFileViewer('superdoc:docx', exts:['docx'], priority:10, fetchStrategy:'mediaUrl')
└─ SuperDocView: (暴露全局 SuperDoc)
读:fetch(/sidebar/file?sessionId=&path=) → Blob → new SuperDoc({ document: blob, contained: true })
存:superdoc.export({triggerDownload:false}) → Blob → PUT /sidebar/superdoc/save?sessionId=&path=
Node(host 半,4 条带围栏的路由)
├─ GET /sidebar/superdoc/info 版本 / 健康检查 / 缓存种子
├─ GET /sidebar/superdoc/assets/ superdoc/dist-cdn(封闭白名单)
├─ GET /sidebar/superdoc/engine/dist-cdn/ @superdoc/docx-engine/dist-cdn 镜像(引擎 + worker)
└─ PUT /sidebar/superdoc/save 原始 DOCX 字节 → 会话 cwd 内原子写回
- client 半只做三件事:注册查看器、经 better-sidebar 的 media 路由取文件字节、把 SuperDoc 实例挂进侧栏面板;
- host 半不跑任何文档逻辑,只负责同源资产下发与带围栏的保存;
- 挂载版本:superdoc@2.10.0 + @superdoc/docx-engine@0.9.0(以 package.json 依赖为准,info 路由上报实际版本并兼作缓存种子)。
为什么需要引擎镜像
client 在脚本加载前设置 globalThis.SUPERDOC_ENGINE_CDN_BASE_URL = '/sidebar/superdoc/engine',把 SuperDoc 的引擎解析指到本插件路由;引擎随后动态 import …/dist-cdn/docx-engine.es.js,其 web worker 也相对这个同源 URL 解析 —— 浏览器不允许跨源创建 worker,否则 jsdelivr 会成为运行时依赖。这正是 host 半镜像整个 dist-cdn 目录的全部理由。
安全边界
- 信任围栏(src/trust-fence.ts,与 better-sidebar 行为一致):Host 头必须是 loopback 或 webRuntime.trustedHosts 中的可信授权,sec-fetch-site: cross-site 与 Origin 不匹配一律拒绝 —— 防 DNS rebinding / 跨站请求,不是身份认证。
- 工作区围栏(src/paths.ts + 保存路由):仅接受绝对路径;isWithin 做段级包含比较(/a/bc 不算在 /a/b 内);对父目录做 realpath 封闭符号链接逃逸;仅允许 .docx;请求体超过 fileLimitMb 返回 413;写入走 tmp + rename 原子替换。
- 资产白名单(src/assets.ts):superdoc 构建只暴露 3 个文件的封闭白名单;引擎子路径做形状校验、拒绝 ./.. 段、realpath 必须落在 dist-cdn 内且为普通文件。
- 无外泄:遥测默认关闭(telemetry: { enabled: false }),插件自身不在磁盘保存任何状态。
开发细节和规范
目录结构
src/
index.ts 宿主半:构建并注册 4 条路由(buildRoutes 纯函数,便于测试)
assets.ts node_modules 资产定位 / 白名单 / realpath 包含检查 / 内容类型
config.ts 配置解析(fileLimitMb、allowOutsideWorkspace;纯 TS,零依赖)
paths.ts 绝对路径要求 + 段级包含 + symlink 安全的父目录 realpath
trust-fence.ts 浏览器信任围栏(复制而非 import 上游,插件不得依赖其内部)
wire.ts {ok,...} / {ok:false,error:{code,message}} JSON 形状 + 限长原始字节读取
client/
index.ts 客户端半:注册 superdoc:docx 查看器 + 挂载词典
SuperDocView.tsx 编辑器组件(挂载 / 保存状态机 / 磁盘轮询 / fit-to-pane 缩放)
loader.ts 运行时加载器(script/stylesheet 单例、引擎基址、contained 布局 CSS)
settings.ts 读取打开模式(带校验,回退 editing)
urls.ts /sidebar/file 与保存路由的 URL 构造(对齐 better-sidebar 请求契约)
i18n.ts / locales.ts / icons.tsx zh/en 词典、注册与图标
tests/ vitest:routes / save-flow / viewers / trust-fence / locales
构建产物
- host:lib/index.js,ESM(es2023),运行时零第三方依赖;
- client:lib/client.js —— window.__ModuleLoader__.load({ id, factory }) 注册的 CJS bundle,与 dsh-sidebar-onlyoffice、dsh-web-search-aggregation 相同的官方外置客户端投递形态;
- SuperDoc 编辑器本体不打包进 bundle:由 host 路由在运行时以经典 注入(与 onlyoffice 加载 api.js 的方式同构)。
客户端纯度门禁
tsdown.config.ts 内置 rolldown 插件,构建期直接报错:client bundle 不得 import 任何 Node 内建模块、不得值导入 @deepseek-ai/;React / react-dom / cordis 作为 external 由宿主模块表提供。浏览器半必须自包含。
代码约定
- 不 import monorepo 内部类型:宿主与客户端都定义结构化的 context faces(RouteContext、ClientContextFace),外部插件不得触达 monorepo 的 Context augmentation 图;
- 浏览器 JSON 一律 {ok:...} / {ok:false,error:{code,message}}(对齐 better-sidebar 的 wire 格式),错误码:forbidden / method-error / bad-request / not-found / fs-error / internal;
- viewer id 命名空间化(superdoc:docx),避免与内置及 onlyoffice:docx 冲突;priority 10 > 内置;fetchStrategy: 'mediaUrl';
- 词典 zh / en 的 key 集合必须完全一致(locales 测试强制),注册在插件唯一的 dshSidebarSuperdoc 命名空间;
- 所有页面级注入幂等(stylesheet、布局 CSS、editor script 均为单例,重挂载安全);
- 保存路由是唯一的 fs 写入面;better-sidebar 自带 fs.write 仅支持 UTF-8 文本,二进制导出必须走本路由。
测试
pnpm test(vitest run)覆盖:
| 文件 | 覆盖 |
|---|---|
| routes.test.ts | 4 条路由:白名单命中 / traversal 与符号链接拒绝 / 工作区围栏开与关 / 413 / 405 / 403 |
| save-flow.test.ts | 保存状态机:成功后清除未保存提示、保存中编辑保持未保存、头部按钮位置稳定 |
| viewers.test.ts | 查看器契约:id / exts / priority / fetchStrategy / 设置行,与既有 viewer 无 id 冲突 |
| trust-fence.test.ts | loopback 与可信授权通过;未知 Host / 跨站标记 / Origin 不匹配拒绝 |
| locales.test.ts | zh / en key 一致、值非空、命名空间唯一 |
常用命令
pnpm typecheck # tsc --noEmit
pnpm test # vitest run
pnpm build # host ESM + client ModuleLoader bundle(纯度门禁强制)
已知局限
- 只支持 .docx(SuperDoc 不打开旧版 .doc);
- 有未保存修改时直接关 tab 无法拦截 —— 请留意 ● 未保存圆点;
- better-sidebar 的 workspaceFence 关闭时可以打开工作区外的文件,但保存*它们仍需本插件 allowOutsideWorkspace: true;
- 字体:SuperDoc 核心不带字体,文档以系统字体渲染(如需一致排版可后续接入 @superdoc-dev/fonts,本插件未含)。
许可证
本插件代码为 MIT;整合(未修改、随 pnpm install 安装并由路由原样下发)两个 SuperDoc 组件:
| 包 | 许可证 | 说明 |
|---|---|---|
| superdoc | AGPL-3.0 | 未修改的 npm 产物;以网络服务形式提供时触发 AGPL 源码提供义务 |
| @superdoc/docx-engine | 专有许可(DOCX Engine Proprietary License) | 无商业协议时,仅可作为 SuperDoc 的依赖用于 AGPL 允许的用途(评估 / 开发 / 测试);商业使用需向 SuperDoc 购买授权 |
详见 THIRD-PARTY-NOTICES.md。
致谢
- SuperDoc by Harbour Enterprises —— 编辑器本体;
- dsh-sidebar-onlyoffice —— 本包遵循的插件形态(运行时脚本注入、信任围栏、宿主路由)。扫码进群