创建新标记

创建标记扩展

标记用于在 Tiptap 中为文本添加行内格式。常见例子包括粗体、斜体和下划线格式。让我们逐步学习如何创建我们自己的标记扩展。

可以在 标记 API 中找到可用选项。

基本结构

首先,我们需要创建标记扩展的基本结构:

// 文件路径: src/HighlightMark.ts
import { Mark } from '@tiptap/core'

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

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

export default HighlightMark

我们在这里做了以下操作:

  • 创建了一个名为 HighlightMark 的新标记扩展
  • 添加了一个 addOptions 方法,以定义用户可配置的标记选项

添加样式

通过定义标记如何渲染和解析 HTML,来添加样式功能:

// 文件路径: src/HighlightMark.ts
const HighlightMark = Mark.create({
  // ...现有代码...

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

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

添加属性

通过添加可自定义的属性,使我们的标记更加灵活:

// 文件路径: src/HighlightMark.ts
const HighlightMark = Mark.create({
  // ...现有代码...

  addAttributes() {
    return {
      color: {
        default: 'yellow',
        parseHTML: (element) => element.getAttribute('data-color'),
        renderHTML: (attributes) => ({
          'data-color': attributes.color,
          style: `background-color: ${attributes.color}`,
        }),
      },
    }
  },
})

添加命令

通过命令使标记具互动性:

// 文件路径: src/HighlightMark.ts

// 我们需要扩展命令接口,以将自定义命令添加到编辑器
declare module '@tiptap/core' {
  interface Commands<ReturnType> {
    setHighlight: (attributes: { color: string }) => ReturnType
    toggleHighlight: (attributes: { color: string }) => ReturnType
    unsetHighlight: () => ReturnType
  }
}

const HighlightMark = Mark.create({
  // ...现有代码...

  addCommands() {
    return {
      setHighlight:
        (attributes) =>
        ({ commands }) => {
          return commands.setMark(this.name, attributes)
        },
      toggleHighlight:
        (attributes) =>
        ({ commands }) => {
          return commands.toggleMark(this.name, attributes)
        },
      unsetHighlight:
        () =>
        ({ commands }) => {
          return commands.unsetMark(this.name)
        },
    }
  },
})

这增加了可以在编辑器实例上使用的命令,例如:

  • editor.commands.setHighlight({ color: 'pink' }) 使用命令 API
  • editor.chain().toggleHighlight().run() 使用链式 API

添加键盘快捷键

为快速格式化添加键盘快捷键:

// 文件路径: src/HighlightMark.ts
const HighlightMark = Mark.create({
  // ...现有代码...

  addKeyboardShortcuts() {
    return {
      'Mod-h': () => this.editor.commands.toggleHighlight(),
    }
  },
})

添加输入规则

支持 Markdown 风格的语法:

// 文件路径: src/HighlightMark.ts
import { markInputRule } from '@tiptap/core'

const HighlightMark = Mark.create({
  // ...现有代码...

  addInputRules() {
    return [
      markInputRule({
        find: /(?:==)((?:[^=]+))(?:==)$/,
        type: this.type,
      }),
    ]
  },
})

使用标记

以下是如何使用您的新标记扩展:

// 文件路径: src/Editor.ts
import { Editor } from '@tiptap/core'
import HighlightMark from './HighlightMark'

new Editor({
  extensions: [
    HighlightMark,
    // ... 其他扩展
  ],
})

现在您可以:

  • 使用 ==文本== 来突出显示文本(输入规则)
  • 按 Cmd+H(Windows 上为 Ctrl+H)切换高亮显示
  • 通过编程控制高亮显示:
    editor.commands.setHighlight({ color: 'pink' })
    editor.commands.toggleHighlight()
    editor.commands.unsetHighlight()

测试

创建测试以确保您的标记按预期工作:

// 文件路径: src/HighlightMark.test.ts
import { Editor } from '@tiptap/core'
import HighlightMark from './HighlightMark'

describe('HighlightMark', () => {
  let editor: Editor

  beforeEach(() => {
    editor = new Editor({
      extensions: [HighlightMark],
      content: '',
    })
  })

  test('可以切换高亮信息', () => {
    editor.commands.setContent('测试')
    editor.commands.selectAll()
    editor.commands.toggleHighlight()

    expect(editor.getHTML()).toBe('<mark>测试</mark>')
  })
})

这个标记扩展提供了一个基础,您可以在其上构建以满足您的特定用例。您可以通过添加更多属性、命令或更改它在编辑器中的渲染方式进一步扩展它。