@seafile/sdoc-editor 0.5.52 → 0.5.53
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/comment-article.js +1 -0
- package/dist/basic-sdk/extension/commons/Inline-bug-fix-wrapper/index.js +11 -0
- package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +4 -3
- package/dist/basic-sdk/extension/plugins/image/render-elem.js +2 -1
- package/dist/basic-sdk/extension/plugins/link/helpers.js +0 -10
- package/dist/basic-sdk/extension/plugins/link/plugin.js +15 -14
- package/dist/basic-sdk/extension/plugins/link/render-elem.js +2 -1
- package/dist/basic-sdk/extension/plugins/table/helpers.js +30 -0
- package/dist/basic-sdk/extension/plugins/table/menu/table-context-menu/index.js +23 -4
- package/dist/basic-sdk/extension/plugins/text-style/render-elem.js +8 -0
- package/dist/basic-sdk/utils/diff.js +4 -3
- package/dist/basic-sdk/views/readonly-article.js +1 -0
- package/package.json +3 -2
- package/public/locales/en/sdoc-editor.json +2 -1
- package/public/locales/zh_CN/sdoc-editor.json +2 -1
|
@@ -70,6 +70,7 @@ const CommentArticle = _ref => {
|
|
|
70
70
|
value: slateValue,
|
|
71
71
|
onChange: updateSlateValue
|
|
72
72
|
}, /*#__PURE__*/React.createElement(Editable, {
|
|
73
|
+
id: "sdoc-editor",
|
|
73
74
|
scrollSelectionIntoView: handleScrollIntoView,
|
|
74
75
|
cursors: cursors,
|
|
75
76
|
renderElement: props => RenderCommentEditorCustomRenderElement(_objectSpread(_objectSpread({}, props), {}, {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
const InlineBugFixer = () => {
|
|
3
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
4
|
+
contentEditable: false,
|
|
5
|
+
style: {
|
|
6
|
+
fontSize: 0
|
|
7
|
+
}
|
|
8
|
+
}, String.fromCodePoint(160) /* Non-breaking space */);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default InlineBugFixer;
|
|
@@ -20,7 +20,8 @@ const ImageHoverMenu = _ref => {
|
|
|
20
20
|
parentNodeEntry,
|
|
21
21
|
imageCaptionInputRef,
|
|
22
22
|
onHideImageHoverMenu,
|
|
23
|
-
t
|
|
23
|
+
t,
|
|
24
|
+
readonly
|
|
24
25
|
} = _ref;
|
|
25
26
|
const {
|
|
26
27
|
data,
|
|
@@ -152,7 +153,7 @@ const ImageHoverMenu = _ref => {
|
|
|
152
153
|
style: menuPosition
|
|
153
154
|
}, /*#__PURE__*/React.createElement("div", {
|
|
154
155
|
className: "hover-menu-container"
|
|
155
|
-
}, type !== TABLE && /*#__PURE__*/React.createElement("span", {
|
|
156
|
+
}, type !== TABLE && !readonly && /*#__PURE__*/React.createElement("span", {
|
|
156
157
|
className: "op-group-item"
|
|
157
158
|
}, /*#__PURE__*/React.createElement("span", {
|
|
158
159
|
role: "button",
|
|
@@ -166,7 +167,7 @@ const ImageHoverMenu = _ref => {
|
|
|
166
167
|
className: "mr-1"
|
|
167
168
|
}, t(type === IMAGE_BLOCK ? 'Block' : 'Inline')), /*#__PURE__*/React.createElement("i", {
|
|
168
169
|
className: "sdocfont sdoc-drop-down icon-font"
|
|
169
|
-
}))), /*#__PURE__*/React.createElement("span", {
|
|
170
|
+
}))), !readonly && /*#__PURE__*/React.createElement("span", {
|
|
170
171
|
className: "op-group-item"
|
|
171
172
|
}, type === IMAGE_BLOCK && /*#__PURE__*/React.createElement("span", {
|
|
172
173
|
role: "button",
|
|
@@ -254,12 +254,13 @@ const Image = _ref => {
|
|
|
254
254
|
onCompositionStart: e => {
|
|
255
255
|
e.stopPropagation();
|
|
256
256
|
}
|
|
257
|
-
}))), children),
|
|
257
|
+
}))), children), isShowImageHoverMenu && /*#__PURE__*/React.createElement(ImageHoverMenu, {
|
|
258
258
|
editor: editor,
|
|
259
259
|
menuPosition: menuPosition,
|
|
260
260
|
element: element,
|
|
261
261
|
parentNodeEntry: nodeEntry,
|
|
262
262
|
imageCaptionInputRef: imageCaptionInputRef,
|
|
263
|
+
readonly: readOnly,
|
|
263
264
|
onHideImageHoverMenu: () => {
|
|
264
265
|
setIsShowImageHoverMenu(false);
|
|
265
266
|
}
|
|
@@ -66,10 +66,6 @@ export const insertLink = function (editor, title, url) {
|
|
|
66
66
|
}
|
|
67
67
|
const p = generateEmptyElement(ELEMENT_TYPE.PARAGRAPH);
|
|
68
68
|
p.children[1] = linkNode;
|
|
69
|
-
p.children[2] = {
|
|
70
|
-
id: slugid.nice(),
|
|
71
|
-
text: ' '
|
|
72
|
-
};
|
|
73
69
|
Transforms.insertNodes(editor, p, {
|
|
74
70
|
at: [path[0] + 1]
|
|
75
71
|
});
|
|
@@ -85,12 +81,6 @@ export const insertLink = function (editor, title, url) {
|
|
|
85
81
|
if (isCollapsed) {
|
|
86
82
|
const linkNode = genLinkNode(url, title);
|
|
87
83
|
Transforms.insertNodes(editor, linkNode);
|
|
88
|
-
|
|
89
|
-
// Not being able to use insertText directly causes the added Spaces to be added to the linked text, as in the issue above, replaced by insertFragment
|
|
90
|
-
editor.insertFragment([{
|
|
91
|
-
id: slugid.nice(),
|
|
92
|
-
text: ' '
|
|
93
|
-
}]);
|
|
94
84
|
} else {
|
|
95
85
|
const selectedText = Editor.string(editor, selection); // Selected text
|
|
96
86
|
if (selectedText !== title) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Transforms, Node, Editor, Range } from '@seafile/slate';
|
|
2
|
-
import slugid from 'slugid';
|
|
1
|
+
import { Transforms, Node, Editor, Range, Element } from '@seafile/slate';
|
|
3
2
|
import isUrl from 'is-url';
|
|
4
3
|
import context from '../../../../context';
|
|
5
4
|
import { insertSdocFileLink } from '../sdoc-link/helpers';
|
|
@@ -12,7 +11,6 @@ const withLink = editor => {
|
|
|
12
11
|
normalizeNode,
|
|
13
12
|
isInline,
|
|
14
13
|
insertData,
|
|
15
|
-
insertText,
|
|
16
14
|
insertFragment
|
|
17
15
|
} = editor;
|
|
18
16
|
const newEditor = editor;
|
|
@@ -27,17 +25,6 @@ const withLink = editor => {
|
|
|
27
25
|
}
|
|
28
26
|
return isInline(elem);
|
|
29
27
|
};
|
|
30
|
-
newEditor.insertText = text => {
|
|
31
|
-
const path = Editor.path(editor, editor.selection);
|
|
32
|
-
if (Range.isCollapsed(editor.selection) && getSelectedNodeByType(editor, LINK) && Editor.isEnd(editor, editor.selection.focus, path)) {
|
|
33
|
-
editor.insertFragment([{
|
|
34
|
-
id: slugid.nice(),
|
|
35
|
-
text: text
|
|
36
|
-
}]);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
return insertText(text);
|
|
40
|
-
};
|
|
41
28
|
newEditor.insertData = data => {
|
|
42
29
|
// Paste link content
|
|
43
30
|
const text = data.getData('text/plain');
|
|
@@ -95,6 +82,20 @@ const withLink = editor => {
|
|
|
95
82
|
}
|
|
96
83
|
return normalizeNode([node, path]);
|
|
97
84
|
};
|
|
85
|
+
editor.onCompositionStart = e => {
|
|
86
|
+
const {
|
|
87
|
+
selection
|
|
88
|
+
} = editor;
|
|
89
|
+
if (Range.isCollapsed(selection)) {
|
|
90
|
+
const [LinkNodeEntry] = Editor.nodes(editor, {
|
|
91
|
+
match: n => Element.isElement && n.type === LINK
|
|
92
|
+
});
|
|
93
|
+
if (LinkNodeEntry) {
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
98
99
|
return newEditor;
|
|
99
100
|
};
|
|
100
101
|
export default withLink;
|
|
@@ -6,6 +6,7 @@ import LinkHover from './hover';
|
|
|
6
6
|
import EventBus from '../../../utils/event-bus';
|
|
7
7
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
8
8
|
import { ELEMENT_TYPE } from '../../constants';
|
|
9
|
+
import InlineBugFixer from '../../commons/Inline-bug-fix-wrapper';
|
|
9
10
|
class LinkHoverMenuComponent extends React.Component {
|
|
10
11
|
constructor(props) {
|
|
11
12
|
super(props);
|
|
@@ -95,7 +96,7 @@ class LinkHoverMenuComponent extends React.Component {
|
|
|
95
96
|
}), /*#__PURE__*/React.createElement("span", {
|
|
96
97
|
className: "virtual-link",
|
|
97
98
|
title: element.title
|
|
98
|
-
}, children)), isShowLinkMenu && (this.props.readonly || Range.isCollapsed(editor.selection)) && /*#__PURE__*/React.createElement(LinkHover, {
|
|
99
|
+
}, /*#__PURE__*/React.createElement(InlineBugFixer, null), children, /*#__PURE__*/React.createElement(InlineBugFixer, null))), isShowLinkMenu && (this.props.readonly || Range.isCollapsed(editor.selection)) && /*#__PURE__*/React.createElement(LinkHover, {
|
|
99
100
|
editor: editor,
|
|
100
101
|
menuPosition: menuPosition,
|
|
101
102
|
element: element,
|
|
@@ -1878,4 +1878,34 @@ export const getTableColumnSelectedRange = (table, columnIndex) => {
|
|
|
1878
1878
|
minColIndex,
|
|
1879
1879
|
maxColIndex
|
|
1880
1880
|
};
|
|
1881
|
+
};
|
|
1882
|
+
export const isTableWidthFitScreen = editor => {
|
|
1883
|
+
const {
|
|
1884
|
+
table
|
|
1885
|
+
} = getSelectedInfo(editor);
|
|
1886
|
+
const tableNode = ReactEditor.toDOMNode(editor, table);
|
|
1887
|
+
if (!tableNode) return;
|
|
1888
|
+
const tableDom = tableNode.querySelector('.sdoc-table-scroll-wrapper');
|
|
1889
|
+
const {
|
|
1890
|
+
width: tableWidth
|
|
1891
|
+
} = tableDom.getBoundingClientRect();
|
|
1892
|
+
const sdocWidth = editor.width;
|
|
1893
|
+
if (tableWidth >= sdocWidth) return true;
|
|
1894
|
+
return false;
|
|
1895
|
+
};
|
|
1896
|
+
export const fitTableColumnToScreen = editor => {
|
|
1897
|
+
const {
|
|
1898
|
+
table,
|
|
1899
|
+
tablePath
|
|
1900
|
+
} = getSelectedInfo(editor);
|
|
1901
|
+
const colCount = table.columns.length;
|
|
1902
|
+
const columnWidth = Math.max(TABLE_CELL_MIN_WIDTH, parseInt(editor.width / colCount));
|
|
1903
|
+
const columns = table.columns.map(column => _objectSpread(_objectSpread({}, column), {}, {
|
|
1904
|
+
width: columnWidth
|
|
1905
|
+
}));
|
|
1906
|
+
Transforms.setNodes(editor, {
|
|
1907
|
+
columns
|
|
1908
|
+
}, {
|
|
1909
|
+
at: tablePath
|
|
1910
|
+
});
|
|
1881
1911
|
};
|
|
@@ -6,7 +6,7 @@ import { ElementPopover } from '../../../../commons';
|
|
|
6
6
|
import { ELEMENT_TYPE } from '../../../../constants';
|
|
7
7
|
import { getSelectedNodeByType } from '../../../../core';
|
|
8
8
|
import { TABLE_MAX_COLUMNS, TABLE_MAX_ROWS, TABLE_ELEMENT, TABLE_ELEMENT_POSITION, EMPTY_SELECTED_RANGE } from '../../constants';
|
|
9
|
-
import { insertTableElement, removeTableElement, combineCells } from '../../helpers';
|
|
9
|
+
import { insertTableElement, removeTableElement, combineCells, isTableWidthFitScreen, fitTableColumnToScreen } from '../../helpers';
|
|
10
10
|
import InsertTableElement from './insert-table-element';
|
|
11
11
|
import EventBus from '../../../../../utils/event-bus';
|
|
12
12
|
import { INTERNAL_EVENT } from '../../../../../constants';
|
|
@@ -66,7 +66,8 @@ class TableContextMenu extends React.Component {
|
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
68
|
this.state = {
|
|
69
|
-
contextStyle: {}
|
|
69
|
+
contextStyle: {},
|
|
70
|
+
isDisableFitTableWidthToScreen: false
|
|
70
71
|
};
|
|
71
72
|
this.position = null;
|
|
72
73
|
this.eventBus = EventBus.getInstance();
|
|
@@ -97,7 +98,8 @@ class TableContextMenu extends React.Component {
|
|
|
97
98
|
}
|
|
98
99
|
render() {
|
|
99
100
|
const {
|
|
100
|
-
contextStyle
|
|
101
|
+
contextStyle,
|
|
102
|
+
isDisableFitTableWidthToScreen
|
|
101
103
|
} = this.state;
|
|
102
104
|
const {
|
|
103
105
|
editor,
|
|
@@ -118,6 +120,17 @@ class TableContextMenu extends React.Component {
|
|
|
118
120
|
const enableCombineCell = !ObjectUtils.isSameObject(tableSelectedRange, EMPTY_SELECTED_RANGE);
|
|
119
121
|
const enableSplitCell = !enableCombineCell;
|
|
120
122
|
const isMergedCell = this.isMergedCell();
|
|
123
|
+
|
|
124
|
+
// Check if the table width is fit to screen
|
|
125
|
+
// Use queueMicrotask to resolve the issue that the table cell combined or split, the table width is not updated immediately
|
|
126
|
+
queueMicrotask(() => {
|
|
127
|
+
const isDisable = isTableWidthFitScreen(editor);
|
|
128
|
+
if (isDisableFitTableWidthToScreen !== isDisable) {
|
|
129
|
+
this.setState({
|
|
130
|
+
isDisableFitTableWidthToScreen: isTableWidthFitScreen(editor)
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
121
134
|
return /*#__PURE__*/React.createElement(ElementPopover, {
|
|
122
135
|
className: "sdoc-context-menu"
|
|
123
136
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -160,7 +173,13 @@ class TableContextMenu extends React.Component {
|
|
|
160
173
|
className: "dropdown-item",
|
|
161
174
|
disabled: !isMergedCell || !enableSplitCell,
|
|
162
175
|
onMouseDown: this.toggleSplitCellSettingDialog
|
|
163
|
-
}, t('Split_cell'))
|
|
176
|
+
}, t('Split_cell')), /*#__PURE__*/React.createElement("div", {
|
|
177
|
+
className: 'seafile-divider dropdown-divider'
|
|
178
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
179
|
+
className: "dropdown-item",
|
|
180
|
+
disabled: isDisableFitTableWidthToScreen,
|
|
181
|
+
onMouseDown: () => fitTableColumnToScreen(editor)
|
|
182
|
+
}, t('Fit_table_to_page_width'))));
|
|
164
183
|
}
|
|
165
184
|
}
|
|
166
185
|
export default withTranslation('sdoc-editor')(TableContextMenu);
|
|
@@ -16,6 +16,14 @@ const renderText = (props, editor) => {
|
|
|
16
16
|
rest = _objectWithoutProperties(leaf, _excluded);
|
|
17
17
|
let markedChildren = React.cloneElement(children);
|
|
18
18
|
let style = {};
|
|
19
|
+
// The following is a workaround for a Chromium bug where,
|
|
20
|
+
// if you have an inline at the end of a block,
|
|
21
|
+
// clicking the end of a block puts the cursor inside the inline
|
|
22
|
+
// instead of inside the final {text: ''} node
|
|
23
|
+
// https://github.com/ianstormtaylor/slate/issues/4704#issuecomment-1006696364
|
|
24
|
+
if (!text.length) {
|
|
25
|
+
style['paddingLeft'] = '0.1px';
|
|
26
|
+
}
|
|
19
27
|
if (leaf.isCaret) {
|
|
20
28
|
style['position'] = 'relative';
|
|
21
29
|
style['display'] = 'inline-block';
|
|
@@ -19,12 +19,13 @@ const generatorDiffTextElement = function (textElement, diffType) {
|
|
|
19
19
|
};
|
|
20
20
|
export const getTopLevelChanges = changes => {
|
|
21
21
|
const topLevelChanges = [];
|
|
22
|
+
const articleEl = document.getElementById('sdoc-editor');
|
|
22
23
|
changes.forEach(item => {
|
|
23
24
|
let dom = document.querySelectorAll("[data-id=\"".concat(item, "\"]"))[0];
|
|
24
25
|
if (!dom) return [];
|
|
25
|
-
while (((_dom = dom) === null || _dom === void 0 ? void 0 : (_dom$dataset = _dom.dataset) === null || _dom$dataset === void 0 ? void 0 : _dom$dataset.root) !== 'true') {
|
|
26
|
-
var _dom, _dom$dataset, _dom2;
|
|
27
|
-
if (!((
|
|
26
|
+
while (((_dom = dom) === null || _dom === void 0 ? void 0 : (_dom$dataset = _dom.dataset) === null || _dom$dataset === void 0 ? void 0 : _dom$dataset.root) !== 'true' || ((_dom2 = dom) === null || _dom2 === void 0 ? void 0 : _dom2.parentNode) !== articleEl) {
|
|
27
|
+
var _dom, _dom$dataset, _dom2, _dom3;
|
|
28
|
+
if (!((_dom3 = dom) === null || _dom3 === void 0 ? void 0 : _dom3.parentNode) || dom instanceof Document) break;
|
|
28
29
|
const parentNode = dom.parentNode;
|
|
29
30
|
if (parentNode instanceof Document) {
|
|
30
31
|
break;
|
|
@@ -18,6 +18,7 @@ const ReadOnlyArticle = _ref => {
|
|
|
18
18
|
}, /*#__PURE__*/React.createElement(ArticleContainer, {
|
|
19
19
|
editor: editor
|
|
20
20
|
}, /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(SetNodeToDecorations, null), /*#__PURE__*/React.createElement(Editable, {
|
|
21
|
+
id: "sdoc-editor",
|
|
21
22
|
readOnly: true,
|
|
22
23
|
placeholder: "",
|
|
23
24
|
renderElement: renderElement,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seafile/sdoc-editor",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.53",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "This is a sdoc editor",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"scripts": {
|
|
48
48
|
"clean": "rm -rf dist && mkdir dist",
|
|
49
49
|
"start.bak": "node scripts/start.js",
|
|
50
|
-
"start": "
|
|
50
|
+
"start": "cross-env NODE_ENV=development node dev-server.js",
|
|
51
51
|
"build": "node scripts/build.js",
|
|
52
52
|
"pub:dist": "export BABEL_ENV=production && ./node_modules/.bin/babel src --out-dir dist --copy-files",
|
|
53
53
|
"push-translate": "tx push -s",
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"case-sensitive-paths-webpack-plugin": "2.2.0",
|
|
93
93
|
"clean-webpack-plugin": "4.0.0",
|
|
94
94
|
"core-js": "2.6.12",
|
|
95
|
+
"cross-env": "^7.0.3",
|
|
95
96
|
"css-loader": "^6.5.1",
|
|
96
97
|
"css-minimizer-webpack-plugin": "5.0.1",
|
|
97
98
|
"dotenv": "6.2.0",
|
|
@@ -456,5 +456,6 @@
|
|
|
456
456
|
"Print": "Print",
|
|
457
457
|
"Enter_more_character_start_search": "Enter more characters to start search",
|
|
458
458
|
"Create_file_name_sdoc": "Create {{file_name_sdoc}}",
|
|
459
|
-
"Source_document_changed_tip": "Original document has concurrent modifications. Do you like to merge these modifications to the revision?"
|
|
459
|
+
"Source_document_changed_tip": "Original document has concurrent modifications. Do you like to merge these modifications to the revision?",
|
|
460
|
+
"Fit_table_to_page_width": "Fit table to page width"
|
|
460
461
|
}
|
|
@@ -456,5 +456,6 @@
|
|
|
456
456
|
"Print": "打印",
|
|
457
457
|
"Enter_more_character_start_search": "输入更多字符开始搜索",
|
|
458
458
|
"Create_file_name_sdoc": "新建 {{file_name_sdoc}}",
|
|
459
|
-
"Source_document_changed_tip": "源文档有并发的改动。你需要合并这些改动到修订稿吗?"
|
|
459
|
+
"Source_document_changed_tip": "源文档有并发的改动。你需要合并这些改动到修订稿吗?",
|
|
460
|
+
"Fit_table_to_page_width": "自动适应页面宽度"
|
|
460
461
|
}
|