Autoformat

Loading...
Files
components/demo.tsx
'use client';

import React from 'react';

import { Plate } from '@udecode/plate/react';

import { editorPlugins } from '@/components/editor/plugins/editor-plugins';
import { useCreateEditor } from '@/components/editor/use-create-editor';
import { Editor, EditorContainer } from '@/components/plate-ui/editor';

import { DEMO_VALUES } from './values/demo-values';

export default function Demo({ id }: { id: string }) {
  const editor = useCreateEditor({
    plugins: [...editorPlugins],
    value: DEMO_VALUES[id],
  });

  return (
    <Plate editor={editor}>
      <EditorContainer variant="demo">
        <Editor />
      </EditorContainer>
    </Plate>
  );
}

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.

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

'use client';
 
import type { SlateEditor } from '@udecode/plate';
import type { AutoformatRule } from '@udecode/plate-autoformat';
 
import { ElementApi, isType } from '@udecode/plate';
import { ParagraphPlugin } from '@udecode/plate/react';
import {
  autoformatArrow,
  autoformatLegal,
  autoformatLegalHtml,
  autoformatMath,
  autoformatPunctuation,
  autoformatSmartQuotes,
} from '@udecode/plate-autoformat';
import { AutoformatPlugin } from '@udecode/plate-autoformat/react';
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 { 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 { TogglePlugin, openNextToggles } from '@udecode/plate-toggle/react';
 
export const format = (editor: SlateEditor, customFormatting: any) => {
  if (editor.selection) {
    const parentEntry = editor.api.parent(editor.selection);
 
    if (!parentEntry) return;
 
    const [node] = parentEntry;
 
    if (
      ElementApi.isElement(node) &&
      !isType(editor, node, CodeBlockPlugin.key) &&
      !isType(editor, node, CodeLinePlugin.key)
    ) {
      customFormatting();
    }
  }
};
 
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',
    type: HEADING_KEYS.h1,
  },
  {
    match: '## ',
    mode: 'block',
    type: HEADING_KEYS.h2,
  },
  {
    match: '### ',
    mode: 'block',
    type: HEADING_KEYS.h3,
  },
  {
    match: '#### ',
    mode: 'block',
    type: HEADING_KEYS.h4,
  },
  {
    match: '##### ',
    mode: 'block',
    type: HEADING_KEYS.h5,
  },
  {
    match: '###### ',
    mode: 'block',
    type: HEADING_KEYS.h6,
  },
  {
    match: '> ',
    mode: 'block',
    type: BlockquotePlugin.key,
  },
  {
    format: (editor) => {
      insertEmptyCodeBlock(editor, {
        defaultType: ParagraphPlugin.key,
        insertNodesOptions: { select: true },
      });
    },
    match: '```',
    mode: 'block',
    triggerAtBlockStart: false,
    type: CodeBlockPlugin.key,
  },
  {
    match: '+ ',
    mode: 'block',
    preFormat: openNextToggles,
    type: TogglePlugin.key,
  },
  {
    format: (editor) => {
      editor.tf.setNodes({ type: HorizontalRulePlugin.key });
      editor.tf.insertNodes({
        children: [{ text: '' }],
        type: ParagraphPlugin.key,
      });
    },
    match: ['---', '—-', '___ '],
    mode: 'block',
    type: HorizontalRulePlugin.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: [String.raw`^\d+\.$ `, String.raw`^\d+\)$ `],
    matchByRegex: true,
    mode: 'block',
    type: 'list',
  },
  {
    format: (editor) => {
      toggleIndentList(editor, {
        listStyleType: INDENT_LIST_KEYS.todo,
      });
      editor.tf.setNodes({
        checked: false,
        listStyleType: INDENT_LIST_KEYS.todo,
      });
    },
    match: ['[] '],
    mode: 'block',
    type: 'list',
  },
  {
    format: (editor) => {
      toggleIndentList(editor, {
        listStyleType: INDENT_LIST_KEYS.todo,
      });
      editor.tf.setNodes({
        checked: true,
        listStyleType: INDENT_LIST_KEYS.todo,
      });
    },
    match: ['[x] '],
    mode: 'block',
    type: 'list',
  },
];
 
export const autoformatPlugin = AutoformatPlugin.configure({
  options: {
    enableUndoOnDelete: true,
    rules: [
      ...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

Plugins

AutoformatPlugin

Options

Collapse all

    A list of triggering rules.

    • Can be one of: 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

Types

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.

    OptionsAutoformatQueryOptions

    Collapse all

      insertText text.

AutoformatBlockRule

An interface for autoformat rules for block mode.

Attributes

Collapse all

    Block mode: set block type or custom format.

    Pattern to match for the autoformat rule.

    Block type to set. Ignored if format is defined.

    Whether trigger should be at block start.

    • Default: true

    Whether to allow autoformat with same block type above.

    • Default: false

    Function called before format. Used to reset selected block.

    Custom formatting function.

AutoformatMarkRule

An interface for autoformat rules for mark mode.

Attributes

Collapse all

    Mark mode: insert mark(s) between matches.

    Mark(s) to add.

    Whether to format when string can be trimmed.

AutoformatTextRule

An interface for autoformat rules for text mode.

Parameters

Collapse all

    Text mode: insert text.

    Pattern to match for the autoformat rule.

    Text replacement or formatting function.