The core module of milkdown - a plugin-driven WYSIWYG markdown Editor built on top of prosemirror and remark
npx @tessl/cli install tessl/npm-milkdown--core@7.15.0Milkdown Core is the foundational module of the Milkdown editor framework - a plugin-driven WYSIWYG markdown editor built on top of ProseMirror and Remark. It provides the essential runtime, editor lifecycle management, and plugin architecture that enables the creation of extensible markdown editors.
npm install @milkdown/coreimport { Editor } from "@milkdown/core";For specific functionality:
import {
Editor,
EditorStatus,
CommandManager,
KeymapManager,
createCmdKey
} from "@milkdown/core";import { Editor } from "@milkdown/core";
// Create a new editor instance
const editor = await Editor.make()
.config((ctx) => {
// Configure the editor context
})
.use(somePlugin) // Add plugins
.create(); // Initialize the editor
// Check editor status
console.log(editor.status); // EditorStatus.Created
// Execute actions with the editor context
editor.action((ctx) => {
// Access the editor context to perform operations
});
// Clean up when done
await editor.destroy();Milkdown Core is built around several key components:
Ctx) managing slices of state and functionalityThe core Editor class that orchestrates the entire editor lifecycle, from initialization through destruction.
class Editor {
static make(): Editor;
enableInspector(enable?: boolean): Editor;
onStatusChange(onChange: OnStatusChange): Editor;
config(configure: Config): Editor;
removeConfig(configure: Config): Editor;
use(plugins: MilkdownPlugin | MilkdownPlugin[]): Editor;
remove(plugins: MilkdownPlugin | MilkdownPlugin[]): Promise<Editor>;
create(): Promise<Editor>;
destroy(clearPlugins?: boolean): Promise<Editor>;
action<T>(action: (ctx: Ctx) => T): T;
inspect(): Telemetry[];
readonly ctx: Ctx;
readonly status: EditorStatus;
}
enum EditorStatus {
Idle = 'Idle',
OnCreate = 'OnCreate',
Created = 'Created',
OnDestroy = 'OnDestroy',
Destroyed = 'Destroyed'
}
type OnStatusChange = (status: EditorStatus) => void;Type-safe command registration and execution system for editor actions.
class CommandManager {
create<T>(meta: CmdKey<T>, value: Cmd<T>): void;
get<T>(slice: CmdKey<T>): Cmd<T>;
remove<T>(slice: CmdKey<T>): void;
call<T>(slice: CmdKey<T>, payload?: T): boolean;
inline(command: Command): boolean;
chain(): CommandChain;
readonly ctx: Ctx | null;
}
function createCmdKey<T = undefined>(key?: string): CmdKey<T>;
interface CommandChain {
run(): boolean;
inline(command: Command): CommandChain;
pipe<T>(slice: CmdKey<T>, payload?: T): CommandChain;
}Keyboard shortcut handling with priority-based execution and chainable commands.
class KeymapManager {
add(keymap: KeymapItem): () => void;
addObjectKeymap(keymaps: Record<string, Command | KeymapItem>): () => void;
addBaseKeymap(): () => void;
readonly ctx: Ctx | null;
}
interface KeymapItem {
key: string;
onRun: (ctx: Ctx) => Command;
priority?: number;
}The dependency injection and state management system that powers all Milkdown functionality.
// Context slices for core functionality
const editorViewCtx: SliceType<EditorView, 'editorView'>;
const editorStateCtx: SliceType<EditorState, 'editorState'>;
const editorCtx: SliceType<Editor, 'editor'>;
const schemaCtx: SliceType<Schema, 'schema'>;
const parserCtx: SliceType<Parser, 'parser'>;
const serializerCtx: SliceType<Serializer, 'serializer'>;
const commandsCtx: SliceType<CommandManager, 'commands'>;
const keymapCtx: SliceType<KeymapManager, 'keymap'>;
// Configuration slices
const defaultValueCtx: SliceType<DefaultValue, 'defaultValue'>;
const rootCtx: SliceType<RootType, 'root'>;
const rootAttrsCtx: SliceType<Record<string, string>, 'rootAttrs'>;
const editorViewOptionsCtx: SliceType<Partial<EditorOptions>, 'editorViewOptions'>;
// Plugin and rule storage slices
const inputRulesCtx: SliceType<InputRule[], 'inputRules'>;
const prosePluginsCtx: SliceType<Plugin[], 'prosePlugins'>;
const remarkPluginsCtx: SliceType<RemarkPlugin[], 'remarkPlugins'>;
const nodeViewCtx: SliceType<NodeView[], 'nodeView'>;
const markViewCtx: SliceType<MarkView[], 'markView'>;
// Schema definition slices
const nodesCtx: SliceType<Array<[string, NodeSchema]>, 'nodes'>;
const marksCtx: SliceType<Array<[string, MarkSchema]>, 'marks'>;
// Remark processing slices
const remarkCtx: SliceType<RemarkParser, 'remark'>;
const remarkStringifyOptionsCtx: SliceType<Options, 'remarkStringifyOptions'>;Core plugins that provide fundamental editor functionality, automatically loaded during editor creation.
// Core internal plugins
const schema: MilkdownPlugin;
const parser: MilkdownPlugin;
const serializer: MilkdownPlugin;
const commands: MilkdownPlugin;
const keymap: MilkdownPlugin;
const editorState: MilkdownPlugin;
const editorView: MilkdownPlugin;
// Configuration and initialization
function config(configure: Config): MilkdownPlugin;
function init(editor: Editor): MilkdownPlugin;
// Plugin timing system
const ConfigReady: TimerType;
const InitReady: TimerType;
const SchemaReady: TimerType;
const ParserReady: TimerType;
const SerializerReady: TimerType;
const CommandsReady: TimerType;
const KeymapReady: TimerType;
const EditorStateReady: TimerType;
const EditorViewReady: TimerType;// Configuration and lifecycle types
type Config = (ctx: Ctx) => void | Promise<void>;
// Default value types for editor initialization
type DefaultValue =
| string
| { type: 'html'; dom: HTMLElement }
| { type: 'json'; value: JSONRecord };
// JSON record type for structured default values
type JSONRecord = Record<string, any>;
// Command system types
type Cmd<T = undefined> = (payload?: T) => Command;
type CmdKey<T = undefined> = SliceType<Cmd<T>>;
// Keymap types
type KeymapKey = SliceType<KeymapItem>;
// View types
type NodeView = [nodeId: string, view: NodeViewConstructor];
type MarkView = [markId: string, view: MarkViewConstructor];
type RootType = Node | undefined | null | string;
type EditorOptions = Omit<DirectEditorProps, 'state'>;
// State management types
type StateOptions = Parameters<typeof EditorState.create>[0];
type StateOptionsOverride = (prev: StateOptions) => StateOptions;
// Timer management types
const initTimerCtx: SliceType<TimerType[], 'initTimer'>;
const schemaTimerCtx: SliceType<TimerType[], 'schemaTimer'>;
const parserTimerCtx: SliceType<TimerType[], 'parserTimer'>;
const serializerTimerCtx: SliceType<TimerType[], 'serializerTimer'>;
const commandsTimerCtx: SliceType<TimerType[], 'commandsTimer'>;
const keymapTimerCtx: SliceType<TimerType[], 'keymapTimer'>;
const editorStateTimerCtx: SliceType<TimerType[], 'editorStateTimer'>;
const editorViewTimerCtx: SliceType<TimerType[], 'editorViewTimer'>;
// Plugin metadata type
interface Meta {
displayName: string;
package?: string;
group?: string;
}/**
* Adds metadata to a Milkdown plugin for debugging and inspection
* @param plugin - The plugin to add metadata to
* @param meta - Metadata including displayName and optional package/group info
* @returns The plugin with metadata attached
*/
function withMeta<T extends MilkdownPlugin>(
plugin: T,
meta: Partial<Meta> & Pick<Meta, 'displayName'>
): T;
/**
* Creates a ProseMirror document from default value using parser and schema
* @param defaultValue - Initial content (string, HTML element, or JSON)
* @param parser - The markdown parser instance
* @param schema - The ProseMirror schema
* @returns ProseMirror document node
*/
function getDoc(
defaultValue: DefaultValue,
parser: Parser,
schema: Schema
): Node;
/**
* Custom remark handlers for enhanced markdown processing
* Includes handlers for text, strong, and emphasis with special processing
*/
const remarkHandlers: Required<Options>['handlers'];