@tiptap/core 2.0.0-beta.180 → 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.
@@ -105,13 +105,13 @@ class CommandManager {
105
105
  }
106
106
  createCan(startTr) {
107
107
  const { rawCommands, state } = this;
108
- const dispatch = undefined;
108
+ const dispatch = false;
109
109
  const tr = startTr || state.tr;
110
110
  const props = this.buildProps(tr, dispatch);
111
111
  const formattedCommands = Object.fromEntries(Object
112
112
  .entries(rawCommands)
113
113
  .map(([name, command]) => {
114
- return [name, (...args) => command(...args)({ ...props, dispatch })];
114
+ return [name, (...args) => command(...args)({ ...props, dispatch: undefined })];
115
115
  }));
116
116
  return {
117
117
  ...formattedCommands,
@@ -542,10 +542,10 @@ function isExtensionRulesEnabled(extension, enabled) {
542
542
  const getTextContentFromNodes = ($from, maxMatch = 500) => {
543
543
  let textBefore = '';
544
544
  $from.parent.nodesBetween(Math.max(0, $from.parentOffset - maxMatch), $from.parentOffset, (node, pos, parent, index) => {
545
- var _a, _b;
545
+ var _a, _b, _c;
546
546
  textBefore += ((_b = (_a = node.type.spec).toText) === null || _b === void 0 ? void 0 : _b.call(_a, {
547
547
  node, pos, parent, index,
548
- })) || node.textContent || '%leaf%';
548
+ })) || ((_c = $from.nodeBefore) === null || _c === void 0 ? void 0 : _c.text) || '%leaf%';
549
549
  });
550
550
  return textBefore;
551
551
  };
@@ -858,7 +858,7 @@ function pasteRulesPlugin(props) {
858
858
  editor,
859
859
  state: chainableState,
860
860
  from: Math.max(from - 1, 0),
861
- to: to.b,
861
+ to: to.b - 1,
862
862
  rule,
863
863
  });
864
864
  // stop if there are no changes
@@ -1016,15 +1016,21 @@ class ExtensionManager {
1016
1016
  };
1017
1017
  const plugins = [];
1018
1018
  const addKeyboardShortcuts = getExtensionField(extension, 'addKeyboardShortcuts', context);
1019
+ let defaultBindings = {};
1020
+ // bind exit handling
1021
+ if (extension.type === 'mark' && extension.config.exitable) {
1022
+ defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension });
1023
+ }
1019
1024
  if (addKeyboardShortcuts) {
1020
1025
  const bindings = Object.fromEntries(Object
1021
1026
  .entries(addKeyboardShortcuts())
1022
1027
  .map(([shortcut, method]) => {
1023
1028
  return [shortcut, () => method({ editor })];
1024
1029
  }));
1025
- const keyMapPlugin = keymap(bindings);
1026
- plugins.push(keyMapPlugin);
1030
+ defaultBindings = { ...defaultBindings, ...bindings };
1027
1031
  }
1032
+ const keyMapPlugin = keymap(defaultBindings);
1033
+ plugins.push(keyMapPlugin);
1028
1034
  const addInputRules = getExtensionField(extension, 'addInputRules', context);
1029
1035
  if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
1030
1036
  inputRules.push(...addInputRules());
@@ -1447,23 +1453,8 @@ const first = commands => props => {
1447
1453
  return false;
1448
1454
  };
1449
1455
 
1450
- function isClass(value) {
1451
- var _a;
1452
- if (((_a = value.constructor) === null || _a === void 0 ? void 0 : _a.toString().substring(0, 5)) !== 'class') {
1453
- return false;
1454
- }
1455
- return true;
1456
- }
1457
-
1458
- function isObject(value) {
1459
- return (value
1460
- && typeof value === 'object'
1461
- && !Array.isArray(value)
1462
- && !isClass(value));
1463
- }
1464
-
1465
1456
  function isTextSelection(value) {
1466
- return isObject(value) && value instanceof TextSelection;
1457
+ return value instanceof TextSelection;
1467
1458
  }
1468
1459
 
1469
1460
  function minMax(value = 0, min = 0, max = 0) {
@@ -1533,7 +1524,9 @@ const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch,
1533
1524
  delayedFocus();
1534
1525
  return true;
1535
1526
  }
1536
- const selection = resolveFocusPosition(editor.state.doc, position) || editor.state.selection;
1527
+ // pass through tr.doc instead of editor.state.doc
1528
+ // since transactions could change the editors state before this command has been run
1529
+ const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
1537
1530
  const isSameSelection = editor.state.selection.eq(selection);
1538
1531
  if (dispatch) {
1539
1532
  if (!isSameSelection) {
@@ -1932,10 +1925,8 @@ function createDocument(content, schema, parseOptions = {}) {
1932
1925
  const setContent = (content, emitUpdate = false, parseOptions = {}) => ({ tr, editor, dispatch }) => {
1933
1926
  const { doc } = tr;
1934
1927
  const document = createDocument(content, editor.schema, parseOptions);
1935
- const selection = TextSelection.create(doc, 0, doc.content.size);
1936
1928
  if (dispatch) {
1937
- tr.setSelection(selection)
1938
- .replaceSelectionWith(document, false)
1929
+ tr.replaceWith(0, doc.content.size, document)
1939
1930
  .setMeta('preventUpdate', !emitUpdate);
1940
1931
  }
1941
1932
  return true;
@@ -2036,10 +2027,8 @@ const setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) =>
2036
2027
  const setNodeSelection = position => ({ tr, dispatch }) => {
2037
2028
  if (dispatch) {
2038
2029
  const { doc } = tr;
2039
- const minPos = Selection.atStart(doc).from;
2040
- const maxPos = Selection.atEnd(doc).to;
2041
- const resolvedPos = minMax(position, minPos, maxPos);
2042
- const selection = NodeSelection.create(doc, resolvedPos);
2030
+ const from = minMax(position, 0, doc.content.size);
2031
+ const selection = NodeSelection.create(doc, from);
2043
2032
  tr.setSelection(selection);
2044
2033
  }
2045
2034
  return true;
@@ -2066,6 +2055,16 @@ const sinkListItem = typeOrName => ({ state, dispatch }) => {
2066
2055
  return sinkListItem$1(type)(state, dispatch);
2067
2056
  };
2068
2057
 
2058
+ function defaultBlockAt(match) {
2059
+ for (let i = 0; i < match.edgeCount; i += 1) {
2060
+ const { type } = match.edge(i);
2061
+ if (type.isTextblock && !type.hasRequiredAttrs()) {
2062
+ return type;
2063
+ }
2064
+ }
2065
+ return null;
2066
+ }
2067
+
2069
2068
  function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2070
2069
  return Object.fromEntries(Object
2071
2070
  .entries(attributes)
@@ -2080,15 +2079,6 @@ function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2080
2079
  }));
2081
2080
  }
2082
2081
 
2083
- function defaultBlockAt$1(match) {
2084
- for (let i = 0; i < match.edgeCount; i += 1) {
2085
- const { type } = match.edge(i);
2086
- if (type.isTextblock && !type.hasRequiredAttrs()) {
2087
- return type;
2088
- }
2089
- }
2090
- return null;
2091
- }
2092
2082
  function ensureMarks(state, splittableMarks) {
2093
2083
  const marks = state.storedMarks
2094
2084
  || (state.selection.$to.parentOffset && state.selection.$from.marks());
@@ -2124,7 +2114,7 @@ const splitBlock = ({ keepMarks = true } = {}) => ({ tr, state, dispatch, editor
2124
2114
  }
2125
2115
  const deflt = $from.depth === 0
2126
2116
  ? undefined
2127
- : defaultBlockAt$1($from.node(-1).contentMatchAt($from.indexAfter(-1)));
2117
+ : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
2128
2118
  let types = atEnd && deflt
2129
2119
  ? [{
2130
2120
  type: deflt,
@@ -3089,6 +3079,7 @@ class Editor extends EventEmitter {
3089
3079
  */
3090
3080
  setEditable(editable) {
3091
3081
  this.setOptions({ editable });
3082
+ this.emit('update', { editor: this, transaction: this.state.tr });
3092
3083
  }
3093
3084
  /**
3094
3085
  * Returns whether the editor is editable.
@@ -3346,16 +3337,6 @@ function combineTransactionSteps(oldDoc, transactions) {
3346
3337
  return transform;
3347
3338
  }
3348
3339
 
3349
- function defaultBlockAt(match) {
3350
- for (let i = 0; i < match.edgeCount; i += 1) {
3351
- const { type } = match.edge(i);
3352
- if (type.isTextblock && !type.hasRequiredAttrs()) {
3353
- return type;
3354
- }
3355
- }
3356
- return null;
3357
- }
3358
-
3359
3340
  function findChildren(node, predicate) {
3360
3341
  const nodesWithPos = [];
3361
3342
  node.descendants((child, pos) => {
@@ -3573,7 +3554,7 @@ function getMarksBetween(from, to, doc) {
3573
3554
  }
3574
3555
 
3575
3556
  function isNodeSelection(value) {
3576
- return isObject(value) && value instanceof NodeSelection;
3557
+ return value instanceof NodeSelection;
3577
3558
  }
3578
3559
 
3579
3560
  function posToDOMRect(view, from, to) {
@@ -3834,6 +3815,26 @@ class Mark {
3834
3815
  }));
3835
3816
  return extension;
3836
3817
  }
3818
+ static handleExit({ editor, mark, }) {
3819
+ const { tr } = editor.state;
3820
+ const currentPos = editor.state.selection.$from;
3821
+ const isAtEnd = currentPos.pos === currentPos.end();
3822
+ if (isAtEnd) {
3823
+ const currentMarks = currentPos.marks();
3824
+ const isInMark = !!currentMarks.find(m => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
3825
+ if (!isInMark) {
3826
+ return false;
3827
+ }
3828
+ const removeMark = currentMarks.find(m => (m === null || m === void 0 ? void 0 : m.type.name) === mark.name);
3829
+ if (removeMark) {
3830
+ tr.removeStoredMark(removeMark);
3831
+ }
3832
+ tr.insertText(' ', currentPos.pos);
3833
+ editor.view.dispatch(tr);
3834
+ return true;
3835
+ }
3836
+ return false;
3837
+ }
3837
3838
  }
3838
3839
 
3839
3840
  class Node {
@@ -4132,6 +4133,35 @@ function markPasteRule(config) {
4132
4133
  });
4133
4134
  }
4134
4135
 
4136
+ // source: https://stackoverflow.com/a/6969486
4137
+ function escapeForRegEx(string) {
4138
+ return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
4139
+ }
4140
+
4141
+ /**
4142
+ * Build an paste rule that adds a node when the
4143
+ * matched text is pasted into it.
4144
+ */
4145
+ function nodePasteRule(config) {
4146
+ return new PasteRule({
4147
+ find: config.find,
4148
+ handler({ match, chain, range }) {
4149
+ const attributes = callOrReturn(config.getAttributes, undefined, match);
4150
+ if (attributes === false || attributes === null) {
4151
+ return null;
4152
+ }
4153
+ if (match.input) {
4154
+ chain()
4155
+ .deleteRange(range)
4156
+ .insertContent({
4157
+ type: config.type.name,
4158
+ attrs: attributes,
4159
+ });
4160
+ }
4161
+ },
4162
+ });
4163
+ }
4164
+
4135
4165
  /**
4136
4166
  * Build an paste rule that replaces text when the
4137
4167
  * matched text is pasted into it.
@@ -4183,10 +4213,5 @@ class Tracker {
4183
4213
  }
4184
4214
  }
4185
4215
 
4186
- // source: https://stackoverflow.com/a/6969486
4187
- function escapeForRegEx(string) {
4188
- return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
4189
- }
4190
-
4191
- export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, defaultBlockAt, escapeForRegEx, extensions, findChildren, findChildrenInRange, findParentNode, findParentNodeClosestToPos, generateHTML, generateJSON, generateText, getAttributes, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAttributes, getNodeType, getSchema, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, inputRulesPlugin, isActive, isList, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isTextSelection, markInputRule, markPasteRule, mergeAttributes, nodeInputRule, pasteRulesPlugin, posToDOMRect, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
4216
+ export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, defaultBlockAt, escapeForRegEx, extensions, findChildren, findChildrenInRange, findParentNode, findParentNodeClosestToPos, generateHTML, generateJSON, generateText, getAttributes, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAttributes, getNodeType, getSchema, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, inputRulesPlugin, isActive, isList, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isTextSelection, markInputRule, markPasteRule, mergeAttributes, nodeInputRule, nodePasteRule, pasteRulesPlugin, posToDOMRect, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
4192
4217
  //# sourceMappingURL=tiptap-core.esm.js.map