@prosekit/core 0.0.0-next-20240724172520 → 0.0.0-next-20240901092634

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.
@@ -15,13 +15,17 @@ import {
15
15
  htmlFromJSON,
16
16
  htmlFromNode,
17
17
  isAllSelection,
18
+ isElement,
19
+ isFragment,
18
20
  isMark,
19
21
  isMarkAbsent,
20
22
  isMarkActive,
21
23
  isNodeActive,
22
24
  isNodeSelection,
23
- isNotNull,
25
+ isNotNullish,
24
26
  isProseMirrorNode,
27
+ isSelection,
28
+ isSlice,
25
29
  isTextSelection,
26
30
  jsonFromHTML,
27
31
  jsonFromNode,
@@ -35,10 +39,9 @@ import {
35
39
  stateFromJSON,
36
40
  toReversed,
37
41
  union
38
- } from "./chunk-MOSGJZHV.js";
42
+ } from "./chunk-RNBMCB5M.js";
39
43
 
40
44
  // src/commands/add-mark.ts
41
- import "@prosekit/pm/model";
42
45
  function addMark(options) {
43
46
  return (state, dispatch) => {
44
47
  var _a, _b;
@@ -139,8 +142,42 @@ function insertNode(options) {
139
142
  };
140
143
  }
141
144
 
145
+ // src/commands/insert-default-block.ts
146
+ import { TextSelection as TextSelection3 } from "@prosekit/pm/state";
147
+
148
+ // src/utils/default-block-at.ts
149
+ function defaultBlockAt(match) {
150
+ for (let i = 0; i < match.edgeCount; i++) {
151
+ const { type } = match.edge(i);
152
+ if (type.isTextblock && !type.hasRequiredAttrs()) return type;
153
+ }
154
+ return null;
155
+ }
156
+
157
+ // src/commands/insert-default-block.ts
158
+ function insertDefaultBlock(options) {
159
+ return (state, dispatch) => {
160
+ const $pos = (options == null ? void 0 : options.pos) == null ? state.selection.$to : state.doc.resolve(options.pos);
161
+ const depth = $pos.parent.isTextblock ? $pos.depth - 1 : $pos.depth;
162
+ const parent = $pos.node(depth);
163
+ const index = $pos.indexAfter(depth);
164
+ const type = defaultBlockAt(parent.contentMatchAt(index));
165
+ if (!type) return false;
166
+ if (dispatch) {
167
+ const pos = $pos.posAtIndex(index, depth);
168
+ const node = type.createAndFill();
169
+ if (!node) return false;
170
+ const tr = state.tr.insert(pos, node);
171
+ const selection = TextSelection3.findFrom(tr.doc.resolve(pos), 1);
172
+ if (!selection) return false;
173
+ tr.setSelection(selection);
174
+ dispatch(tr.scrollIntoView());
175
+ }
176
+ return true;
177
+ };
178
+ }
179
+
142
180
  // src/commands/remove-mark.ts
143
- import "@prosekit/pm/model";
144
181
  function removeMark(options) {
145
182
  return (state, dispatch) => {
146
183
  var _a, _b;
@@ -157,46 +194,43 @@ function removeMark(options) {
157
194
  }
158
195
 
159
196
  // src/utils/find-parent-node.ts
160
- function findParentNode(nodeType, $pos) {
161
- for (let depth = $pos.depth; depth > 0; depth -= 1) {
197
+ function findParentNode(predicate, $pos) {
198
+ for (let depth = $pos.depth; depth >= 0; depth -= 1) {
162
199
  const node = $pos.node(depth);
163
- if (node.type === nodeType) {
164
- const from = $pos.before(depth);
165
- const to = $pos.after(depth);
166
- return {
167
- from,
168
- to
169
- };
200
+ if (predicate(node)) {
201
+ const pos = depth === 0 ? 0 : $pos.before(depth);
202
+ const start = $pos.start(depth);
203
+ return { node, pos, start, depth };
170
204
  }
171
205
  }
172
- return {
173
- from: null,
174
- to: null
175
- };
206
+ }
207
+
208
+ // src/utils/find-parent-node-of-type.ts
209
+ function findParentNodeOfType(type, $pos) {
210
+ const nodeType = getNodeType($pos.doc.type.schema, type);
211
+ return findParentNode((node) => node.type === nodeType, $pos);
176
212
  }
177
213
 
178
214
  // src/commands/remove-node.ts
179
215
  function removeNode(options) {
180
216
  return (state, dispatch) => {
181
- const nodeType = getNodeType(state.schema, options.type);
182
217
  const $pos = typeof options.pos === "number" ? state.doc.resolve(options.pos) : state.selection.$anchor;
183
- const { from, to } = findParentNode(nodeType, $pos);
184
- if (from == null || to == null || from > to) {
185
- return false;
186
- }
187
- dispatch == null ? void 0 : dispatch(state.tr.delete(from, to));
218
+ const found = findParentNodeOfType(options.type, $pos);
219
+ if (!found) return false;
220
+ const { pos, node } = found;
221
+ dispatch == null ? void 0 : dispatch(state.tr.delete(pos, pos + node.nodeSize));
188
222
  return true;
189
223
  };
190
224
  }
191
225
 
192
226
  // src/utils/get-custom-selection.ts
193
- import { TextSelection as TextSelection3 } from "@prosekit/pm/state";
227
+ import { TextSelection as TextSelection4 } from "@prosekit/pm/state";
194
228
  function getCustomSelection(state, from, to) {
195
229
  const pos = from != null ? from : to;
196
230
  if (pos != null) {
197
231
  const $from = state.doc.resolve(from != null ? from : pos);
198
232
  const $to = state.doc.resolve(to != null ? to : pos);
199
- return TextSelection3.between($from, $to);
233
+ return TextSelection4.between($from, $to);
200
234
  }
201
235
  return state.selection;
202
236
  }
@@ -241,7 +275,6 @@ function setBlockType(options) {
241
275
  }
242
276
 
243
277
  // src/utils/get-node-types.ts
244
- import "@prosekit/pm/model";
245
278
  function getNodeTypes(schema, types) {
246
279
  if (Array.isArray(types)) {
247
280
  return types.map((type) => getNodeType(schema, type));
@@ -282,84 +315,23 @@ function setNodeAttrs(options) {
282
315
  }
283
316
 
284
317
  // src/commands/toggle-mark.ts
285
- import "@prosekit/pm/model";
286
- import "@prosekit/pm/state";
287
- function markApplies(doc, ranges, type) {
288
- for (const { $from, $to } of ranges) {
289
- let can = $from.depth == 0 ? doc.inlineContent && doc.type.allowsMarkType(type) : false;
290
- doc.nodesBetween($from.pos, $to.pos, (node) => {
291
- if (can) return false;
292
- can = node.inlineContent && node.type.allowsMarkType(type);
293
- });
294
- if (can) return true;
295
- }
296
- return false;
297
- }
298
- function baseToggleMark(markType, attrs = null, options) {
299
- const removeWhenPresent = (options && options.removeWhenPresent) !== false;
300
- return function(state, dispatch) {
301
- const { empty, $cursor, ranges } = state.selection;
302
- if (empty && !$cursor || !markApplies(state.doc, ranges, markType))
303
- return false;
304
- if (dispatch) {
305
- if ($cursor) {
306
- if (markType.isInSet(state.storedMarks || $cursor.marks()))
307
- dispatch(state.tr.removeStoredMark(markType));
308
- else dispatch(state.tr.addStoredMark(markType.create(attrs)));
309
- } else {
310
- let add;
311
- const tr = state.tr;
312
- if (removeWhenPresent) {
313
- add = !ranges.some(
314
- (r) => state.doc.rangeHasMark(r.$from.pos, r.$to.pos, markType)
315
- );
316
- } else {
317
- add = !ranges.every((r) => {
318
- let missing = false;
319
- tr.doc.nodesBetween(r.$from.pos, r.$to.pos, (node, pos, parent) => {
320
- if (missing) return false;
321
- missing = !markType.isInSet(node.marks) && !!parent && parent.type.allowsMarkType(markType) && !(node.isText && /^\s*$/.test(
322
- node.textBetween(
323
- Math.max(0, r.$from.pos - pos),
324
- Math.min(node.nodeSize, r.$to.pos - pos)
325
- )
326
- ));
327
- });
328
- return !missing;
329
- });
330
- }
331
- for (const { $from, $to } of ranges) {
332
- if (!add) {
333
- tr.removeMark($from.pos, $to.pos, markType);
334
- } else {
335
- let from = $from.pos, to = $to.pos;
336
- const start = $from.nodeAfter, end = $to.nodeBefore;
337
- const spaceStart = start && start.isText ? /^\s*/.exec(start.text)[0].length : 0;
338
- const spaceEnd = end && end.isText ? /\s*$/.exec(end.text)[0].length : 0;
339
- if (from + spaceStart < to) {
340
- from += spaceStart;
341
- to -= spaceEnd;
342
- }
343
- tr.addMark(from, to, markType.create(attrs));
344
- }
345
- }
346
- dispatch(tr.scrollIntoView());
347
- }
348
- }
349
- return true;
350
- };
351
- }
352
- function toggleMark({ type, attrs }) {
318
+ import { toggleMark as baseToggleMark } from "@prosekit/pm/commands";
319
+ function toggleMark({
320
+ type,
321
+ attrs,
322
+ removeWhenPresent = false,
323
+ enterInlineAtoms = true
324
+ }) {
353
325
  return (state, dispatch, view) => {
354
326
  return baseToggleMark(getMarkType(state.schema, type), attrs, {
355
- removeWhenPresent: false
327
+ removeWhenPresent,
328
+ enterInlineAtoms
356
329
  })(state, dispatch, view);
357
330
  };
358
331
  }
359
332
 
360
333
  // src/commands/toggle-node.ts
361
334
  import { setBlockType as setBlockType2 } from "@prosekit/pm/commands";
362
- import "@prosekit/pm/model";
363
335
  function toggleNode({ type, attrs }) {
364
336
  return (state, dispatch, view) => {
365
337
  if (isNodeActive(state, type, attrs)) {
@@ -377,7 +349,6 @@ function toggleNode({ type, attrs }) {
377
349
 
378
350
  // src/commands/unset-block-type.ts
379
351
  import { Fragment, Slice } from "@prosekit/pm/model";
380
- import "@prosekit/pm/state";
381
352
  import { ReplaceAroundStep } from "@prosekit/pm/transform";
382
353
  function unsetBlockType(options) {
383
354
  return (state, dispatch) => {
@@ -431,14 +402,14 @@ function unsetMark(options) {
431
402
  }
432
403
 
433
404
  // src/commands/wrap.ts
434
- import "@prosekit/pm/model";
435
405
  import { findWrapping } from "@prosekit/pm/transform";
436
- function wrap({ nodeType, attrs }) {
406
+ function wrap(options) {
437
407
  return (state, dispatch) => {
438
408
  const { $from, $to } = state.selection;
439
409
  const range = $from.blockRange($to);
440
410
  if (!range) return false;
441
- const wrapping = findWrapping(range, nodeType, attrs);
411
+ const nodeType = getNodeType(state.schema, options.nodeType || options.type);
412
+ const wrapping = findWrapping(range, nodeType, options.attrs);
442
413
  if (!wrapping) return false;
443
414
  dispatch == null ? void 0 : dispatch(state.tr.wrap(range, wrapping));
444
415
  return true;
@@ -493,6 +464,7 @@ function defineBaseCommands() {
493
464
  wrap,
494
465
  setBlockType,
495
466
  setNodeAttrs,
467
+ insertDefaultBlock,
496
468
  selectAll,
497
469
  addMark,
498
470
  removeMark,
@@ -502,10 +474,10 @@ function defineBaseCommands() {
502
474
  }
503
475
 
504
476
  // src/extensions/node-spec.ts
477
+ import clone from "just-clone";
505
478
  import OrderedMap2 from "orderedmap";
506
479
 
507
480
  // src/facets/schema-spec.ts
508
- import "@prosekit/pm/model";
509
481
  import OrderedMap from "orderedmap";
510
482
  var schemaSpecFacet = defineFacet({
511
483
  reducer: (specs) => {
@@ -524,10 +496,137 @@ var schemaSpecFacet = defineFacet({
524
496
  singleton: true
525
497
  });
526
498
 
527
- // src/utils/is-element.ts
528
- var hasElement = typeof Element !== "undefined";
529
- function isElement(value) {
530
- return hasElement && value instanceof Element;
499
+ // src/utils/array-grouping.ts
500
+ function groupBy(items, keySelector) {
501
+ const result = {};
502
+ for (const item of items) {
503
+ const key = keySelector(item);
504
+ const values = result[key] || (result[key] = []);
505
+ values.push(item);
506
+ }
507
+ return result;
508
+ }
509
+ function groupEntries(entries) {
510
+ const result = {};
511
+ for (const [key, value] of entries) {
512
+ const values = result[key] || (result[key] = []);
513
+ values.push(value);
514
+ }
515
+ return result;
516
+ }
517
+
518
+ // src/utils/remove-undefined-values.ts
519
+ function removeUndefinedValues(obj) {
520
+ const result = {};
521
+ for (const [key, value] of Object.entries(obj)) {
522
+ if (value !== void 0) {
523
+ result[key] = value;
524
+ }
525
+ }
526
+ return result;
527
+ }
528
+
529
+ // src/utils/merge-objects.ts
530
+ function mergeObjects(...objects) {
531
+ const filteredObjects = objects.filter(isNotNullish).map(removeUndefinedValues);
532
+ return Object.assign({}, ...filteredObjects);
533
+ }
534
+
535
+ // src/utils/merge-specs.ts
536
+ function mergeSpecs(a, b) {
537
+ var _a, _b, _c, _d, _e, _f;
538
+ const attrs = {};
539
+ const attrNames = /* @__PURE__ */ new Set([
540
+ ...Object.keys((_a = a.attrs) != null ? _a : {}),
541
+ ...Object.keys((_b = b.attrs) != null ? _b : {})
542
+ ]);
543
+ for (const name of attrNames) {
544
+ const attrSpecA = (_c = a.attrs) == null ? void 0 : _c[name];
545
+ const attrSpecB = (_d = b.attrs) == null ? void 0 : _d[name];
546
+ const attrSpecMerged = mergeObjects(attrSpecA, attrSpecB);
547
+ if (attrSpecMerged) {
548
+ attrs[name] = attrSpecMerged;
549
+ }
550
+ }
551
+ const parseDOM = [...(_e = a.parseDOM) != null ? _e : [], ...(_f = b.parseDOM) != null ? _f : []];
552
+ return mergeObjects(a, b, { attrs, parseDOM });
553
+ }
554
+
555
+ // src/utils/output-spec.ts
556
+ function wrapOutputSpecAttrs(toDOM, options) {
557
+ return (node, ...args) => {
558
+ const dom = toDOM(node, ...args);
559
+ const pairs = options.map((option) => {
560
+ var _a;
561
+ return (_a = option.toDOM) == null ? void 0 : _a.call(option, node.attrs[option.attr]);
562
+ }).filter(isNotNullish);
563
+ return insertOutputSpecAttrs(dom, pairs);
564
+ };
565
+ }
566
+ function wrapTagParseRuleAttrs(rule, options) {
567
+ const existingGetAttrs = rule.getAttrs;
568
+ const existingAttrs = rule.attrs;
569
+ return {
570
+ ...rule,
571
+ getAttrs: (dom) => {
572
+ var _a, _b;
573
+ const baseAttrs = (_b = (_a = existingGetAttrs == null ? void 0 : existingGetAttrs(dom)) != null ? _a : existingAttrs) != null ? _b : {};
574
+ if (baseAttrs === false || !dom || !isElement(dom)) {
575
+ return baseAttrs != null ? baseAttrs : null;
576
+ }
577
+ const insertedAttrs = {};
578
+ for (const option of options) {
579
+ if (option.parseDOM) {
580
+ insertedAttrs[option.attr] = option.parseDOM(dom);
581
+ }
582
+ }
583
+ return { ...baseAttrs, ...insertedAttrs };
584
+ }
585
+ };
586
+ }
587
+ function insertOutputSpecAttrs(dom, attrs) {
588
+ if (!dom) {
589
+ return dom;
590
+ }
591
+ if (Array.isArray(dom)) {
592
+ const rest = dom.slice(1);
593
+ let oldAttrs;
594
+ if (rest.length > 0 && (rest[0] == null || typeof rest[0] === "object")) {
595
+ oldAttrs = rest.shift();
596
+ } else {
597
+ oldAttrs = {};
598
+ }
599
+ const newAttrs = setObjectAttributes(oldAttrs, attrs);
600
+ return [dom[0], newAttrs, ...rest];
601
+ }
602
+ if (isElement(dom)) {
603
+ return setElementAttributes(dom, attrs);
604
+ }
605
+ if (typeof dom === "object" && "dom" in dom && isElement(dom.dom)) {
606
+ return { ...dom, dom: setElementAttributes(dom.dom, attrs) };
607
+ }
608
+ return dom;
609
+ }
610
+ function setObjectAttributes(obj, attrs) {
611
+ obj = { ...obj };
612
+ for (const [key, value] of attrs) {
613
+ const oldValue = obj[key];
614
+ const newValue = key === "style" ? joinStyles(value, typeof oldValue === "string" ? oldValue : "") : value;
615
+ obj[key] = newValue;
616
+ }
617
+ return obj;
618
+ }
619
+ function setElementAttributes(element, attrs) {
620
+ element = element.cloneNode(true);
621
+ for (const [key, value] of attrs) {
622
+ const oldValue = element.getAttribute(key);
623
+ const newValue = key === "style" ? joinStyles(value, typeof oldValue === "string" ? oldValue : "") : value;
624
+ element.setAttribute(key, newValue);
625
+ }
626
+ return element;
627
+ }
628
+ function joinStyles(...styles) {
629
+ return styles.map((style) => style.trim().replace(/;$/, "")).filter(Boolean).join("; ");
531
630
  }
532
631
 
533
632
  // src/extensions/node-spec.ts
@@ -543,105 +642,50 @@ var nodeSpecFacet = defineFacet({
543
642
  reducer: (payloads) => {
544
643
  let specs = OrderedMap2.from({});
545
644
  let topNodeName = void 0;
546
- const specPayloads = payloads.map((input) => input[0]).filter(isNotNull);
547
- const attrPayloads = payloads.map((input) => input[1]).filter(isNotNull);
645
+ const specPayloads = payloads.map((input) => input[0]).filter(isNotNullish);
646
+ const attrPayloads = payloads.map((input) => input[1]).filter(isNotNullish);
548
647
  for (const { name, topNode, ...spec } of specPayloads) {
549
- assert(!specs.get(name), `Node type ${name} can only be defined once`);
550
648
  if (topNode) {
551
649
  topNodeName = name;
552
650
  }
553
- specs = specs.addToStart(name, spec);
651
+ const prevSpec = specs.get(name);
652
+ if (prevSpec) {
653
+ specs = specs.update(name, mergeSpecs(prevSpec, spec));
654
+ } else {
655
+ specs = specs.addToStart(name, spec);
656
+ }
554
657
  }
555
- for (const {
556
- type,
557
- attr,
558
- default: defaultValue,
559
- splittable,
560
- toDOM,
561
- parseDOM
562
- } of attrPayloads) {
563
- const spec = specs.get(type);
564
- assert(spec, `Node type ${type} must be defined`);
658
+ const groupedAttrs = groupBy(attrPayloads, (payload) => payload.type);
659
+ for (const [type, attrs] of Object.entries(groupedAttrs)) {
660
+ if (!attrs) continue;
661
+ const maybeSpec = specs.get(type);
662
+ assert(maybeSpec, `Node type ${type} must be defined`);
663
+ const spec = clone(maybeSpec);
565
664
  if (!spec.attrs) {
566
665
  spec.attrs = {};
567
666
  }
568
- spec.attrs[attr] = {
569
- default: defaultValue,
570
- splittable
571
- };
572
- if (toDOM && spec.toDOM) {
573
- const existingToDom = spec.toDOM;
574
- spec.toDOM = (node) => {
575
- const dom = existingToDom(node);
576
- if (!dom) {
577
- return dom;
578
- }
579
- const attrDOM = toDOM(node.attrs[attr]);
580
- if (!attrDOM) {
581
- return dom;
582
- }
583
- const [key, value] = attrDOM;
584
- if (!key) {
585
- return dom;
586
- }
587
- if (Array.isArray(dom)) {
588
- if (typeof dom[1] === "object") {
589
- return [
590
- dom[0],
591
- setObjectAttribute(
592
- dom[1],
593
- key,
594
- value
595
- ),
596
- ...dom.slice(2)
597
- ];
598
- } else {
599
- return [dom[0], { [key]: value }, ...dom.slice(1)];
600
- }
601
- } else if (isElement(dom)) {
602
- setElementAttribute(dom, key, value);
603
- } else if (typeof dom === "object" && "dom" in dom && isElement(dom.dom)) {
604
- setElementAttribute(dom.dom, key, value);
605
- }
606
- return dom;
667
+ for (const attr of attrs) {
668
+ spec.attrs[attr.attr] = {
669
+ default: attr.default,
670
+ validate: attr.validate,
671
+ splittable: attr.splittable
607
672
  };
608
673
  }
609
- if (parseDOM && spec.parseDOM) {
610
- for (const rule of spec.parseDOM) {
611
- const existingGetAttrs = rule.getAttrs;
612
- const existingAttrs = rule.attrs;
613
- rule.getAttrs = (dom) => {
614
- var _a;
615
- const attrs = (_a = existingGetAttrs == null ? void 0 : existingGetAttrs(dom)) != null ? _a : existingAttrs;
616
- if (attrs === false || !dom || !isElement(dom)) {
617
- return attrs != null ? attrs : null;
618
- }
619
- const value = parseDOM(dom);
620
- return {
621
- ...attrs,
622
- [attr]: value
623
- };
624
- };
625
- }
674
+ if (spec.toDOM) {
675
+ spec.toDOM = wrapOutputSpecAttrs(spec.toDOM, attrs);
626
676
  }
677
+ if (spec.parseDOM) {
678
+ spec.parseDOM = spec.parseDOM.map(
679
+ (rule) => wrapTagParseRuleAttrs(rule, attrs)
680
+ );
681
+ }
682
+ specs = specs.update(type, spec);
627
683
  }
628
684
  return { nodes: specs, topNode: topNodeName };
629
685
  },
630
686
  parent: schemaSpecFacet,
631
687
  singleton: true
632
688
  });
633
- function setObjectAttribute(obj, key, value) {
634
- if (key === "style") {
635
- value = `${value}${obj.style || ""}`;
636
- }
637
- return { ...obj, [key]: value };
638
- }
639
- function setElementAttribute(element, key, value) {
640
- if (key === "style") {
641
- value = `${value}${element.getAttribute("style") || ""}`;
642
- }
643
- element.setAttribute(key, value);
644
- }
645
689
 
646
690
  // src/extensions/doc.ts
647
691
  function defineDoc() {
@@ -653,23 +697,25 @@ function defineDoc() {
653
697
  }
654
698
 
655
699
  // src/extensions/events/plugin-view.ts
656
- import { PluginKey, ProseMirrorPlugin as ProseMirrorPlugin2 } from "@prosekit/pm/state";
700
+ import {
701
+ PluginKey,
702
+ ProseMirrorPlugin
703
+ } from "@prosekit/pm/state";
657
704
 
658
705
  // src/extensions/plugin.ts
659
- import "@prosekit/pm/model";
660
706
  import { Plugin } from "@prosekit/pm/state";
661
707
  function definePlugin(plugin) {
662
- if (plugin instanceof Plugin) {
663
- return defineFacetPayload(pluginFacet, [() => [plugin]]);
664
- }
665
- if (Array.isArray(plugin) && plugin.every((p) => p instanceof Plugin)) {
666
- return defineFacetPayload(pluginFacet, [() => plugin]);
708
+ if (plugin instanceof Plugin || Array.isArray(plugin) && plugin.every((p) => p instanceof Plugin)) {
709
+ return definePluginPayload(() => plugin);
667
710
  }
668
711
  if (typeof plugin === "function") {
669
- return defineFacetPayload(pluginFacet, [plugin]);
712
+ return definePluginPayload(plugin);
670
713
  }
671
714
  throw new TypeError("Invalid plugin");
672
715
  }
716
+ function definePluginPayload(payload) {
717
+ return defineFacetPayload(pluginFacet, [payload]);
718
+ }
673
719
  var pluginFacet = defineFacet({
674
720
  reducer: (payloads) => {
675
721
  return ({ schema }) => {
@@ -694,20 +740,23 @@ var pluginFacet = defineFacet({
694
740
 
695
741
  // src/extensions/events/plugin-view.ts
696
742
  function defineMountHandler(handler) {
697
- return defineFacetPayload(pluginViewFacet, [["mount", handler]]);
743
+ return definePluginViewFacetPayload(["mount", handler]);
698
744
  }
699
745
  function defineUpdateHandler(handler) {
700
- return defineFacetPayload(pluginViewFacet, [["update", handler]]);
746
+ return definePluginViewFacetPayload(["update", handler]);
701
747
  }
702
748
  function defineUnmountHandler(handler) {
703
- return defineFacetPayload(pluginViewFacet, [["unmount", handler]]);
749
+ return definePluginViewFacetPayload(["unmount", handler]);
750
+ }
751
+ function definePluginViewFacetPayload(input) {
752
+ return defineFacetPayload(pluginViewFacet, [input]);
704
753
  }
705
754
  var pluginViewFacet = defineFacet({
706
755
  reduce: () => {
707
756
  let mountHandlers = [];
708
757
  let updateHandlers = [];
709
758
  let unmountHandlers = [];
710
- const plugin = new ProseMirrorPlugin2({
759
+ const plugin = new ProseMirrorPlugin({
711
760
  key: pluginKey,
712
761
  view: (view) => {
713
762
  mountHandlers.forEach((fn) => fn(view));
@@ -759,16 +808,16 @@ function defineDocChangeHandler(handler) {
759
808
  }
760
809
 
761
810
  // src/extensions/events/dom-event.ts
762
- import { PluginKey as PluginKey2, ProseMirrorPlugin as ProseMirrorPlugin3 } from "@prosekit/pm/state";
811
+ import { PluginKey as PluginKey2, ProseMirrorPlugin as ProseMirrorPlugin2 } from "@prosekit/pm/state";
763
812
 
764
813
  // src/utils/combine-event-handlers.ts
765
814
  function combineEventHandlers() {
766
- let _handlers = [];
767
- function setHandlers(handlers) {
768
- _handlers = toReversed(handlers);
815
+ let handlers = [];
816
+ function setHandlers(eventHandlers) {
817
+ handlers = toReversed(eventHandlers);
769
818
  }
770
819
  function combinedEventHandler(...args) {
771
- for (const handler of _handlers) {
820
+ for (const handler of handlers) {
772
821
  if (handler(...args)) {
773
822
  return true;
774
823
  }
@@ -778,20 +827,6 @@ function combineEventHandlers() {
778
827
  return [setHandlers, combinedEventHandler];
779
828
  }
780
829
 
781
- // src/utils/group-entries.ts
782
- function groupEntries(entries) {
783
- const map = {};
784
- for (const [key, value] of entries) {
785
- const values = map[key];
786
- if (!values) {
787
- map[key] = [value];
788
- } else {
789
- values.push(value);
790
- }
791
- }
792
- return map;
793
- }
794
-
795
830
  // src/extensions/events/dom-event.ts
796
831
  function defineDOMEventHandler(event, handler) {
797
832
  return defineFacetPayload(domEventFacet, [
@@ -823,7 +858,7 @@ var domEventFacet = defineFacet({
823
858
  setHandlers(handlers);
824
859
  }
825
860
  if (hasNewEvent) {
826
- plugin = new ProseMirrorPlugin3({
861
+ plugin = new ProseMirrorPlugin2({
827
862
  key: new PluginKey2("prosekit-dom-event-handler"),
828
863
  props: { handleDOMEvents: combinedHandlerMap }
829
864
  });
@@ -839,7 +874,7 @@ var domEventFacet = defineFacet({
839
874
  });
840
875
 
841
876
  // src/extensions/events/editor-event.ts
842
- import { PluginKey as PluginKey3, ProseMirrorPlugin as ProseMirrorPlugin4 } from "@prosekit/pm/state";
877
+ import { PluginKey as PluginKey3, ProseMirrorPlugin as ProseMirrorPlugin3 } from "@prosekit/pm/state";
843
878
  function defineKeyDownHandler(handler) {
844
879
  return defineFacetPayload(editorEventFacet, [["keyDown", handler]]);
845
880
  }
@@ -916,7 +951,7 @@ function setupEditorEventPlugin() {
916
951
  setDropHandlers((_k = map.drop) != null ? _k : []);
917
952
  setScrollToSelectionHandlers((_l = map.scrollToSelection) != null ? _l : []);
918
953
  };
919
- const plugin = new ProseMirrorPlugin4({
954
+ const plugin = new ProseMirrorPlugin3({
920
955
  key: new PluginKey3("prosekit-editor-event"),
921
956
  props: {
922
957
  handleKeyDown,
@@ -956,6 +991,7 @@ var isApple = typeof navigator !== "undefined" ? /Mac|iP(hone|[ao]d)/.test(navig
956
991
  import { chainCommands } from "@prosekit/pm/commands";
957
992
  import { keydownHandler } from "@prosekit/pm/keymap";
958
993
  import { Plugin as Plugin2, PluginKey as PluginKey4 } from "@prosekit/pm/state";
994
+ import mapValues from "just-map-values";
959
995
  function defineKeymap(keymap2) {
960
996
  return defineFacetPayload(keymapFacet, [keymap2]);
961
997
  }
@@ -991,12 +1027,10 @@ function mergeKeymaps(keymaps) {
991
1027
  commands2.push(command);
992
1028
  }
993
1029
  }
994
- return Object.fromEntries(
995
- Object.entries(bindings).map(([key, commands2]) => [
996
- key,
997
- chainCommands(...commands2)
998
- ])
999
- );
1030
+ return mapValues(bindings, mergeCommands);
1031
+ }
1032
+ function mergeCommands(commands2) {
1033
+ return chainCommands(...commands2);
1000
1034
  }
1001
1035
  var keymapPluginKey = new PluginKey4("prosekit-keymap");
1002
1036
 
@@ -1016,11 +1050,11 @@ function defineHistory({
1016
1050
  depth = 200,
1017
1051
  newGroupDelay = 250
1018
1052
  } = {}) {
1019
- return union([
1053
+ return union(
1020
1054
  definePlugin(history({ depth, newGroupDelay })),
1021
1055
  defineKeymap(keymap),
1022
1056
  defineCommands(commands)
1023
- ]);
1057
+ );
1024
1058
  }
1025
1059
 
1026
1060
  // src/extensions/keymap-base.ts
@@ -1061,6 +1095,7 @@ function defineBaseKeymap(options) {
1061
1095
  }
1062
1096
 
1063
1097
  // src/extensions/mark-spec.ts
1098
+ import clone2 from "just-clone";
1064
1099
  import OrderedMap3 from "orderedmap";
1065
1100
  function defineMarkSpec(options) {
1066
1101
  const payload = [options, void 0];
@@ -1073,81 +1108,55 @@ function defineMarkAttr(options) {
1073
1108
  var markSpecFacet = defineFacet({
1074
1109
  reducer: (payloads) => {
1075
1110
  let specs = OrderedMap3.from({});
1076
- const specPayloads = payloads.map((input) => input[0]).filter(isNotNull);
1077
- const attrPayloads = payloads.map((input) => input[1]).filter(isNotNull);
1111
+ const specPayloads = payloads.map((input) => input[0]).filter(isNotNullish);
1112
+ const attrPayloads = payloads.map((input) => input[1]).filter(isNotNullish);
1078
1113
  for (const { name, ...spec } of specPayloads) {
1079
- assert(!specs.get(name), `Mark type ${name} can only be defined once`);
1080
- specs = specs.addToStart(name, spec);
1114
+ const prevSpec = specs.get(name);
1115
+ if (prevSpec) {
1116
+ specs = specs.update(name, mergeSpecs(prevSpec, spec));
1117
+ } else {
1118
+ specs = specs.addToStart(name, spec);
1119
+ }
1081
1120
  }
1082
- for (const {
1083
- type,
1084
- attr,
1085
- default: defaultValue,
1086
- toDOM,
1087
- parseDOM
1088
- } of attrPayloads) {
1089
- const spec = specs.get(type);
1090
- assert(spec, `Mark type ${type} must be defined`);
1121
+ const groupedAttrs = groupBy(attrPayloads, (payload) => payload.type);
1122
+ for (const [type, attrs] of Object.entries(groupedAttrs)) {
1123
+ if (!attrs) continue;
1124
+ const maybeSpec = specs.get(type);
1125
+ assert(maybeSpec, `Mark type ${type} must be defined`);
1126
+ const spec = clone2(maybeSpec);
1091
1127
  if (!spec.attrs) {
1092
1128
  spec.attrs = {};
1093
1129
  }
1094
- spec.attrs[attr] = { default: defaultValue };
1095
- if (toDOM && spec.toDOM) {
1096
- const existingToDom = spec.toDOM;
1097
- spec.toDOM = (mark, inline) => {
1098
- const dom = existingToDom(mark, inline);
1099
- if (!dom) {
1100
- return dom;
1101
- }
1102
- const attrDOM = toDOM(mark.attrs[attr]);
1103
- if (!attrDOM) {
1104
- return dom;
1105
- }
1106
- const [key, value] = attrDOM;
1107
- if (!key) {
1108
- return dom;
1109
- }
1110
- if (Array.isArray(dom)) {
1111
- if (typeof dom[1] === "object") {
1112
- return [dom[0], { ...dom[1], [key]: value }, ...dom.slice(2)];
1113
- } else {
1114
- return [dom[0], { [key]: value }, ...dom.slice(1)];
1115
- }
1116
- } else if (isElement(dom)) {
1117
- dom.setAttribute(key, value);
1118
- } else if (typeof dom === "object" && "dom" in dom && isElement(dom.dom)) {
1119
- dom.dom.setAttribute(key, value);
1120
- }
1121
- return dom;
1130
+ for (const attr of attrs) {
1131
+ spec.attrs[attr.attr] = {
1132
+ default: attr.default,
1133
+ validate: attr.validate
1122
1134
  };
1123
1135
  }
1124
- if (parseDOM && spec.parseDOM) {
1125
- for (const rule of spec.parseDOM) {
1126
- const existingGetAttrs = rule.getAttrs;
1127
- const existingAttrs = rule.attrs;
1128
- rule.getAttrs = (dom) => {
1129
- var _a;
1130
- const attrs = (_a = existingGetAttrs == null ? void 0 : existingGetAttrs(dom)) != null ? _a : existingAttrs;
1131
- if (attrs === false || !dom || !isElement(dom)) {
1132
- return attrs != null ? attrs : null;
1133
- }
1134
- const value = parseDOM(dom);
1135
- return {
1136
- ...attrs,
1137
- [attr]: value
1138
- };
1139
- };
1140
- }
1136
+ if (spec.toDOM) {
1137
+ spec.toDOM = wrapOutputSpecAttrs(spec.toDOM, attrs);
1138
+ }
1139
+ if (spec.parseDOM) {
1140
+ spec.parseDOM = spec.parseDOM.map(
1141
+ (rule) => wrapParseRuleAttrs(rule, attrs)
1142
+ );
1141
1143
  }
1144
+ specs = specs.update(type, spec);
1142
1145
  }
1143
1146
  return { marks: specs, nodes: {} };
1144
1147
  },
1145
1148
  parent: schemaSpecFacet,
1146
1149
  singleton: true
1147
1150
  });
1151
+ function wrapParseRuleAttrs(rule, attrs) {
1152
+ if (rule.tag) {
1153
+ return wrapTagParseRuleAttrs(rule, attrs);
1154
+ }
1155
+ return rule;
1156
+ }
1148
1157
 
1149
1158
  // src/extensions/node-view.ts
1150
- import { PluginKey as PluginKey5, ProseMirrorPlugin as ProseMirrorPlugin5 } from "@prosekit/pm/state";
1159
+ import { PluginKey as PluginKey5, ProseMirrorPlugin as ProseMirrorPlugin4 } from "@prosekit/pm/state";
1151
1160
  function defineNodeView(options) {
1152
1161
  return defineFacetPayload(nodeViewFacet, [options]);
1153
1162
  }
@@ -1160,7 +1169,7 @@ var nodeViewFacet = defineFacet({
1160
1169
  }
1161
1170
  }
1162
1171
  return () => [
1163
- new ProseMirrorPlugin5({
1172
+ new ProseMirrorPlugin4({
1164
1173
  key: new PluginKey5("prosekit-node-view"),
1165
1174
  props: { nodeViews }
1166
1175
  })
@@ -1170,7 +1179,7 @@ var nodeViewFacet = defineFacet({
1170
1179
  });
1171
1180
 
1172
1181
  // src/extensions/node-view-effect.ts
1173
- import { PluginKey as PluginKey6, ProseMirrorPlugin as ProseMirrorPlugin6 } from "@prosekit/pm/state";
1182
+ import { PluginKey as PluginKey6, ProseMirrorPlugin as ProseMirrorPlugin5 } from "@prosekit/pm/state";
1174
1183
  function defineNodeViewFactory(options) {
1175
1184
  const input = [options, null];
1176
1185
  return defineFacetPayload(nodeViewFactoryFacet, [input]);
@@ -1184,15 +1193,15 @@ var nodeViewFactoryFacet = defineFacet({
1184
1193
  reducer: (inputs) => {
1185
1194
  if (isServer) return [];
1186
1195
  const nodeViews = {};
1187
- const factories = inputs.map((x) => x[0]).filter(isNotNull);
1188
- const options = inputs.map((x) => x[1]).filter(isNotNull);
1196
+ const factories = inputs.map((x) => x[0]).filter(isNotNullish);
1197
+ const options = inputs.map((x) => x[1]).filter(isNotNullish);
1189
1198
  for (const { group, name, args } of options) {
1190
1199
  const factory = factories.find((factory2) => factory2.group === group);
1191
1200
  if (!factory) continue;
1192
1201
  nodeViews[name] = factory.factory(args);
1193
1202
  }
1194
1203
  return () => [
1195
- new ProseMirrorPlugin6({
1204
+ new ProseMirrorPlugin5({
1196
1205
  key: new PluginKey6("prosekit-node-view-effect"),
1197
1206
  props: { nodeViews }
1198
1207
  })
@@ -1240,7 +1249,7 @@ function cache(fn) {
1240
1249
  var canUseRegexLookbehind = cache(() => {
1241
1250
  try {
1242
1251
  return "ab".replace(new RegExp("(?<=a)b", "g"), "c") === "ac";
1243
- } catch (error) {
1252
+ } catch (e) {
1244
1253
  return false;
1245
1254
  }
1246
1255
  });
@@ -1249,13 +1258,22 @@ var canUseRegexLookbehind = cache(() => {
1249
1258
  import clsxLite from "clsx/lite";
1250
1259
  var clsx = clsxLite;
1251
1260
 
1261
+ // src/utils/collect-children.ts
1262
+ function collectChildren(parent) {
1263
+ const children = [];
1264
+ for (let i = 0; i < parent.childCount; i++) {
1265
+ children.push(parent.child(i));
1266
+ }
1267
+ return children;
1268
+ }
1269
+
1252
1270
  // src/utils/collect-nodes.ts
1253
- import { ProseMirrorFragment, ProseMirrorNode as ProseMirrorNode2 } from "@prosekit/pm/model";
1271
+ import { ProseMirrorFragment, ProseMirrorNode } from "@prosekit/pm/model";
1254
1272
  function collectNodes(content) {
1255
1273
  if (Array.isArray(content)) {
1256
1274
  return content.flatMap(collectNodes);
1257
1275
  }
1258
- if (content instanceof ProseMirrorNode2) {
1276
+ if (content instanceof ProseMirrorNode) {
1259
1277
  return [content];
1260
1278
  }
1261
1279
  if (content instanceof ProseMirrorFragment) {
@@ -1278,15 +1296,6 @@ function containsInlineNode(doc, from, to) {
1278
1296
  return found;
1279
1297
  }
1280
1298
 
1281
- // src/utils/default-block-at.ts
1282
- function defaultBlockAt(match) {
1283
- for (let i = 0; i < match.edgeCount; i++) {
1284
- const { type } = match.edge(i);
1285
- if (type.isTextblock && !type.hasRequiredAttrs()) return type;
1286
- }
1287
- return null;
1288
- }
1289
-
1290
1299
  // src/utils/get-id.ts
1291
1300
  var id = 0;
1292
1301
  function getId() {
@@ -1338,6 +1347,7 @@ export {
1338
1347
  assert,
1339
1348
  canUseRegexLookbehind,
1340
1349
  clsx,
1350
+ collectChildren,
1341
1351
  collectNodes,
1342
1352
  containsInlineNode,
1343
1353
  createEditor,
@@ -1382,20 +1392,26 @@ export {
1382
1392
  elementFromJSON,
1383
1393
  elementFromNode,
1384
1394
  expandMark,
1395
+ findParentNode,
1396
+ findParentNodeOfType,
1385
1397
  getMarkType,
1386
1398
  getNodeType,
1387
1399
  htmlFromJSON,
1388
1400
  htmlFromNode,
1401
+ insertDefaultBlock,
1389
1402
  insertNode,
1390
1403
  isAllSelection,
1391
1404
  isApple,
1392
1405
  isAtBlockStart,
1406
+ isFragment,
1393
1407
  isInCodeBlock,
1394
1408
  isMark,
1395
1409
  isMarkAbsent,
1396
1410
  isMarkActive,
1397
1411
  isNodeSelection,
1398
1412
  isProseMirrorNode,
1413
+ isSelection,
1414
+ isSlice,
1399
1415
  isTextSelection,
1400
1416
  jsonFromHTML,
1401
1417
  jsonFromNode,