@ file-viewer/ docx (英语)
纯 HTML DOCX 用于基于浏览器的Word预览的渲染器. 此软件包保留了最后的非扫描片 docx-viewer 线条作为稳定的维护轨道,将 WordprocessingML 转换为 HTML ,同时保持语义结构、页面布局、页眉/页脚、编号、字段、表格、图像和常见的绘图ML 内容,只要浏览器布局允许.
此分叉包括对大型 Word 文档的制作加硬化:可选的 Worker 剖析出主线回落,同步渲染输出输出,Word-saved pagignation支持,动态溢出 pagignation和布局遥测.
安装
npm install @file-viewer/docx
对于独立浏览器构建,将这些文件一起传送,并保持Worker URL来源相同:
dist/docx-preview.js
dist/docx-preview.worker.js
dist/jszip.min.js
基本用途
<script src="dist/jszip.min.js"></script>
<script src="dist/docx-preview.js"></script>
<div id="container"></div>
<script>
const options = {
useWorker: true,
workerUrl: "dist/docx-preview.worker.js",
awaitLayout: true,
strictWordCompatibility: true,
ignoreLastRenderedPageBreak: false,
preserveComplexFieldResults: true,
updatePageReferences: false,
hideWebHiddenContent: false,
externalLinkPolicy: "allow",
externalResourcePolicy: "block",
progress: ev => console.log(ev.phase, ev.current, ev.total, ev.message)
};
docx.renderAsync(fileOrArrayBuffer, document.getElementById("container"), null, options)
.then(() => console.log("docx: finished"));
</script>
ES模块使用:
import { renderAsync } from "@file-viewer/docx";
await renderAsync(fileOrArrayBuffer, container, null, {
useWorker: true,
workerUrl: new URL("@file-viewer/docx/worker", import.meta.url).toString(),
awaitLayout: true
});
在一个CSP下: require-trusted-types-for 'script',在
应用边界并经过 workerFactory数字 :
const workerPolicy = trustedTypes.createPolicy("app-docx-worker", {
createScriptURL(value) {
const url = new URL(value, location.href);
if (url.origin !== location.origin)
throw new TypeError("DOCX Worker must be same-origin");
return url.href;
}
});
await renderAsync(fileOrArrayBuffer, container, null, {
useWorker: true,
workerFactory: () => new Worker(
workerPolicy.createScriptURL("/assets/docx-preview.worker.js")
)
});
复制 dist/docx-preview.worker.js 同源应用程序资产路径
部分你的建设或部署.
允许应用程序拥有的 Worker 政策和渲染器的三个窄 HTML
投资政策 trusted-types CSP指令:
trusted-types app-docx-worker file-viewer-docx-xml-parser file-viewer-docx-altchunk-parser file-viewer-docx-altchunk-srcdoc;
require-trusted-types-for 'script';
渲染器政策品牌只包含发送到惰性XML/HTML的确切值
解剖器或已消毒的 AltChunk srcdoc; 没有安装默认策略.
只读审查预览
已跟踪的更改默认仍然禁用 。 过 reviewMode 以保留 Word 修订
在 DOM 中标记,默认显示注释,并启用四个只读视图:
import {
collectDocxReviewChanges,
renderAsync,
renderDocument
} from "@file-viewer/docx";
const document = await renderAsync(file, container, null, {
reviewMode: "all" // "final" | "original" | "simple" | "all"
});
const changes = collectDocxReviewChanges(document);
await renderDocument(document, container, null, { reviewMode: "original" });
renderChanges: true 作为兼容性别名保留 reviewMode: "all"。 。 。 .
设定 renderComments: false 明确需要跟踪更改时无须
评论浮出水面.
默认 reviewPresentation: "balloon" 将已删除的文本作为锁定
边距审查铁路. 没有铁路的宿主可以通过 reviewPresentation: "inline"
用引擎本身的样式显示删除内容.
测量标签、 DraigingML/VML 锚源、 VML 文本取景口、 合并单元格
边缘和页面背景由引擎处理。 绘制文本框使用
独立的 HTML 故事,这样序列化可以保留其段落边界;
出口商不需要更换或修理产生的部件. renderAsync()
更新字体、图像、页码和容器再大小后的坐标.
打电话 disposeRenderedDocument(container) 当卸载以释放文档时
观察员和书签处理员。 在同一容器释放中再次渲染
自动操作.
模式值遵循Word 为审查显示 语义 : simple 保留
带有紧凑变化指标的现有案文, all 曝光每个支持
修订和评论主播, final 是隐藏标记的当前文档,
财务报告和审定财务报表 original 恢复带有标记的修改前文本。 一个东道主
想要使用文字风格的边距气球 collectDocxReviewChanges() 一起行动
与马厩 data-docx-change-* 锚; 渲染器不强制
普通文档预览中的可选审查 UI.
在提供审查模式时解决了段落标记的修订:已删除
标记加入段落 final编号 :simple,插入标记并加入段落
内 original。内容保留在表格单元格、区域或位置
边框。 原生 Word 创建的定着物验证段落边界、 标签、 软
课间休息、 混合粗体运行、 CJK 替换和表格单元格文本对 Word 的
接受所有文件并拒绝所有文件。 浏览器门重复这些检查
主线程和真实的Worker同时重用解析文档.
使用 renderDocument() 在切换视图时使用返回的解析文档
可以更改段落边界;它不会再次剖析或上传文件.
同步 setDocxReviewMode() 帮助只更改 CSS 的能见度 。 没错
不重建段落结构或页形,不能取代
使步为行. 文件查看器的 Word 设置自动执行渲染步骤 .
collectDocxReviewChanges() 返回逻辑文字审查项目而不是原始
OOXML包装. 同一段的相邻/有记录的订正片段,
作者,并编辑会话; ids 列出每个源代码.
这个 presentation 字段为 inline 插入/移入项目和 balloon 页:1
删除/调出/格式/评论项目。 格式项目包括结构化项目
formatChanges 和语义描述,例如: 无下划线。 。 。 .
API 密码
renderAsync(
document: Blob | ArrayBuffer | Uint8Array,
bodyContainer: HTMLElement,
styleContainer?: HTMLElement,
options?: Partial<Options>
): Promise<WordDocument>
parseAsync(
document: Blob | ArrayBuffer | Uint8Array,
options?: Partial<Options>
): Promise<WordDocument>
parseAsyncInWorker(
document: Blob | ArrayBuffer | Uint8Array,
options?: Partial<Options>
): Promise<WordDocument>
renderDocument(
wordDocument: WordDocument,
options?: Partial<Options>
): Promise<Node[]>
awaitRenderedLayout(
container: HTMLElement,
options?: Partial<Options>
): Promise<LayoutSnapshot>
collectLayoutSnapshot(
container: HTMLElement,
options?: Partial<Options>
): LayoutSnapshot
重要选项
{
className: "docx",
inWrapper: true,
hideWrapperOnPrint: false,
ignoreWidth: false,
ignoreHeight: false,
ignoreFonts: false,
breakPages: true,
// Appearance
darkMode: false,
// Word fidelity / pagination
ignoreLastRenderedPageBreak: false,
strictWordCompatibility: true,
paginationTolerance: 2,
maxDynamicPaginationPasses: 1000,
awaitLayout: true,
// Worker and responsiveness
useWorker: true,
workerUrl: "dist/docx-preview.worker.js",
workerFallback: true,
workerTimeout: 120000,
renderPageBatchSize: 2,
renderYieldEveryMs: 16,
progress: ev => void,
// Field and print-layout compatibility
preserveComplexFieldResults: true,
updatePageReferences: false,
hideWebHiddenContent: false,
// Content switches
renderHeaders: true,
renderFooters: true,
renderFootnotes: true,
renderEndnotes: true,
renderComments: false,
renderAltChunks: true,
reviewMode: undefined, // opt-in: "final" | "original" | "simple" | "all"
renderChanges: false,
experimental: false,
trimXmlDeclaration: true,
useBase64URL: false,
debug: false
}
大文档渲染路径
生产途径故意被分成几个阶段:
- 主线程开始一个工人使用
workerUrl。 。 。 . - 自成一体的Worker使用被捆绑的JSZip和XML 解析器导入来解析软件包,解析XML部件,解析关系并串行一个紧凑的文档快照. 默认不需要外部脚本、 Global XML shim 或单独附加的靴子夹 .
- 主线程将快照还原为
WordDocument,然后将 HTML 页面分批生成requestIdleCallback, (中文(简体) ),requestAnimationFrame或者说setTimeout在分页之间. awaitRenderedLayout等待图像和字体,运行动态溢出页并返回 aLayoutSnapshot。 。 。 .collectLayoutSnapshot可以在 CI 或遥测中用于检测溢出页、未解决的介质、页数、合并文本长度、字段和浮动对象.
等待的布局包括字体/图像解析和产生的分页,绘图
和标本测量。 如果被替换,它拒绝
容器被取出,否则无法在其中安放
maxDynamicPaginationPasses。一个 AbortError 识别过时或已删除的
调制。 与 awaitLayout: false,渲染可以在这些测量之前返回
完成; 调用 awaitRenderedLayout 在计量或导出结果之前.
一个离子 renderDocument 有关结果可能在以后提出和等待.
批量渲染和浏览器产量可以避免在一项任务中插入非常大的 DOM 树导致的前演示页冻结. 供应的工人包括它的XML API. workerFallback: true 当工人启动被主机环境所阻断时仍然有用 。 若为 workerJsZipUrl 明确设定了工人装载和使用JSZip资产。 选择必须是非空同源的 HTTP( S) 或 Blob URL 没有证书 。 相对的 URL 解析基于 Worker 脚本 URL; Blob Worker 需要一个绝对的 URL. 跨源的URL和不透明的来源在导入前被拒绝,即使全球JSZip已经存在实施. 启用此选项以使用捆绑的依赖; 明文无效的值不会选择默认值 。 一个失败的负载或无效的 JSZip 导出被报告为错误;它从未默默地取代捆绑的依赖. workerFallback 继续控制主线折返; 设置为 false 当任何工人或被选中的依赖性失败者必须拒绝电话.
插头、页眉/脚和托克
渲染器支持:
- 明确的分页符 (e)
w:br w:type="page"(三); - 保存的分页位置( W)
w:lastRenderedPageBreak默认启用; - 段 次 页 次
pageBreakBefore, (中文(简体) ),keepNext, (中文(简体) ),keepLines财务报告和审定财务报表widowControl提示; - 分页大小、方向、列、边、页眉和页脚;
- 表格行分割为
w:tblHeader保留重复头; - 对结构分页后仍然溢出的内容进行后动态页标;
- 真实的页面本地字段的布局时间更新, 如
PAGE, (中文(简体) ),NUMPAGES, (中文(简体) ),SECTIONPAGES财务报告和审定财务报表SECTION· ; - 保存 Word 存储的复杂场结果
TOC, (中文(简体) ),PAGEREF, (中文(简体) ),REF, (中文(简体) ),SEQ, (中文(简体) ),IF, (中文(简体) ),MERGEFIELD和相关字段默认,因此由Word授权的目录会保留其缓存的页码和标签头,而不是被浏览器错误地重新计算.
对于文字编写的文档,请保留 ignoreLastRenderedPageBreak: false。这些标记保留了Word兼容编辑器所计算的位置,该编辑器上次保存了文档,对于长表格和大型中国技术文件特别重要。 保留 preserveComplexFieldResults: true 除非您有意重算交叉引用字段; 默认匹配 Word 打印/ PAGEREF 现有结果 .
w:webHidden 在此渲染器中默认不被隐藏,因为它只适用于Word的Web布局视图。 在打印版式中, Word 在页码和缓存之前仍然显示 TOC 标签 PAGEREF 即使这些运行被标记 w:webHidden设置 hideWebHiddenContent: true 仅用于明确的 Web 布局样式预览.
外部超链接默认仍然活跃,但只有 HTTP( S), mailto:, (中文(简体) ), tel:
和安全的相对目标 href。脚本能力,本地文件,blob,
每种模式都拒绝相对和未知的方案。 设定
externalLinkPolicy: "block" 以略去安全外部 href 值同时保留
它们的文本和消毒的目标元数据。 仍保留内部书签链接
活动于任一模式.
外部图像关系默认被屏蔽. 设定 externalResourcePolicy: "allow" 仅当文档被信任装入 HTTP( S) 图像资源时。 包装的图像和本地 data:image/... 或者说 blob: 图像 URL 仍然可用而不允许网络访问; 未知和脚本能力协议在两种模式中都被拒绝 .
renderAltChunks 与现有的一体化保持一致。 嵌入式 HTML 是
对脚本、活动元素、事件处理器、 CSS 和
在达到最大限入的沙盒iframe之前,含有URL的属性.
设定 darkMode: true 以复制Word Online的"Switch Modes"黑暗外观. 渲染器所出出的每一色相——文本,背景/高光度,边框,下划线,主题颜色和 DraigML/VML 形状填充和中划——均被转换成同样光度-反转算法 微软用于这一确切目的(参见 roosterjs是因为 getDarkColor:颜色被转换为CIE Lab,只有光度(CL)通道绕一固定基值倒转( L 联 合 国 #333333)),和花相克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克a编号 :b)是未触及的。 保证每个颜色都清晰可见 在黑暗的一页上 纯黑色变成纯白色 纯白色变成纯白色 #333333和任意颜色,例如 rgb(99, 36, 35) 保持其红发的花色,同时变得足够轻而易举地去读取——没有每个频道的RGB倒数的天真的副作用. 切换纯粹是一个渲染时间的 CSS 变换——它不会改变被解析的文档模型——每一个被转换的颜色被 CSS 变量所包裹,以便 @media print 可以恢复准确的原光模式值; 打印输出总是随Word的正常光亮外观而制作, 不论是否 darkMode。 。 。 .
页眉/页脚选择遵循 WordprocessML 打印出规则 : first 引用适用于一节的首页 w:titlePg,以及 even 引用仅在设置含有时适用 w:evenAndOddHeaders。每个省略的引用从上一节继承了自己的变体。 如果第一节中没有选定的变体,其标题/脚为空白. 动态续页选择自己的首个/偶数/默认变体,而不是重复被克隆的首页头/脚.
相邻被保存的页面标记不创建额外的空白页,包括在作者的分页后立即创建一个被保存的标记. 重复撰写 w:br w:type="page" 课间休息仍然保留有意的空白页.
脚注始于载有其第一个可见参考的页面。 长注 文本在页面之间继续排列顺序,保留作者文本、格式化和 嵌入式资源。 尾注跟随最终的正文内容. 自定义注释标记 和区段/页面重新启动设置与生成的编号分开. 保留无法匹配可打印页面的不可分割的注释对象 报告为未解决的布局错误,而不是静默地被剪辑.
复杂的文字格式化是保持脚本意识的. w:iCs 财务报告和审定财务报表 w:bCs 现在影响RTL/Complex-script的跨度,但它们并不适用于东亚TOC文本;这避免了当DOCX只指定了复杂script斜体时将中国TOC三级条目斜体化.
回归固定
tests/regression/database-design.docx 是中国用于验证生产行为的大型数据库设计文档. 固定器有一个大 word/document.xml,上千段,许多表格,TOC/PAGEREF字段,保存了分页符和多页眉/脚引用.
在本地服务器中打开此页面以运行浏览器回归 :
tests/regression/database-design-render.html
节点回归可运行于 :
node tests/regression/check-database-design.cjs
它让 tests/regression/database-design.docx 并声称TOC条目保留Word的缓存页码,例如 引言 5, (中文(简体) ), 各系统与数据库对应关系 6, (中文(简体) ), 表间关系 16 财务报告和审定财务报表 数据恢复策略 103 而不是崩溃到第1页。 它还证实: w:tab 以可衡量方式释放右翼领导人 docx-tab-stop 带有点头样式的元素,因此TOC和图列表的页码点头仍然可见. 回归还检查了打印出TOC超文本链接:TOC超文本链接保留了他们的锚地,但被嵌入的Hyperlink字符风格运行被迫继承了段落颜色和文本装饰,匹配了Word的黑色打印出TOC而不是浏览器-蓝色链接. 一个成功的浏览器运行更新了固定状态的横幅,有页数,溢出页,未解决的媒体和文本长度.
构建
所有JavaScript都是由Rollup从TypeScript源入站点生成的. 构建可读和可改进的UMD/CommonJS兼容和ESM捆绑,自成一体的工人,以及由本地TypeScript编译器生成的申报. 现有产出首先清理 npm pack 自动重建 :
npm run build
安装锁定文件的依赖性 npm ci。没有全局编译器或 NODE_PATH 需要时间. dist/jszip.min.js 从宣布的JSZip依赖状态中复制,用于独立的主线; 捆绑的依赖许可证保留在 dist/THIRD_PARTY_NOTICES.txt。 。 。 .
运行完整的构建、语义回归和包合同检查:
npm run verify
运行 npm run test:worker 用于孤立的节点 VM 协议检查。 这不是浏览器测试 。 运行 npm run e2e:worker (铬)和 npm run e2e:worker -- webkit 以验证生成的 Worker, 主行对等, 真实选中的 JSZip 抓取/ hash, 以及真实浏览器中的依赖/ XML 失败控制 。 设定 DOCX_WORKER_JSZIP_PATH 在检查一个消费者解析的版本时,将输入另一个已安装的JSZip浏览器资产。 这些检查从未将解析器代码附加到工人身上 .
浏览器焦点检查仍可通过 npm run e2e, (中文(简体) ), npm run e2e:chart 财务报告和审定财务报表 npm run e2e:header-guard。 。 。 .
这些命令运行了被绑定的 Playwright 浏览器中现有的茉莉花谱,
只在回回转时提供。 安装铬和火狐
npx playwright install chromium firefox 在运行之前; e2e:security
使用严格的CSP和信任类型固定方式运行两个浏览器. 过
-- --browsers chromium,webkit 以选择已安装的其他引擎.
npm run e2e-watch 更改后重运行相同的规格 tests 或者说 dist。 。 。 .
跑者使用原生文件的盘点和观看来代替遗产
Karma glob 依赖性,包括未标注的依赖性 braces 循环缺陷.
本地演示
在 HTTP 上服务仓库并打开根页 :
python3 -m http.server 8000
演示为普通DOCX文件的自成一体,包括样本文档,页面导航,光/暗渲染和一个选项面板. TIFF支持只有在文档实际包含TIFF介质时才会被加载.
可选显示目标
过 exposeDisplayTargets: true 改为 renderAsync (或两者) parseAsync
财务报告和审定财务报表 renderDocument 将段落身份暴露为
data-office-target 属性。 值是 OOXML 部分路径,然后是
#p:<w14:paraId>,或 #xpath:<structural-path> 当未存储段落ID时.
重复的页眉和被拆分的段落片段可能共享一个身份.
此选项默认被禁用, 并与匹配的 Worker 捆绑配合 . 它添加了只读身份元数据,而不是编辑或文档回写API. 外部显示适配器可以用来定位已渲染的文本. 正在重新装入或 重新定义文档可替换 DOM 节点;适配器必须重新应用 拥有缓存显示状态。 身份被范围化到源软件包 不保证结构编辑到原始文件.
关于忠诚的说明
渲染器遵循OOXML语义,并使用浏览器-内置布局. 它的设计是为了生产预览和回归测试,而不是为了用Microsoft Word的私人布局引擎声称字节或像素完美身份. 使用 LayoutSnapshot 和所提供的回归固定器,以监测依赖于浏览器字体,字体倒回和塑造引擎的剩余差异.
编号后缀和标题/列表编号
OOXML在编号符号后将编号文本从后缀中分出. w:lvlText 包含编号模式, w:numFmt 定义用于扩展的格式 %1, (中文(简体) ), %2等,以及 w:suff 定义在生成的数字和段落文本之间插入的内容。 何时 w:suff 中省略,OOXML将其作为 tab。渲染器将此后缀作为有效的 CSS Unicode 分隔符,而不是隐藏的可见文本,所以标题/列表不再显示文字 \9 或者说 \a0 在编号后.
以 :
node tests/regression/check-numbering-suffix.cjs
大型数据库设计回归利用默认的缓存快照来避免在受限制的CI中花费几分钟重建完整的文档. 设定 DOCXJS_RERENDER_REGRESSION=1 当你需要从DOCX重生的时候.
维护者释放
publish.yml 检查准确的稳定释放标记, 构建软件包, 运行
语义和本地Word浏览器回归,再用npm出处发布.
Npm 信任的出版商必须绑定 @file-viewer/docx 改为
flyfish-dev/docxjs 财务报告和审定财务报表 publish.yml;不需要长寿 npm 令牌 .
工作流程本身并不创建 npm 权限 .
手动调度默认为干线运行,需要已有的放行标记. 在跳过一个程序之前,对装入的SHA-512进行核对 现有版本。 不同的字节或不确定的字节会停止运行 而不是更改版本或重复认证提示.
固定页面预览中的图片布局
绘图ML srcRect 裁剪会选择作者相框内的源像素,包括不对称的收割和自转/迷宫等. 所绘制的图片不会扩展其周围的段落,也不会在后面的文字上作画.
在固定页平面图中,一个比一新页正体高的内线图被按比例缩放以适应,保留了完整的图及其外观比. 普通相片保持其被作者化的维度. 这可以防止同样的超大小相片通过空续页反复移动. 连续/流预览保持其现有的分量行为.