@seafile/sdoc-editor 1.0.212-alph-0.1.9 → 1.0.212-alph-2.1.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.
Files changed (38) hide show
  1. package/dist/api/seafile-api.js +4 -0
  2. package/dist/basic-sdk/assets/css/sdoc-editor-plugins.css +55 -0
  3. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +2 -0
  4. package/dist/basic-sdk/extension/constants/element-type.js +4 -1
  5. package/dist/basic-sdk/extension/constants/index.js +6 -0
  6. package/dist/basic-sdk/extension/core/transforms/index.js +12 -1
  7. package/dist/basic-sdk/extension/core/transforms/rebase.js +75 -0
  8. package/dist/basic-sdk/extension/core/transforms/replace-node.js +2 -16
  9. package/dist/basic-sdk/extension/core/transforms/update-parent-node.js +8 -5
  10. package/dist/basic-sdk/extension/plugins/group/index.js +13 -0
  11. package/dist/basic-sdk/extension/plugins/group/render-elem.js +25 -0
  12. package/dist/basic-sdk/extension/plugins/image/constants/index.js +3 -2
  13. package/dist/basic-sdk/extension/plugins/image/helpers.js +21 -2
  14. package/dist/basic-sdk/extension/plugins/image/render-elem.js +86 -16
  15. package/dist/basic-sdk/extension/plugins/index.js +8 -1
  16. package/dist/basic-sdk/extension/plugins/list/plugin/normalize-list.js +3 -2
  17. package/dist/basic-sdk/extension/plugins/list/transforms/normalize-list-item.js +1 -1
  18. package/dist/basic-sdk/extension/render/custom-element.js +5 -0
  19. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/index.css +2 -1
  20. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-delete-modify-decorate.js +1 -1
  21. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-modify-delete-decorate.js +1 -1
  22. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-modify-modify-decorate.js +63 -31
  23. package/dist/basic-sdk/utils/diff.js +2 -0
  24. package/dist/basic-sdk/utils/rebase.js +63 -16
  25. package/dist/components/doc-operations/revision-operations/changes-count/index.js +0 -5
  26. package/dist/components/doc-operations/revision-operations/revisions/index.css +1 -1
  27. package/dist/pages/simple-editor.js +0 -1
  28. package/package.json +1 -1
  29. package/public/locales/cs/sdoc-editor.json +3 -1
  30. package/public/locales/de/sdoc-editor.json +3 -1
  31. package/public/locales/en/sdoc-editor.json +3 -1
  32. package/public/locales/es/sdoc-editor.json +3 -1
  33. package/public/locales/es_AR/sdoc-editor.json +3 -1
  34. package/public/locales/es_MX/sdoc-editor.json +3 -1
  35. package/public/locales/fr/sdoc-editor.json +3 -1
  36. package/public/locales/it/sdoc-editor.json +3 -1
  37. package/public/locales/ru/sdoc-editor.json +3 -1
  38. package/public/locales/zh_CN/sdoc-editor.json +3 -1
@@ -40,13 +40,17 @@ class SeafileAPI {
40
40
  uploadSdocImage(docUuid, imageFiles) {
41
41
  const url = '/api/v2.1/seadoc/upload-image/' + docUuid + '/';
42
42
  const form = new FormData();
43
+ console.log(form, imageFiles);
43
44
  for (const fileItem of imageFiles) {
45
+ console.log(imageFiles, fileItem);
44
46
  if (fileItem.type.startsWith('image/')) {
45
47
  const fileName = this.getImageFileNameWithUuid(fileItem);
46
48
  const file = new File([fileItem], fileName, {
47
49
  type: fileItem.type
48
50
  });
51
+ console.log(1, file);
49
52
  form.append('file', file);
53
+ console.log(form);
50
54
  }
51
55
  }
52
56
  return this.req.post(url, form);
@@ -62,6 +62,61 @@
62
62
  caret-color: transparent;
63
63
  }
64
64
 
65
+ .sdoc-editor__article .sdoc-image-wrapper .sdoc-image-placeholder-wrapper {
66
+ width: 100%;
67
+ aspect-ratio: 1;
68
+ background-color: #f0f0f0;
69
+ border: 1px solid #ccc;
70
+ padding: 0 3%;
71
+ max-width: 100%;
72
+ user-select: all;
73
+ pointer-events: all;
74
+ }
75
+
76
+ .sdoc-editor__article .sdoc-image-wrapper .sdoc-image-tip-content,
77
+ .sdoc-editor__article .sdoc-image-wrapper .sdoc-image-title {
78
+ user-select: none;
79
+ pointer-events: none;
80
+ }
81
+
82
+ .sdoc-editor__article .sdoc-image-title .sdoc-exclamation-circle {
83
+ font-size: 18px;
84
+ align-items: center;
85
+ justify-content: center;
86
+ color: red;
87
+ display: flex;
88
+ }
89
+
90
+ .sdoc-editor__article .sdoc-image-title .sdoc-image-tip-title {
91
+ color: red;
92
+ font-size: 18px;
93
+ user-select: none;
94
+ pointer-events: none;
95
+ }
96
+
97
+ .sdoc-editor__article .sdoc-image-process-container {
98
+ width: 40px;
99
+ height: 40px;
100
+ display: flex;
101
+ align-items: center;
102
+ }
103
+
104
+ .sdoc-editor__article .sdoc-image-process-container .loading-spinner {
105
+ border: 5px solid #d8d8d8;
106
+ border-top: 5px solid #939393;
107
+ border-radius: 50%;
108
+ width: 30px;
109
+ height: 30px;
110
+ animation: spin 1s linear infinite;
111
+ user-select: none;
112
+ pointer-events: none;
113
+ }
114
+
115
+ @keyframes spin {
116
+ 0% { transform: rotate(0deg); }
117
+ 100% { transform: rotate(360deg); }
118
+ }
119
+
65
120
  .sdoc-editor__article .sdoc-image-inner {
66
121
  position: relative;
67
122
  display: inline-block;
@@ -44,7 +44,9 @@ const InsertElementDialog = _ref => {
44
44
  const uploadLocalVideoInputRef = (0, _react.useRef)();
45
45
  const onFileChanged = (0, _react.useCallback)(event => {
46
46
  const files = event.target.files;
47
+ console.log(1, files);
47
48
  _context.default.uploadLocalImage(files).then(fileUrl => {
49
+ console.log(2, fileUrl);
48
50
  (0, _helpers.insertImage)(validEditor, fileUrl, validEditor.selection, insertPosition);
49
51
  if (uploadLocalImageInputRef.current) {
50
52
  uploadLocalImageInputRef.current.value = '';
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.WIKI_LINK = exports.VIDEO_LINK = exports.VIDEO = exports.UNORDERED_LIST = exports.TWO_COLUMN = exports.TOP_LEVEL_TYPES = exports.TITLE = exports.THREE_COLUMN = exports.TABLE_ROW = exports.TABLE_CELL = exports.TABLE = exports.SUBTITLE = exports.SEATABLE_TABLE = exports.SEATABLE_COLUMN = exports.SDOC_LINK = exports.QUICK_INSERT = exports.PARAGRAPH = exports.ORDERED_LIST = exports.MULTI_COLUMN = exports.MENTION_TEMP = exports.MENTION = exports.LIST_ITEM = exports.LINK = exports.INLINE_LEVEL_TYPES = exports.IMAGE_BLOCK = exports.IMAGE = exports.HEADER6 = exports.HEADER5 = exports.HEADER4 = exports.HEADER3 = exports.HEADER2 = exports.HEADER1 = exports.HEADER = exports.FOUR_COLUMN = exports.FONT_SIZE_REDUCE = exports.FONT_SIZE_INCREASE = exports.FONT_SIZE = exports.FIVE_COLUMN = exports.FILE_LINK_INSET_INPUT_TEMP = exports.FILE_LINK = exports.COLUMN = exports.CODE_LINE = exports.CODE_BLOCK = exports.CHECK_LIST_ITEM = exports.CALL_OUT = exports.BLOCKQUOTE = exports.ASK_AI = void 0;
6
+ exports.WIKI_LINK = exports.VIDEO_LINK = exports.VIDEO = exports.UNORDERED_LIST = exports.TWO_COLUMN = exports.TOP_LEVEL_TYPES = exports.TITLE = exports.THREE_COLUMN = exports.TABLE_ROW = exports.TABLE_CELL = exports.TABLE = exports.SUBTITLE = exports.SEATABLE_TABLE = exports.SEATABLE_COLUMN = exports.SDOC_LINK = exports.QUICK_INSERT = exports.PARAGRAPH = exports.ORDERED_LIST = exports.MULTI_COLUMN = exports.MENTION_TEMP = exports.MENTION = exports.LIST_ITEM = exports.LINK = exports.INLINE_LEVEL_TYPES = exports.IMAGE_BLOCK = exports.IMAGE = exports.HEADER6 = exports.HEADER5 = exports.HEADER4 = exports.HEADER3 = exports.HEADER2 = exports.HEADER1 = exports.HEADER = exports.GROUP = exports.FOUR_COLUMN = exports.FONT_SIZE_REDUCE = exports.FONT_SIZE_INCREASE = exports.FONT_SIZE = exports.FIVE_COLUMN = exports.FILE_LINK_INSET_INPUT_TEMP = exports.FILE_LINK = exports.COLUMN = exports.CODE_LINE = exports.CODE_BLOCK = exports.CHECK_LIST_ITEM = exports.CALL_OUT = exports.BLOCKQUOTE = exports.ASK_AI = void 0;
7
7
  const BLOCKQUOTE = exports.BLOCKQUOTE = 'blockquote';
8
8
  const TITLE = exports.TITLE = 'title';
9
9
  const SUBTITLE = exports.SUBTITLE = 'subtitle';
@@ -51,5 +51,8 @@ const ASK_AI = exports.ASK_AI = 'ask_ai';
51
51
  const FONT_SIZE = exports.FONT_SIZE = 'font-size';
52
52
  const FONT_SIZE_INCREASE = exports.FONT_SIZE_INCREASE = 'font-size-increase';
53
53
  const FONT_SIZE_REDUCE = exports.FONT_SIZE_REDUCE = 'font-size-reduce';
54
+
55
+ // group
56
+ const GROUP = exports.GROUP = 'group';
54
57
  const TOP_LEVEL_TYPES = exports.TOP_LEVEL_TYPES = [BLOCKQUOTE, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, ORDERED_LIST, UNORDERED_LIST, CHECK_LIST_ITEM, PARAGRAPH, CODE_BLOCK, TABLE];
55
58
  const INLINE_LEVEL_TYPES = exports.INLINE_LEVEL_TYPES = [IMAGE, LINK, MENTION, MENTION_TEMP];
@@ -158,6 +158,12 @@ Object.defineProperty(exports, "GOOGLE_FONT_CLASS", {
158
158
  return _font.GOOGLE_FONT_CLASS;
159
159
  }
160
160
  });
161
+ Object.defineProperty(exports, "GROUP", {
162
+ enumerable: true,
163
+ get: function () {
164
+ return _elementType.GROUP;
165
+ }
166
+ });
161
167
  Object.defineProperty(exports, "HEADER", {
162
168
  enumerable: true,
163
169
  get: function () {
@@ -47,7 +47,7 @@ Object.keys(_replaceNode).forEach(function (key) {
47
47
  }
48
48
  });
49
49
  });
50
- var _updateParentNode = require("./update-parent-node.js");
50
+ var _updateParentNode = require("./update-parent-node");
51
51
  Object.keys(_updateParentNode).forEach(function (key) {
52
52
  if (key === "default" || key === "__esModule") return;
53
53
  if (key in exports && exports[key] === _updateParentNode[key]) return;
@@ -57,4 +57,15 @@ Object.keys(_updateParentNode).forEach(function (key) {
57
57
  return _updateParentNode[key];
58
58
  }
59
59
  });
60
+ });
61
+ var _rebase = require("./rebase");
62
+ Object.keys(_rebase).forEach(function (key) {
63
+ if (key === "default" || key === "__esModule") return;
64
+ if (key in exports && exports[key] === _rebase[key]) return;
65
+ Object.defineProperty(exports, key, {
66
+ enumerable: true,
67
+ get: function () {
68
+ return _rebase[key];
69
+ }
70
+ });
60
71
  });
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.replaceRebaseNodeChildren = exports.replaceRebaseNode = exports.rebaseNode = exports.deleteRebaseNodeMark = void 0;
7
+ var _slate = require("@seafile/slate");
8
+ var _removeNodeChildren = require("./remove-node-children");
9
+ var _queries = require("../queries");
10
+ var _constants = require("../../constants");
11
+ const replaceRebaseNodeChildren = (editor, _ref) => {
12
+ let {
13
+ at,
14
+ nodes,
15
+ insertOptions,
16
+ removeOptions
17
+ } = _ref;
18
+ (0, _removeNodeChildren.removeNodeChildren)(editor, at, removeOptions);
19
+ _slate.Transforms.insertNodes(editor, nodes, {
20
+ ...insertOptions,
21
+ at: at.concat([0])
22
+ });
23
+ };
24
+ exports.replaceRebaseNodeChildren = replaceRebaseNodeChildren;
25
+ const replaceRebaseNode = function (editor) {
26
+ let {
27
+ at,
28
+ nodes,
29
+ insertOptions,
30
+ removeOptions
31
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
32
+ const parentPath = at.slice(0, -1);
33
+ const parentNode = at.length > 1 ? (0, _queries.getNode)(editor, parentPath) : {};
34
+ if ([_constants.ELEMENT_TYPE.ORDERED_LIST, _constants.ELEMENT_TYPE.UNORDERED_LIST].includes(parentNode.type)) {
35
+ const newChildren = parentNode.children.slice(0);
36
+ newChildren.splice(at[at.length - 1], 1, ...nodes);
37
+ replaceRebaseNodeChildren(editor, {
38
+ at: parentPath,
39
+ nodes: newChildren
40
+ });
41
+ return;
42
+ }
43
+ _slate.Transforms.removeNodes(editor, {
44
+ at,
45
+ ...removeOptions
46
+ });
47
+ _slate.Transforms.insertNodes(editor, nodes, {
48
+ ...insertOptions,
49
+ at
50
+ });
51
+ };
52
+ exports.replaceRebaseNode = replaceRebaseNode;
53
+ const deleteRebaseNodeMark = function (editor, path, element) {
54
+ let marks = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
55
+ const newElement = {
56
+ ...element
57
+ };
58
+ marks.forEach(markItem => {
59
+ newElement[markItem] && delete newElement[markItem];
60
+ });
61
+ _slate.Transforms.removeNodes(editor, {
62
+ at: path
63
+ });
64
+ _slate.Transforms.insertNodes(editor, newElement, {
65
+ at: path
66
+ });
67
+ };
68
+ exports.deleteRebaseNodeMark = deleteRebaseNodeMark;
69
+ const rebaseNode = (editor, callback) => {
70
+ if (!callback) return;
71
+ _slate.Editor.withoutNormalizing(editor, () => {
72
+ callback && callback();
73
+ });
74
+ };
75
+ exports.rebaseNode = rebaseNode;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.replaceNodeChildren = exports.replaceNode = exports.deleteNodeMark = void 0;
6
+ exports.replaceNodeChildren = exports.replaceNode = void 0;
7
7
  var _slate = require("@seafile/slate");
8
8
  var _removeNodeChildren = require("./remove-node-children");
9
9
  const replaceNodeChildren = (editor, _ref) => {
@@ -40,18 +40,4 @@ const replaceNode = function (editor) {
40
40
  });
41
41
  });
42
42
  };
43
- exports.replaceNode = replaceNode;
44
- const deleteNodeMark = function (editor, path, element) {
45
- let marks = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
46
- const newElement = {
47
- ...element
48
- };
49
- marks.forEach(markItem => {
50
- newElement[markItem] && delete newElement[markItem];
51
- });
52
- replaceNode(editor, {
53
- at: path,
54
- nodes: newElement
55
- });
56
- };
57
- exports.deleteNodeMark = deleteNodeMark;
43
+ exports.replaceNode = replaceNode;
@@ -4,13 +4,14 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.updateRebaseParentNodeByPath = void 0;
7
+ var _slate = require("@seafile/slate");
7
8
  var _constants = require("../../../constants");
9
+ var _constants2 = require("../../constants");
8
10
  var _queries = require("../queries");
9
- var _replaceNode = require("./replace-node");
10
11
  const updateRebaseParentNodeByPath = (editor, path) => {
11
12
  const parentPath = path.slice(0, -1);
12
13
  const parentNode = (0, _queries.getNode)(editor, parentPath);
13
- if (parentNode.children.filter(item => item[_constants.REBASE_MARK_KEY.REBASE_TYPE]).length !== 0) return;
14
+ if (![_constants2.ELEMENT_TYPE.ORDERED_LIST, _constants2.ELEMENT_TYPE.UNORDERED_LIST].includes(parentNode.type)) return;
14
15
  const newParentElement = {
15
16
  ...parentNode
16
17
  };
@@ -23,9 +24,11 @@ const updateRebaseParentNodeByPath = (editor, path) => {
23
24
  item[_constants.REBASE_MARK_KEY.ORIGIN] && delete item[_constants.REBASE_MARK_KEY.ORIGIN];
24
25
  return item;
25
26
  });
26
- (0, _replaceNode.replaceNode)(editor, {
27
- at: parentPath,
28
- nodes: newParentElement
27
+ _slate.Transforms.removeNodes(editor, {
28
+ at: parentPath
29
+ });
30
+ _slate.Transforms.insertNodes(editor, newParentElement, {
31
+ at: parentPath
29
32
  });
30
33
  };
31
34
  exports.updateRebaseParentNodeByPath = updateRebaseParentNodeByPath;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _constants = require("../../constants");
8
+ var _renderElem = require("./render-elem");
9
+ const GroupPlugin = {
10
+ type: _constants.ELEMENT_TYPE.GROUP,
11
+ renderElements: [_renderElem.renderGroup]
12
+ };
13
+ var _default = exports.default = GroupPlugin;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.renderGroup = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ const Group = _ref => {
10
+ let {
11
+ element,
12
+ attributes,
13
+ children,
14
+ className
15
+ } = _ref;
16
+ return /*#__PURE__*/_react.default.createElement("div", Object.assign({
17
+ "data-id": element.id
18
+ }, attributes, {
19
+ className: className
20
+ }), children);
21
+ };
22
+ const renderGroup = props => {
23
+ return /*#__PURE__*/_react.default.createElement(Group, props);
24
+ };
25
+ exports.renderGroup = renderGroup;
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.IMAGE_DISPLAY_TYPE = exports.IMAGE_BORDER_TYPE = void 0;
7
+ exports.SVG_WIDTH = exports.IMAGE_DISPLAY_TYPE = exports.IMAGE_BORDER_TYPE = void 0;
8
8
  var _blackBorder = _interopRequireDefault(require("../../../../assets/images/black-border.png"));
9
9
  var _greyBorder = _interopRequireDefault(require("../../../../assets/images/grey-border.png"));
10
10
  var _noBorder = _interopRequireDefault(require("../../../../assets/images/no-border.png"));
@@ -27,4 +27,5 @@ const IMAGE_BORDER_TYPE = exports.IMAGE_BORDER_TYPE = [{
27
27
  type: 'black',
28
28
  imgUrl: _blackBorder.default,
29
29
  value: '2px solid #41464A'
30
- }];
30
+ }];
31
+ const SVG_WIDTH = exports.SVG_WIDTH = 360;
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.updateImage = exports.selectImageWhenSelectPartial = exports.resetCursor = exports.queryCopyMoveProgressView = exports.isInsertImageMenuDisabled = exports.insertImageFiles = exports.insertImage = exports.hasSdocImages = exports.handleBase64Image = exports.getSingleImageFromFragment = exports.getImageURL = exports.getImageData = exports.generateImageNode = void 0;
7
+ exports.updateImage = exports.selectImageWhenSelectPartial = exports.resetCursor = exports.queryCopyMoveProgressView = exports.isInsertImageMenuDisabled = exports.insertImageFiles = exports.insertImage = exports.hasSdocImages = exports.handleBase64Image = exports.getSingleImageFromFragment = exports.getImageURL = exports.getImageData = exports.generateImageNode = exports.downloadImage = void 0;
8
8
  var _urlJoin = _interopRequireDefault(require("url-join"));
9
9
  var _slate = require("@seafile/slate");
10
10
  var _slateReact = require("@seafile/slate-react");
@@ -133,11 +133,25 @@ const updateImage = (editor, data) => {
133
133
  });
134
134
  };
135
135
  exports.updateImage = updateImage;
136
+ const downloadImage = async url => {
137
+ const response = await fetch(url);
138
+ const blob = await response.blob();
139
+ const file = new File([blob], 'downloaded_image', {
140
+ type: blob.type
141
+ });
142
+ // console.log(file, context.uploadLocalImage(file));
143
+ console.log(10);
144
+ const fileUrl = await _context.default.uploadLocalImage([file]);
145
+ console.log(fileUrl);
146
+ return fileUrl;
147
+ };
148
+ exports.downloadImage = downloadImage;
136
149
  const getImageURL = (data, editor) => {
137
150
  const {
138
151
  src: url,
139
152
  column_key
140
153
  } = data;
154
+ console.log('data', data);
141
155
  if (column_key) {
142
156
  const column = (0, _helpers.getColumnByKey)(editor.columns || [], column_key);
143
157
  const {
@@ -153,7 +167,12 @@ const getImageURL = (data, editor) => {
153
167
  return imgUrl;
154
168
  }
155
169
  }
156
- if (url && url.startsWith('http')) return url;
170
+ if (url && url.startsWith('http')) {
171
+ // return url;
172
+ console.log(6, url);
173
+ // debugger;
174
+ return Promise.resolve().then(() => downloadImage(url));
175
+ }
157
176
  const serviceUrl = _context.default.getSetting('serviceUrl');
158
177
  const assetsUrl = _context.default.getSetting('assetsUrl');
159
178
  return (0, _urlJoin.default)(serviceUrl, assetsUrl, url);
@@ -20,9 +20,8 @@ var _useScrollContext = require("../../../hooks/use-scroll-context");
20
20
  var _constants2 = require("./constants");
21
21
  var _constants3 = require("../../constants");
22
22
  var _constants4 = require("../../../../constants");
23
- var _imagePlaceholder = _interopRequireDefault(require("../../../assets/images/image-placeholder.png"));
24
23
  const Image = _ref => {
25
- var _imageRef$current, _imageRef$current2;
24
+ var _imageRef$current, _imageRef$current2, _imageRef$current3;
26
25
  let {
27
26
  element,
28
27
  editor,
@@ -57,6 +56,8 @@ const Image = _ref => {
57
56
  const [isShowImageHoverMenu, setIsShowImageHoverMenu] = (0, _react.useState)(false);
58
57
  const [menuPosition, setMenuPosition] = (0, _react.useState)({});
59
58
  const [caption, setCaption] = (0, _react.useState)((data === null || data === void 0 ? void 0 : data.caption) || '');
59
+ const [isLoading, setIsLoading] = (0, _react.useState)(true);
60
+ const svgWidth = movingWidth || element.data.width || _constants2.SVG_WIDTH;
60
61
  const registerEvent = (0, _react.useCallback)(eventList => {
61
62
  eventList.forEach(element => {
62
63
  document.addEventListener(element.eventName, element.event);
@@ -71,12 +72,17 @@ const Image = _ref => {
71
72
  var _resizerRef$current;
72
73
  event.preventDefault();
73
74
  event.stopPropagation();
75
+ if (!imageRef.current) return;
74
76
  const changeX = event.clientX - ((_resizerRef$current = resizerRef.current) === null || _resizerRef$current === void 0 ? void 0 : _resizerRef$current.getBoundingClientRect().left) - 5;
75
- const imageWidth = imageRef.current.width + changeX;
76
- if (imageWidth < 20) return;
77
- imageRef.current.width = imageWidth;
78
- setMovingWidth(imageWidth);
79
- }, []);
77
+ let newWidth = isShowImagePlaceholder ? imageRef.current.getBoundingClientRect().width + changeX : imageRef.current.width + changeX;
78
+ if (newWidth < 20) return;
79
+ if (isShowImagePlaceholder) {
80
+ imageRef.current.width.baseVal.value = newWidth;
81
+ } else {
82
+ imageRef.current.width = newWidth;
83
+ }
84
+ setMovingWidth(newWidth);
85
+ }, [isShowImagePlaceholder]);
80
86
  const onResizeEnd = (0, _react.useCallback)(event => {
81
87
  event.preventDefault();
82
88
  event.stopPropagation();
@@ -89,7 +95,7 @@ const Image = _ref => {
89
95
  }]);
90
96
  const newData = {
91
97
  ...element.data,
92
- width: imageRef.current.width
98
+ width: parseFloat(imageRef.current.style.width)
93
99
  };
94
100
  (0, _helpers.updateImage)(editor, newData);
95
101
 
@@ -194,6 +200,7 @@ const Image = _ref => {
194
200
  const reloadImage = (0, _react.useCallback)(() => {
195
201
  if (imageRef.current) {
196
202
  imageRef.current['src'] = (0, _helpers.getImageURL)(data, editor);
203
+ console.log((0, _helpers.getImageURL)(data, editor));
197
204
  setIsShowImagePlaceholder(false);
198
205
  }
199
206
  }, [data, editor]);
@@ -202,6 +209,7 @@ const Image = _ref => {
202
209
  if (data.src.startsWith('data:image/jpeg;base64')) {
203
210
  return (0, _helpers.handleBase64Image)(editor, path, data);
204
211
  }
212
+ setIsLoading(false);
205
213
  setIsShowImagePlaceholder(true);
206
214
  // External network images do not reload after failure to load
207
215
  if (!data.src.startsWith('http')) {
@@ -224,7 +232,22 @@ const Image = _ref => {
224
232
  });
225
233
  }
226
234
  }, [data, editor, element]);
227
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement("span", Object.assign({
235
+ (0, _react.useEffect)(() => {
236
+ if (imageRef.current) {
237
+ imageRef.current.onload = () => setIsLoading(false);
238
+ imageRef.current.onerror = onImageLoadError;
239
+ }
240
+ }, [element.data]);
241
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
242
+ className: "sdoc-image-process-container",
243
+ style: {
244
+ display: isLoading ? 'inline-block' : 'none'
245
+ }
246
+ }, /*#__PURE__*/_react.default.createElement("div", {
247
+ className: "loading-spinner"
248
+ }, /*#__PURE__*/_react.default.createElement("div", {
249
+ className: "spinner"
250
+ })), children), isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement("span", Object.assign({
228
251
  className: (0, _classnames.default)('sdoc-image-wrapper', className)
229
252
  }, attributes, {
230
253
  style: {
@@ -233,13 +256,60 @@ const Image = _ref => {
233
256
  onMouseOver: e => (0, _helpers.selectImageWhenSelectPartial)(e, editor, element, isSelected),
234
257
  contentEditable: "false",
235
258
  suppressContentEditableWarning: true
236
- }), /*#__PURE__*/_react.default.createElement("img", {
259
+ }), /*#__PURE__*/_react.default.createElement("svg", {
260
+ xmlns: "http://www.w3.org/2000/svg",
261
+ viewBox: `0 0 ${svgWidth} ${svgWidth}`,
262
+ preserveAspectRatio: "xMinYMin meet",
263
+ className: (0, _classnames.default)('sdoc-image-placeholder-wrapper', {
264
+ 'image-selected': isSelected
265
+ }),
237
266
  ref: imageRef,
238
- src: _imagePlaceholder.default,
239
267
  style: getImageStyle(),
240
- draggable: false,
241
- alt: ""
242
- }), children), !isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", Object.assign({
268
+ draggable: false
269
+ }, /*#__PURE__*/_react.default.createElement("rect", {
270
+ width: "100%",
271
+ height: "100%",
272
+ fill: "#f0f0f0"
273
+ }), /*#__PURE__*/_react.default.createElement("g", {
274
+ className: "sdoc-image-content-wrapper",
275
+ transform: `translate(${svgWidth / 2}, ${svgWidth / 2}) scale(${svgWidth / _constants2.SVG_WIDTH})`
276
+ }, /*#__PURE__*/_react.default.createElement("g", {
277
+ className: "sdoc-image-title",
278
+ transform: "translate(0, 0)"
279
+ }, /*#__PURE__*/_react.default.createElement("foreignObject", {
280
+ x: "-85",
281
+ y: "-16",
282
+ width: "20",
283
+ height: "28"
284
+ }, /*#__PURE__*/_react.default.createElement("div", {
285
+ className: "sdocfont sdoc-exclamation-circle"
286
+ })), /*#__PURE__*/_react.default.createElement("text", {
287
+ className: "sdoc-image-tip-title",
288
+ transform: "translate(-55, 4)",
289
+ fontSize: "20",
290
+ fill: "red",
291
+ fontFamily: "Arial, sans-serif"
292
+ }, t('Image_copy_error'))), /*#__PURE__*/_react.default.createElement("text", {
293
+ className: "sdoc-image-tip-content",
294
+ transform: "translate(0, 35)",
295
+ fontSize: "12",
296
+ textAnchor: "middle",
297
+ fill: "black",
298
+ fontFamily: "Arial, sans-serif"
299
+ }, t('Image_cannot_be_copied_Please_download_the_source_image')), /*#__PURE__*/_react.default.createElement("text", {
300
+ className: "sdoc-image-tip-content",
301
+ transform: "translate(0, 55)",
302
+ fontSize: "12",
303
+ textAnchor: "middle",
304
+ fill: "black",
305
+ fontFamily: "Arial, sans-serif"
306
+ }, t('And_select_insert_-_image_to_upload')))), isSelected && /*#__PURE__*/_react.default.createElement("span", {
307
+ className: "image-resizer",
308
+ ref: resizerRef,
309
+ onMouseDown: onResizeStart
310
+ }), isResizing && /*#__PURE__*/_react.default.createElement("span", {
311
+ className: "image-size"
312
+ }, /*#__PURE__*/_react.default.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current = imageRef.current) === null || _imageRef$current === void 0 ? void 0 : _imageRef$current.clientWidth))), /*#__PURE__*/_react.default.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/_react.default.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight)), children), !isShowImagePlaceholder && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", Object.assign({
243
313
  "data-id": element.id,
244
314
  className: (0, _classnames.default)('sdoc-image-wrapper', className)
245
315
  }, attributes, {
@@ -272,12 +342,12 @@ const Image = _ref => {
272
342
  onMouseDown: onResizeStart
273
343
  }), isResizing && /*#__PURE__*/_react.default.createElement("span", {
274
344
  className: "image-size"
275
- }, /*#__PURE__*/_react.default.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current = imageRef.current) === null || _imageRef$current === void 0 ? void 0 : _imageRef$current.clientWidth))), /*#__PURE__*/_react.default.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/_react.default.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === _constants3.IMAGE_BLOCK && show_caption && /*#__PURE__*/_react.default.createElement("input", {
345
+ }, /*#__PURE__*/_react.default.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current2 = imageRef.current) === null || _imageRef$current2 === void 0 ? void 0 : _imageRef$current2.clientWidth))), /*#__PURE__*/_react.default.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/_react.default.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === _constants3.IMAGE_BLOCK && show_caption && /*#__PURE__*/_react.default.createElement("input", {
276
346
  id: "sdoc-image-caption-input",
277
347
  ref: imageCaptionInputRef,
278
348
  className: "sdoc-image-caption-input-wrapper",
279
349
  style: {
280
- width: (data === null || data === void 0 ? void 0 : data.width) || ((_imageRef$current2 = imageRef.current) === null || _imageRef$current2 === void 0 ? void 0 : _imageRef$current2.clientWidth)
350
+ width: (data === null || data === void 0 ? void 0 : data.width) || ((_imageRef$current3 = imageRef.current) === null || _imageRef$current3 === void 0 ? void 0 : _imageRef$current3.clientWidth)
281
351
  },
282
352
  placeholder: t('Caption'),
283
353
  autoComplete: "off",
@@ -41,6 +41,12 @@ Object.defineProperty(exports, "FontPlugin", {
41
41
  return _font.default;
42
42
  }
43
43
  });
44
+ Object.defineProperty(exports, "GroupPlugin", {
45
+ enumerable: true,
46
+ get: function () {
47
+ return _group.default;
48
+ }
49
+ });
44
50
  Object.defineProperty(exports, "HeaderPlugin", {
45
51
  enumerable: true,
46
52
  get: function () {
@@ -181,7 +187,8 @@ var _quickInsert = _interopRequireDefault(require("./quick-insert"));
181
187
  var _wikiLink = _interopRequireDefault(require("./wiki-link"));
182
188
  var _seatableColumn = _interopRequireDefault(require("./seatable-column"));
183
189
  var _seatableTables = _interopRequireDefault(require("./seatable-tables"));
184
- const Plugins = [_markdown.default, _html.default, _header.default, _link.default, _blockquote.default, _list.default, _checkList.default, _codeBlock.default, _image.default, _video.default, _table.default, _multiColumn.default, _textStyle.default, _textAlign.default, _font.default, _sdocLink.default, _paragraph.default, _fileLink.default, _callout.default, _searchReplace.default, _quickInsert.default];
190
+ var _group = _interopRequireDefault(require("./group"));
191
+ const Plugins = [_markdown.default, _html.default, _header.default, _link.default, _blockquote.default, _list.default, _checkList.default, _codeBlock.default, _image.default, _video.default, _table.default, _multiColumn.default, _textStyle.default, _textAlign.default, _font.default, _sdocLink.default, _paragraph.default, _fileLink.default, _callout.default, _searchReplace.default, _quickInsert.default, _group.default];
185
192
  const WikiPlugins = exports.WikiPlugins = [...Plugins, _wikiLink.default];
186
193
  const CommentPlugins = exports.CommentPlugins = [_markdown.default, _html.default, _paragraph.default, _textStyle.default, _list.default, _image.default, _link.default, _mention.default, _blockquote.default];
187
194
  var _default = exports.default = Plugins;
@@ -10,6 +10,7 @@ var _core = require("../../../core");
10
10
  var _queries = require("../queries");
11
11
  var _transforms = require("../transforms");
12
12
  var _model = require("../model");
13
+ const validChildrenTypes = [_constants.GROUP, _constants.LIST_ITEM];
13
14
  const normalizeList = editor => {
14
15
  const {
15
16
  normalizeNode
@@ -26,7 +27,7 @@ const normalizeList = editor => {
26
27
  const children = (0, _core.getChildren)([node, path]);
27
28
  const nonLiChild = children.find(_ref2 => {
28
29
  let [child] = _ref2;
29
- return child.type !== _constants.LIST_ITEM;
30
+ return !validChildrenTypes.includes(child.type);
30
31
  });
31
32
  if (nonLiChild) {
32
33
  const listItem = (0, _model.generateEmptyListItem)();
@@ -39,7 +40,7 @@ const normalizeList = editor => {
39
40
  if ((0, _core.match)(node, [], {
40
41
  type: listTypes
41
42
  })) {
42
- if (!node.children.length || !node.children.find(item => item.type === _constants.LIST_ITEM)) {
43
+ if (!node.children.length || !node.children.find(child => validChildrenTypes.includes(child.type))) {
43
44
  _slate.Transforms.removeNodes(editor, {
44
45
  at: path
45
46
  });
@@ -15,7 +15,7 @@ const normalizeListItem = (editor, _ref) => {
15
15
  listItem
16
16
  } = _ref;
17
17
  let changed = false;
18
- const validLiChildrenTypes = [...(0, _queries.getListTypes)(), _constants.PARAGRAPH];
18
+ const validLiChildrenTypes = [...(0, _queries.getListTypes)(), _constants.PARAGRAPH, _constants.GROUP];
19
19
  const [, liPath] = listItem;
20
20
  const liChildren = (0, _core.getChildren)(listItem);
21
21
  const invalidLiChildrenPathRefs = liChildren.filter(_ref2 => {
@@ -210,6 +210,11 @@ const CustomRenderElement = props => {
210
210
  const [renderSeaTableTable] = _plugins.SeaTableViewsPlugin.renderElements;
211
211
  return renderSeaTableTable(props, editor);
212
212
  }
213
+ case _constants.ELEMENT_TYPE.GROUP:
214
+ {
215
+ const [renderGroup] = _plugins.GroupPlugin.renderElements;
216
+ return renderGroup(props);
217
+ }
213
218
  default:
214
219
  {
215
220
  const [renderParagraph] = _plugins.ParagraphPlugin.renderElements;
@@ -41,6 +41,7 @@
41
41
 
42
42
  .sdoc-rebase-my-changes > *:first-child,
43
43
  .sdoc-rebase-other-changes > *:first-child {
44
- margin: 0;
44
+ margin-top: 0 !important;
45
+ margin-bottom: 0 !important;
45
46
  padding: 0.8em 0 0.8em 0.2em;
46
47
  }
@@ -34,7 +34,7 @@ const RebaseDeleteModifyDecorate = _ref => {
34
34
  }, [editor, element]);
35
35
  const deleteMark = (0, _react.useCallback)(() => {
36
36
  const path = (0, _core.findPath)(editor, element);
37
- (0, _core.deleteNodeMark)(editor, path, element, _constants2.REBASE_MARKS);
37
+ (0, _core.deleteRebaseNodeMark)(editor, path, element, _constants2.REBASE_MARKS);
38
38
  if (element.type === _constants.ELEMENT_TYPE.LIST_ITEM) {
39
39
  (0, _core.updateRebaseParentNodeByPath)(editor, path);
40
40
  }
@@ -34,7 +34,7 @@ const RebaseModifyDeleteDecorate = _ref => {
34
34
  }, [editor, element]);
35
35
  const deleteMark = (0, _react.useCallback)(() => {
36
36
  const path = (0, _core.findPath)(editor, element);
37
- (0, _core.deleteNodeMark)(editor, path, element, _constants2.REBASE_MARKS);
37
+ (0, _core.deleteRebaseNodeMark)(editor, path, element, _constants2.REBASE_MARKS);
38
38
  if (element.type === _constants.ELEMENT_TYPE.LIST_ITEM) {
39
39
  (0, _core.updateRebaseParentNodeByPath)(editor, path);
40
40
  }
@@ -24,47 +24,79 @@ const RebaseModifyModifyDecorate = _ref => {
24
24
  } = (0, _reactI18next.useTranslation)('sdoc-editor');
25
25
  const editor = (0, _slateReact.useSlateStatic)();
26
26
  const useMasterChanges = (0, _react.useCallback)(() => {
27
- const path = (0, _core.findPath)(editor, element);
28
- (0, _core.deleteNodeMark)(editor, path, element[_constants2.REBASE_MARK_KEY.OLD_ELEMENT], _constants2.REBASE_MARKS);
29
- const nextElementPath = [...path];
30
- nextElementPath[path.length - 1] = path[path.length - 1] + 1;
31
- _slate.Transforms.removeNodes(editor, {
32
- at: nextElementPath
33
- });
34
- if (element.type === _constants.ELEMENT_TYPE.LIST_ITEM) {
27
+ (0, _core.rebaseNode)(editor, () => {
28
+ const path = (0, _core.findPath)(editor, element);
29
+
30
+ // delete my changes
31
+ const nextElementPath = [...path];
32
+ nextElementPath[path.length - 1] = path[path.length - 1] + 1;
33
+ _slate.Transforms.removeNodes(editor, {
34
+ at: nextElementPath
35
+ });
36
+
37
+ // update master changes
38
+ if (element.type === _constants.ELEMENT_TYPE.GROUP) {
39
+ (0, _core.replaceRebaseNode)(editor, {
40
+ at: path,
41
+ nodes: element.children
42
+ });
43
+ } else {
44
+ (0, _core.deleteRebaseNodeMark)(editor, path, element[_constants2.REBASE_MARK_KEY.OLD_ELEMENT], _constants2.REBASE_MARKS);
45
+ }
35
46
  (0, _core.updateRebaseParentNodeByPath)(editor, path);
36
- }
47
+ });
37
48
 
38
49
  // eslint-disable-next-line react-hooks/exhaustive-deps
39
50
  }, [editor, element]);
40
- const useCurrentChanges = (0, _react.useCallback)(() => {
41
- const path = (0, _core.findPath)(editor, element);
42
- const currentElementPath = [...path];
43
- currentElementPath[path.length - 1] = path[path.length - 1] + 1;
44
- const currentElement = (0, _core.getNode)(editor, currentElementPath);
45
- const newCurrentElement = (0, _deepCopy.default)(currentElement);
46
- (0, _core.deleteNodeMark)(editor, currentElementPath, newCurrentElement, _constants2.REBASE_MARKS);
47
- _slate.Transforms.removeNodes(editor, {
48
- at: path
49
- });
50
- if (element.type === _constants.ELEMENT_TYPE.LIST_ITEM) {
51
+ const useMyChanges = (0, _react.useCallback)(() => {
52
+ (0, _core.rebaseNode)(editor, () => {
53
+ const path = (0, _core.findPath)(editor, element);
54
+ const currentElementPath = [...path];
55
+ currentElementPath[path.length - 1] = path[path.length - 1] + 1;
56
+ const currentElement = (0, _core.getNode)(editor, currentElementPath);
57
+ const newCurrentElement = (0, _deepCopy.default)(currentElement);
58
+ if (element.type === _constants.ELEMENT_TYPE.GROUP) {
59
+ (0, _core.replaceRebaseNode)(editor, {
60
+ at: currentElementPath,
61
+ nodes: newCurrentElement.children
62
+ });
63
+ } else {
64
+ (0, _core.deleteRebaseNodeMark)(editor, currentElementPath, newCurrentElement, _constants2.REBASE_MARKS);
65
+ }
66
+ _slate.Transforms.removeNodes(editor, {
67
+ at: path
68
+ });
51
69
  (0, _core.updateRebaseParentNodeByPath)(editor, path);
52
- }
70
+ });
53
71
 
54
72
  // eslint-disable-next-line react-hooks/exhaustive-deps
55
73
  }, [editor, element]);
56
74
  const useBothChanges = (0, _react.useCallback)(() => {
57
- // delete element marks
58
- const path = (0, _core.findPath)(editor, element);
59
- (0, _core.deleteNodeMark)(editor, path, element, _constants2.REBASE_MARKS);
75
+ (0, _core.rebaseNode)(editor, () => {
76
+ const path = (0, _core.findPath)(editor, element);
77
+ const nextElementPath = [...path.slice(0, -1), path[path.length - 1] + 1];
78
+ const nextElement = (0, _core.getNode)(editor, nextElementPath);
79
+ if (element.type === _constants.ELEMENT_TYPE.GROUP) {
80
+ // replace next element
81
+ (0, _core.replaceRebaseNode)(editor, {
82
+ at: nextElementPath,
83
+ nodes: nextElement.children
84
+ });
60
85
 
61
- // delete next element marks
62
- const nextElementPath = [...path.slice(0, -1), path[path.length - 1] + 1];
63
- const nextElement = (0, _core.getNode)(editor, nextElementPath);
64
- (0, _core.deleteNodeMark)(editor, nextElementPath, nextElement, _constants2.REBASE_MARKS);
65
- if (element.type === _constants.ELEMENT_TYPE.LIST_ITEM) {
86
+ // replace current element
87
+ (0, _core.replaceRebaseNode)(editor, {
88
+ at: path,
89
+ nodes: element.children
90
+ });
91
+ } else {
92
+ // delete element marks
93
+ (0, _core.deleteRebaseNodeMark)(editor, path, element, _constants2.REBASE_MARKS);
94
+
95
+ // delete next element marks
96
+ (0, _core.deleteRebaseNodeMark)(editor, nextElementPath, nextElement, _constants2.REBASE_MARKS);
97
+ }
66
98
  (0, _core.updateRebaseParentNodeByPath)(editor, path);
67
- }
99
+ });
68
100
 
69
101
  // eslint-disable-next-line react-hooks/exhaustive-deps
70
102
  }, [editor, element]);
@@ -79,7 +111,7 @@ const RebaseModifyModifyDecorate = _ref => {
79
111
  className: "mr-2 ml-2"
80
112
  }, '|'), /*#__PURE__*/_react.default.createElement("div", {
81
113
  className: "sdoc-rebase-btn",
82
- onClick: useCurrentChanges
114
+ onClick: useMyChanges
83
115
  }, t('Keep_my_modification')), /*#__PURE__*/_react.default.createElement("div", {
84
116
  className: "mr-2 ml-2"
85
117
  }, '|'), /*#__PURE__*/_react.default.createElement("div", {
@@ -37,7 +37,9 @@ const getTopLevelChanges = changes => {
37
37
  if (parentNode instanceof Document) {
38
38
  break;
39
39
  } else {
40
+ var _dom4, _dom4$dataset;
40
41
  dom = parentNode;
42
+ if ((_dom4 = dom) !== null && _dom4 !== void 0 && (_dom4$dataset = _dom4.dataset) !== null && _dom4$dataset !== void 0 && _dom4$dataset.id && !dom.classList.contains('table-cell')) break;
41
43
  }
42
44
  }
43
45
  topLevelChanges.push(dom.dataset.id);
@@ -32,6 +32,49 @@ const hasConflict = content => {
32
32
  return flag;
33
33
  };
34
34
  exports.hasConflict = hasConflict;
35
+ const expandGroup = content => {
36
+ if ([_constants2.ELEMENT_TYPE.UNORDERED_LIST, _constants2.ELEMENT_TYPE.ORDERED_LIST].includes(content.type)) {
37
+ return [{
38
+ ...content,
39
+ children: content.children.map(item => {
40
+ if (item.type === _constants2.ELEMENT_TYPE.GROUP) {
41
+ return expandGroup(item);
42
+ }
43
+ return item;
44
+ }).flat(1)
45
+ }];
46
+ }
47
+ return content.type === _constants2.ELEMENT_TYPE.GROUP ? content.children : [content];
48
+ };
49
+ const mergeChanges = changes => {
50
+ if (!Array.isArray(changes) || changes.length === 0) return changes;
51
+ let value = [];
52
+ let i = 0;
53
+ while (i < changes.length) {
54
+ const change = changes[i];
55
+ const lastChange = value[value.length - 1];
56
+ if (change && lastChange && change[_constants.REBASE_MARK_KEY.MODIFY_TYPE] === _constants.MODIFY_TYPE.ADD && lastChange[_constants.REBASE_MARK_KEY.MODIFY_TYPE] === _constants.MODIFY_TYPE.DELETE) {
57
+ value = value.slice(0, value.length - 1);
58
+ lastChange[_constants.REBASE_MARK_KEY.MODIFY_TYPE] && delete lastChange[_constants.REBASE_MARK_KEY.MODIFY_TYPE];
59
+ change[_constants.REBASE_MARK_KEY.MODIFY_TYPE] && delete change[_constants.REBASE_MARK_KEY.MODIFY_TYPE];
60
+ value.push({
61
+ id: change.id.endsWith('_group') ? change.id : change.id + '_group',
62
+ type: _constants2.ELEMENT_TYPE.GROUP,
63
+ [_constants.REBASE_MARK_KEY.MODIFY_TYPE]: _constants.MODIFY_TYPE.MODIFY,
64
+ children: expandGroup(change),
65
+ [_constants.REBASE_MARK_KEY.OLD_ELEMENT]: {
66
+ id: lastChange.id.endsWith('_group') ? lastChange.id : lastChange.id + '_group',
67
+ type: _constants2.ELEMENT_TYPE.GROUP,
68
+ children: expandGroup(lastChange)
69
+ }
70
+ });
71
+ } else {
72
+ value.push(change);
73
+ }
74
+ i++;
75
+ }
76
+ return value;
77
+ };
35
78
  const getChanges = function (masterContent, revisionContent) {
36
79
  let childrenName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children';
37
80
  const {
@@ -51,17 +94,21 @@ const getChanges = function (masterContent, revisionContent) {
51
94
  removed
52
95
  } = idDiff;
53
96
  if (added) {
54
- const addedList = value.map(item => ({
55
- ...currentContentMap[item],
56
- [_constants.REBASE_MARK_KEY.MODIFY_TYPE]: _constants.MODIFY_TYPE.ADD
57
- }));
58
- content.push(...addedList);
97
+ // merge consecutive identical operations
98
+ content.push({
99
+ id: value[0] + '_group',
100
+ type: _constants2.ELEMENT_TYPE.GROUP,
101
+ [_constants.REBASE_MARK_KEY.MODIFY_TYPE]: _constants.MODIFY_TYPE.ADD,
102
+ children: value.map(item => currentContentMap[item])
103
+ });
59
104
  } else if (removed) {
60
- const deletedList = value.map(item => ({
61
- ...masterContentMap[item],
62
- [_constants.REBASE_MARK_KEY.MODIFY_TYPE]: _constants.MODIFY_TYPE.DELETE
63
- }));
64
- content.push(...deletedList);
105
+ // merge consecutive identical operations
106
+ content.push({
107
+ id: value[0] + '_group',
108
+ type: _constants2.ELEMENT_TYPE.GROUP,
109
+ [_constants.REBASE_MARK_KEY.MODIFY_TYPE]: _constants.MODIFY_TYPE.DELETE,
110
+ children: value.map(item => masterContentMap[item])
111
+ });
65
112
  } else {
66
113
  value.forEach(elementId => {
67
114
  if (_objectUtils.default.isSameObject(masterContentMap[elementId], currentContentMap[elementId])) {
@@ -87,7 +134,7 @@ const getChanges = function (masterContent, revisionContent) {
87
134
  });
88
135
  }
89
136
  });
90
- return content;
137
+ return mergeChanges(content);
91
138
  };
92
139
  const getMergeElement = (diffElement, baseElement) => {
93
140
  const modifyType = diffElement[_constants.REBASE_MARK_KEY.MODIFY_TYPE];
@@ -99,7 +146,7 @@ const getMergeElement = (diffElement, baseElement) => {
99
146
  // revision does not have this element, master has this element
100
147
  if (modifyType === _constants.MODIFY_TYPE.DELETE) {
101
148
  // base content does not have this element, indicating that it is newly added by master and needs to be retained, and will not be counted as a conflict.
102
- if (!baseElement) return [newElement];
149
+ if (!baseElement) return expandGroup(newElement);
103
150
 
104
151
  // base content has this element, master modified it, indicating that revision deleted it, and the user manually selected the conflict
105
152
  if (!_objectUtils.default.isSameObject(baseElement, diffElement, [_constants.REBASE_MARK_KEY.MODIFY_TYPE])) {
@@ -114,7 +161,7 @@ const getMergeElement = (diffElement, baseElement) => {
114
161
  // revision has this element, master does not have this element
115
162
  if (modifyType === _constants.MODIFY_TYPE.ADD) {
116
163
  // base content does not have this element, indicating that it is newly added by revision and needs to be retained, and will not be counted as a conflict.
117
- if (!baseElement) return [newElement];
164
+ if (!baseElement) return expandGroup(newElement);
118
165
 
119
166
  // master deleted it, revision modified it, and the user manually selected the conflict
120
167
  if (!_objectUtils.default.isSameObject(baseElement, diffElement, [_constants.REBASE_MARK_KEY.MODIFY_TYPE])) {
@@ -184,10 +231,10 @@ const getMergeElement = (diffElement, baseElement) => {
184
231
  [_constants.REBASE_MARK_KEY.ORIGIN]: _constants.REBASE_ORIGIN.MY
185
232
  }];
186
233
  }
187
- if (_objectUtils.default.isSameObject(masterElement, baseElement)) return [newElement];
234
+ if (_objectUtils.default.isSameObject(masterElement, baseElement)) return expandGroup(newElement);
188
235
  if (_objectUtils.default.isSameObject(newElement, baseElement)) return [masterElement];
189
236
  if (_objectUtils.default.isSameObject(masterElement, newElement, ['type'])) {
190
- if (_objectUtils.default.isSameObject(masterElement, baseElement, ['type'])) return [newElement];
237
+ if (_objectUtils.default.isSameObject(masterElement, baseElement, ['type'])) return expandGroup(newElement);
191
238
  if (_objectUtils.default.isSameObject(newElement, baseElement, ['type'])) return [masterElement];
192
239
  }
193
240
 
@@ -199,7 +246,7 @@ const getMergeElement = (diffElement, baseElement) => {
199
246
  }];
200
247
  }
201
248
  newElement[_constants.REBASE_MARK_KEY.OLD_ELEMENT] && delete newElement[_constants.REBASE_MARK_KEY.OLD_ELEMENT];
202
- return [newElement];
249
+ return expandGroup(newElement);
203
250
  };
204
251
  const getMergeContent = function (baseContent, diffChanges) {
205
252
  let childrenName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children';
@@ -33,12 +33,9 @@ const ChangesCount = _ref => {
33
33
  }
34
34
  }, 100);
35
35
  }).then(() => {
36
- console.log('allchange', allChanges);
37
36
  if (allChanges.changes.length !== 0) {
38
37
  const topLevelChanges = (0, _diff.getTopLevelChanges)(allChanges.changes);
39
- console.log(topLevelChanges);
40
38
  const changes = (0, _diff.getMergedChanges)(topLevelChanges, allChanges.value);
41
- console.log(9, changes);
42
39
  setChanges(changes);
43
40
  }
44
41
  });
@@ -78,12 +75,10 @@ const ChangesCount = _ref => {
78
75
  // eslint-disable-next-line react-hooks/exhaustive-deps
79
76
  }, [changes, currentDiffIndex]);
80
77
  if (!Array.isArray(changes) || changes.length === 0) {
81
- console.log('change', changes);
82
78
  return /*#__PURE__*/_react.default.createElement("div", {
83
79
  className: "sdoc-revision-changes-container d-flex align-items-center pl-2 pr-2 ml-4"
84
80
  }, t('No_changes'));
85
81
  }
86
- console.log('changes', changes);
87
82
  const changesCount = changes.length;
88
83
  return /*#__PURE__*/_react.default.createElement("div", {
89
84
  className: "sdoc-revision-changes-container d-flex align-items-center ml-4"
@@ -3,7 +3,7 @@
3
3
  width: fit-content;
4
4
  border: 1px solid #E5E5E5;
5
5
  border-radius: 3px;
6
- line-height: 28px;
6
+ line-height: 26px;
7
7
  text-align: center;
8
8
  padding: 0 16px;
9
9
  margin-left: 1rem;
@@ -52,7 +52,6 @@ const SimpleEditor = _ref => {
52
52
  // eslint-disable-next-line react-hooks/exhaustive-deps
53
53
  }, []);
54
54
  const setDiffChanges = (0, _react.useCallback)(diff => {
55
- console.log(32323);
56
55
  setChanges(diff);
57
56
  // eslint-disable-next-line react-hooks/exhaustive-deps
58
57
  }, [isShowChanges]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "1.0.212-alph-0.1.9",
3
+ "version": "1.0.212-alph-2.1.0",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Videolink hinzufügen",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Add video link",
611
611
  "Link_Seafile_video_file": "Link Seafile video file",
612
612
  "Select_video_file": "Select video file",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "Добавить ссылку на видео",
611
611
  "Link_Seafile_video_file": "Ссылка на видео файл Seafile",
612
612
  "Select_video_file": "Выбрать видео файл",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
615
+ "And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload."
614
616
  }
@@ -610,5 +610,7 @@
610
610
  "Add_video_link": "添加视频链接",
611
611
  "Link_Seafile_video_file": "链接Seafile视频文件",
612
612
  "Select_video_file": "选择视频文件",
613
- "Support_Youtube_Tencent_Bilibili_and_more": "支持Youtube,腾讯视频,B站及其他平台"
613
+ "Support_Youtube_Tencent_Bilibili_and_more": "支持Youtube,腾讯视频,B站及其他平台",
614
+ "Image_cannot_be_copied_Please_download_the_source_image": "此照片不支持复制,请下载原图",
615
+ "And_select_insert_-_image_to_upload": "后点击工具栏「插入」- 「照片」上传"
614
616
  }