@domternal/core 0.7.3 → 0.7.5

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.
package/dist/index.cjs CHANGED
@@ -299,7 +299,8 @@ var ExtensionManager = class {
299
299
  }
300
300
  const flattened = this.flattenExtensions(options.extensions);
301
301
  const deduped = this.deduplicateExtensions(flattened);
302
- this._extensions = this.resolveExtensions(deduped);
302
+ const cloned = this.cloneExtensions(deduped);
303
+ this._extensions = this.resolveExtensions(cloned);
303
304
  this.detectConflicts();
304
305
  this.checkDependencies();
305
306
  this.bindEditorToExtensions();
@@ -407,6 +408,17 @@ var ExtensionManager = class {
407
408
  }
408
409
  return extensions.filter((ext, i) => seen.get(ext.name) === i);
409
410
  }
411
+ /**
412
+ * Clone every extension so this editor owns its instances. Extensions hold
413
+ * per-editor mutable state (`editor`, plus the `nodeType`/`markType` getters
414
+ * derived from it), and the same extension object is commonly reused across
415
+ * editors (one shared `extensions` array). Without cloning, binding a later
416
+ * editor clobbers an earlier one: its list `Enter` then falls back to a plain
417
+ * block split, dropping an indented "child" paragraph instead of a new `<li>`.
418
+ */
419
+ cloneExtensions(extensions) {
420
+ return extensions.map((ext) => ext.clone());
421
+ }
410
422
  /**
411
423
  * Sorts extensions by priority (higher priority first)
412
424
  * Default priority is 100
@@ -1126,7 +1138,7 @@ var markInputRulePatterns = {
1126
1138
  highlight: /(?:==)([^=]+)(?:==)$/
1127
1139
  };
1128
1140
  function wrappingInputRule(options) {
1129
- const { find: find2, type, getAttributes = null, joinPredicate, undoable, guard } = options;
1141
+ const { find: find2, type, getAttributes = null, joinPredicate, undoable, guard, joinForward } = options;
1130
1142
  return new inputrules.InputRule(
1131
1143
  find2,
1132
1144
  (state, match, start, end) => {
@@ -1142,6 +1154,21 @@ function wrappingInputRule(options) {
1142
1154
  if (before?.type === type && transform.canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) {
1143
1155
  tr.join(start - 1);
1144
1156
  }
1157
+ if (joinForward) {
1158
+ const $cursor = tr.selection.$from;
1159
+ for (let d = $cursor.depth; d >= 0; d--) {
1160
+ if ($cursor.node(d).type === type) {
1161
+ const after = $cursor.after(d);
1162
+ if (after < tr.doc.content.size && transform.canJoin(tr.doc, after)) {
1163
+ const nodeAfter = tr.doc.nodeAt(after);
1164
+ if (nodeAfter?.type === type && (!joinPredicate || joinPredicate(match, nodeAfter))) {
1165
+ tr.join(after);
1166
+ }
1167
+ }
1168
+ break;
1169
+ }
1170
+ }
1171
+ }
1145
1172
  return tr;
1146
1173
  },
1147
1174
  undoable !== void 0 ? { undoable } : {}
@@ -1524,6 +1551,19 @@ var Extension = class _Extension {
1524
1551
  };
1525
1552
  return new _Extension(newConfig);
1526
1553
  }
1554
+ /**
1555
+ * Returns a fresh, unbound copy built from the same `config`: `editor` reset to
1556
+ * null and `options`/`storage` re-derived, while `configure()`/`extend()`
1557
+ * results are preserved (they live in `config`). Polymorphic: a `Node`/`Mark`
1558
+ * clones to its own subclass.
1559
+ *
1560
+ * `ExtensionManager` clones every extension so each editor owns its instances
1561
+ * and binding one editor can't mutate extensions shared with another.
1562
+ */
1563
+ clone() {
1564
+ const Ctor = this.constructor;
1565
+ return new Ctor(this.config);
1566
+ }
1527
1567
  /**
1528
1568
  * Creates a new extension with extended configuration
1529
1569
  * Original extension is not modified
@@ -1962,6 +2002,7 @@ function isInListItemLabel($pos) {
1962
2002
  }
1963
2003
 
1964
2004
  // src/utils/liftCurrentListItem.ts
2005
+ var LIST_ITEM_TYPES = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
1965
2006
  function liftCurrentListItem(state, tr) {
1966
2007
  if (!tr.selection.empty) return false;
1967
2008
  if (tr.steps.length !== 0) return false;
@@ -1969,6 +2010,16 @@ function liftCurrentListItem(state, tr) {
1969
2010
  const listItemDepth = findListItemAncestorDepth($from);
1970
2011
  if (listItemDepth === -1) return false;
1971
2012
  if ($from.index(listItemDepth) !== 0) return false;
2013
+ const wrapperParent = $from.node(listItemDepth - 2);
2014
+ const isNested = LIST_ITEM_TYPES.has(wrapperParent.type.name);
2015
+ if (isNested) {
2016
+ const range = $from.blockRange();
2017
+ if (!range) return false;
2018
+ const target = transform.liftTarget(range);
2019
+ if (target === null) return false;
2020
+ tr.lift(range, target);
2021
+ return true;
2022
+ }
1972
2023
  const listItemType = $from.node(listItemDepth).type;
1973
2024
  return schemaList.liftListItem(listItemType)(state, (liftTr) => {
1974
2025
  for (const step of liftTr.steps) tr.step(step);
@@ -2176,13 +2227,13 @@ var lift = () => ({ tr, dispatch }) => {
2176
2227
  };
2177
2228
 
2178
2229
  // src/utils/listItemCursorContext.ts
2179
- var LIST_ITEM_TYPES = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
2230
+ var LIST_ITEM_TYPES2 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
2180
2231
  function getListItemCursorContext($from) {
2181
2232
  if ($from.parent.type.name !== "paragraph") return null;
2182
2233
  const itemDepth = $from.depth - 1;
2183
2234
  if (itemDepth < 1) return null;
2184
2235
  const itemNode = $from.node(itemDepth);
2185
- if (!LIST_ITEM_TYPES.has(itemNode.type.name)) return null;
2236
+ if (!LIST_ITEM_TYPES2.has(itemNode.type.name)) return null;
2186
2237
  const wrapperDepth = itemDepth - 1;
2187
2238
  const childIndex = $from.index(itemDepth);
2188
2239
  return {
@@ -4078,7 +4129,7 @@ function defaultBubbleContexts(editor) {
4078
4129
  }
4079
4130
 
4080
4131
  // src/utils/insertAsListItemChild.ts
4081
- var LIST_ITEM_TYPES2 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
4132
+ var LIST_ITEM_TYPES3 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
4082
4133
  var LIST_WRAPPER_TYPES = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
4083
4134
  function insertAsListItemChild(args) {
4084
4135
  const { tr, wrapperPos, targetItemPos, blockNode, sourceRange } = args;
@@ -4091,7 +4142,7 @@ function insertAsListItemChild(args) {
4091
4142
  if (targetItemPos !== void 0) {
4092
4143
  if (targetItemPos < 0 || targetItemPos >= tr.doc.content.size) return { ok: false };
4093
4144
  const candidate = tr.doc.nodeAt(targetItemPos);
4094
- if (!candidate || !LIST_ITEM_TYPES2.has(candidate.type.name)) return { ok: false };
4145
+ if (!candidate || !LIST_ITEM_TYPES3.has(candidate.type.name)) return { ok: false };
4095
4146
  if (targetItemPos < wrapperPos + 1 || targetItemPos >= wrapperPos + wrapper.nodeSize) {
4096
4147
  return { ok: false };
4097
4148
  }
@@ -4099,7 +4150,7 @@ function insertAsListItemChild(args) {
4099
4150
  targetItemStart = targetItemPos;
4100
4151
  } else {
4101
4152
  const last = wrapper.lastChild;
4102
- if (!last || !LIST_ITEM_TYPES2.has(last.type.name)) return { ok: false };
4153
+ if (!last || !LIST_ITEM_TYPES3.has(last.type.name)) return { ok: false };
4103
4154
  let pos = wrapperPos + 1;
4104
4155
  for (let i = 0; i < wrapper.childCount - 1; i++) {
4105
4156
  pos += wrapper.child(i).nodeSize;
@@ -5893,11 +5944,11 @@ var BulletList = Node2.create({
5893
5944
  }
5894
5945
  return [
5895
5946
  // - item
5896
- wrappingInputRule({ find: /^\s*[-]\s$/, type: nodeType, guard: notInsideList }),
5947
+ wrappingInputRule({ find: /^\s*[-]\s$/, type: nodeType, guard: notInsideList, joinForward: true }),
5897
5948
  // * item
5898
- wrappingInputRule({ find: /^\s*[*]\s$/, type: nodeType, guard: notInsideList }),
5949
+ wrappingInputRule({ find: /^\s*[*]\s$/, type: nodeType, guard: notInsideList, joinForward: true }),
5899
5950
  // + item
5900
- wrappingInputRule({ find: /^\s*[+]\s$/, type: nodeType, guard: notInsideList })
5951
+ wrappingInputRule({ find: /^\s*[+]\s$/, type: nodeType, guard: notInsideList, joinForward: true })
5901
5952
  ];
5902
5953
  }
5903
5954
  });
@@ -5998,6 +6049,7 @@ var OrderedList = Node2.create({
5998
6049
  find: /^(\d+)\.\s$/,
5999
6050
  type: nodeType,
6000
6051
  guard: notInsideList,
6052
+ joinForward: true,
6001
6053
  getAttributes: (match) => {
6002
6054
  const num = match[1];
6003
6055
  return { start: num ? parseInt(num, 10) : 1 };
@@ -6527,9 +6579,9 @@ var TaskList = Node2.create({
6527
6579
  }
6528
6580
  return [
6529
6581
  // [ ] at start of line creates unchecked task
6530
- wrappingInputRule({ find: /^\s*\[\s?\]\s$/, type: nodeType, guard: notInsideList }),
6582
+ wrappingInputRule({ find: /^\s*\[\s?\]\s$/, type: nodeType, guard: notInsideList, joinForward: true }),
6531
6583
  // [x] or [X] at start of line creates checked task
6532
- wrappingInputRule({ find: /^\s*\[[xX]\]\s$/, type: nodeType, guard: notInsideList })
6584
+ wrappingInputRule({ find: /^\s*\[[xX]\]\s$/, type: nodeType, guard: notInsideList, joinForward: true })
6533
6585
  ];
6534
6586
  }
6535
6587
  });
@@ -7712,12 +7764,12 @@ var Placeholder = Extension.create({
7712
7764
  ];
7713
7765
  }
7714
7766
  });
7715
- var LIST_ITEM_TYPES3 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
7767
+ var LIST_ITEM_TYPES4 = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
7716
7768
  var LIST_WRAPPER_TYPES2 = /* @__PURE__ */ new Set(["bulletList", "orderedList", "taskList"]);
7717
7769
  function isCursorInsideListItem(state) {
7718
7770
  const { $from } = state.selection;
7719
7771
  for (let d = $from.depth; d > 0; d--) {
7720
- if (LIST_ITEM_TYPES3.has($from.node(d).type.name)) return true;
7772
+ if (LIST_ITEM_TYPES4.has($from.node(d).type.name)) return true;
7721
7773
  }
7722
7774
  return false;
7723
7775
  }
@@ -7772,7 +7824,7 @@ function outdentBlockFromListItem(state$1, dispatch) {
7772
7824
  const { $from } = selection;
7773
7825
  let listItemDepth = -1;
7774
7826
  for (let d = $from.depth; d > 0; d--) {
7775
- if (LIST_ITEM_TYPES3.has($from.node(d).type.name)) {
7827
+ if (LIST_ITEM_TYPES4.has($from.node(d).type.name)) {
7776
7828
  listItemDepth = d;
7777
7829
  break;
7778
7830
  }
@@ -8676,8 +8728,13 @@ var SelectionDecoration = Extension.create(
8676
8728
  handleDOMEvents: {
8677
8729
  blur(view, event) {
8678
8730
  const related = event.relatedTarget;
8679
- if (related instanceof HTMLElement && (related.closest("[data-dm-editor-ui]") || related.closest(".dm-toolbar") || related.closest(".dm-bubble-menu"))) {
8680
- return false;
8731
+ if (related instanceof HTMLElement) {
8732
+ const ownContainer = view.dom.closest(".dm-editor");
8733
+ const relatedContainer = related.closest(".dm-editor");
8734
+ const movedToAnotherEditor = ownContainer !== null && relatedContainer !== null && relatedContainer !== ownContainer;
8735
+ if (!movedToAnotherEditor && (related.closest("[data-dm-editor-ui]") || related.closest(".dm-toolbar") || related.closest(".dm-bubble-menu"))) {
8736
+ return false;
8737
+ }
8681
8738
  }
8682
8739
  const { from, to } = view.state.selection;
8683
8740
  if (from !== to) {
@@ -10030,7 +10087,7 @@ var StarterKit = Extension.create({
10030
10087
  maybeAdd(Gapcursor, this.options.gapcursor);
10031
10088
  maybeAdd(TrailingNode, this.options.trailingNode);
10032
10089
  maybeAdd(ListKeymap, this.options.listKeymap);
10033
- maybeAdd(ListIndent, this.options.listIndent);
10090
+ if (this.options.listIndent === true) extensions.push(ListIndent);
10034
10091
  maybeAdd(LinkPopover, this.options.linkPopover);
10035
10092
  maybeAdd(SelectionDecoration, this.options.selectionDecoration);
10036
10093
  return extensions;