@prosekit/core 0.7.7 → 0.7.9

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.
@@ -16,14 +16,16 @@ import {
16
16
  htmlFromNode,
17
17
  isAllSelection,
18
18
  isElement,
19
+ isFragment,
19
20
  isMark,
20
21
  isMarkAbsent,
21
22
  isMarkActive,
22
23
  isNodeActive,
23
24
  isNodeSelection,
24
- isNotNull,
25
+ isNotNullish,
25
26
  isProseMirrorNode,
26
27
  isSelection,
28
+ isSlice,
27
29
  isTextSelection,
28
30
  jsonFromHTML,
29
31
  jsonFromNode,
@@ -37,10 +39,9 @@ import {
37
39
  stateFromJSON,
38
40
  toReversed,
39
41
  union
40
- } from "./chunk-MDJ2B4IL.js";
42
+ } from "./chunk-RNBMCB5M.js";
41
43
 
42
44
  // src/commands/add-mark.ts
43
- import "@prosekit/pm/model";
44
45
  function addMark(options) {
45
46
  return (state, dispatch) => {
46
47
  var _a, _b;
@@ -142,7 +143,6 @@ function insertNode(options) {
142
143
  }
143
144
 
144
145
  // src/commands/remove-mark.ts
145
- import "@prosekit/pm/model";
146
146
  function removeMark(options) {
147
147
  return (state, dispatch) => {
148
148
  var _a, _b;
@@ -159,34 +159,31 @@ function removeMark(options) {
159
159
  }
160
160
 
161
161
  // src/utils/find-parent-node.ts
162
- function findParentNode(nodeType, $pos) {
163
- for (let depth = $pos.depth; depth > 0; depth -= 1) {
162
+ function findParentNode(predicate, $pos) {
163
+ for (let depth = $pos.depth; depth >= 0; depth -= 1) {
164
164
  const node = $pos.node(depth);
165
- if (node.type === nodeType) {
166
- const from = $pos.before(depth);
167
- const to = $pos.after(depth);
168
- return {
169
- from,
170
- to
171
- };
165
+ if (predicate(node)) {
166
+ const pos = depth === 0 ? 0 : $pos.before(depth);
167
+ const start = $pos.start(depth);
168
+ return { node, pos, start, depth };
172
169
  }
173
170
  }
174
- return {
175
- from: null,
176
- to: null
177
- };
171
+ }
172
+
173
+ // src/utils/find-parent-node-of-type.ts
174
+ function findParentNodeOfType(type, $pos) {
175
+ const nodeType = getNodeType($pos.doc.type.schema, type);
176
+ return findParentNode((node) => node.type === nodeType, $pos);
178
177
  }
179
178
 
180
179
  // src/commands/remove-node.ts
181
180
  function removeNode(options) {
182
181
  return (state, dispatch) => {
183
- const nodeType = getNodeType(state.schema, options.type);
184
182
  const $pos = typeof options.pos === "number" ? state.doc.resolve(options.pos) : state.selection.$anchor;
185
- const { from, to } = findParentNode(nodeType, $pos);
186
- if (from == null || to == null || from > to) {
187
- return false;
188
- }
189
- dispatch == null ? void 0 : dispatch(state.tr.delete(from, to));
183
+ const found = findParentNodeOfType(options.type, $pos);
184
+ if (!found) return false;
185
+ const { pos, node } = found;
186
+ dispatch == null ? void 0 : dispatch(state.tr.delete(pos, pos + node.nodeSize));
190
187
  return true;
191
188
  };
192
189
  }
@@ -243,7 +240,6 @@ function setBlockType(options) {
243
240
  }
244
241
 
245
242
  // src/utils/get-node-types.ts
246
- import "@prosekit/pm/model";
247
243
  function getNodeTypes(schema, types) {
248
244
  if (Array.isArray(types)) {
249
245
  return types.map((type) => getNodeType(schema, type));
@@ -284,84 +280,23 @@ function setNodeAttrs(options) {
284
280
  }
285
281
 
286
282
  // src/commands/toggle-mark.ts
287
- import "@prosekit/pm/model";
288
- import "@prosekit/pm/state";
289
- function markApplies(doc, ranges, type) {
290
- for (const { $from, $to } of ranges) {
291
- let can = $from.depth == 0 ? doc.inlineContent && doc.type.allowsMarkType(type) : false;
292
- doc.nodesBetween($from.pos, $to.pos, (node) => {
293
- if (can) return false;
294
- can = node.inlineContent && node.type.allowsMarkType(type);
295
- });
296
- if (can) return true;
297
- }
298
- return false;
299
- }
300
- function baseToggleMark(markType, attrs = null, options) {
301
- const removeWhenPresent = (options && options.removeWhenPresent) !== false;
302
- return function(state, dispatch) {
303
- const { empty, $cursor, ranges } = state.selection;
304
- if (empty && !$cursor || !markApplies(state.doc, ranges, markType))
305
- return false;
306
- if (dispatch) {
307
- if ($cursor) {
308
- if (markType.isInSet(state.storedMarks || $cursor.marks()))
309
- dispatch(state.tr.removeStoredMark(markType));
310
- else dispatch(state.tr.addStoredMark(markType.create(attrs)));
311
- } else {
312
- let add;
313
- const tr = state.tr;
314
- if (removeWhenPresent) {
315
- add = !ranges.some(
316
- (r) => state.doc.rangeHasMark(r.$from.pos, r.$to.pos, markType)
317
- );
318
- } else {
319
- add = !ranges.every((r) => {
320
- let missing = false;
321
- tr.doc.nodesBetween(r.$from.pos, r.$to.pos, (node, pos, parent) => {
322
- if (missing) return false;
323
- missing = !markType.isInSet(node.marks) && !!parent && parent.type.allowsMarkType(markType) && !(node.isText && /^\s*$/.test(
324
- node.textBetween(
325
- Math.max(0, r.$from.pos - pos),
326
- Math.min(node.nodeSize, r.$to.pos - pos)
327
- )
328
- ));
329
- });
330
- return !missing;
331
- });
332
- }
333
- for (const { $from, $to } of ranges) {
334
- if (!add) {
335
- tr.removeMark($from.pos, $to.pos, markType);
336
- } else {
337
- let from = $from.pos, to = $to.pos;
338
- const start = $from.nodeAfter, end = $to.nodeBefore;
339
- const spaceStart = start && start.isText ? /^\s*/.exec(start.text)[0].length : 0;
340
- const spaceEnd = end && end.isText ? /\s*$/.exec(end.text)[0].length : 0;
341
- if (from + spaceStart < to) {
342
- from += spaceStart;
343
- to -= spaceEnd;
344
- }
345
- tr.addMark(from, to, markType.create(attrs));
346
- }
347
- }
348
- dispatch(tr.scrollIntoView());
349
- }
350
- }
351
- return true;
352
- };
353
- }
354
- function toggleMark({ type, attrs }) {
283
+ import { toggleMark as baseToggleMark } from "@prosekit/pm/commands";
284
+ function toggleMark({
285
+ type,
286
+ attrs,
287
+ removeWhenPresent = false,
288
+ enterInlineAtoms = true
289
+ }) {
355
290
  return (state, dispatch, view) => {
356
291
  return baseToggleMark(getMarkType(state.schema, type), attrs, {
357
- removeWhenPresent: false
292
+ removeWhenPresent,
293
+ enterInlineAtoms
358
294
  })(state, dispatch, view);
359
295
  };
360
296
  }
361
297
 
362
298
  // src/commands/toggle-node.ts
363
299
  import { setBlockType as setBlockType2 } from "@prosekit/pm/commands";
364
- import "@prosekit/pm/model";
365
300
  function toggleNode({ type, attrs }) {
366
301
  return (state, dispatch, view) => {
367
302
  if (isNodeActive(state, type, attrs)) {
@@ -379,7 +314,6 @@ function toggleNode({ type, attrs }) {
379
314
 
380
315
  // src/commands/unset-block-type.ts
381
316
  import { Fragment, Slice } from "@prosekit/pm/model";
382
- import "@prosekit/pm/state";
383
317
  import { ReplaceAroundStep } from "@prosekit/pm/transform";
384
318
  function unsetBlockType(options) {
385
319
  return (state, dispatch) => {
@@ -433,14 +367,14 @@ function unsetMark(options) {
433
367
  }
434
368
 
435
369
  // src/commands/wrap.ts
436
- import "@prosekit/pm/model";
437
370
  import { findWrapping } from "@prosekit/pm/transform";
438
- function wrap({ nodeType, attrs }) {
371
+ function wrap(options) {
439
372
  return (state, dispatch) => {
440
373
  const { $from, $to } = state.selection;
441
374
  const range = $from.blockRange($to);
442
375
  if (!range) return false;
443
- const wrapping = findWrapping(range, nodeType, attrs);
376
+ const nodeType = getNodeType(state.schema, options.nodeType || options.type);
377
+ const wrapping = findWrapping(range, nodeType, options.attrs);
444
378
  if (!wrapping) return false;
445
379
  dispatch == null ? void 0 : dispatch(state.tr.wrap(range, wrapping));
446
380
  return true;
@@ -504,10 +438,10 @@ function defineBaseCommands() {
504
438
  }
505
439
 
506
440
  // src/extensions/node-spec.ts
441
+ import clone from "just-clone";
507
442
  import OrderedMap2 from "orderedmap";
508
443
 
509
444
  // src/facets/schema-spec.ts
510
- import "@prosekit/pm/model";
511
445
  import OrderedMap from "orderedmap";
512
446
  var schemaSpecFacet = defineFacet({
513
447
  reducer: (specs) => {
@@ -526,6 +460,139 @@ var schemaSpecFacet = defineFacet({
526
460
  singleton: true
527
461
  });
528
462
 
463
+ // src/utils/array-grouping.ts
464
+ function groupBy(items, keySelector) {
465
+ const result = {};
466
+ for (const item of items) {
467
+ const key = keySelector(item);
468
+ const values = result[key] || (result[key] = []);
469
+ values.push(item);
470
+ }
471
+ return result;
472
+ }
473
+ function groupEntries(entries) {
474
+ const result = {};
475
+ for (const [key, value] of entries) {
476
+ const values = result[key] || (result[key] = []);
477
+ values.push(value);
478
+ }
479
+ return result;
480
+ }
481
+
482
+ // src/utils/remove-undefined-values.ts
483
+ function removeUndefinedValues(obj) {
484
+ const result = {};
485
+ for (const [key, value] of Object.entries(obj)) {
486
+ if (value !== void 0) {
487
+ result[key] = value;
488
+ }
489
+ }
490
+ return result;
491
+ }
492
+
493
+ // src/utils/merge-objects.ts
494
+ function mergeObjects(...objects) {
495
+ const filteredObjects = objects.filter(isNotNullish).map(removeUndefinedValues);
496
+ return Object.assign({}, ...filteredObjects);
497
+ }
498
+
499
+ // src/utils/merge-specs.ts
500
+ function mergeSpecs(a, b) {
501
+ var _a, _b, _c, _d, _e, _f;
502
+ const attrs = {};
503
+ const attrNames = /* @__PURE__ */ new Set([
504
+ ...Object.keys((_a = a.attrs) != null ? _a : {}),
505
+ ...Object.keys((_b = b.attrs) != null ? _b : {})
506
+ ]);
507
+ for (const name of attrNames) {
508
+ const attrSpecA = (_c = a.attrs) == null ? void 0 : _c[name];
509
+ const attrSpecB = (_d = b.attrs) == null ? void 0 : _d[name];
510
+ const attrSpecMerged = mergeObjects(attrSpecA, attrSpecB);
511
+ if (attrSpecMerged) {
512
+ attrs[name] = attrSpecMerged;
513
+ }
514
+ }
515
+ const parseDOM = [...(_e = a.parseDOM) != null ? _e : [], ...(_f = b.parseDOM) != null ? _f : []];
516
+ return mergeObjects(a, b, { attrs, parseDOM });
517
+ }
518
+
519
+ // src/utils/output-spec.ts
520
+ function wrapOutputSpecAttrs(toDOM, options) {
521
+ return (node, ...args) => {
522
+ const dom = toDOM(node, ...args);
523
+ const pairs = options.map((option) => {
524
+ var _a;
525
+ return (_a = option.toDOM) == null ? void 0 : _a.call(option, node.attrs[option.attr]);
526
+ }).filter(isNotNullish);
527
+ return insertOutputSpecAttrs(dom, pairs);
528
+ };
529
+ }
530
+ function wrapTagParseRuleAttrs(rule, options) {
531
+ const existingGetAttrs = rule.getAttrs;
532
+ const existingAttrs = rule.attrs;
533
+ return {
534
+ ...rule,
535
+ getAttrs: (dom) => {
536
+ var _a, _b;
537
+ const baseAttrs = (_b = (_a = existingGetAttrs == null ? void 0 : existingGetAttrs(dom)) != null ? _a : existingAttrs) != null ? _b : {};
538
+ if (baseAttrs === false || !dom || !isElement(dom)) {
539
+ return baseAttrs != null ? baseAttrs : null;
540
+ }
541
+ const insertedAttrs = {};
542
+ for (const option of options) {
543
+ if (option.parseDOM) {
544
+ insertedAttrs[option.attr] = option.parseDOM(dom);
545
+ }
546
+ }
547
+ return { ...baseAttrs, ...insertedAttrs };
548
+ }
549
+ };
550
+ }
551
+ function insertOutputSpecAttrs(dom, attrs) {
552
+ if (!dom) {
553
+ return dom;
554
+ }
555
+ if (Array.isArray(dom)) {
556
+ const rest = dom.slice(1);
557
+ let oldAttrs;
558
+ if (rest.length > 0 && (rest[0] == null || typeof rest[0] === "object")) {
559
+ oldAttrs = rest.shift();
560
+ } else {
561
+ oldAttrs = {};
562
+ }
563
+ const newAttrs = setObjectAttributes(oldAttrs, attrs);
564
+ return [dom[0], newAttrs, ...rest];
565
+ }
566
+ if (isElement(dom)) {
567
+ return setElementAttributes(dom, attrs);
568
+ }
569
+ if (typeof dom === "object" && "dom" in dom && isElement(dom.dom)) {
570
+ return { ...dom, dom: setElementAttributes(dom.dom, attrs) };
571
+ }
572
+ return dom;
573
+ }
574
+ function setObjectAttributes(obj, attrs) {
575
+ obj = { ...obj };
576
+ for (const [key, value] of attrs) {
577
+ const oldValue = obj[key];
578
+ const newValue = key === "style" ? joinStyles(value, typeof oldValue === "string" ? oldValue : "") : value;
579
+ obj[key] = newValue;
580
+ }
581
+ return obj;
582
+ }
583
+ function setElementAttributes(element, attrs) {
584
+ element = element.cloneNode(true);
585
+ for (const [key, value] of attrs) {
586
+ const oldValue = element.getAttribute(key);
587
+ const newValue = key === "style" ? joinStyles(value, typeof oldValue === "string" ? oldValue : "") : value;
588
+ element.setAttribute(key, newValue);
589
+ }
590
+ return element;
591
+ }
592
+ function joinStyles(...styles) {
593
+ return styles.map((style) => style.trim().replace(/;$/, "")).filter(Boolean).join("; ");
594
+ }
595
+
529
596
  // src/extensions/node-spec.ts
530
597
  function defineNodeSpec(options) {
531
598
  const payload = [options, void 0];
@@ -539,105 +606,50 @@ var nodeSpecFacet = defineFacet({
539
606
  reducer: (payloads) => {
540
607
  let specs = OrderedMap2.from({});
541
608
  let topNodeName = void 0;
542
- const specPayloads = payloads.map((input) => input[0]).filter(isNotNull);
543
- const attrPayloads = payloads.map((input) => input[1]).filter(isNotNull);
609
+ const specPayloads = payloads.map((input) => input[0]).filter(isNotNullish);
610
+ const attrPayloads = payloads.map((input) => input[1]).filter(isNotNullish);
544
611
  for (const { name, topNode, ...spec } of specPayloads) {
545
- assert(!specs.get(name), `Node type ${name} can only be defined once`);
546
612
  if (topNode) {
547
613
  topNodeName = name;
548
614
  }
549
- specs = specs.addToStart(name, spec);
615
+ const prevSpec = specs.get(name);
616
+ if (prevSpec) {
617
+ specs = specs.update(name, mergeSpecs(prevSpec, spec));
618
+ } else {
619
+ specs = specs.addToStart(name, spec);
620
+ }
550
621
  }
551
- for (const {
552
- type,
553
- attr,
554
- default: defaultValue,
555
- splittable,
556
- toDOM,
557
- parseDOM
558
- } of attrPayloads) {
559
- const spec = specs.get(type);
560
- assert(spec, `Node type ${type} must be defined`);
622
+ const groupedAttrs = groupBy(attrPayloads, (payload) => payload.type);
623
+ for (const [type, attrs] of Object.entries(groupedAttrs)) {
624
+ if (!attrs) continue;
625
+ const maybeSpec = specs.get(type);
626
+ assert(maybeSpec, `Node type ${type} must be defined`);
627
+ const spec = clone(maybeSpec);
561
628
  if (!spec.attrs) {
562
629
  spec.attrs = {};
563
630
  }
564
- spec.attrs[attr] = {
565
- default: defaultValue,
566
- splittable
567
- };
568
- if (toDOM && spec.toDOM) {
569
- const existingToDom = spec.toDOM;
570
- spec.toDOM = (node) => {
571
- const dom = existingToDom(node);
572
- if (!dom) {
573
- return dom;
574
- }
575
- const attrDOM = toDOM(node.attrs[attr]);
576
- if (!attrDOM) {
577
- return dom;
578
- }
579
- const [key, value] = attrDOM;
580
- if (!key) {
581
- return dom;
582
- }
583
- if (Array.isArray(dom)) {
584
- if (typeof dom[1] === "object") {
585
- return [
586
- dom[0],
587
- setObjectAttribute(
588
- dom[1],
589
- key,
590
- value
591
- ),
592
- ...dom.slice(2)
593
- ];
594
- } else {
595
- return [dom[0], { [key]: value }, ...dom.slice(1)];
596
- }
597
- } else if (isElement(dom)) {
598
- setElementAttribute(dom, key, value);
599
- } else if (typeof dom === "object" && "dom" in dom && isElement(dom.dom)) {
600
- setElementAttribute(dom.dom, key, value);
601
- }
602
- return dom;
631
+ for (const attr of attrs) {
632
+ spec.attrs[attr.attr] = {
633
+ default: attr.default,
634
+ validate: attr.validate,
635
+ splittable: attr.splittable
603
636
  };
604
637
  }
605
- if (parseDOM && spec.parseDOM) {
606
- for (const rule of spec.parseDOM) {
607
- const existingGetAttrs = rule.getAttrs;
608
- const existingAttrs = rule.attrs;
609
- rule.getAttrs = (dom) => {
610
- var _a;
611
- const attrs = (_a = existingGetAttrs == null ? void 0 : existingGetAttrs(dom)) != null ? _a : existingAttrs;
612
- if (attrs === false || !dom || !isElement(dom)) {
613
- return attrs != null ? attrs : null;
614
- }
615
- const value = parseDOM(dom);
616
- return {
617
- ...attrs,
618
- [attr]: value
619
- };
620
- };
621
- }
638
+ if (spec.toDOM) {
639
+ spec.toDOM = wrapOutputSpecAttrs(spec.toDOM, attrs);
622
640
  }
641
+ if (spec.parseDOM) {
642
+ spec.parseDOM = spec.parseDOM.map(
643
+ (rule) => wrapTagParseRuleAttrs(rule, attrs)
644
+ );
645
+ }
646
+ specs = specs.update(type, spec);
623
647
  }
624
648
  return { nodes: specs, topNode: topNodeName };
625
649
  },
626
650
  parent: schemaSpecFacet,
627
651
  singleton: true
628
652
  });
629
- function setObjectAttribute(obj, key, value) {
630
- if (key === "style") {
631
- value = `${value}${obj.style || ""}`;
632
- }
633
- return { ...obj, [key]: value };
634
- }
635
- function setElementAttribute(element, key, value) {
636
- if (key === "style") {
637
- value = `${value}${element.getAttribute("style") || ""}`;
638
- }
639
- element.setAttribute(key, value);
640
- }
641
653
 
642
654
  // src/extensions/doc.ts
643
655
  function defineDoc() {
@@ -649,10 +661,12 @@ function defineDoc() {
649
661
  }
650
662
 
651
663
  // src/extensions/events/plugin-view.ts
652
- import { PluginKey, ProseMirrorPlugin as ProseMirrorPlugin2 } from "@prosekit/pm/state";
664
+ import {
665
+ PluginKey,
666
+ ProseMirrorPlugin
667
+ } from "@prosekit/pm/state";
653
668
 
654
669
  // src/extensions/plugin.ts
655
- import "@prosekit/pm/model";
656
670
  import { Plugin } from "@prosekit/pm/state";
657
671
  function definePlugin(plugin) {
658
672
  if (plugin instanceof Plugin || Array.isArray(plugin) && plugin.every((p) => p instanceof Plugin)) {
@@ -706,7 +720,7 @@ var pluginViewFacet = defineFacet({
706
720
  let mountHandlers = [];
707
721
  let updateHandlers = [];
708
722
  let unmountHandlers = [];
709
- const plugin = new ProseMirrorPlugin2({
723
+ const plugin = new ProseMirrorPlugin({
710
724
  key: pluginKey,
711
725
  view: (view) => {
712
726
  mountHandlers.forEach((fn) => fn(view));
@@ -758,16 +772,16 @@ function defineDocChangeHandler(handler) {
758
772
  }
759
773
 
760
774
  // src/extensions/events/dom-event.ts
761
- import { PluginKey as PluginKey2, ProseMirrorPlugin as ProseMirrorPlugin3 } from "@prosekit/pm/state";
775
+ import { PluginKey as PluginKey2, ProseMirrorPlugin as ProseMirrorPlugin2 } from "@prosekit/pm/state";
762
776
 
763
777
  // src/utils/combine-event-handlers.ts
764
778
  function combineEventHandlers() {
765
- let _handlers = [];
766
- function setHandlers(handlers) {
767
- _handlers = toReversed(handlers);
779
+ let handlers = [];
780
+ function setHandlers(eventHandlers) {
781
+ handlers = toReversed(eventHandlers);
768
782
  }
769
783
  function combinedEventHandler(...args) {
770
- for (const handler of _handlers) {
784
+ for (const handler of handlers) {
771
785
  if (handler(...args)) {
772
786
  return true;
773
787
  }
@@ -777,20 +791,6 @@ function combineEventHandlers() {
777
791
  return [setHandlers, combinedEventHandler];
778
792
  }
779
793
 
780
- // src/utils/group-entries.ts
781
- function groupEntries(entries) {
782
- const map = {};
783
- for (const [key, value] of entries) {
784
- const values = map[key];
785
- if (!values) {
786
- map[key] = [value];
787
- } else {
788
- values.push(value);
789
- }
790
- }
791
- return map;
792
- }
793
-
794
794
  // src/extensions/events/dom-event.ts
795
795
  function defineDOMEventHandler(event, handler) {
796
796
  return defineFacetPayload(domEventFacet, [
@@ -822,7 +822,7 @@ var domEventFacet = defineFacet({
822
822
  setHandlers(handlers);
823
823
  }
824
824
  if (hasNewEvent) {
825
- plugin = new ProseMirrorPlugin3({
825
+ plugin = new ProseMirrorPlugin2({
826
826
  key: new PluginKey2("prosekit-dom-event-handler"),
827
827
  props: { handleDOMEvents: combinedHandlerMap }
828
828
  });
@@ -838,7 +838,7 @@ var domEventFacet = defineFacet({
838
838
  });
839
839
 
840
840
  // src/extensions/events/editor-event.ts
841
- import { PluginKey as PluginKey3, ProseMirrorPlugin as ProseMirrorPlugin4 } from "@prosekit/pm/state";
841
+ import { PluginKey as PluginKey3, ProseMirrorPlugin as ProseMirrorPlugin3 } from "@prosekit/pm/state";
842
842
  function defineKeyDownHandler(handler) {
843
843
  return defineFacetPayload(editorEventFacet, [["keyDown", handler]]);
844
844
  }
@@ -915,7 +915,7 @@ function setupEditorEventPlugin() {
915
915
  setDropHandlers((_k = map.drop) != null ? _k : []);
916
916
  setScrollToSelectionHandlers((_l = map.scrollToSelection) != null ? _l : []);
917
917
  };
918
- const plugin = new ProseMirrorPlugin4({
918
+ const plugin = new ProseMirrorPlugin3({
919
919
  key: new PluginKey3("prosekit-editor-event"),
920
920
  props: {
921
921
  handleKeyDown,
@@ -1014,11 +1014,11 @@ function defineHistory({
1014
1014
  depth = 200,
1015
1015
  newGroupDelay = 250
1016
1016
  } = {}) {
1017
- return union([
1017
+ return union(
1018
1018
  definePlugin(history({ depth, newGroupDelay })),
1019
1019
  defineKeymap(keymap),
1020
1020
  defineCommands(commands)
1021
- ]);
1021
+ );
1022
1022
  }
1023
1023
 
1024
1024
  // src/extensions/keymap-base.ts
@@ -1059,6 +1059,7 @@ function defineBaseKeymap(options) {
1059
1059
  }
1060
1060
 
1061
1061
  // src/extensions/mark-spec.ts
1062
+ import clone2 from "just-clone";
1062
1063
  import OrderedMap3 from "orderedmap";
1063
1064
  function defineMarkSpec(options) {
1064
1065
  const payload = [options, void 0];
@@ -1071,81 +1072,55 @@ function defineMarkAttr(options) {
1071
1072
  var markSpecFacet = defineFacet({
1072
1073
  reducer: (payloads) => {
1073
1074
  let specs = OrderedMap3.from({});
1074
- const specPayloads = payloads.map((input) => input[0]).filter(isNotNull);
1075
- const attrPayloads = payloads.map((input) => input[1]).filter(isNotNull);
1075
+ const specPayloads = payloads.map((input) => input[0]).filter(isNotNullish);
1076
+ const attrPayloads = payloads.map((input) => input[1]).filter(isNotNullish);
1076
1077
  for (const { name, ...spec } of specPayloads) {
1077
- assert(!specs.get(name), `Mark type ${name} can only be defined once`);
1078
- specs = specs.addToStart(name, spec);
1078
+ const prevSpec = specs.get(name);
1079
+ if (prevSpec) {
1080
+ specs = specs.update(name, mergeSpecs(prevSpec, spec));
1081
+ } else {
1082
+ specs = specs.addToStart(name, spec);
1083
+ }
1079
1084
  }
1080
- for (const {
1081
- type,
1082
- attr,
1083
- default: defaultValue,
1084
- toDOM,
1085
- parseDOM
1086
- } of attrPayloads) {
1087
- const spec = specs.get(type);
1088
- assert(spec, `Mark type ${type} must be defined`);
1085
+ const groupedAttrs = groupBy(attrPayloads, (payload) => payload.type);
1086
+ for (const [type, attrs] of Object.entries(groupedAttrs)) {
1087
+ if (!attrs) continue;
1088
+ const maybeSpec = specs.get(type);
1089
+ assert(maybeSpec, `Mark type ${type} must be defined`);
1090
+ const spec = clone2(maybeSpec);
1089
1091
  if (!spec.attrs) {
1090
1092
  spec.attrs = {};
1091
1093
  }
1092
- spec.attrs[attr] = { default: defaultValue };
1093
- if (toDOM && spec.toDOM) {
1094
- const existingToDom = spec.toDOM;
1095
- spec.toDOM = (mark, inline) => {
1096
- const dom = existingToDom(mark, inline);
1097
- if (!dom) {
1098
- return dom;
1099
- }
1100
- const attrDOM = toDOM(mark.attrs[attr]);
1101
- if (!attrDOM) {
1102
- return dom;
1103
- }
1104
- const [key, value] = attrDOM;
1105
- if (!key) {
1106
- return dom;
1107
- }
1108
- if (Array.isArray(dom)) {
1109
- if (typeof dom[1] === "object") {
1110
- return [dom[0], { ...dom[1], [key]: value }, ...dom.slice(2)];
1111
- } else {
1112
- return [dom[0], { [key]: value }, ...dom.slice(1)];
1113
- }
1114
- } else if (isElement(dom)) {
1115
- dom.setAttribute(key, value);
1116
- } else if (typeof dom === "object" && "dom" in dom && isElement(dom.dom)) {
1117
- dom.dom.setAttribute(key, value);
1118
- }
1119
- return dom;
1094
+ for (const attr of attrs) {
1095
+ spec.attrs[attr.attr] = {
1096
+ default: attr.default,
1097
+ validate: attr.validate
1120
1098
  };
1121
1099
  }
1122
- if (parseDOM && spec.parseDOM) {
1123
- for (const rule of spec.parseDOM) {
1124
- const existingGetAttrs = rule.getAttrs;
1125
- const existingAttrs = rule.attrs;
1126
- rule.getAttrs = (dom) => {
1127
- var _a;
1128
- const attrs = (_a = existingGetAttrs == null ? void 0 : existingGetAttrs(dom)) != null ? _a : existingAttrs;
1129
- if (attrs === false || !dom || !isElement(dom)) {
1130
- return attrs != null ? attrs : null;
1131
- }
1132
- const value = parseDOM(dom);
1133
- return {
1134
- ...attrs,
1135
- [attr]: value
1136
- };
1137
- };
1138
- }
1100
+ if (spec.toDOM) {
1101
+ spec.toDOM = wrapOutputSpecAttrs(spec.toDOM, attrs);
1102
+ }
1103
+ if (spec.parseDOM) {
1104
+ spec.parseDOM = spec.parseDOM.map(
1105
+ (rule) => wrapParseRuleAttrs(rule, attrs)
1106
+ );
1139
1107
  }
1108
+ specs = specs.update(type, spec);
1140
1109
  }
1141
1110
  return { marks: specs, nodes: {} };
1142
1111
  },
1143
1112
  parent: schemaSpecFacet,
1144
1113
  singleton: true
1145
1114
  });
1115
+ function wrapParseRuleAttrs(rule, attrs) {
1116
+ if (rule.tag) {
1117
+ return wrapTagParseRuleAttrs(rule, attrs);
1118
+ }
1119
+ return rule;
1120
+ }
1146
1121
 
1147
1122
  // src/extensions/node-view.ts
1148
- import { PluginKey as PluginKey5, ProseMirrorPlugin as ProseMirrorPlugin5 } from "@prosekit/pm/state";
1123
+ import { PluginKey as PluginKey5, ProseMirrorPlugin as ProseMirrorPlugin4 } from "@prosekit/pm/state";
1149
1124
  function defineNodeView(options) {
1150
1125
  return defineFacetPayload(nodeViewFacet, [options]);
1151
1126
  }
@@ -1158,7 +1133,7 @@ var nodeViewFacet = defineFacet({
1158
1133
  }
1159
1134
  }
1160
1135
  return () => [
1161
- new ProseMirrorPlugin5({
1136
+ new ProseMirrorPlugin4({
1162
1137
  key: new PluginKey5("prosekit-node-view"),
1163
1138
  props: { nodeViews }
1164
1139
  })
@@ -1168,7 +1143,7 @@ var nodeViewFacet = defineFacet({
1168
1143
  });
1169
1144
 
1170
1145
  // src/extensions/node-view-effect.ts
1171
- import { PluginKey as PluginKey6, ProseMirrorPlugin as ProseMirrorPlugin6 } from "@prosekit/pm/state";
1146
+ import { PluginKey as PluginKey6, ProseMirrorPlugin as ProseMirrorPlugin5 } from "@prosekit/pm/state";
1172
1147
  function defineNodeViewFactory(options) {
1173
1148
  const input = [options, null];
1174
1149
  return defineFacetPayload(nodeViewFactoryFacet, [input]);
@@ -1182,15 +1157,15 @@ var nodeViewFactoryFacet = defineFacet({
1182
1157
  reducer: (inputs) => {
1183
1158
  if (isServer) return [];
1184
1159
  const nodeViews = {};
1185
- const factories = inputs.map((x) => x[0]).filter(isNotNull);
1186
- const options = inputs.map((x) => x[1]).filter(isNotNull);
1160
+ const factories = inputs.map((x) => x[0]).filter(isNotNullish);
1161
+ const options = inputs.map((x) => x[1]).filter(isNotNullish);
1187
1162
  for (const { group, name, args } of options) {
1188
1163
  const factory = factories.find((factory2) => factory2.group === group);
1189
1164
  if (!factory) continue;
1190
1165
  nodeViews[name] = factory.factory(args);
1191
1166
  }
1192
1167
  return () => [
1193
- new ProseMirrorPlugin6({
1168
+ new ProseMirrorPlugin5({
1194
1169
  key: new PluginKey6("prosekit-node-view-effect"),
1195
1170
  props: { nodeViews }
1196
1171
  })
@@ -1238,7 +1213,7 @@ function cache(fn) {
1238
1213
  var canUseRegexLookbehind = cache(() => {
1239
1214
  try {
1240
1215
  return "ab".replace(new RegExp("(?<=a)b", "g"), "c") === "ac";
1241
- } catch (error) {
1216
+ } catch (e) {
1242
1217
  return false;
1243
1218
  }
1244
1219
  });
@@ -1247,13 +1222,22 @@ var canUseRegexLookbehind = cache(() => {
1247
1222
  import clsxLite from "clsx/lite";
1248
1223
  var clsx = clsxLite;
1249
1224
 
1225
+ // src/utils/collect-children.ts
1226
+ function collectChildren(parent) {
1227
+ const children = [];
1228
+ for (let i = 0; i < parent.childCount; i++) {
1229
+ children.push(parent.child(i));
1230
+ }
1231
+ return children;
1232
+ }
1233
+
1250
1234
  // src/utils/collect-nodes.ts
1251
- import { ProseMirrorFragment, ProseMirrorNode as ProseMirrorNode2 } from "@prosekit/pm/model";
1235
+ import { ProseMirrorFragment, ProseMirrorNode } from "@prosekit/pm/model";
1252
1236
  function collectNodes(content) {
1253
1237
  if (Array.isArray(content)) {
1254
1238
  return content.flatMap(collectNodes);
1255
1239
  }
1256
- if (content instanceof ProseMirrorNode2) {
1240
+ if (content instanceof ProseMirrorNode) {
1257
1241
  return [content];
1258
1242
  }
1259
1243
  if (content instanceof ProseMirrorFragment) {
@@ -1336,6 +1320,7 @@ export {
1336
1320
  assert,
1337
1321
  canUseRegexLookbehind,
1338
1322
  clsx,
1323
+ collectChildren,
1339
1324
  collectNodes,
1340
1325
  containsInlineNode,
1341
1326
  createEditor,
@@ -1380,6 +1365,8 @@ export {
1380
1365
  elementFromJSON,
1381
1366
  elementFromNode,
1382
1367
  expandMark,
1368
+ findParentNode,
1369
+ findParentNodeOfType,
1383
1370
  getMarkType,
1384
1371
  getNodeType,
1385
1372
  htmlFromJSON,
@@ -1388,6 +1375,7 @@ export {
1388
1375
  isAllSelection,
1389
1376
  isApple,
1390
1377
  isAtBlockStart,
1378
+ isFragment,
1391
1379
  isInCodeBlock,
1392
1380
  isMark,
1393
1381
  isMarkAbsent,
@@ -1395,6 +1383,7 @@ export {
1395
1383
  isNodeSelection,
1396
1384
  isProseMirrorNode,
1397
1385
  isSelection,
1386
+ isSlice,
1398
1387
  isTextSelection,
1399
1388
  jsonFromHTML,
1400
1389
  jsonFromNode,