建立外掛
本指南介紹如何建立、測試與發佈 docx-kit 外掛。自訂圖表呈現器、簽名區或專用文件元素都遵循同樣的流程。
快速開始
建立外掛項目最快的方法是使用鷹架工具:
npx @docxkit/create-plugin my-chart-plugin產生的完整項目包含:
my-chart-plugin/
├── docx-kit.plugin.json — Plugin manifest
├── src/
│ └── index.ts — Plugin source
├── tests/
│ └── index.test.ts — Plugin tests
├── package.json — npm package config
├── tsconfig.json — TypeScript config
└── README.md — Documentation外掛清單
每個外掛都應在套件根目錄提供 docx-kit.plugin.json 清單,用於聲明中繼資料與兼容性要求:
{
"name": "docx-kit-plugin-chart",
"version": "1.0.0",
"docxKit": "^0.2.0",
"main": "./dist/index.js",
"plugin": {
"name": "chart"
},
"description": "A chart plugin for docx-kit",
"types": "./dist/index.d.ts",
"peerDependencies": {
"docx-kit": "^0.2.0"
}
}必填欄位:
| 欄位 | 型別 | 說明 |
|---|---|---|
name | string | npm 套件名 |
version | string | 有效的 semver 版本 |
docxKit | string | 與 docx-kit 兼容的 semver 版本範圍 |
plugin.name | string | 外掛短名稱(用於 DSL) |
main | string | 入口檔案路徑 |
可選欄位:description、types、dependencies、peerDependencies、exports。
從 npm、URL 或本地來源載入時,PluginLoader 會驗證清單。有效清單可以確保兼容性,併為外掛登錄服務提供中繼資料。
definePlugin() API
definePlugin() 是恆等函式,為外掛定義提供型別推斷:
import { definePlugin } from 'docx-kit'
import { Paragraph } from 'docx'
interface ChartOptions {
data: number[]
title: string
type: 'bar' | 'line' | 'pie'
}
export function chartPlugin() {
return definePlugin<'chart', ChartOptions>({
name: 'chart',
// Optional: called once when the plugin is registered
setup(context) {
// Register types, load assets, configure defaults
},
// Required: called each time a plugin node is encountered
render(options, context) {
return new Paragraph({
children: [
new TextRun({ text: options.title, bold: true }),
],
})
},
})
}型別參數
- TName — 外掛名稱的字串字面量,作為 DSL 中節點的
type,併為建構器的.chart()提供自動補全。 - TOptions —
render()接收的選項型別,使用者透過{ options: { ... } }傳入。
setup() 鉤子
可選的 setup() 鉤子在 builder.use(plugin) 註冊外掛時呼叫一次,接收 PluginRenderContext,其中包含:
builder— DocxBuilder 實例config— 文件設定styles— 目前樣式表
適合註冊輔助樣式、預載入資源等一次性初始化。
render() 函式
每當編譯器遇到 type === pluginName 的節點時,都會呼叫 render(),傳入:
options— DSL 節點中的 TOptions 物件context— 包含 builder、config 和 styles 的PluginRenderContext
必須回傳 docx 文件子節點(Paragraph、Table、ImageRun 等)或子節點陣列。
外掛呈現模式
不同外掛採用不同呈現模式,常見方式如下:
基於段落(簡單文字輸出)
badge、watermark 等外掛呈現單個 Paragraph:
render(options) {
return new Paragraph({
children: [
new TextRun({ text: options.text, bold: true }),
],
})
}基於表格(結構化資料)
dataTable、propertyTable 和 callout 等外掛呈現 Table。Callout 使用單個儲存格,以便在 Word 和瀏覽器預覽中保留內邊距:
render(options) {
const rows = options.data.map(item =>
new TableRow({
children: options.columns.map(col =>
new TableCell({
children: [new Paragraph({ children: [new TextRun({ text: String(item[col.key]) })] })],
}),
),
}),
)
return new Table({ rows })
}基於圖片(產生圖形)
qrcode、echarts 等外掛透過產生的資料呈現 ImageRun:
async render(options, context) {
// Generate image data (e.g. QR code, chart)
const imageData = await generateImage(options)
return new Paragraph({
children: [
new ImageRun({
data: imageData,
transformation: { width: options.width, height: options.height },
}),
],
})
}注意:圖片類外掛通常使用 async render(),並動態載入 echarts、qrcode 等同儕相依套件。
使用 PDK 測試
外掛開發工具套件(PDK)提供專為外掛作者設計的測試工具:
import { renderPlugin, assertRendersParagraph, assertPluginDefined } from 'docx-kit/pdk'
import { chartPlugin } from '../src'
const plugin = chartPlugin()
// Verify the plugin structure
assertPluginDefined(plugin, 'chart')
// Test rendering in isolation
const result = await renderPlugin(plugin, { data: [1, 2, 3], title: 'Chart', type: 'bar' })
assertRendersParagraph(result)PDK 函式
| 函式 | 說明 |
|---|---|
renderPlugin(plugin, options) | 獨立呈現外掛,回傳 docx 子節點 |
createPluginTestContext() | 建立用於測試的模擬 PluginRenderContext |
assertRendersParagraph(result) | 斷言輸出為 Paragraph |
assertRendersParagraph(result, text) | 斷言輸出為包含預期文字的 Paragraph |
assertRendersChildType(result, constructor) | 斷言輸出包含指定 docx 型別 |
assertRendersChildType(result, constructor, count) | 斷言輸出包含某型別的 N 個實例 |
assertPluginDefined(plugin) | 斷言外掛結構有效(name + render) |
assertPluginDefined(plugin, name) | 斷言外掛名稱匹配 |
發佈到 npm
建置外掛:
bashpnpm run build添加發現關鍵字:
在
package.json的 keywords 中添加docx-kit-plugin:json{ "keywords": ["docx-kit-plugin", "chart"] }發佈:
bashnpm publish --access public驗證外掛發現:
發佈後,外掛應出現在登錄服務搜尋中:
tsimport { createPluginRegistry } from 'docx-kit/registry' const registry = createPluginRegistry() const results = await registry.search('chart')
整合:在文件中使用外掛
使用者透過 builder.use() 註冊外掛:
import { createDocx } from 'docx-kit'
import { chartPlugin } from 'docx-kit-plugin-chart'
const doc = createDocx()
.use(chartPlugin()) // Register the plugin
.chart({ // Use the plugin DSL method
data: [10, 20, 30],
title: 'Revenue Chart',
type: 'bar',
})也可以透過 JSON schema 註冊:
import { renderDocx } from 'docx-kit'
const builder = await renderDocx({
plugins: [{ plugin: chartPlugin(), type: 'inline' }],
content: [
{ type: 'plugin', name: 'chart', options: { data: [10, 20, 30], title: 'Chart', type: 'bar' } },
],
})外掛載入
從 npm、URL 或本地檔案載入外部外掛:
import { createPluginLoader } from 'docx-kit/loader/node' // Node.js
// import { createPluginLoader } from 'docx-kit/loader/browser' // Browser
const loader = createPluginLoader()
// From npm
const { plugin } = await loader.load({
type: 'npm',
package: 'docx-kit-plugin-chart',
})
// From URL (browser only)
const { plugin } = await loader.load({
type: 'url',
url: 'https://cdn.example.com/docx-kit-plugin-chart/docx-kit.plugin.json',
})
// From local file
const { plugin } = await loader.load({
type: 'local',
path: './my-plugins/chart.js',
})
// Then register
doc.use(plugin)