0
# Editor Management
1
2
The Editor class is the central orchestrator of the Milkdown editor, managing the complete lifecycle from initialization through destruction. It provides a fluent API for configuration and plugin management.
3
4
## Capabilities
5
6
### Editor Class
7
8
The main editor class that manages the entire editor lifecycle.
9
10
```typescript { .api }
11
/**
12
* The milkdown editor class that orchestrates editor lifecycle
13
*/
14
class Editor {
15
/** Create a new editor instance */
16
static make(): Editor;
17
18
/** Enable or disable inspector for debugging (default: true) */
19
enableInspector(enable?: boolean): Editor;
20
21
/** Subscribe to status change events - replaces previous subscription */
22
onStatusChange(onChange: OnStatusChange): Editor;
23
24
/** Add a configuration function to be executed during initialization */
25
config(configure: Config): Editor;
26
27
/** Remove a previously added configuration function */
28
removeConfig(configure: Config): Editor;
29
30
/** Add plugin(s) to the editor - can be single plugin or array */
31
use(plugins: MilkdownPlugin | MilkdownPlugin[]): Editor;
32
33
/** Remove plugin(s) from the editor - returns Promise for async cleanup */
34
remove(plugins: MilkdownPlugin | MilkdownPlugin[]): Promise<Editor>;
35
36
/** Create/initialize the editor with current config and plugins */
37
create(): Promise<Editor>;
38
39
/** Destroy the editor, optionally clearing all plugins */
40
destroy(clearPlugins?: boolean): Promise<Editor>;
41
42
/** Execute an action with access to the editor context */
43
action<T>(action: (ctx: Ctx) => T): T;
44
45
/** Get inspection data - requires inspector to be enabled */
46
inspect(): Telemetry[];
47
48
/** Get the editor's context instance */
49
readonly ctx: Ctx;
50
51
/** Get the current editor status */
52
readonly status: EditorStatus;
53
}
54
```
55
56
**Usage Examples:**
57
58
```typescript
59
import { Editor, EditorStatus } from "@milkdown/core";
60
61
// Basic editor creation
62
const editor = Editor.make()
63
.config((ctx) => {
64
// Configure context slices
65
ctx.set(rootCtx, document.getElementById('editor'));
66
})
67
.use([plugin1, plugin2]) // Add multiple plugins
68
.create(); // Returns Promise<Editor>
69
70
// Monitor status changes
71
editor.onStatusChange((status) => {
72
if (status === EditorStatus.Created) {
73
console.log('Editor ready!');
74
}
75
});
76
77
// Execute commands
78
editor.action((ctx) => {
79
const commandManager = ctx.get(commandsCtx);
80
commandManager.call(someCommand, payload);
81
});
82
83
// Cleanup
84
await editor.destroy(true); // Clear all plugins
85
```
86
87
### Editor Status
88
89
Enum representing the current state of the editor lifecycle.
90
91
```typescript { .api }
92
/**
93
* The status of the editor throughout its lifecycle
94
*/
95
enum EditorStatus {
96
/** The editor is not initialized */
97
Idle = 'Idle',
98
/** The editor is in the process of being created */
99
OnCreate = 'OnCreate',
100
/** The editor has been created and is ready to use */
101
Created = 'Created',
102
/** The editor is in the process of being destroyed */
103
OnDestroy = 'OnDestroy',
104
/** The editor has been destroyed */
105
Destroyed = 'Destroyed'
106
}
107
```
108
109
### Status Change Callback
110
111
Type for functions that respond to editor status changes.
112
113
```typescript { .api }
114
/**
115
* Callback function type for editor status changes
116
* @param status - The new editor status
117
*/
118
type OnStatusChange = (status: EditorStatus) => void;
119
```
120
121
**Usage Examples:**
122
123
```typescript
124
import { Editor, EditorStatus } from "@milkdown/core";
125
126
const editor = Editor.make()
127
.onStatusChange((status) => {
128
switch (status) {
129
case EditorStatus.OnCreate:
130
showLoadingSpinner();
131
break;
132
case EditorStatus.Created:
133
hideLoadingSpinner();
134
enableEditorFeatures();
135
break;
136
case EditorStatus.OnDestroy:
137
disableEditorFeatures();
138
break;
139
case EditorStatus.Destroyed:
140
cleanup();
141
break;
142
}
143
});
144
145
// Status is initially Idle
146
console.log(editor.status); // EditorStatus.Idle
147
148
// Status changes to OnCreate, then Created
149
await editor.create();
150
console.log(editor.status); // EditorStatus.Created
151
152
// Status changes to OnDestroy, then Destroyed
153
await editor.destroy();
154
console.log(editor.status); // EditorStatus.Destroyed
155
```
156
157
## Configuration Management
158
159
### Configuration Function Type
160
161
Type for configuration functions that modify the editor context during initialization.
162
163
```typescript { .api }
164
/**
165
* Configuration function type for customizing editor initialization
166
* @param ctx - The editor context to configure
167
*/
168
type Config = (ctx: Ctx) => void | Promise<void>;
169
```
170
171
**Usage Examples:**
172
173
```typescript
174
import { Editor, defaultValueCtx, rootCtx } from "@milkdown/core";
175
176
// Synchronous configuration
177
const syncConfig: Config = (ctx) => {
178
ctx.set(defaultValueCtx, '# Hello World\n\nThis is **bold** text.');
179
ctx.set(rootCtx, document.getElementById('editor'));
180
};
181
182
// Asynchronous configuration
183
const asyncConfig: Config = async (ctx) => {
184
const content = await fetch('/api/initial-content').then(r => r.text());
185
ctx.set(defaultValueCtx, content);
186
};
187
188
const editor = Editor.make()
189
.config(syncConfig)
190
.config(asyncConfig)
191
.removeConfig(syncConfig) // Remove if needed
192
.create();
193
```
194
195
## Plugin Management
196
197
**Adding Plugins:**
198
199
```typescript
200
import { Editor } from "@milkdown/core";
201
import { somePlugin, anotherPlugin } from "@milkdown/preset-plugins";
202
203
const editor = Editor.make()
204
.use(somePlugin) // Single plugin
205
.use([anotherPlugin, somePlugin]) // Multiple plugins
206
.create();
207
```
208
209
**Removing Plugins:**
210
211
```typescript
212
// Remove plugins after creation (async operation)
213
await editor.remove(somePlugin);
214
await editor.remove([plugin1, plugin2]);
215
```
216
217
## Inspector and Debugging
218
219
**Enable Inspector:**
220
221
```typescript
222
const editor = Editor.make()
223
.enableInspector(true) // Enable debugging
224
.create();
225
226
// Get telemetry data
227
const telemetry = editor.inspect();
228
console.log('Plugin telemetry:', telemetry);
229
```
230
231
## Error Handling
232
233
The editor provides several safeguards for common error scenarios:
234
235
- **Concurrent Operations**: If you try to remove plugins while editor is creating, it will wait and retry
236
- **Multiple Creations**: Creating an already-created editor will destroy and recreate it
237
- **Missing Inspector**: Calling `inspect()` without enabling inspector will log a warning and return empty array
238
- **Context Access**: The `action()` method ensures you have proper context access for operations
239
240
**Example Error Handling:**
241
242
```typescript
243
try {
244
const editor = Editor.make()
245
.config((ctx) => {
246
// Configuration that might throw
247
if (!document.getElementById('editor')) {
248
throw new Error('Editor root element not found');
249
}
250
ctx.set(rootCtx, document.getElementById('editor'));
251
})
252
.create();
253
254
// Safe action execution
255
editor.action((ctx) => {
256
const commands = ctx.get(commandsCtx);
257
if (!commands.call(someCommand, payload)) {
258
console.warn('Command execution failed');
259
}
260
});
261
} catch (error) {
262
console.error('Editor setup failed:', error);
263
}
264
```