@tiptap/core 2.8.0 → 2.9.0

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
@@ -1668,12 +1668,16 @@ function getMarkRange($pos, type, attributes = {}) {
1668
1668
  return;
1669
1669
  }
1670
1670
  let start = $pos.parent.childAfter($pos.parentOffset);
1671
- if ($pos.parentOffset === start.offset && start.offset !== 0) {
1671
+ // If the cursor is at the start of a text node that does not have the mark, look backward
1672
+ if (!start.node || !start.node.marks.some(mark => mark.type === type)) {
1672
1673
  start = $pos.parent.childBefore($pos.parentOffset);
1673
1674
  }
1674
- if (!start.node) {
1675
+ // If there is no text node with the mark even backward, return undefined
1676
+ if (!start.node || !start.node.marks.some(mark => mark.type === type)) {
1675
1677
  return;
1676
1678
  }
1679
+ // We now know that the cursor is either at the start, middle or end of a text node with the specified mark
1680
+ // so we can look it up on the targeted mark
1677
1681
  const mark = findMarkInSet([...start.node.marks], type, attributes);
1678
1682
  if (!mark) {
1679
1683
  return;
@@ -1963,7 +1967,7 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1963
1967
  var _a;
1964
1968
  if (dispatch) {
1965
1969
  options = {
1966
- parseOptions: {},
1970
+ parseOptions: editor.options.parseOptions,
1967
1971
  updateSelection: true,
1968
1972
  applyInputRules: false,
1969
1973
  applyPasteRules: false,
@@ -1984,7 +1988,9 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1984
1988
  editor,
1985
1989
  error: e,
1986
1990
  disableCollaboration: () => {
1987
- console.error('[tiptap error]: Unable to disable collaboration at this point in time');
1991
+ if (editor.storage.collaboration) {
1992
+ editor.storage.collaboration.isDisabled = true;
1993
+ }
1988
1994
  },
1989
1995
  });
1990
1996
  return false;
@@ -3963,7 +3969,8 @@ class NodePos {
3963
3969
  const children = [];
3964
3970
  this.node.content.forEach((node, offset) => {
3965
3971
  const isBlock = node.isBlock && !node.isTextblock;
3966
- const targetPos = this.pos + offset + 1;
3972
+ const isNonTextAtom = node.isAtom && !node.isText;
3973
+ const targetPos = this.pos + offset + (isNonTextAtom ? 0 : 1);
3967
3974
  const $pos = this.resolvedPos.doc.resolve(targetPos);
3968
3975
  if (!isBlock && $pos.depth <= this.depth) {
3969
3976
  return;
@@ -4039,9 +4046,12 @@ class NodePos {
4039
4046
  return nodes;
4040
4047
  }
4041
4048
  setAttribute(attributes) {
4042
- const oldSelection = this.editor.state.selection;
4043
- this.editor.chain().setTextSelection(this.from).updateAttributes(this.node.type.name, attributes).setTextSelection(oldSelection.from)
4044
- .run();
4049
+ const { tr } = this.editor.state;
4050
+ tr.setNodeMarkup(this.from, undefined, {
4051
+ ...this.node.attrs,
4052
+ ...attributes,
4053
+ });
4054
+ this.editor.view.dispatch(tr);
4045
4055
  }
4046
4056
  }
4047
4057
 
@@ -4293,18 +4303,27 @@ class Editor extends EventEmitter {
4293
4303
  /**
4294
4304
  * Unregister a ProseMirror plugin.
4295
4305
  *
4296
- * @param nameOrPluginKey The plugins name
4306
+ * @param nameOrPluginKeyToRemove The plugins name
4297
4307
  * @returns The new editor state or undefined if the editor is destroyed
4298
4308
  */
4299
- unregisterPlugin(nameOrPluginKey) {
4309
+ unregisterPlugin(nameOrPluginKeyToRemove) {
4300
4310
  if (this.isDestroyed) {
4301
4311
  return undefined;
4302
4312
  }
4303
- // @ts-ignore
4304
- const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key;
4305
- const state = this.state.reconfigure({
4313
+ const prevPlugins = this.state.plugins;
4314
+ let plugins = prevPlugins;
4315
+ [].concat(nameOrPluginKeyToRemove).forEach(nameOrPluginKey => {
4316
+ // @ts-ignore
4317
+ const name = typeof nameOrPluginKey === 'string' ? `${nameOrPluginKey}$` : nameOrPluginKey.key;
4306
4318
  // @ts-ignore
4307
- plugins: this.state.plugins.filter(plugin => !plugin.key.startsWith(name)),
4319
+ plugins = prevPlugins.filter(plugin => !plugin.key.startsWith(name));
4320
+ });
4321
+ if (prevPlugins.length === plugins.length) {
4322
+ // No plugin was removed, so we don’t need to update the state
4323
+ return undefined;
4324
+ }
4325
+ const state = this.state.reconfigure({
4326
+ plugins,
4308
4327
  });
4309
4328
  this.view.updateState(state);
4310
4329
  return state;
@@ -4367,6 +4386,9 @@ class Editor extends EventEmitter {
4367
4386
  editor: this,
4368
4387
  error: e,
4369
4388
  disableCollaboration: () => {
4389
+ if (this.storage.collaboration) {
4390
+ this.storage.collaboration.isDisabled = true;
4391
+ }
4370
4392
  // To avoid syncing back invalid content, reinitialize the extensions without the collaboration extension
4371
4393
  this.options.extensions = this.options.extensions.filter(extension => extension.name !== 'collaboration');
4372
4394
  // Restart the initialization process by recreating the extension manager with the new set of extensions
@@ -4385,6 +4407,12 @@ class Editor extends EventEmitter {
4385
4407
  selection: selection || undefined,
4386
4408
  }),
4387
4409
  });
4410
+ // add `role="textbox"` to the editor element
4411
+ this.view.dom.setAttribute('role', 'textbox');
4412
+ // add aria-label to the editor element
4413
+ if (!this.view.dom.getAttribute('aria-label')) {
4414
+ this.view.dom.setAttribute('aria-label', 'Rich-Text Editor');
4415
+ }
4388
4416
  // `editor.view` is not yet available at this time.
4389
4417
  // Therefore we will add all plugins and node views directly afterwards.
4390
4418
  const newState = this.state.reconfigure({