Markdown editor

The full editor can store things Markdown cannot: underline, colors, fonts, alignment, columns. This editor leaves them out. The toolbar, the floating toolbar and the slash menu only offer what Markdown can write, so what you see is what a Markdown export keeps.

0 words0 characters

Installation

This editor is components/editor/editor-md.tsx. It is installed with @intentui/editor, next to editor.tsx. Render DemoMarkdownEditor, or copy the file and rename it.

npx shadcn@latest add @intentui/editor
app/page.tsx
import { DemoMarkdownEditor } from "@/components/editor/editor-md"

export default function Page() {
  return <DemoMarkdownEditor />
}

What's included

Extensions

ExtensionBehavior
RichTextExtensionRich text editing. Required.
HistoryExtensionUndo and redo.
TabIndentationExtensionIndent and outdent list items with Tab.
ListExtension, CheckListExtensionBulleted, numbered and check lists.
LinkExtension, AutoLinkExtensionLinks and automatic link detection.
CodeExtensionCode blocks with syntax highlighting.
TableExtensionTables.
HorizontalRuleExtensionDividers.
ImageExtension, DragDropPasteExtensionImages, including drag, drop and paste.
FormatStateExtensionLets the toolbar show which formats are active.
ClearEditorExtensionThe clear editor button.
ClipboardDOMImportExtensionCleaner pasting of HTML.

Toolbar, floating toolbar and slash menu

RegionContents
ToolbarUndo and redo, block type, bold, italic, strikethrough, inline code, link, insert menu, clear, import and export.
Floating toolbarBold, italic, strikethrough, inline code and link.
Slash menuParagraph, headings 1 to 3, table, numbered list, bulleted list, check list, quote, code block, divider and image.
Insert menuCode block, divider, image and table.
Activity barWord and character counts and the read-only toggle.

Everything else is the same as in the full editor: the same plugins, the same composition.

Compared with the full editor

These are left out because Markdown has no syntax for them.

Left outWhere it was
Underline, highlight, subscript, superscript, uppercase, lowercase, title caseToolbar and floating toolbar
Font family, font size, text and highlight colorToolbar
Alignment, indent and outdent buttonsToolbar
ColumnsInsert menu and slash menu
Emoji, mentions, hashtags and special textInsert menu, pickers and extensions
Speech to text, the shortcuts dialog and ShortcutsExtensionActivity bar and extensions
Autocomplete and tab focusExtensions
Context menuContent area

Text formats

TextFormatToolbarPlugin has a markdown option for this editor. It renders only the formats Markdown can write, in one group.

<TextFormatToolbarPlugin formats="markdown" />

The floating toolbar uses the same option, so both show the same four buttons.

Formats Markdown cannot write

Buttons are not the only way to apply a format. Ctrl U underlines text in any Lexical editor, and the underline would then disappear from the Markdown export. The editor refuses those formats from every source with a small command handler:

components/editor/editor-md.tsx
const MARKDOWN_TEXT_FORMATS: TextFormatType[] = ["bold", "italic", "strikethrough", "code"]

register: (editor) =>
  mergeRegister(
    registerMarkdownShortcuts(editor, MARKDOWN_TRANSFORMERS),
    editor.registerCommand(
      FORMAT_TEXT_COMMAND,
      (format) => !MARKDOWN_TEXT_FORMATS.includes(format),
      COMMAND_PRIORITY_HIGH,
    ),
  ),

Returning true marks the command as handled, so it stops there. Remove the handler if you want the keyboard to stay unrestricted.

Markdown shortcuts

Typing Markdown converts it as you go. MARKDOWN_TRANSFORMERS is the stock Lexical list plus the editor's table, divider, image and check list transformers, without highlight.

TypeResult
# Heading 1. ## and ### give headings 2 and 3.
**text**Bold
*text*Italic
~~text~~Strikethrough
`text`Inline code
> Quote
1. Numbered list
- Bulleted list
[ ] on its own lineCheck list
--- Divider
```js then spaceCode block

==text== stays plain text. Highlight is not in the Markdown transformers, so it does not convert. In a bulleted list item, typing [ ] does not turn the item into a check item. Start the line with [ ] instead.

Import and export

ImportExportToolbarPlugin receives MARKDOWN_TRANSFORMERS, so Export as, Markdown downloads a .md file that includes tables, images and dividers. The menu also offers Lexical JSON and HTML.

Import file uses Lexical's importer, which reads .lexical files only. It does not read Markdown files. To start from Markdown text, convert it with $convertFromMarkdownString from @lexical/markdown, see the Lexical Markdown docs.

API

The new option on TextFormatToolbarPlugin.
formats"basic" | "markdown" | "all"
markdown renders bold, italic, strikethrough and inline code in one group.
Default: "all"