📝 Sign Up | 🔐 Log In

← Root | ↑ Up

┌────────────────────────────────────────────────────────────┐ │ 📄 shadcn/directory/udecode/plate/(guides)/plugin-rules.cn │ └────────────────────────────────────────────────────────────┘

╔══════════════════════════════════════════════════════════════════════════════════════════════╗
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║

title: 插件规则 description: 配眮垞见的猖蟑行䞺。

插件规则控制猖蟑噚节点劂䜕响应垞见的甚户操䜜。悚可以盎接圚插件的 rules 属性䞊配眮这些行䞺而无需重写猖蟑噚方法。

本指南展瀺劂䜕䜿甚 rules.break、rules.delete、rules.merge、rules.normalize、rules.selection 和 rules.match 来创建盎观的猖蟑䜓验。

<ComponentPreview name="plugin-rules-demo" />

操䜜类型

插件规则䜿甚特定的操䜜名称来定义行䞺

  • 'default': Slate 的默讀行䞺。
  • 'reset': 将圓前块重眮䞺默讀段萜保留内容。
  • 'exit': 退出圓前块结构圚其后插入新段萜。诊见 Exit Break 了解歀行䞺的曎倚信息。
  • 'deleteExit': 删陀内容后退出块。
  • 'lineBreak': 插入换行笊 (\n) 而非拆分块。

default

标准 Slate 行䞺。对于 rules.break 䌚拆分块对于 rules.delete 䌚䞎前䞀䞪块合并。

<p>
  Hello world|
</p>

按䞋 Enter 后

<p>Hello world</p>
<p>
  |
</p>

按䞋 Backspace 后

<p>Hello world|</p>

reset

将圓前块蜬换䞺默讀段萜同时保留内容。自定义属性将被移陀。

<h3 listStyleType="disc">
  |
</h3>

配眮 rules: { break: { empty: 'reset' } } 后按䞋 Enter

<p>
  |
</p>

exit

通过圚其后插入新段萜来退出圓前块结构。

<blockquote>
  |
</blockquote>

配眮 rules: { break: { empty: 'exit' } } 后按䞋 Enter

<blockquote>
  <text />
</blockquote>
<p>
  |
</p>

deleteExit

删陀内容后退出块。

<blockquote>
  line1
  |
</blockquote>

配眮 rules: { break: { emptyLineEnd: 'deleteExit' } } 后按䞋 Enter

<blockquote>line1</blockquote>
<p>
  |
</p>

lineBreak

插入蜯换行笊 (\n) 而非拆分块。

<blockquote>
  Hello|
</blockquote>

配眮 rules: { break: { default: 'lineBreak' } } 后按䞋 Enter

<blockquote>
  Hello
  |
</blockquote>

rules.break

控制甚户圚特定块类型内按䞋 Enter 时的行䞺。

配眮

BlockquotePlugin.configure({
  rules: {
    break: {
      // 正垞按䞋 Enter 时的操䜜
      default: 'default' | 'lineBreak' | 'exit' | 'deleteExit',
      
      // 圚空块䞭按䞋 Enter 时的操䜜
      empty: 'default' | 'reset' | 'exit' | 'deleteExit',
      
      // 圚空行末尟按䞋 Enter 时的操䜜
      emptyLineEnd: 'default' | 'exit' | 'deleteExit',

      // 劂果䞺 true拆分后的新块将被重眮
      splitReset: boolean,
    },
  },
});

每䞪属性控制特定场景

瀺䟋

标题拆分时重眮

import { H1Plugin } from '@platejs/heading/react';

const plugins = [
  // ...其他插件
  H1Plugin.configure({
    rules: {
      break: {
        splitReset: true,
      },
    },
  }),
];

按䞋 Enter 前

<h1>
  Heading|text
</h1>

按䞋后拆分并重眮

<h1>
  Heading
</h1>
<p>
  |text
</p>

垊换行和智胜退出的块匕甚

import { BlockquotePlugin } from '@platejs/basic-nodes/react';

const plugins = [
  // ...其他插件
  BlockquotePlugin.configure({
    rules: {
      break: {
        default: 'lineBreak',
        empty: 'reset',
        emptyLineEnd: 'deleteExit',
      },
    },
  }),
];

圚块匕甚䞭按䞋 Enter 前

<blockquote>
  Quote text|
</blockquote>

按䞋后换行

<blockquote>
  Quote text
  |
</blockquote>

垊自定义空块倄理的代码块

import { CodeBlockPlugin } from '@platejs/code-block/react';

const plugins = [
  // ...其他插件
  CodeBlockPlugin.configure({
    rules: {
      delete: { empty: 'reset' },
      match: ({ editor, rule }) => {
        return rule === 'delete.empty' && isCodeBlockEmpty(editor);
      },
    },
  }),
];

圚空代码块䞭按䞋 Backspace 前

<code_block>
  <code_line>
    |
  </code_line>
</code_block>

按䞋后重眮

<p>
  |
</p>

rules.delete

控制甚户圚特定䜍眮按䞋 Backspace 时的行䞺。

配眮

HeadingPlugin.configure({
  rules: {
    delete: {
      // 圚块起始倄按䞋 Backspace 时的操䜜
      start: 'default' | 'reset',
      
      // 圚空块䞭按䞋 Backspace 时的操䜜
      empty: 'default' | 'reset',
    },
  },
});

每䞪属性控制特定场景

瀺䟋

圚起始倄重眮块匕甚

import { BlockquotePlugin } from '@platejs/basic-nodes/react';

const plugins = [
  // ...其他插件
  BlockquotePlugin.configure({
    rules: {
      delete: { start: 'reset' },
    },
  }),
];

圚起始倄按䞋 Backspace 前

<blockquote>
  |Quote content
</blockquote>

按䞋后重眮

<p>
  |Quote content
</p>

垊起始重眮的列衚项

import { ListPlugin } from '@platejs/list/react';

const plugins = [
  // ...其他插件
  ListPlugin.configure({
    rules: {
      delete: { start: 'reset' },
      match: ({ rule, node }) => {
        return rule === 'delete.start' && Boolean(node.listStyleType);
      },
    },
  }),
];

圚列衚项起始倄按䞋 Backspace 前

<p listStyleType="disc">
  |List item content
</p>

按䞋后重眮

<p>
  |List item content
</p>

rules.merge

控制块䞎前䞀䞪块合并时的行䞺。

配眮

ParagraphPlugin.configure({
  rules: {
    merge: {
      // 合并时是吊移陀空块
      removeEmpty: boolean,
    },
  },
});

瀺䟋

默讀情况䞋只有段萜和标题插件启甚移陀功胜。倧倚数其他插件䜿甚 false

import { H1Plugin, ParagraphPlugin } from 'platejs/react';

const plugins = [
  // ...其他插件
  H1Plugin, // 默讀 rules.merge: { removeEmpty: true }
  ParagraphPlugin, // 默讀 rules.merge: { removeEmpty: true }
];

圚起始倄按䞋 Backspace 前

<p>
  <text />
</p>
<h1>
  |Heading content
</h1>

按䞋后空段萜被移陀

<h1>
  |Heading content
</h1>

犁甚移陀的块匕甚

import { BlockquotePlugin } from '@platejs/basic-nodes/react';

const plugins = [
  // ...其他插件
  BlockquotePlugin.configure({
    rules: {
      merge: { removeEmpty: false }, // 默讀
    },
  }),
];

圚起始倄按䞋 Backspace 前

<p>
  <text />
</p>
<blockquote>
  |Code content
</blockquote>

按䞋后保留空段萜

<p>
  |Code content
</p>

衚栌单元栌圚合并时保留结构

import { TablePlugin } from '@platejs/table/react';

const plugins = [
  // ...其他插件
  TablePlugin, // 衚栌单元栌有 rules.merge: { removeEmpty: false }
];

圚段萜末尟按䞋 Delete 前

<p>
  Content|
</p>
<table>
  <tr>
    <td>
      <p>Cell data</p>
    </td>
    <td>
      <p>More data</p>
    </td>
  </tr>
</table>

按䞋后合并单元栌内容保留结构

<p>
  Content|Cell data
</p>
<table>
  <tr>
    <td>
      <p>
        <text />
      </p>
    </td>
    <td>
      <p>More data</p>
    </td>
  </tr>
</table>
<Callout> Slate 的默讀倌䞺 `true`因䞺默讀块段萜是䞀等公民而 Plate 插件埈可胜甚于定义其他节点行䞺这些行䞺䞍应自劚移陀空的前驱块。 </Callout>

rules.normalize

控制圚规范化过皋䞭劂䜕规范化节点。

配眮

LinkPlugin.configure({
  rules: {
    normalize: {
      // 是吊移陀空文本节点
      removeEmpty: boolean,
    },
  },
});

瀺䟋

移陀空铟接节点

import { LinkPlugin } from '@platejs/link/react';

const plugins = [
  // ...其他插件
  LinkPlugin.configure({
    rules: {
      normalize: { removeEmpty: true },
    },
  }),
];

规范化前

<p>
  <a href="http://google.com">
    <text />
  </a>
  <cursor />
</p>

规范化后移陀空铟接

<p>
  <cursor />
</p>

rules.match

插件规则䞭的 match 凜数允讞悚基于节点属性而䞍仅仅是类型匹配芆盖特定插件的默讀行䞺。这圚悚想䞺现有节点类型扩展新行䞺时特别有甚。

瀺䟋

垊自定义空块检测的代码块

import { CodeBlockPlugin } from '@platejs/code-block/react';

const plugins = [
  // ...其他插件
  CodeBlockPlugin.configure({
    rules: {
      delete: { empty: 'reset' },
      match: ({ rule, node }) => {
        return rule === 'delete.empty' && isCodeBlockEmpty(editor);
      },
    },
  }),
];

由于列衚插件扩展了已有自己的插件配眮的现有块劂 ParagraphPlugin䜿甚 rules.match 允讞悚芆盖这些行䞺。

段萜的列衚芆盖

import { ListPlugin } from '@platejs/list/react';

const plugins = [
  // ...其他插件
  ListPlugin.configure({
    rules: {
      match: ({ editor, rule }) => {
        return rule === 'delete.empty' && isCodeBlockEmpty(editor);
      },
    },
  }),
];

自定义重眮逻蟑

某些插件需芁超出标准段萜蜬换的特殊重眮行䞺。悚可以芆盖 resetBlock 蜬换

列衚插件重眮猩进而非蜬换䞺段萜

const ListPlugin = createPlatePlugin({
  key: 'list',
  // ... 其他配眮
}).overrideEditor(({ editor, tf: { resetBlock } }) => ({
  transforms: {
    resetBlock(options) {
      if (editor.api.block(options)?.[0]?.listStyleType) {
        outdentList();
        return;
      }
      
      return resetBlock(options);
    },
  },
}));

代码块重眮解包而非蜬换

const CodeBlockPlugin = createPlatePlugin({
  key: 'code_block',
  // ... 其他配眮
}).overrideEditor(({ editor, tf: { resetBlock } }) => ({
  transforms: {
    resetBlock(options) {
      if (editor.api.block({
        at: options?.at,
        match: { type: 'code_block' },
      })) {
        unwrapCodeBlock();
        return;
      }
      
      return resetBlock(options);
    },
  },
}));

组合规则

悚可以组合䞍同的规则来实现党面的块行䞺

import { H1Plugin } from '@platejs/heading/react';

const plugins = [
  // ...其他插件
  H1Plugin.configure({
    rules: {
      break: {
        empty: 'reset',
        splitReset: true,
      },
      delete: {
        start: 'reset',
      },
    },
  }),
];

换行行䞺默讀

<blockquote>
  Hello|
</blockquote>

按䞋 Enter 后

<blockquote>
  Hello
  |
</blockquote>

空块重眮行䞺

<blockquote>
  |
</blockquote>

按䞋 Enter 后

<p>
  |
</p>

起始倄重眮行䞺

<blockquote>
  |Quote content
</blockquote>

按䞋 Backspace 后

<p>
  |Quote content
</p>

高级甚法

对于超出简单规则的倍杂场景悚可以盎接䜿甚 .overrideEditor 芆盖猖蟑噚蜬换。这䜿悚可以完党控制 resetBlock 和 insertExitBreak 等蜬换

const CustomPlugin = createPlatePlugin({
  key: 'custom',
  // ... 其他配眮
}).overrideEditor(({ editor, tf: { insertBreak, deleteBackward, resetBlock } }) => ({
  transforms: {
    insertBreak() {
      const block = editor.api.block();
      
      if (/* 自定义条件 */) {
        // 自定义行䞺
        return;
      }
      
      // 默讀行䞺
      insertBreak();
    },
    
    deleteBackward(unit) {
      const block = editor.api.block();
      
      if (/* 自定义条件 */) {
        // 自定义行䞺
        return;
      }
      
      deleteBackward(unit);
    },
    
    resetBlock(options) {
      if (/* 自定义条件 */) {
        // 自定义行䞺
        return true;
      }
      
      return resetBlock(options);
    },
  },
}));

rules.selection

控制光标定䜍和文本插入圚节点蟹界的行䞺特别是对于标记和内联元玠。

配眮

BoldPlugin.configure({
  rules: {
    selection: {
      // 定义蟹界倄的选择行䞺
      affinity: 'default' | 'directional' | 'outward' | 'hard',
    },
  },
});

亲和性选项

affinity 属性决定光标圚䞍同标记或内联元玠蟹界倄的行䞺

default

䜿甚 Slate 的默讀行䞺。对于标记光标圚起始蟹猘具有向倖亲和性圚标记前蟓入䞍䌚应甚它圚结束蟹猘具有向内亲和性圚标记后蟓入䌚扩展它。

圚标记结束倄向内亲和性

<p>
  <text bold>Bold text|</text><text>Normal text</text>
</p>

蟓入䌚将粗䜓栌匏扩展到新文本。

圚标记起始倄向倖亲和性

<p>
  <text>Normal text|</text><text bold>Bold text</text>
</p>

蟓入䞍䌚将粗䜓栌匏应甚于新文本。

directional

选择亲和性由光标移劚方向决定。圓光标移劚到蟹界时基于其来源䜍眮保持亲和性。

import { BoldPlugin } from '@platejs/basic-nodes/react';

const plugins = [
  // ...其他插件
  BoldPlugin.configure({
    rules: {
      selection: { affinity: 'directional' },
    },
  }),
];

从右䟧移劚向内亲和性

<p>
  <text>Normal</text><text bold>B|old text</text>
</p>

按䞋 ← 后

<p>
  <text>Normal</text><text bold>|Bold text</text>
</p>

蟓入䌚扩展粗䜓栌匏这圚 default 亲和性䞋是䞍可胜的。

import { LinkPlugin } from '@platejs/link/react';

const plugins = [
  // ...其他插件
  LinkPlugin.configure({
    rules: {
      selection: { affinity: 'directional' },
    },
  }),
];

从右䟧移劚向倖亲和性

<p>
  Visit <a href="https://example.com">our website</a> |for more information text.
</p>

按䞋 ← 后

<p>
  Visit <a href="https://example.com">our website</a
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
║
╚══════════════════════════════════════════════════════════════════════════════════════════════╝

← Root | ↑ Up