@seafile/sdoc-editor 0.3.21 → 0.3.23

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 (34) hide show
  1. package/dist/api/seafile-api.js +8 -6
  2. package/dist/basic-sdk/assets/css/sdoc-editor-plugins.css +5 -0
  3. package/dist/basic-sdk/comment/components/comment-item-wrapper.js +5 -3
  4. package/dist/basic-sdk/comment/components/comment-list.css +15 -7
  5. package/dist/basic-sdk/comment/components/global-comment/index.css +1 -1
  6. package/dist/basic-sdk/editor/revision-editor.js +74 -0
  7. package/dist/basic-sdk/editor/sdoc-editor.js +23 -18
  8. package/dist/basic-sdk/extension/commons/insert-element-dialog/index.js +3 -2
  9. package/dist/basic-sdk/extension/plugins/image/helpers.js +8 -6
  10. package/dist/basic-sdk/extension/plugins/list/render-elem.js +5 -1
  11. package/dist/basic-sdk/extension/plugins/table/constants/index.js +7 -5
  12. package/dist/basic-sdk/extension/plugins/table/helpers.js +114 -33
  13. package/dist/basic-sdk/extension/plugins/table/menu/table-context-menu/index.js +13 -2
  14. package/dist/basic-sdk/extension/plugins/table/menu/table-menu/index.js +3 -2
  15. package/dist/basic-sdk/extension/plugins/table/plugin.js +0 -1
  16. package/dist/basic-sdk/extension/plugins/table/popover/table-template/index.js +2 -2
  17. package/dist/basic-sdk/extension/plugins/table/popover/table-template/sample-table.js +13 -15
  18. package/dist/basic-sdk/extension/plugins/table/render/alternate-color.css +8 -8
  19. package/dist/basic-sdk/extension/plugins/table/render/index.js +2 -5
  20. package/dist/basic-sdk/extension/plugins/table/render/render-cell.js +25 -4
  21. package/dist/basic-sdk/index.js +2 -1
  22. package/dist/basic-sdk/socket/socket-manager.js +6 -0
  23. package/dist/basic-sdk/socket/with-socket-io.js +1 -0
  24. package/dist/basic-sdk/views/revision-diff-viewer.js +6 -0
  25. package/dist/components/tooltip/index.css +4 -0
  26. package/dist/context.js +2 -2
  27. package/dist/pages/simple-editor.js +28 -14
  28. package/package.json +1 -1
  29. package/public/media/sdoc-editor-font/iconfont.eot +0 -0
  30. package/public/media/sdoc-editor-font/iconfont.svg +3 -9
  31. package/public/media/sdoc-editor-font/iconfont.ttf +0 -0
  32. package/public/media/sdoc-editor-font/iconfont.woff +0 -0
  33. package/public/media/sdoc-editor-font/iconfont.woff2 +0 -0
  34. package/public/media/sdoc-editor-font.css +13 -12
@@ -29,14 +29,16 @@ class SeafileAPI {
29
29
  var d = Date.now();
30
30
  return 'image-' + d.toString() + file.name.slice(file.name.lastIndexOf('.'));
31
31
  }
32
- uploadSdocImage(docUuid, imageFile) {
32
+ uploadSdocImage(docUuid, imageFiles) {
33
33
  const url = '/api/v2.1/seadoc/upload-image/' + docUuid + '/';
34
34
  const form = new FormData();
35
- const fileName = this.getImageFileNameWithTimestamp(imageFile);
36
- const file = new File([imageFile], fileName, {
37
- type: imageFile.type
38
- });
39
- form.append('file', file);
35
+ for (const fileItem of imageFiles) {
36
+ const fileName = this.getImageFileNameWithTimestamp(fileItem);
37
+ const file = new File([fileItem], fileName, {
38
+ type: fileItem.type
39
+ });
40
+ form.append('file', file);
41
+ }
40
42
  return this.req.post(url, form);
41
43
  }
42
44
  getSdocDownloadImageUrl(docUuid, imageName) {
@@ -28,6 +28,10 @@
28
28
  padding-left: 1.2em !important;
29
29
  }
30
30
 
31
+ .sdoc-editor-container .article .list-container .sdoc-li-blod::marker {
32
+ font-weight: bold;
33
+ }
34
+
31
35
  /* check list */
32
36
  .sdoc-editor-container .article .sdoc-checkbox-container {
33
37
  padding: 0px 2px;
@@ -161,4 +165,5 @@
161
165
 
162
166
  .sdoc-editor-container .article .virtual-link:hover {
163
167
  text-decoration: underline;
168
+ text-underline-position: under;
164
169
  }
@@ -238,10 +238,12 @@ const CommentItemWrapper = _ref => {
238
238
  className: className,
239
239
  onClick: onItemClick
240
240
  }, element && /*#__PURE__*/React.createElement("div", {
241
- className: "comment-item-selected-text"
241
+ className: "comment-item-selected-text-container"
242
242
  }, /*#__PURE__*/React.createElement("i", {
243
- className: "sdocfont sdoc-selected-text mr-2"
244
- }), Node.string(element)), /*#__PURE__*/React.createElement("ul", {
243
+ className: "sdocfont sdoc-comment-quote mr-2"
244
+ }), /*#__PURE__*/React.createElement("div", {
245
+ className: "comment-item-selected-text"
246
+ }, Node.string(element))), /*#__PURE__*/React.createElement("ul", {
245
247
  ref: listRef,
246
248
  className: "comment-item-list"
247
249
  }, /*#__PURE__*/React.createElement(CommentItemContent, {
@@ -18,19 +18,27 @@
18
18
  box-shadow: 0 1px 3px rgba(0,0,0,.3), 0 4px 8px 3px rgba(0,0,0,.15);
19
19
  }
20
20
 
21
- .sdoc-comment-list-container .comment-item-selected-text {
22
- padding: 6px 16px;
21
+ .sdoc-comment-list-container .comment-item-selected-text-container {
23
22
  width: 100%;
23
+ height: 32px;
24
+ display: flex;
25
+ padding: 6px 16px;
26
+ align-items: center;
24
27
  overflow: hidden;
25
- text-overflow: ellipsis;
26
- white-space: nowrap;
27
- font-size: 14px;
28
- line-height: 20px;
29
28
  border-radius: 8px 8px 0 0;
30
29
  }
31
30
 
32
- .sdoc-comment-list-container .comment-item-selected-text .sdoc-selected-text {
31
+ .sdoc-comment-list-container .comment-item-selected-text-container .sdoc-comment-quote {
33
32
  font-size: 12px;
33
+ flex-shrink: 0;
34
+ }
35
+
36
+ .sdoc-comment-list-container .comment-item-selected-text-container .comment-item-selected-text {
37
+ flex: 1;
38
+ font-size: 14px;
39
+ overflow: hidden;
40
+ text-overflow: ellipsis;
41
+ white-space: nowrap;
34
42
  }
35
43
 
36
44
  .sdoc-comment-list-container .comment-item-list {
@@ -136,7 +136,7 @@
136
136
  border: 1px solid #c7c7c7;
137
137
  }
138
138
 
139
- .global-comments-popover .sdoc-comment-list-container .comment-item-selected-text {
139
+ .global-comments-popover .sdoc-comment-list-container .comment-item-selected-text-container {
140
140
  background-color: #F5F5F5;
141
141
  border-bottom: 1px solid #c7c7c7;
142
142
  }
@@ -0,0 +1,74 @@
1
+ import React, { useEffect, useRef, useImperativeHandle, forwardRef, useMemo } from 'react';
2
+ import SdocEditor from './sdoc-editor';
3
+ import { RevisionDiffViewer } from '../views';
4
+ import context from '../../context';
5
+ import { createDefaultEditor } from '../extension';
6
+ import withNodeId from '../node-id';
7
+ import { withSocketIO } from '../socket';
8
+ import { PAGE_EDIT_AREA_WIDTH } from '../constants';
9
+ const RevisionEditor = forwardRef((_ref, ref) => {
10
+ let {
11
+ isShowChanges,
12
+ isReloading,
13
+ document,
14
+ revisionContent,
15
+ didMountCallback
16
+ } = _ref;
17
+ const editorRef = useRef(null);
18
+ const editor = useMemo(() => {
19
+ const defaultEditor = createDefaultEditor();
20
+ const editorConfig = context.getEditorConfig();
21
+ const newEditor = withNodeId(withSocketIO(defaultEditor, {
22
+ document,
23
+ config: editorConfig
24
+ }));
25
+ const {
26
+ cursors
27
+ } = document;
28
+ newEditor.cursors = cursors || {};
29
+ newEditor.width = PAGE_EDIT_AREA_WIDTH; // default width
30
+ return newEditor;
31
+
32
+ // eslint-disable-next-line react-hooks/exhaustive-deps
33
+ }, []);
34
+
35
+ // useMount: init socket connection
36
+ useEffect(() => {
37
+ editor.openConnection();
38
+ return () => {
39
+ editor.closeConnection();
40
+ };
41
+
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+
45
+ // The parent component can call the method of this component through ref
46
+ useImperativeHandle(ref, () => ({
47
+ setSlateValue: document => {
48
+ return editorRef.current.setSlateValue(document);
49
+ },
50
+ updateDocumentVersion: document => {
51
+ return editorRef.current.updateDocumentVersion(document);
52
+ },
53
+ // get value
54
+ getSlateValue: () => {
55
+ return editorRef.current.getSlateValue();
56
+ }
57
+
58
+ // eslint-disable-next-line react-hooks/exhaustive-deps
59
+ }), [editorRef]);
60
+ if (isShowChanges) {
61
+ return /*#__PURE__*/React.createElement(RevisionDiffViewer, {
62
+ editor: editor,
63
+ revisionContent: revisionContent,
64
+ didMountCallback: didMountCallback
65
+ });
66
+ }
67
+ return /*#__PURE__*/React.createElement(SdocEditor, {
68
+ ref: editorRef,
69
+ editor: editor,
70
+ isReloading: isReloading,
71
+ document: document
72
+ });
73
+ });
74
+ export default RevisionEditor;
@@ -19,10 +19,11 @@ import { isMobile } from '../../utils';
19
19
  import { CollaboratorsProvider } from '../../hooks';
20
20
  const SdocEditor = forwardRef((_ref, ref) => {
21
21
  let {
22
+ editor,
22
23
  document,
23
24
  isReloading
24
25
  } = _ref;
25
- const editor = useMemo(() => {
26
+ const validEditor = editor || useMemo(() => {
26
27
  const defaultEditor = createDefaultEditor();
27
28
  const editorConfig = context.getEditorConfig();
28
29
  const newEditor = withNodeId(withSocketIO(defaultEditor, {
@@ -39,12 +40,16 @@ const SdocEditor = forwardRef((_ref, ref) => {
39
40
  // eslint-disable-next-line react-hooks/exhaustive-deps
40
41
  }, []);
41
42
  const [slateValue, setSlateValue] = useState(document.children);
43
+ useEffect(() => {
44
+ validEditor.readonly = false;
45
+ }, []);
42
46
 
43
47
  // useMount: init socket connection
44
48
  useEffect(() => {
45
- editor.openConnection();
49
+ if (editor) return;
50
+ validEditor.openConnection();
46
51
  return () => {
47
- editor.closeConnection();
52
+ validEditor.closeConnection();
48
53
  };
49
54
 
50
55
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -53,16 +58,16 @@ const SdocEditor = forwardRef((_ref, ref) => {
53
58
  // useMount: focus editor
54
59
  useEffect(() => {
55
60
  const timer = setTimeout(() => {
56
- const [firstNode] = editor.children;
61
+ const [firstNode] = validEditor.children;
57
62
  if (firstNode) {
58
63
  const [firstNodeFirstChild] = firstNode.children;
59
64
  if (firstNodeFirstChild) {
60
- const endOfFirstNode = Editor.end(editor, [0, 0]);
65
+ const endOfFirstNode = Editor.end(validEditor, [0, 0]);
61
66
  const range = {
62
67
  anchor: endOfFirstNode,
63
68
  focus: endOfFirstNode
64
69
  };
65
- focusEditor(editor, range);
70
+ focusEditor(validEditor, range);
66
71
  }
67
72
  }
68
73
  }, 300);
@@ -76,11 +81,11 @@ const SdocEditor = forwardRef((_ref, ref) => {
76
81
  useImperativeHandle(ref, () => ({
77
82
  setSlateValue: document => {
78
83
  // Force update of editor's child elements
79
- editor.children = document.children;
84
+ validEditor.children = document.children;
80
85
  setSlateValue([...document.children]);
81
86
  },
82
87
  updateDocumentVersion: document => {
83
- editor.updateDocumentVersion(document);
88
+ validEditor.updateDocumentVersion(document);
84
89
  },
85
90
  // get value
86
91
  getSlateValue: () => {
@@ -90,7 +95,7 @@ const SdocEditor = forwardRef((_ref, ref) => {
90
95
  }
91
96
 
92
97
  // eslint-disable-next-line react-hooks/exhaustive-deps
93
- }), [document, editor, slateValue]);
98
+ }), [document, validEditor, slateValue]);
94
99
  const isFreezed = context.getSetting('isFreezed');
95
100
  if (isReloading) {
96
101
  return /*#__PURE__*/React.createElement("div", {
@@ -99,47 +104,47 @@ const SdocEditor = forwardRef((_ref, ref) => {
99
104
  }
100
105
  if (isMobile) {
101
106
  return /*#__PURE__*/React.createElement(EditorContainer, {
102
- editor: editor,
107
+ editor: validEditor,
103
108
  readonly: true
104
109
  }, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement(EditorContent, {
105
110
  docValue: slateValue,
106
111
  readonly: true,
107
112
  showOutline: false
108
113
  }, /*#__PURE__*/React.createElement(ReadOnlyArticle, {
109
- editor: editor,
114
+ editor: validEditor,
110
115
  slateValue: slateValue
111
116
  }))));
112
117
  }
113
118
  if (isFreezed) {
114
119
  return /*#__PURE__*/React.createElement(EditorContainer, {
115
- editor: editor,
120
+ editor: validEditor,
116
121
  readonly: isFreezed
117
122
  }, /*#__PURE__*/React.createElement(CollaboratorsProvider, null, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement(HeaderToolbar, {
118
- editor: editor,
123
+ editor: validEditor,
119
124
  readonly: isFreezed
120
125
  }), /*#__PURE__*/React.createElement(EditorContent, {
121
126
  docValue: slateValue,
122
127
  showOutline: true,
123
128
  readonly: isFreezed
124
129
  }, /*#__PURE__*/React.createElement(ReadOnlyArticle, {
125
- editor: editor,
130
+ editor: validEditor,
126
131
  slateValue: slateValue,
127
132
  isShowComment: true
128
133
  })))));
129
134
  }
130
135
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EditorContainer, {
131
- editor: editor
136
+ editor: validEditor
132
137
  }, /*#__PURE__*/React.createElement(CollaboratorsProvider, null, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement(HeaderToolbar, {
133
- editor: editor
138
+ editor: validEditor
134
139
  }), /*#__PURE__*/React.createElement(EditorContent, {
135
140
  docValue: slateValue,
136
141
  showOutline: true
137
142
  }, /*#__PURE__*/React.createElement(EditableArticle, {
138
- editor: editor,
143
+ editor: validEditor,
139
144
  slateValue: slateValue,
140
145
  updateSlateValue: setSlateValue
141
146
  }))))), /*#__PURE__*/React.createElement(InsertElementDialog, {
142
- editor: editor
147
+ editor: validEditor
143
148
  }));
144
149
  });
145
150
  export default SdocEditor;
@@ -18,8 +18,8 @@ const InsertElementDialog = _ref => {
18
18
  const [insertLinkCallback, setInsertLinkCallback] = useState(null);
19
19
  const uploadLocalImageInputRef = useRef();
20
20
  const onFileChanged = useCallback(event => {
21
- const file = event.target.files[0];
22
- context.uploadLocalImage(file).then(fileUrl => {
21
+ const files = event.target.files;
22
+ context.uploadLocalImage(files).then(fileUrl => {
23
23
  insertImage(editor, fileUrl, editor.selection, insertPosition, slateNode);
24
24
  if (uploadLocalImageInputRef.current) {
25
25
  uploadLocalImageInputRef.current.value = '';
@@ -110,6 +110,7 @@ const InsertElementDialog = _ref => {
110
110
  return /*#__PURE__*/React.createElement("input", {
111
111
  ref: uploadLocalImageInputRef,
112
112
  type: "file",
113
+ multiple: true,
113
114
  accept: "image/*",
114
115
  style: {
115
116
  display: 'none'
@@ -39,33 +39,35 @@ export const generateImageNode = src => {
39
39
  }
40
40
  });
41
41
  };
42
- export const insertImage = function (editor, src, selection) {
42
+ export const insertImage = function (editor, srcList, selection) {
43
43
  let position = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : INSERT_POSITION.CURRENT;
44
44
  let slateNode = arguments.length > 4 ? arguments[4] : undefined;
45
- if (!src) return;
45
+ if (!srcList) return;
46
46
  if (position !== INSERT_POSITION.AFTER) {
47
47
  if (isInsertImageMenuDisabled(editor)) return;
48
48
  }
49
- const imageNode = generateImageNode(src);
49
+ const imageNodes = srcList.map(src => generateImageNode(src));
50
50
  const validSelection = selection || editor.selection;
51
51
  if (position === INSERT_POSITION.AFTER) {
52
52
  let path = Editor.path(editor, validSelection);
53
53
  if (slateNode && (slateNode === null || slateNode === void 0 ? void 0 : slateNode.type) === LIST_ITEM) {
54
54
  path = ReactEditor.findPath(editor, slateNode);
55
55
  const nextPath = Path.next(path);
56
- Transforms.insertNodes(editor, imageNode, {
56
+ Transforms.insertNodes(editor, imageNodes, {
57
57
  at: nextPath
58
58
  });
59
59
  return;
60
60
  }
61
61
  const p = generateEmptyElement(ELEMENT_TYPE.PARAGRAPH);
62
- p.children[0] = imageNode;
62
+ imageNodes.forEach((item, index) => {
63
+ p.children[index] = item;
64
+ });
63
65
  Transforms.insertNodes(editor, p, {
64
66
  at: [path[0] + 1]
65
67
  });
66
68
  return;
67
69
  }
68
- Transforms.insertNodes(editor, imageNode, {
70
+ Transforms.insertNodes(editor, imageNodes, {
69
71
  at: validSelection
70
72
  });
71
73
  };
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import classnames from 'classnames';
2
3
  import { ORDERED_LIST } from '../../constants';
3
4
  const renderList = (props, editor) => {
4
5
  const {
@@ -33,11 +34,14 @@ const renderListItem = (props, editor) => {
33
34
  default:
34
35
  className = '';
35
36
  }
37
+ const isBlod = element.children[0].children.every(item => item.bold === true);
36
38
  return /*#__PURE__*/React.createElement("li", Object.assign({
37
39
  "data-id": element.id,
38
40
  "data-root": "true"
39
41
  }, attributes, {
40
- className: className
42
+ className: classnames(className, {
43
+ 'sdoc-li-blod': isBlod
44
+ })
41
45
  }), children);
42
46
  };
43
47
  const renderListLic = (props, editor) => {
@@ -32,8 +32,10 @@ export const TABLE_ROW_STYLE = {
32
32
  MIN_HEIGHT: 'min_height'
33
33
  };
34
34
  export const TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP = {
35
- '#3f495d': 'sdoc-table-3f495d',
36
- '#2367f2': 'sdoc-table-2367f2',
37
- '#f77d21': 'sdoc-table-f77d21',
38
- '#0099f4': 'sdoc-table-0099f4'
39
- };
35
+ 'sdoc-table-header-3f495d': 'sdoc-table-body-3f495d',
36
+ 'sdoc-table-header-2367f2': 'sdoc-table-body-2367f2',
37
+ 'sdoc-table-header-f77d21': 'sdoc-table-body-f77d21',
38
+ 'sdoc-table-header-0099f4': 'sdoc-table-body-0099f4'
39
+ };
40
+ export const INHERIT_CELL_STYLE_WHEN_SELECT_SINGLE = ['background_color'];
41
+ export const INHERIT_CELL_STYLE_WHEN_SELECT_MULTIPLE = ['background_color', 'text_align'];
@@ -3,9 +3,9 @@ import slugid from 'slugid';
3
3
  import { Editor, Range, Transforms, Point, Node } from '@seafile/slate';
4
4
  import { ReactEditor } from '@seafile/slate-react';
5
5
  import deepCopy from 'deep-copy';
6
- import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, getSelectedElems, focusEditor, getNode, findPath, replaceNodeChildren, replaceNode } from '../../core';
6
+ import { getNodeType, getParentNode, getSelectedNodeByType, isTextNode, getSelectedElems, focusEditor, getNode, findPath, replaceNodeChildren, replaceNode, getSelectedNodeEntryByType, getAboveBlockNode } from '../../core';
7
7
  import { ELEMENT_TYPE, KEYBOARD, CLIPBOARD_FORMAT_KEY, INSERT_POSITION } from '../../constants';
8
- import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE, TABLE_ROW_MIN_HEIGHT, TABLE_CELL_MIN_WIDTH, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, TABLE_ROW_STYLE } from './constants';
8
+ import { TABLE_MAX_ROWS, TABLE_MAX_COLUMNS, EMPTY_SELECTED_RANGE, TABLE_ROW_MIN_HEIGHT, TABLE_CELL_MIN_WIDTH, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, TABLE_ROW_STYLE, INHERIT_CELL_STYLE_WHEN_SELECT_MULTIPLE, INHERIT_CELL_STYLE_WHEN_SELECT_SINGLE, TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP } from './constants';
9
9
  import EventBus from '../../../utils/event-bus';
10
10
  import { INTERNAL_EVENT, PAGE_EDIT_AREA_WIDTH } from '../../../constants';
11
11
  import ObjectUtils from '../../../utils/object-utils';
@@ -54,20 +54,28 @@ export const isCombineCellsDisabled = (editor, readonly) => {
54
54
  }
55
55
  return true;
56
56
  };
57
- export const generateTableCell = () => {
57
+ export const generateTableCell = (editor, rowIndex, cellIndex) => {
58
+ let style = {};
59
+ const tableNodeEntry = getSelectedNodeEntryByType(editor, ELEMENT_TYPE.TABLE);
60
+ if (tableNodeEntry && rowIndex !== undefined && cellIndex !== undefined) {
61
+ const [, tablePath] = tableNodeEntry;
62
+ style = getCellInheritStyles(editor, tablePath, rowIndex, cellIndex);
63
+ }
58
64
  return {
59
65
  id: slugid.nice(),
60
66
  type: ELEMENT_TYPE.TABLE_CELL,
61
67
  children: [{
62
68
  text: '',
63
69
  id: slugid.nice()
64
- }]
70
+ }],
71
+ style,
72
+ inherit_style: style
65
73
  };
66
74
  };
67
- export const generateTableRow = colsCount => {
75
+ export const generateTableRow = (editor, colsCount, rowIndex) => {
68
76
  let children = [];
69
77
  for (let i = 0; i < colsCount; i++) {
70
- const tableCell = generateTableCell();
78
+ const tableCell = generateTableCell(editor, rowIndex, i);
71
79
  children.push(tableCell);
72
80
  }
73
81
  return {
@@ -97,7 +105,7 @@ export const generateEmptyTable = (editor, tableProps) => {
97
105
  const colsCount = size[1];
98
106
  let children = [];
99
107
  for (let i = 0; i < rowsCount; i++) {
100
- const tableRow = generateTableRow(colsCount);
108
+ const tableRow = generateTableRow(editor, colsCount, i);
101
109
  children.push(tableRow);
102
110
  }
103
111
  const columnWidth = Math.max(TABLE_CELL_MIN_WIDTH, parseInt(editor.width / colsCount));
@@ -133,16 +141,10 @@ export const insertTable = function (editor, size, selection) {
133
141
  });
134
142
  const validSelection = selection || editor.selection;
135
143
  const path = Editor.path(editor, validSelection);
136
- if (position === INSERT_POSITION.AFTER) {
137
- Transforms.insertNodes(editor, tableNode, {
138
- at: [path[0] + 1]
139
- });
140
- return;
141
- }
142
- Transforms.insertNodes(editor, tableNode, {
143
- at: [path[0]]
144
- });
144
+ handleInsertTable(editor, position, path, tableNode);
145
145
  };
146
+
147
+ // tableSize [tableHeight, tableWidth]
146
148
  export const getSelectedInfo = editor => {
147
149
  const currentTable = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE);
148
150
  const currentRow = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_ROW);
@@ -175,6 +177,7 @@ export const isAllInTable = editor => {
175
177
  };
176
178
 
177
179
  export const setCellStyle = (editor, style) => {
180
+ // Select single cell
178
181
  if (ObjectUtils.isSameObject(editor.tableSelectedRange, EMPTY_SELECTED_RANGE)) {
179
182
  const selectedNodes = getSelectedElems(editor);
180
183
  let firstTableCellNodePath;
@@ -184,7 +187,8 @@ export const setCellStyle = (editor, style) => {
184
187
  if (path) {
185
188
  firstTableCellNodePath = firstTableCellNodePath ? firstTableCellNodePath : path;
186
189
  Transforms.setNodes(editor, {
187
- style: _objectSpread(_objectSpread({}, node.style), style)
190
+ style: _objectSpread(_objectSpread({}, node.style), style),
191
+ inherit_style: generateInheritStyle(INHERIT_CELL_STYLE_WHEN_SELECT_SINGLE, style, node)
188
192
  }, {
189
193
  at: path
190
194
  });
@@ -202,6 +206,7 @@ export const setCellStyle = (editor, style) => {
202
206
  }
203
207
  return;
204
208
  }
209
+ // Select multiple cells
205
210
  const {
206
211
  minColIndex,
207
212
  maxColIndex,
@@ -216,7 +221,8 @@ export const setCellStyle = (editor, style) => {
216
221
  const path = [...tablePath, i, j];
217
222
  const node = getNode(editor, path);
218
223
  Transforms.setNodes(editor, {
219
- style: _objectSpread(_objectSpread({}, node.style), style)
224
+ style: _objectSpread(_objectSpread({}, node.style), style),
225
+ inherit_style: generateInheritStyle(INHERIT_CELL_STYLE_WHEN_SELECT_MULTIPLE, style, node)
220
226
  }, {
221
227
  at: path
222
228
  });
@@ -228,7 +234,7 @@ export const insertTableRow = function (editor, table, rowIndex) {
228
234
  const tableRowCount = table.children.length;
229
235
  if (tableRowCount >= TABLE_MAX_ROWS) return;
230
236
  const tableColumnCount = table.children[0].children.length;
231
- const row = generateTableRow(tableColumnCount);
237
+ const row = generateTableRow(editor, tableColumnCount, rowIndex);
232
238
  const tablePath = findPath(editor, table);
233
239
  const targetPath = position === TABLE_ELEMENT_POSITION.AFTER ? [...tablePath, rowIndex + 1] : [...tablePath, rowIndex];
234
240
  Transforms.insertNodes(editor, row, {
@@ -303,7 +309,7 @@ export const insertTableColumn = function (editor, table, columnIndex) {
303
309
  const tableRowCount = table.children.length;
304
310
  for (let i = 0; i < tableRowCount; i++) {
305
311
  const newCellPath = [...tablePath, i, newCellIndex];
306
- const newCell = generateTableCell();
312
+ const newCell = generateTableCell(editor, i, columnIndex);
307
313
  Transforms.insertNodes(editor, newCell, {
308
314
  at: newCellPath
309
315
  });
@@ -382,7 +388,7 @@ export const insertTableElement = function (editor, type) {
382
388
  const targetPath = position === TABLE_ELEMENT_POSITION.AFTER ? [...tablePath, rowIndex + 1] : [...tablePath, rowIndex];
383
389
  const validCount = Math.min(TABLE_MAX_ROWS - tableSize[0], count);
384
390
  for (let i = 0; i < validCount; i++) {
385
- const row = generateTableRow(tableSize[1]);
391
+ const row = generateTableRow(editor, tableSize[1], rowIndex);
386
392
  Transforms.insertNodes(editor, row, {
387
393
  at: targetPath
388
394
  });
@@ -406,7 +412,7 @@ export const insertTableElement = function (editor, type) {
406
412
  for (let j = 0; j < validCount; j++) {
407
413
  for (let i = 0; i < tableSize[0]; i++) {
408
414
  const newCellPath = [...tablePath, i, newCellIndex];
409
- const newCell = generateTableCell();
415
+ const newCell = generateTableCell(editor, i, cellIndex);
410
416
  Transforms.insertNodes(editor, newCell, {
411
417
  at: newCellPath
412
418
  });
@@ -450,7 +456,7 @@ export const combineCells = editor => {
450
456
  }
451
457
  }
452
458
  const targetCellPath = [...tablePath, minRowIndex, minColIndex];
453
- const newCell = generateTableCell();
459
+ const newCell = generateTableCell(editor);
454
460
  newCell.children = newCellContent;
455
461
  newCell.rowspan = maxRowIndex - minRowIndex + 1;
456
462
  newCell.colspan = maxColIndex - minColIndex + 1;
@@ -494,7 +500,7 @@ export const splitCell = (editor, rowNumber, columnNumber) => {
494
500
  let newRowSpan = rowspanBase + (i + 1 <= rowspanLeft ? 1 : 0);
495
501
  let colspanSum = 0;
496
502
  for (let j = 0; j < columnNumber; j++) {
497
- const newCell = generateTableCell();
503
+ const newCell = generateTableCell(editor);
498
504
  let startIndex = (i * columnNumber + j) * dataBlockNumber;
499
505
  if (startIndex < cell.children.length) {
500
506
  let endIndex = Math.min(startIndex + dataBlockNumber, cell.children.length);
@@ -661,7 +667,7 @@ export const handleCombinedCellsBeforeDeleteTableRow = (editor, tablePath, table
661
667
  } else {
662
668
  if (rowspan > 1) {
663
669
  const targetCellPath = [...tablePath, rowIndex + 1, i];
664
- const newCell = generateTableCell();
670
+ const newCell = generateTableCell(editor);
665
671
  newCell.rowspan = rowspan - 1;
666
672
  newCell.colspan = colspan;
667
673
  Transforms.removeNodes(editor, {
@@ -701,7 +707,7 @@ export const handleCombinedCellsBeforeDeleteTableColumn = (editor, tablePath, ta
701
707
  } else {
702
708
  if (colspan > 1) {
703
709
  const targetCellPath = [...tablePath, i, columnIndex + 1];
704
- const newCell = generateTableCell();
710
+ const newCell = generateTableCell(editor);
705
711
  newCell.rowspan = rowspan;
706
712
  newCell.colspan = colspan - 1;
707
713
  Transforms.removeNodes(editor, {
@@ -878,7 +884,7 @@ export const insertMultipleRowsAndColumns = (editor, rows, columns) => {
878
884
  const validInsertColumns = insertColumns.slice(0, Math.min(TABLE_MAX_COLUMNS - tableSize[1], columns.length));
879
885
  for (let i = 0; i < validInsertRows.length; i++) {
880
886
  const insertRow = validInsertRows[i];
881
- const row = generateTableRow(tableSize[1]);
887
+ const row = generateTableRow(editor, tableSize[1], rowIndex);
882
888
  row.style = insertRow.style;
883
889
  newTable.children.push(row);
884
890
  }
@@ -887,7 +893,7 @@ export const insertMultipleRowsAndColumns = (editor, rows, columns) => {
887
893
  }
888
894
  for (let j = 0; j < validInsertColumns.length; j++) {
889
895
  for (let i = 0; i < tableSize[0] + validInsertRows.length; i++) {
890
- const newCell = generateTableCell();
896
+ const newCell = generateTableCell(editor);
891
897
  newTable.children[i].children.push(newCell);
892
898
  }
893
899
  }
@@ -1244,8 +1250,8 @@ export const getRowHeight = (element, rowIndex) => {
1244
1250
  const rowHeight = style[TABLE_ROW_STYLE.MIN_HEIGHT] || TABLE_ROW_MIN_HEIGHT;
1245
1251
  return rowIndex === 0 ? rowHeight + 1 : rowHeight;
1246
1252
  };
1247
- const normalizeTableCell = cell => {
1248
- if (!cell) return generateTableCell();
1253
+ const normalizeTableCell = (editor, cell) => {
1254
+ if (!cell) return generateTableCell(editor);
1249
1255
  let newCell = _objectSpread({
1250
1256
  children: [{
1251
1257
  text: '',
@@ -1300,7 +1306,7 @@ export const normalizeTableELement = (editor, element) => {
1300
1306
  for (let i = 0; i < element.children.length; i++) {
1301
1307
  const row = newElement.children[i];
1302
1308
  for (let j = 0; j < row.children.length; j++) {
1303
- row.children[j] = normalizeTableCell(row.children[j]);
1309
+ row.children[j] = normalizeTableCell(editor, row.children[j]);
1304
1310
  }
1305
1311
  newElement.children[i] = row;
1306
1312
  }
@@ -1314,7 +1320,82 @@ export const insertTableByTemplate = (editor, alternateColor) => {
1314
1320
  alternate_highlight: true
1315
1321
  });
1316
1322
  const path = Editor.path(editor, editor.selection);
1317
- Transforms.insertNodes(editor, tableNode, {
1318
- at: [path[0]]
1323
+ const insertPosition = getInsertPosition(editor);
1324
+ handleInsertTable(editor, insertPosition, path, tableNode);
1325
+ };
1326
+
1327
+ /**
1328
+ * @param {Editor} editor
1329
+ * @param {InsertPosition} insertPosition
1330
+ * @param {Path} path
1331
+ * @param {Node} tableNode
1332
+ * Insert table by insertPosition
1333
+ */
1334
+ export const handleInsertTable = (editor, insertPosition, path, tableNode) => {
1335
+ const {
1336
+ selection
1337
+ } = editor;
1338
+ if (insertPosition === INSERT_POSITION.BEFORE) {
1339
+ const insertPath = [path[0]];
1340
+ Transforms.insertNodes(editor, tableNode, {
1341
+ at: insertPath
1342
+ });
1343
+ } else if (insertPosition === INSERT_POSITION.AFTER) {
1344
+ const insertPath = [path[0] + 1];
1345
+ Transforms.insertNodes(editor, tableNode, {
1346
+ at: insertPath
1347
+ });
1348
+ } else if (insertPosition === INSERT_POSITION.CURRENT) {
1349
+ Transforms.splitNodes(editor, {
1350
+ at: selection,
1351
+ always: true
1352
+ });
1353
+ Transforms.insertNodes(editor, tableNode, {
1354
+ at: selection.anchor
1355
+ });
1356
+ }
1357
+ };
1358
+ export const getInsertPosition = editor => {
1359
+ const {
1360
+ selection
1361
+ } = editor;
1362
+ if (!selection) return INSERT_POSITION.CURRENT;
1363
+ if (!Range.isCollapsed(selection)) return INSERT_POSITION.CURRENT;
1364
+ const aboveNodeEntry = getAboveBlockNode(editor);
1365
+ if (!aboveNodeEntry) return INSERT_POSITION.CURRENT;
1366
+ const isAtStart = Editor.isStart(editor, selection.anchor, aboveNodeEntry[1]);
1367
+ if (isAtStart) return INSERT_POSITION.BEFORE;
1368
+ const isAtEnd = Editor.isEnd(editor, selection.anchor, aboveNodeEntry[1]);
1369
+ if (isAtEnd) return INSERT_POSITION.AFTER;
1370
+ return INSERT_POSITION.CURRENT;
1371
+ };
1372
+ export const generateInheritStyle = (allowedInheritStyleList, style, cell) => {
1373
+ const inheritStyle = _objectSpread({}, cell['inherit_style']) || {};
1374
+ for (const key in style) {
1375
+ if (Object.hasOwnProperty.call(style, key) && allowedInheritStyleList.includes(key)) {
1376
+ inheritStyle[key] = style[key];
1377
+ }
1378
+ }
1379
+ return inheritStyle;
1380
+ };
1381
+ export const getCellInheritStyles = (editor, tablePath, rowIndex, colIndex) => {
1382
+ var _table$children$rowIn, _tableCell$inherit_st;
1383
+ const [tableNodeEntry] = Editor.nodes(editor, {
1384
+ match: n => n.type === ELEMENT_TYPE.TABLE,
1385
+ at: tablePath
1319
1386
  });
1387
+ if (!tableNodeEntry) return {};
1388
+ const table = tableNodeEntry[0];
1389
+ const tableCell = (_table$children$rowIn = table.children[rowIndex]) === null || _table$children$rowIn === void 0 ? void 0 : _table$children$rowIn.children[colIndex];
1390
+ if (!tableCell) return {};
1391
+ return (_tableCell$inherit_st = tableCell['inherit_style']) !== null && _tableCell$inherit_st !== void 0 ? _tableCell$inherit_st : {};
1392
+ };
1393
+ export const getCellHighlightClassName = (primaryColorClassName, rowIndex) => {
1394
+ let className = '';
1395
+ if (rowIndex === 0) {
1396
+ className = primaryColorClassName;
1397
+ } else if (rowIndex % 2 === 0) {
1398
+ className = TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP[primaryColorClassName];
1399
+ }
1400
+ return className;
1320
1401
  };
@@ -5,7 +5,7 @@ import { ElementPopover } from '../../../../commons';
5
5
  import { ELEMENT_TYPE } from '../../../../constants';
6
6
  import { getSelectedNodeByType } from '../../../../core';
7
7
  import { TABLE_MAX_COLUMNS, TABLE_MAX_ROWS, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, EMPTY_SELECTED_RANGE } from '../../constants';
8
- import { insertTableElement, removeTableElement, getSelectedInfo, combineCells } from '../../helpers';
8
+ import { insertTableElement, removeTableElement, combineCells } from '../../helpers';
9
9
  import InsertTableElement from './insert-table-element';
10
10
  import EventBus from '../../../../../utils/event-bus';
11
11
  import { INTERNAL_EVENT } from '../../../../../constants';
@@ -84,6 +84,16 @@ class TableContextMenu extends React.Component {
84
84
  componentWillUnmount() {
85
85
  this.menu = null;
86
86
  }
87
+ isMergedCell() {
88
+ const {
89
+ editor
90
+ } = this.props;
91
+ const {
92
+ colspan,
93
+ rowspan
94
+ } = getSelectedNodeByType(editor, ELEMENT_TYPE.TABLE_CELL);
95
+ return colspan > 1 || rowspan > 1;
96
+ }
87
97
  render() {
88
98
  const {
89
99
  contextStyle
@@ -106,6 +116,7 @@ class TableContextMenu extends React.Component {
106
116
  const canAddColsCount = currentColumnsCount + selectedCols > TABLE_MAX_COLUMNS ? TABLE_MAX_COLUMNS - currentColumnsCount : selectedCols;
107
117
  const enableCombineCell = !ObjectUtils.isSameObject(tableSelectedRange, EMPTY_SELECTED_RANGE);
108
118
  const enableSplitCell = !enableCombineCell;
119
+ const isMergedCell = this.isMergedCell();
109
120
  return /*#__PURE__*/React.createElement(ElementPopover, {
110
121
  className: "sdoc-context-menu"
111
122
  }, /*#__PURE__*/React.createElement("div", {
@@ -146,7 +157,7 @@ class TableContextMenu extends React.Component {
146
157
  onMouseDown: this.combineCells
147
158
  }, t('Combine_cell')), /*#__PURE__*/React.createElement("button", {
148
159
  className: "dropdown-item",
149
- disabled: !enableSplitCell,
160
+ disabled: !isMergedCell || !enableSplitCell,
150
161
  onMouseDown: this.toggleSplitCellSettingDialog
151
162
  }, t('Split_cell'))));
152
163
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { withTranslation } from 'react-i18next';
3
- import { insertTable, isTableMenuDisabled } from '../../helpers';
3
+ import { getInsertPosition, insertTable, isTableMenuDisabled } from '../../helpers';
4
4
  import { MENUS_CONFIG_MAP, ELEMENT_TYPE, INSERT_POSITION } from '../../../../constants';
5
5
  import TableSizePopover from '../../popover/table-size-popover';
6
6
  import ElementDropdownMenuItem from '../../../../commons/dropdown-menu-item';
@@ -13,7 +13,8 @@ const TableMenu = _ref => {
13
13
  const disabled = isTableMenuDisabled(editor, readonly);
14
14
  const menuConfig = MENUS_CONFIG_MAP[ELEMENT_TYPE.TABLE];
15
15
  const createTable = useCallback(size => {
16
- insertTable(editor, size, editor.selection, INSERT_POSITION.CURRENT);
16
+ const insertPosition = getInsertPosition(editor, INSERT_POSITION.AFTER);
17
+ insertTable(editor, size, editor.selection, insertPosition);
17
18
  }, [editor]);
18
19
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ElementDropdownMenuItem, {
19
20
  disabled: disabled,
@@ -26,7 +26,6 @@ const withTable = editor => {
26
26
  const eventBus = EventBus.getInstance();
27
27
  newEditor.tableOnKeyDown = event => {
28
28
  // Handle special keyboard events
29
-
30
29
  if (isHotkey('mod+a', event)) {
31
30
  event.preventDefault();
32
31
  const {
@@ -1,7 +1,7 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
2
  import { UncontrolledPopover } from 'reactstrap';
3
3
  import { TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP } from '../../constants';
4
- import SmapleTable from './sample-table';
4
+ import SampleTable from './sample-table';
5
5
  import { insertTableByTemplate } from '../../helpers';
6
6
  import './index.css';
7
7
  import '../../render/alternate-color.css';
@@ -22,7 +22,7 @@ const TableTemplate = _ref => {
22
22
  fade: false,
23
23
  className: "sdoc-sub-dropdown-menu sdoc-table-template-popover",
24
24
  innerClassName: "sdoc-table-template-inner-popover"
25
- }, tableTemplatePreviewList.map((alternateColor, index) => /*#__PURE__*/React.createElement(SmapleTable, {
25
+ }, tableTemplatePreviewList.map((alternateColor, index) => /*#__PURE__*/React.createElement(SampleTable, {
26
26
  key: alternateColor + index,
27
27
  alternateColor: alternateColor,
28
28
  onClickTemplate: handleClickTemplate
@@ -1,29 +1,27 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP } from '../../constants';
3
+ import { getCellHighlightClassName } from '../../helpers';
4
4
  import './index.css';
5
- const SmapleTable = _ref => {
5
+ const SampleTable = _ref => {
6
6
  let {
7
7
  alternateColor,
8
8
  onClickTemplate
9
9
  } = _ref;
10
10
  // generate table
11
- const renderTableRow = useCallback((row, column) => new Array(row).fill(null).map((_, index) => {
12
- return /*#__PURE__*/React.createElement("div", {
13
- className: "sdoc-table-template-row table-row",
14
- key: "sdoc-template-table-row-".concat(index),
15
- onClick: e => onClickTemplate(e, alternateColor)
16
- }, new Array(column).fill(null).map((_, index) => /*#__PURE__*/React.createElement("div", {
17
- className: "sdoc-table-template-cell",
18
- key: "sdoc-template-table-cell-".concat(index)
19
- })));
20
- }), [onClickTemplate, alternateColor]);
11
+ const renderTableRow = useCallback((row, column) => new Array(row).fill(null).map((_, index) => /*#__PURE__*/React.createElement("div", {
12
+ className: "sdoc-table-template-row table-row ".concat(getCellHighlightClassName(alternateColor, index)),
13
+ key: "sdoc-template-table-row-".concat(index),
14
+ onClick: e => onClickTemplate(e, alternateColor)
15
+ }, new Array(column).fill(null).map((_, index) => /*#__PURE__*/React.createElement("div", {
16
+ className: "sdoc-table-template-cell",
17
+ key: "sdoc-template-table-cell-".concat(index)
18
+ })))), [onClickTemplate, alternateColor]);
21
19
  return /*#__PURE__*/React.createElement("div", {
22
- className: "sdoc-table-template-view-table ".concat(TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP[alternateColor])
20
+ className: "sdoc-table-template-view-table"
23
21
  }, renderTableRow(4, 4));
24
22
  };
25
- SmapleTable.proptoTypes = {
23
+ SampleTable.protoTypes = {
26
24
  alternateColor: PropTypes.string.isRequired,
27
25
  onClickTemplate: PropTypes.func.isRequired
28
26
  };
29
- export default SmapleTable;
27
+ export default SampleTable;
@@ -1,37 +1,37 @@
1
1
  /* type1 */
2
- .sdoc-table-3f495d .table-row:nth-child(2n + 1) {
2
+ .sdoc-table-body-3f495d {
3
3
  background-color: #f1f3f6;
4
4
  }
5
5
 
6
- .sdoc-table-3f495d .table-row:first-child {
6
+ .sdoc-table-header-3f495d {
7
7
  background-color: #3f495d;
8
8
  color: white;
9
9
  }
10
10
 
11
11
  /* type2 */
12
- .sdoc-table-2367f2 .table-row:nth-child(2n + 1) {
12
+ .sdoc-table-body-2367f2 {
13
13
  background-color: #e1edff;
14
14
  }
15
15
 
16
- .sdoc-table-2367f2 .table-row:first-child {
16
+ .sdoc-table-header-2367f2 {
17
17
  background-color: #2367f2;
18
18
  color: white;
19
19
  }
20
20
 
21
21
  /* type3 */
22
- .sdoc-table-f77d21 .table-row:nth-child(2n + 1) {
22
+ .sdoc-table-body-f77d21 {
23
23
  background-color: #fff1e8;
24
24
  }
25
25
 
26
- .sdoc-table-f77d21 .table-row:first-child {
26
+ .sdoc-table-header-f77d21 {
27
27
  background-color: #f77d21;
28
28
  }
29
29
 
30
30
  /* type4 */
31
- .sdoc-table-0099f4 .table-row:nth-child(2n + 1) {
31
+ .sdoc-table-body-0099f4 {
32
32
  background-color: #e1f5ff;
33
33
  }
34
34
 
35
- .sdoc-table-0099f4 .table-row:first-child {
35
+ .sdoc-table-header-0099f4 {
36
36
  background-color: #0099f4;
37
37
  }
@@ -4,7 +4,7 @@ import classnames from 'classnames';
4
4
  import throttle from 'lodash.throttle';
5
5
  import { useSelected, useSlateStatic, useReadOnly } from '@seafile/slate-react';
6
6
  import { Transforms, Editor } from '@seafile/slate';
7
- import { EMPTY_SELECTED_RANGE, TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP } from '../constants';
7
+ import { EMPTY_SELECTED_RANGE } from '../constants';
8
8
  import { ResizeHandlersContext, TableSelectedRangeContext, SettingSelectRangeContext } from './hooks';
9
9
  import EventBus from '../../../../utils/event-bus';
10
10
  import { INTERNAL_EVENT } from '../../../../constants';
@@ -18,7 +18,6 @@ import { findPath } from '../../../core';
18
18
  import './index.css';
19
19
  import './alternate-color.css';
20
20
  const Table = _ref => {
21
- var _element$ui, _element$ui2;
22
21
  let {
23
22
  className,
24
23
  attributes,
@@ -190,9 +189,7 @@ const Table = _ref => {
190
189
  table: element,
191
190
  setSelectedRange: setSelectedRangeByClick
192
191
  }), /*#__PURE__*/React.createElement("div", {
193
- className: classnames(tableContainerClassName, {
194
- [TABLE_ALTERNATE_HIGHLIGHT_CLASS_MAP[element === null || element === void 0 ? void 0 : (_element$ui = element.ui) === null || _element$ui === void 0 ? void 0 : _element$ui.alternate_highlight_color]]: element === null || element === void 0 ? void 0 : (_element$ui2 = element.ui) === null || _element$ui2 === void 0 ? void 0 : _element$ui2.alternate_highlight
195
- }),
192
+ className: classnames(tableContainerClassName),
196
193
  style: style,
197
194
  onMouseDown: onMouseDown,
198
195
  ref: table,
@@ -1,13 +1,14 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
- import React, { useCallback } from 'react';
2
+ import React, { useCallback, useMemo } from 'react';
3
3
  import classnames from 'classnames';
4
4
  import { useSlateStatic, useReadOnly } from '@seafile/slate-react';
5
- import { Transforms } from '@seafile/slate';
5
+ import { Editor, Transforms } from '@seafile/slate';
6
6
  import ObjectUtils from '../../../../utils/object-utils';
7
7
  import { findPath, focusEditor } from '../../../core';
8
8
  import { useResizeHandlersContext, useTableSelectedRangeContext } from './hooks';
9
9
  import { EMPTY_SELECTED_RANGE, SELECTED_TABLE_CELL_BACKGROUND_COLOR, TABLE_CELL_STYLE } from '../constants';
10
- import { getTableColumns, getCellColumn, colorBlend } from '../helpers';
10
+ import { getTableColumns, colorBlend, getCellHighlightClassName } from '../helpers';
11
+ import { ELEMENT_TYPE } from '../../../constants';
11
12
  const TableCell = _ref => {
12
13
  let {
13
14
  attributes,
@@ -67,9 +68,29 @@ const TableCell = _ref => {
67
68
  colspan = 1
68
69
  } = element;
69
70
  style.gridArea = "".concat(rowIndex + 1, " / ").concat(cellIndex + 1, " / span ").concat(rowspan, " / span ").concat(colspan);
71
+ if (element.style) {
72
+ style = _objectSpread(_objectSpread({}, element.style), style);
73
+ }
74
+
75
+ // Table alternate highlight
76
+ const highlightClass = useMemo(() => {
77
+ var _tableEntry$;
78
+ const [tableEntry] = Editor.nodes(editor, {
79
+ at: cellPath,
80
+ match: n => n.type === ELEMENT_TYPE.TABLE
81
+ });
82
+ const {
83
+ alternate_highlight,
84
+ alternate_highlight_color
85
+ } = ((_tableEntry$ = tableEntry[0]) === null || _tableEntry$ === void 0 ? void 0 : _tableEntry$.ui) || {};
86
+ if (!alternate_highlight) return '';
87
+ const className = getCellHighlightClassName(alternate_highlight_color, rowIndex);
88
+ return className;
89
+ // eslint-disable-next-line react-hooks/exhaustive-deps
90
+ }, [editor, rowIndex]);
70
91
  return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
71
92
  style: _objectSpread(_objectSpread({}, element.style), style),
72
- className: classnames('table-cell', attributes.className, {
93
+ className: classnames('table-cell', attributes.className, highlightClass, {
73
94
  'cell-selected': isSelected,
74
95
  'cell-light-height-left-border': isSelectedFirstCell,
75
96
  'cell-light-height-right-border': isSelectedLastCell,
@@ -1,5 +1,6 @@
1
1
  import SDocEditor from './editor/sdoc-editor';
2
+ import RevisionEditor from './editor/revision-editor';
2
3
  import { DiffViewer, SDocViewer, PublishedRevisionDiffViewer } from './views';
3
4
  import SDocOutline from './outline';
4
5
  import EventBus from './utils/event-bus';
5
- export { SDocEditor, SDocViewer, SDocOutline, EventBus, DiffViewer, PublishedRevisionDiffViewer };
6
+ export { SDocEditor, RevisionEditor, SDocViewer, SDocOutline, EventBus, DiffViewer, PublishedRevisionDiffViewer };
@@ -50,6 +50,7 @@ class SocketManager {
50
50
  this.eventBus.dispatch(EXTERNAL_EVENT.NEW_NOTIFICATION, notification);
51
51
  };
52
52
  this.onReceiveLocalOperations = operations => {
53
+ if (this.editor.readonly) return;
53
54
  this.pendingOperationList.push(operations);
54
55
  const lastOpBeginTime = new Date().getTime();
55
56
  this.pendingOperationBeginTimeList.push(lastOpBeginTime);
@@ -61,6 +62,7 @@ class SocketManager {
61
62
  this.sendOperations();
62
63
  };
63
64
  this.sendOperations = () => {
65
+ if (this.editor.readonly) return;
64
66
  if (this.state !== STATE.IDLE) return;
65
67
  stateDebug("State changed: ".concat(this.state, " -> ").concat(STATE.SENDING));
66
68
  this.state = STATE.SENDING;
@@ -141,6 +143,7 @@ class SocketManager {
141
143
  this.onReceiveRemoteOperations = params => {
142
144
  // if this.disconnect is true, Then the message sent by the remote end cannot be received
143
145
  if (this.state !== STATE.IDLE) return;
146
+ if (this.editor.readonly) return;
144
147
  const {
145
148
  version: serverVersion
146
149
  } = params;
@@ -203,6 +206,7 @@ class SocketManager {
203
206
  this.socketClient.getRecentOperations();
204
207
  };
205
208
  this.onGetRecentOperations = result => {
209
+ if (this.editor.readonly) return;
206
210
  const {
207
211
  mode,
208
212
  content
@@ -242,6 +246,7 @@ class SocketManager {
242
246
  this.resolveConflicting(loseOperations);
243
247
  };
244
248
  this.resolveConflicting = loseOperations => {
249
+ if (this.editor.readonly) return;
245
250
  conflictDebug('resolve conflicts');
246
251
  this.editor.isRemote = true;
247
252
  if (this.pendingOperationList.length !== 0) {
@@ -312,6 +317,7 @@ class SocketManager {
312
317
  this.socketClient.sendCursorLocation(location);
313
318
  };
314
319
  this.receiveCursorLocation = params => {
320
+ if (this.editor.readonly) return;
315
321
  const {
316
322
  user,
317
323
  location,
@@ -25,6 +25,7 @@ const withSocketIO = (editor, options) => {
25
25
  SocketManager.destroy();
26
26
  };
27
27
  newEditor.onChange = () => {
28
+ if (newEditor.readonly) return;
28
29
  const {
29
30
  document,
30
31
  config
@@ -6,6 +6,7 @@ import Loading from '../../components/loading';
6
6
  import '../../assets/css/diff-viewer.css';
7
7
  const RevisionDiffViewer = _ref => {
8
8
  let {
9
+ editor,
9
10
  revisionContent,
10
11
  didMountCallback
11
12
  } = _ref;
@@ -27,12 +28,17 @@ const RevisionDiffViewer = _ref => {
27
28
  setIsLoading(false);
28
29
  });
29
30
  }, [revisionContent, didMountCallback]);
31
+ useEffect(() => {
32
+ if (!editor) return;
33
+ editor.readonly = true;
34
+ }, []);
30
35
  if (isLoading) {
31
36
  return /*#__PURE__*/React.createElement(Loading, null);
32
37
  }
33
38
  return /*#__PURE__*/React.createElement(SDocViewer, {
34
39
  showToolbar: true,
35
40
  showOutline: true,
41
+ editor: editor,
36
42
  document: {
37
43
  children: diff.value
38
44
  }
@@ -1,3 +1,7 @@
1
+ .sdoc-tooltip {
2
+ pointer-events: none;
3
+ }
4
+
1
5
  .sdoc-tooltip .tooltip-inner {
2
6
  font-weight: lighter;
3
7
  text-align: start;
package/dist/context.js CHANGED
@@ -25,9 +25,9 @@ class Context {
25
25
  this.settings['originFileURL'] = originFileURL;
26
26
  }
27
27
  };
28
- this.uploadLocalImage = imageFile => {
28
+ this.uploadLocalImage = imageFiles => {
29
29
  const docUuid = this.getSetting('docUuid');
30
- return this.api.uploadSdocImage(docUuid, imageFile).then(res => {
30
+ return this.api.uploadSdocImage(docUuid, imageFiles).then(res => {
31
31
  const {
32
32
  relative_path
33
33
  } = res.data;
@@ -6,8 +6,8 @@ import DocOperations from '../components/doc-operations';
6
6
  import Layout, { Header, Content } from '../layout';
7
7
  import context from '../context';
8
8
  import ErrorBoundary from './error-boundary';
9
- import { SDocEditor } from '../basic-sdk';
10
- import { PublishedRevisionDiffViewer, RevisionDiffViewer } from '../basic-sdk/views';
9
+ import { SDocEditor, RevisionEditor } from '../basic-sdk';
10
+ import { PublishedRevisionDiffViewer } from '../basic-sdk/views';
11
11
  import { useDocument } from '../hooks';
12
12
  import { resetWebTitle } from '../utils';
13
13
  import '../assets/css/simple-editor.css';
@@ -31,6 +31,7 @@ const SimpleEditor = _ref => {
31
31
  const [revisionContent, setRevisionContent] = useState(null);
32
32
  const [changes, setChanges] = useState([]);
33
33
  const initIsPublished = context.getSetting('isPublished') || false;
34
+ const isSdocRevision = context.getSetting('isSdocRevision') || false;
34
35
  const [isPublished, setPublished] = useState(initIsPublished);
35
36
 
36
37
  // useMount: reset title
@@ -93,6 +94,30 @@ const SimpleEditor = _ref => {
93
94
  setPublished(true);
94
95
  });
95
96
  }, [setErrorMessage]);
97
+ const renderEditor = useCallback(() => {
98
+ if (!isSdocRevision) {
99
+ return /*#__PURE__*/React.createElement(SDocEditor, {
100
+ ref: editorRef,
101
+ isReloading: isReloading,
102
+ document: document
103
+ });
104
+ }
105
+ if (isPublished) {
106
+ return /*#__PURE__*/React.createElement(PublishedRevisionDiffViewer, {
107
+ isShowChanges: isShowChanges,
108
+ revisionContent: revisionContent,
109
+ didMountCallback: setDiffChanges
110
+ });
111
+ }
112
+ return /*#__PURE__*/React.createElement(RevisionEditor, {
113
+ ref: editorRef,
114
+ isShowChanges: isShowChanges,
115
+ isReloading: isReloading,
116
+ document: document,
117
+ revisionContent: revisionContent,
118
+ didMountCallback: setDiffChanges
119
+ });
120
+ }, [isSdocRevision, editorRef, isReloading, document, isPublished, isShowChanges, revisionContent, setDiffChanges]);
96
121
  if (isFirstLoading) {
97
122
  return /*#__PURE__*/React.createElement(Loading, null);
98
123
  }
@@ -115,17 +140,6 @@ const SimpleEditor = _ref => {
115
140
  handleViewChangesToggle: handleViewChangesToggle,
116
141
  handleRevisionMerged: handleRevisionMerged,
117
142
  handleRevisionPublished: handleRevisionPublished
118
- })), /*#__PURE__*/React.createElement(Content, null, isPublished && /*#__PURE__*/React.createElement(PublishedRevisionDiffViewer, {
119
- isShowChanges: isShowChanges,
120
- revisionContent: revisionContent,
121
- didMountCallback: setDiffChanges
122
- }), !isPublished && !isShowChanges && /*#__PURE__*/React.createElement(SDocEditor, {
123
- ref: editorRef,
124
- isReloading: isReloading,
125
- document: document
126
- }), !isPublished && isShowChanges && /*#__PURE__*/React.createElement(RevisionDiffViewer, {
127
- revisionContent: revisionContent,
128
- didMountCallback: setDiffChanges
129
- }))));
143
+ })), /*#__PURE__*/React.createElement(Content, null, renderEditor())));
130
144
  };
131
145
  export default withTranslation('sdoc-editor')(SimpleEditor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.3.21",
3
+ "version": "0.3.23",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -14,24 +14,18 @@
14
14
  />
15
15
  <missing-glyph />
16
16
 
17
- <<<<<<< HEAD
18
- <glyph glyph-name="sdoc-selected-text" unicode="&#58974;" d="M48 480h928c25.6 0 48-22.4 48-48s-22.4-48-48-48h-928C22.4 384 0 406.4 0 432S22.4 480 48 480z m0-352h352c25.6 0 48-22.4 48-48s-22.4-48-48-48h-352C22.4 32 0 54.4 0 80S22.4 128 48 128z m0 704h928c25.6 0 48-22.4 48-48S1001.6 736 976 736h-928C22.4 736 0 758.4 0 784S22.4 832 48 832z m675.2-950.4c-12.8 0-28.8 6.4-38.4 16l-124.8 118.4c-22.4 19.2-22.4 51.2 0 73.6s54.4 19.2 76.8 0l86.4-83.2 211.2 204.8c22.4 19.2 54.4 19.2 76.8 0s22.4-51.2 0-73.6l-249.6-240c-12.8-12.8-25.6-16-38.4-16z" horiz-adv-x="1028" />
17
+ <glyph glyph-name="sdoc-comment-quote" unicode="&#58976;" d="M48 896C73.6 896 96 873.6 96 848v-928c0-25.6-22.4-48-48-48S0-105.6 0-80v928C0 873.6 22.4 896 48 896z m224-665.6c51.2 16 96 48 124.8 92.8 32 41.6 48 118.4 48 163.2-9.6-6.4-22.4-6.4-44.8-6.4-38.4 0-70.4 12.8-99.2 41.6-25.6 28.8-41.6 64-41.6 108.8s16 80 44.8 108.8 70.4 41.6 108.8 41.6c51.2 0 89.6-22.4 124.8-64 32-41.6 48-96 48-160 0-102.4-28.8-220.8-83.2-294.4-54.4-76.8-131.2-128-227.2-153.6l-3.2 121.6z m438.4 6.4c51.2 16 89.6 48 124.8 92.8 35.2 41.6 51.2 118.4 48 163.2-9.6-6.4-22.4-6.4-44.8-6.4-38.4 0-73.6 12.8-99.2 41.6-28.8 28.8-41.6 64-41.6 108.8s16 80 41.6 108.8c32 25.6 70.4 38.4 112 38.4 51.2 0 89.6-22.4 121.6-64s48-96 48-160c0-102.4-28.8-220.8-83.2-294.4-54.4-76.8-131.2-128-227.2-153.6v124.8z" horiz-adv-x="1024" />
18
+
19
+ <glyph glyph-name="sdoc-find-replace" unicode="&#58975;" d="M468.66016 896C260.66016 896 81.46016 761.6 20.66016 566.4s16-409.6 185.6-521.6 396.8-102.4 553.6 25.6l185.6-185.6c19.2-16 48-16 64 0 19.2 19.2 19.2 48 0 64l-185.6 185.6c115.2 140.8 137.6 332.8 60.8 492.8S647.86016 896 468.66016 896zM97.46016 432C97.46016 636.8 260.66016 800 465.46016 800S833.46016 636.8 833.46016 432 670.26016 64 465.46016 64 97.46016 227.2 97.46016 432z" horiz-adv-x="1025" />
19
20
 
20
- =======
21
- <<<<<<< HEAD
22
- >>>>>>> 4ad4d178 (feat: change icon)
23
21
  <glyph glyph-name="sdoc-freezed" unicode="&#58973;" d="M512 384m-512 0a512 512 0 1 1 1024 0 512 512 0 1 1-1024 0ZM316.8 716.8c118.4 70.4 265.6 70.4 384 3.2s192-195.2 192-332.8c0-137.6-73.6-265.6-195.2-332.8-182.4-105.6-416-41.6-521.6 140.8S134.4 608 316.8 716.8z m348.8-604.8c137.6 80 195.2 249.6 131.2 396.8L259.2 195.2c92.8-124.8 268.8-163.2 406.4-83.2zM352 652.8c-137.6-80-192-249.6-128-393.6l537.6 310.4c-96 128-272 163.2-409.6 83.2z" horiz-adv-x="1024" />
24
22
 
25
23
  <glyph glyph-name="sdoc-jump-to" unicode="&#58970;" d="M361.6 896c32 0 54.4-16 54.4-48S393.6 800 361.6 800H96v-832h832v262.4c0 32 16 57.6 48 57.6s48-25.6 48-57.6v-300.8c0-32-28.8-57.6-60.8-57.6H60.8c-32 0-60.8 25.6-60.8 57.6V835.2C0 870.4 25.6 896 60.8 896h300.8zM992 896c19.2 0 32-12.8 32-32v-332.8c0-28.8-19.2-51.2-48-51.2s-48 22.4-48 51.2V729.6L531.2 336c-6.4-9.6-19.2-16-35.2-16-12.8 0-25.6 6.4-35.2 16-19.2 19.2-19.2 51.2 0 70.4L857.6 800h-198.4c-28.8 0-51.2 19.2-51.2 48S630.4 896 656 896H992z" horiz-adv-x="1024" />
26
24
 
27
- =======
28
- >>>>>>> 0183ac39 (feat: change icon)
29
25
  <glyph glyph-name="sdoc-callout" unicode="&#58972;" d="M992 352H32c-19.2 0-32 12.8-32 32V832c0 19.2 12.8 32 32 32h960c19.2 0 32-12.8 32-32v-448c0-19.2-12.8-32-32-32zM96 448h832V768H96v-320z m-96-224v-96h1024v96H0z m0-224v-96h576v96H0z" horiz-adv-x="1024" />
30
26
 
31
27
  <glyph glyph-name="sdoc-chart" unicode="&#58971;" d="M992-128H32c-19.2 0-32 12.8-32 32V864c0 19.2 12.8 32 32 32h960c19.2 0 32-12.8 32-32v-960c0-19.2-12.8-32-32-32zM96-32h832V800H96v-832z m0 464v-96h832v96H96zM560 800h-96v-832h96V800z" horiz-adv-x="1024" />
32
28
 
33
- <glyph glyph-name="sdoc-notification" unicode="&#58970;" d="M931.2 80c-3.2 80-44.8 150.4-105.6 198.4V496c0 124.8-89.6 233.6-208 256v6.4C617.6 816 572.8 864 515.2 864S409.6 816 409.6 758.4v-6.4c-118.4-25.6-208-131.2-208-256v-217.6C137.6 233.6 99.2 160 96 80h835.2zM492.8-96h25.6c67.2 0 124.8 51.2 134.4 118.4H377.6c9.6-67.2 64-118.4 134.4-118.4h-19.2z" horiz-adv-x="1024" />
34
-
35
29
  <glyph glyph-name="sdoc-add" unicode="&#58968;" d="M512-128C227.2-128 0 99.2 0 384S227.2 896 512 896s512-227.2 512-512-227.2-512-512-512z m-51.2 563.2H291.2c-19.2 0-35.2-12.8-35.2-35.2v-35.2c0-19.2 12.8-35.2 35.2-35.2h169.6V160c0-19.2 12.8-35.2 35.2-35.2h35.2c19.2 0 35.2 12.8 35.2 35.2v169.6H736c19.2 0 35.2 12.8 35.2 35.2v35.2c0 19.2-12.8 35.2-35.2 35.2h-169.6V604.8c0 19.2-12.8 35.2-35.2 35.2h-35.2c-19.2 0-35.2-12.8-35.2-35.2v-169.6z" horiz-adv-x="1024" />
36
30
 
37
31
  <glyph glyph-name="sdoc-tag" unicode="&#58969;" d="M521.353986 860.33363l466.979644-466.979644c22.389435-22.389435 35.183398-51.175851 35.183398-83.160758s-12.793963-60.771324-35.183398-83.160759l-323.047562-319.849071c-22.389435-22.389435-51.175851-35.183398-79.962268-35.183398-31.984907 0-60.771324 12.793963-83.160758 35.183398L35.183398 374.163042c-25.587926 25.587926-38.381889 60.771324-31.984907 95.954721l31.984907 291.062655c6.396981 54.374342 47.977361 95.954721 102.351703 102.351703l291.062654 31.984907c31.984907 3.198491 67.168305-9.595472 92.756231-35.183398zM444.590209 767.577399L159.924536 735.592492l-31.984908-281.467182L578.926819-0.060372l316.65058 313.45209L444.590209 767.577399z m12.793963-127.939628c57.572833-57.572833 57.572833-147.130573 0-204.703406-25.587926-25.587926-63.969814-41.580379-102.351703-41.580379-38.381889 0-73.565286 12.793963-102.351703 41.580379-57.572833 57.572833-57.572833 147.130573 0 204.703406 57.572833 57.572833 150.329063 57.572833 204.703406 0z m-102.351703-70.366796c-6.396981 0-15.992454-3.198491-22.389435-9.595472-12.793963-12.793963-12.793963-31.984907 0-44.77887 12.793963-12.793963 31.984907-12.793963 44.77887 0 12.793963 12.793963 12.793963 31.984907 0 44.77887-6.396981 6.396981-12.793963 9.595472-22.389435 9.595472z" horiz-adv-x="1024" />
@@ -1,11 +1,11 @@
1
1
  @font-face {
2
2
  font-family: "sdocfont"; /* Project id 4097705 */
3
- src: url('./sdoc-editor-font/iconfont.eot?t=1700642464361'); /* IE9 */
4
- src: url('./sdoc-editor-font/iconfont.eot?t=1700642464361#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
- url('./sdoc-editor-font/iconfont.woff2?t=1700642464361') format('woff2'),
6
- url('./sdoc-editor-font/iconfont.woff?t=1700642464361') format('woff'),
7
- url('./sdoc-editor-font/iconfont.ttf?t=1700642464361') format('truetype'),
8
- url('./sdoc-editor-font/iconfont.svg?t=1700642464361#sdocfont') format('svg');
3
+ src: url('./sdoc-editor-font/iconfont.eot?t=1702000194437'); /* IE9 */
4
+ src: url('./sdoc-editor-font/iconfont.eot?t=1702000194437#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
+ url('./sdoc-editor-font/iconfont.woff2?t=1702000194437') format('woff2'),
6
+ url('./sdoc-editor-font/iconfont.woff?t=1702000194437') format('woff'),
7
+ url('./sdoc-editor-font/iconfont.ttf?t=1702000194437') format('truetype'),
8
+ url('./sdoc-editor-font/iconfont.svg?t=1702000194437#sdocfont') format('svg');
9
9
  }
10
10
 
11
11
  .sdocfont {
@@ -16,8 +16,12 @@
16
16
  -moz-osx-font-smoothing: grayscale;
17
17
  }
18
18
 
19
- .sdoc-selected-text:before {
20
- content: "\e65e";
19
+ .sdoc-comment-quote:before {
20
+ content: "\e660";
21
+ }
22
+
23
+ .sdoc-find-replace:before {
24
+ content: "\e65f";
21
25
  }
22
26
 
23
27
  .sdoc-freezed:before {
@@ -36,10 +40,6 @@
36
40
  content: "\e65b";
37
41
  }
38
42
 
39
- .sdoc-notification:before {
40
- content: "\e65a";
41
- }
42
-
43
43
  .sdoc-add:before {
44
44
  content: "\e658";
45
45
  }
@@ -391,3 +391,4 @@
391
391
  .sdoc-user:before {
392
392
  content: "\e629";
393
393
  }
394
+