generateDocx(ast: LitAstNode): Promise<Uint8Array>
generateDocx 没有其他参数。它根据 LitAST 重新构建整个 DOCX 包,返回完整文件的字节;不会在某个已有文件上局部修改。
输出字节
// Node
await writeFile("out.docx", await generateDocx(ast));
// 浏览器:生成下载链接
const bytes = await generateDocx(ast);
const url = URL.createObjectURL(new Blob([bytes], {
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
}));
手写节点
LitAST 节点是普通对象,根节点是 document:
const ast = {
type: "document",
children: [
{
type: "paragraph",
children: [
{ type: "text", text: "Hello " },
{ type: "text", text: "world", marks: [{ type: "bold" }] },
],
},
],
};
这份文档生成后再用 parseDocx 读回,得到的 children 与上面完全一致。
用 docx 辅助函数
docx 是一个分组的辅助对象,返回的就是上面这样的节点,只是写起来更短,并带有类型检查:
| 分组 | 内容 |
|---|---|
docx.blocks | paragraph、heading、blockquote、codeBlock、pageBreak、callout |
docx.inline | text、link、ruby |
docx.marks | bold、highlight、link、textStyle |
docx.tables | table、row、cell、shadedCell |
docx.styles | paragraphProperties、spacing、indentation、shading、border、runProperties |
辅助函数没有覆盖所有节点。根节点 document、图片 image、分节 section、列表 list 需要手写,二者可以自由混用。斜体等没有辅助函数的标记直接写 { type: "italic" }。
docx.blocks.paragraph({
children: [
docx.inline.text("重要", { marks: [docx.marks.bold(), docx.marks.textStyle({ color: "C00000", fontSize: "14pt" })] }),
docx.inline.text(":详见"),
docx.inline.link("说明", { href: "https://example.com" }),
],
properties: docx.styles.paragraphProperties({
textAlign: "center",
spacing: docx.styles.spacing({ after: 120 }),
}),
});
拼音指南
docx.inline.ruby 生成原生 w:ruby。base 是正文,annotation 是注音;两层可以
分别设置文字格式。读音由调用者提供,lit-docx 不包含自动拼音词典。
const guide = docx.inline.ruby({
marks: [docx.marks.textStyle({ fontSize: "12pt" })],
base: [docx.inline.text("汉", {
marks: [docx.marks.textStyle({ fontSize: "12pt" })],
})],
annotation: [docx.inline.text("hàn", {
marks: [docx.marks.textStyle({ fontFamily: "Arial", fontSize: "6pt" })],
})],
rubyAlign: "center",
hps: 12,
hpsRaise: 24,
hpsBaseText: 24,
lid: "zh-CN",
});
const bytes = await generateDocx({
type: "document",
children: [docx.blocks.paragraph({ children: [guide] })],
});
这五个属性在新建时都需显式提供。hps、hpsRaise、hpsBaseText 的数字单位是半磅;
hpsRaise 是文件中的抬升量,不是 Word 对话框“拼音文字距离”的直接数值。
本例来自 Word 16.109.2 的 12pt 正文、6pt 注音样本,不代表通用字体的自动间距算法。
外层 marks 的字号、基文字号与 hpsBaseText 保持一致;参考字号不会替代实际文字格式。
对齐值有 center、left、right、distributeLetter、distributeSpace、rightVertical。
解析后的节点使用 children 存正文、attrs.rubyText 存注音。可修改文字和以上属性后再生成;
未知或未改的来源属性按往返规则保留。超链接应放在整个 ruby
节点的 marks 上;不能把 docx.inline.link 直接放进任一文字层。
表格
表格的层级是 table > tableRow > tableCell > 段落。单元格里至少要有一个块级节点,用辅助函数创建时会自动补一个空段落。
docx.tables.table({
columns: [3000, 3000],
rows: [
docx.tables.row({ isHeader: true, cells: [docx.tables.cell({ children: [docx.blocks.paragraph({ children: [docx.inline.text("地区")] })] })] }),
],
});
图片、分节与页眉页脚
- 图片:
{ type: "image", attrs: { src, width, height } },src是图片的 Data URL,宽高单位是像素(按 96 DPI 换算)。 - 分节:
section是document.children里的一个兄弟节点,表示它之前的内容到此结束一节,并携带这一节的页面设置。 - 页眉页脚:作为
section的子节点,header用attrs.headerType,footer用attrs.footerType,取值为"default"、"first"或"even"。
快速开始里的报告示例同时用到了这三者。
单位约定
| 数值 | 单位 |
|---|---|
| 页面宽高、页边距、段落缩进、段前段后间距、表格列宽 | twips,即 1/20 磅;1 英寸 = 1440,1 厘米 ≈ 567 |
| 图片宽高 | 像素,按 96 DPI 换算 |
textStyle 的 fontSize | "12pt" 这样的字符串,或以磅为单位的数字 |
ruby 的 hps、hpsRaise、hpsBaseText | 数字为半磅,或保留 OOXML 显式单位字符串 |
| 颜色 | 6 位十六进制 RGB,"C00000" 与 "#C00000" 均可;解析结果带 # |
A4 纸为 pageWidth: 11906, pageHeight: 16838,US Letter 为 12240 × 15840。
新文档会自动补齐的部件
从零生成时没有原始的 styles.xml、numbering.xml 等部件,生成器会按文档中实际用到的内容补齐编号、批注、脚注尾注等部件。从已有文件读进来的 LitAST 则会写回 ast.meta.rawXmlFiles 中保存的原始部件,见往返与保留。