Docs
Autoformat

Autoformat

Apply formatting automatically using shortcodes.

🏃‍♀️ Autoformat

Empower your writing experience by enabling autoformatting features. Add Markdown-like shortcuts that automatically apply formatting as you type.
While typing, try these mark rules:
  • 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'.
At the beginning of any new block or existing block, try these (block rules):
  • Type *, - or +followed by space to create a bulleted list.
  • Type 1. or 1) followed by spaceto create a numbered list.
  • Type [],or [x]followed by space to create a todo list.
  • Type > followed by space to create a block quote.
  • Type ``` to create a code block.
  • Type --- to create a horizontal rule.
  • Type # followed by space to create an H1 heading.
  • Type ### followed by space to create an H3 sub-heading.
  • Type #### followed by space to create an H4 sub-heading.
  • Type ##### followed by space to create an H5 sub-heading.
  • Type ###### followed by space 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 { insertEmptyCodeBlock } from '@udecode/plate-code-block';
import {
  CodeBlockPlugin,
  CodeLinePlugin,
} from '@udecode/plate-code-block/react';
import {
  getParentNode,
  insertNodes,
  isBlock,
  isElement,
  isType,
  setNodes,
} from '@udecode/plate-common';
import { ParagraphPlugin } from '@udecode/plate-common/react';
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

Collapse all

    A list of triggering rules.

    • Can be one of the following: AutoformatBlockRule, AutoformatMarkRule, AutoformatTextRule.
    • Extends AutoformatCommonRule.

    Enable undo on delete.

Rules

You can import the following rules:

NameDescription
autoformatSmartQuotesConverts "text" to "text".
Converts 'text' to 'text'.
autoformatPunctuationConverts -- to .
Converts ... to .
Converts >> to ».
Converts << to «.
autoformatArrowConverts -> to .
Converts <- to .
Converts => to .
Converts <= and ≤= to .
autoformatLegalConverts (tm) and (TM) to .
Converts (r) and (R) to ®.
Converts (c) and (C) to ©.
autoformatLegalHtmlConverts &trade; to .
Converts &reg; to ®.
Converts &copy; to ©.
Converts &sect; to §.
autoformatComparisonConverts !> to !>.
Converts !< to .
Converts >= to .
Converts <= to .
Converts !>= to .
Converts !<= to .
autoformatEqualityConverts != to .
Converts == to .
Converts !== and ≠= to .
Converts ~= to .
Converts !~= to .
autoformatFractionConverts 1/2 to ½.
Converts 1/3 to .
...
Converts 7/8 to .
autoformatDivisionConverts // to ÷.
autoformatOperationConverts +- to ±.
Converts %% to .
Converts %%% and ‰% to `‱.
autoformatDivision rules.
autoformatSubscriptNumbersConverts ~0 to .
Converts ~1 to .
...
Converts ~9 to .
autoformatSubscriptSymbolsConverts ~+ to .
Converts ~- to .
autoformatSuperscriptNumbersConverts ^0 to .
Converts ^1 to ¹.
...
Converts ^9 to .
autoformatSuperscriptSymbolsConverts ^+ to °.
Converts ^- to .
autoformatMathautoformatComparison 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

Collapse all

    The rule applies when the trigger and the text just before the cursor matches.

    • For mode: 'block': lookup for the end match(es) before the cursor.
    • For mode: 'text': lookup for the end match(es) before the cursor. If format 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:

    Triggering character to autoformat.

    If true, insert the triggering character after autoformatting.

    • Default: false

    A query function to allow autoformat.

    • AutoformatQueryOptions extends Omit<AutoformatCommonRule, 'query'>:

AutoformatBlockRule

An interface for autoformat rules for block mode.

Attributes

Collapse all

    • Text: insert text.
    • Block: set block type or custom format.
    • Mark: insert mark(s) between matches.

    A pattern to match for the autoformat rule to apply.

    • For mode: 'block': set block type. If format is defined, this field is ignored.
    • For mode: 'mark': Mark(s) to add.

    If true, the trigger should be at block start to allow autoformatting.

    • Default: true

    If true, allow to autoformat even if there is a block of the same type above the selected block.

    • Default: false

    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

Collapse all

    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

Collapse all

    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.