@seafile/sdoc-editor 0.5.68 → 0.5.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basic-sdk/editor/sdoc-editor.js +1 -18
- package/dist/basic-sdk/editor/wiki-editor.js +161 -0
- package/dist/basic-sdk/extension/plugins/header/menu/index.js +1 -1
- package/dist/basic-sdk/extension/plugins/link/menu/index.js +3 -3
- package/dist/basic-sdk/extension/plugins/link/plugin.js +2 -0
- package/dist/basic-sdk/extension/plugins/table/plugin.js +8 -1
- package/dist/basic-sdk/utils/dom-utils.js +1 -2
- package/dist/components/doc-operations/more-operations.js +3 -3
- package/dist/pages/sdoc-wiki-viewer.js +11 -10
- package/package.json +1 -1
|
@@ -25,8 +25,7 @@ const SdocEditor = forwardRef((_ref, ref) => {
|
|
|
25
25
|
isReloading,
|
|
26
26
|
showComment,
|
|
27
27
|
isShowHeaderToolbar = true,
|
|
28
|
-
showOutline = true
|
|
29
|
-
isWikiReadOnly
|
|
28
|
+
showOutline = true
|
|
30
29
|
} = _ref;
|
|
31
30
|
const validEditor = propsEditor || useMemo(() => {
|
|
32
31
|
const defaultEditor = createDefaultEditor();
|
|
@@ -167,22 +166,6 @@ const SdocEditor = forwardRef((_ref, ref) => {
|
|
|
167
166
|
}
|
|
168
167
|
const isShowComment = typeof showComment === 'boolean' ? showComment : true;
|
|
169
168
|
const Provider = isShowComment ? CollaboratorsProvider : Fragment;
|
|
170
|
-
if (isWikiReadOnly) {
|
|
171
|
-
return /*#__PURE__*/React.createElement(EditorContainer, {
|
|
172
|
-
editor: validEditor,
|
|
173
|
-
readonly: isWikiReadOnly
|
|
174
|
-
}, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement(EditorContent, {
|
|
175
|
-
docValue: slateValue,
|
|
176
|
-
showOutline: showOutline !== null && showOutline !== void 0 ? showOutline : true,
|
|
177
|
-
readonly: isWikiReadOnly,
|
|
178
|
-
editor: validEditor,
|
|
179
|
-
showComment: isShowComment
|
|
180
|
-
}, /*#__PURE__*/React.createElement(ReadOnlyArticle, {
|
|
181
|
-
editor: validEditor,
|
|
182
|
-
slateValue: slateValue,
|
|
183
|
-
showComment: isShowComment
|
|
184
|
-
}))));
|
|
185
|
-
}
|
|
186
169
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EditorContainer, {
|
|
187
170
|
editor: validEditor
|
|
188
171
|
}, /*#__PURE__*/React.createElement(Provider, null, /*#__PURE__*/React.createElement(ColorProvider, null, isShowHeaderToolbar && /*#__PURE__*/React.createElement(HeaderToolbar, {
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import React, { useEffect, useState, useImperativeHandle, forwardRef, useMemo, useCallback } from 'react';
|
|
3
|
+
import { Editor } from '@seafile/slate';
|
|
4
|
+
import deepCopy from 'deep-copy';
|
|
5
|
+
import context from '../../context';
|
|
6
|
+
import CommonLoading from '../../components/common-loading';
|
|
7
|
+
import { INTERNAL_EVENT, PAGE_EDIT_AREA_WIDTH } from '../constants';
|
|
8
|
+
import { createDefaultEditor } from '../extension';
|
|
9
|
+
import withNodeId from '../node-id';
|
|
10
|
+
import { withSocketIO } from '../socket';
|
|
11
|
+
import { focusEditor } from '../extension/core';
|
|
12
|
+
import InsertElementDialog from '../extension/commons/insert-element-dialog';
|
|
13
|
+
import { EditorContainer, EditorContent } from '../layout';
|
|
14
|
+
import EditableArticle from './editable-article';
|
|
15
|
+
import { ColorProvider } from '../hooks/use-color-context';
|
|
16
|
+
import ReadOnlyArticle from '../views/readonly-article';
|
|
17
|
+
import { isMobile } from '../../utils';
|
|
18
|
+
import { EventBus } from '../../basic-sdk';
|
|
19
|
+
import { EXTERNAL_EVENT } from '../../constants';
|
|
20
|
+
const WikiEditor = forwardRef((_ref, ref) => {
|
|
21
|
+
let {
|
|
22
|
+
editor: propsEditor,
|
|
23
|
+
document,
|
|
24
|
+
isReloading,
|
|
25
|
+
isWikiReadOnly,
|
|
26
|
+
topSlot
|
|
27
|
+
} = _ref;
|
|
28
|
+
const validEditor = propsEditor || useMemo(() => {
|
|
29
|
+
const defaultEditor = createDefaultEditor();
|
|
30
|
+
const editorConfig = context.getEditorConfig();
|
|
31
|
+
const newEditor = withNodeId(withSocketIO(defaultEditor, {
|
|
32
|
+
document,
|
|
33
|
+
config: editorConfig
|
|
34
|
+
}));
|
|
35
|
+
const {
|
|
36
|
+
cursors
|
|
37
|
+
} = document;
|
|
38
|
+
newEditor.cursors = cursors || {};
|
|
39
|
+
newEditor.width = PAGE_EDIT_AREA_WIDTH; // default width
|
|
40
|
+
return newEditor;
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
+
}, []);
|
|
44
|
+
const [slateValue, setSlateValue] = useState(document.children);
|
|
45
|
+
|
|
46
|
+
// Fix: The editor's children are not updated when the document is updated in revision
|
|
47
|
+
// In revision mode, the document is updated, but the editor's children are not updated,as onValueChange override the new document.children. This unexpected action cause the editor to display the old content
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
setSlateValue(document.children);
|
|
50
|
+
}, [document.children]);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
validEditor.readonly = false;
|
|
53
|
+
return () => {
|
|
54
|
+
validEditor.selection = null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
58
|
+
}, []);
|
|
59
|
+
// useMount: init socket connection
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (propsEditor) return;
|
|
62
|
+
validEditor.openConnection();
|
|
63
|
+
return () => {
|
|
64
|
+
validEditor.closeConnection();
|
|
65
|
+
};
|
|
66
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
// useMount: focus editor
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const timer = setTimeout(() => {
|
|
72
|
+
const [firstNode] = validEditor.children;
|
|
73
|
+
if (firstNode) {
|
|
74
|
+
const [firstNodeFirstChild] = firstNode.children;
|
|
75
|
+
if (firstNodeFirstChild) {
|
|
76
|
+
const endOfFirstNode = Editor.end(validEditor, [0, 0]);
|
|
77
|
+
const range = {
|
|
78
|
+
anchor: endOfFirstNode,
|
|
79
|
+
focus: endOfFirstNode
|
|
80
|
+
};
|
|
81
|
+
focusEditor(validEditor, range);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}, 300);
|
|
85
|
+
return () => {
|
|
86
|
+
clearTimeout(timer);
|
|
87
|
+
};
|
|
88
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
|
+
}, []);
|
|
90
|
+
const onRefreshDocument = useCallback(() => {
|
|
91
|
+
window.location.reload();
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
// useMount: refresh document
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const eventBus = EventBus.getInstance();
|
|
97
|
+
eventBus.subscribe(EXTERNAL_EVENT.REFRESH_DOCUMENT, onRefreshDocument);
|
|
98
|
+
}, [onRefreshDocument]);
|
|
99
|
+
|
|
100
|
+
// The parent component can call the method of this component through ref
|
|
101
|
+
useImperativeHandle(ref, () => ({
|
|
102
|
+
setSlateValue: document => {
|
|
103
|
+
// Force update of editor's child elements
|
|
104
|
+
validEditor.children = document.children;
|
|
105
|
+
setSlateValue([...document.children]);
|
|
106
|
+
},
|
|
107
|
+
updateDocumentVersion: document => {
|
|
108
|
+
validEditor.updateDocumentVersion(document);
|
|
109
|
+
},
|
|
110
|
+
// get value
|
|
111
|
+
getSlateValue: () => {
|
|
112
|
+
return deepCopy(_objectSpread(_objectSpread({}, document), {}, {
|
|
113
|
+
children: slateValue
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
118
|
+
}), [document, validEditor, slateValue]);
|
|
119
|
+
const onValueChange = value => {
|
|
120
|
+
const eventBus = EventBus.getInstance();
|
|
121
|
+
eventBus.dispatch(INTERNAL_EVENT.UPDATE_SEARCH_REPLACE_HIGHLIGHT, value);
|
|
122
|
+
setSlateValue(value);
|
|
123
|
+
};
|
|
124
|
+
if (isReloading) {
|
|
125
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
126
|
+
className: "h-100 w-100 d-flex align-items-center justify-content-center"
|
|
127
|
+
}, /*#__PURE__*/React.createElement(CommonLoading, null));
|
|
128
|
+
}
|
|
129
|
+
if (isMobile || isWikiReadOnly) {
|
|
130
|
+
return /*#__PURE__*/React.createElement(EditorContainer, {
|
|
131
|
+
editor: validEditor,
|
|
132
|
+
readonly: true
|
|
133
|
+
}, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement(EditorContent, {
|
|
134
|
+
docValue: slateValue,
|
|
135
|
+
readonly: true,
|
|
136
|
+
showOutline: false,
|
|
137
|
+
editor: validEditor,
|
|
138
|
+
showComment: false
|
|
139
|
+
}, topSlot, /*#__PURE__*/React.createElement(ReadOnlyArticle, {
|
|
140
|
+
editor: validEditor,
|
|
141
|
+
slateValue: slateValue,
|
|
142
|
+
showComment: false
|
|
143
|
+
}))));
|
|
144
|
+
}
|
|
145
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EditorContainer, {
|
|
146
|
+
editor: validEditor
|
|
147
|
+
}, /*#__PURE__*/React.createElement(ColorProvider, null, /*#__PURE__*/React.createElement(EditorContent, {
|
|
148
|
+
docValue: slateValue,
|
|
149
|
+
showOutline: false,
|
|
150
|
+
editor: validEditor,
|
|
151
|
+
showComment: false
|
|
152
|
+
}, topSlot, /*#__PURE__*/React.createElement(EditableArticle, {
|
|
153
|
+
editor: validEditor,
|
|
154
|
+
slateValue: slateValue,
|
|
155
|
+
updateSlateValue: onValueChange,
|
|
156
|
+
showComment: false
|
|
157
|
+
})))), /*#__PURE__*/React.createElement(InsertElementDialog, {
|
|
158
|
+
editor: validEditor
|
|
159
|
+
}));
|
|
160
|
+
});
|
|
161
|
+
export default WikiEditor;
|
|
@@ -81,7 +81,7 @@ class HeaderMenu extends React.Component {
|
|
|
81
81
|
this.menu = ref;
|
|
82
82
|
});
|
|
83
83
|
_defineProperty(this, "getToolTip", type => {
|
|
84
|
-
return isMac ? MAC_HOTKEYS[type] : WIN_HOTKEYS[type];
|
|
84
|
+
return isMac() ? MAC_HOTKEYS[type] : WIN_HOTKEYS[type];
|
|
85
85
|
});
|
|
86
86
|
this.state = {
|
|
87
87
|
isShowHeaderPopover: false
|
|
@@ -42,15 +42,15 @@ const LinkMenu = _ref => {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
45
|
-
const
|
|
46
|
-
const printTexts = isMac ? ['⌘', 'k'] : ['Ctrl', 'k'];
|
|
45
|
+
const linkShortCutTexts = useMemo(() => {
|
|
46
|
+
const printTexts = isMac() ? ['⌘', 'k'] : ['Ctrl', 'k'];
|
|
47
47
|
return printTexts;
|
|
48
48
|
}, []);
|
|
49
49
|
return /*#__PURE__*/React.createElement(DropdownMenuItem, {
|
|
50
50
|
disabled: disabled,
|
|
51
51
|
menuConfig: menuConfig,
|
|
52
52
|
onClick: openLinkDialog,
|
|
53
|
-
shortcut:
|
|
53
|
+
shortcut: linkShortCutTexts
|
|
54
54
|
});
|
|
55
55
|
};
|
|
56
56
|
export default LinkMenu;
|
|
@@ -73,6 +73,8 @@ const withLink = editor => {
|
|
|
73
73
|
} = newEditor;
|
|
74
74
|
const isCollapsed = Range.isCollapsed(selection);
|
|
75
75
|
if (isHotkey('mod+k', e) && isCollapsed) {
|
|
76
|
+
// Prevent edge behavior
|
|
77
|
+
e.preventDefault();
|
|
76
78
|
const eventBus = EventBus.getInstance();
|
|
77
79
|
eventBus.dispatch(INTERNAL_EVENT.INSERT_ELEMENT, {
|
|
78
80
|
type: ELEMENT_TYPE.LINK,
|
|
@@ -2,7 +2,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
|
2
2
|
import isHotkey from 'is-hotkey';
|
|
3
3
|
import { Editor, Transforms, Path, Element } from '@seafile/slate';
|
|
4
4
|
import { ReactEditor } from '@seafile/slate-react';
|
|
5
|
-
import { getNodeType, getParentNode, getSelectedNodeByType, isLastNode, generateEmptyElement, focusEditor } from '../../core';
|
|
5
|
+
import { getNodeType, getParentNode, getSelectedNodeByType, isLastNode, generateEmptyElement, focusEditor, getAboveBlockNode } from '../../core';
|
|
6
6
|
import { ELEMENT_TYPE, KEYBOARD, PARAGRAPH, CLIPBOARD_FORMAT_KEY, CHECK_LIST_ITEM, ORDERED_LIST, UNORDERED_LIST, TABLE_ROW, TABLE, TABLE_CELL } from '../../constants';
|
|
7
7
|
import { TABLE_MAX_ROWS, EMPTY_SELECTED_RANGE, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, TABLE_CELL_MIN_WIDTH, TABLE_ROW_MIN_HEIGHT } from './constants';
|
|
8
8
|
import ObjectUtils from '../../../utils/object-utils';
|
|
@@ -58,6 +58,13 @@ const withTable = editor => {
|
|
|
58
58
|
if (isHotkey('tab', event)) {
|
|
59
59
|
event.preventDefault();
|
|
60
60
|
}
|
|
61
|
+
if (isHotkey('shift+enter', event)) {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
const [, tablePath] = getAboveBlockNode(newEditor);
|
|
64
|
+
const focusPath = [tablePath[0] + 1];
|
|
65
|
+
const focusPoint = Editor.start(newEditor, focusPath);
|
|
66
|
+
focusEditor(newEditor, focusPoint);
|
|
67
|
+
}
|
|
61
68
|
};
|
|
62
69
|
newEditor.insertBreak = () => {
|
|
63
70
|
const selectedNode = getSelectedNodeByType(newEditor, ELEMENT_TYPE.TABLE);
|
|
@@ -58,8 +58,7 @@ export const getHeaderHeight = editor => {
|
|
|
58
58
|
} = editor;
|
|
59
59
|
switch (editorType) {
|
|
60
60
|
case WIKI_EDITOR:
|
|
61
|
-
|
|
62
|
-
return 49;
|
|
61
|
+
return 113.2;
|
|
63
62
|
default:
|
|
64
63
|
// sdoc-editor-page-header height = 56
|
|
65
64
|
// sdoc-editor-toolbar height = 37
|
|
@@ -56,8 +56,8 @@ const MoreOperations = _ref => {
|
|
|
56
56
|
event.nativeEvent.stopImmediatePropagation();
|
|
57
57
|
window.location.href = historyURL;
|
|
58
58
|
}, [docPerm, historyURL, isSdocRevision]);
|
|
59
|
-
const
|
|
60
|
-
const printTexts = isMac ? ['⌘', 'P'] : ['Ctrl', 'P'];
|
|
59
|
+
const printShortcutTexts = useMemo(() => {
|
|
60
|
+
const printTexts = isMac() ? ['⌘', 'P'] : ['Ctrl', 'P'];
|
|
61
61
|
return printTexts;
|
|
62
62
|
}, []);
|
|
63
63
|
return /*#__PURE__*/React.createElement(Dropdown, {
|
|
@@ -78,7 +78,7 @@ const MoreOperations = _ref => {
|
|
|
78
78
|
}, /*#__PURE__*/React.createElement("div", {
|
|
79
79
|
className: "sdoc-dropdown-print-container"
|
|
80
80
|
}, /*#__PURE__*/React.createElement("div", null, t('Print')), /*#__PURE__*/React.createElement(MenuShortcutPrompt, {
|
|
81
|
-
shortcuts:
|
|
81
|
+
shortcuts: printShortcutTexts
|
|
82
82
|
}))), isPro && isFreezed && /*#__PURE__*/React.createElement(DropdownItem, {
|
|
83
83
|
className: "sdoc-dropdown-menu-item",
|
|
84
84
|
onClick: unFreeze
|
|
@@ -2,21 +2,25 @@ import React, { useEffect, useMemo } from 'react';
|
|
|
2
2
|
import { withTranslation } from 'react-i18next';
|
|
3
3
|
import context from '../context';
|
|
4
4
|
import ErrorBoundary from './error-boundary';
|
|
5
|
-
import { SDocEditor } from '../basic-sdk';
|
|
6
5
|
import { PAGE_EDIT_AREA_WIDTH, WIKI_EDITOR } from '../basic-sdk/constants';
|
|
7
6
|
import { createWikiEditor } from '../basic-sdk/extension';
|
|
8
7
|
import withNodeId from '../basic-sdk/node-id';
|
|
9
8
|
import { withSocketIO } from '../basic-sdk/socket';
|
|
9
|
+
import { TITLE } from '../basic-sdk/extension/constants';
|
|
10
|
+
import WikiEditor from '../basic-sdk/editor/wiki-editor';
|
|
10
11
|
import '../assets/css/simple-viewer.css';
|
|
11
12
|
const SdocWikiViewer = _ref => {
|
|
12
13
|
let {
|
|
13
14
|
document,
|
|
14
|
-
showOutline,
|
|
15
|
-
scrollRef,
|
|
16
15
|
docUuid,
|
|
17
|
-
isWikiReadOnly
|
|
16
|
+
isWikiReadOnly,
|
|
17
|
+
topSlot
|
|
18
18
|
} = _ref;
|
|
19
19
|
context.initApi();
|
|
20
|
+
|
|
21
|
+
// Wiki editor need filter initialized title node
|
|
22
|
+
const [firstNode, ...restNodes] = document.children;
|
|
23
|
+
if (firstNode.type === TITLE) document.children = restNodes;
|
|
20
24
|
const validEditor = useMemo(() => {
|
|
21
25
|
const defaultEditor = createWikiEditor();
|
|
22
26
|
// getEditorConfig cashe the config, so we need to update the uuid,for wiki editor
|
|
@@ -42,15 +46,12 @@ const SdocWikiViewer = _ref => {
|
|
|
42
46
|
validEditor.closeConnection();
|
|
43
47
|
};
|
|
44
48
|
}, [validEditor]);
|
|
45
|
-
return /*#__PURE__*/React.createElement(ErrorBoundary, null, /*#__PURE__*/React.createElement(
|
|
46
|
-
showComment: false,
|
|
49
|
+
return /*#__PURE__*/React.createElement(ErrorBoundary, null, /*#__PURE__*/React.createElement(WikiEditor, {
|
|
47
50
|
document: document,
|
|
48
|
-
showOutline: showOutline,
|
|
49
|
-
scrollRef: scrollRef,
|
|
50
51
|
docUuid: docUuid,
|
|
51
|
-
isShowHeaderToolbar: false,
|
|
52
52
|
editor: validEditor,
|
|
53
|
-
isWikiReadOnly: isWikiReadOnly
|
|
53
|
+
isWikiReadOnly: isWikiReadOnly,
|
|
54
|
+
topSlot: topSlot
|
|
54
55
|
}));
|
|
55
56
|
};
|
|
56
57
|
export default withTranslation('sdoc-editor')(SdocWikiViewer);
|