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.00
# Milkdown Core
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: @milkdown/core
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @milkdown/core`
10
11
## Core Imports
12
13
```typescript
14
import { Editor } from "@milkdown/core";
15
```
16
17
For specific functionality:
18
19
```typescript
20
import {
21
Editor,
22
EditorStatus,
23
CommandManager,
24
KeymapManager,
25
createCmdKey
26
} from "@milkdown/core";
27
```
28
29
## Basic Usage
30
31
```typescript
32
import { Editor } from "@milkdown/core";
33
34
// Create a new editor instance
35
const editor = await Editor.make()
36
.config((ctx) => {
37
// Configure the editor context
38
})
39
.use(somePlugin) // Add plugins
40
.create(); // Initialize the editor
41
42
// Check editor status
43
console.log(editor.status); // EditorStatus.Created
44
45
// Execute actions with the editor context
46
editor.action((ctx) => {
47
// Access the editor context to perform operations
48
});
49
50
// Clean up when done
51
await editor.destroy();
52
```
53
54
## Architecture
55
56
Milkdown Core is built around several key components:
57
58
- **Editor Class**: Central editor instance managing the entire lifecycle from creation to destruction
59
- **Context System**: Dependency injection system (`Ctx`) managing slices of state and functionality
60
- **Plugin Architecture**: Modular system where all functionality is implemented as plugins
61
- **Internal Plugins**: Core plugins that provide fundamental features (schema, parser, serializer, commands, etc.)
62
- **Command System**: Type-safe command registration and execution system
63
- **Keymap Management**: Keyboard shortcut handling with priority-based execution
64
65
## Capabilities
66
67
### Editor Lifecycle Management
68
69
The core Editor class that orchestrates the entire editor lifecycle, from initialization through destruction.
70
71
```typescript { .api }
72
class Editor {
73
static make(): Editor;
74
75
enableInspector(enable?: boolean): Editor;
76
onStatusChange(onChange: OnStatusChange): Editor;
77
config(configure: Config): Editor;
78
removeConfig(configure: Config): Editor;
79
use(plugins: MilkdownPlugin | MilkdownPlugin[]): Editor;
80
remove(plugins: MilkdownPlugin | MilkdownPlugin[]): Promise<Editor>;
81
create(): Promise<Editor>;
82
destroy(clearPlugins?: boolean): Promise<Editor>;
83
action<T>(action: (ctx: Ctx) => T): T;
84
inspect(): Telemetry[];
85
86
readonly ctx: Ctx;
87
readonly status: EditorStatus;
88
}
89
90
enum EditorStatus {
91
Idle = 'Idle',
92
OnCreate = 'OnCreate',
93
Created = 'Created',
94
OnDestroy = 'OnDestroy',
95
Destroyed = 'Destroyed'
96
}
97
98
type OnStatusChange = (status: EditorStatus) => void;
99
```
100
101
[Editor Management](./editor-management.md)
102
103
### Command System
104
105
Type-safe command registration and execution system for editor actions.
106
107
```typescript { .api }
108
class CommandManager {
109
create<T>(meta: CmdKey<T>, value: Cmd<T>): void;
110
get<T>(slice: CmdKey<T>): Cmd<T>;
111
remove<T>(slice: CmdKey<T>): void;
112
call<T>(slice: CmdKey<T>, payload?: T): boolean;
113
inline(command: Command): boolean;
114
chain(): CommandChain;
115
116
readonly ctx: Ctx | null;
117
}
118
119
function createCmdKey<T = undefined>(key?: string): CmdKey<T>;
120
121
interface CommandChain {
122
run(): boolean;
123
inline(command: Command): CommandChain;
124
pipe<T>(slice: CmdKey<T>, payload?: T): CommandChain;
125
}
126
```
127
128
[Command System](./command-system.md)
129
130
### Keymap Management
131
132
Keyboard shortcut handling with priority-based execution and chainable commands.
133
134
```typescript { .api }
135
class KeymapManager {
136
add(keymap: KeymapItem): () => void;
137
addObjectKeymap(keymaps: Record<string, Command | KeymapItem>): () => void;
138
addBaseKeymap(): () => void;
139
140
readonly ctx: Ctx | null;
141
}
142
143
interface KeymapItem {
144
key: string;
145
onRun: (ctx: Ctx) => Command;
146
priority?: number;
147
}
148
```
149
150
[Keymap Management](./keymap-management.md)
151
152
### Context System
153
154
The dependency injection and state management system that powers all Milkdown functionality.
155
156
```typescript { .api }
157
// Context slices for core functionality
158
const editorViewCtx: SliceType<EditorView, 'editorView'>;
159
const editorStateCtx: SliceType<EditorState, 'editorState'>;
160
const editorCtx: SliceType<Editor, 'editor'>;
161
const schemaCtx: SliceType<Schema, 'schema'>;
162
const parserCtx: SliceType<Parser, 'parser'>;
163
const serializerCtx: SliceType<Serializer, 'serializer'>;
164
const commandsCtx: SliceType<CommandManager, 'commands'>;
165
const keymapCtx: SliceType<KeymapManager, 'keymap'>;
166
167
// Configuration slices
168
const defaultValueCtx: SliceType<DefaultValue, 'defaultValue'>;
169
const rootCtx: SliceType<RootType, 'root'>;
170
const rootAttrsCtx: SliceType<Record<string, string>, 'rootAttrs'>;
171
const editorViewOptionsCtx: SliceType<Partial<EditorOptions>, 'editorViewOptions'>;
172
173
// Plugin and rule storage slices
174
const inputRulesCtx: SliceType<InputRule[], 'inputRules'>;
175
const prosePluginsCtx: SliceType<Plugin[], 'prosePlugins'>;
176
const remarkPluginsCtx: SliceType<RemarkPlugin[], 'remarkPlugins'>;
177
const nodeViewCtx: SliceType<NodeView[], 'nodeView'>;
178
const markViewCtx: SliceType<MarkView[], 'markView'>;
179
180
// Schema definition slices
181
const nodesCtx: SliceType<Array<[string, NodeSchema]>, 'nodes'>;
182
const marksCtx: SliceType<Array<[string, MarkSchema]>, 'marks'>;
183
184
// Remark processing slices
185
const remarkCtx: SliceType<RemarkParser, 'remark'>;
186
const remarkStringifyOptionsCtx: SliceType<Options, 'remarkStringifyOptions'>;
187
```
188
189
[Context System](./context-system.md)
190
191
### Internal Plugins
192
193
Core plugins that provide fundamental editor functionality, automatically loaded during editor creation.
194
195
```typescript { .api }
196
// Core internal plugins
197
const schema: MilkdownPlugin;
198
const parser: MilkdownPlugin;
199
const serializer: MilkdownPlugin;
200
const commands: MilkdownPlugin;
201
const keymap: MilkdownPlugin;
202
const editorState: MilkdownPlugin;
203
const editorView: MilkdownPlugin;
204
205
// Configuration and initialization
206
function config(configure: Config): MilkdownPlugin;
207
function init(editor: Editor): MilkdownPlugin;
208
209
// Plugin timing system
210
const ConfigReady: TimerType;
211
const InitReady: TimerType;
212
const SchemaReady: TimerType;
213
const ParserReady: TimerType;
214
const SerializerReady: TimerType;
215
const CommandsReady: TimerType;
216
const KeymapReady: TimerType;
217
const EditorStateReady: TimerType;
218
const EditorViewReady: TimerType;
219
```
220
221
[Internal Plugins](./internal-plugins.md)
222
223
## Types
224
225
```typescript { .api }
226
// Configuration and lifecycle types
227
type Config = (ctx: Ctx) => void | Promise<void>;
228
229
// Default value types for editor initialization
230
type DefaultValue =
231
| string
232
| { type: 'html'; dom: HTMLElement }
233
| { type: 'json'; value: JSONRecord };
234
235
// JSON record type for structured default values
236
type JSONRecord = Record<string, any>;
237
238
// Command system types
239
type Cmd<T = undefined> = (payload?: T) => Command;
240
type CmdKey<T = undefined> = SliceType<Cmd<T>>;
241
242
// Keymap types
243
type KeymapKey = SliceType<KeymapItem>;
244
245
// View types
246
type NodeView = [nodeId: string, view: NodeViewConstructor];
247
type MarkView = [markId: string, view: MarkViewConstructor];
248
type RootType = Node | undefined | null | string;
249
type EditorOptions = Omit<DirectEditorProps, 'state'>;
250
251
// State management types
252
type StateOptions = Parameters<typeof EditorState.create>[0];
253
type StateOptionsOverride = (prev: StateOptions) => StateOptions;
254
255
// Timer management types
256
const initTimerCtx: SliceType<TimerType[], 'initTimer'>;
257
const schemaTimerCtx: SliceType<TimerType[], 'schemaTimer'>;
258
const parserTimerCtx: SliceType<TimerType[], 'parserTimer'>;
259
const serializerTimerCtx: SliceType<TimerType[], 'serializerTimer'>;
260
const commandsTimerCtx: SliceType<TimerType[], 'commandsTimer'>;
261
const keymapTimerCtx: SliceType<TimerType[], 'keymapTimer'>;
262
const editorStateTimerCtx: SliceType<TimerType[], 'editorStateTimer'>;
263
const editorViewTimerCtx: SliceType<TimerType[], 'editorViewTimer'>;
264
265
// Plugin metadata type
266
interface Meta {
267
displayName: string;
268
package?: string;
269
group?: string;
270
}
271
```
272
273
## Internal Utilities
274
275
```typescript { .api }
276
/**
277
* Adds metadata to a Milkdown plugin for debugging and inspection
278
* @param plugin - The plugin to add metadata to
279
* @param meta - Metadata including displayName and optional package/group info
280
* @returns The plugin with metadata attached
281
*/
282
function withMeta<T extends MilkdownPlugin>(
283
plugin: T,
284
meta: Partial<Meta> & Pick<Meta, 'displayName'>
285
): T;
286
287
/**
288
* Creates a ProseMirror document from default value using parser and schema
289
* @param defaultValue - Initial content (string, HTML element, or JSON)
290
* @param parser - The markdown parser instance
291
* @param schema - The ProseMirror schema
292
* @returns ProseMirror document node
293
*/
294
function getDoc(
295
defaultValue: DefaultValue,
296
parser: Parser,
297
schema: Schema
298
): Node;
299
300
/**
301
* Custom remark handlers for enhanced markdown processing
302
* Includes handlers for text, strong, and emphasis with special processing
303
*/
304
const remarkHandlers: Required<Options>['handlers'];
305
```