prosekit 0.0.0-next-20230627094841

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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/basic/style.css +133 -0
  4. package/dist/chunk-23S3SZFA.js +46 -0
  5. package/dist/chunk-2MVHS73Q.js +709 -0
  6. package/dist/chunk-4GDRVRDP.js +0 -0
  7. package/dist/chunk-5PFF57NB.js +1546 -0
  8. package/dist/chunk-6A2XHVFY.js +46 -0
  9. package/dist/chunk-7OYIOTDD.js +16472 -0
  10. package/dist/chunk-ARJTWYPA.js +1321 -0
  11. package/dist/chunk-CDGN4JUS.js +1546 -0
  12. package/dist/chunk-CG5B6PMC.js +973 -0
  13. package/dist/chunk-DDN3TFRH.js +185 -0
  14. package/dist/chunk-EQV3CWHZ.js +2213 -0
  15. package/dist/chunk-ERNIDFFW.js +1711 -0
  16. package/dist/chunk-FAVXZAF7.js +3279 -0
  17. package/dist/chunk-HSPTUO6P.js +53 -0
  18. package/dist/chunk-JMNJUDT7.js +165 -0
  19. package/dist/chunk-LXCCO2LO.js +52 -0
  20. package/dist/chunk-MIPON3OH.js +922 -0
  21. package/dist/chunk-NAWSCY5F.js +166 -0
  22. package/dist/chunk-S64NFSV2.js +236 -0
  23. package/dist/chunk-S65R2BUY.js +15 -0
  24. package/dist/chunk-T2V5UU6H.js +204 -0
  25. package/dist/chunk-TWIMWRRZ.js +57 -0
  26. package/dist/chunk-US2P3K6I.js +185 -0
  27. package/dist/chunk-UTNVEPBA.js +950 -0
  28. package/dist/chunk-UWHQRU5N.js +4883 -0
  29. package/dist/chunk-VIKPJJET.js +662 -0
  30. package/dist/chunk-WAMZOD5I.js +67 -0
  31. package/dist/chunk-YUY5I2TY.js +236 -0
  32. package/dist/core/style.css +54 -0
  33. package/dist/extension-list/style.css +78 -0
  34. package/dist/pm/view/style/prosemirror.css +52 -0
  35. package/dist/prosekit-basic.js +2 -0
  36. package/dist/prosekit-core.js +2 -0
  37. package/dist/prosekit-extension-blockquote.js +2 -0
  38. package/dist/prosekit-extension-bold.js +2 -0
  39. package/dist/prosekit-extension-code-block.js +2 -0
  40. package/dist/prosekit-extension-code.js +2 -0
  41. package/dist/prosekit-extension-heading.js +2 -0
  42. package/dist/prosekit-extension-horizontal-rule.js +2 -0
  43. package/dist/prosekit-extension-italic.js +2 -0
  44. package/dist/prosekit-extension-list.js +2 -0
  45. package/dist/prosekit-extension-suggestion.js +2 -0
  46. package/dist/prosekit-lit-elements-menu-item.js +2 -0
  47. package/dist/prosekit-lit-elements-menu.js +2 -0
  48. package/dist/prosekit-lit-elements-popover.js +2 -0
  49. package/dist/prosekit-lit.js +2 -0
  50. package/dist/prosekit-pm-commands.js +2 -0
  51. package/dist/prosekit-pm-inputrules.js +2 -0
  52. package/dist/prosekit-pm-keymap.js +2 -0
  53. package/dist/prosekit-pm-model.js +2 -0
  54. package/dist/prosekit-pm-state.js +2 -0
  55. package/dist/prosekit-pm-transform.js +2 -0
  56. package/dist/prosekit-pm-view.js +2 -0
  57. package/dist/prosekit-pm.js +2 -0
  58. package/dist/prosekit-react-components-menu-item.js +2 -0
  59. package/dist/prosekit-react-components-menu.js +2 -0
  60. package/dist/prosekit-react-components-popover-suggestion.js +2 -0
  61. package/dist/prosekit-react-components-popover.js +2 -0
  62. package/dist/prosekit-react.js +2 -0
  63. package/dist/prosekit-vue-components-menu-item.js +2 -0
  64. package/dist/prosekit-vue-components-menu.js +2 -0
  65. package/dist/prosekit-vue-components-popover-suggestion.js +2 -0
  66. package/dist/prosekit-vue-components-popover.js +2 -0
  67. package/dist/prosekit-vue.js +2 -0
  68. package/dist/prosekit.js +0 -0
  69. package/package.json +262 -0
  70. package/src/index.ts +1 -0
@@ -0,0 +1,950 @@
1
+ import {
2
+ ReplaceAroundStep,
3
+ ReplaceStep,
4
+ Transform
5
+ } from "./chunk-ERNIDFFW.js";
6
+ import {
7
+ Fragment,
8
+ Mark,
9
+ Node,
10
+ Slice
11
+ } from "./chunk-FAVXZAF7.js";
12
+
13
+ // ../../node_modules/.pnpm/prosemirror-state@1.4.3/node_modules/prosemirror-state/dist/index.js
14
+ var classesById = /* @__PURE__ */ Object.create(null);
15
+ var Selection = class {
16
+ /**
17
+ Initialize a selection with the head and anchor and ranges. If no
18
+ ranges are given, constructs a single range across `$anchor` and
19
+ `$head`.
20
+ */
21
+ constructor($anchor, $head, ranges) {
22
+ this.$anchor = $anchor;
23
+ this.$head = $head;
24
+ this.ranges = ranges || [new SelectionRange($anchor.min($head), $anchor.max($head))];
25
+ }
26
+ /**
27
+ The selection's anchor, as an unresolved position.
28
+ */
29
+ get anchor() {
30
+ return this.$anchor.pos;
31
+ }
32
+ /**
33
+ The selection's head.
34
+ */
35
+ get head() {
36
+ return this.$head.pos;
37
+ }
38
+ /**
39
+ The lower bound of the selection's main range.
40
+ */
41
+ get from() {
42
+ return this.$from.pos;
43
+ }
44
+ /**
45
+ The upper bound of the selection's main range.
46
+ */
47
+ get to() {
48
+ return this.$to.pos;
49
+ }
50
+ /**
51
+ The resolved lower bound of the selection's main range.
52
+ */
53
+ get $from() {
54
+ return this.ranges[0].$from;
55
+ }
56
+ /**
57
+ The resolved upper bound of the selection's main range.
58
+ */
59
+ get $to() {
60
+ return this.ranges[0].$to;
61
+ }
62
+ /**
63
+ Indicates whether the selection contains any content.
64
+ */
65
+ get empty() {
66
+ let ranges = this.ranges;
67
+ for (let i = 0; i < ranges.length; i++)
68
+ if (ranges[i].$from.pos != ranges[i].$to.pos)
69
+ return false;
70
+ return true;
71
+ }
72
+ /**
73
+ Get the content of this selection as a slice.
74
+ */
75
+ content() {
76
+ return this.$from.doc.slice(this.from, this.to, true);
77
+ }
78
+ /**
79
+ Replace the selection with a slice or, if no slice is given,
80
+ delete the selection. Will append to the given transaction.
81
+ */
82
+ replace(tr, content = Slice.empty) {
83
+ let lastNode = content.content.lastChild, lastParent = null;
84
+ for (let i = 0; i < content.openEnd; i++) {
85
+ lastParent = lastNode;
86
+ lastNode = lastNode.lastChild;
87
+ }
88
+ let mapFrom = tr.steps.length, ranges = this.ranges;
89
+ for (let i = 0; i < ranges.length; i++) {
90
+ let { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom);
91
+ tr.replaceRange(mapping.map($from.pos), mapping.map($to.pos), i ? Slice.empty : content);
92
+ if (i == 0)
93
+ selectionToInsertionEnd(tr, mapFrom, (lastNode ? lastNode.isInline : lastParent && lastParent.isTextblock) ? -1 : 1);
94
+ }
95
+ }
96
+ /**
97
+ Replace the selection with the given node, appending the changes
98
+ to the given transaction.
99
+ */
100
+ replaceWith(tr, node) {
101
+ let mapFrom = tr.steps.length, ranges = this.ranges;
102
+ for (let i = 0; i < ranges.length; i++) {
103
+ let { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom);
104
+ let from = mapping.map($from.pos), to = mapping.map($to.pos);
105
+ if (i) {
106
+ tr.deleteRange(from, to);
107
+ } else {
108
+ tr.replaceRangeWith(from, to, node);
109
+ selectionToInsertionEnd(tr, mapFrom, node.isInline ? -1 : 1);
110
+ }
111
+ }
112
+ }
113
+ /**
114
+ Find a valid cursor or leaf node selection starting at the given
115
+ position and searching back if `dir` is negative, and forward if
116
+ positive. When `textOnly` is true, only consider cursor
117
+ selections. Will return null when no valid selection position is
118
+ found.
119
+ */
120
+ static findFrom($pos, dir, textOnly = false) {
121
+ let inner = $pos.parent.inlineContent ? new TextSelection($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
122
+ if (inner)
123
+ return inner;
124
+ for (let depth = $pos.depth - 1; depth >= 0; depth--) {
125
+ let found = dir < 0 ? findSelectionIn($pos.node(0), $pos.node(depth), $pos.before(depth + 1), $pos.index(depth), dir, textOnly) : findSelectionIn($pos.node(0), $pos.node(depth), $pos.after(depth + 1), $pos.index(depth) + 1, dir, textOnly);
126
+ if (found)
127
+ return found;
128
+ }
129
+ return null;
130
+ }
131
+ /**
132
+ Find a valid cursor or leaf node selection near the given
133
+ position. Searches forward first by default, but if `bias` is
134
+ negative, it will search backwards first.
135
+ */
136
+ static near($pos, bias = 1) {
137
+ return this.findFrom($pos, bias) || this.findFrom($pos, -bias) || new AllSelection($pos.node(0));
138
+ }
139
+ /**
140
+ Find the cursor or leaf node selection closest to the start of
141
+ the given document. Will return an
142
+ [`AllSelection`](https://prosemirror.net/docs/ref/#state.AllSelection) if no valid position
143
+ exists.
144
+ */
145
+ static atStart(doc) {
146
+ return findSelectionIn(doc, doc, 0, 0, 1) || new AllSelection(doc);
147
+ }
148
+ /**
149
+ Find the cursor or leaf node selection closest to the end of the
150
+ given document.
151
+ */
152
+ static atEnd(doc) {
153
+ return findSelectionIn(doc, doc, doc.content.size, doc.childCount, -1) || new AllSelection(doc);
154
+ }
155
+ /**
156
+ Deserialize the JSON representation of a selection. Must be
157
+ implemented for custom classes (as a static class method).
158
+ */
159
+ static fromJSON(doc, json) {
160
+ if (!json || !json.type)
161
+ throw new RangeError("Invalid input for Selection.fromJSON");
162
+ let cls = classesById[json.type];
163
+ if (!cls)
164
+ throw new RangeError(`No selection type ${json.type} defined`);
165
+ return cls.fromJSON(doc, json);
166
+ }
167
+ /**
168
+ To be able to deserialize selections from JSON, custom selection
169
+ classes must register themselves with an ID string, so that they
170
+ can be disambiguated. Try to pick something that's unlikely to
171
+ clash with classes from other modules.
172
+ */
173
+ static jsonID(id, selectionClass) {
174
+ if (id in classesById)
175
+ throw new RangeError("Duplicate use of selection JSON ID " + id);
176
+ classesById[id] = selectionClass;
177
+ selectionClass.prototype.jsonID = id;
178
+ return selectionClass;
179
+ }
180
+ /**
181
+ Get a [bookmark](https://prosemirror.net/docs/ref/#state.SelectionBookmark) for this selection,
182
+ which is a value that can be mapped without having access to a
183
+ current document, and later resolved to a real selection for a
184
+ given document again. (This is used mostly by the history to
185
+ track and restore old selections.) The default implementation of
186
+ this method just converts the selection to a text selection and
187
+ returns the bookmark for that.
188
+ */
189
+ getBookmark() {
190
+ return TextSelection.between(this.$anchor, this.$head).getBookmark();
191
+ }
192
+ };
193
+ Selection.prototype.visible = true;
194
+ var SelectionRange = class {
195
+ /**
196
+ Create a range.
197
+ */
198
+ constructor($from, $to) {
199
+ this.$from = $from;
200
+ this.$to = $to;
201
+ }
202
+ };
203
+ var warnedAboutTextSelection = false;
204
+ function checkTextSelection($pos) {
205
+ if (!warnedAboutTextSelection && !$pos.parent.inlineContent) {
206
+ warnedAboutTextSelection = true;
207
+ console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
208
+ }
209
+ }
210
+ var TextSelection = class _TextSelection extends Selection {
211
+ /**
212
+ Construct a text selection between the given points.
213
+ */
214
+ constructor($anchor, $head = $anchor) {
215
+ checkTextSelection($anchor);
216
+ checkTextSelection($head);
217
+ super($anchor, $head);
218
+ }
219
+ /**
220
+ Returns a resolved position if this is a cursor selection (an
221
+ empty text selection), and null otherwise.
222
+ */
223
+ get $cursor() {
224
+ return this.$anchor.pos == this.$head.pos ? this.$head : null;
225
+ }
226
+ map(doc, mapping) {
227
+ let $head = doc.resolve(mapping.map(this.head));
228
+ if (!$head.parent.inlineContent)
229
+ return Selection.near($head);
230
+ let $anchor = doc.resolve(mapping.map(this.anchor));
231
+ return new _TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head);
232
+ }
233
+ replace(tr, content = Slice.empty) {
234
+ super.replace(tr, content);
235
+ if (content == Slice.empty) {
236
+ let marks = this.$from.marksAcross(this.$to);
237
+ if (marks)
238
+ tr.ensureMarks(marks);
239
+ }
240
+ }
241
+ eq(other) {
242
+ return other instanceof _TextSelection && other.anchor == this.anchor && other.head == this.head;
243
+ }
244
+ getBookmark() {
245
+ return new TextBookmark(this.anchor, this.head);
246
+ }
247
+ toJSON() {
248
+ return { type: "text", anchor: this.anchor, head: this.head };
249
+ }
250
+ /**
251
+ @internal
252
+ */
253
+ static fromJSON(doc, json) {
254
+ if (typeof json.anchor != "number" || typeof json.head != "number")
255
+ throw new RangeError("Invalid input for TextSelection.fromJSON");
256
+ return new _TextSelection(doc.resolve(json.anchor), doc.resolve(json.head));
257
+ }
258
+ /**
259
+ Create a text selection from non-resolved positions.
260
+ */
261
+ static create(doc, anchor, head = anchor) {
262
+ let $anchor = doc.resolve(anchor);
263
+ return new this($anchor, head == anchor ? $anchor : doc.resolve(head));
264
+ }
265
+ /**
266
+ Return a text selection that spans the given positions or, if
267
+ they aren't text positions, find a text selection near them.
268
+ `bias` determines whether the method searches forward (default)
269
+ or backwards (negative number) first. Will fall back to calling
270
+ [`Selection.near`](https://prosemirror.net/docs/ref/#state.Selection^near) when the document
271
+ doesn't contain a valid text position.
272
+ */
273
+ static between($anchor, $head, bias) {
274
+ let dPos = $anchor.pos - $head.pos;
275
+ if (!bias || dPos)
276
+ bias = dPos >= 0 ? 1 : -1;
277
+ if (!$head.parent.inlineContent) {
278
+ let found = Selection.findFrom($head, bias, true) || Selection.findFrom($head, -bias, true);
279
+ if (found)
280
+ $head = found.$head;
281
+ else
282
+ return Selection.near($head, bias);
283
+ }
284
+ if (!$anchor.parent.inlineContent) {
285
+ if (dPos == 0) {
286
+ $anchor = $head;
287
+ } else {
288
+ $anchor = (Selection.findFrom($anchor, -bias, true) || Selection.findFrom($anchor, bias, true)).$anchor;
289
+ if ($anchor.pos < $head.pos != dPos < 0)
290
+ $anchor = $head;
291
+ }
292
+ }
293
+ return new _TextSelection($anchor, $head);
294
+ }
295
+ };
296
+ Selection.jsonID("text", TextSelection);
297
+ var TextBookmark = class _TextBookmark {
298
+ constructor(anchor, head) {
299
+ this.anchor = anchor;
300
+ this.head = head;
301
+ }
302
+ map(mapping) {
303
+ return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
304
+ }
305
+ resolve(doc) {
306
+ return TextSelection.between(doc.resolve(this.anchor), doc.resolve(this.head));
307
+ }
308
+ };
309
+ var NodeSelection = class _NodeSelection extends Selection {
310
+ /**
311
+ Create a node selection. Does not verify the validity of its
312
+ argument.
313
+ */
314
+ constructor($pos) {
315
+ let node = $pos.nodeAfter;
316
+ let $end = $pos.node(0).resolve($pos.pos + node.nodeSize);
317
+ super($pos, $end);
318
+ this.node = node;
319
+ }
320
+ map(doc, mapping) {
321
+ let { deleted, pos } = mapping.mapResult(this.anchor);
322
+ let $pos = doc.resolve(pos);
323
+ if (deleted)
324
+ return Selection.near($pos);
325
+ return new _NodeSelection($pos);
326
+ }
327
+ content() {
328
+ return new Slice(Fragment.from(this.node), 0, 0);
329
+ }
330
+ eq(other) {
331
+ return other instanceof _NodeSelection && other.anchor == this.anchor;
332
+ }
333
+ toJSON() {
334
+ return { type: "node", anchor: this.anchor };
335
+ }
336
+ getBookmark() {
337
+ return new NodeBookmark(this.anchor);
338
+ }
339
+ /**
340
+ @internal
341
+ */
342
+ static fromJSON(doc, json) {
343
+ if (typeof json.anchor != "number")
344
+ throw new RangeError("Invalid input for NodeSelection.fromJSON");
345
+ return new _NodeSelection(doc.resolve(json.anchor));
346
+ }
347
+ /**
348
+ Create a node selection from non-resolved positions.
349
+ */
350
+ static create(doc, from) {
351
+ return new _NodeSelection(doc.resolve(from));
352
+ }
353
+ /**
354
+ Determines whether the given node may be selected as a node
355
+ selection.
356
+ */
357
+ static isSelectable(node) {
358
+ return !node.isText && node.type.spec.selectable !== false;
359
+ }
360
+ };
361
+ NodeSelection.prototype.visible = false;
362
+ Selection.jsonID("node", NodeSelection);
363
+ var NodeBookmark = class _NodeBookmark {
364
+ constructor(anchor) {
365
+ this.anchor = anchor;
366
+ }
367
+ map(mapping) {
368
+ let { deleted, pos } = mapping.mapResult(this.anchor);
369
+ return deleted ? new TextBookmark(pos, pos) : new _NodeBookmark(pos);
370
+ }
371
+ resolve(doc) {
372
+ let $pos = doc.resolve(this.anchor), node = $pos.nodeAfter;
373
+ if (node && NodeSelection.isSelectable(node))
374
+ return new NodeSelection($pos);
375
+ return Selection.near($pos);
376
+ }
377
+ };
378
+ var AllSelection = class _AllSelection extends Selection {
379
+ /**
380
+ Create an all-selection over the given document.
381
+ */
382
+ constructor(doc) {
383
+ super(doc.resolve(0), doc.resolve(doc.content.size));
384
+ }
385
+ replace(tr, content = Slice.empty) {
386
+ if (content == Slice.empty) {
387
+ tr.delete(0, tr.doc.content.size);
388
+ let sel = Selection.atStart(tr.doc);
389
+ if (!sel.eq(tr.selection))
390
+ tr.setSelection(sel);
391
+ } else {
392
+ super.replace(tr, content);
393
+ }
394
+ }
395
+ toJSON() {
396
+ return { type: "all" };
397
+ }
398
+ /**
399
+ @internal
400
+ */
401
+ static fromJSON(doc) {
402
+ return new _AllSelection(doc);
403
+ }
404
+ map(doc) {
405
+ return new _AllSelection(doc);
406
+ }
407
+ eq(other) {
408
+ return other instanceof _AllSelection;
409
+ }
410
+ getBookmark() {
411
+ return AllBookmark;
412
+ }
413
+ };
414
+ Selection.jsonID("all", AllSelection);
415
+ var AllBookmark = {
416
+ map() {
417
+ return this;
418
+ },
419
+ resolve(doc) {
420
+ return new AllSelection(doc);
421
+ }
422
+ };
423
+ function findSelectionIn(doc, node, pos, index, dir, text = false) {
424
+ if (node.inlineContent)
425
+ return TextSelection.create(doc, pos);
426
+ for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
427
+ let child = node.child(i);
428
+ if (!child.isAtom) {
429
+ let inner = findSelectionIn(doc, child, pos + dir, dir < 0 ? child.childCount : 0, dir, text);
430
+ if (inner)
431
+ return inner;
432
+ } else if (!text && NodeSelection.isSelectable(child)) {
433
+ return NodeSelection.create(doc, pos - (dir < 0 ? child.nodeSize : 0));
434
+ }
435
+ pos += child.nodeSize * dir;
436
+ }
437
+ return null;
438
+ }
439
+ function selectionToInsertionEnd(tr, startLen, bias) {
440
+ let last = tr.steps.length - 1;
441
+ if (last < startLen)
442
+ return;
443
+ let step = tr.steps[last];
444
+ if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep))
445
+ return;
446
+ let map = tr.mapping.maps[last], end;
447
+ map.forEach((_from, _to, _newFrom, newTo) => {
448
+ if (end == null)
449
+ end = newTo;
450
+ });
451
+ tr.setSelection(Selection.near(tr.doc.resolve(end), bias));
452
+ }
453
+ var UPDATED_SEL = 1;
454
+ var UPDATED_MARKS = 2;
455
+ var UPDATED_SCROLL = 4;
456
+ var Transaction = class extends Transform {
457
+ /**
458
+ @internal
459
+ */
460
+ constructor(state) {
461
+ super(state.doc);
462
+ this.curSelectionFor = 0;
463
+ this.updated = 0;
464
+ this.meta = /* @__PURE__ */ Object.create(null);
465
+ this.time = Date.now();
466
+ this.curSelection = state.selection;
467
+ this.storedMarks = state.storedMarks;
468
+ }
469
+ /**
470
+ The transaction's current selection. This defaults to the editor
471
+ selection [mapped](https://prosemirror.net/docs/ref/#state.Selection.map) through the steps in the
472
+ transaction, but can be overwritten with
473
+ [`setSelection`](https://prosemirror.net/docs/ref/#state.Transaction.setSelection).
474
+ */
475
+ get selection() {
476
+ if (this.curSelectionFor < this.steps.length) {
477
+ this.curSelection = this.curSelection.map(this.doc, this.mapping.slice(this.curSelectionFor));
478
+ this.curSelectionFor = this.steps.length;
479
+ }
480
+ return this.curSelection;
481
+ }
482
+ /**
483
+ Update the transaction's current selection. Will determine the
484
+ selection that the editor gets when the transaction is applied.
485
+ */
486
+ setSelection(selection) {
487
+ if (selection.$from.doc != this.doc)
488
+ throw new RangeError("Selection passed to setSelection must point at the current document");
489
+ this.curSelection = selection;
490
+ this.curSelectionFor = this.steps.length;
491
+ this.updated = (this.updated | UPDATED_SEL) & ~UPDATED_MARKS;
492
+ this.storedMarks = null;
493
+ return this;
494
+ }
495
+ /**
496
+ Whether the selection was explicitly updated by this transaction.
497
+ */
498
+ get selectionSet() {
499
+ return (this.updated & UPDATED_SEL) > 0;
500
+ }
501
+ /**
502
+ Set the current stored marks.
503
+ */
504
+ setStoredMarks(marks) {
505
+ this.storedMarks = marks;
506
+ this.updated |= UPDATED_MARKS;
507
+ return this;
508
+ }
509
+ /**
510
+ Make sure the current stored marks or, if that is null, the marks
511
+ at the selection, match the given set of marks. Does nothing if
512
+ this is already the case.
513
+ */
514
+ ensureMarks(marks) {
515
+ if (!Mark.sameSet(this.storedMarks || this.selection.$from.marks(), marks))
516
+ this.setStoredMarks(marks);
517
+ return this;
518
+ }
519
+ /**
520
+ Add a mark to the set of stored marks.
521
+ */
522
+ addStoredMark(mark) {
523
+ return this.ensureMarks(mark.addToSet(this.storedMarks || this.selection.$head.marks()));
524
+ }
525
+ /**
526
+ Remove a mark or mark type from the set of stored marks.
527
+ */
528
+ removeStoredMark(mark) {
529
+ return this.ensureMarks(mark.removeFromSet(this.storedMarks || this.selection.$head.marks()));
530
+ }
531
+ /**
532
+ Whether the stored marks were explicitly set for this transaction.
533
+ */
534
+ get storedMarksSet() {
535
+ return (this.updated & UPDATED_MARKS) > 0;
536
+ }
537
+ /**
538
+ @internal
539
+ */
540
+ addStep(step, doc) {
541
+ super.addStep(step, doc);
542
+ this.updated = this.updated & ~UPDATED_MARKS;
543
+ this.storedMarks = null;
544
+ }
545
+ /**
546
+ Update the timestamp for the transaction.
547
+ */
548
+ setTime(time) {
549
+ this.time = time;
550
+ return this;
551
+ }
552
+ /**
553
+ Replace the current selection with the given slice.
554
+ */
555
+ replaceSelection(slice) {
556
+ this.selection.replace(this, slice);
557
+ return this;
558
+ }
559
+ /**
560
+ Replace the selection with the given node. When `inheritMarks` is
561
+ true and the content is inline, it inherits the marks from the
562
+ place where it is inserted.
563
+ */
564
+ replaceSelectionWith(node, inheritMarks = true) {
565
+ let selection = this.selection;
566
+ if (inheritMarks)
567
+ node = node.mark(this.storedMarks || (selection.empty ? selection.$from.marks() : selection.$from.marksAcross(selection.$to) || Mark.none));
568
+ selection.replaceWith(this, node);
569
+ return this;
570
+ }
571
+ /**
572
+ Delete the selection.
573
+ */
574
+ deleteSelection() {
575
+ this.selection.replace(this);
576
+ return this;
577
+ }
578
+ /**
579
+ Replace the given range, or the selection if no range is given,
580
+ with a text node containing the given string.
581
+ */
582
+ insertText(text, from, to) {
583
+ let schema = this.doc.type.schema;
584
+ if (from == null) {
585
+ if (!text)
586
+ return this.deleteSelection();
587
+ return this.replaceSelectionWith(schema.text(text), true);
588
+ } else {
589
+ if (to == null)
590
+ to = from;
591
+ to = to == null ? from : to;
592
+ if (!text)
593
+ return this.deleteRange(from, to);
594
+ let marks = this.storedMarks;
595
+ if (!marks) {
596
+ let $from = this.doc.resolve(from);
597
+ marks = to == from ? $from.marks() : $from.marksAcross(this.doc.resolve(to));
598
+ }
599
+ this.replaceRangeWith(from, to, schema.text(text, marks));
600
+ if (!this.selection.empty)
601
+ this.setSelection(Selection.near(this.selection.$to));
602
+ return this;
603
+ }
604
+ }
605
+ /**
606
+ Store a metadata property in this transaction, keyed either by
607
+ name or by plugin.
608
+ */
609
+ setMeta(key, value) {
610
+ this.meta[typeof key == "string" ? key : key.key] = value;
611
+ return this;
612
+ }
613
+ /**
614
+ Retrieve a metadata property for a given name or plugin.
615
+ */
616
+ getMeta(key) {
617
+ return this.meta[typeof key == "string" ? key : key.key];
618
+ }
619
+ /**
620
+ Returns true if this transaction doesn't contain any metadata,
621
+ and can thus safely be extended.
622
+ */
623
+ get isGeneric() {
624
+ for (let _ in this.meta)
625
+ return false;
626
+ return true;
627
+ }
628
+ /**
629
+ Indicate that the editor should scroll the selection into view
630
+ when updated to the state produced by this transaction.
631
+ */
632
+ scrollIntoView() {
633
+ this.updated |= UPDATED_SCROLL;
634
+ return this;
635
+ }
636
+ /**
637
+ True when this transaction has had `scrollIntoView` called on it.
638
+ */
639
+ get scrolledIntoView() {
640
+ return (this.updated & UPDATED_SCROLL) > 0;
641
+ }
642
+ };
643
+ function bind(f, self) {
644
+ return !self || !f ? f : f.bind(self);
645
+ }
646
+ var FieldDesc = class {
647
+ constructor(name, desc, self) {
648
+ this.name = name;
649
+ this.init = bind(desc.init, self);
650
+ this.apply = bind(desc.apply, self);
651
+ }
652
+ };
653
+ var baseFields = [
654
+ new FieldDesc("doc", {
655
+ init(config) {
656
+ return config.doc || config.schema.topNodeType.createAndFill();
657
+ },
658
+ apply(tr) {
659
+ return tr.doc;
660
+ }
661
+ }),
662
+ new FieldDesc("selection", {
663
+ init(config, instance) {
664
+ return config.selection || Selection.atStart(instance.doc);
665
+ },
666
+ apply(tr) {
667
+ return tr.selection;
668
+ }
669
+ }),
670
+ new FieldDesc("storedMarks", {
671
+ init(config) {
672
+ return config.storedMarks || null;
673
+ },
674
+ apply(tr, _marks, _old, state) {
675
+ return state.selection.$cursor ? tr.storedMarks : null;
676
+ }
677
+ }),
678
+ new FieldDesc("scrollToSelection", {
679
+ init() {
680
+ return 0;
681
+ },
682
+ apply(tr, prev) {
683
+ return tr.scrolledIntoView ? prev + 1 : prev;
684
+ }
685
+ })
686
+ ];
687
+ var Configuration = class {
688
+ constructor(schema, plugins) {
689
+ this.schema = schema;
690
+ this.plugins = [];
691
+ this.pluginsByKey = /* @__PURE__ */ Object.create(null);
692
+ this.fields = baseFields.slice();
693
+ if (plugins)
694
+ plugins.forEach((plugin) => {
695
+ if (this.pluginsByKey[plugin.key])
696
+ throw new RangeError("Adding different instances of a keyed plugin (" + plugin.key + ")");
697
+ this.plugins.push(plugin);
698
+ this.pluginsByKey[plugin.key] = plugin;
699
+ if (plugin.spec.state)
700
+ this.fields.push(new FieldDesc(plugin.key, plugin.spec.state, plugin));
701
+ });
702
+ }
703
+ };
704
+ var EditorState = class _EditorState {
705
+ /**
706
+ @internal
707
+ */
708
+ constructor(config) {
709
+ this.config = config;
710
+ }
711
+ /**
712
+ The schema of the state's document.
713
+ */
714
+ get schema() {
715
+ return this.config.schema;
716
+ }
717
+ /**
718
+ The plugins that are active in this state.
719
+ */
720
+ get plugins() {
721
+ return this.config.plugins;
722
+ }
723
+ /**
724
+ Apply the given transaction to produce a new state.
725
+ */
726
+ apply(tr) {
727
+ return this.applyTransaction(tr).state;
728
+ }
729
+ /**
730
+ @internal
731
+ */
732
+ filterTransaction(tr, ignore = -1) {
733
+ for (let i = 0; i < this.config.plugins.length; i++)
734
+ if (i != ignore) {
735
+ let plugin = this.config.plugins[i];
736
+ if (plugin.spec.filterTransaction && !plugin.spec.filterTransaction.call(plugin, tr, this))
737
+ return false;
738
+ }
739
+ return true;
740
+ }
741
+ /**
742
+ Verbose variant of [`apply`](https://prosemirror.net/docs/ref/#state.EditorState.apply) that
743
+ returns the precise transactions that were applied (which might
744
+ be influenced by the [transaction
745
+ hooks](https://prosemirror.net/docs/ref/#state.PluginSpec.filterTransaction) of
746
+ plugins) along with the new state.
747
+ */
748
+ applyTransaction(rootTr) {
749
+ if (!this.filterTransaction(rootTr))
750
+ return { state: this, transactions: [] };
751
+ let trs = [rootTr], newState = this.applyInner(rootTr), seen = null;
752
+ for (; ; ) {
753
+ let haveNew = false;
754
+ for (let i = 0; i < this.config.plugins.length; i++) {
755
+ let plugin = this.config.plugins[i];
756
+ if (plugin.spec.appendTransaction) {
757
+ let n = seen ? seen[i].n : 0, oldState = seen ? seen[i].state : this;
758
+ let tr = n < trs.length && plugin.spec.appendTransaction.call(plugin, n ? trs.slice(n) : trs, oldState, newState);
759
+ if (tr && newState.filterTransaction(tr, i)) {
760
+ tr.setMeta("appendedTransaction", rootTr);
761
+ if (!seen) {
762
+ seen = [];
763
+ for (let j = 0; j < this.config.plugins.length; j++)
764
+ seen.push(j < i ? { state: newState, n: trs.length } : { state: this, n: 0 });
765
+ }
766
+ trs.push(tr);
767
+ newState = newState.applyInner(tr);
768
+ haveNew = true;
769
+ }
770
+ if (seen)
771
+ seen[i] = { state: newState, n: trs.length };
772
+ }
773
+ }
774
+ if (!haveNew)
775
+ return { state: newState, transactions: trs };
776
+ }
777
+ }
778
+ /**
779
+ @internal
780
+ */
781
+ applyInner(tr) {
782
+ if (!tr.before.eq(this.doc))
783
+ throw new RangeError("Applying a mismatched transaction");
784
+ let newInstance = new _EditorState(this.config), fields = this.config.fields;
785
+ for (let i = 0; i < fields.length; i++) {
786
+ let field = fields[i];
787
+ newInstance[field.name] = field.apply(tr, this[field.name], this, newInstance);
788
+ }
789
+ return newInstance;
790
+ }
791
+ /**
792
+ Start a [transaction](https://prosemirror.net/docs/ref/#state.Transaction) from this state.
793
+ */
794
+ get tr() {
795
+ return new Transaction(this);
796
+ }
797
+ /**
798
+ Create a new state.
799
+ */
800
+ static create(config) {
801
+ let $config = new Configuration(config.doc ? config.doc.type.schema : config.schema, config.plugins);
802
+ let instance = new _EditorState($config);
803
+ for (let i = 0; i < $config.fields.length; i++)
804
+ instance[$config.fields[i].name] = $config.fields[i].init(config, instance);
805
+ return instance;
806
+ }
807
+ /**
808
+ Create a new state based on this one, but with an adjusted set
809
+ of active plugins. State fields that exist in both sets of
810
+ plugins are kept unchanged. Those that no longer exist are
811
+ dropped, and those that are new are initialized using their
812
+ [`init`](https://prosemirror.net/docs/ref/#state.StateField.init) method, passing in the new
813
+ configuration object..
814
+ */
815
+ reconfigure(config) {
816
+ let $config = new Configuration(this.schema, config.plugins);
817
+ let fields = $config.fields, instance = new _EditorState($config);
818
+ for (let i = 0; i < fields.length; i++) {
819
+ let name = fields[i].name;
820
+ instance[name] = this.hasOwnProperty(name) ? this[name] : fields[i].init(config, instance);
821
+ }
822
+ return instance;
823
+ }
824
+ /**
825
+ Serialize this state to JSON. If you want to serialize the state
826
+ of plugins, pass an object mapping property names to use in the
827
+ resulting JSON object to plugin objects. The argument may also be
828
+ a string or number, in which case it is ignored, to support the
829
+ way `JSON.stringify` calls `toString` methods.
830
+ */
831
+ toJSON(pluginFields) {
832
+ let result = { doc: this.doc.toJSON(), selection: this.selection.toJSON() };
833
+ if (this.storedMarks)
834
+ result.storedMarks = this.storedMarks.map((m) => m.toJSON());
835
+ if (pluginFields && typeof pluginFields == "object")
836
+ for (let prop in pluginFields) {
837
+ if (prop == "doc" || prop == "selection")
838
+ throw new RangeError("The JSON fields `doc` and `selection` are reserved");
839
+ let plugin = pluginFields[prop], state = plugin.spec.state;
840
+ if (state && state.toJSON)
841
+ result[prop] = state.toJSON.call(plugin, this[plugin.key]);
842
+ }
843
+ return result;
844
+ }
845
+ /**
846
+ Deserialize a JSON representation of a state. `config` should
847
+ have at least a `schema` field, and should contain array of
848
+ plugins to initialize the state with. `pluginFields` can be used
849
+ to deserialize the state of plugins, by associating plugin
850
+ instances with the property names they use in the JSON object.
851
+ */
852
+ static fromJSON(config, json, pluginFields) {
853
+ if (!json)
854
+ throw new RangeError("Invalid input for EditorState.fromJSON");
855
+ if (!config.schema)
856
+ throw new RangeError("Required config field 'schema' missing");
857
+ let $config = new Configuration(config.schema, config.plugins);
858
+ let instance = new _EditorState($config);
859
+ $config.fields.forEach((field) => {
860
+ if (field.name == "doc") {
861
+ instance.doc = Node.fromJSON(config.schema, json.doc);
862
+ } else if (field.name == "selection") {
863
+ instance.selection = Selection.fromJSON(instance.doc, json.selection);
864
+ } else if (field.name == "storedMarks") {
865
+ if (json.storedMarks)
866
+ instance.storedMarks = json.storedMarks.map(config.schema.markFromJSON);
867
+ } else {
868
+ if (pluginFields)
869
+ for (let prop in pluginFields) {
870
+ let plugin = pluginFields[prop], state = plugin.spec.state;
871
+ if (plugin.key == field.name && state && state.fromJSON && Object.prototype.hasOwnProperty.call(json, prop)) {
872
+ instance[field.name] = state.fromJSON.call(plugin, config, json[prop], instance);
873
+ return;
874
+ }
875
+ }
876
+ instance[field.name] = field.init(config, instance);
877
+ }
878
+ });
879
+ return instance;
880
+ }
881
+ };
882
+ function bindProps(obj, self, target) {
883
+ for (let prop in obj) {
884
+ let val = obj[prop];
885
+ if (val instanceof Function)
886
+ val = val.bind(self);
887
+ else if (prop == "handleDOMEvents")
888
+ val = bindProps(val, self, {});
889
+ target[prop] = val;
890
+ }
891
+ return target;
892
+ }
893
+ var Plugin = class {
894
+ /**
895
+ Create a plugin.
896
+ */
897
+ constructor(spec) {
898
+ this.spec = spec;
899
+ this.props = {};
900
+ if (spec.props)
901
+ bindProps(spec.props, this, this.props);
902
+ this.key = spec.key ? spec.key.key : createKey("plugin");
903
+ }
904
+ /**
905
+ Extract the plugin's state field from an editor state.
906
+ */
907
+ getState(state) {
908
+ return state[this.key];
909
+ }
910
+ };
911
+ var keys = /* @__PURE__ */ Object.create(null);
912
+ function createKey(name) {
913
+ if (name in keys)
914
+ return name + "$" + ++keys[name];
915
+ keys[name] = 0;
916
+ return name + "$";
917
+ }
918
+ var PluginKey = class {
919
+ /**
920
+ Create a plugin key.
921
+ */
922
+ constructor(name = "key") {
923
+ this.key = createKey(name);
924
+ }
925
+ /**
926
+ Get the active plugin with this key, if any, from an editor
927
+ state.
928
+ */
929
+ get(state) {
930
+ return state.config.pluginsByKey[this.key];
931
+ }
932
+ /**
933
+ Get the plugin's state from an editor state.
934
+ */
935
+ getState(state) {
936
+ return state[this.key];
937
+ }
938
+ };
939
+
940
+ export {
941
+ Selection,
942
+ SelectionRange,
943
+ TextSelection,
944
+ NodeSelection,
945
+ AllSelection,
946
+ Transaction,
947
+ EditorState,
948
+ Plugin,
949
+ PluginKey
950
+ };