@lobehub/editor 4.3.2 → 4.5.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/es/locale/index.d.ts +2 -0
- package/es/locale/index.js +2 -0
- package/es/plugins/common/react/ReactPlainText.js +7 -2
- package/es/plugins/common/react/type.d.ts +11 -1
- package/es/plugins/markdown/command/index.d.ts +2 -2
- package/es/plugins/markdown/command/index.js +13 -20
- package/es/plugins/markdown/plugin/index.d.ts +11 -1
- package/es/plugins/markdown/plugin/index.js +175 -98
- package/es/plugins/markdown/react/index.js +8 -42
- package/es/react/Editor/Editor.js +7 -2
- package/es/react/Editor/type.d.ts +11 -1
- package/es/renderer/LexicalDiff.d.ts +22 -0
- package/es/renderer/LexicalDiff.js +116 -0
- package/es/renderer/diff/compute.d.ts +3 -0
- package/es/renderer/diff/compute.js +510 -0
- package/es/renderer/diff/style.d.ts +13 -0
- package/es/renderer/diff/style.js +20 -0
- package/es/renderer/diff/types.d.ts +28 -0
- package/es/renderer/diff/types.js +1 -0
- package/es/renderer/index.d.ts +3 -0
- package/es/renderer/index.js +1 -0
- package/es/renderer/renderers/codeblock.js +5 -0
- package/es/renderer/renderers/mermaid.d.ts +2 -0
- package/es/renderer/renderers/mermaid.js +18 -0
- package/es/types/kernel.d.ts +6 -4
- package/package.json +2 -1
|
@@ -9,6 +9,11 @@ interface MentionOption extends Partial<ReactSlashOptionProps> {
|
|
|
9
9
|
}
|
|
10
10
|
export interface EditorProps extends Partial<ReactEditorContentProps>, Omit<ReactPlainTextProps, 'children'> {
|
|
11
11
|
autoFocus?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Automatically convert pasted markdown once the detection threshold is reached
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
autoFormatMarkdown?: boolean;
|
|
12
17
|
children?: ReactNode;
|
|
13
18
|
className?: string;
|
|
14
19
|
/**
|
|
@@ -19,7 +24,7 @@ export interface EditorProps extends Partial<ReactEditorContentProps>, Omit<Reac
|
|
|
19
24
|
editable?: boolean;
|
|
20
25
|
editor?: IEditor;
|
|
21
26
|
/**
|
|
22
|
-
* Enable automatic markdown
|
|
27
|
+
* Enable automatic markdown conversion for pasted content
|
|
23
28
|
* @default true
|
|
24
29
|
*/
|
|
25
30
|
enablePasteMarkdown?: boolean;
|
|
@@ -42,6 +47,11 @@ export interface EditorProps extends Partial<ReactEditorContentProps>, Omit<Reac
|
|
|
42
47
|
* Unlike onChange, this won't trigger on cursor movement or selection changes
|
|
43
48
|
*/
|
|
44
49
|
onTextChange?: (editor: IEditor) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Minimum markdown score required before auto conversion runs
|
|
52
|
+
* @default 5
|
|
53
|
+
*/
|
|
54
|
+
pasteMarkdownAutoConvertThreshold?: number;
|
|
45
55
|
plugins?: EditorPlugin[];
|
|
46
56
|
slashOption?: Partial<ReactSlashOptionProps>;
|
|
47
57
|
/** Force slash menu placement direction, skipping auto-flip detection */
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SerializedEditorState } from 'lexical';
|
|
2
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
3
|
+
import type { LexicalDiffBlockRenderer } from './diff/types';
|
|
4
|
+
import type { LexicalRendererProps } from './types';
|
|
5
|
+
export type { LexicalDiffBlockRenderContext, LexicalDiffBlockRenderer, LexicalDiffCell, LexicalDiffRow, LexicalDiffRowKind, } from './diff/types';
|
|
6
|
+
export interface LexicalDiffProps {
|
|
7
|
+
blockRenderers?: Record<string, LexicalDiffBlockRenderer>;
|
|
8
|
+
className?: string;
|
|
9
|
+
extraNodes?: LexicalRendererProps['extraNodes'];
|
|
10
|
+
labels?: {
|
|
11
|
+
new?: ReactNode;
|
|
12
|
+
old?: ReactNode;
|
|
13
|
+
};
|
|
14
|
+
newValue: SerializedEditorState;
|
|
15
|
+
oldValue: SerializedEditorState;
|
|
16
|
+
overrides?: LexicalRendererProps['overrides'];
|
|
17
|
+
renderBlockDiff?: LexicalDiffBlockRenderer;
|
|
18
|
+
renderContext?: LexicalRendererProps['renderContext'];
|
|
19
|
+
style?: CSSProperties;
|
|
20
|
+
variant?: LexicalRendererProps['variant'];
|
|
21
|
+
}
|
|
22
|
+
export declare function LexicalDiff({ oldValue, newValue, variant, extraNodes, overrides, renderContext, labels, blockRenderers, renderBlockDiff, className, style, }: LexicalDiffProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { cx } from 'antd-style';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { LexicalRenderer } from "./LexicalRenderer";
|
|
4
|
+
import { computeLexicalDiffRows } from "./diff/compute";
|
|
5
|
+
import { styles } from "./diff/style";
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
function wrapBlock(block) {
|
|
9
|
+
return {
|
|
10
|
+
root: {
|
|
11
|
+
children: [block],
|
|
12
|
+
direction: 'ltr',
|
|
13
|
+
format: '',
|
|
14
|
+
indent: 0,
|
|
15
|
+
type: 'root',
|
|
16
|
+
version: 1
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function RowCell(_ref) {
|
|
21
|
+
var className = _ref.className,
|
|
22
|
+
content = _ref.content;
|
|
23
|
+
return /*#__PURE__*/_jsx("div", {
|
|
24
|
+
className: className,
|
|
25
|
+
children: content
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export function LexicalDiff(_ref2) {
|
|
29
|
+
var _labels$old, _labels$new;
|
|
30
|
+
var oldValue = _ref2.oldValue,
|
|
31
|
+
newValue = _ref2.newValue,
|
|
32
|
+
_ref2$variant = _ref2.variant,
|
|
33
|
+
variant = _ref2$variant === void 0 ? 'default' : _ref2$variant,
|
|
34
|
+
extraNodes = _ref2.extraNodes,
|
|
35
|
+
overrides = _ref2.overrides,
|
|
36
|
+
renderContext = _ref2.renderContext,
|
|
37
|
+
labels = _ref2.labels,
|
|
38
|
+
blockRenderers = _ref2.blockRenderers,
|
|
39
|
+
renderBlockDiff = _ref2.renderBlockDiff,
|
|
40
|
+
className = _ref2.className,
|
|
41
|
+
style = _ref2.style;
|
|
42
|
+
var rows = useMemo(function () {
|
|
43
|
+
return computeLexicalDiffRows(oldValue, newValue);
|
|
44
|
+
}, [oldValue, newValue]);
|
|
45
|
+
var renderDefaultCell = function renderDefaultCell(block) {
|
|
46
|
+
if (!block) return null;
|
|
47
|
+
return /*#__PURE__*/_jsx(LexicalRenderer, {
|
|
48
|
+
extraNodes: extraNodes,
|
|
49
|
+
overrides: overrides,
|
|
50
|
+
renderContext: renderContext,
|
|
51
|
+
value: wrapBlock(block),
|
|
52
|
+
variant: variant
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
var renderRow = function renderRow(row, index) {
|
|
56
|
+
var _row$oldCell, _row$newCell, _ref3, _row$oldCell$blockTyp, _row$oldCell2, _row$newCell2, _row$oldCell3, _row$newCell3, _ref4, _row$oldCell$baseBloc, _row$oldCell4, _row$newCell4, _row$newCell$baseBloc, _row$newCell5, _row$newCell$blockTyp, _row$newCell6, _row$oldCell$baseBloc2, _row$oldCell5, _row$oldCell$blockTyp2, _row$oldCell6, _rendered$old, _rendered, _rendered$new, _rendered2;
|
|
57
|
+
var blockType = (_row$oldCell = row.oldCell) !== null && _row$oldCell !== void 0 && _row$oldCell.blockType && (_row$newCell = row.newCell) !== null && _row$newCell !== void 0 && _row$newCell.blockType ? row.oldCell.blockType === row.newCell.blockType ? row.oldCell.blockType : null : (_ref3 = (_row$oldCell$blockTyp = (_row$oldCell2 = row.oldCell) === null || _row$oldCell2 === void 0 ? void 0 : _row$oldCell2.blockType) !== null && _row$oldCell$blockTyp !== void 0 ? _row$oldCell$blockTyp : (_row$newCell2 = row.newCell) === null || _row$newCell2 === void 0 ? void 0 : _row$newCell2.blockType) !== null && _ref3 !== void 0 ? _ref3 : null;
|
|
58
|
+
var baseBlockType = (_row$oldCell3 = row.oldCell) !== null && _row$oldCell3 !== void 0 && _row$oldCell3.baseBlockType && (_row$newCell3 = row.newCell) !== null && _row$newCell3 !== void 0 && _row$newCell3.baseBlockType ? row.oldCell.baseBlockType === row.newCell.baseBlockType ? row.oldCell.baseBlockType : null : (_ref4 = (_row$oldCell$baseBloc = (_row$oldCell4 = row.oldCell) === null || _row$oldCell4 === void 0 ? void 0 : _row$oldCell4.baseBlockType) !== null && _row$oldCell$baseBloc !== void 0 ? _row$oldCell$baseBloc : (_row$newCell4 = row.newCell) === null || _row$newCell4 === void 0 ? void 0 : _row$newCell4.baseBlockType) !== null && _ref4 !== void 0 ? _ref4 : null;
|
|
59
|
+
var context = {
|
|
60
|
+
baseBlockType: baseBlockType,
|
|
61
|
+
blockType: blockType,
|
|
62
|
+
newBaseBlockType: (_row$newCell$baseBloc = (_row$newCell5 = row.newCell) === null || _row$newCell5 === void 0 ? void 0 : _row$newCell5.baseBlockType) !== null && _row$newCell$baseBloc !== void 0 ? _row$newCell$baseBloc : null,
|
|
63
|
+
newBlockType: (_row$newCell$blockTyp = (_row$newCell6 = row.newCell) === null || _row$newCell6 === void 0 ? void 0 : _row$newCell6.blockType) !== null && _row$newCell$blockTyp !== void 0 ? _row$newCell$blockTyp : null,
|
|
64
|
+
oldBaseBlockType: (_row$oldCell$baseBloc2 = (_row$oldCell5 = row.oldCell) === null || _row$oldCell5 === void 0 ? void 0 : _row$oldCell5.baseBlockType) !== null && _row$oldCell$baseBloc2 !== void 0 ? _row$oldCell$baseBloc2 : null,
|
|
65
|
+
oldBlockType: (_row$oldCell$blockTyp2 = (_row$oldCell6 = row.oldCell) === null || _row$oldCell6 === void 0 ? void 0 : _row$oldCell6.blockType) !== null && _row$oldCell$blockTyp2 !== void 0 ? _row$oldCell$blockTyp2 : null,
|
|
66
|
+
renderDefaultNew: function renderDefaultNew() {
|
|
67
|
+
var _row$newCell$block, _row$newCell7;
|
|
68
|
+
return renderDefaultCell((_row$newCell$block = (_row$newCell7 = row.newCell) === null || _row$newCell7 === void 0 ? void 0 : _row$newCell7.block) !== null && _row$newCell$block !== void 0 ? _row$newCell$block : null);
|
|
69
|
+
},
|
|
70
|
+
renderDefaultOld: function renderDefaultOld() {
|
|
71
|
+
var _row$oldCell$block, _row$oldCell7;
|
|
72
|
+
return renderDefaultCell((_row$oldCell$block = (_row$oldCell7 = row.oldCell) === null || _row$oldCell7 === void 0 ? void 0 : _row$oldCell7.block) !== null && _row$oldCell$block !== void 0 ? _row$oldCell$block : null);
|
|
73
|
+
},
|
|
74
|
+
row: row
|
|
75
|
+
};
|
|
76
|
+
var renderers = [blockType ? blockRenderers === null || blockRenderers === void 0 ? void 0 : blockRenderers[blockType] : undefined, baseBlockType && baseBlockType !== blockType ? blockRenderers === null || blockRenderers === void 0 ? void 0 : blockRenderers[baseBlockType] : undefined, renderBlockDiff];
|
|
77
|
+
var rendered;
|
|
78
|
+
for (var _i = 0, _renderers = renderers; _i < _renderers.length; _i++) {
|
|
79
|
+
var renderer = _renderers[_i];
|
|
80
|
+
if (!renderer) continue;
|
|
81
|
+
var next = renderer(context);
|
|
82
|
+
if (next === null) continue;
|
|
83
|
+
rendered = next;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
var oldContent = (_rendered$old = (_rendered = rendered) === null || _rendered === void 0 ? void 0 : _rendered.old) !== null && _rendered$old !== void 0 ? _rendered$old : context.renderDefaultOld();
|
|
87
|
+
var newContent = (_rendered$new = (_rendered2 = rendered) === null || _rendered2 === void 0 ? void 0 : _rendered2.new) !== null && _rendered$new !== void 0 ? _rendered$new : context.renderDefaultNew();
|
|
88
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
89
|
+
className: styles.row,
|
|
90
|
+
children: [/*#__PURE__*/_jsx(RowCell, {
|
|
91
|
+
className: cx(styles.cell, styles.cellOld, !row.oldCell && styles.emptyCell, row.kind === 'delete' && styles.deleteCell),
|
|
92
|
+
content: oldContent
|
|
93
|
+
}), /*#__PURE__*/_jsx(RowCell, {
|
|
94
|
+
className: cx(styles.cell, !row.newCell && styles.emptyCell, row.kind === 'insert' && styles.insertCell),
|
|
95
|
+
content: newContent
|
|
96
|
+
})]
|
|
97
|
+
}, "row-".concat(index));
|
|
98
|
+
};
|
|
99
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
100
|
+
className: cx(styles.root, className),
|
|
101
|
+
style: style,
|
|
102
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
103
|
+
className: styles.header,
|
|
104
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
105
|
+
className: cx(styles.headerCell, styles.headerOld),
|
|
106
|
+
children: (_labels$old = labels === null || labels === void 0 ? void 0 : labels.old) !== null && _labels$old !== void 0 ? _labels$old : 'Old'
|
|
107
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
108
|
+
className: styles.headerCell,
|
|
109
|
+
children: (_labels$new = labels === null || labels === void 0 ? void 0 : labels.new) !== null && _labels$new !== void 0 ? _labels$new : 'New'
|
|
110
|
+
})]
|
|
111
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
112
|
+
className: styles.body,
|
|
113
|
+
children: rows.map(renderRow)
|
|
114
|
+
})]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
5
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
6
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
7
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
8
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
9
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
10
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
11
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
12
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
13
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
14
|
+
var CHAR_DIFF_MAX_MATRIX_CELLS = 50000;
|
|
15
|
+
var DELETE_MARK_STYLE = 'background-color: color-mix(in srgb, var(--ant-color-error) 18%, transparent); text-decoration: line-through;';
|
|
16
|
+
var INSERT_MARK_STYLE = 'background-color: color-mix(in srgb, var(--ant-color-success) 18%, transparent);';
|
|
17
|
+
function getBaseNodeType(node) {
|
|
18
|
+
if (!node) return null;
|
|
19
|
+
var type = node.type;
|
|
20
|
+
return typeof type === 'string' ? type : null;
|
|
21
|
+
}
|
|
22
|
+
function getNormalizedBlockType(node) {
|
|
23
|
+
if (!node) return null;
|
|
24
|
+
var record = node;
|
|
25
|
+
var type = getBaseNodeType(node);
|
|
26
|
+
if (!type) return null;
|
|
27
|
+
if (type === 'heading') return "heading:".concat(String(record.tag || 'unknown'));
|
|
28
|
+
if (type === 'list') return "list:".concat(String(record.listType || 'bullet'));
|
|
29
|
+
return type;
|
|
30
|
+
}
|
|
31
|
+
function createCell(block) {
|
|
32
|
+
if (!block) return null;
|
|
33
|
+
return {
|
|
34
|
+
baseBlockType: getBaseNodeType(block),
|
|
35
|
+
block: block,
|
|
36
|
+
blockType: getNormalizedBlockType(block)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function getChildren(node) {
|
|
40
|
+
var children = node.children;
|
|
41
|
+
return Array.isArray(children) ? children : null;
|
|
42
|
+
}
|
|
43
|
+
function nodesEqual(a, b) {
|
|
44
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
45
|
+
}
|
|
46
|
+
function isTextNode(node) {
|
|
47
|
+
var record = node;
|
|
48
|
+
return record.type === 'text' && typeof record.text === 'string';
|
|
49
|
+
}
|
|
50
|
+
function appendStyle(baseStyle, extraStyle) {
|
|
51
|
+
var normalizedBase = typeof baseStyle === 'string' ? baseStyle.trim() : '';
|
|
52
|
+
if (!normalizedBase) return extraStyle;
|
|
53
|
+
return "".concat(normalizedBase).concat(normalizedBase.endsWith(';') ? '' : ';', " ").concat(extraStyle);
|
|
54
|
+
}
|
|
55
|
+
function cloneTextNode(node, text, markKind) {
|
|
56
|
+
var style = node.style;
|
|
57
|
+
if (markKind === 'delete') {
|
|
58
|
+
style = appendStyle(style, DELETE_MARK_STYLE);
|
|
59
|
+
} else if (markKind === 'insert') {
|
|
60
|
+
style = appendStyle(style, INSERT_MARK_STYLE);
|
|
61
|
+
}
|
|
62
|
+
return _objectSpread(_objectSpread({}, node), {}, {
|
|
63
|
+
style: style,
|
|
64
|
+
text: text
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function cloneNodeWithChildren(node, children) {
|
|
68
|
+
return _objectSpread(_objectSpread({}, node), {}, {
|
|
69
|
+
children: children
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function decorateSubtree(node, kind) {
|
|
73
|
+
if (isTextNode(node)) return cloneTextNode(node, node.text, kind);
|
|
74
|
+
var children = getChildren(node);
|
|
75
|
+
if (!children) return node;
|
|
76
|
+
return cloneNodeWithChildren(node, children.map(function (child) {
|
|
77
|
+
return decorateSubtree(child, kind);
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
function reverseText(value) {
|
|
81
|
+
return Array.from(value).reverse().join('');
|
|
82
|
+
}
|
|
83
|
+
function mergeTextOps(ops) {
|
|
84
|
+
var merged = [];
|
|
85
|
+
var _iterator = _createForOfIteratorHelper(ops),
|
|
86
|
+
_step;
|
|
87
|
+
try {
|
|
88
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
89
|
+
var op = _step.value;
|
|
90
|
+
if (!op.text) continue;
|
|
91
|
+
var last = merged.at(-1);
|
|
92
|
+
if (last && last.kind === op.kind) {
|
|
93
|
+
last.text += op.text;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
merged.push(_objectSpread({}, op));
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
_iterator.e(err);
|
|
100
|
+
} finally {
|
|
101
|
+
_iterator.f();
|
|
102
|
+
}
|
|
103
|
+
return merged;
|
|
104
|
+
}
|
|
105
|
+
function diffMiddleChars(oldChars, newChars) {
|
|
106
|
+
var m = oldChars.length;
|
|
107
|
+
var n = newChars.length;
|
|
108
|
+
if (m === 0 && n === 0) return [];
|
|
109
|
+
if (m === 0) return [{
|
|
110
|
+
kind: 'insert',
|
|
111
|
+
text: newChars.join('')
|
|
112
|
+
}];
|
|
113
|
+
if (n === 0) return [{
|
|
114
|
+
kind: 'delete',
|
|
115
|
+
text: oldChars.join('')
|
|
116
|
+
}];
|
|
117
|
+
if (m * n > CHAR_DIFF_MAX_MATRIX_CELLS) {
|
|
118
|
+
return [{
|
|
119
|
+
kind: 'delete',
|
|
120
|
+
text: oldChars.join('')
|
|
121
|
+
}, {
|
|
122
|
+
kind: 'insert',
|
|
123
|
+
text: newChars.join('')
|
|
124
|
+
}];
|
|
125
|
+
}
|
|
126
|
+
var dp = Array.from({
|
|
127
|
+
length: m + 1
|
|
128
|
+
}, function () {
|
|
129
|
+
return Array.from({
|
|
130
|
+
length: n + 1
|
|
131
|
+
}).fill(0);
|
|
132
|
+
});
|
|
133
|
+
for (var _i = 1; _i <= m; _i++) {
|
|
134
|
+
for (var _j = 1; _j <= n; _j++) {
|
|
135
|
+
if (oldChars[_i - 1] === newChars[_j - 1]) {
|
|
136
|
+
dp[_i][_j] = dp[_i - 1][_j - 1] + 1;
|
|
137
|
+
} else {
|
|
138
|
+
dp[_i][_j] = Math.max(dp[_i - 1][_j], dp[_i][_j - 1]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
var reversedOps = [];
|
|
143
|
+
var i = m;
|
|
144
|
+
var j = n;
|
|
145
|
+
while (i > 0 && j > 0) {
|
|
146
|
+
if (oldChars[i - 1] === newChars[j - 1]) {
|
|
147
|
+
var last = reversedOps.at(-1);
|
|
148
|
+
if (last && last.kind === 'equal') {
|
|
149
|
+
last.text += oldChars[i - 1];
|
|
150
|
+
} else {
|
|
151
|
+
reversedOps.push({
|
|
152
|
+
kind: 'equal',
|
|
153
|
+
text: oldChars[i - 1]
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
i--;
|
|
157
|
+
j--;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (dp[i - 1][j] >= dp[i][j - 1]) {
|
|
161
|
+
var _last = reversedOps.at(-1);
|
|
162
|
+
if (_last && _last.kind === 'delete') {
|
|
163
|
+
_last.text += oldChars[i - 1];
|
|
164
|
+
} else {
|
|
165
|
+
reversedOps.push({
|
|
166
|
+
kind: 'delete',
|
|
167
|
+
text: oldChars[i - 1]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
i--;
|
|
171
|
+
} else {
|
|
172
|
+
var _last2 = reversedOps.at(-1);
|
|
173
|
+
if (_last2 && _last2.kind === 'insert') {
|
|
174
|
+
_last2.text += newChars[j - 1];
|
|
175
|
+
} else {
|
|
176
|
+
reversedOps.push({
|
|
177
|
+
kind: 'insert',
|
|
178
|
+
text: newChars[j - 1]
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
j--;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
while (i > 0) {
|
|
185
|
+
var _last3 = reversedOps.at(-1);
|
|
186
|
+
if (_last3 && _last3.kind === 'delete') {
|
|
187
|
+
_last3.text += oldChars[i - 1];
|
|
188
|
+
} else {
|
|
189
|
+
reversedOps.push({
|
|
190
|
+
kind: 'delete',
|
|
191
|
+
text: oldChars[i - 1]
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
i--;
|
|
195
|
+
}
|
|
196
|
+
while (j > 0) {
|
|
197
|
+
var _last4 = reversedOps.at(-1);
|
|
198
|
+
if (_last4 && _last4.kind === 'insert') {
|
|
199
|
+
_last4.text += newChars[j - 1];
|
|
200
|
+
} else {
|
|
201
|
+
reversedOps.push({
|
|
202
|
+
kind: 'insert',
|
|
203
|
+
text: newChars[j - 1]
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
j--;
|
|
207
|
+
}
|
|
208
|
+
return mergeTextOps(reversedOps.reverse().map(function (op) {
|
|
209
|
+
return {
|
|
210
|
+
kind: op.kind,
|
|
211
|
+
text: reverseText(op.text)
|
|
212
|
+
};
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
function diffTextByChar(oldText, newText) {
|
|
216
|
+
var oldChars = Array.from(oldText);
|
|
217
|
+
var newChars = Array.from(newText);
|
|
218
|
+
var prefix = 0;
|
|
219
|
+
while (prefix < oldChars.length && prefix < newChars.length && oldChars[prefix] === newChars[prefix]) {
|
|
220
|
+
prefix++;
|
|
221
|
+
}
|
|
222
|
+
var oldSuffix = oldChars.length - 1;
|
|
223
|
+
var newSuffix = newChars.length - 1;
|
|
224
|
+
while (oldSuffix >= prefix && newSuffix >= prefix && oldChars[oldSuffix] === newChars[newSuffix]) {
|
|
225
|
+
oldSuffix--;
|
|
226
|
+
newSuffix--;
|
|
227
|
+
}
|
|
228
|
+
var ops = [];
|
|
229
|
+
if (prefix > 0) {
|
|
230
|
+
ops.push({
|
|
231
|
+
kind: 'equal',
|
|
232
|
+
text: oldChars.slice(0, prefix).join('')
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
ops.push.apply(ops, _toConsumableArray(diffMiddleChars(oldChars.slice(prefix, oldSuffix + 1), newChars.slice(prefix, newSuffix + 1))));
|
|
236
|
+
if (oldSuffix < oldChars.length - 1) {
|
|
237
|
+
ops.push({
|
|
238
|
+
kind: 'equal',
|
|
239
|
+
text: oldChars.slice(oldSuffix + 1).join('')
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return mergeTextOps(ops);
|
|
243
|
+
}
|
|
244
|
+
function splitTextNodeByCharDiff(oldNode, newNode) {
|
|
245
|
+
var ops = diffTextByChar(oldNode.text, newNode.text);
|
|
246
|
+
var oldNodes = [];
|
|
247
|
+
var newNodes = [];
|
|
248
|
+
var changed = false;
|
|
249
|
+
var _iterator2 = _createForOfIteratorHelper(ops),
|
|
250
|
+
_step2;
|
|
251
|
+
try {
|
|
252
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
253
|
+
var op = _step2.value;
|
|
254
|
+
if (!op.text) continue;
|
|
255
|
+
if (op.kind === 'equal') {
|
|
256
|
+
oldNodes.push(cloneTextNode(oldNode, op.text));
|
|
257
|
+
newNodes.push(cloneTextNode(newNode, op.text));
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
changed = true;
|
|
261
|
+
if (op.kind === 'delete') {
|
|
262
|
+
oldNodes.push(cloneTextNode(oldNode, op.text, 'delete'));
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
newNodes.push(cloneTextNode(newNode, op.text, 'insert'));
|
|
266
|
+
}
|
|
267
|
+
} catch (err) {
|
|
268
|
+
_iterator2.e(err);
|
|
269
|
+
} finally {
|
|
270
|
+
_iterator2.f();
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
changed: changed,
|
|
274
|
+
newNodes: newNodes.length > 0 ? newNodes : [newNode],
|
|
275
|
+
oldNodes: oldNodes.length > 0 ? oldNodes : [oldNode]
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function alignNodes(oldNodes, newNodes) {
|
|
279
|
+
var m = oldNodes.length;
|
|
280
|
+
var n = newNodes.length;
|
|
281
|
+
var dp = Array.from({
|
|
282
|
+
length: m + 1
|
|
283
|
+
}, function () {
|
|
284
|
+
return Array.from({
|
|
285
|
+
length: n + 1
|
|
286
|
+
}).fill(0);
|
|
287
|
+
});
|
|
288
|
+
for (var _i2 = 1; _i2 <= m; _i2++) {
|
|
289
|
+
for (var _j2 = 1; _j2 <= n; _j2++) {
|
|
290
|
+
var skip = Math.max(dp[_i2 - 1][_j2], dp[_i2][_j2 - 1]);
|
|
291
|
+
var oldType = getNormalizedBlockType(oldNodes[_i2 - 1]);
|
|
292
|
+
var newType = getNormalizedBlockType(newNodes[_j2 - 1]);
|
|
293
|
+
if (oldType && oldType === newType) {
|
|
294
|
+
var score = nodesEqual(oldNodes[_i2 - 1], newNodes[_j2 - 1]) ? 2 : 1;
|
|
295
|
+
dp[_i2][_j2] = Math.max(skip, dp[_i2 - 1][_j2 - 1] + score);
|
|
296
|
+
} else {
|
|
297
|
+
dp[_i2][_j2] = skip;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
var ops = [];
|
|
302
|
+
var i = m;
|
|
303
|
+
var j = n;
|
|
304
|
+
while (i > 0 && j > 0) {
|
|
305
|
+
var _oldType = getNormalizedBlockType(oldNodes[i - 1]);
|
|
306
|
+
var _newType = getNormalizedBlockType(newNodes[j - 1]);
|
|
307
|
+
if (_oldType && _oldType === _newType) {
|
|
308
|
+
var exact = nodesEqual(oldNodes[i - 1], newNodes[j - 1]);
|
|
309
|
+
var _score = exact ? 2 : 1;
|
|
310
|
+
if (dp[i][j] === dp[i - 1][j - 1] + _score) {
|
|
311
|
+
ops.push(exact ? {
|
|
312
|
+
kind: 'equal',
|
|
313
|
+
node: oldNodes[i - 1]
|
|
314
|
+
} : {
|
|
315
|
+
kind: 'modify',
|
|
316
|
+
newNode: newNodes[j - 1],
|
|
317
|
+
oldNode: oldNodes[i - 1]
|
|
318
|
+
});
|
|
319
|
+
i--;
|
|
320
|
+
j--;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (dp[i - 1][j] >= dp[i][j - 1]) {
|
|
325
|
+
ops.push({
|
|
326
|
+
kind: 'delete',
|
|
327
|
+
node: oldNodes[i - 1]
|
|
328
|
+
});
|
|
329
|
+
i--;
|
|
330
|
+
} else {
|
|
331
|
+
ops.push({
|
|
332
|
+
kind: 'insert',
|
|
333
|
+
node: newNodes[j - 1]
|
|
334
|
+
});
|
|
335
|
+
j--;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
while (i > 0) {
|
|
339
|
+
ops.push({
|
|
340
|
+
kind: 'delete',
|
|
341
|
+
node: oldNodes[--i]
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
while (j > 0) {
|
|
345
|
+
ops.push({
|
|
346
|
+
kind: 'insert',
|
|
347
|
+
node: newNodes[--j]
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
return ops.reverse();
|
|
351
|
+
}
|
|
352
|
+
function diffChildrenInline(oldChildren, newChildren) {
|
|
353
|
+
var ops = alignNodes(oldChildren, newChildren);
|
|
354
|
+
var nextOldChildren = [];
|
|
355
|
+
var nextNewChildren = [];
|
|
356
|
+
var changed = false;
|
|
357
|
+
var _iterator3 = _createForOfIteratorHelper(ops),
|
|
358
|
+
_step3;
|
|
359
|
+
try {
|
|
360
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
361
|
+
var op = _step3.value;
|
|
362
|
+
switch (op.kind) {
|
|
363
|
+
case 'equal':
|
|
364
|
+
{
|
|
365
|
+
nextOldChildren.push(op.node);
|
|
366
|
+
nextNewChildren.push(op.node);
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
case 'delete':
|
|
370
|
+
{
|
|
371
|
+
changed = true;
|
|
372
|
+
nextOldChildren.push(decorateSubtree(op.node, 'delete'));
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
case 'insert':
|
|
376
|
+
{
|
|
377
|
+
changed = true;
|
|
378
|
+
nextNewChildren.push(decorateSubtree(op.node, 'insert'));
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
case 'modify':
|
|
382
|
+
{
|
|
383
|
+
changed = true;
|
|
384
|
+
if (isTextNode(op.oldNode) && isTextNode(op.newNode)) {
|
|
385
|
+
var textDiff = splitTextNodeByCharDiff(op.oldNode, op.newNode);
|
|
386
|
+
nextOldChildren.push.apply(nextOldChildren, _toConsumableArray(textDiff.oldNodes));
|
|
387
|
+
nextNewChildren.push.apply(nextNewChildren, _toConsumableArray(textDiff.newNodes));
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Recursive descent is intentional here: same-type element nodes diff their children.
|
|
392
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
393
|
+
var nested = diffNodeInline(op.oldNode, op.newNode);
|
|
394
|
+
nextOldChildren.push(nested.oldNode);
|
|
395
|
+
nextNewChildren.push(nested.newNode);
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
} catch (err) {
|
|
401
|
+
_iterator3.e(err);
|
|
402
|
+
} finally {
|
|
403
|
+
_iterator3.f();
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
changed: changed,
|
|
407
|
+
newChildren: nextNewChildren,
|
|
408
|
+
oldChildren: nextOldChildren
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function diffNodeInline(oldNode, newNode) {
|
|
412
|
+
if (nodesEqual(oldNode, newNode)) {
|
|
413
|
+
return {
|
|
414
|
+
changed: false,
|
|
415
|
+
newNode: newNode,
|
|
416
|
+
oldNode: oldNode
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
var oldChildren = getChildren(oldNode);
|
|
420
|
+
var newChildren = getChildren(newNode);
|
|
421
|
+
if (!oldChildren || !newChildren) {
|
|
422
|
+
return {
|
|
423
|
+
changed: true,
|
|
424
|
+
newNode: newNode,
|
|
425
|
+
oldNode: oldNode
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
var childDiff = diffChildrenInline(oldChildren, newChildren);
|
|
429
|
+
if (!childDiff.changed) {
|
|
430
|
+
return {
|
|
431
|
+
changed: false,
|
|
432
|
+
newNode: newNode,
|
|
433
|
+
oldNode: oldNode
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
changed: true,
|
|
438
|
+
newNode: cloneNodeWithChildren(newNode, childDiff.newChildren),
|
|
439
|
+
oldNode: cloneNodeWithChildren(oldNode, childDiff.oldChildren)
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function getRootChildren(state) {
|
|
443
|
+
return Array.isArray(state.root.children) ? _toConsumableArray(state.root.children) : [];
|
|
444
|
+
}
|
|
445
|
+
export function computeLexicalDiffRows(oldState, newState) {
|
|
446
|
+
var ops = alignNodes(getRootChildren(oldState), getRootChildren(newState));
|
|
447
|
+
var rows = [];
|
|
448
|
+
var index = 0;
|
|
449
|
+
while (index < ops.length) {
|
|
450
|
+
var op = ops[index];
|
|
451
|
+
if (op.kind === 'equal') {
|
|
452
|
+
rows.push({
|
|
453
|
+
kind: 'equal',
|
|
454
|
+
newCell: createCell(op.node),
|
|
455
|
+
oldCell: createCell(op.node)
|
|
456
|
+
});
|
|
457
|
+
index++;
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
if (op.kind === 'modify') {
|
|
461
|
+
var diffed = diffNodeInline(op.oldNode, op.newNode);
|
|
462
|
+
rows.push({
|
|
463
|
+
kind: 'modify',
|
|
464
|
+
newCell: createCell(diffed.newNode),
|
|
465
|
+
oldCell: createCell(diffed.oldNode)
|
|
466
|
+
});
|
|
467
|
+
index++;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
var deletes = [];
|
|
471
|
+
var inserts = [];
|
|
472
|
+
while (index < ops.length && (ops[index].kind === 'delete' || ops[index].kind === 'insert')) {
|
|
473
|
+
var current = ops[index];
|
|
474
|
+
if (current.kind === 'delete') {
|
|
475
|
+
deletes.push(current.node);
|
|
476
|
+
} else if (current.kind === 'insert') {
|
|
477
|
+
inserts.push(current.node);
|
|
478
|
+
}
|
|
479
|
+
index++;
|
|
480
|
+
}
|
|
481
|
+
var maxLength = Math.max(deletes.length, inserts.length);
|
|
482
|
+
for (var pairIndex = 0; pairIndex < maxLength; pairIndex++) {
|
|
483
|
+
var _deletes$pairIndex, _inserts$pairIndex;
|
|
484
|
+
var oldBlock = (_deletes$pairIndex = deletes[pairIndex]) !== null && _deletes$pairIndex !== void 0 ? _deletes$pairIndex : null;
|
|
485
|
+
var newBlock = (_inserts$pairIndex = inserts[pairIndex]) !== null && _inserts$pairIndex !== void 0 ? _inserts$pairIndex : null;
|
|
486
|
+
if (oldBlock && newBlock) {
|
|
487
|
+
rows.push({
|
|
488
|
+
kind: 'modify',
|
|
489
|
+
newCell: createCell(newBlock),
|
|
490
|
+
oldCell: createCell(oldBlock)
|
|
491
|
+
});
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
if (oldBlock) {
|
|
495
|
+
rows.push({
|
|
496
|
+
kind: 'delete',
|
|
497
|
+
newCell: null,
|
|
498
|
+
oldCell: createCell(oldBlock)
|
|
499
|
+
});
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
rows.push({
|
|
503
|
+
kind: 'insert',
|
|
504
|
+
newCell: createCell(newBlock),
|
|
505
|
+
oldCell: null
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return rows;
|
|
510
|
+
}
|