@conql/codemirror-live-markdown
Obsidian-inspired Live Preview for CodeMirror 6. Markdown text stays the source of truth; formatting, tables and previews are CodeMirror extensions.
English | 简体中文
Version 1.0.0 is the independently maintained fork of blueberrycongee's original library. See the migration guide and integration examples.
Install
npm install @conql/codemirror-live-markdown
Try this checkout
npm ci --include=dev
npm run demo
Open http://localhost:5173. The demo offers a single note, local browser saving, an outline, search, Markdown export, three display modes, and light/dark themes. It does not provide a vault or attachment storage.
To test local changes in another project, run npm pack in this checkout, then install the generated .tgz in the consumer. prepare builds the ESM, CommonJS and TypeScript outputs for packing and Git installation.
CodeMirror and Lezer are peer dependencies. Current npm versions install required peers automatically. KaTeX and lowlight remain optional:
npm install katex lowlight
Quick start
import { EditorView } from '@codemirror/view';
import {
liveMarkdown,
initHighlighter,
initMathRenderer,
} from '@conql/codemirror-live-markdown';
import 'katex/dist/katex.min.css';
await Promise.all([initHighlighter(), initMathRenderer()]);
const view = new EditorView({
doc: '# A note\n\nWrite **naturally**.\n\n- [ ] First task',
parent: document.querySelector('#editor')!,
extensions: [liveMarkdown()],
});
Omit the optional initialization and KaTeX CSS when those renderers are not installed; use math: false to disable formula previews. Unavailable syntax highlighting falls back to plain code. No manual document-level mouse listeners are needed.
Included behavior
| Area | Capabilities |
|---|---|
| Editing | Live / source / read-only reading modes, native code editing, drag selection, composition-aware updates |
| Text | Headings, emphasis, strikethrough, inline code, horizontal rules, quotes, hanging list indentation, task checkboxes |
| Note syntax | Highlights, comments, tags, wiki links and aliases, callouts with folding, footnote navigation, frontmatter recognition |
| Math | $…$, multiline $ blocks, legacy backtick math and math fences; optional KaTeX or custom renderer |
| Tables | Editable cells, Tab / Shift-Tab / Enter navigation, row/column actions, alignment, TSV grid paste, transaction history |
| Writing tools | Formatting commands, search/replace, folding, outline extraction, static or asynchronous wiki target completion |
| Host integration | Internal-link callbacks, image path resolution, wiki image sizes, attachment paste/drop saving callback, optional fenced-code renderers |
| Appearance | Complete light/dark themes, shared spacing and color variables, narrow-screen demo |
Frontmatter stays editable as source. Note/block transclusion, a property panel, vault indexing, backlinks, synchronization and a plugin marketplace are outside this editor implementation. A wiki target may contain #Heading or #^block; the host resolves it.
Preset options
liveMarkdown({
mode: 'live', // 'live' | 'source' | 'reading'
theme: 'light', // 'light' | 'dark' | false
codeBlocks: { interaction: 'inline', lineNumbers: false, copyButton: false },
tables: 'editable', // 'editable' | 'preview' | false
math: true,
images: { maxWidth: '100%', showAlt: true },
links: { onWikiLinkClick: target => openNote(target) },
wikiLinks: [{ target: 'Writing plan' }],
keybindings: true,
});
openNote is supplied by your application. images, links and codeBlocks also accept false. attachments and codeRenderers are opt-in; see integration examples.
The preset includes its Markdown language and history/search/folding/formatting setup. To reuse an existing editor's parser or history, compose the individual exports instead; avoid installing duplicate code or table renderers. keybindings: false omits history, search and folding together with the preset's editing keymap.
Code blocks support inline (preset default), auto (standalone codeBlockField default, source on cursor entry), and toggle (explicit MD/Code button). Incomplete fences remain editable. Reading mode is read-only in the preset; a mode facet used on its own changes presentation only.
Commands and themes
| Shortcut | Command |
|---|---|
| Ctrl / Cmd + B | toggleBold |
| Ctrl / Cmd + I | toggleItalic |
| Ctrl / Cmd + E | toggleInlineCode |
| Ctrl / Cmd + K | insertLink |
| Ctrl / Cmd + Shift + H | toggleHighlight |
| Ctrl / Cmd + Enter | toggleTask |
| Ctrl / Cmd + F | Search; CodeMirror's search panel also supports replacement |
Also exported: toggleStrikethrough, toggleInlineFormat, insertTable, getDocumentOutline, wikiLinkCompletion and individually configurable plugins. See src/index.ts for the public API.
#editor {
--md-font: system-ui, sans-serif;
--md-code-font: ui-monospace, monospace;
--md-font-size: 16px;
--md-padding: 24px;
--md-accent: #6751c7;
--md-code-bg: rgba(80, 90, 110, .055);
}
Variables accept complete CSS colors, including hex and hsl(...). Use theme: 'dark' or darkEditorTheme for the dark palette. The host controls the editor's outer width and scrolling container.
Development
npm run typecheck
npm run typecheck:demo
npm run lint
npm test
npm run build
npm run build:demo
npx playwright install chromium
npm run test:e2e
Use CHROME_PATH=/path/to/chrome to run browser tests with an installed browser. With the demo running, node scripts/capture.mjs captures desktop/mobile screenshots and long-document measurements. Browser traces and failure screenshots go to test-results/.
See CONTRIBUTING.md for implementation boundaries and manual acceptance checks. Automated composition and viewport tests do not replace real OS input-method, touch, or assistive-technology testing.
License
MIT. Based on blueberrycongee's CodeMirror Live Markdown library, inspired by Obsidian, and built on CodeMirror 6 and Lezer.