Node API
Tiptap 的强大之处在于它的灵活性。你可以从零开始创建自己的扩展,构建量身定制的独特编辑体验。
创建一个节点
节点是你编辑器的基本构建块。它们可以是块节点或行内节点。好的学习实例包括 Paragraph、Heading 或 CodeBlock。
它们扩展了 扩展 API 的所有选项和方法,并添加了一些特定于节点的选项。
让我们添加一个简单的节点扩展,看看它是如何工作的。
import { Node } from '@tiptap/core'
const CustomNode = Node.create({
name: 'customNode',
addOptions() {
return {
HTMLAttributes: {},
}
},
parseHTML() {
return [
{
tag: 'div',
},
]
},
renderHTML({ HTMLAttributes }) {
return ['div', HTMLAttributes, 0]
},
})你也可以使用回调函数来创建节点。如果你想封装扩展的逻辑,比如定义事件处理程序或其他自定义逻辑,这非常有用。
import { Node } from '@tiptap/core'
const CustomNode = Node.create(() => {
// 你可以在这里定义变量或函数,用于你的架构定义
const customVariable = 'foo'
function onCreate() {}
function onUpdate() {}
return {
name: 'customNode',
onCreate,
onUpdate,
// 你的代码写在这里。
}
})这段代码创建了一个名为 CustomNode 的新节点扩展。它添加了一个 addOptions 方法来定义节点的选项,这些选项可由用户配置。同时它还添加了 parseHTML 和 renderHTML 方法,定义节点如何解析和渲染为 HTML。
安装到编辑器时,与其他扩展一样,将其添加到 extensions 数组中。
import { Editor } from '@tiptap/core'
new Editor({
extensions: [CustomNode],
})
// 或者如果使用 React 或 Vue
const editor = useEditor({
extensions: [CustomNode],
})现在让我们仔细看看可用于节点的选项和方法。
节点选项
创建一个节点时,可以定义可由用户配置的选项。这些选项可用于自定义节点的行为或外观。
parseHTML
parseHTML 方法用于定义如何从 HTML 中解析标记。它应该返回一个数组,表示标记的属性。
将映射到 ProseMirror 架构 中的 parseDOM 属性。
const CustomMark = Mark.create({
name: 'customMark',
parseHTML() {
return [
{
tag: 'span',
getAttrs: (node) => {
return {
class: node.getAttribute('class'),
}
},
},
]
},
})这将在粘贴事件期间用于将 HTML 内容解析为标记。
renderHTML
renderHTML 方法用于定义如何将标记渲染为 HTML。它应该返回一个表示标记 HTML 表示的数组。
将映射到 ProseMirror 架构 中的 toDOM 属性。
const CustomMark = Mark.create({
name: 'customMark',
renderHTML({ HTMLAttributes }) {
return ['span', HTMLAttributes, 0]
},
})这将在复制事件期间用于将标记渲染为 HTML。更多细节请参见 扩展现有扩展 指南。
addAttributes
addAttributes 方法用于定义标记的自定义属性。它应该返回一个包含属性名称及其默认值的对象。
将映射到 ProseMirror 架构 中的 attrs 属性。
const CustomMark = Mark.create({
name: 'customMark',
addAttributes() {
return {
customAttribute: {
default: 'value',
parseHTML: (element) => element.getAttribute('data-custom-attribute'),
},
}
},
})有关更多细节,请参见 扩展现有扩展 指南。
topNode
定义此节点是否应为顶级节点(文档)。
将映射到 ProseMirror 架构 中的 topNode 属性。
const CustomNode = Node.create({
name: 'customNode',
topNode: true,
})content
该节点的内容表达式,如 架构指南 所述。如果未给定,则该节点不允许任何内容。
你可以在 Prosemirror 文档中阅读更多内容 这里。
const CustomNode = Node.create({
name: 'customNode',
content: 'block+',
})marks
该节点内允许的标记。可以是指向标记名称或组的空格分隔字符串,"_" 明确允许所有标记,或 "" 禁止标记。如果未给定,具有行内内容的节点默认允许所有标记,其他节点默认不允许标记。
将映射到 ProseMirror 架构 中的 marks 属性。
const CustomNode = Node.create({
name: 'customNode',
marks: 'strong em',
})group
该节点所属的组或用空格分隔的组,可以在架构的内容表达式中引用。
默认情况下,Tiptap 将 block 和 inline 作为节点的组。如果你想将特定节点分组并在架构中处理它们,也可以使用自定义组。
将映射到 ProseMirror 架构 中的 group 属性。
const CustomNode = Node.create({
name: 'customNode',
group: 'block',
})inline
此属性应该设置为 true ,以表示行内节点。(对文本节点是隐含的)。
将映射到 ProseMirror 架构 中的 inline 属性。
const CustomNode = Node.create({
name: 'customNode',
inline: true,
})atom
可以设置为 true,以指示虽然这不是一个 叶节点,但它没有直接可编辑的内容,应视为视图中的一个单元。
将映射到 ProseMirror 架构 中的 atom 属性。
const CustomNode = Node.create({
name: 'customNode',
atom: true,
})selectable
控制该类型的节点是否可以被选中作为 节点选择。默认情况下,对于非文本节点为 true。
将映射到 ProseMirror 架构 中的 selectable 属性。
const CustomNode = Node.create({
name: 'customNode',
selectable: false,
})draggable
确定该类型的节点是否可以在不被选中的情况下拖动。默认值为 false。
将映射到 ProseMirror 架构 中的 draggable 属性。
const CustomNode = Node.create({
name: 'customNode',
draggable: true,
})code
可以用于指示此节点包含代码,这会导致某些命令表现得不同。
将映射到 ProseMirror 架构 中的 code 属性。
const CustomNode = Node.create({
name: 'customNode',
code: true,
})whitespace
控制该节点中空格的解析方式。默认值为 "normal",这会导致 DOM 解析器 在正常模式下折叠空格,其他情况则标准化(用空格替换换行等)。"pre" 则使解析器保留节点内的空格。如果未给定此选项,但 code 为 true,则 whitespace 默认值为 "pre"。
将映射到 ProseMirror 架构 中的 whitespace 属性。
const CustomNode = Node.create({
name: 'customNode',
whitespace: 'pre',
})linebreakReplacement
允许将 单个 节点设置为换行等价物(例如 hardBreak)。在转换具有空格设置为 "pre" 并且不支持换行节点(例如 codeBlock)与支持换行节点的其他块类型(例如段落)之间进行转换时,将使用此节点作为换行,而不是删除换行符。
将映射到 ProseMirror 架构 中的 linebreakReplacement 属性。
const CustomNode = Node.create({
name: 'customNode',
linebreakReplacement: true,
})defining
启用时,同时启用 definingAsContext 和 definingForContent。
将映射到 ProseMirror 架构 中的 defining 属性。
const CustomNode = Node.create({
name: 'customNode',
defining: true,
})isolating
启用时(默认值为 false),该类型节点的两侧视为边界,常规编辑操作(如退格或提升)不会穿越。一个应该启用此功能的节点示例是表格单元。
将映射到 ProseMirror 架构 中的 isolating 属性。
const CustomNode = Node.create({
name: 'customNode',
isolating: true,
})addNodeView(高级)
对于高级用例,比如需要在节点内部执行 JavaScript,例如渲染一个围绕图像的复杂界面,你需要了解节点视图。
它们非常强大,但也很复杂。简单来说,你需要返回一个父 DOM 元素和一个内容应该渲染到的 DOM 元素。查看以下简化示例:
import Image from '@tiptap/extension-image'
const CustomImage = Image.extend({
addNodeView() {
return () => {
const container = document.createElement('div')
container.addEventListener('click', (event) => {
alert('点击了容器')
})
const content = document.createElement('div')
container.append(content)
return {
dom: container,
contentDOM: content,
}
}
},
})关于节点视图有很多内容需要学习,因此请前往我们指南中关于节点视图的 专门部分 获取更多信息。如果你正在寻找一个实际的例子,查看 TaskItem 节点的源代码。这个节点使用节点视图来渲染复选框。