Subscript

PreviousNext

Format inline text below the baseline.

Subscript applies the subscript leaf mark to selected text. Its toggle transform removes superscript, so the same text cannot keep both vertical-position marks through the plugin API.

Loading…

Features

  • KEYS.sub leaf mark.
  • Directional selection affinity.
  • HTML deserialization from sub and vertical-align: sub.
  • <sub> rendering by default.
  • Optional Markdown-style input rule through SubscriptRules.
  • Mutual exclusion with KEYS.sup.

Kit Usage

Add Basic Marks

BasicMarksKit includes SubscriptPlugin, the ~ input rule, and a mod+comma shortcut.

'use client';
 
import {
  BoldRules,
  CodeRules,
  HighlightRules,
  ItalicRules,
  MarkComboRules,
  StrikethroughRules,
  SubscriptRules,
  SuperscriptRules,
  UnderlineRules,
} from '@platejs/basic-nodes';
import {
  BoldPlugin,
  CodePlugin,
  HighlightPlugin,
  ItalicPlugin,
  KbdPlugin,
  StrikethroughPlugin,
  SubscriptPlugin,
  SuperscriptPlugin,
  UnderlinePlugin,
} from '@platejs/basic-nodes/react';
 
import { CodeLeaf } from '@/components/ui/code-node';
import { HighlightLeaf } from '@/components/ui/highlight-node';
import { KbdLeaf } from '@/components/ui/kbd-node';
 
export const BasicMarksKit = [
  BoldPlugin.configure({
    inputRules: [
      BoldRules.markdown({ variant: '*' }),
      BoldRules.markdown({ variant: '_' }),
      MarkComboRules.markdown({ variant: 'boldItalic' }),
      MarkComboRules.markdown({ variant: 'boldUnderline' }),
      MarkComboRules.markdown({ variant: 'boldItalicUnderline' }),
      MarkComboRules.markdown({ variant: 'italicUnderline' }),
    ],
  }),
  ItalicPlugin.configure({
    inputRules: [
      ItalicRules.markdown({ variant: '*' }),
      ItalicRules.markdown({ variant: '_' }),
    ],
  }),
  UnderlinePlugin.configure({
    inputRules: [UnderlineRules.markdown()],
  }),
  CodePlugin.configure({
    inputRules: [CodeRules.markdown()],
    node: { component: CodeLeaf },
    shortcuts: { toggle: { keys: 'mod+e' } },
  }),
  StrikethroughPlugin.configure({
    inputRules: [StrikethroughRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+shift+x' } },
  }),
  SubscriptPlugin.configure({
    inputRules: [SubscriptRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+comma' } },
  }),
  SuperscriptPlugin.configure({
    inputRules: [SuperscriptRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+period' } },
  }),
  HighlightPlugin.configure({
    inputRules: [
      HighlightRules.markdown({ variant: '==' }),
      HighlightRules.markdown({ variant: '≡' }),
    ],
    node: { component: HighlightLeaf },
    shortcuts: { toggle: { keys: 'mod+shift+h' } },
  }),
  KbdPlugin.withComponent(KbdLeaf),
];
'use client';
 
import {
  BoldRules,
  CodeRules,
  HighlightRules,
  ItalicRules,
  MarkComboRules,
  StrikethroughRules,
  SubscriptRules,
  SuperscriptRules,
  UnderlineRules,
} from '@platejs/basic-nodes';
import {
  BoldPlugin,
  CodePlugin,
  HighlightPlugin,
  ItalicPlugin,
  KbdPlugin,
  StrikethroughPlugin,
  SubscriptPlugin,
  SuperscriptPlugin,
  UnderlinePlugin,
} from '@platejs/basic-nodes/react';
 
import { CodeLeaf } from '@/components/ui/code-node';
import { HighlightLeaf } from '@/components/ui/highlight-node';
import { KbdLeaf } from '@/components/ui/kbd-node';
 
export const BasicMarksKit = [
  BoldPlugin.configure({
    inputRules: [
      BoldRules.markdown({ variant: '*' }),
      BoldRules.markdown({ variant: '_' }),
      MarkComboRules.markdown({ variant: 'boldItalic' }),
      MarkComboRules.markdown({ variant: 'boldUnderline' }),
      MarkComboRules.markdown({ variant: 'boldItalicUnderline' }),
      MarkComboRules.markdown({ variant: 'italicUnderline' }),
    ],
  }),
  ItalicPlugin.configure({
    inputRules: [
      ItalicRules.markdown({ variant: '*' }),
      ItalicRules.markdown({ variant: '_' }),
    ],
  }),
  UnderlinePlugin.configure({
    inputRules: [UnderlineRules.markdown()],
  }),
  CodePlugin.configure({
    inputRules: [CodeRules.markdown()],
    node: { component: CodeLeaf },
    shortcuts: { toggle: { keys: 'mod+e' } },
  }),
  StrikethroughPlugin.configure({
    inputRules: [StrikethroughRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+shift+x' } },
  }),
  SubscriptPlugin.configure({
    inputRules: [SubscriptRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+comma' } },
  }),
  SuperscriptPlugin.configure({
    inputRules: [SuperscriptRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+period' } },
  }),
  HighlightPlugin.configure({
    inputRules: [
      HighlightRules.markdown({ variant: '==' }),
      HighlightRules.markdown({ variant: '≡' }),
    ],
    node: { component: HighlightLeaf },
    shortcuts: { toggle: { keys: 'mod+shift+h' } },
  }),
  KbdPlugin.withComponent(KbdLeaf),
];
import { createPlateEditor } from 'platejs/react';
 
import { BasicMarksKit } from '@/components/editor/plugins/basic-marks-kit';
 
export const editor = createPlateEditor({
  plugins: [...BasicMarksKit],
});
import { createPlateEditor } from 'platejs/react';
 
import { BasicMarksKit } from '@/components/editor/plugins/basic-marks-kit';
 
export const editor = createPlateEditor({
  plugins: [...BasicMarksKit],
});

Add a Toolbar Control

The registry MoreToolbarButton toggles subscript from the More menu and removes superscript.

import { MoreToolbarButton } from '@/components/ui/more-toolbar-button';
 
export function FormattingMoreMenu() {
  return <MoreToolbarButton />;
}
import { MoreToolbarButton } from '@/components/ui/more-toolbar-button';
 
export function FormattingMoreMenu() {
  return <MoreToolbarButton />;
}

Manual Usage

Install the mark package.

pnpm add @platejs/basic-nodes
pnpm add @platejs/basic-nodes

Add SubscriptPlugin directly when you want the default <sub> render.

import { SubscriptPlugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
 
export const editor = createPlateEditor({
  plugins: [SubscriptPlugin],
});
import { SubscriptPlugin } from '@platejs/basic-nodes/react';
import { createPlateEditor } from 'platejs/react';
 
export const editor = createPlateEditor({
  plugins: [SubscriptPlugin],
});

Configure the input rule and shortcut when you want the same behavior as the kit.

import { SubscriptRules } from '@platejs/basic-nodes';
import { SubscriptPlugin } from '@platejs/basic-nodes/react';
 
export const subscriptPlugin = SubscriptPlugin.configure({
  inputRules: [SubscriptRules.markdown()],
  shortcuts: { toggle: { keys: 'mod+comma' } },
});
import { SubscriptRules } from '@platejs/basic-nodes';
import { SubscriptPlugin } from '@platejs/basic-nodes/react';
 
export const subscriptPlugin = SubscriptPlugin.configure({
  inputRules: [SubscriptRules.markdown()],
  shortcuts: { toggle: { keys: 'mod+comma' } },
});

Ownership

SurfaceOwnerWhat It Does
BaseSubscriptPlugin@platejs/basic-nodesHeadless subscript mark, HTML parser, render tag, selection rule, and toggle transform.
SubscriptPlugin@platejs/basic-nodes/reactReact wrapper for the headless subscript mark.
SubscriptRules.markdown@platejs/basic-nodesOptional ~ mark input rule factory.
BasicMarksKitRegistryAdds SubscriptPlugin, the input rule, and mod+comma.
MoreToolbarButtonRegistry UICalls editor.tf.toggleMark(KEYS.sub, { remove: KEYS.sup }).

The package owns subscript semantics. The registry owns shortcut configuration and toolbar placement.

Behavior

BehaviorSource
Mark keyKEYS.sub (subscript)
Leaf behaviornode.isLeaf: true
Toggle transformeditor.tf.subscript.toggle() calls editor.tf.toggleMark(type, { remove: editor.getType(KEYS.sup) }).
Selection affinitydirectional
HTML tagssub
HTML stylesvertical-align: sub
Render outputsub
Kit input ruleSubscriptRules.markdown()
Kit shortcutmod+comma

API Reference

APIPackageUse
BaseSubscriptPlugin@platejs/basic-nodesHeadless subscript plugin.
SubscriptPlugin@platejs/basic-nodes/reactReact subscript plugin.
SubscriptRules.markdown()@platejs/basic-nodesCreates the ~ mark input rule.
tf.subscript.toggle()@platejs/basic-nodesToggles subscript and removes superscript.