@jvs-milkdown/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/lib/__internal__/index.d.ts +3 -0
  4. package/lib/__internal__/index.d.ts.map +1 -0
  5. package/lib/__internal__/remark-handlers.d.ts +3 -0
  6. package/lib/__internal__/remark-handlers.d.ts.map +1 -0
  7. package/lib/__internal__/utils.d.ts +3 -0
  8. package/lib/__internal__/utils.d.ts.map +1 -0
  9. package/lib/editor/editor.d.ts +28 -0
  10. package/lib/editor/editor.d.ts.map +1 -0
  11. package/lib/editor/index.d.ts +2 -0
  12. package/lib/editor/index.d.ts.map +1 -0
  13. package/lib/index.d.ts +3 -0
  14. package/lib/index.d.ts.map +1 -0
  15. package/lib/index.js +676 -0
  16. package/lib/index.js.map +1 -0
  17. package/lib/internal-plugin/atoms.d.ts +22 -0
  18. package/lib/internal-plugin/atoms.d.ts.map +1 -0
  19. package/lib/internal-plugin/commands.d.ts +38 -0
  20. package/lib/internal-plugin/commands.d.ts.map +1 -0
  21. package/lib/internal-plugin/config.d.ts +5 -0
  22. package/lib/internal-plugin/config.d.ts.map +1 -0
  23. package/lib/internal-plugin/editor-state.d.ts +22 -0
  24. package/lib/internal-plugin/editor-state.d.ts.map +1 -0
  25. package/lib/internal-plugin/editor-view.d.ts +13 -0
  26. package/lib/internal-plugin/editor-view.d.ts.map +1 -0
  27. package/lib/internal-plugin/index.d.ts +12 -0
  28. package/lib/internal-plugin/index.d.ts.map +1 -0
  29. package/lib/internal-plugin/init.d.ts +5 -0
  30. package/lib/internal-plugin/init.d.ts.map +1 -0
  31. package/lib/internal-plugin/keymap.d.ts +22 -0
  32. package/lib/internal-plugin/keymap.d.ts.map +1 -0
  33. package/lib/internal-plugin/keymap.test.d.ts +2 -0
  34. package/lib/internal-plugin/keymap.test.d.ts.map +1 -0
  35. package/lib/internal-plugin/parser.d.ts +7 -0
  36. package/lib/internal-plugin/parser.d.ts.map +1 -0
  37. package/lib/internal-plugin/paste-rule.d.ts +12 -0
  38. package/lib/internal-plugin/paste-rule.d.ts.map +1 -0
  39. package/lib/internal-plugin/schema.d.ts +10 -0
  40. package/lib/internal-plugin/schema.d.ts.map +1 -0
  41. package/lib/internal-plugin/serializer.d.ts +7 -0
  42. package/lib/internal-plugin/serializer.d.ts.map +1 -0
  43. package/lib/tsconfig.tsbuildinfo +1 -0
  44. package/package.json +45 -0
  45. package/src/__internal__/index.ts +2 -0
  46. package/src/__internal__/remark-handlers.ts +48 -0
  47. package/src/__internal__/utils.ts +14 -0
  48. package/src/editor/editor.ts +300 -0
  49. package/src/editor/index.ts +1 -0
  50. package/src/index.ts +2 -0
  51. package/src/internal-plugin/atoms.ts +69 -0
  52. package/src/internal-plugin/commands.ts +176 -0
  53. package/src/internal-plugin/config.ts +34 -0
  54. package/src/internal-plugin/editor-state.ts +140 -0
  55. package/src/internal-plugin/editor-view.ts +166 -0
  56. package/src/internal-plugin/index.ts +11 -0
  57. package/src/internal-plugin/init.ts +78 -0
  58. package/src/internal-plugin/keymap.test.ts +136 -0
  59. package/src/internal-plugin/keymap.ts +167 -0
  60. package/src/internal-plugin/parser.ts +51 -0
  61. package/src/internal-plugin/paste-rule.ts +53 -0
  62. package/src/internal-plugin/schema.ts +88 -0
  63. package/src/internal-plugin/serializer.ts +61 -0
package/lib/index.js ADDED
@@ -0,0 +1,676 @@
1
+ import { Clock, Container, Ctx, createSlice, createTimer } from "@jvs-milkdown/ctx";
2
+ import remarkParse from "remark-parse";
3
+ import remarkStringify from "remark-stringify";
4
+ import { unified } from "unified";
5
+ import { callCommandBeforeEditorView, ctxCallOutOfScope, docTypeError } from "@jvs-milkdown/exception";
6
+ import { baseKeymap, chainCommands, deleteSelection, joinTextblockBackward, selectNodeBackward } from "@jvs-milkdown/prose/commands";
7
+ import { DOMParser, Node, Schema } from "@jvs-milkdown/prose/model";
8
+ import { customInputRules } from "@jvs-milkdown/prose";
9
+ import { keymap as keymap$1 } from "@jvs-milkdown/prose/keymap";
10
+ import { EditorState, Plugin, PluginKey } from "@jvs-milkdown/prose/state";
11
+ import { undoInputRule } from "@jvs-milkdown/prose/inputrules";
12
+ import { ParserState, SerializerState } from "@jvs-milkdown/transformer";
13
+ import { EditorView } from "@jvs-milkdown/prose/view";
14
+ //#region src/__internal__/utils.ts
15
+ function withMeta(plugin, meta) {
16
+ plugin.meta = {
17
+ package: "@jvs-milkdown/core",
18
+ group: "System",
19
+ ...meta
20
+ };
21
+ return plugin;
22
+ }
23
+ //#endregion
24
+ //#region src/__internal__/remark-handlers.ts
25
+ var remarkHandlers = {
26
+ text: (node, _, state, info) => {
27
+ const value = node.value;
28
+ if (/^[^*_\\]*\s+$/.test(value)) return value;
29
+ return state.safe(value, {
30
+ ...info,
31
+ encode: []
32
+ });
33
+ },
34
+ strong: (node, _, state, info) => {
35
+ const marker = node.marker || state.options.strong || "*";
36
+ const exit = state.enter("strong");
37
+ const tracker = state.createTracker(info);
38
+ let value = tracker.move(marker + marker);
39
+ value += tracker.move(state.containerPhrasing(node, {
40
+ before: value,
41
+ after: marker,
42
+ ...tracker.current()
43
+ }));
44
+ value += tracker.move(marker + marker);
45
+ exit();
46
+ return value;
47
+ },
48
+ emphasis: (node, _, state, info) => {
49
+ const marker = node.marker || state.options.emphasis || "*";
50
+ const exit = state.enter("emphasis");
51
+ const tracker = state.createTracker(info);
52
+ let value = tracker.move(marker);
53
+ value += tracker.move(state.containerPhrasing(node, {
54
+ before: value,
55
+ after: marker,
56
+ ...tracker.current()
57
+ }));
58
+ value += tracker.move(marker);
59
+ exit();
60
+ return value;
61
+ }
62
+ };
63
+ //#endregion
64
+ //#region src/internal-plugin/atoms.ts
65
+ var editorViewCtx = createSlice({}, "editorView");
66
+ var editorStateCtx = createSlice({}, "editorState");
67
+ var initTimerCtx = createSlice([], "initTimer");
68
+ var editorCtx = createSlice({}, "editor");
69
+ var inputRulesCtx = createSlice([], "inputRules");
70
+ var prosePluginsCtx = createSlice([], "prosePlugins");
71
+ var remarkPluginsCtx = createSlice([], "remarkPlugins");
72
+ var nodeViewCtx = createSlice([], "nodeView");
73
+ var markViewCtx = createSlice([], "markView");
74
+ var remarkCtx = createSlice(unified().use(remarkParse).use(remarkStringify), "remark");
75
+ var remarkStringifyOptionsCtx = createSlice({
76
+ handlers: remarkHandlers,
77
+ encode: []
78
+ }, "remarkStringifyOptions");
79
+ //#endregion
80
+ //#region src/internal-plugin/config.ts
81
+ var ConfigReady = createTimer("ConfigReady");
82
+ function config(configure) {
83
+ const plugin = (ctx) => {
84
+ ctx.record(ConfigReady);
85
+ return async () => {
86
+ await configure(ctx);
87
+ ctx.done(ConfigReady);
88
+ return () => {
89
+ ctx.clearTimer(ConfigReady);
90
+ };
91
+ };
92
+ };
93
+ withMeta(plugin, { displayName: "Config" });
94
+ return plugin;
95
+ }
96
+ //#endregion
97
+ //#region src/internal-plugin/init.ts
98
+ var InitReady = createTimer("InitReady");
99
+ function init(editor) {
100
+ const plugin = (ctx) => {
101
+ ctx.inject(editorCtx, editor).inject(prosePluginsCtx, []).inject(remarkPluginsCtx, []).inject(inputRulesCtx, []).inject(nodeViewCtx, []).inject(markViewCtx, []).inject(remarkStringifyOptionsCtx, {
102
+ handlers: remarkHandlers,
103
+ encode: []
104
+ }).inject(remarkCtx, unified().use(remarkParse).use(remarkStringify)).inject(initTimerCtx, [ConfigReady]).record(InitReady);
105
+ return async () => {
106
+ await ctx.waitTimers(initTimerCtx);
107
+ const options = ctx.get(remarkStringifyOptionsCtx);
108
+ ctx.set(remarkCtx, unified().use(remarkParse).use(remarkStringify, options));
109
+ ctx.done(InitReady);
110
+ return () => {
111
+ ctx.remove(editorCtx).remove(prosePluginsCtx).remove(remarkPluginsCtx).remove(inputRulesCtx).remove(nodeViewCtx).remove(markViewCtx).remove(remarkStringifyOptionsCtx).remove(remarkCtx).remove(initTimerCtx).clearTimer(InitReady);
112
+ };
113
+ };
114
+ };
115
+ withMeta(plugin, { displayName: "Init" });
116
+ return plugin;
117
+ }
118
+ //#endregion
119
+ //#region src/internal-plugin/schema.ts
120
+ var SchemaReady = createTimer("SchemaReady");
121
+ var schemaTimerCtx = createSlice([], "schemaTimer");
122
+ var schemaCtx = createSlice({}, "schema");
123
+ var nodesCtx = createSlice([], "nodes");
124
+ var marksCtx = createSlice([], "marks");
125
+ function extendPriority(x) {
126
+ return {
127
+ ...x,
128
+ parseDOM: x.parseDOM?.map((rule) => ({
129
+ priority: x.priority,
130
+ ...rule
131
+ }))
132
+ };
133
+ }
134
+ var schema = (ctx) => {
135
+ ctx.inject(schemaCtx, {}).inject(nodesCtx, []).inject(marksCtx, []).inject(schemaTimerCtx, [InitReady]).record(SchemaReady);
136
+ return async () => {
137
+ await ctx.waitTimers(schemaTimerCtx);
138
+ const remark = ctx.get(remarkCtx);
139
+ const processor = ctx.get(remarkPluginsCtx).reduce((acc, plug) => acc.use(plug.plugin, plug.options), remark);
140
+ ctx.set(remarkCtx, processor);
141
+ const schema = new Schema({
142
+ nodes: Object.fromEntries(ctx.get(nodesCtx).map(([key, x]) => [key, extendPriority(x)])),
143
+ marks: Object.fromEntries(ctx.get(marksCtx).map(([key, x]) => [key, extendPriority(x)]))
144
+ });
145
+ ctx.set(schemaCtx, schema);
146
+ ctx.done(SchemaReady);
147
+ return () => {
148
+ ctx.remove(schemaCtx).remove(nodesCtx).remove(marksCtx).remove(schemaTimerCtx).clearTimer(SchemaReady);
149
+ };
150
+ };
151
+ };
152
+ withMeta(schema, { displayName: "Schema" });
153
+ //#endregion
154
+ //#region src/internal-plugin/commands.ts
155
+ var CommandManager = class {
156
+ constructor() {
157
+ this.setCtx = (ctx) => {
158
+ this.#ctx = ctx;
159
+ };
160
+ this.chain = () => {
161
+ if (this.#ctx == null) throw callCommandBeforeEditorView();
162
+ const ctx = this.#ctx;
163
+ const commands = [];
164
+ const get = this.get.bind(this);
165
+ const chains = {
166
+ run: () => {
167
+ const chained = chainCommands(...commands);
168
+ const view = ctx.get(editorViewCtx);
169
+ return chained(view.state, view.dispatch, view);
170
+ },
171
+ inline: (command) => {
172
+ commands.push(command);
173
+ return chains;
174
+ },
175
+ pipe: pipe.bind(this)
176
+ };
177
+ function pipe(slice, payload) {
178
+ const cmd = get(slice);
179
+ commands.push(cmd(payload));
180
+ return chains;
181
+ }
182
+ return chains;
183
+ };
184
+ }
185
+ #container = new Container();
186
+ #ctx = null;
187
+ get ctx() {
188
+ return this.#ctx;
189
+ }
190
+ create(meta, value) {
191
+ const slice = meta.create(this.#container.sliceMap);
192
+ slice.set(value);
193
+ return slice;
194
+ }
195
+ get(slice) {
196
+ return this.#container.get(slice).get();
197
+ }
198
+ remove(slice) {
199
+ return this.#container.remove(slice);
200
+ }
201
+ call(slice, payload) {
202
+ if (this.#ctx == null) throw callCommandBeforeEditorView();
203
+ const command = this.get(slice)(payload);
204
+ const view = this.#ctx.get(editorViewCtx);
205
+ return command(view.state, view.dispatch, view);
206
+ }
207
+ inline(command) {
208
+ if (this.#ctx == null) throw callCommandBeforeEditorView();
209
+ const view = this.#ctx.get(editorViewCtx);
210
+ return command(view.state, view.dispatch, view);
211
+ }
212
+ };
213
+ function createCmdKey(key = "cmdKey") {
214
+ return createSlice((() => () => false), key);
215
+ }
216
+ var commandsCtx = createSlice(new CommandManager(), "commands");
217
+ var commandsTimerCtx = createSlice([SchemaReady], "commandsTimer");
218
+ var CommandsReady = createTimer("CommandsReady");
219
+ var commands = (ctx) => {
220
+ const cmd = new CommandManager();
221
+ cmd.setCtx(ctx);
222
+ ctx.inject(commandsCtx, cmd).inject(commandsTimerCtx, [SchemaReady]).record(CommandsReady);
223
+ return async () => {
224
+ await ctx.waitTimers(commandsTimerCtx);
225
+ ctx.done(CommandsReady);
226
+ return () => {
227
+ ctx.remove(commandsCtx).remove(commandsTimerCtx).clearTimer(CommandsReady);
228
+ };
229
+ };
230
+ };
231
+ withMeta(commands, { displayName: "Commands" });
232
+ //#endregion
233
+ //#region src/internal-plugin/keymap.ts
234
+ function overrideBaseKeymap(keymap) {
235
+ keymap.Backspace = chainCommands(undoInputRule, deleteSelection, joinTextblockBackward, selectNodeBackward);
236
+ return keymap;
237
+ }
238
+ var KeymapManager = class {
239
+ constructor() {
240
+ this.setCtx = (ctx) => {
241
+ this.#ctx = ctx;
242
+ };
243
+ this.add = (keymap) => {
244
+ this.#keymap.push(keymap);
245
+ return () => {
246
+ this.#keymap = this.#keymap.filter((item) => item !== keymap);
247
+ };
248
+ };
249
+ this.addObjectKeymap = (keymaps) => {
250
+ const remove = [];
251
+ Object.entries(keymaps).forEach(([key, command]) => {
252
+ if (typeof command === "function") {
253
+ const keymapItem = {
254
+ key,
255
+ onRun: () => command
256
+ };
257
+ this.#keymap.push(keymapItem);
258
+ remove.push(() => {
259
+ this.#keymap = this.#keymap.filter((item) => item !== keymapItem);
260
+ });
261
+ } else {
262
+ this.#keymap.push(command);
263
+ remove.push(() => {
264
+ this.#keymap = this.#keymap.filter((item) => item !== command);
265
+ });
266
+ }
267
+ });
268
+ return () => {
269
+ remove.forEach((fn) => fn());
270
+ };
271
+ };
272
+ this.addBaseKeymap = () => {
273
+ const base = overrideBaseKeymap(baseKeymap);
274
+ return this.addObjectKeymap(base);
275
+ };
276
+ this.build = () => {
277
+ const keymap = {};
278
+ this.#keymap.forEach((item) => {
279
+ keymap[item.key] = [...keymap[item.key] || [], item];
280
+ });
281
+ return Object.fromEntries(Object.entries(keymap).map(([key, items]) => {
282
+ const sortedItems = items.sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
283
+ const command = (state, dispatch, view) => {
284
+ const ctx = this.#ctx;
285
+ if (ctx == null) throw ctxCallOutOfScope();
286
+ return chainCommands(...sortedItems.map((item) => item.onRun(ctx)))(state, dispatch, view);
287
+ };
288
+ return [key, command];
289
+ }));
290
+ };
291
+ }
292
+ #ctx = null;
293
+ #keymap = [];
294
+ get ctx() {
295
+ return this.#ctx;
296
+ }
297
+ };
298
+ var keymapCtx = createSlice(new KeymapManager(), "keymap");
299
+ var keymapTimerCtx = createSlice([SchemaReady], "keymapTimer");
300
+ var KeymapReady = createTimer("KeymapReady");
301
+ var keymap = (ctx) => {
302
+ const km = new KeymapManager();
303
+ km.setCtx(ctx);
304
+ ctx.inject(keymapCtx, km).inject(keymapTimerCtx, [SchemaReady]).record(KeymapReady);
305
+ return async () => {
306
+ await ctx.waitTimers(keymapTimerCtx);
307
+ ctx.done(KeymapReady);
308
+ return () => {
309
+ ctx.remove(keymapCtx).remove(keymapTimerCtx).clearTimer(KeymapReady);
310
+ };
311
+ };
312
+ };
313
+ //#endregion
314
+ //#region src/internal-plugin/parser.ts
315
+ var ParserReady = createTimer("ParserReady");
316
+ var outOfScope$1 = (() => {
317
+ throw ctxCallOutOfScope();
318
+ });
319
+ var parserCtx = createSlice(outOfScope$1, "parser");
320
+ var parserTimerCtx = createSlice([], "parserTimer");
321
+ var parser = (ctx) => {
322
+ ctx.inject(parserCtx, outOfScope$1).inject(parserTimerCtx, [SchemaReady]).record(ParserReady);
323
+ return async () => {
324
+ await ctx.waitTimers(parserTimerCtx);
325
+ const remark = ctx.get(remarkCtx);
326
+ const schema = ctx.get(schemaCtx);
327
+ ctx.set(parserCtx, ParserState.create(schema, remark));
328
+ ctx.done(ParserReady);
329
+ return () => {
330
+ ctx.remove(parserCtx).remove(parserTimerCtx).clearTimer(ParserReady);
331
+ };
332
+ };
333
+ };
334
+ withMeta(parser, { displayName: "Parser" });
335
+ //#endregion
336
+ //#region src/internal-plugin/serializer.ts
337
+ var SerializerReady = createTimer("SerializerReady");
338
+ var serializerTimerCtx = createSlice([], "serializerTimer");
339
+ var outOfScope = (() => {
340
+ throw ctxCallOutOfScope();
341
+ });
342
+ var serializerCtx = createSlice(outOfScope, "serializer");
343
+ var serializer = (ctx) => {
344
+ ctx.inject(serializerCtx, outOfScope).inject(serializerTimerCtx, [SchemaReady]).record(SerializerReady);
345
+ return async () => {
346
+ await ctx.waitTimers(serializerTimerCtx);
347
+ const remark = ctx.get(remarkCtx);
348
+ const schema = ctx.get(schemaCtx);
349
+ ctx.set(serializerCtx, SerializerState.create(schema, remark));
350
+ ctx.done(SerializerReady);
351
+ return () => {
352
+ ctx.remove(serializerCtx).remove(serializerTimerCtx).clearTimer(SerializerReady);
353
+ };
354
+ };
355
+ };
356
+ withMeta(serializer, { displayName: "Serializer" });
357
+ //#endregion
358
+ //#region src/internal-plugin/editor-state.ts
359
+ var defaultValueCtx = createSlice("", "defaultValue");
360
+ var editorStateOptionsCtx = createSlice((x) => x, "stateOptions");
361
+ var editorStateTimerCtx = createSlice([], "editorStateTimer");
362
+ var EditorStateReady = createTimer("EditorStateReady");
363
+ function getDoc(defaultValue, parser, schema) {
364
+ if (typeof defaultValue === "string") return parser(defaultValue);
365
+ if (defaultValue.type === "html") return DOMParser.fromSchema(schema).parse(defaultValue.dom);
366
+ if (defaultValue.type === "json") return Node.fromJSON(schema, defaultValue.value);
367
+ throw docTypeError(defaultValue);
368
+ }
369
+ var key$1 = new PluginKey("MILKDOWN_STATE_TRACKER");
370
+ var editorState = (ctx) => {
371
+ ctx.inject(defaultValueCtx, "").inject(editorStateCtx, {}).inject(editorStateOptionsCtx, (x) => x).inject(editorStateTimerCtx, [
372
+ ParserReady,
373
+ SerializerReady,
374
+ CommandsReady,
375
+ KeymapReady
376
+ ]).record(EditorStateReady);
377
+ return async () => {
378
+ await ctx.waitTimers(editorStateTimerCtx);
379
+ const schema = ctx.get(schemaCtx);
380
+ const parser = ctx.get(parserCtx);
381
+ const rules = ctx.get(inputRulesCtx);
382
+ const optionsOverride = ctx.get(editorStateOptionsCtx);
383
+ const prosePlugins = ctx.get(prosePluginsCtx);
384
+ const doc = getDoc(ctx.get(defaultValueCtx), parser, schema);
385
+ const km = ctx.get(keymapCtx);
386
+ const disposeBaseKeymap = km.addBaseKeymap();
387
+ const plugins = [
388
+ ...prosePlugins,
389
+ new Plugin({
390
+ key: key$1,
391
+ state: {
392
+ init: () => {},
393
+ apply: (_tr, _value, _oldState, newState) => {
394
+ ctx.set(editorStateCtx, newState);
395
+ }
396
+ }
397
+ }),
398
+ customInputRules({ rules }),
399
+ keymap$1(km.build())
400
+ ];
401
+ ctx.set(prosePluginsCtx, plugins);
402
+ const options = optionsOverride({
403
+ schema,
404
+ doc,
405
+ plugins
406
+ });
407
+ const state = EditorState.create(options);
408
+ ctx.set(editorStateCtx, state);
409
+ ctx.done(EditorStateReady);
410
+ return () => {
411
+ disposeBaseKeymap();
412
+ ctx.remove(defaultValueCtx).remove(editorStateCtx).remove(editorStateOptionsCtx).remove(editorStateTimerCtx).clearTimer(EditorStateReady);
413
+ };
414
+ };
415
+ };
416
+ withMeta(editorState, { displayName: "EditorState" });
417
+ //#endregion
418
+ //#region src/internal-plugin/paste-rule.ts
419
+ var pasteRulesCtx = createSlice([], "pasteRule");
420
+ var pasteRulesTimerCtx = createSlice([SchemaReady], "pasteRuleTimer");
421
+ var PasteRulesReady = createTimer("PasteRuleReady");
422
+ var pasteRule = (ctx) => {
423
+ ctx.inject(pasteRulesCtx, []).inject(pasteRulesTimerCtx, [SchemaReady]).record(PasteRulesReady);
424
+ return async () => {
425
+ await ctx.waitTimers(pasteRulesTimerCtx);
426
+ ctx.done(PasteRulesReady);
427
+ return () => {
428
+ ctx.remove(pasteRulesCtx).remove(pasteRulesTimerCtx).clearTimer(PasteRulesReady);
429
+ };
430
+ };
431
+ };
432
+ withMeta(pasteRule, { displayName: "PasteRule" });
433
+ //#endregion
434
+ //#region src/internal-plugin/editor-view.ts
435
+ var EditorViewReady = createTimer("EditorViewReady");
436
+ var editorViewTimerCtx = createSlice([], "editorViewTimer");
437
+ var editorViewOptionsCtx = createSlice({}, "editorViewOptions");
438
+ var rootCtx = createSlice(null, "root");
439
+ var rootDOMCtx = createSlice(null, "rootDOM");
440
+ var rootAttrsCtx = createSlice({}, "rootAttrs");
441
+ function createViewContainer(root, ctx) {
442
+ const container = document.createElement("div");
443
+ container.className = "milkdown";
444
+ root.appendChild(container);
445
+ ctx.set(rootDOMCtx, container);
446
+ const attrs = ctx.get(rootAttrsCtx);
447
+ Object.entries(attrs).forEach(([key, value]) => container.setAttribute(key, value));
448
+ return container;
449
+ }
450
+ function prepareViewDom(dom) {
451
+ dom.classList.add("editor");
452
+ dom.setAttribute("role", "textbox");
453
+ }
454
+ var key = new PluginKey("MILKDOWN_VIEW_CLEAR");
455
+ var editorView = (ctx) => {
456
+ ctx.inject(rootCtx, document.body).inject(editorViewCtx, {}).inject(editorViewOptionsCtx, {}).inject(rootDOMCtx, null).inject(rootAttrsCtx, {}).inject(editorViewTimerCtx, [EditorStateReady, PasteRulesReady]).record(EditorViewReady);
457
+ return async () => {
458
+ await ctx.wait(InitReady);
459
+ const root = ctx.get(rootCtx) || document.body;
460
+ const el = typeof root === "string" ? document.querySelector(root) : root;
461
+ ctx.update(prosePluginsCtx, (xs) => [new Plugin({
462
+ key,
463
+ view: (editorView) => {
464
+ const container = el ? createViewContainer(el, ctx) : void 0;
465
+ const handleDOM = () => {
466
+ if (container && el) {
467
+ const editor = editorView.dom;
468
+ el.replaceChild(container, editor);
469
+ container.appendChild(editor);
470
+ }
471
+ };
472
+ handleDOM();
473
+ return { destroy: () => {
474
+ if (container?.parentNode) container?.parentNode.replaceChild(editorView.dom, container);
475
+ container?.remove();
476
+ } };
477
+ }
478
+ }), ...xs]);
479
+ await ctx.waitTimers(editorViewTimerCtx);
480
+ const state = ctx.get(editorStateCtx);
481
+ const options = ctx.get(editorViewOptionsCtx);
482
+ const view = new EditorView(el, {
483
+ state,
484
+ nodeViews: Object.fromEntries(ctx.get(nodeViewCtx)),
485
+ markViews: Object.fromEntries(ctx.get(markViewCtx)),
486
+ transformPasted: (slice, view, isPlainText) => {
487
+ ctx.get(pasteRulesCtx).sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50)).map((rule) => rule.run).forEach((runner) => {
488
+ slice = runner(slice, view, isPlainText);
489
+ });
490
+ return slice;
491
+ },
492
+ ...options
493
+ });
494
+ prepareViewDom(view.dom);
495
+ ctx.set(editorViewCtx, view);
496
+ ctx.done(EditorViewReady);
497
+ return () => {
498
+ view?.destroy();
499
+ ctx.remove(rootCtx).remove(editorViewCtx).remove(editorViewOptionsCtx).remove(rootDOMCtx).remove(rootAttrsCtx).remove(editorViewTimerCtx).clearTimer(EditorViewReady);
500
+ };
501
+ };
502
+ };
503
+ withMeta(editorView, { displayName: "EditorView" });
504
+ //#endregion
505
+ //#region src/editor/editor.ts
506
+ var EditorStatus = /* @__PURE__ */ function(EditorStatus) {
507
+ EditorStatus["Idle"] = "Idle";
508
+ EditorStatus["OnCreate"] = "OnCreate";
509
+ EditorStatus["Created"] = "Created";
510
+ EditorStatus["OnDestroy"] = "OnDestroy";
511
+ EditorStatus["Destroyed"] = "Destroyed";
512
+ return EditorStatus;
513
+ }({});
514
+ var Editor = class Editor {
515
+ constructor() {
516
+ this.enableInspector = (enable = true) => {
517
+ this.#enableInspector = enable;
518
+ return this;
519
+ };
520
+ this.onStatusChange = (onChange) => {
521
+ this.#onStatusChange = onChange;
522
+ return this;
523
+ };
524
+ this.config = (configure) => {
525
+ this.#configureList.push(configure);
526
+ return this;
527
+ };
528
+ this.removeConfig = (configure) => {
529
+ this.#configureList = this.#configureList.filter((x) => x !== configure);
530
+ return this;
531
+ };
532
+ this.use = (plugins) => {
533
+ const _plugins = [plugins].flat();
534
+ _plugins.flat().forEach((plugin) => {
535
+ this.#usrPluginStore.set(plugin, {
536
+ ctx: void 0,
537
+ handler: void 0,
538
+ cleanup: void 0
539
+ });
540
+ });
541
+ if (this.#status === EditorStatus.Created) this.#prepare(_plugins, this.#usrPluginStore);
542
+ return this;
543
+ };
544
+ this.remove = async (plugins) => {
545
+ if (this.#status === EditorStatus.OnCreate) {
546
+ console.warn("[Milkdown]: You are trying to remove plugins when the editor is creating, this is not recommended, please check your code.");
547
+ return new Promise((resolve) => {
548
+ setTimeout(() => {
549
+ resolve(this.remove(plugins));
550
+ }, 50);
551
+ });
552
+ }
553
+ await this.#cleanup([plugins].flat(), true);
554
+ return this;
555
+ };
556
+ this.create = async () => {
557
+ if (this.#status === EditorStatus.OnCreate) return this;
558
+ if (this.#status === EditorStatus.Created) await this.destroy();
559
+ this.#setStatus(EditorStatus.OnCreate);
560
+ this.#loadInternal();
561
+ this.#prepare([...this.#usrPluginStore.keys()], this.#usrPluginStore);
562
+ await Promise.all([this.#loadPluginInStore(this.#sysPluginStore), this.#loadPluginInStore(this.#usrPluginStore)].flat());
563
+ this.#setStatus(EditorStatus.Created);
564
+ return this;
565
+ };
566
+ this.destroy = async (clearPlugins = false) => {
567
+ if (this.#status === EditorStatus.Destroyed || this.#status === EditorStatus.OnDestroy) return this;
568
+ if (this.#status === EditorStatus.OnCreate) return new Promise((resolve) => {
569
+ setTimeout(() => {
570
+ resolve(this.destroy(clearPlugins));
571
+ }, 50);
572
+ });
573
+ if (clearPlugins) this.#configureList = [];
574
+ this.#setStatus(EditorStatus.OnDestroy);
575
+ await this.#cleanup([...this.#usrPluginStore.keys()], clearPlugins);
576
+ await this.#cleanupInternal();
577
+ this.#setStatus(EditorStatus.Destroyed);
578
+ return this;
579
+ };
580
+ this.action = (action) => action(this.#ctx);
581
+ this.inspect = () => {
582
+ if (!this.#enableInspector) {
583
+ console.warn("[Milkdown]: You are trying to collect inspection when inspector is disabled, please enable inspector by `editor.enableInspector()` first.");
584
+ return [];
585
+ }
586
+ return [...this.#sysPluginStore.values(), ...this.#usrPluginStore.values()].map(({ ctx }) => ctx?.inspector?.read()).filter((x) => Boolean(x));
587
+ };
588
+ }
589
+ static make() {
590
+ return new Editor();
591
+ }
592
+ #enableInspector = false;
593
+ #status = EditorStatus.Idle;
594
+ #configureList = [];
595
+ #onStatusChange = () => void 0;
596
+ #container = new Container();
597
+ #clock = new Clock();
598
+ #usrPluginStore = /* @__PURE__ */ new Map();
599
+ #sysPluginStore = /* @__PURE__ */ new Map();
600
+ #ctx = new Ctx(this.#container, this.#clock);
601
+ #loadInternal = () => {
602
+ const configPlugin = config(async (ctx) => {
603
+ await Promise.all(this.#configureList.map((fn) => Promise.resolve(fn(ctx))));
604
+ });
605
+ const internalPlugins = [
606
+ schema,
607
+ parser,
608
+ serializer,
609
+ commands,
610
+ keymap,
611
+ pasteRule,
612
+ editorState,
613
+ editorView,
614
+ init(this),
615
+ configPlugin
616
+ ];
617
+ this.#prepare(internalPlugins, this.#sysPluginStore);
618
+ };
619
+ #prepare = (plugins, store) => {
620
+ plugins.forEach((plugin) => {
621
+ const ctx = this.#ctx.produce(this.#enableInspector ? plugin.meta : void 0);
622
+ const handler = plugin(ctx);
623
+ store.set(plugin, {
624
+ ctx,
625
+ handler,
626
+ cleanup: void 0
627
+ });
628
+ });
629
+ };
630
+ #cleanup = (plugins, remove = false) => {
631
+ return Promise.all([plugins].flat().map(async (plugin) => {
632
+ const cleanup = this.#usrPluginStore.get(plugin)?.cleanup;
633
+ if (remove) this.#usrPluginStore.delete(plugin);
634
+ else this.#usrPluginStore.set(plugin, {
635
+ ctx: void 0,
636
+ handler: void 0,
637
+ cleanup: void 0
638
+ });
639
+ if (typeof cleanup === "function") return cleanup();
640
+ return cleanup;
641
+ }));
642
+ };
643
+ #cleanupInternal = async () => {
644
+ await Promise.all([...this.#sysPluginStore.entries()].map(async ([_, { cleanup }]) => {
645
+ if (typeof cleanup === "function") return cleanup();
646
+ return cleanup;
647
+ }));
648
+ this.#sysPluginStore.clear();
649
+ };
650
+ #setStatus = (status) => {
651
+ this.#status = status;
652
+ this.#onStatusChange(status);
653
+ };
654
+ #loadPluginInStore = (store) => {
655
+ return [...store.entries()].map(async ([key, loader]) => {
656
+ const { ctx, handler } = loader;
657
+ if (!handler) return;
658
+ const cleanup = await handler();
659
+ store.set(key, {
660
+ ctx,
661
+ handler,
662
+ cleanup
663
+ });
664
+ });
665
+ };
666
+ get ctx() {
667
+ return this.#ctx;
668
+ }
669
+ get status() {
670
+ return this.#status;
671
+ }
672
+ };
673
+ //#endregion
674
+ export { CommandManager, CommandsReady, ConfigReady, Editor, EditorStateReady, EditorStatus, EditorViewReady, InitReady, KeymapManager, KeymapReady, ParserReady, PasteRulesReady, SchemaReady, SerializerReady, commands, commandsCtx, commandsTimerCtx, config, createCmdKey, defaultValueCtx, editorCtx, editorState, editorStateCtx, editorStateOptionsCtx, editorStateTimerCtx, editorView, editorViewCtx, editorViewOptionsCtx, editorViewTimerCtx, getDoc, init, initTimerCtx, inputRulesCtx, keymap, keymapCtx, keymapTimerCtx, markViewCtx, marksCtx, nodeViewCtx, nodesCtx, parser, parserCtx, parserTimerCtx, pasteRule, pasteRulesCtx, pasteRulesTimerCtx, prosePluginsCtx, remarkCtx, remarkPluginsCtx, remarkStringifyOptionsCtx, rootAttrsCtx, rootCtx, rootDOMCtx, schema, schemaCtx, schemaTimerCtx, serializer, serializerCtx, serializerTimerCtx };
675
+
676
+ //# sourceMappingURL=index.js.map