---
title: "Mark API"
description: "为你的 Tiptap 编辑器创建一个新的标记，从零打造独特的编辑器体验。详情请参阅文档！"
canonical_url: "https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/create-new/mark"
---

# Mark API

为你的 Tiptap 编辑器创建一个新的标记，从零打造独特的编辑器体验。详情请参阅文档！

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

## 创建标记

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

它们继承了 [Extension API](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/create-new/extension.md) 中所有选项和方法，并添加了一些特定于标记的内容。

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

```typescript
import { Mark } from '@tiptap/core'

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

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

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

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

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

```js
import { Mark } from '@tiptap/core'

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

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

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

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

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

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

```typescript
import { Editor } from '@tiptap/core'

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

// 或者如果使用 React 或 Vue

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

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

## 标记选项

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

### `parseHTML`

`parseHTML` 方法用于定义如何从 HTML 解析标记。它应该返回一个对象数组，表示标记的属性。

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.parseDOM) 中的 `parseDOM` 属性。

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

  parseHTML() {
    return [
      {
        tag: 'span',
        getAttrs: (node) => {
          return {
            class: node.getAttribute('class'),
          }
        },
      },
    ]
  },
})
```

它将在粘贴事件时用于解析 HTML 内容为标记。

### `renderHTML`

`renderHTML` 方法用于定义标记如何渲染为 HTML。它应该返回一个数组，表示标记的 HTML 表现。

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.toDOM) 中的 `toDOM` 属性。

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

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

它将在复制事件时用于将标记渲染为 HTML。更多详情请见 [扩展已有扩展](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/extend-existing.md#render-html) 指南。

### `addAttributes`

`addAttributes` 方法用于定义标记的自定义属性。它应该返回一个包含属性名和默认值的对象。

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.attrs) 中的 `attrs` 属性。

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

  addAttributes() {
    return {
      customAttribute: {
        default: 'value',
        parseHTML: (element) => element.getAttribute('data-custom-attribute'),
      },
    }
  },
})
```

更多详情请见 [扩展已有扩展](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/extend-existing.md#rattributes) 指南。

### `keepOnSplit`

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

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

  keepOnSplit: true,
})
```

### `inclusive`

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

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.inclusive) 中的 `inclusive` 属性。

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

  inclusive: true,
})
```

### `excludes`

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

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) 中的 `excludes` 属性。

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

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

### `exitable`

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

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.exitable) 中的 `exitable` 属性。

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

  exitable: true,
})
```

### `group`

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

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.group) 中的 `group` 属性。

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

  group: 'textStyle',
})
```

### `spanning`

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

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.spanning) 中的 `spanning` 属性。

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

  spanning: true,
})
```

### `code`

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

对应于 [ProseMirror 规范](https://prosemirror.net/docs/ref/#model.MarkSpec.code) 中的 `code` 属性。

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

  code: true,
})
```

### `clearable`

默认情况下，可以使用 `unsetAllMarks` 命令移除标记。你可以将 `clearable` 设置为 `false`，以保护标记不被 `unsetAllMarks` 移除。`unsetMark` 命令不受影响——只有 `unsetAllMarks` 会遵守此选项。

你也可以使用回调函数，根据编辑器状态动态判断是否可以清除标记。

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

  // 此标记不会被 unsetAllMarks 移除
  clearable: false,
})
```

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

  // 动态判断是否可以清除该标记
  clearable: () => {
    return editor.state.doc.textContent.length < 100
  },
})
```

默认为 `true`。
