or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

editor-management.mddocs/

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

```