@seafile/sdoc-editor 1.0.46 → 1.0.48
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/extension/plugins/image/helpers.js +27 -7
- package/dist/basic-sdk/extension/plugins/image/plugin.js +44 -20
- package/dist/basic-sdk/extension/plugins/image/render-elem.js +6 -6
- package/dist/basic-sdk/extension/plugins/seatable-tables/helpers.js +2 -0
- package/dist/basic-sdk/extension/plugins/table/helpers.js +24 -2
- package/dist/basic-sdk/extension/plugins/table/menu/table-context-menu/index.js +2 -2
- package/dist/pages/sdoc-wiki-editor.js +0 -1
- package/package.json +1 -1
|
@@ -5,10 +5,10 @@ import { ReactEditor } from '@seafile/slate-react';
|
|
|
5
5
|
import slugId from 'slugid';
|
|
6
6
|
import context from '../../../../context';
|
|
7
7
|
import EventBus from '../../../utils/event-bus';
|
|
8
|
-
import { generateEmptyElement, getNodeType, isTextNode, getParentNode, focusEditor } from '../../core';
|
|
8
|
+
import { generateEmptyElement, getNodeType, isTextNode, getParentNode, focusEditor, getAboveBlockNode } from '../../core';
|
|
9
9
|
import { isList } from '../../toolbar/side-toolbar/helpers';
|
|
10
10
|
import { COMMENT_EDITOR, INTERNAL_EVENT } from '../../../constants';
|
|
11
|
-
import { CODE_BLOCK, ELEMENT_TYPE, IMAGE, IMAGE_BLOCK, INSERT_POSITION } from '../../constants';
|
|
11
|
+
import { CODE_BLOCK, ELEMENT_TYPE, IMAGE, IMAGE_BLOCK, INSERT_POSITION, PARAGRAPH, SUBTITLE, TITLE } from '../../constants';
|
|
12
12
|
import base64ToUnit8Array from '../../../../utils/base64-to-unit8array';
|
|
13
13
|
export const isInsertImageMenuDisabled = (editor, readonly) => {
|
|
14
14
|
if (readonly) return true;
|
|
@@ -26,6 +26,8 @@ export const isInsertImageMenuDisabled = (editor, readonly) => {
|
|
|
26
26
|
}
|
|
27
27
|
if (type === CODE_BLOCK) return true;
|
|
28
28
|
if (type.startsWith('header')) return true;
|
|
29
|
+
if (type === TITLE) return true;
|
|
30
|
+
if (type === SUBTITLE) return true;
|
|
29
31
|
if (Editor.isVoid(editor, n)) return true;
|
|
30
32
|
return false;
|
|
31
33
|
},
|
|
@@ -55,6 +57,22 @@ export const insertImage = function (editor, srcList, selection) {
|
|
|
55
57
|
});
|
|
56
58
|
const validSelection = selection || editor.selection;
|
|
57
59
|
let path = Editor.path(editor, validSelection);
|
|
60
|
+
const aboveNodeEntry = getAboveBlockNode(editor);
|
|
61
|
+
const isEmptyParagraph = aboveNodeEntry[0].type === PARAGRAPH && Node.string(aboveNodeEntry[0]).length === 0;
|
|
62
|
+
if (imageNodes.length === 1 && isEmptyParagraph) {
|
|
63
|
+
const imageNode = imageNodes[0];
|
|
64
|
+
Transforms.insertNodes(editor, imageNode, {
|
|
65
|
+
at: validSelection
|
|
66
|
+
});
|
|
67
|
+
Transforms.setNodes(editor, {
|
|
68
|
+
type: IMAGE_BLOCK
|
|
69
|
+
}, {
|
|
70
|
+
at: validSelection
|
|
71
|
+
});
|
|
72
|
+
const imageEndSelection = Path.next(Path.next(path));
|
|
73
|
+
focusEditor(editor, imageEndSelection);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
58
76
|
if (position === INSERT_POSITION.AFTER) {
|
|
59
77
|
if (isList(editor, path)) {
|
|
60
78
|
const targetPath = path.slice(0, -2);
|
|
@@ -147,11 +165,13 @@ export const resetCursor = editor => {
|
|
|
147
165
|
Transforms.select(editor, targetPath);
|
|
148
166
|
});
|
|
149
167
|
};
|
|
150
|
-
export const
|
|
151
|
-
if (data.length !== 1) return
|
|
152
|
-
if (Node.string(data[0]).length !== 0) return
|
|
153
|
-
|
|
154
|
-
|
|
168
|
+
export const getSingleImageFromFragment = data => {
|
|
169
|
+
if (data.length !== 1) return null;
|
|
170
|
+
if (Node.string(data[0]).length !== 0) return null;
|
|
171
|
+
const children = data[0].children;
|
|
172
|
+
const images = children.filter(item => (item === null || item === void 0 ? void 0 : item.type) === IMAGE);
|
|
173
|
+
if (images.length !== 1) return null;
|
|
174
|
+
return images[0];
|
|
155
175
|
};
|
|
156
176
|
export const insertImageFiles = (files, editor, targetPath) => {
|
|
157
177
|
context.uploadLocalImage(files).then(fileUrl => {
|
|
@@ -2,11 +2,11 @@ import { Transforms, Path, Editor, Element, Range } from '@seafile/slate';
|
|
|
2
2
|
import toaster from '../../../../components/toast';
|
|
3
3
|
import context from '../../../../context';
|
|
4
4
|
import EventBus from '../../../utils/event-bus';
|
|
5
|
-
import { insertImage, hasSdocImages, getImageData, queryCopyMoveProgressView, resetCursor,
|
|
6
|
-
import { focusEditor, generateEmptyElement, isBlockAboveEmpty } from '../../core';
|
|
5
|
+
import { insertImage, hasSdocImages, getImageData, queryCopyMoveProgressView, resetCursor, isInsertImageMenuDisabled, getSingleImageFromFragment } from './helpers';
|
|
6
|
+
import { focusEditor, generateEmptyElement, getLastChildPath, getSelectedNodeEntryByType, isBlockAboveEmpty, isSelectionAtBlockStart } from '../../core';
|
|
7
7
|
import { getErrorMsg } from '../../../../utils';
|
|
8
8
|
import { getSlateFragmentAttribute } from '../../../utils/document-utils';
|
|
9
|
-
import { INSERT_POSITION, CLIPBOARD_FORMAT_KEY, CLIPBOARD_ORIGIN_SDOC_KEY, IMAGE, IMAGE_BLOCK, PARAGRAPH } from '../../constants';
|
|
9
|
+
import { INSERT_POSITION, CLIPBOARD_FORMAT_KEY, CLIPBOARD_ORIGIN_SDOC_KEY, IMAGE, IMAGE_BLOCK, PARAGRAPH, ELEMENT_TYPE } from '../../constants';
|
|
10
10
|
import { INTERNAL_EVENT } from '../../../constants';
|
|
11
11
|
const withImage = editor => {
|
|
12
12
|
const {
|
|
@@ -70,14 +70,27 @@ const withImage = editor => {
|
|
|
70
70
|
if (data.types && data.types.includes('Files') && data.files[0].type.includes(IMAGE)) {
|
|
71
71
|
context.uploadLocalImage(data.files).then(fileUrl => {
|
|
72
72
|
insertImage(newEditor, fileUrl, editor.selection, INSERT_POSITION.CURRENT);
|
|
73
|
-
resetCursor(newEditor);
|
|
74
73
|
});
|
|
75
74
|
return;
|
|
76
75
|
}
|
|
77
76
|
insertData(data);
|
|
78
77
|
};
|
|
79
78
|
newEditor.insertFragment = data => {
|
|
80
|
-
|
|
79
|
+
const singleImage = getSingleImageFromFragment(data);
|
|
80
|
+
if (singleImage && isInsertImageMenuDisabled(editor)) {
|
|
81
|
+
const path = Editor.path(editor, editor.selection);
|
|
82
|
+
const nextPath = Path.next([path[0]]);
|
|
83
|
+
const p = generateEmptyElement(ELEMENT_TYPE.PARAGRAPH);
|
|
84
|
+
p.children = [singleImage];
|
|
85
|
+
Transforms.insertNodes(editor, p, {
|
|
86
|
+
at: nextPath
|
|
87
|
+
});
|
|
88
|
+
// There will be a space before and after the image
|
|
89
|
+
const imagePath = [...nextPath, 1];
|
|
90
|
+
focusEditor(editor, Path.next(imagePath));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (singleImage) {
|
|
81
94
|
resetCursor(newEditor);
|
|
82
95
|
}
|
|
83
96
|
return insertFragment(data);
|
|
@@ -110,28 +123,39 @@ const withImage = editor => {
|
|
|
110
123
|
const {
|
|
111
124
|
selection
|
|
112
125
|
} = editor;
|
|
113
|
-
|
|
126
|
+
if (!selection) return deleteBackward(unit);
|
|
114
127
|
const point = Editor.before(editor, selection, {
|
|
115
128
|
distance: 1
|
|
116
129
|
});
|
|
117
130
|
if (!point) return deleteBackward(unit);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (isPerviousNodeImage && Range.isCollapsed(selection) && isBlockAboveEmpty(editor) && !Path.isCommon(path, selection.anchor.path)) {
|
|
121
|
-
deleteBackward(unit);
|
|
122
|
-
focusEditor(newEditor, Editor.end(newEditor, focusPoint));
|
|
123
|
-
return;
|
|
131
|
+
if (!Range.isCollapsed(selection)) {
|
|
132
|
+
return deleteBackward(unit);
|
|
124
133
|
}
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
134
|
+
if (isSelectionAtBlockStart(editor)) {
|
|
135
|
+
const path = selection.anchor.path;
|
|
136
|
+
const beforePath = [path[0] - 1];
|
|
137
|
+
const beforeBlock = Editor.node(editor, beforePath);
|
|
138
|
+
if (beforeBlock && beforeBlock[0].type === IMAGE_BLOCK) {
|
|
139
|
+
focusEditor(editor, [...beforePath, 1]);
|
|
132
140
|
return;
|
|
133
141
|
}
|
|
134
|
-
|
|
142
|
+
}
|
|
143
|
+
const imageBlock = getSelectedNodeEntryByType(editor, IMAGE_BLOCK);
|
|
144
|
+
if (imageBlock) {
|
|
145
|
+
const path = selection.anchor.path;
|
|
146
|
+
const deletePath = [path[0]];
|
|
147
|
+
Transforms.removeNodes(editor, {
|
|
148
|
+
at: deletePath
|
|
149
|
+
});
|
|
150
|
+
const beforeEntry = Editor.node(editor, Path.previous(deletePath));
|
|
151
|
+
const selectPath = getLastChildPath(beforeEntry);
|
|
152
|
+
const endOfFirstNode = Editor.end(editor, selectPath);
|
|
153
|
+
const range = {
|
|
154
|
+
anchor: endOfFirstNode,
|
|
155
|
+
focus: endOfFirstNode
|
|
156
|
+
};
|
|
157
|
+
focusEditor(editor, range);
|
|
158
|
+
return;
|
|
135
159
|
}
|
|
136
160
|
deleteBackward(unit);
|
|
137
161
|
};
|
|
@@ -201,7 +201,8 @@ const Image = _ref => {
|
|
|
201
201
|
}, attributes, {
|
|
202
202
|
style: _objectSpread({}, style),
|
|
203
203
|
onMouseOver: e => selectImageWhenSelectPartial(e, editor, element, isSelected),
|
|
204
|
-
contentEditable: "true"
|
|
204
|
+
contentEditable: "true",
|
|
205
|
+
suppressContentEditableWarning: true
|
|
205
206
|
}), /*#__PURE__*/React.createElement("img", {
|
|
206
207
|
ref: imageRef,
|
|
207
208
|
src: imagePlaceholder,
|
|
@@ -214,10 +215,10 @@ const Image = _ref => {
|
|
|
214
215
|
}, attributes, {
|
|
215
216
|
style: _objectSpread({}, style),
|
|
216
217
|
onMouseOver: e => selectImageWhenSelectPartial(e, editor, element, isSelected),
|
|
217
|
-
contentEditable: "true"
|
|
218
|
+
contentEditable: "true",
|
|
219
|
+
suppressContentEditableWarning: true
|
|
218
220
|
}), /*#__PURE__*/React.createElement("span", {
|
|
219
|
-
className: "sdoc-image-inner"
|
|
220
|
-
contentEditable: "false"
|
|
221
|
+
className: "sdoc-image-inner"
|
|
221
222
|
}, /*#__PURE__*/React.createElement("span", {
|
|
222
223
|
className: "sdoc-image-content"
|
|
223
224
|
}, /*#__PURE__*/React.createElement("span", {
|
|
@@ -238,8 +239,7 @@ const Image = _ref => {
|
|
|
238
239
|
ref: resizerRef,
|
|
239
240
|
onMouseDown: onResizeStart
|
|
240
241
|
}), isResizing && /*#__PURE__*/React.createElement("span", {
|
|
241
|
-
className: "image-size"
|
|
242
|
-
contentEditable: false
|
|
242
|
+
className: "image-size"
|
|
243
243
|
}, /*#__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", {
|
|
244
244
|
id: "sdoc-image-caption-input",
|
|
245
245
|
ref: imageCaptionInputRef,
|
|
@@ -18,6 +18,8 @@ export const isInsertSeaTableTableDisabled = (editor, readonly) => {
|
|
|
18
18
|
type = getNodeType(parentNode);
|
|
19
19
|
}
|
|
20
20
|
if (type.startsWith('header')) return true;
|
|
21
|
+
if (type === ELEMENT_TYPE.TITLE) return true;
|
|
22
|
+
if (type === ELEMENT_TYPE.SUBTITLE) return true;
|
|
21
23
|
if (type === ELEMENT_TYPE.CODE_BLOCK) return true;
|
|
22
24
|
if (type === ELEMENT_TYPE.ORDERED_LIST) return true;
|
|
23
25
|
if (type === ELEMENT_TYPE.UNORDERED_LIST) return true;
|
|
@@ -25,6 +25,8 @@ export const isTableMenuDisabled = (editor, readonly) => {
|
|
|
25
25
|
type = getNodeType(parentNode);
|
|
26
26
|
}
|
|
27
27
|
if (type.startsWith('header')) return true;
|
|
28
|
+
if (type === ELEMENT_TYPE.TITLE) return true;
|
|
29
|
+
if (type === ELEMENT_TYPE.SUBTITLE) return true;
|
|
28
30
|
if (type === ELEMENT_TYPE.CODE_BLOCK) return true;
|
|
29
31
|
if (type === ELEMENT_TYPE.ORDERED_LIST) return true;
|
|
30
32
|
if (type === ELEMENT_TYPE.UNORDERED_LIST) return true;
|
|
@@ -575,8 +577,10 @@ export const removeTableElement = (editor, type) => {
|
|
|
575
577
|
return;
|
|
576
578
|
}
|
|
577
579
|
for (let i = minRowIndex; i <= maxRowIndex; i++) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
+
queueMicrotask(() => {
|
|
581
|
+
Transforms.removeNodes(editor, {
|
|
582
|
+
at: [...tablePath, minRowIndex]
|
|
583
|
+
});
|
|
580
584
|
});
|
|
581
585
|
}
|
|
582
586
|
const focusPath = [...tablePath, minRowIndex === 0 ? 0 : minRowIndex - 1, cellIndex];
|
|
@@ -1770,9 +1774,27 @@ export const isHideDragHandlerLine = (editor, displayType, table, cellPath, isDr
|
|
|
1770
1774
|
if (displayType === DRAG_HANDLER_COLUMN && cellIndex > 0) {
|
|
1771
1775
|
const prevCell = table.children[rowIndex].children[cellIndex - 1];
|
|
1772
1776
|
preCellDom = ReactEditor.toDOMNode(editor, prevCell);
|
|
1777
|
+
|
|
1778
|
+
// Check if there are merged cells in the columns before and after the drag line
|
|
1779
|
+
const beforeLineColumnHasCombined = table.children.find(item => {
|
|
1780
|
+
const cell = item.children[cellIndex - 1];
|
|
1781
|
+
return cell.children.length > 1;
|
|
1782
|
+
});
|
|
1783
|
+
const afterLineColumnHasCombined = table.children.find(item => {
|
|
1784
|
+
const cell = item.children[cellIndex];
|
|
1785
|
+
return (cell === null || cell === void 0 ? void 0 : cell.is_combined) === true;
|
|
1786
|
+
});
|
|
1787
|
+
if (beforeLineColumnHasCombined && afterLineColumnHasCombined) return true;
|
|
1773
1788
|
} else if (displayType === DRAG_HANDLER_ROW && rowIndex > 0) {
|
|
1774
1789
|
const prevCell = table.children[rowIndex - 1].children[cellIndex];
|
|
1775
1790
|
preCellDom = ReactEditor.toDOMNode(editor, prevCell);
|
|
1791
|
+
|
|
1792
|
+
// Check whether there are merged cells in the rows before and after the drag line
|
|
1793
|
+
const beforeLineRow = table.children[rowIndex - 1];
|
|
1794
|
+
const afterLineRow = table.children[rowIndex];
|
|
1795
|
+
const beforeLineRowHasCombined = beforeLineRow.children.find(item => item.children.length > 1);
|
|
1796
|
+
const afterLineRowHasCombined = afterLineRow.children.find(item => (item === null || item === void 0 ? void 0 : item.is_combined) === true);
|
|
1797
|
+
if (beforeLineRowHasCombined && afterLineRowHasCombined) return true;
|
|
1776
1798
|
}
|
|
1777
1799
|
|
|
1778
1800
|
// Check is above cell selected
|
|
@@ -46,7 +46,7 @@ class TableContextMenu extends React.Component {
|
|
|
46
46
|
} = this.props;
|
|
47
47
|
insertTableElement(editor, type, position, count);
|
|
48
48
|
});
|
|
49
|
-
_defineProperty(this, "
|
|
49
|
+
_defineProperty(this, "removeTableElements", type => {
|
|
50
50
|
const {
|
|
51
51
|
editor
|
|
52
52
|
} = this.props;
|
|
@@ -54,7 +54,7 @@ class TableContextMenu extends React.Component {
|
|
|
54
54
|
});
|
|
55
55
|
_defineProperty(this, "renderRemoveBtn", (type, title) => {
|
|
56
56
|
return /*#__PURE__*/React.createElement("button", {
|
|
57
|
-
onMouseDown: this.
|
|
57
|
+
onMouseDown: this.removeTableElements.bind(this, type),
|
|
58
58
|
className: "dropdown-item"
|
|
59
59
|
}, this.props.t(title));
|
|
60
60
|
});
|
|
@@ -6,7 +6,6 @@ import { PAGE_EDIT_AREA_WIDTH, WIKI_EDITOR } from '../basic-sdk/constants';
|
|
|
6
6
|
import { createWikiEditor } from '../basic-sdk/extension';
|
|
7
7
|
import withNodeId from '../basic-sdk/node-id';
|
|
8
8
|
import { withSocketIO } from '../basic-sdk/socket';
|
|
9
|
-
import { TITLE } from '../basic-sdk/extension/constants';
|
|
10
9
|
import WikiEditor from '../basic-sdk/editor/wiki-editor';
|
|
11
10
|
import '../assets/css/simple-viewer.css';
|
|
12
11
|
const SdocWikiEditor = _ref => {
|