探索 Tiptap V3 的最新功能

Mark API

Tiptap 的强大之处在于其灵活性。你可以从零开始创建自己的扩展,构建符合你需求的独特编辑体验。

创建标记

标记用于在 Tiptap 中给文本添加内联格式。常见的示例包括加粗、斜体和下划线格式。

它们继承了 Extension API 中所有选项和方法,并添加了一些特定于标记的内容。

让我们添加一个简单的标记扩展,看看它是如何工作的。

import { Mark } from '@tiptap/core'

const HighlightMark = Mark.create({
  name: 'highlight',

  addOptions() {
    return {
      HTMLAttributes: {},
    }
  },

  parseHTML() {
    return [
      {
        tag: 'mark',
      },
    ]
  },

  renderHTML({ HTMLAttributes }) {
    return ['mark', HTMLAttributes, 0]
  },
})

你也可以使用回调函数来创建标记。如果你想封装扩展的逻辑,比如定义事件处理器或其他自定义逻辑,这将非常有用。

import { Mark } from '@tiptap/core'

const CustomMark = Mark.create(() => {
  // 定义变量或函数供扩展内部使用
  const customVariable = 'foo'

  function onCreate() {}
  function onUpdate() {}

  return {
    name: 'customMark',
    onCreate,
    onUpdate,

    // 你的代码写在这里。
  }
})

这段代码创建了一个名为 HighlightMark 的新标记扩展。它添加了一个 addOptions 方法来定义标记的选项,这些选项可以由用户配置。它还添加了 parseHTMLrenderHTML 方法,来定义标记如何被解析和渲染为 HTML。

它的安装方式与其他扩展一样,通过将其添加到 extensions 数组中。

import { Editor } from '@tiptap/core'

new Editor({
  extensions: [HighlightMark],
})

// 或者如果使用 React 或 Vue

const editor = useEditor({
  extensions: [HighlightMark],
})

现在让我们仔细看看标记可用的选项和方法。

标记选项

创建标记扩展时,你可以定义用户可配置的选项。通过这些选项可以自定义标记的行为或外观。

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'),
      },
    }
  },
})

更多详情请见 扩展已有扩展 指南。

keepOnSplit

默认情况下,当节点被拆分时,标记会从内容中移除。你可以将 keepOnSplit 设置为 true 来保持标记在新节点上。

const CustomMark = Mark.create({
  name: 'customMark',

  keepOnSplit: true,
})

inclusive

默认情况下,标记不是包容性的,意味着不能应用于节点的开始或结束。你可以将 inclusive 设置为 true 以允许标记应用于节点的开始或结束。

对应于 ProseMirror 规范 中的 inclusive 属性。

const CustomMark = Mark.create({
  name: 'customMark',

  inclusive: true,
})

excludes

默认情况下,标记不会排斥其他标记。你可以定义一个标记列表,当应用此标记时,这些标记应被排除。

对应于 ProseMirror 规范 中的 excludes 属性。

const CustomMark = Mark.create({
  name: 'customMark',

  excludes: ['bold', 'italic'],
})

exitable

默认情况下,标记不可退出,意味着不能通过在标记起始处按退格键来移除标记。你可以将 exitable 设置为 true 以允许以此方式移除标记。

对应于 ProseMirror 规范 中的 exitable 属性。

const CustomMark = Mark.create({
  name: 'customMark',

  exitable: true,
})

group

默认情况下,标记不属于任何组,意味着它们单独应用。你可以为标记定义一个组,以确保同一时间只能应用该组中的一个标记。

对应于 ProseMirror 规范 中的 group 属性。

const CustomMark = Mark.create({
  name: 'customMark',

  group: 'textStyle',
})

spanning

默认情况下,标记不会跨越多个节点。你可以将 spanning 设置为 true 以允许标记跨越多个节点。

对应于 ProseMirror 规范 中的 spanning 属性。

const CustomMark = Mark.create({
  name: 'customMark',

  spanning: true,
})

code

默认情况下,标记不被视为代码标记。你可以将 code 设置为 true 将标记视为代码标记。

对应于 ProseMirror 规范 中的 code 属性。

const CustomMark = Mark.create({
  name: 'customMark',

  code: true,
})