Skip to content

Markdown ​

markdownToNodes() 将 Markdown 转换为 docx-kit 现有的文档 DSL。 生成的节点与手写节点使用相同的构建器、样式、主题、预设、图片 解析器和插件。转换器基于 Marked,同时支持浏览器与 Node.js。

转换与渲染 ​

ts
import { markdownToNodes } from 'docx-kit/markdown'
import { codeBlockPlugin, createDocx, defineStyles } from 'docx-kit/node'

const markdown = `# Project report

Hello **docx-kit**. Visit [the docs](https://docx-kit.ntnyq.dev).

- [x] Parse Markdown
- [ ] Review the document

~~~ts
const answer = 42
~~~
`

const doc = createDocx({
  styles: defineStyles({
    h1: { fontSize: 24, color: '$colors.primary' },
    body: { fontSize: 12, lineHeight: 1.5 },
  }),
  theme: { colors: { primary: '#2563eb' } },
}).use(codeBlockPlugin())

for (const node of markdownToNodes(markdown, {
  classNames: { paragraph: 'body' },
})) {
  doc.add(node)
}

await doc.save('report.docx')

在浏览器中,从 docx-kit 导入构建器与插件,并通过 await doc.toBlob() 导出。转换器不依赖文件系统或 DOM。 使用独立包时,从 @docxkit/markdown 导入。

节点也可以作为 schema 内容传入:

ts
import { markdownToNodes } from 'docx-kit/markdown'
import { codeBlockPlugin, renderDocx } from 'docx-kit/node'

const doc = await renderDocx({
  content: markdownToNodes('# Summary\n\nA **formatted** paragraph.'),
  plugins: [{ plugin: codeBlockPlugin(), type: 'inline' }],
})

await doc.save('summary.docx')

支持的语法 ​

MarkdownDSL 输出
ATX 与 Setext 标题heading,1–6 级
段落与强调包含样式化 text 片段的 paragraph
加粗、斜体、删除线、行内代码已有文本片段样式
链接、自动链接、引用链接行内 hyperlink
图片与引用图片块级或行内 image
无序、有序、嵌套与任务列表列表节点、条目层级与原生行内复选框
GFM 表格table、列对齐与富内容单元格渲染器
引用块转换后的块,可使用指定类名或默认左缩进
围栏与缩进代码块名称为 codeBlock 的 plugin 节点
分隔线thematicBreak
硬换行已有的片段级 style.docx.break

代码块要求调用方注册已有的 codeBlockPlugin()。 语言取自围栏信息字符串的第一个单词。语法 高亮沿用该插件对可选 highlight.js 的支持。

选项与样式表类名 ​

MarkdownOptions 接收:

选项默认值用途
gfmtrue表格、任务列表、删除线与扩展自动链接
breaksfalse启用 GFM 时,将软换行视为硬换行
classNames无将语法映射到已有样式表类名
imageSize无默认图片 width 和/或 height
transform无替换、调整或忽略每个转换后的块

类名目标包括 heading、paragraph、blockquote、list、table、code、 inlineCode、link、image、hr 和 html,值可以是类名字符串或 数组。请在文档已有的样式表中定义这些类名。未显式 指定标题或段落类名时,仍使用正常的 h1–h6 与 p 回退 规则。行内代码默认使用 Consolas;通过 inlineCode 类名 可以由样式表指定字体,也可以使用主题令牌。

复用自定义插件 ​

transform 接收转换后的节点,以及每个来源块的 { type, raw }。 它在子块转换完成后运行。返回 [] 可忽略该块, 也可以返回已有插件节点来自定义渲染:

ts
import { calloutPlugin, createDocx } from 'docx-kit'
import { markdownToNodes } from 'docx-kit/markdown'

const doc = createDocx().use(calloutPlugin())
const nodes = markdownToNodes('> A note for the reader.', {
  transform(nodes, context) {
    if (context.type === 'blockquote') {
      return [{
        name: 'callout',
        options: {
          content: context.raw.replace(/^> ?/gm, ''),
          type: 'info',
        },
        type: 'plugin',
      }]
    }
    return nodes
  },
})

for (const node of nodes) {
  doc.add(node)
}

const blob = await doc.toBlob()

DSL 边界 ​

  • 标题与表头保留可见文本,其现有 DSL 字段不支持行内格式。
  • 表格正文单元格通过列渲染函数保留强调、链接与 图片。序列化为 JSON 时会保留可读文本,但移除这些 函数。需要富内容表格时应直接渲染。筛选 或排序已有行对象会保留富内容。编辑后的 单元格、复制的行和新增行会将当前值渲染为纯 文本。
  • 图片保留来源与替代文本。URL 或其他自定义来源需要配置 resolveImage, 支持的本地路径可使用 Node.js 入口。 转换过程不加载图片。链接中的图片会变为替代文本, 因为超链接的子节点只接受文本片段。
  • 原始 HTML 保留为字面文本,不会作为文档标记解析。
  • 列表沿用 Word 编号模型,最大嵌套层级为 8,遇到 嵌套块时拆分列表并保留内容顺序。后续块是 普通 DSL 块,不是嵌套列表容器。
  • 片段链接不会自动生成匹配的标题书签。

Released under the MIT License.