ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â ð shadcn/directory/udecode/plate/(guides)/plugin-rules.cn â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â
æä»¶è§åæ§å¶çŒèŸåšèç¹åŠäœååºåžžè§ççšæ·æäœãæšå¯ä»¥çŽæ¥åšæä»¶ç rules 屿§äžé
眮è¿äºè¡äžºïŒèæ ééåçŒèŸå𿹿³ã
æ¬æåå±ç€ºåŠäœäœ¿çš rules.breakãrules.deleteãrules.mergeãrules.normalizeãrules.selection å rules.match æ¥å建çŽè§ççŒèŸäœéªã
æä»¶è§å䜿çšç¹å®çæäœåç§°æ¥å®ä¹è¡äžºïŒ
'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,
},
},
});
æ¯äžªå±æ§æ§å¶ç¹å®åºæ¯ïŒ
default
empty
emptyLineEnd
splitReset: åŠæäžº trueïŒæååçæ°åå°è¢«é眮䞺é»è®€ç±»åãè¿å¯¹äºéåºæ ŒåŒååïŒåŠæ é¢ïŒåŸæçšã
æ 颿忶é眮ïŒ
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
â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ