@tiptap/core 3.0.0-next.4 → 3.0.0-next.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.
Files changed (39) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/index.cjs +352 -238
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1084 -1431
  5. package/dist/index.d.ts +1084 -1431
  6. package/dist/index.js +344 -235
  7. package/dist/index.js.map +1 -1
  8. package/dist/jsx-runtime/jsx-runtime.cjs +56 -0
  9. package/dist/jsx-runtime/jsx-runtime.cjs.map +1 -0
  10. package/dist/jsx-runtime/jsx-runtime.d.cts +22 -0
  11. package/dist/jsx-runtime/jsx-runtime.d.ts +22 -0
  12. package/dist/jsx-runtime/jsx-runtime.js +26 -0
  13. package/dist/jsx-runtime/jsx-runtime.js.map +1 -0
  14. package/jsx-runtime/index.cjs +1 -0
  15. package/jsx-runtime/index.d.cts +1 -0
  16. package/jsx-runtime/index.d.ts +1 -0
  17. package/jsx-runtime/index.js +1 -0
  18. package/package.json +20 -3
  19. package/src/Editor.ts +104 -22
  20. package/src/Extendable.ts +483 -0
  21. package/src/Extension.ts +5 -490
  22. package/src/ExtensionManager.ts +55 -10
  23. package/src/Mark.ts +135 -623
  24. package/src/MarkView.ts +66 -0
  25. package/src/Node.ts +325 -829
  26. package/src/commands/clearContent.ts +9 -4
  27. package/src/commands/focus.ts +7 -1
  28. package/src/commands/insertContentAt.ts +6 -2
  29. package/src/commands/setContent.ts +15 -14
  30. package/src/extensions/delete.ts +89 -0
  31. package/src/extensions/index.ts +1 -0
  32. package/src/extensions/keymap.ts +4 -0
  33. package/src/helpers/getExtensionField.ts +10 -7
  34. package/src/index.ts +3 -7
  35. package/src/jsx-runtime.ts +64 -0
  36. package/src/types.ts +334 -19
  37. package/src/utilities/elementFromString.ts +3 -0
  38. package/src/utilities/index.ts +1 -0
  39. package/src/utilities/mergeAttributes.ts +1 -1
package/dist/index.js CHANGED
@@ -220,6 +220,9 @@ var removeWhitespaces = (node) => {
220
220
  return node;
221
221
  };
222
222
  function elementFromString(value) {
223
+ if (typeof window === "undefined") {
224
+ throw new Error("[tiptap error]: there is no window object available, so this function cannot be used");
225
+ }
223
226
  const wrappedValue = `<body>${value}</body>`;
224
227
  const html = new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
225
228
  return removeWhitespaces(html);
@@ -542,7 +545,7 @@ function mergeAttributes(...objects) {
542
545
  return;
543
546
  }
544
547
  if (key === "class") {
545
- const valueClasses = value ? value.split(" ") : [];
548
+ const valueClasses = value ? String(value).split(" ") : [];
546
549
  const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(" ") : [];
547
550
  const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
548
551
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
@@ -1767,44 +1770,40 @@ function mergeDeep(target, source) {
1767
1770
  return output;
1768
1771
  }
1769
1772
 
1770
- // src/Mark.ts
1771
- var Mark = class _Mark {
1773
+ // src/Extendable.ts
1774
+ var Extendable = class {
1772
1775
  constructor(config = {}) {
1773
- this.type = "mark";
1774
- this.name = "mark";
1776
+ this.type = "extendable";
1775
1777
  this.parent = null;
1776
1778
  this.child = null;
1779
+ this.name = "";
1777
1780
  this.config = {
1778
- name: this.name,
1779
- defaultOptions: {}
1781
+ name: this.name
1780
1782
  };
1781
1783
  this.config = {
1782
1784
  ...this.config,
1783
1785
  ...config
1784
1786
  };
1785
1787
  this.name = this.config.name;
1786
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
1787
- console.warn(
1788
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
1789
- );
1790
- }
1791
- this.options = this.config.defaultOptions;
1792
- if (this.config.addOptions) {
1793
- this.options = callOrReturn(
1788
+ }
1789
+ get options() {
1790
+ return {
1791
+ ...callOrReturn(
1794
1792
  getExtensionField(this, "addOptions", {
1795
1793
  name: this.name
1796
1794
  })
1797
- );
1798
- }
1799
- this.storage = callOrReturn(
1800
- getExtensionField(this, "addStorage", {
1801
- name: this.name,
1802
- options: this.options
1803
- })
1804
- ) || {};
1795
+ ) || {}
1796
+ };
1805
1797
  }
1806
- static create(config = {}) {
1807
- return new _Mark(config);
1798
+ get storage() {
1799
+ return {
1800
+ ...callOrReturn(
1801
+ getExtensionField(this, "addStorage", {
1802
+ name: this.name,
1803
+ options: this.options
1804
+ })
1805
+ ) || {}
1806
+ };
1808
1807
  }
1809
1808
  configure(options = {}) {
1810
1809
  const extension = this.extend({
@@ -1818,28 +1817,23 @@ var Mark = class _Mark {
1818
1817
  return extension;
1819
1818
  }
1820
1819
  extend(extendedConfig = {}) {
1821
- const extension = new _Mark(extendedConfig);
1820
+ const extension = new this.constructor({ ...this.config, ...extendedConfig });
1822
1821
  extension.parent = this;
1823
1822
  this.child = extension;
1824
1823
  extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
1825
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
1826
- console.warn(
1827
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
1828
- );
1829
- }
1830
- extension.options = callOrReturn(
1831
- getExtensionField(extension, "addOptions", {
1832
- name: extension.name
1833
- })
1834
- );
1835
- extension.storage = callOrReturn(
1836
- getExtensionField(extension, "addStorage", {
1837
- name: extension.name,
1838
- options: extension.options
1839
- })
1840
- );
1841
1824
  return extension;
1842
1825
  }
1826
+ };
1827
+
1828
+ // src/Mark.ts
1829
+ var Mark = class _Mark extends Extendable {
1830
+ constructor() {
1831
+ super(...arguments);
1832
+ this.type = "mark";
1833
+ }
1834
+ static create(config = {}) {
1835
+ return new _Mark(config);
1836
+ }
1843
1837
  static handleExit({ editor, mark }) {
1844
1838
  const { tr } = editor.state;
1845
1839
  const currentPos = editor.state.selection.$from;
@@ -2109,7 +2103,7 @@ var ExtensionManager = class {
2109
2103
  const context = {
2110
2104
  name: extension.name,
2111
2105
  options: extension.options,
2112
- storage: extension.storage,
2106
+ storage: this.editor.extensionStorage[extension.name],
2113
2107
  editor: this.editor,
2114
2108
  type: getSchemaTypeByName(extension.name, this.schema)
2115
2109
  };
@@ -2136,7 +2130,7 @@ var ExtensionManager = class {
2136
2130
  const context = {
2137
2131
  name: extension.name,
2138
2132
  options: extension.options,
2139
- storage: extension.storage,
2133
+ storage: this.editor.extensionStorage[extension.name],
2140
2134
  editor,
2141
2135
  type: getSchemaTypeByName(extension.name, this.schema)
2142
2136
  };
@@ -2211,7 +2205,7 @@ var ExtensionManager = class {
2211
2205
  const context = {
2212
2206
  name: extension.name,
2213
2207
  options: extension.options,
2214
- storage: extension.storage,
2208
+ storage: this.editor.extensionStorage[extension.name],
2215
2209
  editor,
2216
2210
  type: getNodeType(extension.name, this.schema)
2217
2211
  };
@@ -2238,18 +2232,55 @@ var ExtensionManager = class {
2238
2232
  })
2239
2233
  );
2240
2234
  }
2235
+ get markViews() {
2236
+ const { editor } = this;
2237
+ const { markExtensions } = splitExtensions(this.extensions);
2238
+ return Object.fromEntries(
2239
+ markExtensions.filter((extension) => !!getExtensionField(extension, "addMarkView")).map((extension) => {
2240
+ const extensionAttributes = this.attributes.filter((attribute) => attribute.type === extension.name);
2241
+ const context = {
2242
+ name: extension.name,
2243
+ options: extension.options,
2244
+ storage: this.editor.extensionStorage[extension.name],
2245
+ editor,
2246
+ type: getMarkType(extension.name, this.schema)
2247
+ };
2248
+ const addMarkView = getExtensionField(extension, "addMarkView", context);
2249
+ if (!addMarkView) {
2250
+ return [];
2251
+ }
2252
+ const markView = (mark, view, inline) => {
2253
+ const HTMLAttributes = getRenderedAttributes(mark, extensionAttributes);
2254
+ return addMarkView()({
2255
+ // pass-through
2256
+ mark,
2257
+ view,
2258
+ inline,
2259
+ // tiptap-specific
2260
+ editor,
2261
+ extension,
2262
+ HTMLAttributes
2263
+ });
2264
+ };
2265
+ return [extension.name, markView];
2266
+ })
2267
+ );
2268
+ }
2241
2269
  /**
2242
2270
  * Go through all extensions, create extension storages & setup marks
2243
2271
  * & bind editor event listener.
2244
2272
  */
2245
2273
  setupExtensions() {
2246
- this.extensions.forEach((extension) => {
2274
+ const extensions = this.extensions;
2275
+ this.editor.extensionStorage = Object.fromEntries(
2276
+ extensions.map((extension) => [extension.name, extension.storage])
2277
+ );
2278
+ extensions.forEach((extension) => {
2247
2279
  var _a;
2248
- this.editor.extensionStorage[extension.name] = extension.storage;
2249
2280
  const context = {
2250
2281
  name: extension.name,
2251
2282
  options: extension.options,
2252
- storage: extension.storage,
2283
+ storage: this.editor.extensionStorage[extension.name],
2253
2284
  editor: this.editor,
2254
2285
  type: getSchemaTypeByName(extension.name, this.schema)
2255
2286
  };
@@ -2307,6 +2338,7 @@ var extensions_exports = {};
2307
2338
  __export(extensions_exports, {
2308
2339
  ClipboardTextSerializer: () => ClipboardTextSerializer,
2309
2340
  Commands: () => Commands,
2341
+ Delete: () => Delete,
2310
2342
  Drop: () => Drop,
2311
2343
  Editable: () => Editable,
2312
2344
  FocusEvents: () => FocusEvents,
@@ -2319,78 +2351,14 @@ __export(extensions_exports, {
2319
2351
  import { Plugin as Plugin3, PluginKey } from "@tiptap/pm/state";
2320
2352
 
2321
2353
  // src/Extension.ts
2322
- var Extension = class _Extension {
2323
- constructor(config = {}) {
2354
+ var Extension = class _Extension extends Extendable {
2355
+ constructor() {
2356
+ super(...arguments);
2324
2357
  this.type = "extension";
2325
- this.name = "extension";
2326
- this.parent = null;
2327
- this.child = null;
2328
- this.config = {
2329
- name: this.name,
2330
- defaultOptions: {}
2331
- };
2332
- this.config = {
2333
- ...this.config,
2334
- ...config
2335
- };
2336
- this.name = this.config.name;
2337
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
2338
- console.warn(
2339
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
2340
- );
2341
- }
2342
- this.options = this.config.defaultOptions;
2343
- if (this.config.addOptions) {
2344
- this.options = callOrReturn(
2345
- getExtensionField(this, "addOptions", {
2346
- name: this.name
2347
- })
2348
- );
2349
- }
2350
- this.storage = callOrReturn(
2351
- getExtensionField(this, "addStorage", {
2352
- name: this.name,
2353
- options: this.options
2354
- })
2355
- ) || {};
2356
2358
  }
2357
2359
  static create(config = {}) {
2358
2360
  return new _Extension(config);
2359
2361
  }
2360
- configure(options = {}) {
2361
- const extension = this.extend({
2362
- ...this.config,
2363
- addOptions: () => {
2364
- return mergeDeep(this.options, options);
2365
- }
2366
- });
2367
- extension.name = this.name;
2368
- extension.parent = this.parent;
2369
- return extension;
2370
- }
2371
- extend(extendedConfig = {}) {
2372
- const extension = new _Extension({ ...this.config, ...extendedConfig });
2373
- extension.parent = this;
2374
- this.child = extension;
2375
- extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
2376
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
2377
- console.warn(
2378
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
2379
- );
2380
- }
2381
- extension.options = callOrReturn(
2382
- getExtensionField(extension, "addOptions", {
2383
- name: extension.name
2384
- })
2385
- );
2386
- extension.storage = callOrReturn(
2387
- getExtensionField(extension, "addStorage", {
2388
- name: extension.name,
2389
- options: extension.options
2390
- })
2391
- );
2392
- return extension;
2393
- }
2394
2362
  };
2395
2363
 
2396
2364
  // src/extensions/clipboardTextSerializer.ts
@@ -2503,8 +2471,8 @@ var blur = () => ({ editor, view }) => {
2503
2471
  };
2504
2472
 
2505
2473
  // src/commands/clearContent.ts
2506
- var clearContent = (emitUpdate = false) => ({ commands }) => {
2507
- return commands.setContent("", emitUpdate);
2474
+ var clearContent = (emitUpdate = true) => ({ commands }) => {
2475
+ return commands.setContent("", { emitUpdate });
2508
2476
  };
2509
2477
 
2510
2478
  // src/commands/clearNodes.ts
@@ -2656,6 +2624,17 @@ var first = (commands) => (props) => {
2656
2624
  return false;
2657
2625
  };
2658
2626
 
2627
+ // src/utilities/isAndroid.ts
2628
+ function isAndroid() {
2629
+ return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
2630
+ }
2631
+
2632
+ // src/utilities/isiOS.ts
2633
+ function isiOS() {
2634
+ return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
2635
+ navigator.userAgent.includes("Mac") && "ontouchend" in document;
2636
+ }
2637
+
2659
2638
  // src/commands/focus.ts
2660
2639
  var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch }) => {
2661
2640
  options = {
@@ -2663,8 +2642,10 @@ var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch })
2663
2642
  ...options
2664
2643
  };
2665
2644
  const delayedFocus = () => {
2666
- ;
2667
- view.dom.focus();
2645
+ if (isiOS() || isAndroid()) {
2646
+ ;
2647
+ view.dom.focus();
2648
+ }
2668
2649
  requestAnimationFrame(() => {
2669
2650
  if (!editor.isDestroyed) {
2670
2651
  view.focus();
@@ -2735,7 +2716,8 @@ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) =
2735
2716
  editor,
2736
2717
  error: e,
2737
2718
  disableCollaboration: () => {
2738
- if (editor.storage.collaboration) {
2719
+ if ("collaboration" in editor.storage && typeof editor.storage.collaboration === "object" && editor.storage.collaboration) {
2720
+ ;
2739
2721
  editor.storage.collaboration.isDisabled = true;
2740
2722
  }
2741
2723
  }
@@ -2867,12 +2849,6 @@ var joinTextblockForward = () => ({ state, dispatch }) => {
2867
2849
  return originalCommand2(state, dispatch);
2868
2850
  };
2869
2851
 
2870
- // src/utilities/isiOS.ts
2871
- function isiOS() {
2872
- return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
2873
- navigator.userAgent.includes("Mac") && "ontouchend" in document;
2874
- }
2875
-
2876
2852
  // src/utilities/isMacOS.ts
2877
2853
  function isMacOS() {
2878
2854
  return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
@@ -3073,12 +3049,11 @@ var selectTextblockStart = () => ({ state, dispatch }) => {
3073
3049
  };
3074
3050
 
3075
3051
  // src/commands/setContent.ts
3076
- var setContent = (content, emitUpdate = false, parseOptions = {}, options = {}) => ({ editor, tr, dispatch, commands }) => {
3077
- var _a, _b;
3052
+ var setContent = (content, { errorOnInvalidContent, emitUpdate = true, parseOptions = {} } = {}) => ({ editor, tr, dispatch, commands }) => {
3078
3053
  const { doc } = tr;
3079
3054
  if (parseOptions.preserveWhitespace !== "full") {
3080
3055
  const document2 = createDocument(content, editor.schema, parseOptions, {
3081
- errorOnInvalidContent: (_a = options.errorOnInvalidContent) != null ? _a : editor.options.enableContentCheck
3056
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
3082
3057
  });
3083
3058
  if (dispatch) {
3084
3059
  tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
@@ -3090,7 +3065,7 @@ var setContent = (content, emitUpdate = false, parseOptions = {}, options = {})
3090
3065
  }
3091
3066
  return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
3092
3067
  parseOptions,
3093
- errorOnInvalidContent: (_b = options.errorOnInvalidContent) != null ? _b : editor.options.enableContentCheck
3068
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
3094
3069
  });
3095
3070
  };
3096
3071
 
@@ -3690,6 +3665,80 @@ var Commands = Extension.create({
3690
3665
  }
3691
3666
  });
3692
3667
 
3668
+ // src/extensions/delete.ts
3669
+ import { RemoveMarkStep } from "@tiptap/pm/transform";
3670
+ var Delete = Extension.create({
3671
+ name: "delete",
3672
+ onUpdate({ transaction, appendedTransactions }) {
3673
+ var _a, _b, _c;
3674
+ const callback = () => {
3675
+ var _a2, _b2, _c2, _d;
3676
+ if ((_d = (_c2 = (_b2 = (_a2 = this.editor.options.coreExtensionOptions) == null ? void 0 : _a2.delete) == null ? void 0 : _b2.filterTransaction) == null ? void 0 : _c2.call(_b2, transaction)) != null ? _d : transaction.getMeta("y-sync$")) {
3677
+ return;
3678
+ }
3679
+ const nextTransaction = combineTransactionSteps(transaction.before, [transaction, ...appendedTransactions]);
3680
+ const changes = getChangedRanges(nextTransaction);
3681
+ changes.forEach((change) => {
3682
+ if (nextTransaction.mapping.mapResult(change.oldRange.from).deletedAfter && nextTransaction.mapping.mapResult(change.oldRange.to).deletedBefore) {
3683
+ nextTransaction.before.nodesBetween(change.oldRange.from, change.oldRange.to, (node, from) => {
3684
+ const to = from + node.nodeSize - 2;
3685
+ const isFullyWithinRange = change.oldRange.from <= from && to <= change.oldRange.to;
3686
+ this.editor.emit("delete", {
3687
+ type: "node",
3688
+ node,
3689
+ from,
3690
+ to,
3691
+ newFrom: nextTransaction.mapping.map(from),
3692
+ newTo: nextTransaction.mapping.map(to),
3693
+ deletedRange: change.oldRange,
3694
+ newRange: change.newRange,
3695
+ partial: !isFullyWithinRange,
3696
+ editor: this.editor,
3697
+ transaction,
3698
+ combinedTransform: nextTransaction
3699
+ });
3700
+ });
3701
+ }
3702
+ });
3703
+ const mapping = nextTransaction.mapping;
3704
+ nextTransaction.steps.forEach((step, index) => {
3705
+ var _a3, _b3;
3706
+ if (step instanceof RemoveMarkStep) {
3707
+ const newStart = mapping.slice(index).map(step.from, -1);
3708
+ const newEnd = mapping.slice(index).map(step.to);
3709
+ const oldStart = mapping.invert().map(newStart, -1);
3710
+ const oldEnd = mapping.invert().map(newEnd);
3711
+ const foundBeforeMark = (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark));
3712
+ const foundAfterMark = (_b3 = nextTransaction.doc.nodeAt(newEnd)) == null ? void 0 : _b3.marks.some((mark) => mark.eq(step.mark));
3713
+ this.editor.emit("delete", {
3714
+ type: "mark",
3715
+ mark: step.mark,
3716
+ from: step.from,
3717
+ to: step.to,
3718
+ deletedRange: {
3719
+ from: oldStart,
3720
+ to: oldEnd
3721
+ },
3722
+ newRange: {
3723
+ from: newStart,
3724
+ to: newEnd
3725
+ },
3726
+ partial: Boolean(foundAfterMark || foundBeforeMark),
3727
+ editor: this.editor,
3728
+ transaction,
3729
+ combinedTransform: nextTransaction
3730
+ });
3731
+ }
3732
+ });
3733
+ };
3734
+ if ((_c = (_b = (_a = this.editor.options.coreExtensionOptions) == null ? void 0 : _a.delete) == null ? void 0 : _b.async) != null ? _c : true) {
3735
+ setTimeout(callback, 0);
3736
+ } else {
3737
+ callback();
3738
+ }
3739
+ }
3740
+ });
3741
+
3693
3742
  // src/extensions/drop.ts
3694
3743
  import { Plugin as Plugin4, PluginKey as PluginKey2 } from "@tiptap/pm/state";
3695
3744
  var Drop = Extension.create({
@@ -3835,6 +3884,9 @@ var Keymap = Extension.create({
3835
3884
  new Plugin7({
3836
3885
  key: new PluginKey5("clearDocument"),
3837
3886
  appendTransaction: (transactions, oldState, newState) => {
3887
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
3888
+ return;
3889
+ }
3838
3890
  const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
3839
3891
  const ignoreTr = transactions.some((transaction) => transaction.getMeta("preventClearDocument"));
3840
3892
  if (!docChanges || ignoreTr) {
@@ -4176,6 +4228,7 @@ function createStyleTag(style2, nonce, suffix) {
4176
4228
  var Editor = class extends EventEmitter {
4177
4229
  constructor(options = {}) {
4178
4230
  super();
4231
+ this.editorView = null;
4179
4232
  this.isFocused = false;
4180
4233
  /**
4181
4234
  * The editor is considered initialized after the `create` event has been emitted.
@@ -4187,7 +4240,7 @@ var Editor = class extends EventEmitter {
4187
4240
  */
4188
4241
  this.instanceId = Math.random().toString(36).slice(2, 9);
4189
4242
  this.options = {
4190
- element: document.createElement("div"),
4243
+ element: typeof document !== "undefined" ? document.createElement("div") : null,
4191
4244
  content: "",
4192
4245
  injectCSS: true,
4193
4246
  injectNonce: void 0,
@@ -4213,7 +4266,8 @@ var Editor = class extends EventEmitter {
4213
4266
  throw error;
4214
4267
  },
4215
4268
  onPaste: () => null,
4216
- onDrop: () => null
4269
+ onDrop: () => null,
4270
+ onDelete: () => null
4217
4271
  };
4218
4272
  this.isCapturingTransaction = false;
4219
4273
  this.capturedTransaction = null;
@@ -4224,8 +4278,6 @@ var Editor = class extends EventEmitter {
4224
4278
  this.on("beforeCreate", this.options.onBeforeCreate);
4225
4279
  this.emit("beforeCreate", { editor: this });
4226
4280
  this.on("contentError", this.options.onContentError);
4227
- this.createView();
4228
- this.injectCSS();
4229
4281
  this.on("create", this.options.onCreate);
4230
4282
  this.on("update", this.options.onUpdate);
4231
4283
  this.on("selectionUpdate", this.options.onSelectionUpdate);
@@ -4235,6 +4287,25 @@ var Editor = class extends EventEmitter {
4235
4287
  this.on("destroy", this.options.onDestroy);
4236
4288
  this.on("drop", ({ event, slice, moved }) => this.options.onDrop(event, slice, moved));
4237
4289
  this.on("paste", ({ event, slice }) => this.options.onPaste(event, slice));
4290
+ this.on("delete", this.options.onDelete);
4291
+ const initialDoc = this.createDoc();
4292
+ const selection = resolveFocusPosition(initialDoc, this.options.autofocus);
4293
+ this.editorState = EditorState4.create({
4294
+ doc: initialDoc,
4295
+ schema: this.schema,
4296
+ selection: selection || void 0
4297
+ });
4298
+ if (this.options.element) {
4299
+ this.mount(this.options.element);
4300
+ }
4301
+ }
4302
+ mount(el) {
4303
+ if (typeof document === "undefined") {
4304
+ throw new Error(
4305
+ `[tiptap error]: The editor cannot be mounted because there is no 'document' defined in this environment.`
4306
+ );
4307
+ }
4308
+ this.createView(el);
4238
4309
  window.setTimeout(() => {
4239
4310
  if (this.isDestroyed) {
4240
4311
  return;
@@ -4272,7 +4343,7 @@ var Editor = class extends EventEmitter {
4272
4343
  * Inject CSS styles.
4273
4344
  */
4274
4345
  injectCSS() {
4275
- if (this.options.injectCSS && document) {
4346
+ if (this.options.injectCSS && typeof document !== "undefined") {
4276
4347
  this.css = createStyleTag(style, this.options.injectNonce);
4277
4348
  }
4278
4349
  }
@@ -4286,7 +4357,7 @@ var Editor = class extends EventEmitter {
4286
4357
  ...this.options,
4287
4358
  ...options
4288
4359
  };
4289
- if (!this.view || !this.state || this.isDestroyed) {
4360
+ if (!this.editorView || !this.state || this.isDestroyed) {
4290
4361
  return;
4291
4362
  }
4292
4363
  if (this.options.editorProps) {
@@ -4309,11 +4380,50 @@ var Editor = class extends EventEmitter {
4309
4380
  get isEditable() {
4310
4381
  return this.options.editable && this.view && this.view.editable;
4311
4382
  }
4383
+ /**
4384
+ * Returns the editor state.
4385
+ */
4386
+ get view() {
4387
+ if (this.editorView) {
4388
+ return this.editorView;
4389
+ }
4390
+ return new Proxy(
4391
+ {
4392
+ state: this.editorState,
4393
+ updateState: (state) => {
4394
+ this.editorState = state;
4395
+ },
4396
+ dispatch: (tr) => {
4397
+ this.editorState = this.state.apply(tr);
4398
+ },
4399
+ // Stub some commonly accessed properties to prevent errors
4400
+ composing: false,
4401
+ dragging: null,
4402
+ editable: true
4403
+ },
4404
+ {
4405
+ get: (obj, key) => {
4406
+ if (key === "state") {
4407
+ return this.editorState;
4408
+ }
4409
+ if (key in obj) {
4410
+ return Reflect.get(obj, key);
4411
+ }
4412
+ throw new Error(
4413
+ `[tiptap error]: The editor view is not available. Cannot access view['${key}']. The editor may not be mounted yet.`
4414
+ );
4415
+ }
4416
+ }
4417
+ );
4418
+ }
4312
4419
  /**
4313
4420
  * Returns the editor state.
4314
4421
  */
4315
4422
  get state() {
4316
- return this.view.state;
4423
+ if (this.editorView) {
4424
+ this.editorState = this.view.state;
4425
+ }
4426
+ return this.editorState;
4317
4427
  }
4318
4428
  /**
4319
4429
  * Register a ProseMirror plugin.
@@ -4368,7 +4478,8 @@ var Editor = class extends EventEmitter {
4368
4478
  Keymap,
4369
4479
  Tabindex,
4370
4480
  Drop,
4371
- Paste
4481
+ Paste,
4482
+ Delete
4372
4483
  ].filter((ext) => {
4373
4484
  if (typeof this.options.enableCoreExtensions === "object") {
4374
4485
  return this.options.enableCoreExtensions[ext.name] !== false;
@@ -4395,10 +4506,9 @@ var Editor = class extends EventEmitter {
4395
4506
  this.schema = this.extensionManager.schema;
4396
4507
  }
4397
4508
  /**
4398
- * Creates a ProseMirror view.
4509
+ * Creates the initial document.
4399
4510
  */
4400
- createView() {
4401
- var _a;
4511
+ createDoc() {
4402
4512
  let doc;
4403
4513
  try {
4404
4514
  doc = createDocument(this.options.content, this.schema, this.options.parseOptions, {
@@ -4412,7 +4522,8 @@ var Editor = class extends EventEmitter {
4412
4522
  editor: this,
4413
4523
  error: e,
4414
4524
  disableCollaboration: () => {
4415
- if (this.storage.collaboration) {
4525
+ if ("collaboration" in this.storage && typeof this.storage.collaboration === "object" && this.storage.collaboration) {
4526
+ ;
4416
4527
  this.storage.collaboration.isDisabled = true;
4417
4528
  }
4418
4529
  this.options.extensions = this.options.extensions.filter((extension) => extension.name !== "collaboration");
@@ -4423,8 +4534,14 @@ var Editor = class extends EventEmitter {
4423
4534
  errorOnInvalidContent: false
4424
4535
  });
4425
4536
  }
4426
- const selection = resolveFocusPosition(doc, this.options.autofocus);
4427
- this.view = new EditorView(this.options.element, {
4537
+ return doc;
4538
+ }
4539
+ /**
4540
+ * Creates a ProseMirror view.
4541
+ */
4542
+ createView(element) {
4543
+ var _a;
4544
+ this.editorView = new EditorView(element, {
4428
4545
  ...this.options.editorProps,
4429
4546
  attributes: {
4430
4547
  // add `role="textbox"` to the editor element
@@ -4432,10 +4549,7 @@ var Editor = class extends EventEmitter {
4432
4549
  ...(_a = this.options.editorProps) == null ? void 0 : _a.attributes
4433
4550
  },
4434
4551
  dispatchTransaction: this.dispatchTransaction.bind(this),
4435
- state: EditorState4.create({
4436
- doc,
4437
- selection: selection || void 0
4438
- })
4552
+ state: this.editorState
4439
4553
  });
4440
4554
  const newState = this.state.reconfigure({
4441
4555
  plugins: this.extensionManager.plugins
@@ -4443,6 +4557,7 @@ var Editor = class extends EventEmitter {
4443
4557
  this.view.updateState(newState);
4444
4558
  this.createNodeViews();
4445
4559
  this.prependClass();
4560
+ this.injectCSS();
4446
4561
  const dom = this.view.dom;
4447
4562
  dom.editor = this;
4448
4563
  }
@@ -4454,6 +4569,7 @@ var Editor = class extends EventEmitter {
4454
4569
  return;
4455
4570
  }
4456
4571
  this.view.setProps({
4572
+ markViews: this.extensionManager.markViews,
4457
4573
  nodeViews: this.extensionManager.nodeViews
4458
4574
  });
4459
4575
  }
@@ -4590,12 +4706,12 @@ var Editor = class extends EventEmitter {
4590
4706
  */
4591
4707
  destroy() {
4592
4708
  this.emit("destroy");
4593
- if (this.view) {
4594
- const dom = this.view.dom;
4709
+ if (this.editorView) {
4710
+ const dom = this.editorView.dom;
4595
4711
  if (dom && dom.editor) {
4596
4712
  delete dom.editor;
4597
4713
  }
4598
- this.view.destroy();
4714
+ this.editorView.destroy();
4599
4715
  }
4600
4716
  this.removeAllListeners();
4601
4717
  }
@@ -4764,90 +4880,88 @@ function wrappingInputRule(config) {
4764
4880
  });
4765
4881
  }
4766
4882
 
4767
- // src/Node.ts
4768
- var Node3 = class _Node {
4769
- constructor(config = {}) {
4770
- this.type = "node";
4771
- this.name = "node";
4772
- this.parent = null;
4773
- this.child = null;
4774
- this.config = {
4775
- name: this.name,
4776
- defaultOptions: {}
4777
- };
4778
- this.config = {
4779
- ...this.config,
4780
- ...config
4781
- };
4782
- this.name = this.config.name;
4783
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
4784
- console.warn(
4785
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
4786
- );
4883
+ // src/jsx-runtime.ts
4884
+ function Fragment7(props) {
4885
+ return props.children;
4886
+ }
4887
+ var h = (tag, attributes) => {
4888
+ if (tag === "slot") {
4889
+ return 0;
4890
+ }
4891
+ if (tag instanceof Function) {
4892
+ return tag(attributes);
4893
+ }
4894
+ const { children, ...rest } = attributes != null ? attributes : {};
4895
+ if (tag === "svg") {
4896
+ throw new Error("SVG elements are not supported in the JSX syntax, use the array syntax instead");
4897
+ }
4898
+ return [tag, rest, children];
4899
+ };
4900
+
4901
+ // src/utilities/escapeForRegEx.ts
4902
+ function escapeForRegEx(string) {
4903
+ return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
4904
+ }
4905
+
4906
+ // src/utilities/isString.ts
4907
+ function isString(value) {
4908
+ return typeof value === "string";
4909
+ }
4910
+
4911
+ // src/MarkView.ts
4912
+ var MarkView = class {
4913
+ constructor(component, props, options) {
4914
+ this.component = component;
4915
+ this.editor = props.editor;
4916
+ this.options = { ...options };
4917
+ this.mark = props.mark;
4918
+ this.HTMLAttributes = props.HTMLAttributes;
4919
+ }
4920
+ get dom() {
4921
+ return this.editor.view.dom;
4922
+ }
4923
+ get contentDOM() {
4924
+ return null;
4925
+ }
4926
+ ignoreMutation(mutation) {
4927
+ if (!this.dom || !this.contentDOM) {
4928
+ return true;
4787
4929
  }
4788
- this.options = this.config.defaultOptions;
4789
- if (this.config.addOptions) {
4790
- this.options = callOrReturn(
4791
- getExtensionField(this, "addOptions", {
4792
- name: this.name
4793
- })
4794
- );
4930
+ if (typeof this.options.ignoreMutation === "function") {
4931
+ return this.options.ignoreMutation({ mutation });
4795
4932
  }
4796
- this.storage = callOrReturn(
4797
- getExtensionField(this, "addStorage", {
4798
- name: this.name,
4799
- options: this.options
4800
- })
4801
- ) || {};
4933
+ if (mutation.type === "selection") {
4934
+ return false;
4935
+ }
4936
+ if (this.dom.contains(mutation.target) && mutation.type === "childList" && (isiOS() || isAndroid()) && this.editor.isFocused) {
4937
+ const changedNodes = [...Array.from(mutation.addedNodes), ...Array.from(mutation.removedNodes)];
4938
+ if (changedNodes.every((node) => node.isContentEditable)) {
4939
+ return false;
4940
+ }
4941
+ }
4942
+ if (this.contentDOM === mutation.target && mutation.type === "attributes") {
4943
+ return true;
4944
+ }
4945
+ if (this.contentDOM.contains(mutation.target)) {
4946
+ return false;
4947
+ }
4948
+ return true;
4949
+ }
4950
+ };
4951
+
4952
+ // src/Node.ts
4953
+ var Node3 = class _Node extends Extendable {
4954
+ constructor() {
4955
+ super(...arguments);
4956
+ this.type = "node";
4802
4957
  }
4803
4958
  static create(config = {}) {
4804
4959
  return new _Node(config);
4805
4960
  }
4806
- configure(options = {}) {
4807
- const extension = this.extend({
4808
- ...this.config,
4809
- addOptions: () => {
4810
- return mergeDeep(this.options, options);
4811
- }
4812
- });
4813
- extension.name = this.name;
4814
- extension.parent = this.parent;
4815
- return extension;
4816
- }
4817
- extend(extendedConfig = {}) {
4818
- const extension = new _Node(extendedConfig);
4819
- extension.parent = this;
4820
- this.child = extension;
4821
- extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
4822
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
4823
- console.warn(
4824
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
4825
- );
4826
- }
4827
- extension.options = callOrReturn(
4828
- getExtensionField(extension, "addOptions", {
4829
- name: extension.name
4830
- })
4831
- );
4832
- extension.storage = callOrReturn(
4833
- getExtensionField(extension, "addStorage", {
4834
- name: extension.name,
4835
- options: extension.options
4836
- })
4837
- );
4838
- return extension;
4839
- }
4840
4961
  };
4841
4962
 
4842
4963
  // src/NodeView.ts
4843
4964
  import { NodeSelection as NodeSelection4 } from "@tiptap/pm/state";
4844
-
4845
- // src/utilities/isAndroid.ts
4846
- function isAndroid() {
4847
- return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
4848
- }
4849
-
4850
- // src/NodeView.ts
4851
4965
  var NodeView = class {
4852
4966
  constructor(component, props, options) {
4853
4967
  this.isDragging = false;
@@ -5069,16 +5183,6 @@ function markPasteRule(config) {
5069
5183
  });
5070
5184
  }
5071
5185
 
5072
- // src/utilities/escapeForRegEx.ts
5073
- function escapeForRegEx(string) {
5074
- return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
5075
- }
5076
-
5077
- // src/utilities/isString.ts
5078
- function isString(value) {
5079
- return typeof value === "string";
5080
- }
5081
-
5082
5186
  // src/pasteRules/nodePasteRule.ts
5083
5187
  function nodePasteRule(config) {
5084
5188
  return new PasteRule({
@@ -5148,8 +5252,10 @@ export {
5148
5252
  CommandManager,
5149
5253
  Editor,
5150
5254
  Extension,
5255
+ Fragment7 as Fragment,
5151
5256
  InputRule,
5152
5257
  Mark,
5258
+ MarkView,
5153
5259
  Node3 as Node,
5154
5260
  NodePos,
5155
5261
  NodeView,
@@ -5159,6 +5265,7 @@ export {
5159
5265
  combineTransactionSteps,
5160
5266
  createChainableState,
5161
5267
  createDocument,
5268
+ h as createElement,
5162
5269
  createNodeFromContent,
5163
5270
  createStyleTag,
5164
5271
  defaultBlockAt,
@@ -5199,9 +5306,11 @@ export {
5199
5306
  getTextBetween,
5200
5307
  getTextContentFromNodes,
5201
5308
  getTextSerializersFromSchema,
5309
+ h,
5202
5310
  injectExtensionAttributesToParseRule,
5203
5311
  inputRulesPlugin,
5204
5312
  isActive,
5313
+ isAndroid,
5205
5314
  isAtEndOfNode,
5206
5315
  isAtStartOfNode,
5207
5316
  isEmptyObject,