@tiptap/core 2.5.0-beta.3 → 2.5.0-beta.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.js CHANGED
@@ -464,6 +464,7 @@ function getSchemaByResolvedExtensions(extensions, editor) {
464
464
  selectable: callOrReturn(getExtensionField(extension, 'selectable', context)),
465
465
  draggable: callOrReturn(getExtensionField(extension, 'draggable', context)),
466
466
  code: callOrReturn(getExtensionField(extension, 'code', context)),
467
+ whitespace: callOrReturn(getExtensionField(extension, 'whitespace', context)),
467
468
  defining: callOrReturn(getExtensionField(extension, 'defining', context)),
468
469
  isolating: callOrReturn(getExtensionField(extension, 'isolating', context)),
469
470
  attrs: Object.fromEntries(extensionAttributes.map(extensionAttribute => {
@@ -1081,7 +1082,7 @@ class ExtensionManager {
1081
1082
  const addKeyboardShortcuts = getExtensionField(extension, 'addKeyboardShortcuts', context);
1082
1083
  let defaultBindings = {};
1083
1084
  // bind exit handling
1084
- if (extension.type === 'mark' && extension.config.exitable) {
1085
+ if (extension.type === 'mark' && getExtensionField(extension, 'exitable', context)) {
1085
1086
  defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension });
1086
1087
  }
1087
1088
  if (addKeyboardShortcuts) {
@@ -1287,13 +1288,17 @@ class Extension {
1287
1288
  configure(options = {}) {
1288
1289
  // return a new instance so we can use the same extension
1289
1290
  // with different calls of `configure`
1290
- const extension = this.extend();
1291
+ const extension = this.extend({
1292
+ ...this.config,
1293
+ addOptions() {
1294
+ var _a;
1295
+ return mergeDeep(((_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this)) || {}, options);
1296
+ },
1297
+ });
1298
+ // Always preserve the current name
1299
+ extension.name = this.name;
1300
+ // Set the parent to be our parent
1291
1301
  extension.parent = this.parent;
1292
- extension.options = mergeDeep(this.options, options);
1293
- extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
1294
- name: extension.name,
1295
- options: extension.options,
1296
- }));
1297
1302
  return extension;
1298
1303
  }
1299
1304
  extend(extendedConfig = {}) {
@@ -1301,7 +1306,7 @@ class Extension {
1301
1306
  extension.parent = this;
1302
1307
  this.child = extension;
1303
1308
  extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
1304
- if (extendedConfig.defaultOptions) {
1309
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
1305
1310
  console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
1306
1311
  }
1307
1312
  extension.options = callOrReturn(getExtensionField(extension, 'addOptions', {
@@ -1775,6 +1780,7 @@ function createNodeFromContent(content, schema, options) {
1775
1780
  if (isTextContent) {
1776
1781
  let schemaToUse = schema;
1777
1782
  let hasInvalidContent = false;
1783
+ let invalidContent = '';
1778
1784
  // Only ever check for invalid content if we're supposed to throw an error
1779
1785
  if (options.errorOnInvalidContent) {
1780
1786
  schemaToUse = new Schema({
@@ -1789,9 +1795,11 @@ function createNodeFromContent(content, schema, options) {
1789
1795
  parseDOM: [
1790
1796
  {
1791
1797
  tag: '*',
1792
- getAttrs: () => {
1798
+ getAttrs: e => {
1793
1799
  // If this is ever called, we know that the content has something that we don't know how to handle in the schema
1794
1800
  hasInvalidContent = true;
1801
+ // Try to stringify the element for a more helpful error message
1802
+ invalidContent = typeof e === 'string' ? e : e.outerHTML;
1795
1803
  return null;
1796
1804
  },
1797
1805
  },
@@ -1805,7 +1813,7 @@ function createNodeFromContent(content, schema, options) {
1805
1813
  ? parser.parseSlice(elementFromString(content), options.parseOptions).content
1806
1814
  : parser.parse(elementFromString(content), options.parseOptions);
1807
1815
  if (options.errorOnInvalidContent && hasInvalidContent) {
1808
- throw new Error('[tiptap error]: Invalid HTML content');
1816
+ throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) });
1809
1817
  }
1810
1818
  return response;
1811
1819
  }
@@ -1858,10 +1866,6 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1858
1866
  catch (e) {
1859
1867
  return false;
1860
1868
  }
1861
- // don’t dispatch an empty fragment because this can lead to strange errors
1862
- if (content.toString() === '<>') {
1863
- return true;
1864
- }
1865
1869
  let { from, to } = typeof position === 'number' ? { from: position, to: position } : { from: position.from, to: position.to };
1866
1870
  let isOnlyTextContent = true;
1867
1871
  let isOnlyBlockContent = true;
@@ -2231,22 +2235,27 @@ function createDocument(content, schema, parseOptions = {}, options = {}) {
2231
2235
  });
2232
2236
  }
2233
2237
 
2234
- const setContent = (content, emitUpdate = false, parseOptions = {}, options = {}) => ({ tr, editor, dispatch }) => {
2235
- var _a;
2238
+ const setContent = (content, emitUpdate = false, parseOptions = {}, options = {}) => ({ editor, tr, dispatch, commands, }) => {
2239
+ var _a, _b;
2236
2240
  const { doc } = tr;
2237
- let document;
2238
- try {
2239
- document = createDocument(content, editor.schema, parseOptions, {
2241
+ // This is to keep backward compatibility with the previous behavior
2242
+ // TODO remove this in the next major version
2243
+ if (parseOptions.preserveWhitespace !== 'full') {
2244
+ const document = createDocument(content, editor.schema, parseOptions, {
2240
2245
  errorOnInvalidContent: (_a = options.errorOnInvalidContent) !== null && _a !== void 0 ? _a : editor.options.enableContentCheck,
2241
2246
  });
2242
- }
2243
- catch (e) {
2244
- return false;
2247
+ if (dispatch) {
2248
+ tr.replaceWith(0, doc.content.size, document).setMeta('preventUpdate', !emitUpdate);
2249
+ }
2250
+ return true;
2245
2251
  }
2246
2252
  if (dispatch) {
2247
- tr.replaceWith(0, doc.content.size, document).setMeta('preventUpdate', !emitUpdate);
2253
+ tr.setMeta('preventUpdate', !emitUpdate);
2248
2254
  }
2249
- return true;
2255
+ return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
2256
+ parseOptions,
2257
+ errorOnInvalidContent: (_b = options.errorOnInvalidContent) !== null && _b !== void 0 ? _b : editor.options.enableContentCheck,
2258
+ });
2250
2259
  };
2251
2260
 
2252
2261
  function getMarkAttributes(state, typeOrName) {
@@ -3350,40 +3359,30 @@ const updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch
3350
3359
  markType = getMarkType(typeOrName, state.schema);
3351
3360
  }
3352
3361
  if (dispatch) {
3353
- let lastPos;
3354
- let lastNode;
3355
- let trimmedFrom;
3356
- let trimmedTo;
3357
- tr.selection.ranges.forEach((range) => {
3362
+ tr.selection.ranges.forEach(range => {
3358
3363
  const from = range.$from.pos;
3359
3364
  const to = range.$to.pos;
3360
3365
  state.doc.nodesBetween(from, to, (node, pos) => {
3361
3366
  if (nodeType && nodeType === node.type) {
3362
- trimmedFrom = Math.max(pos, from);
3363
- trimmedTo = Math.min(pos + node.nodeSize, to);
3364
- lastPos = pos;
3365
- lastNode = node;
3367
+ tr.setNodeMarkup(pos, undefined, {
3368
+ ...node.attrs,
3369
+ ...attributes,
3370
+ });
3371
+ }
3372
+ if (markType && node.marks.length) {
3373
+ node.marks.forEach(mark => {
3374
+ if (markType === mark.type) {
3375
+ const trimmedFrom = Math.max(pos, from);
3376
+ const trimmedTo = Math.min(pos + node.nodeSize, to);
3377
+ tr.addMark(trimmedFrom, trimmedTo, markType.create({
3378
+ ...mark.attrs,
3379
+ ...attributes,
3380
+ }));
3381
+ }
3382
+ });
3366
3383
  }
3367
3384
  });
3368
3385
  });
3369
- if (lastNode) {
3370
- if (lastPos !== undefined) {
3371
- tr.setNodeMarkup(lastPos, undefined, {
3372
- ...lastNode.attrs,
3373
- ...attributes,
3374
- });
3375
- }
3376
- if (markType && lastNode.marks.length) {
3377
- lastNode.marks.forEach((mark) => {
3378
- if (markType === mark.type) {
3379
- tr.addMark(trimmedFrom, trimmedTo, markType.create({
3380
- ...mark.attrs,
3381
- ...attributes,
3382
- }));
3383
- }
3384
- });
3385
- }
3386
- }
3387
3386
  }
3388
3387
  return true;
3389
3388
  };
@@ -3639,7 +3638,7 @@ const Tabindex = Extension.create({
3639
3638
  new Plugin({
3640
3639
  key: new PluginKey('tabindex'),
3641
3640
  props: {
3642
- attributes: this.editor.isEditable ? { tabindex: '0' } : {},
3641
+ attributes: () => (this.editor.isEditable ? { tabindex: '0' } : {}),
3643
3642
  },
3644
3643
  }),
3645
3644
  ];
@@ -4554,20 +4553,25 @@ class Mark {
4554
4553
  configure(options = {}) {
4555
4554
  // return a new instance so we can use the same extension
4556
4555
  // with different calls of `configure`
4557
- const extension = this.extend();
4558
- extension.options = mergeDeep(this.options, options);
4559
- extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
4560
- name: extension.name,
4561
- options: extension.options,
4562
- }));
4556
+ const extension = this.extend({
4557
+ ...this.config,
4558
+ addOptions() {
4559
+ var _a;
4560
+ return mergeDeep(((_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this)) || {}, options);
4561
+ },
4562
+ });
4563
+ // Always preserve the current name
4564
+ extension.name = this.name;
4565
+ // Set the parent to be our parent
4566
+ extension.parent = this.parent;
4563
4567
  return extension;
4564
4568
  }
4565
4569
  extend(extendedConfig = {}) {
4566
- const extension = new Mark({ ...this.config, ...extendedConfig });
4570
+ const extension = new Mark(extendedConfig);
4567
4571
  extension.parent = this;
4568
4572
  this.child = extension;
4569
4573
  extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
4570
- if (extendedConfig.defaultOptions) {
4574
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
4571
4575
  console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
4572
4576
  }
4573
4577
  extension.options = callOrReturn(getExtensionField(extension, 'addOptions', {
@@ -4641,20 +4645,25 @@ class Node {
4641
4645
  configure(options = {}) {
4642
4646
  // return a new instance so we can use the same extension
4643
4647
  // with different calls of `configure`
4644
- const extension = this.extend();
4645
- extension.options = mergeDeep(this.options, options);
4646
- extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
4647
- name: extension.name,
4648
- options: extension.options,
4649
- }));
4648
+ const extension = this.extend({
4649
+ ...this.config,
4650
+ addOptions() {
4651
+ var _a;
4652
+ return mergeDeep(((_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this)) || {}, options);
4653
+ },
4654
+ });
4655
+ // Always preserve the current name
4656
+ extension.name = this.name;
4657
+ // Set the parent to be our parent
4658
+ extension.parent = this.parent;
4650
4659
  return extension;
4651
4660
  }
4652
4661
  extend(extendedConfig = {}) {
4653
- const extension = new Node({ ...this.config, ...extendedConfig });
4662
+ const extension = new Node(extendedConfig);
4654
4663
  extension.parent = this;
4655
4664
  this.child = extension;
4656
4665
  extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
4657
- if (extendedConfig.defaultOptions) {
4666
+ if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
4658
4667
  console.warn(`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`);
4659
4668
  }
4660
4669
  extension.options = callOrReturn(getExtensionField(extension, 'addOptions', {