@seafile/sdoc-editor 0.4.0 → 0.4.2-1

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 (30) hide show
  1. package/dist/basic-sdk/assets/css/sdoc-md-viewer.css +29 -0
  2. package/dist/basic-sdk/constants/index.js +2 -2
  3. package/dist/basic-sdk/extension/plugins/blockquote/plugin.js +47 -55
  4. package/dist/basic-sdk/extension/plugins/file-link/render-elem.js +2 -2
  5. package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +13 -6
  6. package/dist/basic-sdk/extension/plugins/image/render-elem.js +15 -10
  7. package/dist/basic-sdk/extension/plugins/sdoc-link/render-elem.js +2 -2
  8. package/dist/basic-sdk/extension/plugins/table/plugin.js +20 -3
  9. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/index.css +26 -9
  10. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-delete-modify-decorate.js +9 -9
  11. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-modify-delete-decorate.js +8 -8
  12. package/dist/basic-sdk/extension/render/element-decorate/rebase-decorate/rebase-modify-modify-decorate.js +8 -11
  13. package/dist/basic-sdk/index.js +2 -2
  14. package/dist/basic-sdk/md-outline/index.js +70 -0
  15. package/dist/basic-sdk/md-outline/outline-item.js +24 -0
  16. package/dist/basic-sdk/md-outline/style.css +45 -0
  17. package/dist/basic-sdk/utils/rebase.js +20 -4
  18. package/dist/basic-sdk/views/index.js +2 -1
  19. package/dist/basic-sdk/views/sdoc-md-viewer.js +44 -0
  20. package/dist/components/doc-operations/index.js +1 -2
  21. package/dist/components/doc-operations/more-operations.js +17 -4
  22. package/dist/components/tip-dialog/index.js +1 -1
  23. package/dist/index.js +2 -1
  24. package/dist/pages/markdown-viewer.js +17 -0
  25. package/package.json +1 -1
  26. package/public/locales/en/sdoc-editor.json +4 -1
  27. package/public/locales/fr/sdoc-editor.json +2 -1
  28. package/public/locales/ru/sdoc-editor.json +2 -2
  29. package/public/locales/zh_CN/sdoc-editor.json +5 -2
  30. package/dist/components/doc-operations/history-operation.js +0 -23
@@ -0,0 +1,29 @@
1
+ .sdoc-editor-container {
2
+ flex: 1;
3
+ display: flex;
4
+ min-height: 0;
5
+ }
6
+
7
+ .sdoc-md-scroll-container {
8
+ display: flex;
9
+ overflow: auto;
10
+ }
11
+
12
+ .sdoc-md-scroll-container .sdoc-article-container {
13
+ width: 100%;
14
+ margin: 0 340px 0 40px !important;
15
+ }
16
+
17
+ .sdoc-md-scroll-container .sdoc-article-container .article .sdoc-header-2 {
18
+ border-bottom: 1px solid #ccc;
19
+ }
20
+
21
+ .sdoc-md-outline-container {
22
+ height: 80%;
23
+ overflow-y: auto;
24
+ padding-right: 1rem;
25
+ position: fixed;
26
+ right: 0;
27
+ top: 97px;
28
+ width: 300px;
29
+ }
@@ -29,9 +29,9 @@ export const MODIFY_TYPE = {
29
29
  export const REBASE_TYPE = {
30
30
  MODIFY_MODIFY: 'modify_modify',
31
31
  DELETE_MODIFY: 'delete_modify',
32
- MODIFY_DELETE: 'modify_delete',
33
- CHILDREN_MODIFY: 'children_modify'
32
+ MODIFY_DELETE: 'modify_delete'
34
33
  };
34
+ export const REBASE_TYPES = [REBASE_TYPE.MODIFY_DELETE, REBASE_TYPE.DELETE_MODIFY, REBASE_TYPE.MODIFY_MODIFY];
35
35
  export const REBASE_MARK_KEY = {
36
36
  ORIGIN: 'origin',
37
37
  REBASE_TYPE: 'rebase_type',
@@ -1,14 +1,10 @@
1
- import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
- import { Editor, Element, Point, Transforms, Node, Range } from '@seafile/slate';
3
- import { ReactEditor } from '@seafile/slate-react';
4
- import { generateEmptyElement, getSelectedNodeByType, isSelectionAtBlockStart } from '../../core';
1
+ import { Editor, Element, Transforms, Node } from '@seafile/slate';
2
+ import { focusEditor, generateDefaultText, getSelectedNodeByType, isSelectionAtBlockStart } from '../../core';
5
3
  import { BLOCKQUOTE, PARAGRAPH, CODE_BLOCK, TABLE } from '../../constants';
6
4
  import { setBlockQuoteType, getFormattedElements, getFormattedRestElements } from './helpers';
7
- import { getCalloutEntry, insertElementAtNewLineInCallout } from '../callout/helper';
8
5
  const withBlockquote = editor => {
9
6
  const {
10
7
  insertBreak,
11
- insertText,
12
8
  deleteBackward,
13
9
  insertFragment
14
10
  } = editor;
@@ -18,40 +14,38 @@ const withBlockquote = editor => {
18
14
  selection
19
15
  } = editor;
20
16
  if (selection == null) return insertBreak();
21
- const [nodeEntry] = Editor.nodes(editor, {
17
+ const [quoteBlockEntry] = Editor.nodes(editor, {
22
18
  match: n => Element.isElement(n) && n.type === BLOCKQUOTE,
23
19
  universal: true
24
20
  });
25
- if (!nodeEntry) return insertBreak();
26
- const quoteElem = nodeEntry[0];
27
- const quotePath = ReactEditor.findPath(editor, quoteElem);
28
- const quoteEndLocation = Editor.end(editor, quotePath);
29
- if (Point.equals(quoteEndLocation, selection.focus)) {
30
- // Cursor is at the end of blockquote
31
- const str = Node.string(quoteElem);
32
- // The last of the blockquote text is \n;
33
- if (str && str.slice(-1) === '\n') {
34
- const calloutEntry = getCalloutEntry(editor);
35
- if (calloutEntry) {
36
- // If the cursor is at the end of the callout, insert a paragraph inside the callout
37
- // Remove the last \n
38
- editor.deleteBackward('character');
39
- insertElementAtNewLineInCallout(editor, PARAGRAPH, quotePath);
40
- return;
41
- }
42
- // Step 1: Remove the last \n
43
- editor.deleteBackward('character');
44
- // Step 2: Insert a paragraph
45
- const p = generateEmptyElement(PARAGRAPH);
46
- Transforms.insertNodes(newEditor, p, {
47
- mode: 'highest'
21
+ if (!quoteBlockEntry) return insertBreak();
22
+ const [currentLineEntry] = Editor.nodes(newEditor, {
23
+ match: n => Element.isElement(n) && n.type === PARAGRAPH,
24
+ mode: 'lowest'
25
+ });
26
+ // Exit blockquote when current line is empty
27
+ const isAtEnd = currentLineEntry[1].slice(-1)[0] === quoteBlockEntry[0].children.length - 1;
28
+ if (isAtEnd) {
29
+ const isEmptyLine = !(currentLineEntry && Editor.string(newEditor, currentLineEntry[1]).length);
30
+ const movePath = quoteBlockEntry[1];
31
+ movePath.push(movePath.pop() + 1);
32
+ if (isEmptyLine) {
33
+ Transforms.moveNodes(newEditor, {
34
+ at: currentLineEntry[1],
35
+ to: movePath
48
36
  });
49
37
  return;
50
38
  }
51
39
  }
52
40
 
53
- // In other cases, insert a newline
54
- insertText('\n');
41
+ // Insert new line
42
+ Transforms.insertNodes(editor, {
43
+ type: PARAGRAPH,
44
+ children: [generateDefaultText()]
45
+ }, {
46
+ at: newEditor.selection,
47
+ select: true
48
+ });
55
49
  };
56
50
  newEditor.deleteBackward = unit => {
57
51
  const {
@@ -63,32 +57,30 @@ const withBlockquote = editor => {
63
57
  }
64
58
  const node = getSelectedNodeByType(editor, BLOCKQUOTE);
65
59
  if (node) {
66
- if (isSelectionAtBlockStart(editor)) {
60
+ const [currentLineEntry] = Editor.nodes(newEditor, {
61
+ match: n => Element.isElement(n) && n.type === PARAGRAPH,
62
+ mode: 'lowest'
63
+ });
64
+ if (!currentLineEntry) return deleteBackward(unit);
65
+ const currentLineIndex = currentLineEntry[1].slice(-1)[0];
66
+ if (currentLineIndex === 0) {
67
67
  setBlockQuoteType(editor, PARAGRAPH);
68
68
  return;
69
69
  }
70
- if (unit === 'line' && Range.isCollapsed(selection)) {
71
- const quoteString = Node.string(node);
72
- for (let index = selection.anchor.offset; index > 1; index--) {
73
- const char = quoteString.slice(index - 1, index);
74
- if (char === '\n') {
75
- const deleteRange = selection.anchor.offset === index ? _objectSpread(_objectSpread({}, selection), {}, {
76
- anchor: _objectSpread(_objectSpread({}, selection.anchor), {}, {
77
- offset: index - 1
78
- })
79
- }) // cursor at beginning of line, delete \n
80
- : _objectSpread(_objectSpread({}, selection), {}, {
81
- anchor: _objectSpread(_objectSpread({}, selection.anchor), {}, {
82
- offset: index
83
- })
84
- }); // cursor at middle or end of line, save \n
85
- Transforms.delete(editor, {
86
- at: deleteRange
87
- });
88
- return;
89
- }
90
- }
91
- deleteBackward(unit);
70
+ if (isSelectionAtBlockStart(editor)) {
71
+ const lineText = Node.string(currentLineEntry[0]);
72
+ const previousNodeEntry = Editor.previous(editor, {
73
+ at: currentLineEntry[1]
74
+ });
75
+ const focusPoint = Editor.end(newEditor, previousNodeEntry[1]);
76
+ Transforms.insertText(newEditor, lineText, {
77
+ at: Editor.end(newEditor, previousNodeEntry[1])
78
+ });
79
+ Transforms.removeNodes(editor, {
80
+ at: currentLineEntry[1]
81
+ });
82
+ focusEditor(newEditor, focusPoint);
83
+ return;
92
84
  }
93
85
  }
94
86
  deleteBackward(unit);
@@ -86,9 +86,9 @@ const FileLink = _ref => {
86
86
  // eslint-disable-next-line react-hooks/exhaustive-deps
87
87
  }, []);
88
88
  let style = {};
89
- if (element.ADD) {
89
+ if (element.add) {
90
90
  style = _objectSpread({}, ADDED_STYLE);
91
- } else if (element.DELETE) {
91
+ } else if (element.delete) {
92
92
  style = _objectSpread({}, DELETED_STYLE);
93
93
  }
94
94
  if (style.computed_background_color) {
@@ -19,7 +19,6 @@ const ImageHoverMenu = _ref => {
19
19
  element,
20
20
  parentNodeEntry,
21
21
  onHideImageHoverMenu,
22
- onShowCaption,
23
22
  t
24
23
  } = _ref;
25
24
  const {
@@ -31,7 +30,7 @@ const ImageHoverMenu = _ref => {
31
30
  type
32
31
  } = parentNodeEntry[0];
33
32
  const {
34
- caption = ''
33
+ show_caption = false
35
34
  } = data;
36
35
  const [popoverState, setPopoverState] = useState({
37
36
  displayPopover: false,
@@ -125,6 +124,14 @@ const ImageHoverMenu = _ref => {
125
124
  onHideImageHoverMenu();
126
125
  return;
127
126
  }
127
+ if (Object.keys(props)[0] === 'show_caption') {
128
+ Transforms.setNodes(editor, {
129
+ data: _objectSpread(_objectSpread({}, data), props)
130
+ }, {
131
+ at: path
132
+ });
133
+ return;
134
+ }
128
135
  }
129
136
  // eslint-disable-next-line react-hooks/exhaustive-deps
130
137
  }, []);
@@ -182,11 +189,11 @@ const ImageHoverMenu = _ref => {
182
189
  id: "sdoc_image_caption",
183
190
  role: "button",
184
191
  className: classnames('op-item', 'ml-1', {
185
- 'active': (caption === null || caption === void 0 ? void 0 : caption.length) !== 0
192
+ 'active': show_caption
186
193
  }),
187
- onClick: () => {
188
- onShowCaption();
189
- }
194
+ onClick: event => onSelect(event, {
195
+ 'show_caption': !show_caption
196
+ })
190
197
  }, /*#__PURE__*/React.createElement("i", {
191
198
  className: "sdocfont sdoc-describe icon-font mr-1"
192
199
  }), isShowTooltip && /*#__PURE__*/React.createElement(Tooltip, {
@@ -10,9 +10,10 @@ import { INTERNAL_EVENT } from '../../../constants';
10
10
  import ImageHoverMenu from './hover-menu';
11
11
  import { useScrollContext } from '../../../hooks/use-scroll-context';
12
12
  import { IMAGE_BORDER_TYPE } from './constants';
13
- import { ADDED_STYLE, DELETED_STYLE } from '../../constants';
13
+ import { ADDED_STYLE, DELETED_STYLE, IMAGE_BLOCK } from '../../constants';
14
14
  import imagePlaceholder from '../../../assets/images/image-placeholder.png';
15
15
  const Image = _ref => {
16
+ var _imageRef$current, _imageRef$current2;
16
17
  let {
17
18
  element,
18
19
  editor,
@@ -27,6 +28,9 @@ const Image = _ref => {
27
28
  data,
28
29
  border_type = IMAGE_BORDER_TYPE[0].type
29
30
  } = element;
31
+ const {
32
+ show_caption = false
33
+ } = data;
30
34
  const path = ReactEditor.findPath(editor, element);
31
35
  const nodeEntry = Editor.node(editor, [path[0]]);
32
36
  const imageStyle = {
@@ -42,7 +46,6 @@ const Image = _ref => {
42
46
  const [isShowImageHoverMenu, setIsShowImageHoverMenu] = useState(false);
43
47
  const [menuPosition, setMenuPosition] = useState({});
44
48
  const [caption, setCaption] = useState((data === null || data === void 0 ? void 0 : data.caption) || '');
45
- const [isShowCaption, setIsShowCaption] = useState(false);
46
49
  const registerEvent = useCallback(eventList => {
47
50
  eventList.forEach(element => {
48
51
  document.addEventListener(element.eventName, element.event);
@@ -114,7 +117,8 @@ const Image = _ref => {
114
117
  var _imagePreviewer$;
115
118
  if (isResizing) return;
116
119
  const imagePreviewer = document.getElementsByClassName('sf-editor-image-previewer');
117
- if (e.target === imageRef.current || ((_imagePreviewer$ = imagePreviewer[0]) === null || _imagePreviewer$ === void 0 ? void 0 : _imagePreviewer$.contains(e.target))) return;
120
+ const isCaptionInput = e.target.id === 'sdoc-image-caption-input';
121
+ if (e.target === imageRef.current || ((_imagePreviewer$ = imagePreviewer[0]) === null || _imagePreviewer$ === void 0 ? void 0 : _imagePreviewer$.contains(e.target)) || isCaptionInput) return;
118
122
  setIsShowImageHoverMenu(false);
119
123
  }, [isResizing]);
120
124
  useEffect(() => {
@@ -225,10 +229,11 @@ const Image = _ref => {
225
229
  }), isResizing && /*#__PURE__*/React.createElement("span", {
226
230
  className: "image-size",
227
231
  contentEditable: false
228
- }, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(movingWidth || imageRef.current.clientWidth)), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === 'image_block' && (isShowCaption || (data === null || data === void 0 ? void 0 : data.caption)) && /*#__PURE__*/React.createElement("input", {
232
+ }, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(movingWidth || ((_imageRef$current = imageRef.current) === null || _imageRef$current === void 0 ? void 0 : _imageRef$current.clientWidth))), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === IMAGE_BLOCK && show_caption && /*#__PURE__*/React.createElement("input", {
233
+ id: "sdoc-image-caption-input",
229
234
  className: "sdoc-image-caption-input-wrapper",
230
235
  style: {
231
- width: (data === null || data === void 0 ? void 0 : data.width) || imageRef.current.clientWidth
236
+ width: (data === null || data === void 0 ? void 0 : data.width) || ((_imageRef$current2 = imageRef.current) === null || _imageRef$current2 === void 0 ? void 0 : _imageRef$current2.clientWidth)
232
237
  },
233
238
  placeholder: t('Insert_caption'),
234
239
  value: caption,
@@ -246,9 +251,6 @@ const Image = _ref => {
246
251
  parentNodeEntry: nodeEntry,
247
252
  onHideImageHoverMenu: () => {
248
253
  setIsShowImageHoverMenu(false);
249
- },
250
- onShowCaption: () => {
251
- setIsShowCaption(true);
252
254
  }
253
255
  })));
254
256
  };
@@ -266,8 +268,11 @@ export function renderImage(props, editor) {
266
268
  if (leaf && leaf.computed_background_color) {
267
269
  style['backgroundColor'] = leaf.computed_background_color;
268
270
  }
269
- if (element.ADD || element.DELETE) {
270
- style = Object.assign({}, style, element.ADD ? ADDED_STYLE : DELETED_STYLE);
271
+ if (element.add || element.delete) {
272
+ style = Object.assign({}, style, element.add ? ADDED_STYLE : DELETED_STYLE);
273
+ if (style.computed_background_color) {
274
+ style['backgroundColor'] = style.computed_background_color;
275
+ }
271
276
  }
272
277
  return /*#__PURE__*/React.createElement(SdocImage, Object.assign({}, props, {
273
278
  style: style,
@@ -88,9 +88,9 @@ const SdocFileLink = _ref => {
88
88
  // eslint-disable-next-line react-hooks/exhaustive-deps
89
89
  }, []);
90
90
  let style = {};
91
- if (element.ADD) {
91
+ if (element.add) {
92
92
  style = _objectSpread({}, ADDED_STYLE);
93
- } else if (element.DELETE) {
93
+ } else if (element.delete) {
94
94
  style = _objectSpread({}, DELETED_STYLE);
95
95
  }
96
96
  if (style.computed_background_color) {
@@ -1,8 +1,9 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import isHotkey from 'is-hotkey';
3
- import { Editor, Transforms, Path } from '@seafile/slate';
4
- import { getNodeType, getParentNode, getSelectedNodeByType, isLastNode, generateEmptyElement } from '../../core';
5
- import { ELEMENT_TYPE, KEYBOARD, PARAGRAPH, CLIPBOARD_FORMAT_KEY } from '../../constants';
3
+ import { Editor, Transforms, Path, Element } from '@seafile/slate';
4
+ import { ReactEditor } from '@seafile/slate-react';
5
+ import { getNodeType, getParentNode, getSelectedNodeByType, isLastNode, generateEmptyElement, focusEditor } from '../../core';
6
+ import { ELEMENT_TYPE, KEYBOARD, PARAGRAPH, CLIPBOARD_FORMAT_KEY, CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST } from '../../constants';
6
7
  import { TABLE_MAX_ROWS, EMPTY_SELECTED_RANGE, TABLE_ELEMENT, TABLE_ELEMENT_POSITION } from './constants';
7
8
  import ObjectUtils from '../../../utils/object-utils';
8
9
  import { getSelectedInfo, insertTableElement, removeTable, insertMultipleRowsAndColumns, setTableFragmentData, deleteTableRangeData, focusCell, deleteHandler, isTableLocation, isLastTableCell } from './helpers';
@@ -88,9 +89,25 @@ const withTable = editor => {
88
89
  const before = Editor.before(newEditor, selection);
89
90
  if (before) {
90
91
  // If the current is not a table and the previous one is a table, no deletion will be performed. Otherwise, the last cell of the table will be deleted
92
+ // If deleting node is empty check-list, order-list, unordered-list, change to paragraph
91
93
  const isTableOnBeforeLocation = isTableLocation(newEditor, before);
92
94
  const isTableOnCurSelection = isTableLocation(newEditor, selection);
93
95
  if (isTableOnBeforeLocation && !isTableOnCurSelection) {
96
+ const transformTypes = [CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST];
97
+ const [currentNodeEntry] = Editor.nodes(editor, {
98
+ match: n => Element.isElement(n) && !Editor.parent(n, ReactEditor.findPath(editor, n))[1].length
99
+ });
100
+ if (!currentNodeEntry) return;
101
+ const [currentNode, currentPath] = Array.from(currentNodeEntry);
102
+ if (transformTypes.includes(currentNode.type)) {
103
+ Transforms.delete(newEditor, {
104
+ at: currentPath
105
+ });
106
+ Transforms.insertNodes(newEditor, generateEmptyElement(PARAGRAPH), {
107
+ at: currentPath
108
+ });
109
+ focusEditor(editor, Editor.start(editor, currentPath));
110
+ }
94
111
  return;
95
112
  }
96
113
  }
@@ -1,29 +1,46 @@
1
1
  .sdoc-rebase-btn-group {
2
+ display: flex;
3
+ width: 100%;
2
4
  color: #aaa;
5
+ margin-bottom: 3px;
3
6
  }
4
7
 
5
8
  .sdoc-rebase-btn-group .sdoc-rebase-btn {
6
9
  cursor: pointer;
7
10
  }
8
11
 
9
- .sdoc-rebase-current-changes-start {
12
+ .sdoc-rebase-other-changes-title {
13
+ width: 100%;
14
+ padding-left: 4px;
10
15
  background-color: rgb(202, 232, 254);
16
+ border-radius: 3px 3px 0 0;
11
17
  }
12
18
 
13
- .sdoc-rebase-current-changes {
19
+ .sdoc-rebase-other-changes {
14
20
  background-color: rgba(202, 232, 254, .8);
21
+ border-radius: 0 0 3px 3px;
22
+ margin-bottom: 3px;
15
23
  }
16
24
 
17
- .sdoc-rebase-incoming-changes {
25
+ .sdoc-rebase-my-changes-title {
26
+ width: 100%;
27
+ padding-left: 4px;
28
+ background-color: rgb(212, 212, 254);
29
+ border-radius: 3px 3px 0 0;
30
+ }
31
+
32
+ .sdoc-rebase-my-changes {
18
33
  background-color: rgb(222, 232, 254);
34
+ border-radius: 0 0 3px 3px;
19
35
  }
20
36
 
21
- .sdoc-rebase-incoming-changes > *:first-child,
22
- .sdoc-rebase-current-changes > *:first-child {
23
- margin: 0;
24
- padding: 0.8em 0 0.8em 0.2em;
37
+ .sdoc-rebase-my-changes.empty,
38
+ .sdoc-rebase-other-changes.empty {
39
+ height: 3px;
25
40
  }
26
41
 
27
- .sdoc-rebase-incoming-changes-end {
28
- background-color: rgb(212, 212, 254);
42
+ .sdoc-rebase-my-changes > *:first-child,
43
+ .sdoc-rebase-other-changes > *:first-child {
44
+ margin: 0;
45
+ padding: 0.8em 0 0.8em 0.2em;
29
46
  }
@@ -35,7 +35,7 @@ const RebaseDeleteModifyDecorate = _ref => {
35
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
36
36
  }, [editor, element]);
37
37
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
38
- className: "w-100 d-flex sdoc-rebase-btn-group",
38
+ className: "sdoc-rebase-btn-group",
39
39
  contentEditable: false
40
40
  }, /*#__PURE__*/React.createElement("div", {
41
41
  className: "sdoc-rebase-btn",
@@ -51,17 +51,17 @@ const RebaseDeleteModifyDecorate = _ref => {
51
51
  className: "sdoc-rebase-btn",
52
52
  onClick: deleteMark
53
53
  }, t('Keep_both_modification'))), /*#__PURE__*/React.createElement("div", {
54
- className: "w-100 sdoc-rebase-current-changes-start",
54
+ className: "sdoc-rebase-other-changes-title",
55
55
  contentEditable: false
56
- }, '<<<<<<<'), /*#__PURE__*/React.createElement("div", {
57
- className: "w-100",
56
+ }, t('Other_modification')), /*#__PURE__*/React.createElement("div", {
57
+ className: "sdoc-rebase-other-changes empty",
58
58
  contentEditable: false
59
- }, '======='), /*#__PURE__*/React.createElement("div", {
60
- className: "w-100 sdoc-rebase-incoming-changes",
59
+ }), /*#__PURE__*/React.createElement("div", {
60
+ className: "sdoc-rebase-my-changes-title",
61
61
  contentEditable: false
62
- }, children), /*#__PURE__*/React.createElement("div", {
63
- className: "w-100 sdoc-rebase-incoming-changes-end",
62
+ }, t('My_modification')), /*#__PURE__*/React.createElement("div", {
63
+ className: "sdoc-rebase-my-changes",
64
64
  contentEditable: false
65
- }, '>>>>>>>'));
65
+ }, children));
66
66
  };
67
67
  export default RebaseDeleteModifyDecorate;
@@ -35,7 +35,7 @@ const RebaseModifyDeleteDecorate = _ref => {
35
35
  // eslint-disable-next-line react-hooks/exhaustive-deps
36
36
  }, [editor, element]);
37
37
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
38
- className: "w-100 d-flex sdoc-rebase-btn-group",
38
+ className: "sdoc-rebase-btn-group",
39
39
  contentEditable: false
40
40
  }, /*#__PURE__*/React.createElement("div", {
41
41
  className: "sdoc-rebase-btn",
@@ -51,17 +51,17 @@ const RebaseModifyDeleteDecorate = _ref => {
51
51
  className: "sdoc-rebase-btn",
52
52
  onClick: deleteMark
53
53
  }, t('Keep_both_modification'))), /*#__PURE__*/React.createElement("div", {
54
- className: "w-100 sdoc-rebase-current-changes-start",
54
+ className: "sdoc-rebase-other-changes-title",
55
55
  contentEditable: false
56
- }, '<<<<<<<'), /*#__PURE__*/React.createElement("div", {
57
- className: "w-100 sdoc-rebase-incoming-changes",
56
+ }, t('Other_modification')), /*#__PURE__*/React.createElement("div", {
57
+ className: "w-100 sdoc-rebase-my-changes",
58
58
  contentEditable: false
59
59
  }, children), /*#__PURE__*/React.createElement("div", {
60
- className: "w-100",
60
+ className: "sdoc-rebase-my-changes-title",
61
61
  contentEditable: false
62
- }, '======='), /*#__PURE__*/React.createElement("div", {
63
- className: "w-100 sdoc-rebase-incoming-changes-end",
62
+ }, t('My_modification')), /*#__PURE__*/React.createElement("div", {
63
+ className: "sdoc-rebase-my-changes empty",
64
64
  contentEditable: false
65
- }, '>>>>>>>'));
65
+ }));
66
66
  };
67
67
  export default RebaseModifyDeleteDecorate;
@@ -62,7 +62,7 @@ const RebaseModifyModifyDecorate = _ref => {
62
62
  }, [editor, element]);
63
63
  if (element[REBASE_MARK_KEY.ORIGIN] === REBASE_ORIGIN.OTHER) {
64
64
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
65
- className: "w-100 d-flex sdoc-rebase-btn-group",
65
+ className: "sdoc-rebase-btn-group",
66
66
  contentEditable: false
67
67
  }, /*#__PURE__*/React.createElement("div", {
68
68
  className: "sdoc-rebase-btn",
@@ -78,22 +78,19 @@ const RebaseModifyModifyDecorate = _ref => {
78
78
  className: "sdoc-rebase-btn",
79
79
  onClick: useBothChanges
80
80
  }, t('Keep_both_modification'))), /*#__PURE__*/React.createElement("div", {
81
- className: "w-100 sdoc-rebase-current-changes-start",
81
+ className: "sdoc-rebase-other-changes-title",
82
82
  contentEditable: false
83
- }, '<<<<<<<'), /*#__PURE__*/React.createElement("div", {
84
- className: "w-100 sdoc-rebase-current-changes",
83
+ }, t('Other_modification')), /*#__PURE__*/React.createElement("div", {
84
+ className: "sdoc-rebase-other-changes",
85
85
  contentEditable: false
86
86
  }, children));
87
87
  }
88
88
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
89
- className: "w-100",
89
+ className: "sdoc-rebase-my-changes-title",
90
90
  contentEditable: false
91
- }, '======='), /*#__PURE__*/React.createElement("div", {
92
- className: "w-100 sdoc-rebase-incoming-changes",
91
+ }, t('My_modification')), /*#__PURE__*/React.createElement("div", {
92
+ className: "sdoc-rebase-my-changes",
93
93
  contentEditable: false
94
- }, children), /*#__PURE__*/React.createElement("div", {
95
- className: "w-100 sdoc-rebase-incoming-changes-end",
96
- contentEditable: false
97
- }, '>>>>>>>'));
94
+ }, children));
98
95
  };
99
96
  export default RebaseModifyModifyDecorate;
@@ -1,6 +1,6 @@
1
1
  import SDocEditor from './editor/sdoc-editor';
2
2
  import RevisionEditor from './editor/revision-editor';
3
- import { DiffViewer, SDocViewer, PublishedRevisionDiffViewer } from './views';
3
+ import { DiffViewer, SDocViewer, PublishedRevisionDiffViewer, SDocMdViewer } from './views';
4
4
  import SDocOutline from './outline';
5
5
  import EventBus from './utils/event-bus';
6
- export { SDocEditor, RevisionEditor, SDocViewer, SDocOutline, EventBus, DiffViewer, PublishedRevisionDiffViewer };
6
+ export { SDocEditor, RevisionEditor, SDocViewer, SDocOutline, EventBus, DiffViewer, PublishedRevisionDiffViewer, SDocMdViewer };
@@ -0,0 +1,70 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import OutlineItem from './Outline-item';
4
+ import { useScrollContext } from '../hooks/use-scroll-context';
5
+ import './style.css';
6
+ const getHeaderList = children => {
7
+ const headerList = [];
8
+ children.forEach(node => {
9
+ if (node.type === 'header2' || node.type === 'header3') {
10
+ headerList.push(node);
11
+ }
12
+ });
13
+ return headerList;
14
+ };
15
+ const Outline = _ref => {
16
+ let {
17
+ editor
18
+ } = _ref;
19
+ const {
20
+ t
21
+ } = useTranslation();
22
+ const scrollRef = useScrollContext();
23
+ const [headerList, setHeaderList] = useState([]);
24
+ const [activeId, setActiveId] = useState('');
25
+ useEffect(() => {
26
+ const headerList = getHeaderList(editor.children);
27
+ setHeaderList(headerList);
28
+ }, [editor.children]);
29
+ const handleScroll = useCallback(e => {
30
+ const scrollTop = scrollRef.current.scrollTop;
31
+ const styles = getComputedStyle(scrollRef === null || scrollRef === void 0 ? void 0 : scrollRef.current);
32
+ const paddingTop = parseInt(styles.paddingTop);
33
+ for (let i = 0; i < headerList.length; i++) {
34
+ const headerItem = headerList[i];
35
+ const dom = document.getElementById(headerItem.id);
36
+ const {
37
+ offsetTop,
38
+ offsetHeight
39
+ } = dom;
40
+ const styles = getComputedStyle(dom);
41
+ const marginTop = parseInt(styles.marginTop);
42
+ if (offsetTop + offsetHeight + marginTop > scrollTop - paddingTop) {
43
+ setActiveId(headerItem.id);
44
+ break;
45
+ }
46
+ }
47
+ }, [headerList, scrollRef]);
48
+ useEffect(() => {
49
+ let observerRefValue = null;
50
+ if (scrollRef.current) {
51
+ scrollRef.current.addEventListener('scroll', handleScroll);
52
+ observerRefValue = scrollRef.current;
53
+ }
54
+ return () => {
55
+ observerRefValue.removeEventListener('scroll', handleScroll);
56
+ };
57
+ }, [handleScroll, scrollRef]);
58
+ return /*#__PURE__*/React.createElement("div", {
59
+ className: "sdoc-md-editor-outline"
60
+ }, headerList.length === 0 && /*#__PURE__*/React.createElement("div", {
61
+ className: "empty-container"
62
+ }, t('No_out_line')), headerList.length > 0 && headerList.map((node, index) => {
63
+ return /*#__PURE__*/React.createElement(OutlineItem, {
64
+ key: index,
65
+ node: node,
66
+ activeId: activeId
67
+ });
68
+ }));
69
+ };
70
+ export default Outline;
@@ -0,0 +1,24 @@
1
+ import React, { useCallback } from 'react';
2
+ import classNames from 'classnames';
3
+ const OutlineItem = _ref => {
4
+ let {
5
+ node,
6
+ activeId
7
+ } = _ref;
8
+ const onItemClick = useCallback(() => {
9
+ const {
10
+ id
11
+ } = node;
12
+ document.getElementById(id).scrollIntoView();
13
+ }, [node]);
14
+ const className = classNames({
15
+ 'outline-h2': node.type === 'header2',
16
+ 'outline-h3': node.type === 'header3',
17
+ 'active': node.id === activeId
18
+ });
19
+ return /*#__PURE__*/React.createElement("div", {
20
+ className: className,
21
+ onClick: onItemClick
22
+ }, node.children.map(child => child.text).join(''));
23
+ };
24
+ export default OutlineItem;
@@ -0,0 +1,45 @@
1
+ .sdoc-md-editor-outline {
2
+ border-left: 1px solid #ddd;
3
+ padding: .5rem 1rem .5rem 0;
4
+ }
5
+
6
+ .sdoc-md-editor-outline .outline-h2,
7
+ .sdoc-md-editor-outline .outline-h3 {
8
+ white-space: nowrap;
9
+ overflow: hidden;
10
+ text-overflow: ellipsis;
11
+ }
12
+
13
+ .sdoc-md-editor-outline .outline-h2 {
14
+ margin-left: 20px;
15
+ line-height: 2.5;
16
+ color:#364149;
17
+ white-space: nowrap;
18
+ cursor:pointer;
19
+ }
20
+
21
+ .sdoc-md-editor-outline .outline-h2:hover {
22
+ color: #eb8205;
23
+ }
24
+
25
+ .sdoc-md-editor-outline .outline-h3 {
26
+ margin-left: 40px;
27
+ line-height: 2.5;
28
+ color:#364149;
29
+ white-space: nowrap;
30
+ cursor:pointer;
31
+ }
32
+
33
+ .sdoc-md-editor-outline .outline-h3:hover {
34
+ color: #eb8205;
35
+ }
36
+
37
+ .sdoc-md-editor-outline .empty-container {
38
+ margin-top: 10px;
39
+ text-align: center;
40
+ }
41
+
42
+ .sdoc-md-editor-outline .outline-h2.active,
43
+ .sdoc-md-editor-outline .outline-h3.active {
44
+ color: #eb8205;
45
+ }
@@ -1,12 +1,29 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import { generateIdMapAndIds, getIdDiffs } from './diff';
3
3
  import ObjectUtils from './object-utils';
4
- import { MODIFY_TYPE, REBASE_TYPE, REBASE_MARK_KEY, REBASE_ORIGIN } from '../constants';
4
+ import { MODIFY_TYPE, REBASE_TYPE, REBASE_MARK_KEY, REBASE_ORIGIN, REBASE_TYPES } from '../constants';
5
5
  import { ELEMENT_TYPE } from '../extension/constants';
6
6
  import { replaceNodeId } from '../node-id/helpers';
7
7
  export const hasConflict = content => {
8
8
  if (!Array.isArray(content) || content.length === 0) return false;
9
- return content.filter(item => item.rebase_type).length !== 0;
9
+ let flag = false;
10
+ for (let i = 0; i < content.length; i++) {
11
+ const element = content[i];
12
+ const {
13
+ rebase_type,
14
+ children
15
+ } = element;
16
+ if (REBASE_TYPES.includes(rebase_type)) {
17
+ flag = true;
18
+ break;
19
+ } else {
20
+ const childrenFlag = hasConflict(children);
21
+ if (!childrenFlag) continue;
22
+ flag = childrenFlag;
23
+ break;
24
+ }
25
+ }
26
+ return flag;
10
27
  };
11
28
  const getChanges = (masterContent, revisionContent) => {
12
29
  const {
@@ -156,8 +173,7 @@ const getMergeElement = (diffElement, baseElement) => {
156
173
  content: childrenContent
157
174
  } = getMergeContent(baseElement, diffElement.children);
158
175
  return [_objectSpread(_objectSpread({}, newElement), {}, {
159
- children: childrenContent,
160
- [REBASE_MARK_KEY.REBASE_TYPE]: REBASE_TYPE.CHILDREN_MODIFY
176
+ children: childrenContent
161
177
  })];
162
178
  }
163
179
  newElement[REBASE_MARK_KEY.OLD_ELEMENT] && delete newElement[REBASE_MARK_KEY.OLD_ELEMENT];
@@ -2,4 +2,5 @@ import SDocViewer from './sdoc-viewer';
2
2
  import DiffViewer from './sdoc-diff-viewer';
3
3
  import RevisionDiffViewer from './revision-diff-viewer';
4
4
  import PublishedRevisionDiffViewer from './published-revision-diff-viewer';
5
- export { SDocViewer, DiffViewer, RevisionDiffViewer, PublishedRevisionDiffViewer };
5
+ import SDocMdViewer from './sdoc-md-viewer';
6
+ export { SDocViewer, DiffViewer, RevisionDiffViewer, PublishedRevisionDiffViewer, SDocMdViewer };
@@ -0,0 +1,44 @@
1
+ import React, { useRef } from 'react';
2
+ import { createDefaultEditor } from '../extension';
3
+ import withNodeId from '../node-id';
4
+ import { generateDefaultDocContent } from '../../utils';
5
+ import { EditorContainer } from '../layout';
6
+ import ReadOnlyArticle from './readonly-article';
7
+ import { ColorProvider } from '../hooks/use-color-context';
8
+ import { ScrollContext } from '../hooks/use-scroll-context';
9
+ import Outline from '../md-outline';
10
+ import '../assets/css/sdoc-md-viewer.css';
11
+ const SDocMdViewer = _ref => {
12
+ let {
13
+ editor,
14
+ document,
15
+ showOutline
16
+ } = _ref;
17
+ const validEditor = editor || withNodeId(createDefaultEditor());
18
+ const slateValue = (document || generateDefaultDocContent()).children;
19
+ const scrollRef = useRef(null);
20
+ return /*#__PURE__*/React.createElement(EditorContainer, {
21
+ editor: validEditor,
22
+ readonly: true
23
+ }, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement("div", {
24
+ ref: scrollRef,
25
+ className: "sdoc-md-scroll-container"
26
+ }, /*#__PURE__*/React.createElement(ScrollContext.Provider, {
27
+ value: {
28
+ scrollRef
29
+ }
30
+ }, /*#__PURE__*/React.createElement(ReadOnlyArticle, {
31
+ editor: validEditor,
32
+ slateValue: slateValue,
33
+ isShowComment: false
34
+ }), showOutline && /*#__PURE__*/React.createElement("div", {
35
+ className: "sdoc-md-outline-container"
36
+ }, /*#__PURE__*/React.createElement(Outline, {
37
+ editor: validEditor
38
+ }))))));
39
+ };
40
+ SDocMdViewer.defaultProps = {
41
+ showToolbar: false,
42
+ showOutline: false
43
+ };
44
+ export default SDocMdViewer;
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import { withTranslation } from 'react-i18next';
3
3
  import context from '../../context';
4
4
  import RevisionOperations from './revision-operations';
5
- import HistoryOperation from './history-operation';
6
5
  import CollaboratorsOperation from './collaborators-operation';
7
6
  import MoreOperations from './more-operations';
8
7
  import CommentsOperation from './comments-operation';
@@ -34,6 +33,6 @@ const DocOperations = _ref => {
34
33
  handleViewChangesToggle: handleViewChangesToggle,
35
34
  handleRevisionMerged: handleRevisionMerged,
36
35
  handleRevisionPublished: handleRevisionPublished
37
- }), !isPublished && /*#__PURE__*/React.createElement(TagOperation, null), !isPublished && /*#__PURE__*/React.createElement(CommentsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(ShareOperation, null), /*#__PURE__*/React.createElement(HistoryOperation, null), !isPublished && /*#__PURE__*/React.createElement(CollaboratorsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(MoreOperations, null));
36
+ }), !isPublished && /*#__PURE__*/React.createElement(TagOperation, null), !isPublished && /*#__PURE__*/React.createElement(CommentsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(ShareOperation, null), !isPublished && /*#__PURE__*/React.createElement(CollaboratorsOperation, null), !isSdocRevision && /*#__PURE__*/React.createElement(MoreOperations, null));
38
37
  };
39
38
  export default withTranslation('sdoc-editor')(DocOperations);
@@ -9,6 +9,12 @@ const MoreOperations = _ref => {
9
9
  t
10
10
  } = _ref;
11
11
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
12
+ const parentFolderURL = context.getSetting('parentFolderURL');
13
+ const isPro = context.getSetting('isPro');
14
+ const isFreezed = context.getSetting('isFreezed');
15
+ const docPerm = context.getSetting('docPerm');
16
+ const historyURL = context.getSetting('historyURL');
17
+ const isSdocRevision = context.getSetting('isSdocRevision');
12
18
  const toggleDropdown = useCallback(isDropdownOpen => {
13
19
  setIsDropdownOpen(!isDropdownOpen);
14
20
  }, []);
@@ -20,9 +26,13 @@ const MoreOperations = _ref => {
20
26
  const eventBus = EventBus.getInstance();
21
27
  eventBus.dispatch(EXTERNAL_EVENT.UNFREEZE);
22
28
  }, []);
23
- const parentFolderURL = context.getSetting('parentFolderURL');
24
- const isPro = context.getSetting('isPro');
25
- const isFreezed = context.getSetting('isFreezed');
29
+ const handleClickHistory = useCallback(event => {
30
+ if (docPerm !== 'rw' || !historyURL) return;
31
+ if (isSdocRevision) return;
32
+ event.stopPropagation();
33
+ event.nativeEvent.stopImmediatePropagation();
34
+ window.location.href = historyURL;
35
+ }, [docPerm, historyURL, isSdocRevision]);
26
36
  return /*#__PURE__*/React.createElement(Dropdown, {
27
37
  isOpen: isDropdownOpen,
28
38
  toggle: () => toggleDropdown(isDropdownOpen)
@@ -44,6 +54,9 @@ const MoreOperations = _ref => {
44
54
  }, t('Unfreeze')), isPro && !isFreezed && /*#__PURE__*/React.createElement(DropdownItem, {
45
55
  className: "sdoc-dropdown-menu-item",
46
56
  onClick: onFreezeDocument
47
- }, t('Freeze_Document'))));
57
+ }, t('Freeze_Document')), /*#__PURE__*/React.createElement(DropdownItem, {
58
+ className: "sdoc-dropdown-menu-item",
59
+ onClick: handleClickHistory
60
+ }, t('Document_history'))));
48
61
  };
49
62
  export default withTranslation('sdoc-editor')(MoreOperations);
@@ -27,7 +27,7 @@ const TipDialog = _ref => {
27
27
  // eslint-disable-next-line react-hooks/exhaustive-deps
28
28
  }, [tipType, isSubmitting]);
29
29
  const onSubmit = useCallback(() => {
30
- if (tipType === TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES) {
30
+ if ([TIP_TYPE.HAS_CONFLICT_BEFORE_VIEW_CHANGES, TIP_TYPE.HAS_CONFLICT_BEFORE_PUBLISH].includes(tipType)) {
31
31
  closeDialog();
32
32
  return;
33
33
  }
package/dist/index.js CHANGED
@@ -4,4 +4,5 @@ import SimpleEditor from './pages/simple-editor';
4
4
  import SimpleViewer from './pages/simple-viewer';
5
5
  import DiffViewer from './pages/diff-viewer';
6
6
  import PublishedRevisionViewer from './pages/published-revision-viewer';
7
- export { SDocViewer, SimpleEditor, SimpleViewer, EventBus, EXTERNAL_EVENT, DiffViewer, PublishedRevisionViewer };
7
+ import MarkdownViewer from './pages/markdown-viewer';
8
+ export { SDocViewer, SimpleEditor, SimpleViewer, EventBus, EXTERNAL_EVENT, DiffViewer, PublishedRevisionViewer, MarkdownViewer };
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import context from '../context';
3
+ import ErrorBoundary from './error-boundary';
4
+ import { SDocMdViewer } from '../basic-sdk';
5
+ import '../assets/css/simple-viewer.css';
6
+ context.initApi();
7
+ const MarkdownViewer = _ref => {
8
+ let {
9
+ document,
10
+ showOutline
11
+ } = _ref;
12
+ return /*#__PURE__*/React.createElement(ErrorBoundary, null, /*#__PURE__*/React.createElement(SDocMdViewer, {
13
+ document: document,
14
+ showOutline: showOutline
15
+ }));
16
+ };
17
+ export default MarkdownViewer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.4.0",
3
+ "version": "0.4.2-1",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",
@@ -425,5 +425,8 @@
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
427
  "Freeze_Document": "Freeze Document",
428
- "Unfreeze": "Unfreeze"
428
+ "Unfreeze": "Unfreeze",
429
+ "Other_modification": "Other's modification",
430
+ "My_modification": "My modification",
431
+ "Document_history": "Document history"
429
432
  }
@@ -424,5 +424,6 @@
424
424
  "Row_number": "Row number",
425
425
  "Column_number": "Column number",
426
426
  "The_maximum_row_number_is_{number}": "The maximum row number is {number}",
427
- "The_maximum_column_number_is_{number}": "The maximum column number is {number}"
427
+ "Freeze_Document": "Freeze Document",
428
+ "Unfreeze": "Unfreeze"
428
429
  }
@@ -424,6 +424,6 @@
424
424
  "Row_number": "Номер строки",
425
425
  "Column_number": "Номер столбца",
426
426
  "The_maximum_row_number_is_{number}": "Максимальное количество строк - {number}",
427
- "Freeze_Document": "Freeze Document",
428
- "Unfreeze": "Unfreeze"
427
+ "Freeze_Document": "Заморозить документ",
428
+ "Unfreeze": "Разморозить"
429
429
  }
@@ -376,7 +376,7 @@
376
376
  "Link_sdoc": "链接 sdoc",
377
377
  "Link_file": "文件链接",
378
378
  "Keep_my_modification": "保留我的更改",
379
- "Keep_other_modification": "保留其他的更改",
379
+ "Keep_other_modification": "保留他人的更改",
380
380
  "Keep_both_modification": "保留两者更改",
381
381
  "Tip": "提示",
382
382
  "Rebase_delete_no_change_revision_tip": "修订改没有更改,是否删除修订稿?",
@@ -425,5 +425,8 @@
425
425
  "Column_number": "列数",
426
426
  "The_maximum_row_number_is_{number}": "最大行数为 {number}",
427
427
  "Freeze_Document": "冻结文档",
428
- "Unfreeze": "取消冻结"
428
+ "Unfreeze": "取消冻结",
429
+ "Other_modification": "他人更改",
430
+ "My_modification": "我的更改",
431
+ "Document_history":"文档历史"
429
432
  }
@@ -1,23 +0,0 @@
1
- import React, { useCallback } from 'react';
2
- import context from '../../context';
3
- const HistoryOperation = () => {
4
- const docPerm = context.getSetting('docPerm');
5
- const historyURL = context.getSetting('historyURL');
6
- const isSdocRevision = context.getSetting('isSdocRevision');
7
- const toggleHistory = useCallback(event => {
8
- event.stopPropagation();
9
- event.nativeEvent.stopImmediatePropagation();
10
- window.location.href = historyURL;
11
-
12
- // eslint-disable-next-line react-hooks/exhaustive-deps
13
- }, []);
14
- if (docPerm !== 'rw' || !historyURL) return null;
15
- if (isSdocRevision) return null;
16
- return /*#__PURE__*/React.createElement("span", {
17
- className: "op-item",
18
- onClick: toggleHistory
19
- }, /*#__PURE__*/React.createElement("i", {
20
- className: "sdocfont sdoc-history"
21
- }));
22
- };
23
- export default HistoryOperation;