@tiptap/core 3.0.0-next.4 → 3.0.0-next.6

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.cjs CHANGED
@@ -23,8 +23,10 @@ __export(index_exports, {
23
23
  CommandManager: () => CommandManager,
24
24
  Editor: () => Editor,
25
25
  Extension: () => Extension,
26
+ Fragment: () => Fragment7,
26
27
  InputRule: () => InputRule,
27
28
  Mark: () => Mark,
29
+ MarkView: () => MarkView,
28
30
  Node: () => Node3,
29
31
  NodePos: () => NodePos,
30
32
  NodeView: () => NodeView,
@@ -34,6 +36,7 @@ __export(index_exports, {
34
36
  combineTransactionSteps: () => combineTransactionSteps,
35
37
  createChainableState: () => createChainableState,
36
38
  createDocument: () => createDocument,
39
+ createElement: () => h,
37
40
  createNodeFromContent: () => createNodeFromContent,
38
41
  createStyleTag: () => createStyleTag,
39
42
  defaultBlockAt: () => defaultBlockAt,
@@ -74,9 +77,11 @@ __export(index_exports, {
74
77
  getTextBetween: () => getTextBetween,
75
78
  getTextContentFromNodes: () => getTextContentFromNodes,
76
79
  getTextSerializersFromSchema: () => getTextSerializersFromSchema,
80
+ h: () => h,
77
81
  injectExtensionAttributesToParseRule: () => injectExtensionAttributesToParseRule,
78
82
  inputRulesPlugin: () => inputRulesPlugin,
79
83
  isActive: () => isActive,
84
+ isAndroid: () => isAndroid,
80
85
  isAtEndOfNode: () => isAtEndOfNode,
81
86
  isAtStartOfNode: () => isAtStartOfNode,
82
87
  isEmptyObject: () => isEmptyObject,
@@ -334,6 +339,9 @@ var removeWhitespaces = (node) => {
334
339
  return node;
335
340
  };
336
341
  function elementFromString(value) {
342
+ if (typeof window === "undefined") {
343
+ throw new Error("[tiptap error]: there is no window object available, so this function cannot be used");
344
+ }
337
345
  const wrappedValue = `<body>${value}</body>`;
338
346
  const html = new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
339
347
  return removeWhitespaces(html);
@@ -656,7 +664,7 @@ function mergeAttributes(...objects) {
656
664
  return;
657
665
  }
658
666
  if (key === "class") {
659
- const valueClasses = value ? value.split(" ") : [];
667
+ const valueClasses = value ? String(value).split(" ") : [];
660
668
  const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(" ") : [];
661
669
  const insertClasses = valueClasses.filter((valueClass) => !existingClasses.includes(valueClass));
662
670
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
@@ -1881,44 +1889,40 @@ function mergeDeep(target, source) {
1881
1889
  return output;
1882
1890
  }
1883
1891
 
1884
- // src/Mark.ts
1885
- var Mark = class _Mark {
1892
+ // src/Extendable.ts
1893
+ var Extendable = class {
1886
1894
  constructor(config = {}) {
1887
- this.type = "mark";
1888
- this.name = "mark";
1895
+ this.type = "extendable";
1889
1896
  this.parent = null;
1890
1897
  this.child = null;
1898
+ this.name = "";
1891
1899
  this.config = {
1892
- name: this.name,
1893
- defaultOptions: {}
1900
+ name: this.name
1894
1901
  };
1895
1902
  this.config = {
1896
1903
  ...this.config,
1897
1904
  ...config
1898
1905
  };
1899
1906
  this.name = this.config.name;
1900
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
1901
- console.warn(
1902
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
1903
- );
1904
- }
1905
- this.options = this.config.defaultOptions;
1906
- if (this.config.addOptions) {
1907
- this.options = callOrReturn(
1907
+ }
1908
+ get options() {
1909
+ return {
1910
+ ...callOrReturn(
1908
1911
  getExtensionField(this, "addOptions", {
1909
1912
  name: this.name
1910
1913
  })
1911
- );
1912
- }
1913
- this.storage = callOrReturn(
1914
- getExtensionField(this, "addStorage", {
1915
- name: this.name,
1916
- options: this.options
1917
- })
1918
- ) || {};
1914
+ ) || {}
1915
+ };
1919
1916
  }
1920
- static create(config = {}) {
1921
- return new _Mark(config);
1917
+ get storage() {
1918
+ return {
1919
+ ...callOrReturn(
1920
+ getExtensionField(this, "addStorage", {
1921
+ name: this.name,
1922
+ options: this.options
1923
+ })
1924
+ ) || {}
1925
+ };
1922
1926
  }
1923
1927
  configure(options = {}) {
1924
1928
  const extension = this.extend({
@@ -1932,28 +1936,23 @@ var Mark = class _Mark {
1932
1936
  return extension;
1933
1937
  }
1934
1938
  extend(extendedConfig = {}) {
1935
- const extension = new _Mark(extendedConfig);
1939
+ const extension = new this.constructor({ ...this.config, ...extendedConfig });
1936
1940
  extension.parent = this;
1937
1941
  this.child = extension;
1938
1942
  extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
1939
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
1940
- console.warn(
1941
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
1942
- );
1943
- }
1944
- extension.options = callOrReturn(
1945
- getExtensionField(extension, "addOptions", {
1946
- name: extension.name
1947
- })
1948
- );
1949
- extension.storage = callOrReturn(
1950
- getExtensionField(extension, "addStorage", {
1951
- name: extension.name,
1952
- options: extension.options
1953
- })
1954
- );
1955
1943
  return extension;
1956
1944
  }
1945
+ };
1946
+
1947
+ // src/Mark.ts
1948
+ var Mark = class _Mark extends Extendable {
1949
+ constructor() {
1950
+ super(...arguments);
1951
+ this.type = "mark";
1952
+ }
1953
+ static create(config = {}) {
1954
+ return new _Mark(config);
1955
+ }
1957
1956
  static handleExit({ editor, mark }) {
1958
1957
  const { tr } = editor.state;
1959
1958
  const currentPos = editor.state.selection.$from;
@@ -2223,7 +2222,7 @@ var ExtensionManager = class {
2223
2222
  const context = {
2224
2223
  name: extension.name,
2225
2224
  options: extension.options,
2226
- storage: extension.storage,
2225
+ storage: this.editor.extensionStorage[extension.name],
2227
2226
  editor: this.editor,
2228
2227
  type: getSchemaTypeByName(extension.name, this.schema)
2229
2228
  };
@@ -2250,7 +2249,7 @@ var ExtensionManager = class {
2250
2249
  const context = {
2251
2250
  name: extension.name,
2252
2251
  options: extension.options,
2253
- storage: extension.storage,
2252
+ storage: this.editor.extensionStorage[extension.name],
2254
2253
  editor,
2255
2254
  type: getSchemaTypeByName(extension.name, this.schema)
2256
2255
  };
@@ -2325,7 +2324,7 @@ var ExtensionManager = class {
2325
2324
  const context = {
2326
2325
  name: extension.name,
2327
2326
  options: extension.options,
2328
- storage: extension.storage,
2327
+ storage: this.editor.extensionStorage[extension.name],
2329
2328
  editor,
2330
2329
  type: getNodeType(extension.name, this.schema)
2331
2330
  };
@@ -2352,18 +2351,55 @@ var ExtensionManager = class {
2352
2351
  })
2353
2352
  );
2354
2353
  }
2354
+ get markViews() {
2355
+ const { editor } = this;
2356
+ const { markExtensions } = splitExtensions(this.extensions);
2357
+ return Object.fromEntries(
2358
+ markExtensions.filter((extension) => !!getExtensionField(extension, "addMarkView")).map((extension) => {
2359
+ const extensionAttributes = this.attributes.filter((attribute) => attribute.type === extension.name);
2360
+ const context = {
2361
+ name: extension.name,
2362
+ options: extension.options,
2363
+ storage: this.editor.extensionStorage[extension.name],
2364
+ editor,
2365
+ type: getMarkType(extension.name, this.schema)
2366
+ };
2367
+ const addMarkView = getExtensionField(extension, "addMarkView", context);
2368
+ if (!addMarkView) {
2369
+ return [];
2370
+ }
2371
+ const markView = (mark, view, inline) => {
2372
+ const HTMLAttributes = getRenderedAttributes(mark, extensionAttributes);
2373
+ return addMarkView()({
2374
+ // pass-through
2375
+ mark,
2376
+ view,
2377
+ inline,
2378
+ // tiptap-specific
2379
+ editor,
2380
+ extension,
2381
+ HTMLAttributes
2382
+ });
2383
+ };
2384
+ return [extension.name, markView];
2385
+ })
2386
+ );
2387
+ }
2355
2388
  /**
2356
2389
  * Go through all extensions, create extension storages & setup marks
2357
2390
  * & bind editor event listener.
2358
2391
  */
2359
2392
  setupExtensions() {
2360
- this.extensions.forEach((extension) => {
2393
+ const extensions = this.extensions;
2394
+ this.editor.extensionStorage = Object.fromEntries(
2395
+ extensions.map((extension) => [extension.name, extension.storage])
2396
+ );
2397
+ extensions.forEach((extension) => {
2361
2398
  var _a;
2362
- this.editor.extensionStorage[extension.name] = extension.storage;
2363
2399
  const context = {
2364
2400
  name: extension.name,
2365
2401
  options: extension.options,
2366
- storage: extension.storage,
2402
+ storage: this.editor.extensionStorage[extension.name],
2367
2403
  editor: this.editor,
2368
2404
  type: getSchemaTypeByName(extension.name, this.schema)
2369
2405
  };
@@ -2421,6 +2457,7 @@ var extensions_exports = {};
2421
2457
  __export(extensions_exports, {
2422
2458
  ClipboardTextSerializer: () => ClipboardTextSerializer,
2423
2459
  Commands: () => Commands,
2460
+ Delete: () => Delete,
2424
2461
  Drop: () => Drop,
2425
2462
  Editable: () => Editable,
2426
2463
  FocusEvents: () => FocusEvents,
@@ -2433,78 +2470,14 @@ __export(extensions_exports, {
2433
2470
  var import_state7 = require("@tiptap/pm/state");
2434
2471
 
2435
2472
  // src/Extension.ts
2436
- var Extension = class _Extension {
2437
- constructor(config = {}) {
2473
+ var Extension = class _Extension extends Extendable {
2474
+ constructor() {
2475
+ super(...arguments);
2438
2476
  this.type = "extension";
2439
- this.name = "extension";
2440
- this.parent = null;
2441
- this.child = null;
2442
- this.config = {
2443
- name: this.name,
2444
- defaultOptions: {}
2445
- };
2446
- this.config = {
2447
- ...this.config,
2448
- ...config
2449
- };
2450
- this.name = this.config.name;
2451
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
2452
- console.warn(
2453
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
2454
- );
2455
- }
2456
- this.options = this.config.defaultOptions;
2457
- if (this.config.addOptions) {
2458
- this.options = callOrReturn(
2459
- getExtensionField(this, "addOptions", {
2460
- name: this.name
2461
- })
2462
- );
2463
- }
2464
- this.storage = callOrReturn(
2465
- getExtensionField(this, "addStorage", {
2466
- name: this.name,
2467
- options: this.options
2468
- })
2469
- ) || {};
2470
2477
  }
2471
2478
  static create(config = {}) {
2472
2479
  return new _Extension(config);
2473
2480
  }
2474
- configure(options = {}) {
2475
- const extension = this.extend({
2476
- ...this.config,
2477
- addOptions: () => {
2478
- return mergeDeep(this.options, options);
2479
- }
2480
- });
2481
- extension.name = this.name;
2482
- extension.parent = this.parent;
2483
- return extension;
2484
- }
2485
- extend(extendedConfig = {}) {
2486
- const extension = new _Extension({ ...this.config, ...extendedConfig });
2487
- extension.parent = this;
2488
- this.child = extension;
2489
- extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
2490
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
2491
- console.warn(
2492
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
2493
- );
2494
- }
2495
- extension.options = callOrReturn(
2496
- getExtensionField(extension, "addOptions", {
2497
- name: extension.name
2498
- })
2499
- );
2500
- extension.storage = callOrReturn(
2501
- getExtensionField(extension, "addStorage", {
2502
- name: extension.name,
2503
- options: extension.options
2504
- })
2505
- );
2506
- return extension;
2507
- }
2508
2481
  };
2509
2482
 
2510
2483
  // src/extensions/clipboardTextSerializer.ts
@@ -2617,8 +2590,8 @@ var blur = () => ({ editor, view }) => {
2617
2590
  };
2618
2591
 
2619
2592
  // src/commands/clearContent.ts
2620
- var clearContent = (emitUpdate = false) => ({ commands }) => {
2621
- return commands.setContent("", emitUpdate);
2593
+ var clearContent = (emitUpdate = true) => ({ commands }) => {
2594
+ return commands.setContent("", { emitUpdate });
2622
2595
  };
2623
2596
 
2624
2597
  // src/commands/clearNodes.ts
@@ -2770,6 +2743,17 @@ var first = (commands) => (props) => {
2770
2743
  return false;
2771
2744
  };
2772
2745
 
2746
+ // src/utilities/isAndroid.ts
2747
+ function isAndroid() {
2748
+ return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
2749
+ }
2750
+
2751
+ // src/utilities/isiOS.ts
2752
+ function isiOS() {
2753
+ return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
2754
+ navigator.userAgent.includes("Mac") && "ontouchend" in document;
2755
+ }
2756
+
2773
2757
  // src/commands/focus.ts
2774
2758
  var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch }) => {
2775
2759
  options = {
@@ -2777,8 +2761,10 @@ var focus = (position = null, options = {}) => ({ editor, view, tr, dispatch })
2777
2761
  ...options
2778
2762
  };
2779
2763
  const delayedFocus = () => {
2780
- ;
2781
- view.dom.focus();
2764
+ if (isiOS() || isAndroid()) {
2765
+ ;
2766
+ view.dom.focus();
2767
+ }
2782
2768
  requestAnimationFrame(() => {
2783
2769
  if (!editor.isDestroyed) {
2784
2770
  view.focus();
@@ -2849,7 +2835,8 @@ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) =
2849
2835
  editor,
2850
2836
  error: e,
2851
2837
  disableCollaboration: () => {
2852
- if (editor.storage.collaboration) {
2838
+ if ("collaboration" in editor.storage && typeof editor.storage.collaboration === "object" && editor.storage.collaboration) {
2839
+ ;
2853
2840
  editor.storage.collaboration.isDisabled = true;
2854
2841
  }
2855
2842
  }
@@ -2976,12 +2963,6 @@ var joinTextblockForward = () => ({ state, dispatch }) => {
2976
2963
  return (0, import_commands6.joinTextblockForward)(state, dispatch);
2977
2964
  };
2978
2965
 
2979
- // src/utilities/isiOS.ts
2980
- function isiOS() {
2981
- return ["iPad Simulator", "iPhone Simulator", "iPod Simulator", "iPad", "iPhone", "iPod"].includes(navigator.platform) || // iPad on iOS 13 detection
2982
- navigator.userAgent.includes("Mac") && "ontouchend" in document;
2983
- }
2984
-
2985
2966
  // src/utilities/isMacOS.ts
2986
2967
  function isMacOS() {
2987
2968
  return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
@@ -3182,12 +3163,11 @@ var selectTextblockStart = () => ({ state, dispatch }) => {
3182
3163
  };
3183
3164
 
3184
3165
  // src/commands/setContent.ts
3185
- var setContent = (content, emitUpdate = false, parseOptions = {}, options = {}) => ({ editor, tr, dispatch, commands }) => {
3186
- var _a, _b;
3166
+ var setContent = (content, { errorOnInvalidContent, emitUpdate = true, parseOptions = {} } = {}) => ({ editor, tr, dispatch, commands }) => {
3187
3167
  const { doc } = tr;
3188
3168
  if (parseOptions.preserveWhitespace !== "full") {
3189
3169
  const document2 = createDocument(content, editor.schema, parseOptions, {
3190
- errorOnInvalidContent: (_a = options.errorOnInvalidContent) != null ? _a : editor.options.enableContentCheck
3170
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
3191
3171
  });
3192
3172
  if (dispatch) {
3193
3173
  tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
@@ -3199,7 +3179,7 @@ var setContent = (content, emitUpdate = false, parseOptions = {}, options = {})
3199
3179
  }
3200
3180
  return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
3201
3181
  parseOptions,
3202
- errorOnInvalidContent: (_b = options.errorOnInvalidContent) != null ? _b : editor.options.enableContentCheck
3182
+ errorOnInvalidContent: errorOnInvalidContent != null ? errorOnInvalidContent : editor.options.enableContentCheck
3203
3183
  });
3204
3184
  };
3205
3185
 
@@ -3799,6 +3779,80 @@ var Commands = Extension.create({
3799
3779
  }
3800
3780
  });
3801
3781
 
3782
+ // src/extensions/delete.ts
3783
+ var import_transform9 = require("@tiptap/pm/transform");
3784
+ var Delete = Extension.create({
3785
+ name: "delete",
3786
+ onUpdate({ transaction, appendedTransactions }) {
3787
+ var _a, _b, _c;
3788
+ const callback = () => {
3789
+ var _a2, _b2, _c2, _d;
3790
+ 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$")) {
3791
+ return;
3792
+ }
3793
+ const nextTransaction = combineTransactionSteps(transaction.before, [transaction, ...appendedTransactions]);
3794
+ const changes = getChangedRanges(nextTransaction);
3795
+ changes.forEach((change) => {
3796
+ if (nextTransaction.mapping.mapResult(change.oldRange.from).deletedAfter && nextTransaction.mapping.mapResult(change.oldRange.to).deletedBefore) {
3797
+ nextTransaction.before.nodesBetween(change.oldRange.from, change.oldRange.to, (node, from) => {
3798
+ const to = from + node.nodeSize - 2;
3799
+ const isFullyWithinRange = change.oldRange.from <= from && to <= change.oldRange.to;
3800
+ this.editor.emit("delete", {
3801
+ type: "node",
3802
+ node,
3803
+ from,
3804
+ to,
3805
+ newFrom: nextTransaction.mapping.map(from),
3806
+ newTo: nextTransaction.mapping.map(to),
3807
+ deletedRange: change.oldRange,
3808
+ newRange: change.newRange,
3809
+ partial: !isFullyWithinRange,
3810
+ editor: this.editor,
3811
+ transaction,
3812
+ combinedTransform: nextTransaction
3813
+ });
3814
+ });
3815
+ }
3816
+ });
3817
+ const mapping = nextTransaction.mapping;
3818
+ nextTransaction.steps.forEach((step, index) => {
3819
+ var _a3, _b3;
3820
+ if (step instanceof import_transform9.RemoveMarkStep) {
3821
+ const newStart = mapping.slice(index).map(step.from, -1);
3822
+ const newEnd = mapping.slice(index).map(step.to);
3823
+ const oldStart = mapping.invert().map(newStart, -1);
3824
+ const oldEnd = mapping.invert().map(newEnd);
3825
+ const foundBeforeMark = (_a3 = nextTransaction.doc.nodeAt(newStart - 1)) == null ? void 0 : _a3.marks.some((mark) => mark.eq(step.mark));
3826
+ const foundAfterMark = (_b3 = nextTransaction.doc.nodeAt(newEnd)) == null ? void 0 : _b3.marks.some((mark) => mark.eq(step.mark));
3827
+ this.editor.emit("delete", {
3828
+ type: "mark",
3829
+ mark: step.mark,
3830
+ from: step.from,
3831
+ to: step.to,
3832
+ deletedRange: {
3833
+ from: oldStart,
3834
+ to: oldEnd
3835
+ },
3836
+ newRange: {
3837
+ from: newStart,
3838
+ to: newEnd
3839
+ },
3840
+ partial: Boolean(foundAfterMark || foundBeforeMark),
3841
+ editor: this.editor,
3842
+ transaction,
3843
+ combinedTransform: nextTransaction
3844
+ });
3845
+ }
3846
+ });
3847
+ };
3848
+ if ((_c = (_b = (_a = this.editor.options.coreExtensionOptions) == null ? void 0 : _a.delete) == null ? void 0 : _b.async) != null ? _c : true) {
3849
+ setTimeout(callback, 0);
3850
+ } else {
3851
+ callback();
3852
+ }
3853
+ }
3854
+ });
3855
+
3802
3856
  // src/extensions/drop.ts
3803
3857
  var import_state15 = require("@tiptap/pm/state");
3804
3858
  var Drop = Extension.create({
@@ -3944,6 +3998,9 @@ var Keymap = Extension.create({
3944
3998
  new import_state18.Plugin({
3945
3999
  key: new import_state18.PluginKey("clearDocument"),
3946
4000
  appendTransaction: (transactions, oldState, newState) => {
4001
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
4002
+ return;
4003
+ }
3947
4004
  const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
3948
4005
  const ignoreTr = transactions.some((transaction) => transaction.getMeta("preventClearDocument"));
3949
4006
  if (!docChanges || ignoreTr) {
@@ -4285,6 +4342,7 @@ function createStyleTag(style2, nonce, suffix) {
4285
4342
  var Editor = class extends EventEmitter {
4286
4343
  constructor(options = {}) {
4287
4344
  super();
4345
+ this.editorView = null;
4288
4346
  this.isFocused = false;
4289
4347
  /**
4290
4348
  * The editor is considered initialized after the `create` event has been emitted.
@@ -4296,7 +4354,7 @@ var Editor = class extends EventEmitter {
4296
4354
  */
4297
4355
  this.instanceId = Math.random().toString(36).slice(2, 9);
4298
4356
  this.options = {
4299
- element: document.createElement("div"),
4357
+ element: typeof document !== "undefined" ? document.createElement("div") : null,
4300
4358
  content: "",
4301
4359
  injectCSS: true,
4302
4360
  injectNonce: void 0,
@@ -4322,7 +4380,8 @@ var Editor = class extends EventEmitter {
4322
4380
  throw error;
4323
4381
  },
4324
4382
  onPaste: () => null,
4325
- onDrop: () => null
4383
+ onDrop: () => null,
4384
+ onDelete: () => null
4326
4385
  };
4327
4386
  this.isCapturingTransaction = false;
4328
4387
  this.capturedTransaction = null;
@@ -4333,8 +4392,6 @@ var Editor = class extends EventEmitter {
4333
4392
  this.on("beforeCreate", this.options.onBeforeCreate);
4334
4393
  this.emit("beforeCreate", { editor: this });
4335
4394
  this.on("contentError", this.options.onContentError);
4336
- this.createView();
4337
- this.injectCSS();
4338
4395
  this.on("create", this.options.onCreate);
4339
4396
  this.on("update", this.options.onUpdate);
4340
4397
  this.on("selectionUpdate", this.options.onSelectionUpdate);
@@ -4344,6 +4401,25 @@ var Editor = class extends EventEmitter {
4344
4401
  this.on("destroy", this.options.onDestroy);
4345
4402
  this.on("drop", ({ event, slice, moved }) => this.options.onDrop(event, slice, moved));
4346
4403
  this.on("paste", ({ event, slice }) => this.options.onPaste(event, slice));
4404
+ this.on("delete", this.options.onDelete);
4405
+ const initialDoc = this.createDoc();
4406
+ const selection = resolveFocusPosition(initialDoc, this.options.autofocus);
4407
+ this.editorState = import_state21.EditorState.create({
4408
+ doc: initialDoc,
4409
+ schema: this.schema,
4410
+ selection: selection || void 0
4411
+ });
4412
+ if (this.options.element) {
4413
+ this.mount(this.options.element);
4414
+ }
4415
+ }
4416
+ mount(el) {
4417
+ if (typeof document === "undefined") {
4418
+ throw new Error(
4419
+ `[tiptap error]: The editor cannot be mounted because there is no 'document' defined in this environment.`
4420
+ );
4421
+ }
4422
+ this.createView(el);
4347
4423
  window.setTimeout(() => {
4348
4424
  if (this.isDestroyed) {
4349
4425
  return;
@@ -4381,7 +4457,7 @@ var Editor = class extends EventEmitter {
4381
4457
  * Inject CSS styles.
4382
4458
  */
4383
4459
  injectCSS() {
4384
- if (this.options.injectCSS && document) {
4460
+ if (this.options.injectCSS && typeof document !== "undefined") {
4385
4461
  this.css = createStyleTag(style, this.options.injectNonce);
4386
4462
  }
4387
4463
  }
@@ -4395,7 +4471,7 @@ var Editor = class extends EventEmitter {
4395
4471
  ...this.options,
4396
4472
  ...options
4397
4473
  };
4398
- if (!this.view || !this.state || this.isDestroyed) {
4474
+ if (!this.editorView || !this.state || this.isDestroyed) {
4399
4475
  return;
4400
4476
  }
4401
4477
  if (this.options.editorProps) {
@@ -4418,11 +4494,50 @@ var Editor = class extends EventEmitter {
4418
4494
  get isEditable() {
4419
4495
  return this.options.editable && this.view && this.view.editable;
4420
4496
  }
4497
+ /**
4498
+ * Returns the editor state.
4499
+ */
4500
+ get view() {
4501
+ if (this.editorView) {
4502
+ return this.editorView;
4503
+ }
4504
+ return new Proxy(
4505
+ {
4506
+ state: this.editorState,
4507
+ updateState: (state) => {
4508
+ this.editorState = state;
4509
+ },
4510
+ dispatch: (tr) => {
4511
+ this.editorState = this.state.apply(tr);
4512
+ },
4513
+ // Stub some commonly accessed properties to prevent errors
4514
+ composing: false,
4515
+ dragging: null,
4516
+ editable: true
4517
+ },
4518
+ {
4519
+ get: (obj, key) => {
4520
+ if (key === "state") {
4521
+ return this.editorState;
4522
+ }
4523
+ if (key in obj) {
4524
+ return Reflect.get(obj, key);
4525
+ }
4526
+ throw new Error(
4527
+ `[tiptap error]: The editor view is not available. Cannot access view['${key}']. The editor may not be mounted yet.`
4528
+ );
4529
+ }
4530
+ }
4531
+ );
4532
+ }
4421
4533
  /**
4422
4534
  * Returns the editor state.
4423
4535
  */
4424
4536
  get state() {
4425
- return this.view.state;
4537
+ if (this.editorView) {
4538
+ this.editorState = this.view.state;
4539
+ }
4540
+ return this.editorState;
4426
4541
  }
4427
4542
  /**
4428
4543
  * Register a ProseMirror plugin.
@@ -4477,7 +4592,8 @@ var Editor = class extends EventEmitter {
4477
4592
  Keymap,
4478
4593
  Tabindex,
4479
4594
  Drop,
4480
- Paste
4595
+ Paste,
4596
+ Delete
4481
4597
  ].filter((ext) => {
4482
4598
  if (typeof this.options.enableCoreExtensions === "object") {
4483
4599
  return this.options.enableCoreExtensions[ext.name] !== false;
@@ -4504,10 +4620,9 @@ var Editor = class extends EventEmitter {
4504
4620
  this.schema = this.extensionManager.schema;
4505
4621
  }
4506
4622
  /**
4507
- * Creates a ProseMirror view.
4623
+ * Creates the initial document.
4508
4624
  */
4509
- createView() {
4510
- var _a;
4625
+ createDoc() {
4511
4626
  let doc;
4512
4627
  try {
4513
4628
  doc = createDocument(this.options.content, this.schema, this.options.parseOptions, {
@@ -4521,7 +4636,8 @@ var Editor = class extends EventEmitter {
4521
4636
  editor: this,
4522
4637
  error: e,
4523
4638
  disableCollaboration: () => {
4524
- if (this.storage.collaboration) {
4639
+ if ("collaboration" in this.storage && typeof this.storage.collaboration === "object" && this.storage.collaboration) {
4640
+ ;
4525
4641
  this.storage.collaboration.isDisabled = true;
4526
4642
  }
4527
4643
  this.options.extensions = this.options.extensions.filter((extension) => extension.name !== "collaboration");
@@ -4532,8 +4648,14 @@ var Editor = class extends EventEmitter {
4532
4648
  errorOnInvalidContent: false
4533
4649
  });
4534
4650
  }
4535
- const selection = resolveFocusPosition(doc, this.options.autofocus);
4536
- this.view = new import_view.EditorView(this.options.element, {
4651
+ return doc;
4652
+ }
4653
+ /**
4654
+ * Creates a ProseMirror view.
4655
+ */
4656
+ createView(element) {
4657
+ var _a;
4658
+ this.editorView = new import_view.EditorView(element, {
4537
4659
  ...this.options.editorProps,
4538
4660
  attributes: {
4539
4661
  // add `role="textbox"` to the editor element
@@ -4541,10 +4663,7 @@ var Editor = class extends EventEmitter {
4541
4663
  ...(_a = this.options.editorProps) == null ? void 0 : _a.attributes
4542
4664
  },
4543
4665
  dispatchTransaction: this.dispatchTransaction.bind(this),
4544
- state: import_state21.EditorState.create({
4545
- doc,
4546
- selection: selection || void 0
4547
- })
4666
+ state: this.editorState
4548
4667
  });
4549
4668
  const newState = this.state.reconfigure({
4550
4669
  plugins: this.extensionManager.plugins
@@ -4552,6 +4671,7 @@ var Editor = class extends EventEmitter {
4552
4671
  this.view.updateState(newState);
4553
4672
  this.createNodeViews();
4554
4673
  this.prependClass();
4674
+ this.injectCSS();
4555
4675
  const dom = this.view.dom;
4556
4676
  dom.editor = this;
4557
4677
  }
@@ -4563,6 +4683,7 @@ var Editor = class extends EventEmitter {
4563
4683
  return;
4564
4684
  }
4565
4685
  this.view.setProps({
4686
+ markViews: this.extensionManager.markViews,
4566
4687
  nodeViews: this.extensionManager.nodeViews
4567
4688
  });
4568
4689
  }
@@ -4699,12 +4820,12 @@ var Editor = class extends EventEmitter {
4699
4820
  */
4700
4821
  destroy() {
4701
4822
  this.emit("destroy");
4702
- if (this.view) {
4703
- const dom = this.view.dom;
4823
+ if (this.editorView) {
4824
+ const dom = this.editorView.dom;
4704
4825
  if (dom && dom.editor) {
4705
4826
  delete dom.editor;
4706
4827
  }
4707
- this.view.destroy();
4828
+ this.editorView.destroy();
4708
4829
  }
4709
4830
  this.removeAllListeners();
4710
4831
  }
@@ -4838,7 +4959,7 @@ function textInputRule(config) {
4838
4959
  }
4839
4960
 
4840
4961
  // src/inputRules/wrappingInputRule.ts
4841
- var import_transform9 = require("@tiptap/pm/transform");
4962
+ var import_transform10 = require("@tiptap/pm/transform");
4842
4963
  function wrappingInputRule(config) {
4843
4964
  return new InputRule({
4844
4965
  find: config.find,
@@ -4847,7 +4968,7 @@ function wrappingInputRule(config) {
4847
4968
  const tr = state.tr.delete(range.from, range.to);
4848
4969
  const $start = tr.doc.resolve(range.from);
4849
4970
  const blockRange = $start.blockRange();
4850
- const wrapping = blockRange && (0, import_transform9.findWrapping)(blockRange, config.type, attributes);
4971
+ const wrapping = blockRange && (0, import_transform10.findWrapping)(blockRange, config.type, attributes);
4851
4972
  if (!wrapping) {
4852
4973
  return null;
4853
4974
  }
@@ -4866,97 +4987,95 @@ function wrappingInputRule(config) {
4866
4987
  chain().updateAttributes(nodeType, attributes).run();
4867
4988
  }
4868
4989
  const before = tr.doc.resolve(range.from - 1).nodeBefore;
4869
- if (before && before.type === config.type && (0, import_transform9.canJoin)(tr.doc, range.from - 1) && (!config.joinPredicate || config.joinPredicate(match, before))) {
4990
+ if (before && before.type === config.type && (0, import_transform10.canJoin)(tr.doc, range.from - 1) && (!config.joinPredicate || config.joinPredicate(match, before))) {
4870
4991
  tr.join(range.from - 1);
4871
4992
  }
4872
4993
  }
4873
4994
  });
4874
4995
  }
4875
4996
 
4876
- // src/Node.ts
4877
- var Node3 = class _Node {
4878
- constructor(config = {}) {
4879
- this.type = "node";
4880
- this.name = "node";
4881
- this.parent = null;
4882
- this.child = null;
4883
- this.config = {
4884
- name: this.name,
4885
- defaultOptions: {}
4886
- };
4887
- this.config = {
4888
- ...this.config,
4889
- ...config
4890
- };
4891
- this.name = this.config.name;
4892
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
4893
- console.warn(
4894
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
4895
- );
4997
+ // src/jsx-runtime.ts
4998
+ function Fragment7(props) {
4999
+ return props.children;
5000
+ }
5001
+ var h = (tag, attributes) => {
5002
+ if (tag === "slot") {
5003
+ return 0;
5004
+ }
5005
+ if (tag instanceof Function) {
5006
+ return tag(attributes);
5007
+ }
5008
+ const { children, ...rest } = attributes != null ? attributes : {};
5009
+ if (tag === "svg") {
5010
+ throw new Error("SVG elements are not supported in the JSX syntax, use the array syntax instead");
5011
+ }
5012
+ return [tag, rest, children];
5013
+ };
5014
+
5015
+ // src/utilities/escapeForRegEx.ts
5016
+ function escapeForRegEx(string) {
5017
+ return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
5018
+ }
5019
+
5020
+ // src/utilities/isString.ts
5021
+ function isString(value) {
5022
+ return typeof value === "string";
5023
+ }
5024
+
5025
+ // src/MarkView.ts
5026
+ var MarkView = class {
5027
+ constructor(component, props, options) {
5028
+ this.component = component;
5029
+ this.editor = props.editor;
5030
+ this.options = { ...options };
5031
+ this.mark = props.mark;
5032
+ this.HTMLAttributes = props.HTMLAttributes;
5033
+ }
5034
+ get dom() {
5035
+ return this.editor.view.dom;
5036
+ }
5037
+ get contentDOM() {
5038
+ return null;
5039
+ }
5040
+ ignoreMutation(mutation) {
5041
+ if (!this.dom || !this.contentDOM) {
5042
+ return true;
4896
5043
  }
4897
- this.options = this.config.defaultOptions;
4898
- if (this.config.addOptions) {
4899
- this.options = callOrReturn(
4900
- getExtensionField(this, "addOptions", {
4901
- name: this.name
4902
- })
4903
- );
5044
+ if (typeof this.options.ignoreMutation === "function") {
5045
+ return this.options.ignoreMutation({ mutation });
4904
5046
  }
4905
- this.storage = callOrReturn(
4906
- getExtensionField(this, "addStorage", {
4907
- name: this.name,
4908
- options: this.options
4909
- })
4910
- ) || {};
5047
+ if (mutation.type === "selection") {
5048
+ return false;
5049
+ }
5050
+ if (this.dom.contains(mutation.target) && mutation.type === "childList" && (isiOS() || isAndroid()) && this.editor.isFocused) {
5051
+ const changedNodes = [...Array.from(mutation.addedNodes), ...Array.from(mutation.removedNodes)];
5052
+ if (changedNodes.every((node) => node.isContentEditable)) {
5053
+ return false;
5054
+ }
5055
+ }
5056
+ if (this.contentDOM === mutation.target && mutation.type === "attributes") {
5057
+ return true;
5058
+ }
5059
+ if (this.contentDOM.contains(mutation.target)) {
5060
+ return false;
5061
+ }
5062
+ return true;
5063
+ }
5064
+ };
5065
+
5066
+ // src/Node.ts
5067
+ var Node3 = class _Node extends Extendable {
5068
+ constructor() {
5069
+ super(...arguments);
5070
+ this.type = "node";
4911
5071
  }
4912
5072
  static create(config = {}) {
4913
5073
  return new _Node(config);
4914
5074
  }
4915
- configure(options = {}) {
4916
- const extension = this.extend({
4917
- ...this.config,
4918
- addOptions: () => {
4919
- return mergeDeep(this.options, options);
4920
- }
4921
- });
4922
- extension.name = this.name;
4923
- extension.parent = this.parent;
4924
- return extension;
4925
- }
4926
- extend(extendedConfig = {}) {
4927
- const extension = new _Node(extendedConfig);
4928
- extension.parent = this;
4929
- this.child = extension;
4930
- extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
4931
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
4932
- console.warn(
4933
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
4934
- );
4935
- }
4936
- extension.options = callOrReturn(
4937
- getExtensionField(extension, "addOptions", {
4938
- name: extension.name
4939
- })
4940
- );
4941
- extension.storage = callOrReturn(
4942
- getExtensionField(extension, "addStorage", {
4943
- name: extension.name,
4944
- options: extension.options
4945
- })
4946
- );
4947
- return extension;
4948
- }
4949
5075
  };
4950
5076
 
4951
5077
  // src/NodeView.ts
4952
5078
  var import_state22 = require("@tiptap/pm/state");
4953
-
4954
- // src/utilities/isAndroid.ts
4955
- function isAndroid() {
4956
- return navigator.platform === "Android" || /android/i.test(navigator.userAgent);
4957
- }
4958
-
4959
- // src/NodeView.ts
4960
5079
  var NodeView = class {
4961
5080
  constructor(component, props, options) {
4962
5081
  this.isDragging = false;
@@ -5178,16 +5297,6 @@ function markPasteRule(config) {
5178
5297
  });
5179
5298
  }
5180
5299
 
5181
- // src/utilities/escapeForRegEx.ts
5182
- function escapeForRegEx(string) {
5183
- return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
5184
- }
5185
-
5186
- // src/utilities/isString.ts
5187
- function isString(value) {
5188
- return typeof value === "string";
5189
- }
5190
-
5191
5300
  // src/pasteRules/nodePasteRule.ts
5192
5301
  function nodePasteRule(config) {
5193
5302
  return new PasteRule({
@@ -5258,8 +5367,10 @@ var Tracker = class {
5258
5367
  CommandManager,
5259
5368
  Editor,
5260
5369
  Extension,
5370
+ Fragment,
5261
5371
  InputRule,
5262
5372
  Mark,
5373
+ MarkView,
5263
5374
  Node,
5264
5375
  NodePos,
5265
5376
  NodeView,
@@ -5269,6 +5380,7 @@ var Tracker = class {
5269
5380
  combineTransactionSteps,
5270
5381
  createChainableState,
5271
5382
  createDocument,
5383
+ createElement,
5272
5384
  createNodeFromContent,
5273
5385
  createStyleTag,
5274
5386
  defaultBlockAt,
@@ -5309,9 +5421,11 @@ var Tracker = class {
5309
5421
  getTextBetween,
5310
5422
  getTextContentFromNodes,
5311
5423
  getTextSerializersFromSchema,
5424
+ h,
5312
5425
  injectExtensionAttributesToParseRule,
5313
5426
  inputRulesPlugin,
5314
5427
  isActive,
5428
+ isAndroid,
5315
5429
  isAtEndOfNode,
5316
5430
  isAtStartOfNode,
5317
5431
  isEmptyObject,