Skip to main content

Features

This page documents each built-in feature as it is actually implemented in the source.

Incremental rendering

The preview uses block-level incremental rendering to stay responsive on large documents:

  • Block splitting (splitIntoBlocks): the source is split into blocks at ATX heading lines (# through ######). Content inside code fences (```` or~~~) is never treated as a split point, and headings inside :::` custom containers are also preserved. Documents with no headings degrade to a single block.
  • Per-block rendering: only blocks whose content hash changed are re-run through markdown-it / KaTeX. Unchanged blocks reuse their existing DOM nodes directly, including already-hydrated mindmap SVGs.
  • Content-hash cache: render results are cached by content hash (a fast djb2-style hash plus length), so undo/redo and copy-paste of identical paragraphs also hit the cache. The cache is capped at 800 entries and evicts hashes no longer present in the document.
  • Reordering: reordered blocks are moved natively by appending existing nodes to a DocumentFragment.
  • Adaptive debounce (adaptiveDebounceMs(docLength, base = 120, max = 600)): the pause before a render is base + floor(docLength / 20000) * 60, capped at max. Override with renderDebounce, or set renderDebounce: false to render synchronously.
  • content-visibility: auto: each block is wrapped in a .md-editor-block element so off-screen blocks skip layout and paint.

A single block failing to render never blanks the whole preview; it falls back to an escaped <pre> of that block's source.

KaTeX math

The self-contained markdown-it math plugin renders math with KaTeX (no markdown-it-texmath dependency):

  • Inline math: $E=mc^2$ — content must not contain $, newline, or be empty. Currency-like content such as $5 or $10.50 is heuristically excluded.
  • Block math:
    $$
    \int_0^1 x^2 \, dx
    $$
    Single-line ($$ ... $$) and multi-line forms are both supported. KaTeX CSS is bundled with the package. Disable with math: false.

Markmap mindmaps

Write a ```mindmap fenced block whose body is a markdown outline:

```mindmap
# Root topic
## Branch one
- Child A
- Child B
## Branch two
- Child C
```

The block rule tracks fence nesting depth, so nested code fences inside a mindmap are preserved. The synchronous render pass emits a placeholder <div>; Renderer.hydrate(container) asynchronously imports markmap-lib and markmap-view and turns each placeholder into an interactive SVG. Hydration failures are non-fatal. Disable with mindmap: false.

Code highlighting with copy button

Fenced code blocks are highlighted with highlight.js. The build registers a fixed set of languages: JavaScript, TypeScript, Python, JSON, Bash/Shell, CSS, XML/HTML/SVG, SQL, YAML, Markdown, Go, Rust, Java, C, and C++ (with common aliases such as js, ts, py, sh, yml, md, rs, c++). Unknown languages are auto-detected; detection failures fall back to escaped plain text.

Each highlighted block is wrapped in a macOS-style container with traffic-light dots, a language label, and a Copy button. The copy button uses event delegation on the preview pane and falls back to document.execCommand('copy') when the Clipboard API is unavailable. Disable with codeHighlight: false.

Toolbar actions

In complex mode, the toolbar is built from the 22 actions below, in this default order:

#Action nameDefault label
1headingHeading
2boldBold (Ctrl+B)
3italicItalic (Ctrl+I)
4linkLink (Ctrl+K)
5imageInsert image
6videoInsert video
7youtubeInsert YouTube video
8quoteQuote
9ulUnordered list
10olOrdered list
11tasklistTask list
12mentionMention (@)
13doclinkInsert document link
14codeCode block
15tableTable
16mathMath formula
17mindmapInsert mindmap
18hrHorizontal rule
19tipsInsert callout
20previewToggle preview
21helpKeyboard shortcuts
22themeToggle theme

Several actions open popup dialogs or template pickers: image, video, YouTube, table, math (templates), mindmap (templates), callout (type grid), and help. Configure the toolbar with the toolbar option as described in Configuration.

Keyboard shortcuts

The built-in shortcuts are defined in DEFAULT_SHORTCUTS. Mod maps to Ctrl on Windows/Linux and Cmd on macOS.

KeyActionDescription
Mod-bboldBold
Mod-iitalicItalic
Mod-Alt-1headingHeading
Mod-klinkInsert link
Mod-Alt-ccodeCode block
Mod-Shift-.quoteBlockquote
Mod-Shift-8ulUnordered list
Mod-Shift-7olOrdered list
Mod-Shift-9tasklistTask list
Mod-Alt-mmathMath formula
Mod-Alt-ppreviewToggle preview
Mod-Shift-lthemeToggle theme

The toolbar Help button opens a dialog that lists these shortcuts with styled key caps, plus a quick-reference section for task lists, mentions, doc links, math, mindmaps, and callouts.

Image upload

Provide onImageUpload: (file: File) => Promise<string>. The hook is called when an image file is pasted, dropped onto the editor, or selected through the image popup. Resolve to the public image URL; the editor inserts ![alt](url) at the cursor (using the file name, minus extension, as the alt text). Upload failures are swallowed silently so the user can retry.

@mention

Pass a mention option to enable a searchable dropdown when the user types @:

  • onMentionSearch(query) returns matching MentionItems.
  • onMentionSelect(item) returns the inserted text. The default is [@label](mention:id), which the renderer turns into a styled badge.
  • minChars (default 0) and maxItems (default 8) tune the dropdown.

The dropdown supports ArrowUp/ArrowDown, Enter/Tab, and Escape navigation, and closes on editor blur. Typing @ in prose (such as @media) never triggers the dropdown because real mentions use the mention: link scheme.

Pass a docLink option to enable a document search dropdown after the trigger character (default /):

  • onDocSearch(query) returns matching DocItems.
  • onFetchDocMeta(url) fetches title, thumbnail, and description. The built-in implementation uses fetch + DOMParser to read Open Graph tags, but will fail on cross-origin URLs due to CORS — override it with a backend proxy in production.
  • insertStyle controls insertion: 'auto' (card when metadata is available), 'card', or 'link'.

A selected document is inserted as either a plain link or a :::doc-link card that renders title, thumbnail, description, and hostname as a clickable preview card.

Admonition / callout blocks

Write a ::: container with one of six types. An optional title may follow the type on the opening line:

:::notice
This is a notice.
:::

:::warning[Title here]
Warning content.
:::

Supported types: notice, info, tip, success, warning, danger. Each renders with an icon, a colored left border, and a header. The toolbar callout button opens a visual picker for all six types. Disable with tips: false.

Task lists

List items matching - [ ] or - [x] (with arbitrary whitespace inside the brackets) render as disabled checkboxes. Note the project convention: - [ ] renders as checked (green) and - [x] renders as unchecked — the inverse of GitHub Flavored Markdown. The toolbar task-list button toggles markers on the current line or selected lines.

Next steps