Docs
word-editor 文档
面向宿主业务系统的完整接入指南,覆盖 DOCX 展示与编辑、书签逻辑及视觉位置、定点内容插入、保存、导入导出、事件、类型、安全和生产发布。
快速开始
构建并导入浏览器运行时,页面中放置 <word-editor>。元素连接到 DOM 后,使用稳定的宿主接口导入 DOCX、监听状态并保存。
<word-editor id="editor" mode="edit" zoom="1"></word-editor>
<script type="module">
import "/packages/word-editor/dist/index.js";
const editor = document.querySelector("#editor");
editor.addEventListener("ready", () => console.log("ready"));
editor.addEventListener("changed", (event) => {
console.log("dirty", event.detail.dirty);
});
editor.addEventListener("error", (event) => {
console.error(event.detail.code, event.detail.message);
});
await editor.importDocument(file, { name: file.name });
editor.insertContent("由业务系统写入", { at: "cursor" });
const output = await editor.saveDocument();
</script>
源码构建或私有部署导入 /packages/word-editor/dist/index.js。本官网的授权 Cloudflare Pages 产物使用同源 /word-editor-runtime-loader.mjs;发布脚本会自动重写示例引用。
生命周期
宿主系统负责文件存储、权限、版本和并发控制;编辑器负责 DOCX 解析、呈现、编辑和序列化。生产接入应遵循同一条生命周期。
- 挂载把元素连接到 DOM,等待
ready。 - 导入调用
importDocument()或loadBlank(),等待loaded。 - 编辑通过 ribbon、
exec()、插入 API 或书签 API 修改内容。 - 跟踪监听
changed,并以editor.dirty控制保存和离开页面提示。 - 保存串行调用
saveDocument(),上传成功后再确认业务版本。 - 销毁仅在宿主真正卸载编辑器时调用
destroy()。
const editor = document.querySelector("word-editor");
let saving = false;
editor.addEventListener("changed", ({ detail }) => {
saveButton.disabled = saving || !detail.dirty;
});
async function saveToBusinessSystem(documentId, version) {
if (saving) return;
saving = true;
try {
const blob = await editor.saveDocument();
await businessApi.putDocument(documentId, blob, {
name: editor.documentName,
version,
});
} finally {
saving = false;
}
}
导入、保存与导出
稳定宿主接口使用明确的业务名称;旧的 load() 和 save() 保持兼容。
| 方法 | 输入 / 返回 | 行为 |
|---|---|---|
importDocument(input, options?) | File | Blob | ArrayBuffer | Uint8Array | 导入 DOCX,触发 loaded,重置 dirty。 |
load(input, name?) | File | Blob | ArrayBuffer | 兼容加载入口。 |
loadBlank(name?) | Promise<void> | 创建空白 DOCX。 |
saveDocument() | Promise<Blob> | 序列化为 DOCX Blob,触发 saved。 |
exportDocument() | Promise<Blob> | 导出适合下载或上传的 Blob。 |
exportDocument({ output: "array-buffer" }) | Promise<ArrayBuffer> | 导出适合二进制传输的字节。 |
save() | Promise<Blob> | 兼容保存入口。 |
const response = await fetch(`/api/documents/${documentId}`);
if (!response.ok) throw new Error(`open failed: ${response.status}`);
const blob = await response.blob();
await editor.importDocument(blob, {
name: response.headers.get("x-document-name") || "document.docx",
});
const output = await editor.exportDocument();
await fetch(`/api/documents/${documentId}`, {
method: "PUT",
headers: { "Content-Type": output.type },
body: output,
});
saved 表示编辑器已经完成序列化,不代表服务器已经持久化。宿主必须自行处理上传失败、版本冲突、重试和原文件保留。
定点插入内容
insertContent(content, options?) 是统一插入管线。当前只接收安全纯文本;不会解析 HTML,换行会转为文档换行。
editor.insertContent("替换当前选区或写入光标处");
editor.insertContent("文档前缀", { at: "document-start" });
editor.insertContent("文档后缀", { at: "document-end" });
editor.insertContent({ type: "text", text: "签署人:王宇" }, {
at: "bookmark",
bookmark: "CustomerSignature",
placement: "start",
});
at | 必填选项 | 语义 |
|---|---|---|
cursor | 无 | 替换当前选区,或在光标处插入。默认值。 |
document-start | 无 | 在正文起点插入。 |
document-end | 无 | 在正文末尾插入。 |
bookmark | bookmark,可选 placement | 在书签边界插入。 |
书签 placement 支持 before、start、end、after,默认是 start。insertText() 与 insertTextAtBookmark() 是兼容快捷方法。
方法返回 boolean。成功接受操作返回 true;只读、受保护文档、书签不存在或当前位置不可编辑时返回 false。
书签管理与位置
书签是文档内稳定锚点,支持点书签、范围书签以及导入文档中的兼容书签。查询结果同时提供逻辑位置和当前渲染位置。
listBookmarks()列出全部书签及其名称、ID、类型、文本、页码和位置。hasBookmark(name)按名称或 ID 判断书签是否存在。findBookmark(name)返回一个 WordEditorBookmarkInfo。getBookmarkPosition(name)重新计算并返回最新的起点与终点位置。gotoBookmark(name)滚动到书签并恢复其选区,成功返回 true。addBookmark(name?)从当前光标或选区创建书签,返回最终唯一名称。deleteBookmark(name)删除标记但保留被标记内容。insertTextAtBookmark(name, text)通过统一插入管线写入书签起点。const bookmark = editor.findBookmark("CustomerSignature");
const position = editor.getBookmarkPosition("CustomerSignature");
console.log({
type: bookmark?.type, // "point" | "range" | "legacy"
page: position?.start.page, // 1-based
blockIndex: position?.start.blockIndex,
offsetInBlock: position?.start.offsetInBlock,
documentOffset: position?.start.documentOffset,
pageOffset: position?.start.pageOffset,
viewportRect: position?.start.viewportRect,
});
editor.gotoBookmark("CustomerSignature");
| 字段 | 坐标系 / 单位 | 说明 |
|---|---|---|
page | 从 1 开始 | 当前分页中的页码。 |
blockIndex | 从 0 开始 | 正文块索引。 |
offsetInBlock | 从 0 开始,UTF-16 | 块内文本偏移。 |
documentOffset | 从 0 开始,UTF-16 | 正文逻辑偏移,不含页眉页脚。 |
pageOffset | CSS px | 相对当前渲染页左上角。 |
viewportRect | CSS px | 相对浏览器视口的瞬时矩形。 |
缩放、窗口尺寸、字体加载、内容编辑或重新分页后,视觉坐标可能变化。需要定位浮层或业务标注时,应重新调用 getBookmarkPosition(),不要长期缓存 pageOffset 或 viewportRect。
完整 API
Element
word-editor 是原生 Custom Element。默认包入口会自动注册,也可以从模块中手动调用 defineWordEditorElement(tagName)。
| Attribute | Values | Default | 说明 |
|---|---|---|---|
mode |
edit, view |
edit |
编辑或只读查看模式,可通过 setMode() 同步。 |
engine |
ts |
ts |
当前生产引擎为纯 TypeScript DOCX runtime。 |
zoom |
正数 | 1 |
页面缩放比例,可通过 setZoom() 更新。 |
auto-font-gateway |
boolean attribute | off | 启用后台字体网关加载,不阻塞首屏文档呈现。 |
font-gateway-url |
URL | 默认网关 | 字体 manifest 地址;当前可配置为 https://font.flyfish.group/manifest.json。 |
font-gateway-limit |
正整数 | 默认限制 | 自动加载字体数量上限,用于控制网络和内存预算。 |
license-required |
boolean attribute | off | 启用授权门禁;生产环境建议开启。 |
license-feature |
string | runtime 默认 | 授权校验使用的功能名。 |
Methods
importDocument(input, options?)从 File、Blob、ArrayBuffer 或 Uint8Array 导入 DOCX。load(input, name?)兼容文档加载入口。loadBlank(name?)创建空白文档,默认文件名为 document.docx。saveDocument()保存当前文档为 DOCX Blob,并触发 saved。exportDocument(options?)导出 Blob 或 ArrayBuffer。save()兼容保存入口。insertContent(content, options?)在光标、文档首末或书签边界插入安全纯文本。insertText(text)在当前光标或选区插入安全纯文本。listBookmarks() / findBookmark(name)列出或查询书签信息。getBookmarkPosition(name) / gotoBookmark(name)读取书签位置或导航到书签。addBookmark(name?) / deleteBookmark(name)创建或删除书签标记。exec(command, value?)执行 ribbon/API 命令,例如 bold、fontName、toggleRuler。insertTable(rows?, columns?)在当前选区插入表格。insertImage(input, options?)插入图片,支持 alt、mimeType 和最大宽度。registerFont(font)注册单个字体源。registerFonts(fonts)批量注册字体源。importFont(input, options?)导入字体文件,可写入持久字体仓库。loadFontGatewayFonts(options?)按 manifest 后台加载字体网关字体。loadRepositoryFonts(manifestUrl?, persist?, options?)从自定义字体仓库加载字体。listPersistedFonts()列出浏览器端已持久化字体。clearPersistedFonts()清理浏览器端字体缓存。setMode(mode)切换 edit 或 view。setZoom(value)设置缩放比例。reflowPages()请求重新分页和布局。getRuntimeStatus()读取运行时状态、页数、字体、dirty 状态和布局信息。destroy()销毁引擎并清空挂载点。Properties
dirty当前文档是否存在尚未序列化的修改。documentName当前文档名称;尚未加载时为 undefined。modeedit 或 view。engineKind当前为 ts。zoom当前页面缩放比例。命令
命令由 exec(command, value?) 统一执行。格式类命令会优先作用于当前选区;视图类命令会更新对应 UI 状态。
格式
bold, italic, underline, strikeThrough, fontName, fontSizePt, foreColor, hiliteColor, removeFormat, subscript, superscript
段落与页面
justifyLeft, justifyCenter, justifyRight, justifyFull, insertOrderedList, insertUnorderedList, lineSpacing, setPageSize, setMargins, setOrientation
对象
insertTable, insertShape, insertTextBox, insertWordArt, insertSmartArt, insertChart, insertEquation, insertHyperlink, insertComment
审阅与视图
toggleTrackChanges, acceptRevision, rejectRevision, updateFields, toggleRuler, toggleNavigation, togglePageEnds, toggleGridlines, toggleDarkMode
事件
| Event | detail | 用途 |
|---|---|---|
ready |
none | 编辑器引擎已挂载。 |
loaded |
{ name, engine, pageCount, fonts, persistedFonts } |
文档加载完成,可同步标题、页数和字体状态。 |
changed |
{ dirty } |
内容发生变化或保存后 dirty 状态变化。 |
saved |
{ name, blob } |
保存完成,宿主应用可上传 Blob。 |
error |
{ code, message, detail } |
授权、加载、保存或命令异常。 |
word-editor-operation |
operation commit | 编辑操作桥接事件,适合审计、协作或回放。 |
word-editor-action |
{ action, ...detail } |
宿主边界动作事件,例如共享、外部服务、插件任务。 |
word-editor-semantic-paste |
semantic paste payload | 结构化粘贴结果和操作摘要。 |
TypeScript
构建产物会生成公共声明文件。应用可直接导入元素类和所有宿主 API 类型,不需要自行维护重复接口。
import {
WordEditorElement,
type WordEditorBookmarkInfo,
type WordEditorBookmarkPosition,
type WordEditorContentInput,
type WordEditorDocumentExportOptions,
type WordEditorDocumentImportOptions,
type WordEditorDocumentInput,
type WordEditorDocumentPosition,
type WordEditorInsertContentOptions,
type WordEditorSaveResult,
} from "@word-editor/word-editor";
const editor = document.querySelector<WordEditorElement>("word-editor");
if (!editor) throw new Error("word-editor is not mounted");
const options: WordEditorInsertContentOptions = {
at: "bookmark",
bookmark: "CustomerSignature",
placement: "start",
};
editor.insertContent("已签署", options);
源码或私有包使用生成的 dist/index.d.ts。官网授权运行时是浏览器交付入口,不提供在线类型解析;项目编译时应依赖同版本私有包或声明产物。
字体网关
生产建议开启异步字体加载:先呈现文档,再在后台下载字体和触发布局刷新,避免首屏被字体阻塞。
<word-editor
auto-font-gateway
font-gateway-url="https://font.flyfish.group/manifest.json"
font-gateway-limit="32">
</word-editor>
宿主也可以直接调用 registerFont() 或 loadRepositoryFonts() 控制字体来源、授权和缓存策略。
错误、安全与授权
错误语义
异步生命周期、导入、保存和运行时失败会抛出异常,并通过 error 事件向宿主报告。编辑类同步方法在操作不可接受时返回 false。
editor.addEventListener("error", ({ detail }) => {
logEditorError(detail.code, detail.message, detail.detail);
showDocumentError(detail.message);
});
try {
await editor.importDocument(input, { name });
} catch (error) {
showRetryAction(error);
}
if (!editor.insertContent("审批意见")) {
showToast("当前位置不可编辑或文档为只读模式");
}
宿主安全边界
- 在服务端校验文件类型、文件大小、租户权限和病毒扫描结果;不要只信任浏览器 MIME。
- 内容插入 API 仅接受纯文本,不要把不可信 HTML 直接写入编辑器 DOM。
- 保存期间禁用重复提交;使用业务版本号或 ETag 处理并发覆盖。
- 新 Blob 成功上传并确认版本之前保留原文档,不要把本地序列化等同于远端持久化。
- 离开页面前根据
dirty提示,并在宿主应用中记录error技术细节。
生产授权
生产构建包含 office-preview-license.json、授权运行时和 WASM 门禁。启用 license-required 后,元素挂载时会校验授权;失败时触发 error 并显示授权错误面板。
<word-editor
license-required
license-feature="word-editor-production">
</word-editor>
部署
当前生产目标为 https://docx-editor.pages.dev。先签发并提交运行授权,再从该 commit 创建全新的干净 worktree。发布脚本会重建 runtime、复制站点和 Markdown 文档、复制授权资产与 WASM、写入 Cloudflare 控制文件、生成 release metadata,并把同 commit 的对应源码归档一起封装。完整步骤见 Deployment Guide。
# 在已提交发布 SHA 的全新 clean worktree 中
npm ci
npm run build:cloudflare
npm run deploy:cloudflare
/产品主页和生产入口。/docs/本开发文档;/docs/*.md 提供版本化 Markdown 原文。/examples/demo/完整在线编辑器。/examples/integration/第三方宿主 API 集成 Demo。/word-editor-runtime-loader.mjs授权发布使用的同源运行时加载入口。/auth/*、/wasm/*授权运行时和 Office 解析核心。/word-editor-release.json版本、产物和部署来源元数据。/source/current.tar.gz与当前线上运行时同 commit 的完整对应源码。/source/current.tar.gz.sha256对应源码归档的 SHA-256 校验文件。/source/index.json源码 commit、不可变归档地址、摘要和大小的机器可读索引。生产运维
- 上线前验证根主页、文档页、完整 Demo、集成 Demo、授权文件、WASM MIME 和 release metadata。
- 验证导入、编辑、书签查询、四种插入目标、保存 Blob 和 ArrayBuffer 导出。
- 对变更范围执行受影响测试;涉及编辑器 runtime 时再运行浏览器端 smoke 和核心回归。
- 字体仓库、授权域名和 Cloudflare 项目名应随发布记录一起审计。
- 宿主应用应处理
changed、saved、error,并在离开页面前处理 dirty 状态。 - 监控导入失败率、保存耗时、上传失败、版本冲突和授权错误,不记录文档正文。