slate 0.47.4 → 0.47.8

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/lib/slate.es.js CHANGED
@@ -609,7 +609,7 @@ function transform(path, operation) {
609
609
  p = operation.path;
610
610
 
611
611
 
612
- if (type === 'add_mark' || type === 'insert_text' || type === 'remove_mark' || type === 'remove_text' || type === 'set_mark' || type === 'set_node' || type === 'set_selection' || type === 'set_value' || path.size === 0) {
612
+ if (type === 'add_mark' || type === 'insert_text' || type === 'remove_mark' || type === 'remove_text' || type === 'set_mark' || type === 'set_node' || type === 'set_selection' || type === 'set_value' || type === 'add_annotation' || type === 'remove_annotation' || type === 'set_annotation' || path.size === 0) {
613
613
  return List([path]);
614
614
  }
615
615
 
@@ -2757,7 +2757,7 @@ var Text = function (_Record) {
2757
2757
  }
2758
2758
 
2759
2759
  // If the range starts after the leaf, or ends before it, continue.
2760
- if (start.offset > offset + length || end.offset <= offset) {
2760
+ if (start.offset > offset + length || end.offset < offset || end.offset === offset && offset !== 0) {
2761
2761
  next.push(leaf);
2762
2762
  continue;
2763
2763
  }
@@ -3473,10 +3473,14 @@ var Value = function (_Record) {
3473
3473
  annotation = Annotation.create(annotation);
3474
3474
  var value = this;
3475
3475
  var _value = value,
3476
- annotations = _value.annotations;
3476
+ annotations = _value.annotations,
3477
+ document = _value.document;
3477
3478
  var _annotation = annotation,
3478
3479
  key = _annotation.key;
3479
3480
 
3481
+ annotation = annotation.updatePoints(function (point) {
3482
+ return point.normalize(document);
3483
+ });
3480
3484
  annotations = annotations.set(key, annotation);
3481
3485
  value = value.set('annotations', annotations);
3482
3486
  return value;
@@ -3709,16 +3713,16 @@ var Value = function (_Record) {
3709
3713
 
3710
3714
  value = value.mapRanges(function (range) {
3711
3715
  var _range = range,
3712
- start = _range.start,
3713
- end = _range.end;
3716
+ anchor = _range.anchor,
3717
+ focus = _range.focus;
3714
3718
 
3715
3719
 
3716
- if (node.hasNode(start.key)) {
3717
- range = prev ? range.moveStartTo(prev.key, prev.text.length) : next ? range.moveStartTo(next.key, 0) : range.unset();
3720
+ if (node.hasNode(anchor.key)) {
3721
+ range = prev ? range.moveAnchorTo(prev.key, prev.text.length) : next ? range.moveAnchorTo(next.key, 0) : range.unset();
3718
3722
  }
3719
3723
 
3720
- if (node.hasNode(end.key)) {
3721
- range = prev ? range.moveEndTo(prev.key, prev.text.length) : next ? range.moveEndTo(next.key, 0) : range.unset();
3724
+ if (node.hasNode(focus.key)) {
3725
+ range = prev ? range.moveFocusTo(prev.key, prev.text.length) : next ? range.moveFocusTo(next.key, 0) : range.unset();
3722
3726
  }
3723
3727
 
3724
3728
  range = range.updatePoints(function (point) {
@@ -3918,18 +3922,18 @@ var Value = function (_Record) {
3918
3922
  value = value.mapRanges(function (range) {
3919
3923
  var next = newDocument.getNextText(node.key);
3920
3924
  var _range2 = range,
3921
- start = _range2.start,
3922
- end = _range2.end;
3925
+ anchor = _range2.anchor,
3926
+ focus = _range2.focus;
3923
3927
 
3924
- // If the start was after the split, move it to the next node.
3928
+ // If the anchor was after the split, move it to the next node.
3925
3929
 
3926
- if (node.key === start.key && position <= start.offset) {
3927
- range = range.moveStartTo(next.key, start.offset - position);
3930
+ if (node.key === anchor.key && position <= anchor.offset) {
3931
+ range = range.moveAnchorTo(next.key, anchor.offset - position);
3928
3932
  }
3929
3933
 
3930
- // If the end was after the split, move it to the next node.
3931
- if (node.key === end.key && position <= end.offset) {
3932
- range = range.moveEndTo(next.key, end.offset - position);
3934
+ // If the focus was after the split, move it to the next node.
3935
+ if (node.key === focus.key && position <= focus.offset) {
3936
+ range = range.moveFocusTo(next.key, focus.offset - position);
3933
3937
  }
3934
3938
 
3935
3939
  range = range.updatePoints(function (point) {
@@ -4368,7 +4372,7 @@ var Value = function (_Record) {
4368
4372
 
4369
4373
  if (isPlainObject(a)) {
4370
4374
  var p = {};
4371
- if ('annotations' in a) p.annotations = Annotation.createList(a.annotations);
4375
+ if ('annotations' in a) p.annotations = Annotation.createMap(a.annotations);
4372
4376
  if ('data' in a) p.data = Data.create(a.data);
4373
4377
  return p;
4374
4378
  }
@@ -5829,7 +5833,7 @@ Commands$1.deleteBackwardAtRange = function (editor, range) {
5829
5833
 
5830
5834
  // If the focus offset is farther than the number of characters to delete,
5831
5835
  // just remove the characters backwards inside the current node.
5832
- if (n < focus.offset) {
5836
+ if (n <= focus.offset) {
5833
5837
  range = range.moveFocusBackward(n);
5834
5838
  editor.deleteAtRange(range);
5835
5839
  return;
@@ -6205,7 +6209,7 @@ Commands$1.insertFragmentAtRange = function (editor, range, fragment) {
6205
6209
 
6206
6210
  // Regenerate the keys for all of the fragments nodes, so that they're
6207
6211
  // guaranteed not to collide with the existing keys in the document. Otherwise
6208
- // they will be rengerated automatically and we won't have an easy way to
6212
+ // they will be regenerated automatically and we won't have an easy way to
6209
6213
  // reference them.
6210
6214
  fragment = fragment.mapDescendants(function (child) {
6211
6215
  return child.regenerateKey();
@@ -7014,6 +7018,63 @@ Commands$2.addMarksByPath = function (editor, path, offset, length, marks) {
7014
7018
  });
7015
7019
  };
7016
7020
 
7021
+ /**
7022
+ * Sets specific set of marks on the path
7023
+ * @param {Editor} editor
7024
+ * @param {Array} path
7025
+ * @param {Number} offset
7026
+ * @param {Number} length
7027
+ * @param {Array<Object|Mark>} marks
7028
+ */
7029
+
7030
+ Commands$2.replaceMarksByPath = function (editor, path, offset, length, marks) {
7031
+ var marksSet = Mark.createSet(marks);
7032
+
7033
+ var value = editor.value;
7034
+ var document = value.document;
7035
+
7036
+ var node = document.assertNode(path);
7037
+
7038
+ if (node.marks.equals(marksSet)) {
7039
+ return;
7040
+ }
7041
+
7042
+ editor.withoutNormalizing(function () {
7043
+ // If it ends before the end of the node, we'll need to split to create a new
7044
+ // text with different marks.
7045
+ if (offset + length < node.text.length) {
7046
+ editor.splitNodeByPath(path, offset + length);
7047
+ }
7048
+
7049
+ // Same thing if it starts after the start. But in that case, we need to
7050
+ // update our path and offset to point to the new start.
7051
+ if (offset > 0) {
7052
+ editor.splitNodeByPath(path, offset);
7053
+ path = PathUtils.increment(path);
7054
+ offset = 0;
7055
+ }
7056
+
7057
+ var marksToApply = marksSet.subtract(node.marks);
7058
+ var marksToRemove = node.marks.subtract(marksSet);
7059
+
7060
+ marksToRemove.forEach(function (mark) {
7061
+ editor.applyOperation({
7062
+ type: 'remove_mark',
7063
+ path: path,
7064
+ mark: Mark.create(mark)
7065
+ });
7066
+ });
7067
+
7068
+ marksToApply.forEach(function (mark) {
7069
+ editor.applyOperation({
7070
+ type: 'add_mark',
7071
+ path: path,
7072
+ mark: Mark.create(mark)
7073
+ });
7074
+ });
7075
+ });
7076
+ };
7077
+
7017
7078
  /**
7018
7079
  * Insert a `fragment` at `index` in a node by `path`.
7019
7080
  *
@@ -7057,7 +7118,6 @@ Commands$2.insertNodeByPath = function (editor, path, index, node) {
7057
7118
  */
7058
7119
 
7059
7120
  Commands$2.insertTextByPath = function (editor, path, offset, text, marks) {
7060
- marks = Mark.createSet(marks);
7061
7121
  var value = editor.value;
7062
7122
  var annotations = value.annotations,
7063
7123
  document = value.document;
@@ -7111,8 +7171,8 @@ Commands$2.insertTextByPath = function (editor, path, offset, text, marks) {
7111
7171
  text: text
7112
7172
  });
7113
7173
 
7114
- if (marks.size) {
7115
- editor.addMarksByPath(path, offset, text.length, marks);
7174
+ if (marks) {
7175
+ editor.replaceMarksByPath(path, offset, text.length, marks);
7116
7176
  }
7117
7177
  });
7118
7178
  };
@@ -7207,6 +7267,10 @@ Commands$2.removeMarksByPath = function (editor, path, offset, length, marks) {
7207
7267
 
7208
7268
  var node = document.assertNode(path);
7209
7269
 
7270
+ if (marks.intersect(node.marks).isEmpty()) {
7271
+ return;
7272
+ }
7273
+
7210
7274
  editor.withoutNormalizing(function () {
7211
7275
  // If it ends before the end of the node, we'll need to split to create a new
7212
7276
  // text with different marks.
@@ -7763,7 +7827,7 @@ Commands$2.wrapNodeByPath = function (editor, path, node) {
7763
7827
  * Mix in `*ByKey` variants.
7764
7828
  */
7765
7829
 
7766
- var COMMANDS = ['addMark', 'insertFragment', 'insertNode', 'insertText', 'mergeNode', 'removeAllMarks', 'removeMark', 'removeNode', 'removeText', 'replaceNode', 'replaceText', 'setMark', 'setNode', 'setText', 'splitNode', 'unwrapBlock', 'unwrapChildren', 'unwrapInline', 'unwrapNode', 'wrapBlock', 'wrapInline', 'wrapNode'];
7830
+ var COMMANDS = ['addMark', 'insertFragment', 'insertNode', 'insertText', 'mergeNode', 'removeAllMarks', 'removeMark', 'removeNode', 'removeText', 'replaceMarks', 'replaceNode', 'replaceText', 'setMark', 'setNode', 'setText', 'splitNode', 'unwrapBlock', 'unwrapChildren', 'unwrapInline', 'unwrapNode', 'wrapBlock', 'wrapInline', 'wrapNode'];
7767
7831
 
7768
7832
  var _loop = function _loop(method) {
7769
7833
  Commands$2[method + 'ByKey'] = function (editor, key) {
@@ -7856,7 +7920,7 @@ Commands$3.save = function (editor, operation) {
7856
7920
  save = _editor$tmp.save,
7857
7921
  merge = _editor$tmp.merge;
7858
7922
 
7859
- if (save === false) return;
7923
+ if (save === false || !isValidOperation(operation)) return;
7860
7924
 
7861
7925
  var undos = data.get('undos') || List();
7862
7926
  var lastBatch = undos.last();
@@ -7917,13 +7981,13 @@ Commands$3.redo = function (editor) {
7917
7981
  batch.forEach(function (op) {
7918
7982
  var _op = op,
7919
7983
  type = _op.type,
7920
- properties = _op.properties;
7984
+ newProperties = _op.newProperties;
7921
7985
 
7922
7986
  // When the operation mutates the selection, omit its `isFocused` value to
7923
7987
  // prevent the editor focus from changing during redoing.
7924
7988
 
7925
7989
  if (type === 'set_selection') {
7926
- op = op.set('properties', omit(properties, 'isFocused'));
7990
+ op = op.set('newProperties', omit(newProperties, 'isFocused'));
7927
7991
  }
7928
7992
 
7929
7993
  editor.applyOperation(op);
@@ -7961,13 +8025,13 @@ Commands$3.undo = function (editor) {
7961
8025
  }).forEach(function (inverse) {
7962
8026
  var _inverse = inverse,
7963
8027
  type = _inverse.type,
7964
- properties = _inverse.properties;
8028
+ newProperties = _inverse.newProperties;
7965
8029
 
7966
8030
  // When the operation mutates the selection, omit its `isFocused` value to
7967
8031
  // prevent the editor focus from changing during undoing.
7968
8032
 
7969
8033
  if (type === 'set_selection') {
7970
- inverse = inverse.set('properties', omit(properties, 'isFocused'));
8034
+ inverse = inverse.set('newProperties', omit(newProperties, 'isFocused'));
7971
8035
  }
7972
8036
 
7973
8037
  editor.applyOperation(inverse);
@@ -8028,6 +8092,28 @@ function shouldMerge(o, p) {
8028
8092
  return merge;
8029
8093
  }
8030
8094
 
8095
+ /**
8096
+ * Check weather an operation needs to be saved to the history
8097
+ * @param {Object} o - operation
8098
+ * @returns {Boolean}
8099
+ */
8100
+
8101
+ function isValidOperation(o) {
8102
+ if (o.type === 'set_selection') {
8103
+ var _o$newProperties = o.newProperties,
8104
+ isFocused = _o$newProperties.isFocused,
8105
+ anchor = _o$newProperties.anchor,
8106
+ focus = _o$newProperties.focus;
8107
+
8108
+ // this is blur/focus operation, dont need to store it into the history
8109
+
8110
+ if (isFocused !== undefined && !anchor && !focus) {
8111
+ return false;
8112
+ }
8113
+ }
8114
+ return true;
8115
+ }
8116
+
8031
8117
  var Commands$4 = {};
8032
8118
 
8033
8119
  Commands$4.blur = function (editor) {
@@ -9059,6 +9145,20 @@ Commands$5.setAnnotation = function (editor, annotation, newProperties) {
9059
9145
  });
9060
9146
  };
9061
9147
 
9148
+ Commands$5.setAnnotations = function (editor) {
9149
+ var annotations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
9150
+ var value = editor.value;
9151
+
9152
+ var newProperties = Value.createProperties({ annotations: annotations });
9153
+ var prevProperties = pick(value, Object.keys(newProperties));
9154
+
9155
+ editor.applyOperation({
9156
+ type: 'set_value',
9157
+ properties: prevProperties,
9158
+ newProperties: newProperties
9159
+ });
9160
+ };
9161
+
9062
9162
  /**
9063
9163
  * A plugin that adds a set of queries to the editor.
9064
9164
  *
@@ -10148,27 +10248,14 @@ Commands$6.insertFragment = function (editor, fragment) {
10148
10248
  var _value = value,
10149
10249
  document = _value.document,
10150
10250
  selection = _value.selection;
10151
- var start = selection.start,
10152
- end = selection.end;
10153
- var _value2 = value,
10154
- startText = _value2.startText,
10155
- endText = _value2.endText,
10156
- startInline = _value2.startInline;
10157
-
10158
- var lastText = fragment.getLastText();
10159
- var lastInline = fragment.getClosestInline(lastText.key);
10160
- var lastBlock = fragment.getClosestBlock(lastText.key);
10161
- var firstChild = fragment.nodes.first();
10162
- var lastChild = fragment.nodes.last();
10251
+ var start = selection.start;
10252
+
10163
10253
  var keys = Array.from(document.texts(), function (_ref) {
10164
10254
  var _ref2 = slicedToArray(_ref, 1),
10165
10255
  text = _ref2[0];
10166
10256
 
10167
10257
  return text.key;
10168
10258
  });
10169
- var isAppending = !startInline || start.isAtStartOfNode(startText) || end.isAtStartOfNode(startText) || start.isAtEndOfNode(endText) || end.isAtEndOfNode(endText);
10170
-
10171
- var isInserting = firstChild.hasBlockChildren() || lastChild.hasBlockChildren();
10172
10259
 
10173
10260
  editor.insertFragmentAtRange(selection, fragment);
10174
10261
  value = editor.value;
@@ -10177,25 +10264,28 @@ Commands$6.insertFragment = function (editor, fragment) {
10177
10264
  var newTexts = document.getTexts().filter(function (n) {
10178
10265
  return !keys.includes(n.key);
10179
10266
  });
10180
- var newText = isAppending ? newTexts.last() : newTexts.takeLast(2).first();
10181
-
10182
- if (newText && (lastInline || isInserting)) {
10183
- editor.moveToEndOfNode(newText);
10184
- } else if (newText) {
10185
- // The position within the last text node needs to be calculated. This is the length
10186
- // of all text nodes within the last block, but if the last block contains inline nodes,
10187
- // these have to be skipped.
10188
- var nodes = lastBlock.nodes;
10189
-
10190
- var lastIndex = nodes.findLastIndex(function (node) {
10191
- return node && node.object === 'inline';
10192
- });
10193
- var remainingTexts = nodes.takeLast(nodes.size - lastIndex - 1);
10194
- var remainingTextLength = remainingTexts.reduce(function (acc, val) {
10195
- return acc + val.text.length;
10196
- }, 0);
10197
- editor.moveToStartOfNode(newText).moveForward(remainingTextLength);
10267
+ if (newTexts.size === 0) return;
10268
+ var fragmentLength = fragment.text.length;
10269
+
10270
+ // Either startText is still here, or we want the first un-previously known text
10271
+ var startText = document.getNode(start.key) || newTexts.first();
10272
+ // We want the last un-previously known text
10273
+ var endText = newTexts.last() || startText;
10274
+
10275
+ if (startText === endText) {
10276
+ editor.moveTo(endText.key, fragmentLength);
10277
+ return;
10198
10278
  }
10279
+
10280
+ // Everything will be calculated relative to the first common ancestor to optimize speed
10281
+ var parent = document.getCommonAncestor(startText.key, endText.key);
10282
+
10283
+ var startOffset = parent.getOffset(startText.key) + (start.key === startText.key ? start.offset : 0);
10284
+
10285
+ // endText might not be the last un-previously known text node, so we precisely pick it by offset
10286
+ endText = parent.getTextAtOffset(startOffset + fragmentLength - 1) || endText;
10287
+
10288
+ editor.moveTo(endText.key, startOffset + fragmentLength - parent.getOffset(endText.key));
10199
10289
  };
10200
10290
 
10201
10291
  /**
@@ -10758,14 +10848,27 @@ var Editor = function () {
10758
10848
 
10759
10849
  // Get the paths of the affected nodes, and mark them as dirty.
10760
10850
  var newDirtyPaths = getDirtyPaths(operation);
10761
- var dirty = this.tmp.dirty.reduce(function (memo, path) {
10851
+
10852
+ var dirty = this.tmp.dirty.map(function (path) {
10762
10853
  path = PathUtils.create(path);
10763
10854
  var transformed = PathUtils.transform(path, operation);
10764
- memo = memo.concat(transformed.toArray());
10765
- return memo;
10766
- }, newDirtyPaths);
10855
+ return transformed.toArray();
10856
+ });
10767
10857
 
10768
- this.tmp.dirty = dirty;
10858
+ var pathIndex = {};
10859
+ var dirtyPaths = Array.prototype.concat.apply(newDirtyPaths, dirty);
10860
+ this.tmp.dirty = [];
10861
+
10862
+ // PERF: De-dupe the paths so we don't do extra normalization.
10863
+ dirtyPaths.forEach(function (dirtyPath) {
10864
+ var key = dirtyPath.join(',');
10865
+
10866
+ if (!pathIndex[key]) {
10867
+ _this.tmp.dirty.push(dirtyPath);
10868
+ }
10869
+
10870
+ pathIndex[key] = true;
10871
+ });
10769
10872
 
10770
10873
  // If we're not already, queue the flushing process on the next tick.
10771
10874
  if (!this.tmp.flushing) {