Autoformat
Apply formatting automatically using shortcodes.
🏃♀️ Autoformat
- Type
**
or__
on either side of your text to add **bold* mark.
- Type
*
or_
on either side of your text to add *italic mark.
- Type
`
on either side of your text to add `inline code mark.
- Type
~~
on either side of your text to add ~~strikethrough~ mark.
- Note that nothing happens when there is a character before, try on:*bold
- We even support smart quotes, try typing
"hello" 'world'
.
- Type
*
,-
or+
followed byspace
to create a bulleted list.
- Type
1.
or1)
followed byspace
to create a numbered list.
- Type
[]
,or[x]
followed byspace
to create a todo list.
- Type
>
followed byspace
to create a block quote.
- Type
```
to create a code block.
- Type
---
to create a horizontal rule.
- Type
#
followed byspace
to create an H1 heading.
- Type
###
followed byspace
to create an H3 sub-heading.
- Type
####
followed byspace
to create an H4 sub-heading.
- Type
#####
followed byspace
to create an H5 sub-heading.
- Type
######
followed byspace
to create an H6 sub-heading.
Features
- Enables quick content formatting via shortcodes.
- Offers markdown-like inline codes for real-time typing.
- Enhances and simplifies editing by avoiding toolbar buttons and shortcuts for common formatting.
- Auto conversion feature (e.g.,
#
to H1). - Provides predefined formatting rules.
Formatting shortcodes:
text*
for bold text._text_
for italicized text.~~text~~
for strikethrough text.- ... and more.
Installation
npm install @udecode/plate-autoformat
Usage
import { AutoformatPlugin } from '@udecode/plate-autoformat/react';
const plugins = [
// ...otherPlugins,
AutoformatPlugin.configure({
options: {
rules: autoformatRules,
enableUndoOnDelete: true,
},
}),
];
Examples
autoformatRules
import {
autoformatArrow,
autoformatLegal,
autoformatLegalHtml,
autoformatMath,
autoformatPunctuation,
autoformatSmartQuotes,
} from '@udecode/plate-autoformat';
import {
BoldPlugin,
CodePlugin,
ItalicPlugin,
StrikethroughPlugin,
SubscriptPlugin,
SuperscriptPlugin,
UnderlinePlugin,
} from '@udecode/plate-basic-marks/react';
import { BlockquotePlugin } from '@udecode/plate-block-quote/react';
import {
CodeBlockPlugin,
CodeLinePlugin,
insertEmptyCodeBlock,
} from '@udecode/plate-code-block';
import {
getParentNode,
insertNodes,
isBlock,
isElement,
isType,
ParagraphPlugin,
setNodes,
} from '@udecode/plate-common';
import { HEADING_KEYS } from '@udecode/plate-heading';
import { HighlightPlugin } from '@udecode/plate-highlight/react';
import { HorizontalRulePlugin } from '@udecode/plate-horizontal-rule/react';
import {
INDENT_LIST_KEYS,
ListStyleType,
toggleIndentList,
} from '@udecode/plate-indent-list';
import { toggleList, unwrapList } from '@udecode/plate-list';
import {
BulletedListPlugin,
ListItemPlugin,
NumberedListPlugin,
TodoListPlugin,
} from '@udecode/plate-list/react';
import { openNextToggles, TogglePlugin } from '@udecode/plate-toggle/react';
import type {
AutoformatBlockRule,
AutoformatRule,
} from '@udecode/plate-autoformat';
import type { SlateEditor } from '@udecode/plate-common';
import type { TTodoListItemElement } from '@udecode/plate-list';
export const preFormat: AutoformatBlockRule['preFormat'] = (editor) =>
unwrapList(editor);
export const format = (editor: SlateEditor, customFormatting: any) => {
if (editor.selection) {
const parentEntry = getParentNode(editor, editor.selection);
if (!parentEntry) return;
const [node] = parentEntry;
if (
isElement(node) &&
!isType(editor, node, CodeBlockPlugin.key) &&
!isType(editor, node, CodeLinePlugin.key)
) {
customFormatting();
}
}
};
export const formatList = (editor: SlateEditor, elementType: string) => {
format(editor, () =>
toggleList(editor, {
type: elementType,
})
);
};
export const autoformatMarks: AutoformatRule[] = [
{
match: '***',
mode: 'mark',
type: [BoldPlugin.key, ItalicPlugin.key],
},
{
match: '__*',
mode: 'mark',
type: [UnderlinePlugin.key, ItalicPlugin.key],
},
{
match: '__**',
mode: 'mark',
type: [UnderlinePlugin.key, BoldPlugin.key],
},
{
match: '___***',
mode: 'mark',
type: [UnderlinePlugin.key, BoldPlugin.key, ItalicPlugin.key],
},
{
match: '**',
mode: 'mark',
type: BoldPlugin.key,
},
{
match: '__',
mode: 'mark',
type: UnderlinePlugin.key,
},
{
match: '*',
mode: 'mark',
type: ItalicPlugin.key,
},
{
match: '_',
mode: 'mark',
type: ItalicPlugin.key,
},
{
match: '~~',
mode: 'mark',
type: StrikethroughPlugin.key,
},
{
match: '^',
mode: 'mark',
type: SuperscriptPlugin.key,
},
{
match: '~',
mode: 'mark',
type: SubscriptPlugin.key,
},
{
match: '==',
mode: 'mark',
type: HighlightPlugin.key,
},
{
match: '≡',
mode: 'mark',
type: HighlightPlugin.key,
},
{
match: '`',
mode: 'mark',
type: CodePlugin.key,
},
];
export const autoformatBlocks: AutoformatRule[] = [
{
match: '# ',
mode: 'block',
preFormat,
type: HEADING_KEYS.h1,
},
{
match: '## ',
mode: 'block',
preFormat,
type: HEADING_KEYS.h2,
},
{
match: '### ',
mode: 'block',
preFormat,
type: HEADING_KEYS.h3,
},
{
match: '#### ',
mode: 'block',
preFormat,
type: HEADING_KEYS.h4,
},
{
match: '##### ',
mode: 'block',
preFormat,
type: HEADING_KEYS.h5,
},
{
match: '###### ',
mode: 'block',
preFormat,
type: HEADING_KEYS.h6,
},
{
match: '> ',
mode: 'block',
preFormat,
type: BlockquotePlugin.key,
},
{
format: (editor) => {
insertEmptyCodeBlock(editor, {
defaultType: ParagraphPlugin.key,
insertNodesOptions: { select: true },
});
},
match: '```',
mode: 'block',
preFormat,
triggerAtBlockStart: false,
type: CodeBlockPlugin.key,
},
{
match: '+ ',
mode: 'block',
preFormat: openNextToggles,
type: TogglePlugin.key,
},
{
format: (editor) => {
setNodes(editor, { type: HorizontalRulePlugin.key });
insertNodes(editor, {
children: [{ text: '' }],
type: ParagraphPlugin.key,
});
},
match: ['---', '—-', '___ '],
mode: 'block',
type: HorizontalRulePlugin.key,
},
];
export const autoformatLists: AutoformatRule[] = [
{
format: (editor) => formatList(editor, BulletedListPlugin.key),
match: ['* ', '- '],
mode: 'block',
preFormat,
type: ListItemPlugin.key,
},
{
format: (editor) => formatList(editor, NumberedListPlugin.key),
match: ['^\\d+\\.$ ', '^\\d+\\)$ '],
matchByRegex: true,
mode: 'block',
preFormat,
type: ListItemPlugin.key,
},
{
match: '[] ',
mode: 'block',
type: TodoListPlugin.key,
},
{
format: (editor) =>
setNodes<TTodoListItemElement>(
editor,
{ checked: true, type: TodoListPlugin.key },
{
match: (n) => isBlock(editor, n),
}
),
match: '[x] ',
mode: 'block',
type: TodoListPlugin.key,
},
];
export const autoformatIndentLists: AutoformatRule[] = [
{
format: (editor) => {
toggleIndentList(editor, {
listStyleType: ListStyleType.Disc,
});
},
match: ['* ', '- '],
mode: 'block',
type: 'list',
},
{
format: (editor) =>
toggleIndentList(editor, {
listStyleType: ListStyleType.Decimal,
}),
match: ['^\\d+\\.$ ', '^\\d+\\)$ '],
matchByRegex: true,
mode: 'block',
type: 'list',
},
{
format: (editor) => {
toggleIndentList(editor, {
listStyleType: INDENT_LIST_KEYS.todo,
});
setNodes(editor, {
checked: false,
listStyleType: INDENT_LIST_KEYS.todo,
});
},
match: ['[] '],
mode: 'block',
type: 'list',
},
{
format: (editor) => {
toggleIndentList(editor, {
listStyleType: INDENT_LIST_KEYS.todo,
});
setNodes(editor, {
checked: true,
listStyleType: INDENT_LIST_KEYS.todo,
});
},
match: ['[x] '],
mode: 'block',
type: 'list',
},
];
export const autoformatRules: AutoformatRule[] = [
...autoformatBlocks,
...autoformatMarks,
...autoformatSmartQuotes,
...autoformatPunctuation,
...autoformatLegal,
...autoformatLegalHtml,
...autoformatArrow,
...autoformatMath,
...autoformatIndentLists,
];
autoformatBlocks
autoformatIndentLists
If using the Indent List plugin, you can use the following rules:
autoformatLists
If using the List plugin, you can use the following rules:
autoformatMarks
autoformatUtils
API
AutoformatPlugin
Options
- Can be one of the following:
AutoformatBlockRule
,AutoformatMarkRule
,AutoformatTextRule
. - Extends
AutoformatCommonRule
.
A list of triggering rules.
Enable undo on delete.
Rules
You can import the following rules:
Name | Description |
---|---|
autoformatSmartQuotes | Converts "text" to "text" . |
Converts 'text' to 'text' . | |
autoformatPunctuation | Converts -- to — . |
Converts ... to … . | |
Converts >> to » . | |
Converts << to « . | |
autoformatArrow | Converts -> to → . |
Converts <- to ← . | |
Converts => to ⇒ . | |
Converts <= and ≤= to ⇐ . | |
autoformatLegal | Converts (tm) and (TM) to ™ . |
Converts (r) and (R) to ® . | |
Converts (c) and (C) to © . | |
autoformatLegalHtml | Converts ™ to ™ . |
Converts ® to ® . | |
Converts © to © . | |
Converts § to § . | |
autoformatComparison | Converts !> to !> . |
Converts !< to ≮ . | |
Converts >= to ≥ . | |
Converts <= to ≤ . | |
Converts !>= to ≱ . | |
Converts !<= to ≰ . | |
autoformatEquality | Converts != to ≠ . |
Converts == to ≡ . | |
Converts !== and ≠= to ≢ . | |
Converts ~= to ≈ . | |
Converts !~= to ≉ . | |
autoformatFraction | Converts 1/2 to ½ . |
Converts 1/3 to ⅓ . | |
... | |
Converts 7/8 to ⅞ . | |
autoformatDivision | Converts // to ÷ . |
autoformatOperation | Converts +- to ± . |
Converts %% to ‰ . | |
Converts %%% and ‰% to `‱. | |
autoformatDivision rules. | |
autoformatSubscriptNumbers | Converts ~0 to ₀ . |
Converts ~1 to ₁ . | |
... | |
Converts ~9 to ₉ . | |
autoformatSubscriptSymbols | Converts ~+ to ₊ . |
Converts ~- to ₋ . | |
autoformatSuperscriptNumbers | Converts ^0 to ⁰ . |
Converts ^1 to ¹ . | |
... | |
Converts ^9 to ⁹ . | |
autoformatSuperscriptSymbols | Converts ^+ to ° . |
Converts ^- to ⁺ . | |
autoformatMath | autoformatComparison rules |
autoformatEquality rules | |
autoformatOperation rules | |
autoformatFraction rules | |
autoformatSubscriptNumbers rules | |
autoformatSubscriptSymbols rules | |
autoformatSuperscriptNumbers rules | |
autoformatSuperscriptSymbols rules |
AutoformatCommonRule
An interface for the common structure of autoformat rules, regardless of their mode.
Attributes
- For
mode: 'block'
: lookup for the end match(es) before the cursor. - For
mode: 'text'
: lookup for the end match(es) before the cursor. Ifformat
is an array, also lookup for the start match(es). - For
mode: 'mark'
: lookup for the start and end matches. - Note:
'_*'
,['_*']
and{ start: '_*', end: '*_' }
are equivalent. MatchRange
:- Default:
false
AutoformatQueryOptions
extendsOmit<AutoformatCommonRule, 'query'>
:
The rule applies when the trigger and the text just before the cursor matches.
Triggering character to autoformat.
If true, insert the triggering character after autoformatting.
A query function to allow autoformat.
AutoformatBlockRule
An interface for autoformat rules for block mode.
Attributes
- Text: insert text.
- Block: set block type or custom format.
- Mark: insert mark(s) between matches.
- For
mode: 'block'
: set block type. Ifformat
is defined, this field is ignored. - For
mode: 'mark'
: Mark(s) to add. - Default:
true
- Default:
false
A pattern to match for the autoformat rule to apply.
If true, the trigger should be at block start to allow autoformatting.
If true, allow to autoformat even if there is a block of the same type above the selected block.
Function called just before format
. Generally used to reset the selected
block.
Custom formatting function.
AutoformatMarkRule
An interface for autoformat rules for mark mode.
Attributes
The mode is 'mark'.
Mark(s) to add.
If false, do not format when the string can be trimmed.
AutoformatTextRule
An interface for autoformat rules for text mode.
Parameters
The mode is 'text'.
A pattern to match for the autoformat rule to apply.
The matched text is replaced by that string, the matched texts are replaced by these strings, or a function called when there is a match.