@seafile/sdoc-editor 0.1.59 → 0.1.61

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.
Files changed (26) hide show
  1. package/dist/basic-sdk/editor.js +6 -2
  2. package/dist/basic-sdk/extension/constants/index.js +8 -0
  3. package/dist/basic-sdk/extension/core/utils/index.js +7 -4
  4. package/dist/basic-sdk/extension/menu/menu.css +2 -1
  5. package/dist/basic-sdk/extension/plugins/code-block/helpers.js +6 -3
  6. package/dist/basic-sdk/extension/plugins/code-block/render-elem.js +2 -1
  7. package/dist/basic-sdk/extension/plugins/table/constants/index.js +0 -2
  8. package/dist/basic-sdk/extension/plugins/table/helpers.js +10 -10
  9. package/dist/basic-sdk/extension/plugins/table/render/render-cell.js +1 -0
  10. package/dist/basic-sdk/extension/plugins/table/render/table-root.js +15 -10
  11. package/dist/basic-sdk/extension/plugins/text-align/menu/index.js +0 -1
  12. package/dist/basic-sdk/extension/plugins/text-align/menu/style.css +1 -0
  13. package/dist/basic-sdk/extension/plugins/text-style/render-elem.js +13 -8
  14. package/dist/basic-sdk/utils/diff-text.js +255 -0
  15. package/dist/basic-sdk/utils/diff.js +229 -142
  16. package/dist/basic-sdk/utils/document-utils.js +18 -0
  17. package/dist/basic-sdk/viewer.js +48 -66
  18. package/dist/pages/diff-viewer/diff-viewer.js +43 -114
  19. package/dist/pages/diff-viewer/history-version-viewer.js +6 -1
  20. package/package.json +2 -2
  21. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  22. package/public/media/sdoc-editor-font/iconfont.svg +2 -2
  23. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  24. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  25. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  26. package/public/media/sdoc-editor-font.css +10 -10
@@ -1,5 +1,5 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react';
3
3
  import { Node } from '@seafile/slate';
4
4
  import { Editable, Slate, ReactEditor } from '@seafile/slate-react';
5
5
  import defaultEditor, { renderLeaf, renderElement, Toolbar, ContextMenu } from './extension';
@@ -19,6 +19,8 @@ import './assets/css/sdoc-editor-plugins.css';
19
19
  var SDocEditor = function SDocEditor(_ref) {
20
20
  var document = _ref.document,
21
21
  config = _ref.config;
22
+ var articleRef = useRef(null);
23
+
22
24
  // init editor
23
25
  var editor = useMemo(function () {
24
26
  var newEditor = withNodeId(withSocketIO(defaultEditor, {
@@ -57,6 +59,7 @@ var SDocEditor = function SDocEditor(_ref) {
57
59
  // useMount: init socket connection
58
60
  useEffect(function () {
59
61
  editor.openConnection();
62
+ editor.width = articleRef.current.children[0].clientWidth;
60
63
  return function () {
61
64
  editor.closeConnection();
62
65
  };
@@ -111,7 +114,8 @@ var SDocEditor = function SDocEditor(_ref) {
111
114
  value: slateValue,
112
115
  onChange: onChange
113
116
  }, /*#__PURE__*/React.createElement("div", {
114
- className: "article"
117
+ className: "article",
118
+ ref: articleRef
115
119
  }, /*#__PURE__*/React.createElement(SetNodeToDecorations, null), /*#__PURE__*/React.createElement(Editable, {
116
120
  renderElement: renderElement,
117
121
  renderLeaf: renderLeaf,
@@ -113,4 +113,12 @@ export var TABLE_ELEMENT_POSITION = {
113
113
  AFTER: 'after',
114
114
  BEFORE: 'before'
115
115
  };
116
+ export var DELETED_STYLE = {
117
+ background_color: '#ffeef0',
118
+ color: 'rgb(165, 32, 21)'
119
+ };
120
+ export var ADDED_STYLE = {
121
+ background_color: '#e6ffed',
122
+ color: 'rgb(137, 181, 66)'
123
+ };
116
124
  export { BLOCKQUOTE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, BOLD, ITALIC, UNDERLINE, STRIKETHROUGH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, LIST_LIC, CHECK_LIST, CHECK_LIST_ITEM, LINK, HTML, CODE_BLOCK, CODE_LINE, IMAGE, TABLE, TABLE_CELL, TABLE_ROW, FORMULA, COLUMN, TEXT_STYLE, BOLD_ITALIC, TEXT_ALIGN, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ELEMENT_TYPE, KEYBOARD };
@@ -18,13 +18,16 @@ export var match = function match(node, path, predicate) {
18
18
  }
19
19
  return predicate(node, path);
20
20
  };
21
+ export var generateDefaultText = function generateDefaultText() {
22
+ return {
23
+ id: slugid.nice(),
24
+ text: ''
25
+ };
26
+ };
21
27
  export var generateEmptyElement = function generateEmptyElement(type) {
22
28
  return {
23
29
  type: type,
24
- children: [{
25
- id: slugid.nice(),
26
- text: ''
27
- }]
30
+ children: [generateDefaultText()]
28
31
  };
29
32
  };
30
33
  export function Placeholder(props) {
@@ -8,7 +8,8 @@
8
8
 
9
9
  .menu-group .menu-group-item {
10
10
  width: 30px;
11
- height: 100%;
11
+ height: 30px;
12
+ line-height: 30px;
12
13
  margin-right: 10px;
13
14
  border: 1px solid transparent;
14
15
  color: #555555;
@@ -68,7 +68,8 @@ export var changeToCodeBlock = function changeToCodeBlock(editor, language) {
68
68
  id: slugid.nice(),
69
69
  type: CODE_LINE,
70
70
  children: [{
71
- text: strArr.join('\n')
71
+ text: strArr.join('\n'),
72
+ id: slugid.nice()
72
73
  } // Select the plain text of the node
73
74
  ]
74
75
  }]
@@ -95,8 +96,10 @@ export var changeToPlainText = function changeToPlainText(editor) {
95
96
  return {
96
97
  type: 'paragraph',
97
98
  children: [{
98
- text: s
99
- }]
99
+ text: s,
100
+ id: slugid.nice()
101
+ }],
102
+ id: elem.id
100
103
  };
101
104
  });
102
105
  Transforms.insertNodes(editor, pList, {
@@ -99,7 +99,8 @@ var CodeBlock = function CodeBlock(_ref) {
99
99
  document.getElementById('sdoc-editor-article-container').removeEventListener('scroll', onScroll);
100
100
  }
101
101
  return function () {
102
- document.getElementById('sdoc-editor-article-container').removeEventListener('scroll', onScroll);
102
+ var articleContainer = document.getElementById('sdoc-editor-article-container');
103
+ articleContainer && articleContainer.removeEventListener('scroll', onScroll);
103
104
  };
104
105
  // eslint-disable-next-line react-hooks/exhaustive-deps
105
106
  }, [showHoverMenu]);
@@ -6,7 +6,5 @@ export var EMPTY_SELECTED_RANGE = {
6
6
  minColIndex: -1,
7
7
  maxColIndex: -1
8
8
  };
9
- export var TABLE_MAX_WIDTH = 672; // 673 = 794 - 2[borderLeft + borderRight] - 120[paddingLeft + paddingRight]
10
-
11
9
  export var TABLE_ROW_MIN_HEIGHT = 42;
12
10
  export var TABLE_CELL_MIN_WIDTH = 35;
@@ -5,7 +5,7 @@ import slugid from 'slugid';
5
5
  import { Editor, Range, Transforms } from '@seafile/slate';
6
6
  import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, getSelectedElems, focusEditor, getNode, findPath } from '../../core';
7
7
  import { ELEMENT_TYPE, TABLE_ELEMENT, TABLE_ELEMENT_POSITION } from '../../constants';
8
- import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE, TABLE_ROW_MIN_HEIGHT, TABLE_CELL_MIN_WIDTH, TABLE_MAX_WIDTH } from './constants';
8
+ import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE, TABLE_ROW_MIN_HEIGHT, TABLE_CELL_MIN_WIDTH } from './constants';
9
9
  import EventBus from '../../../utils/event-bus';
10
10
  import { EXTERNAL_EVENT } from '../../../../constants';
11
11
  import ObjectUtils from '../../../utils/object-utils';
@@ -65,8 +65,8 @@ export var generateTableRow = function generateTableRow(colsCount) {
65
65
  }
66
66
  };
67
67
  };
68
- export var generateEmptyTable = function generateEmptyTable() {
69
- var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0];
68
+ export var generateEmptyTable = function generateEmptyTable(editor) {
69
+ var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 0];
70
70
  var rowsCount = size[0];
71
71
  var colsCount = size[1];
72
72
  var children = [];
@@ -74,7 +74,7 @@ export var generateEmptyTable = function generateEmptyTable() {
74
74
  var tableRow = generateTableRow(colsCount);
75
75
  children.push(tableRow);
76
76
  }
77
- var columnWidth = Math.max(TABLE_CELL_MIN_WIDTH, parseInt(TABLE_MAX_WIDTH / colsCount));
77
+ var columnWidth = Math.max(TABLE_CELL_MIN_WIDTH, parseInt(editor.width / colsCount));
78
78
  var columns = [];
79
79
  for (var _i = 0; _i < colsCount; _i++) {
80
80
  columns.push({
@@ -91,7 +91,7 @@ export var generateEmptyTable = function generateEmptyTable() {
91
91
  export var insertTable = function insertTable(editor, size, selection) {
92
92
  if (!size) return;
93
93
  if (isTableMenuDisabled(editor)) return;
94
- var tableNode = generateEmptyTable(size);
94
+ var tableNode = generateEmptyTable(editor, size);
95
95
  Transforms.insertNodes(editor, tableNode, {
96
96
  at: selection
97
97
  });
@@ -351,7 +351,7 @@ export var getTableColumnsAfterInsertColumn = function getTableColumnsAfterInser
351
351
  var targetInsertColumnsWidth = targetColumn.width * insertColumnCount;
352
352
 
353
353
  // Currently in scrolling state, insert directly
354
- if (totalColumnsWidth > TABLE_MAX_WIDTH) {
354
+ if (totalColumnsWidth > editor.width) {
355
355
  for (var i = 0; i < insertColumnCount; i++) {
356
356
  newColumns.splice(targetColumnIndex, 0, targetColumn);
357
357
  }
@@ -360,7 +360,7 @@ export var getTableColumnsAfterInsertColumn = function getTableColumnsAfterInser
360
360
 
361
361
  // Not currently scrolling
362
362
  // It is not a scroll state after inserting a new column
363
- if (totalColumnsWidth + targetInsertColumnsWidth < TABLE_MAX_WIDTH) {
363
+ if (totalColumnsWidth + targetInsertColumnsWidth < editor.width) {
364
364
  for (var _i5 = 0; _i5 < insertColumnCount; _i5++) {
365
365
  newColumns.push(targetColumn);
366
366
  }
@@ -372,7 +372,7 @@ export var getTableColumnsAfterInsertColumn = function getTableColumnsAfterInser
372
372
  totalColumnsWidth += targetColumn.width;
373
373
  newColumns.splice(targetColumnIndex, 0, targetColumn);
374
374
  }
375
- var proportion = totalColumnsWidth / (TABLE_MAX_WIDTH - 1);
375
+ var proportion = totalColumnsWidth / (editor.width - 1);
376
376
  return newColumns.map(function (column) {
377
377
  return _objectSpread(_objectSpread({}, column), {}, {
378
378
  width: Math.max(parseInt(column.width / proportion), TABLE_CELL_MIN_WIDTH)
@@ -395,7 +395,7 @@ export var getTableColumns = function getTableColumns(editor, element) {
395
395
  var initColumns = [];
396
396
  for (var i = 0; i < columnsCount; i++) {
397
397
  var column = {
398
- width: Math.max(TABLE_CELL_MIN_WIDTH, parseInt(TABLE_MAX_WIDTH / columnsCount))
398
+ width: Math.max(TABLE_CELL_MIN_WIDTH, parseInt(editor.width / columnsCount))
399
399
  };
400
400
  initColumns.push(column);
401
401
  }
@@ -418,7 +418,7 @@ export var getCellColumn = function getCellColumn(editor, cellElement) {
418
418
  } else {
419
419
  var columnsCount = tableElement.children[0].children.length;
420
420
  column = {
421
- width: Math.max(TABLE_CELL_MIN_WIDTH, parseInt(TABLE_MAX_WIDTH / columnsCount))
421
+ width: Math.max(TABLE_CELL_MIN_WIDTH, parseInt(editor.width / columnsCount))
422
422
  };
423
423
  }
424
424
  return column;
@@ -74,6 +74,7 @@ function renderTableCell(props) {
74
74
  var width = column.width;
75
75
  return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
76
76
  style: _objectSpread(_objectSpread(_objectSpread({}, style), element.style), {}, {
77
+ minWidth: width,
77
78
  width: width
78
79
  }),
79
80
  className: classnames('table-cell', attributes.className),
@@ -1,13 +1,15 @@
1
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
1
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
- import React, { useState, useRef } from 'react';
3
+ import React, { useState, useRef, useCallback } from 'react';
3
4
  import classnames from 'classnames';
4
- import { TABLE_MAX_WIDTH } from '../constants';
5
+ import { useSlateStatic } from '@seafile/slate-react';
5
6
  import { TableRootContext } from './hooks';
6
7
  var TableRoot = function TableRoot(_ref) {
7
8
  var attributes = _ref.attributes,
8
9
  _ref$columns = _ref.columns,
9
10
  columns = _ref$columns === void 0 ? [] : _ref$columns,
10
11
  children = _ref.children;
12
+ var editor = useSlateStatic();
11
13
  var tableScrollWrapper = useRef(null);
12
14
  var _useState = useState(0),
13
15
  _useState2 = _slicedToArray(_useState, 2),
@@ -16,19 +18,22 @@ var TableRoot = function TableRoot(_ref) {
16
18
  var allWidth = columns.reduce(function (pre, cur) {
17
19
  return pre + cur.width;
18
20
  }, 0);
19
- var onScroll = function onScroll(event) {
21
+ var onScroll = useCallback(function (event) {
20
22
  setScrollLeft(event.target.scrollLeft);
21
- };
23
+ }, []);
22
24
  return /*#__PURE__*/React.createElement(TableRootContext.Provider, {
23
25
  value: tableScrollWrapper.current
24
- }, /*#__PURE__*/React.createElement("div", Object.assign({
25
- className: classnames('sdoc-table-wrapper', {
26
- 'scroll position-relative': allWidth > TABLE_MAX_WIDTH
26
+ }, /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
27
+ className: classnames('sdoc-table-wrapper', attributes.className, {
28
+ 'scroll position-relative': allWidth > editor.width
29
+ }),
30
+ style: _objectSpread(_objectSpread({}, attributes.style), {}, {
31
+ maxWidth: editor.width
27
32
  })
28
- }, attributes), /*#__PURE__*/React.createElement("div", {
33
+ }), /*#__PURE__*/React.createElement("div", {
29
34
  className: classnames('sdoc-table-scroll-wrapper', {
30
- 'scroll-at-center': scrollLeft + TABLE_MAX_WIDTH !== allWidth && scrollLeft > 0,
31
- 'scroll-at-right': scrollLeft + TABLE_MAX_WIDTH === allWidth,
35
+ 'scroll-at-center': scrollLeft + editor.width !== allWidth && scrollLeft > 0,
36
+ 'scroll-at-right': scrollLeft + editor.width === allWidth,
32
37
  'scroll-at-left': scrollLeft === 0
33
38
  }),
34
39
  ref: tableScrollWrapper,
@@ -70,7 +70,6 @@ var TextAlignMenu = /*#__PURE__*/function (_React$Component) {
70
70
  key: "render",
71
71
  value: function render() {
72
72
  var _this2 = this;
73
- var t = this.props.t;
74
73
  var isDropdownMenuOpen = this.state.isDropdownMenuOpen;
75
74
  var caretIconClass = "caret-icon sdocfont sdoc-".concat(isDropdownMenuOpen ? 'caret-up' : 'drop-down');
76
75
  var curType = this.getCurrentType();
@@ -26,6 +26,7 @@
26
26
  align-items: center;
27
27
  font-size: 14px;
28
28
  cursor: pointer;
29
+ line-height: 1;
29
30
  }
30
31
 
31
32
  .align-menu .align-toggle .caret-icon {
@@ -9,6 +9,18 @@ var renderText = function renderText(props, editor) {
9
9
  var text = leaf.text,
10
10
  rest = _objectWithoutProperties(leaf, _excluded);
11
11
  var markedChildren = React.cloneElement(children);
12
+ var style = {};
13
+ if (leaf.isCaret) {
14
+ style['position'] = 'relative';
15
+ style['display'] = 'inline-block';
16
+ style['minWidth'] = '2px';
17
+ }
18
+ if (leaf.background_color) {
19
+ style['backgroundColor'] = leaf.background_color;
20
+ }
21
+ if (leaf.color) {
22
+ style['color'] = leaf.color;
23
+ }
12
24
  if (leaf.BOLD) {
13
25
  markedChildren = /*#__PURE__*/React.createElement("strong", null, markedChildren);
14
26
  }
@@ -36,20 +48,13 @@ var renderText = function renderText(props, editor) {
36
48
  markedChildren = /*#__PURE__*/React.createElement("del", null, markedChildren);
37
49
  }
38
50
  if (leaf.ADD) {
39
- markedChildren = /*#__PURE__*/React.createElement("ins", null, markedChildren);
51
+ markedChildren = /*#__PURE__*/React.createElement("span", null, markedChildren);
40
52
  }
41
53
  if (leaf.decoration) {
42
54
  markedChildren = /*#__PURE__*/React.createElement("span", {
43
55
  className: "token ".concat(leaf.type)
44
56
  }, markedChildren);
45
57
  }
46
- var style = {
47
- position: 'relative'
48
- };
49
- if (leaf.isCaret) {
50
- style['display'] = 'inline-block';
51
- style['minWidth'] = '2px';
52
- }
53
58
  return /*#__PURE__*/React.createElement("span", Object.assign({
54
59
  "data-id": leaf.id
55
60
  }, attributes, {
@@ -0,0 +1,255 @@
1
+ import _createClass from "@babel/runtime/helpers/esm/createClass";
2
+ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
3
+ import ObjectUtils from './object-utils';
4
+ var buildValues = function buildValues(diff, components, newString, oldString, valueType, useLongestToken) {
5
+ var componentPos = 0;
6
+ var componentLen = components.length;
7
+ var newPos = 0;
8
+ var oldPos = 0;
9
+ for (; componentPos < componentLen; componentPos++) {
10
+ var component = components[componentPos];
11
+ if (!component.removed) {
12
+ if (!component.added && useLongestToken) {
13
+ var value = newString.slice(newPos, newPos + component.count);
14
+ // eslint-disable-next-line no-loop-func
15
+ value = value.map(function (value, i) {
16
+ var oldValue = oldString[oldPos + i];
17
+ return oldValue.length > value.length ? oldValue : value;
18
+ });
19
+ component.value = diff.join(value, valueType);
20
+ } else {
21
+ component.value = diff.join(newString.slice(newPos, newPos + component.count), valueType);
22
+ }
23
+ newPos += component.count;
24
+
25
+ // Common case
26
+ if (!component.added) {
27
+ oldPos += component.count;
28
+ }
29
+ } else {
30
+ component.value = diff.join(oldString.slice(oldPos, oldPos + component.count), valueType);
31
+ oldPos += component.count;
32
+
33
+ // Reverse add and remove so removes are output first to match common convention
34
+ // The diffing algorithm is tied to add then remove output and this is the simplest
35
+ // route to get the desired output with minimal overhead.
36
+ if (componentPos && components[componentPos - 1].added) {
37
+ var tmp = components[componentPos - 1];
38
+ components[componentPos - 1] = components[componentPos];
39
+ components[componentPos] = tmp;
40
+ }
41
+ }
42
+ }
43
+
44
+ // Special case handle for when one terminal is ignored (i.e. whitespace).
45
+ // For this case we merge the terminal into the prior string and drop the change.
46
+ // This is only available for string mode.
47
+ var lastComponent = components[componentLen - 1];
48
+ if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) {
49
+ components[componentLen - 2].value += lastComponent.value;
50
+ components.pop();
51
+ }
52
+ return components;
53
+ };
54
+ var clonePath = function clonePath(path) {
55
+ return {
56
+ newPos: path.newPos,
57
+ components: path.components.slice(0)
58
+ };
59
+ };
60
+ var DiffText = /*#__PURE__*/_createClass(function DiffText(oldValue, newValue) {
61
+ var _this = this;
62
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
63
+ _classCallCheck(this, DiffText);
64
+ this.done = function (value) {
65
+ if (_this.callback) {
66
+ setTimeout(function () {
67
+ this.callback(undefined, value);
68
+ }, 0);
69
+ return true;
70
+ }
71
+ return value;
72
+ };
73
+ // Main worker method. checks all permutations of a given edit length for acceptance.
74
+ this.execCompareLength = function (bestPath) {
75
+ for (var diagonalPath = -1 * _this.comparePath; diagonalPath <= _this.comparePath; diagonalPath += 2) {
76
+ var basePath = void 0;
77
+ var addPath = bestPath[diagonalPath - 1];
78
+ var removePath = bestPath[diagonalPath + 1];
79
+ var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
80
+ if (addPath) {
81
+ // No one else is going to attempt to use this value, clear it
82
+ bestPath[diagonalPath - 1] = undefined;
83
+ }
84
+ var canAdd = addPath && addPath.newPos + 1 < _this.newLen;
85
+ var canRemove = removePath && 0 <= oldPos && oldPos < _this.oldLen;
86
+ if (!canAdd && !canRemove) {
87
+ // If this path is a terminal then prune
88
+ bestPath[diagonalPath] = undefined;
89
+ continue;
90
+ }
91
+
92
+ // Select the diagonal that we want to branch from. We select the prior
93
+ // path whose position in the new string is the farthest from the origin
94
+ // and does not pass the bounds of the diff graph
95
+ if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
96
+ basePath = clonePath(removePath);
97
+ _this.pushComponent(basePath.components, undefined, true);
98
+ } else {
99
+ basePath = addPath; // No need to clone, we've pulled it from the list
100
+ basePath.newPos++;
101
+ _this.pushComponent(basePath.components, true, undefined);
102
+ }
103
+ oldPos = _this.extractCommon(basePath, _this.newValue, _this.oldValue, diagonalPath);
104
+
105
+ // If we have hit the end of both strings, then we are done
106
+ if (basePath.newPos + 1 >= _this.newLen && oldPos + 1 >= _this.oldLen) {
107
+ return _this.done(buildValues(_this, basePath.components, _this.newValue, _this.oldValue, _this.valueType, _this.useLongestToken));
108
+ } else {
109
+ // Otherwise track this path as a potential candidate and continue.
110
+ bestPath[diagonalPath] = basePath;
111
+ }
112
+ }
113
+ _this.comparePath++;
114
+ };
115
+ this.exec = function (bestPath) {
116
+ setTimeout(function () {
117
+ if (this.comparePath > this.maxEditLength) {
118
+ return this.callback();
119
+ }
120
+ if (!this.execCompareLength(bestPath)) {
121
+ this.exec(bestPath);
122
+ }
123
+ }, 0);
124
+ };
125
+ this.pushComponent = function (components, added, removed) {
126
+ var last = components[components.length - 1];
127
+ if (last && last.added === added && last.removed === removed) {
128
+ // We need to clone here as the component clone operation is just
129
+ // as shallow array clone
130
+ components[components.length - 1] = {
131
+ count: last.count + 1,
132
+ added: added,
133
+ removed: removed
134
+ };
135
+ } else {
136
+ components.push({
137
+ count: 1,
138
+ added: added,
139
+ removed: removed
140
+ });
141
+ }
142
+ };
143
+ this.extractCommon = function (basePath, newString, oldString, diagonalPath) {
144
+ var newLen = newString.length;
145
+ var oldLen = oldString.length;
146
+ var newPos = basePath.newPos;
147
+ var oldPos = newPos - diagonalPath;
148
+ var commonCount = 0;
149
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && _this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
150
+ newPos++;
151
+ oldPos++;
152
+ commonCount++;
153
+ }
154
+ if (commonCount) {
155
+ basePath.components.push({
156
+ count: commonCount
157
+ });
158
+ }
159
+ basePath.newPos = newPos;
160
+ return oldPos;
161
+ };
162
+ this.equals = function (left, right) {
163
+ if (_this.options.comparator) {
164
+ return _this.options.comparator(left, right);
165
+ } else {
166
+ return left === right || _this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
167
+ }
168
+ };
169
+ this.removeEmpty = function (array, type) {
170
+ if (type === 'Array') return array;
171
+ var ret = [];
172
+ for (var i = 0; i < array.length; i++) {
173
+ if (array[i]) {
174
+ ret.push(array[i]);
175
+ }
176
+ }
177
+ return ret;
178
+ };
179
+ this.tokenize = function (value, valueType) {
180
+ if (valueType === 'Array') return value.slice();
181
+ return value.split('');
182
+ };
183
+ this.join = function (value, valueType) {
184
+ if (valueType === 'Array') return value;
185
+ return value.join('');
186
+ };
187
+ this.getDiffs = function () {
188
+ if (!_this.canCompare) {
189
+ return [{
190
+ value: _this.oldValue,
191
+ removed: true
192
+ }, {
193
+ value: _this.newValue,
194
+ added: true
195
+ }];
196
+ }
197
+ var bestPath = [{
198
+ newPos: -1,
199
+ components: []
200
+ }];
201
+
202
+ // Seed editLength = 0, i.e. the content starts with the same values
203
+ var oldPos = _this.extractCommon(bestPath[0], _this.newValue, _this.oldValue, 0);
204
+ if (bestPath[0].newPos + 1 >= _this.newLen && oldPos + 1 >= _this.oldLen) {
205
+ // Identity per the equality and tokenizer
206
+ return _this.done([{
207
+ value: _this.join(_this.newValue, _this.valueType),
208
+ count: _this.oldValue.length
209
+ }]);
210
+ }
211
+
212
+ // Performs the length of edit iteration. Is a bit fugly as this has to support the
213
+ // sync and async mode which is never fun. Loops over execCompareLength until a value
214
+ // is produced, or until the edit length exceeds options.maxEditLength (if given),
215
+ // in which case it will return undefined.
216
+ if (_this.callback) {
217
+ _this.exec(bestPath);
218
+ } else {
219
+ while (_this.comparePath <= _this.maxEditLength) {
220
+ var ret = _this.execCompareLength(bestPath);
221
+ if (ret) {
222
+ return ret;
223
+ }
224
+ }
225
+ }
226
+ };
227
+ this.oldValue = oldValue;
228
+ this.newValue = newValue;
229
+ var oldValueType = ObjectUtils.getDataType(oldValue);
230
+ var newValueType = ObjectUtils.getDataType(newValue);
231
+ this.canCompare = true;
232
+ if (oldValueType !== newValueType) {
233
+ this.canCompare = false;
234
+ return;
235
+ }
236
+ this.valueType = newValueType;
237
+ this.callback = options.callback;
238
+ var optionsType = ObjectUtils.getDataType(options);
239
+ if (optionsType === 'function') {
240
+ this.callback = options;
241
+ this.options = {};
242
+ } else {
243
+ this.options = {};
244
+ }
245
+ this.comparePath = 1;
246
+ this.oldValue = this.removeEmpty(this.tokenize(oldValue, oldValueType), oldValueType);
247
+ this.oldLen = this.oldValue.length;
248
+ this.newValue = this.removeEmpty(this.tokenize(newValue, newValueType), newValueType);
249
+ this.newLen = this.newValue.length;
250
+ this.maxEditLength = this.newLen + this.oldLen;
251
+ if (this.options.maxEditLength) {
252
+ this.maxEditLength = Math.min(this.maxEditLength, this.options.maxEditLength);
253
+ }
254
+ });
255
+ export default DiffText;