导出自定义节点为 .odt
Available in Start planBetav0.4.0
@tiptap-pro/extension-export-odt 扩展支持自定义节点转换,允许您定义在 Tiptap 方案中的自定义节点如何在 ODT 导出中渲染。
需要导出 DOCX 扩展
ODT 导出的自定义节点转换需要 @tiptap-pro/extension-export-docx 扩展已安装并在编辑器中配置。ODT 导出底层使用 DOCX 生成后再转换为 ODT。若未安装,customNodes 选项将无效。
导出自定义节点为 .odt
在配置 ExportOdt 时,通过 customNodes 选项传递您的自定义节点定义:
import { ExportOdt } from '@tiptap-pro/extension-export-odt'
import { ExportDocx } from '@tiptap-pro/extension-export-docx'
const editor = new Editor({
extensions: [
ExportDocx,
ExportOdt.configure({
token: 'YOUR_TOKEN',
appId: 'YOUR_APP_ID',
customNodes: [
{
type: 'hintbox',
render: node => {
// 定义您的自定义节点如何在文档中渲染
},
},
],
onCompleteExport(result) {
// 处理导出的 ODT
},
}),
],
})自定义节点约定
自定义节点转换器必须遵守底层 DOCX 生成库的要求。在实践中,DOCX 的自定义转换函数应返回该节点允许的 DOCX 元素之一:Paragraph 类(或 Paragraph 类的数组)、Table 类、TextRun 类、ExternalHyperlink 类,或者如果该节点应在输出中跳过,则返回 null。
定义自定义节点扩展
举例来说,假设你的编辑器有一个自定义节点类型 hintbox(一个带有提示样式的框)。你可以定义它在导出文档中应如何显示。
下面是 Hintbox 扩展的自定义节点示例:
import { mergeAttributes, Node } from '@tiptap/core'
export interface ParagraphOptions {
/**
* 段落节点的 HTML 属性。
* @default {}
* @example { class: 'foo' }
*/
HTMLAttributes: Record<string, any>
}
declare module '@tiptap/core' {
interface Commands<ReturnType> {
hintbox: {
/**
* 设置一个提示框
* @example editor.commands.setHintbox()
*/
setHintbox: () => ReturnType
/**
* 切换一个提示框
* @example editor.commands.toggleHintbox()
*/
toggleHintbox: () => ReturnType
}
}
}
/**
* 该扩展允许你创建提示框。
* @see https://www.tiptap.dev/api/nodes/paragraph
*/
export const Hintbox = Node.create<ParagraphOptions>({
name: 'hintbox',
priority: 1000,
addOptions() {
return {
HTMLAttributes: {
style: 'padding: 20px; border: 1px solid #b8d8ff; border-radius: 5px; background-color: #e6f3ff;',
},
}
},
group: 'block',
content: 'inline*',
parseHTML() {
return [{ tag: 'p' }]
},
renderHTML({ HTMLAttributes }) {
return ['p', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]
},
addCommands() {
return {
setHintbox:
() =>
({ commands }) => {
return commands.setNode(this.name)
},
toggleHintbox:
() =>
({ commands }) => {
return commands.toggleNode(this.name, 'paragraph')
},
}
},
addKeyboardShortcuts() {
return {
'Mod-Alt-h': () => this.editor.commands.toggleHintbox(),
}
},
})定义自定义节点的渲染函数
我们来定义如何在导出文档中渲染 Hintbox 自定义节点:
import { ExportOdt } from '@tiptap-pro/extension-export-odt'
import {
convertTextNode,
Docx,
ExportDocx,
lineHeightToDocx,
pixelsToHalfPoints,
pointsToTwips,
} from '@tiptap-pro/extension-export-docx'
const editor = new Editor({
extensions: [
// 其他扩展 ...
ExportDocx,
ExportOdt.configure({
token: 'YOUR_TOKEN',
appId: 'YOUR_APP_ID',
onCompleteExport: result => {
const url = URL.createObjectURL(result)
const a = document.createElement('a')
a.href = url
a.download = 'export.odt'
a.click()
URL.revokeObjectURL(url)
},
customNodes: [
{
type: 'hintbox',
render: node => {
return new Docx.Paragraph({
children: node.content.map(content => convertTextNode(content)),
style: 'Hintbox',
})
},
},
],
styleOverrides: {
paragraphStyles: [
{
id: 'Hintbox',
name: 'Hintbox',
basedOn: 'Normal',
next: 'Normal',
quickFormat: false,
run: {
font: 'Aptos Light',
size: pixelsToHalfPoints(16),
},
paragraph: {
spacing: {
before: pointsToTwips(12),
after: pointsToTwips(12),
line: lineHeightToDocx(1),
},
border: {
top: { style: Docx.BorderStyle.SINGLE, size: 1, color: 'b8d8ff', space: 5 },
bottom: { style: Docx.BorderStyle.SINGLE, size: 1, color: 'b8d8ff', space: 5 },
right: { style: Docx.BorderStyle.SINGLE, size: 1, color: 'b8d8ff', space: 5 },
left: { style: Docx.BorderStyle.SINGLE, size: 1, color: 'b8d8ff', space: 5 },
},
shading: {
type: Docx.ShadingType.SOLID,
color: 'e6f3ff',
},
},
},
],
},
}),
// 其他扩展 ...
],
})您可以在 render 函数中使用由 @tiptap-pro/extension-export-docx 包提供的 Docx 导入所包含的 Docx 库类(如 Paragraph、TextRun、Table 等)构造任意支持的 DOCX 元素。