or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

command-system.mdcontext-system.mdeditor-management.mdindex.mdinternal-plugins.mdkeymap-management.md
tile.json

tessl/npm-milkdown--core

The core module of milkdown - a plugin-driven WYSIWYG markdown Editor built on top of prosemirror and remark

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@milkdown/core@7.15.x

To install, run

npx @tessl/cli install tessl/npm-milkdown--core@7.15.0

index.mddocs/

Milkdown Core

Milkdown 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.

Package Information

  • Package Name: @milkdown/core
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @milkdown/core

Core Imports

import { Editor } from "@milkdown/core";

For specific functionality:

import { 
  Editor, 
  EditorStatus,
  CommandManager,
  KeymapManager,
  createCmdKey
} from "@milkdown/core";

Basic Usage

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();

Architecture

Milkdown Core is built around several key components:

  • Editor Class: Central editor instance managing the entire lifecycle from creation to destruction
  • Context System: Dependency injection system (Ctx) managing slices of state and functionality
  • Plugin Architecture: Modular system where all functionality is implemented as plugins
  • Internal Plugins: Core plugins that provide fundamental features (schema, parser, serializer, commands, etc.)
  • Command System: Type-safe command registration and execution system
  • Keymap Management: Keyboard shortcut handling with priority-based execution

Capabilities

Editor Lifecycle Management

The 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;

Editor Management

Command System

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;
}

Command System

Keymap Management

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;
}

Keymap Management

Context System

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'>;

Context System

Internal Plugins

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;

Internal Plugins

Types

// 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;
}

Internal Utilities

/**
 * 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'];