@tiptap/core 2.0.0-beta.182 → 2.0.0-beta.183

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.
@@ -245,6 +245,10 @@ declare module '@tiptap/core' {
245
245
  storage: Storage;
246
246
  parent: ParentConfig<MarkConfig<Options, Storage>>['excludes'];
247
247
  }) => MarkSpec['excludes']);
248
+ /**
249
+ * Marks this Mark as exitable
250
+ */
251
+ exitable?: boolean | (() => boolean);
248
252
  /**
249
253
  * Group
250
254
  */
@@ -316,4 +320,8 @@ export declare class Mark<Options = any, Storage = any> {
316
320
  static create<O = any, S = any>(config?: Partial<MarkConfig<O, S>>): Mark<O, S>;
317
321
  configure(options?: Partial<Options>): Mark<Options, Storage>;
318
322
  extend<ExtendedOptions = Options, ExtendedStorage = Storage>(extendedConfig?: Partial<MarkConfig<ExtendedOptions, ExtendedStorage>>): Mark<ExtendedOptions, ExtendedStorage>;
323
+ static handleExit({ editor, mark, }: {
324
+ editor: Editor;
325
+ mark: Mark;
326
+ }): boolean;
319
327
  }
@@ -109,13 +109,13 @@ class CommandManager {
109
109
  }
110
110
  createCan(startTr) {
111
111
  const { rawCommands, state } = this;
112
- const dispatch = undefined;
112
+ const dispatch = false;
113
113
  const tr = startTr || state.tr;
114
114
  const props = this.buildProps(tr, dispatch);
115
115
  const formattedCommands = Object.fromEntries(Object
116
116
  .entries(rawCommands)
117
117
  .map(([name, command]) => {
118
- return [name, (...args) => command(...args)({ ...props, dispatch })];
118
+ return [name, (...args) => command(...args)({ ...props, dispatch: undefined })];
119
119
  }));
120
120
  return {
121
121
  ...formattedCommands,
@@ -862,7 +862,7 @@ function pasteRulesPlugin(props) {
862
862
  editor,
863
863
  state: chainableState,
864
864
  from: Math.max(from - 1, 0),
865
- to: to.b,
865
+ to: to.b - 1,
866
866
  rule,
867
867
  });
868
868
  // stop if there are no changes
@@ -1020,15 +1020,21 @@ class ExtensionManager {
1020
1020
  };
1021
1021
  const plugins = [];
1022
1022
  const addKeyboardShortcuts = getExtensionField(extension, 'addKeyboardShortcuts', context);
1023
+ let defaultBindings = {};
1024
+ // bind exit handling
1025
+ if (extension.type === 'mark' && extension.config.exitable) {
1026
+ defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension });
1027
+ }
1023
1028
  if (addKeyboardShortcuts) {
1024
1029
  const bindings = Object.fromEntries(Object
1025
1030
  .entries(addKeyboardShortcuts())
1026
1031
  .map(([shortcut, method]) => {
1027
1032
  return [shortcut, () => method({ editor })];
1028
1033
  }));
1029
- const keyMapPlugin = prosemirrorKeymap.keymap(bindings);
1030
- plugins.push(keyMapPlugin);
1034
+ defaultBindings = { ...defaultBindings, ...bindings };
1031
1035
  }
1036
+ const keyMapPlugin = prosemirrorKeymap.keymap(defaultBindings);
1037
+ plugins.push(keyMapPlugin);
1032
1038
  const addInputRules = getExtensionField(extension, 'addInputRules', context);
1033
1039
  if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
1034
1040
  inputRules.push(...addInputRules());
@@ -1451,23 +1457,8 @@ const first = commands => props => {
1451
1457
  return false;
1452
1458
  };
1453
1459
 
1454
- function isClass(value) {
1455
- var _a;
1456
- if (((_a = value.constructor) === null || _a === void 0 ? void 0 : _a.toString().substring(0, 5)) !== 'class') {
1457
- return false;
1458
- }
1459
- return true;
1460
- }
1461
-
1462
- function isObject(value) {
1463
- return (value
1464
- && typeof value === 'object'
1465
- && !Array.isArray(value)
1466
- && !isClass(value));
1467
- }
1468
-
1469
1460
  function isTextSelection(value) {
1470
- return isObject(value) && value instanceof prosemirrorState.TextSelection;
1461
+ return value instanceof prosemirrorState.TextSelection;
1471
1462
  }
1472
1463
 
1473
1464
  function minMax(value = 0, min = 0, max = 0) {
@@ -2040,10 +2031,8 @@ const setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) =>
2040
2031
  const setNodeSelection = position => ({ tr, dispatch }) => {
2041
2032
  if (dispatch) {
2042
2033
  const { doc } = tr;
2043
- const minPos = prosemirrorState.Selection.atStart(doc).from;
2044
- const maxPos = prosemirrorState.Selection.atEnd(doc).to;
2045
- const resolvedPos = minMax(position, minPos, maxPos);
2046
- const selection = prosemirrorState.NodeSelection.create(doc, resolvedPos);
2034
+ const from = minMax(position, 0, doc.content.size);
2035
+ const selection = prosemirrorState.NodeSelection.create(doc, from);
2047
2036
  tr.setSelection(selection);
2048
2037
  }
2049
2038
  return true;
@@ -2070,6 +2059,16 @@ const sinkListItem = typeOrName => ({ state, dispatch }) => {
2070
2059
  return prosemirrorSchemaList.sinkListItem(type)(state, dispatch);
2071
2060
  };
2072
2061
 
2062
+ function defaultBlockAt(match) {
2063
+ for (let i = 0; i < match.edgeCount; i += 1) {
2064
+ const { type } = match.edge(i);
2065
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
2066
+ return type;
2067
+ }
2068
+ }
2069
+ return null;
2070
+ }
2071
+
2073
2072
  function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2074
2073
  return Object.fromEntries(Object
2075
2074
  .entries(attributes)
@@ -2084,15 +2083,6 @@ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2084
2083
  }));
2085
2084
  }
2086
2085
 
2087
- function defaultBlockAt$1(match) {
2088
- for (let i = 0; i < match.edgeCount; i += 1) {
2089
- const { type } = match.edge(i);
2090
- if (type.isTextblock && !type.hasRequiredAttrs()) {
2091
- return type;
2092
- }
2093
- }
2094
- return null;
2095
- }
2096
2086
  function ensureMarks(state, splittableMarks) {
2097
2087
  const marks = state.storedMarks
2098
2088
  || (state.selection.$to.parentOffset && state.selection.$from.marks());
@@ -2128,7 +2118,7 @@ const splitBlock = ({ keepMarks = true } = {}) => ({ tr, state, dispatch, editor
2128
2118
  }
2129
2119
  const deflt = $from.depth === 0
2130
2120
  ? undefined
2131
- : defaultBlockAt$1($from.node(-1).contentMatchAt($from.indexAfter(-1)));
2121
+ : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
2132
2122
  let types = atEnd && deflt
2133
2123
  ? [{
2134
2124
  type: deflt,
@@ -3093,6 +3083,7 @@ class Editor extends EventEmitter {
3093
3083
  */
3094
3084
  setEditable(editable) {
3095
3085
  this.setOptions({ editable });
3086
+ this.emit('update', { editor: this, transaction: this.state.tr });
3096
3087
  }
3097
3088
  /**
3098
3089
  * Returns whether the editor is editable.
@@ -3350,16 +3341,6 @@ function combineTransactionSteps(oldDoc, transactions) {
3350
3341
  return transform;
3351
3342
  }
3352
3343
 
3353
- function defaultBlockAt(match) {
3354
- for (let i = 0; i < match.edgeCount; i += 1) {
3355
- const { type } = match.edge(i);
3356
- if (type.isTextblock && !type.hasRequiredAttrs()) {
3357
- return type;
3358
- }
3359
- }
3360
- return null;
3361
- }
3362
-
3363
3344
  function findChildren(node, predicate) {
3364
3345
  const nodesWithPos = [];
3365
3346
  node.descendants((child, pos) => {
@@ -3577,7 +3558,7 @@ function getMarksBetween(from, to, doc) {
3577
3558
  }
3578
3559
 
3579
3560
  function isNodeSelection(value) {
3580
- return isObject(value) && value instanceof prosemirrorState.NodeSelection;
3561
+ return value instanceof prosemirrorState.NodeSelection;
3581
3562
  }
3582
3563
 
3583
3564
  function posToDOMRect(view, from, to) {
@@ -3838,6 +3819,26 @@ class Mark {
3838
3819
  }));
3839
3820
  return extension;
3840
3821
  }
3822
+ static handleExit({ editor, mark, }) {
3823
+ const { tr } = editor.state;
3824
+ const currentPos = editor.state.selection.$from;
3825
+ const isAtEnd = currentPos.pos === currentPos.end();
3826
+ if (isAtEnd) {
3827
+ const currentMarks = currentPos.marks();
3828
+ const isInMark = !!currentMarks.find(m => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
3829
+ if (!isInMark) {
3830
+ return false;
3831
+ }
3832
+ const removeMark = currentMarks.find(m => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
3833
+ if (removeMark) {
3834
+ tr.removeStoredMark(removeMark);
3835
+ }
3836
+ tr.insertText(' ', currentPos.pos);
3837
+ editor.view.dispatch(tr);
3838
+ return true;
3839
+ }
3840
+ return false;
3841
+ }
3841
3842
  }
3842
3843
 
3843
3844
  class Node {