@seafile/sdoc-editor 2.0.0 → 2.0.2
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/assets/css/sdoc-editor-plugins.css +32 -0
- package/dist/basic-sdk/extension/plugins/font/helpers.js +7 -0
- package/dist/basic-sdk/extension/plugins/header/render-elem.js +2 -1
- package/dist/basic-sdk/extension/plugins/image/helpers.js +9 -3
- package/dist/basic-sdk/extension/plugins/image/image-loader/index.css +37 -0
- package/dist/basic-sdk/extension/plugins/image/image-loader/index.js +23 -0
- package/dist/basic-sdk/extension/plugins/image/render-elem.js +36 -2
- package/dist/basic-sdk/extension/plugins/image/use-upload-image.js +80 -0
- package/dist/basic-sdk/extension/plugins/multi-column/plugin.js +1 -1
- package/dist/basic-sdk/extension/plugins/seatable-column/plugin.js +9 -1
- package/dist/basic-sdk/extension/plugins/seatable-column/render-elem.js +35 -0
- package/dist/basic-sdk/extension/plugins/text-style/helpers.js +1 -1
- package/dist/basic-sdk/extension/plugins/text-style/menu/index.js +10 -1
- package/dist/basic-sdk/extension/toolbar/side-toolbar/helpers.js +2 -1
- package/dist/components/copy-image-error-svg/index.js +64 -0
- package/package.json +7 -6
- package/public/locales/cs/sdoc-editor.json +4 -1
- package/public/locales/de/sdoc-editor.json +4 -1
- package/public/locales/en/sdoc-editor.json +5 -1
- package/public/locales/es/sdoc-editor.json +4 -1
- package/public/locales/es_AR/sdoc-editor.json +4 -1
- package/public/locales/es_MX/sdoc-editor.json +4 -1
- package/public/locales/fr/sdoc-editor.json +4 -1
- package/public/locales/it/sdoc-editor.json +4 -1
- package/public/locales/ru/sdoc-editor.json +4 -1
- package/public/locales/zh_CN/sdoc-editor.json +5 -1
|
@@ -62,6 +62,38 @@
|
|
|
62
62
|
caret-color: transparent;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
.sdoc-editor__article .sdoc-image-wrapper .sdoc-image-placeholder-wrapper {
|
|
66
|
+
width: 100%;
|
|
67
|
+
aspect-ratio: 1;
|
|
68
|
+
background-color: #f0f0f0;
|
|
69
|
+
border: 1px solid #ccc;
|
|
70
|
+
padding: 0 3%;
|
|
71
|
+
max-width: 100%;
|
|
72
|
+
user-select: all;
|
|
73
|
+
pointer-events: all;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.sdoc-editor__article .sdoc-image-wrapper .sdoc-image-tip-content,
|
|
77
|
+
.sdoc-editor__article .sdoc-image-wrapper .sdoc-image-title {
|
|
78
|
+
user-select: none;
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.sdoc-editor__article .sdoc-image-title .sdoc-exclamation-circle {
|
|
83
|
+
font-size: 18px;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
color: red;
|
|
87
|
+
display: flex;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.sdoc-editor__article .sdoc-image-title .sdoc-image-tip-title {
|
|
91
|
+
color: red;
|
|
92
|
+
font-size: 18px;
|
|
93
|
+
user-select: none;
|
|
94
|
+
pointer-events: none;
|
|
95
|
+
}
|
|
96
|
+
|
|
65
97
|
.sdoc-editor__article .sdoc-image-inner {
|
|
66
98
|
position: relative;
|
|
67
99
|
display: inline-block;
|
|
@@ -52,6 +52,13 @@ const getFontSize = editor => {
|
|
|
52
52
|
}
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
|
+
if (!_slate.Editor.isEditor(n) && _slate.Editor.isVoid(editor, n)) {
|
|
56
|
+
const parentNode = (0, _core.getParentNode)(editor.children, n.id);
|
|
57
|
+
if (!parentNode) return false;
|
|
58
|
+
if ([_constants.TITLE, _constants.SUBTITLE, ..._constants.HEADERS, _constants.CODE_LINE].includes(parentNode.type)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
55
62
|
return false;
|
|
56
63
|
}
|
|
57
64
|
});
|
|
@@ -9,6 +9,7 @@ var _react = _interopRequireDefault(require("react"));
|
|
|
9
9
|
var _slate = require("@seafile/slate");
|
|
10
10
|
var _core = require("../../core");
|
|
11
11
|
var _constants = require("../../constants");
|
|
12
|
+
var _helper = require("../paragraph/helper");
|
|
12
13
|
const renderTitle = (props, editor) => {
|
|
13
14
|
const {
|
|
14
15
|
element,
|
|
@@ -69,7 +70,7 @@ const renderHeader = (props, editor) => {
|
|
|
69
70
|
})
|
|
70
71
|
};
|
|
71
72
|
let isShowPlaceHolder = false;
|
|
72
|
-
if (_slate.Node.string(element) === '' && !isComposing) {
|
|
73
|
+
if ((0, _helper.isEmptyNode)(element) && _slate.Node.string(element) === '' && !isComposing) {
|
|
73
74
|
isShowPlaceHolder = true;
|
|
74
75
|
}
|
|
75
76
|
return /*#__PURE__*/_react.default.createElement("div", Object.assign({
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.updateImage = exports.selectImageWhenSelectPartial = exports.resetCursor = exports.queryCopyMoveProgressView = exports.isInsertImageMenuDisabled = exports.insertImageFiles = exports.insertImage = exports.hasSdocImages = exports.handleBase64Image = exports.getSingleImageFromFragment = exports.getImageURL = exports.getImageData = exports.generateImageNode = void 0;
|
|
7
|
+
exports.updateImage = exports.selectImageWhenSelectPartial = exports.resetCursor = exports.queryCopyMoveProgressView = exports.isInsertImageMenuDisabled = exports.isImagUrlIsFromCopy = exports.insertImageFiles = exports.insertImage = exports.hasSdocImages = exports.handleBase64Image = exports.getSingleImageFromFragment = exports.getImageURL = exports.getImageData = exports.generateImageNode = void 0;
|
|
8
8
|
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
9
9
|
var _slate = require("@seafile/slate");
|
|
10
10
|
var _slateReact = require("@seafile/slate-react");
|
|
@@ -153,7 +153,7 @@ const getImageURL = (data, editor) => {
|
|
|
153
153
|
return imgUrl;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
if (url
|
|
156
|
+
if (isImagUrlIsFromCopy(url)) return url;
|
|
157
157
|
const serviceUrl = _context.default.getSetting('serviceUrl');
|
|
158
158
|
const assetsUrl = _context.default.getSetting('assetsUrl');
|
|
159
159
|
return (0, _urlJoin.default)(serviceUrl, assetsUrl, url);
|
|
@@ -277,4 +277,10 @@ const handleBase64Image = (editor, path, imgData) => {
|
|
|
277
277
|
});
|
|
278
278
|
});
|
|
279
279
|
};
|
|
280
|
-
exports.handleBase64Image = handleBase64Image;
|
|
280
|
+
exports.handleBase64Image = handleBase64Image;
|
|
281
|
+
const isImagUrlIsFromCopy = url => {
|
|
282
|
+
if (url && url.startsWith('http')) return true;
|
|
283
|
+
if (url && url.startsWith('attachment')) return true; // from yuque
|
|
284
|
+
return false;
|
|
285
|
+
};
|
|
286
|
+
exports.isImagUrlIsFromCopy = isImagUrlIsFromCopy;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.sdoc-image-process-container {
|
|
2
|
+
position: absolute;
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
align-items: center;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
top: 0;
|
|
10
|
+
left: 0;
|
|
11
|
+
background-color: 'rgba(0, 0, 0, 0.5)'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@keyframes spin {
|
|
15
|
+
0% {
|
|
16
|
+
transform: rotate(0deg);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
100% {
|
|
20
|
+
transform: rotate(360deg);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sdoc-image-process-container .loading-spinner {
|
|
25
|
+
border: 3px solid #d8d8d8;
|
|
26
|
+
border-top: 3px solid #939393;
|
|
27
|
+
border-radius: 50%;
|
|
28
|
+
width: 20px;
|
|
29
|
+
height: 20px;
|
|
30
|
+
animation: spin 1s linear infinite;
|
|
31
|
+
user-select: none;
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sdoc-image-process-container .copyright {
|
|
36
|
+
margin-top: 4px;
|
|
37
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = ImageLoader;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
require("./index.css");
|
|
10
|
+
function ImageLoader(_ref) {
|
|
11
|
+
let {
|
|
12
|
+
copyright
|
|
13
|
+
} = _ref;
|
|
14
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
15
|
+
className: "sdoc-image-process-container"
|
|
16
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
17
|
+
className: "loading-spinner"
|
|
18
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
19
|
+
className: "spinner"
|
|
20
|
+
})), copyright && /*#__PURE__*/_react.default.createElement("div", {
|
|
21
|
+
className: "copyright"
|
|
22
|
+
}, copyright));
|
|
23
|
+
}
|
|
@@ -21,6 +21,9 @@ var _constants2 = require("./constants");
|
|
|
21
21
|
var _constants3 = require("../../constants");
|
|
22
22
|
var _constants4 = require("../../../../constants");
|
|
23
23
|
var _imagePlaceholder = _interopRequireDefault(require("../../../assets/images/image-placeholder.png"));
|
|
24
|
+
var _copyImageErrorSvg = _interopRequireDefault(require("../../../../components/copy-image-error-svg"));
|
|
25
|
+
var _useUploadImage = _interopRequireDefault(require("./use-upload-image"));
|
|
26
|
+
var _imageLoader = _interopRequireDefault(require("./image-loader"));
|
|
24
27
|
const Image = _ref => {
|
|
25
28
|
var _imageRef$current, _imageRef$current2;
|
|
26
29
|
let {
|
|
@@ -57,6 +60,14 @@ const Image = _ref => {
|
|
|
57
60
|
const [isShowImageHoverMenu, setIsShowImageHoverMenu] = (0, _react.useState)(false);
|
|
58
61
|
const [menuPosition, setMenuPosition] = (0, _react.useState)({});
|
|
59
62
|
const [caption, setCaption] = (0, _react.useState)((data === null || data === void 0 ? void 0 : data.caption) || '');
|
|
63
|
+
const {
|
|
64
|
+
isCopyImageLoading,
|
|
65
|
+
isCopyImageError,
|
|
66
|
+
setCopyImageLoading
|
|
67
|
+
} = (0, _useUploadImage.default)({
|
|
68
|
+
editor,
|
|
69
|
+
element
|
|
70
|
+
});
|
|
60
71
|
const registerEvent = (0, _react.useCallback)(eventList => {
|
|
61
72
|
eventList.forEach(element => {
|
|
62
73
|
document.addEventListener(element.eventName, element.event);
|
|
@@ -197,6 +208,11 @@ const Image = _ref => {
|
|
|
197
208
|
setIsShowImagePlaceholder(false);
|
|
198
209
|
}
|
|
199
210
|
}, [data, editor]);
|
|
211
|
+
const onImageLoaded = (0, _react.useCallback)(() => {
|
|
212
|
+
if ((0, _helpers.isImagUrlIsFromCopy)(data.src)) {
|
|
213
|
+
setCopyImageLoading(true);
|
|
214
|
+
}
|
|
215
|
+
}, [data.src, setCopyImageLoading]);
|
|
200
216
|
const onImageLoadError = (0, _react.useCallback)(() => {
|
|
201
217
|
// Check is due to the image is pasted from the clipboard in base64
|
|
202
218
|
if (data.src.startsWith('data:image/jpeg;base64')) {
|
|
@@ -232,6 +248,7 @@ const Image = _ref => {
|
|
|
232
248
|
},
|
|
233
249
|
onMouseOver: e => (0, _helpers.selectImageWhenSelectPartial)(e, editor, element, isSelected),
|
|
234
250
|
contentEditable: "false",
|
|
251
|
+
"data-src": (0, _helpers.getImageURL)(data, editor),
|
|
235
252
|
suppressContentEditableWarning: true
|
|
236
253
|
}), /*#__PURE__*/_react.default.createElement("img", {
|
|
237
254
|
ref: imageRef,
|
|
@@ -239,7 +256,21 @@ const Image = _ref => {
|
|
|
239
256
|
style: getImageStyle(),
|
|
240
257
|
draggable: false,
|
|
241
258
|
alt: ""
|
|
242
|
-
}), children),
|
|
259
|
+
}), children), isCopyImageError && /*#__PURE__*/_react.default.createElement("span", Object.assign({
|
|
260
|
+
className: (0, _classnames.default)('sdoc-image-wrapper', className)
|
|
261
|
+
}, attributes, {
|
|
262
|
+
style: {
|
|
263
|
+
...style
|
|
264
|
+
},
|
|
265
|
+
onMouseOver: e => (0, _helpers.selectImageWhenSelectPartial)(e, editor, element, isSelected),
|
|
266
|
+
contentEditable: "false",
|
|
267
|
+
"data-src": data.src,
|
|
268
|
+
suppressContentEditableWarning: true
|
|
269
|
+
}), /*#__PURE__*/_react.default.createElement(_copyImageErrorSvg.default, {
|
|
270
|
+
t: t,
|
|
271
|
+
isSelected: isSelected,
|
|
272
|
+
imageRef: imageRef
|
|
273
|
+
}), children), !isShowImagePlaceholder && !isCopyImageError && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", Object.assign({
|
|
243
274
|
"data-id": element.id,
|
|
244
275
|
className: (0, _classnames.default)('sdoc-image-wrapper', className)
|
|
245
276
|
}, attributes, {
|
|
@@ -256,16 +287,19 @@ const Image = _ref => {
|
|
|
256
287
|
}, /*#__PURE__*/_react.default.createElement("span", {
|
|
257
288
|
style: imageStyle
|
|
258
289
|
}, /*#__PURE__*/_react.default.createElement("img", {
|
|
290
|
+
ref: imageRef,
|
|
259
291
|
className: (0, _classnames.default)({
|
|
260
292
|
'image-selected': isSelected
|
|
261
293
|
}),
|
|
262
294
|
onClick: onClickImage,
|
|
263
|
-
ref: imageRef,
|
|
264
295
|
src: (0, _helpers.getImageURL)(data, editor),
|
|
265
296
|
style: getImageStyle(),
|
|
266
297
|
draggable: false,
|
|
298
|
+
onLoad: onImageLoaded,
|
|
267
299
|
onError: onImageLoadError,
|
|
268
300
|
alt: ""
|
|
301
|
+
}), isCopyImageLoading && /*#__PURE__*/_react.default.createElement(_imageLoader.default, {
|
|
302
|
+
copyright: t('Image_is_uploading')
|
|
269
303
|
}), isSelected && /*#__PURE__*/_react.default.createElement("span", {
|
|
270
304
|
className: "image-resizer",
|
|
271
305
|
ref: resizerRef,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _slate = require("@seafile/slate");
|
|
10
|
+
var _slateReact = require("@seafile/slate-react");
|
|
11
|
+
var _context = _interopRequireDefault(require("../../../../context"));
|
|
12
|
+
var _helpers = require("./helpers");
|
|
13
|
+
const updateImageNode = async function (editor, element, newUrl) {
|
|
14
|
+
let isError = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
15
|
+
const nodePath = _slateReact.ReactEditor.findPath(editor, element);
|
|
16
|
+
const newData = {
|
|
17
|
+
...element.data,
|
|
18
|
+
src: newUrl,
|
|
19
|
+
is_copy_error: isError
|
|
20
|
+
};
|
|
21
|
+
_slate.Transforms.setNodes(editor, {
|
|
22
|
+
data: newData
|
|
23
|
+
}, {
|
|
24
|
+
at: nodePath
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
const useImageUpload = _ref => {
|
|
28
|
+
let {
|
|
29
|
+
editor,
|
|
30
|
+
element
|
|
31
|
+
} = _ref;
|
|
32
|
+
const {
|
|
33
|
+
data
|
|
34
|
+
} = element;
|
|
35
|
+
const {
|
|
36
|
+
is_copy_error = false
|
|
37
|
+
} = data;
|
|
38
|
+
const [isLoading, setIsLoading] = (0, _react.useState)(false);
|
|
39
|
+
const [isCopyError, setIsCopyError] = (0, _react.useState)(is_copy_error);
|
|
40
|
+
(0, _react.useEffect)(() => {
|
|
41
|
+
const {
|
|
42
|
+
src: url
|
|
43
|
+
} = data;
|
|
44
|
+
if (isCopyError) return;
|
|
45
|
+
if (!(0, _helpers.isImagUrlIsFromCopy)(url)) return;
|
|
46
|
+
const downloadAndUploadImages = async url => {
|
|
47
|
+
try {
|
|
48
|
+
const response = await fetch(url);
|
|
49
|
+
if (response.ok) {
|
|
50
|
+
const blob = await response.blob();
|
|
51
|
+
const file = new File([blob], 'downloaded_image.png', {
|
|
52
|
+
type: blob.type
|
|
53
|
+
});
|
|
54
|
+
const imageUrl = await _context.default.uploadLocalImage([file]);
|
|
55
|
+
if (imageUrl && imageUrl[0]) {
|
|
56
|
+
updateImageNode(editor, element, imageUrl[0]);
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
throw new Error(`HTTP error status: ${response.status}`);
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(error);
|
|
63
|
+
updateImageNode(editor, element, url, true);
|
|
64
|
+
setIsCopyError(true);
|
|
65
|
+
} finally {
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
setIsLoading(false);
|
|
68
|
+
}, 500);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
downloadAndUploadImages(url);
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, []);
|
|
74
|
+
return {
|
|
75
|
+
isCopyImageLoading: isLoading,
|
|
76
|
+
setCopyImageLoading: setIsLoading,
|
|
77
|
+
isCopyImageError: isCopyError
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
var _default = exports.default = useImageUpload;
|
|
@@ -82,7 +82,7 @@ const withMultiColumn = editor => {
|
|
|
82
82
|
const nextNode = _slate.Editor.next(newEditor);
|
|
83
83
|
const nextColumnIndex = nextNode[1][1];
|
|
84
84
|
const currentMultiColumnEntry = (0, _core.getSelectedNodeEntryByType)(editor, _constants.ELEMENT_TYPE.MULTI_COLUMN);
|
|
85
|
-
if (!currentMultiColumnEntry) return
|
|
85
|
+
if (!currentMultiColumnEntry) return deleteForward(unit);
|
|
86
86
|
const {
|
|
87
87
|
column,
|
|
88
88
|
children: childColumn
|
|
@@ -8,7 +8,8 @@ var _constants = require("../../constants");
|
|
|
8
8
|
const withColumn = editor => {
|
|
9
9
|
const {
|
|
10
10
|
isInline,
|
|
11
|
-
isVoid
|
|
11
|
+
isVoid,
|
|
12
|
+
markableVoid
|
|
12
13
|
} = editor;
|
|
13
14
|
const newEditor = editor;
|
|
14
15
|
newEditor.isInline = element => {
|
|
@@ -25,6 +26,13 @@ const withColumn = editor => {
|
|
|
25
26
|
if (type === _constants.ELEMENT_TYPE.SEATABLE_COLUMN) return true;
|
|
26
27
|
return isVoid(element);
|
|
27
28
|
};
|
|
29
|
+
newEditor.markableVoid = element => {
|
|
30
|
+
const {
|
|
31
|
+
type
|
|
32
|
+
} = element;
|
|
33
|
+
if (type === _constants.ELEMENT_TYPE.SEATABLE_COLUMN) return true;
|
|
34
|
+
return markableVoid(element);
|
|
35
|
+
};
|
|
28
36
|
return newEditor;
|
|
29
37
|
};
|
|
30
38
|
var _default = exports.default = withColumn;
|
|
@@ -36,11 +36,46 @@ const Column = _ref => {
|
|
|
36
36
|
setIsClicked(false);
|
|
37
37
|
}
|
|
38
38
|
}, [isSelected, isReadOnly]);
|
|
39
|
+
const {
|
|
40
|
+
font_size = null,
|
|
41
|
+
font = null,
|
|
42
|
+
bold = null,
|
|
43
|
+
italic = null,
|
|
44
|
+
underline = null,
|
|
45
|
+
color = null,
|
|
46
|
+
highlight_color = null,
|
|
47
|
+
strikethrough = null
|
|
48
|
+
} = element.children[0];
|
|
39
49
|
const style = {
|
|
40
50
|
margin: '0 10px',
|
|
41
51
|
border: '1px solid transparent',
|
|
52
|
+
userSelect: 'none',
|
|
42
53
|
...(isClicked && {
|
|
43
54
|
border: '1px solid red'
|
|
55
|
+
}),
|
|
56
|
+
...(font_size && {
|
|
57
|
+
fontSize: font_size
|
|
58
|
+
}),
|
|
59
|
+
...(font && {
|
|
60
|
+
fontFamily: font
|
|
61
|
+
}),
|
|
62
|
+
...(bold && {
|
|
63
|
+
fontWeight: 600
|
|
64
|
+
}),
|
|
65
|
+
...(italic && {
|
|
66
|
+
fontStyle: 'italic'
|
|
67
|
+
}),
|
|
68
|
+
...(underline && {
|
|
69
|
+
textDecoration: 'underline'
|
|
70
|
+
}),
|
|
71
|
+
...(color && {
|
|
72
|
+
color: color
|
|
73
|
+
}),
|
|
74
|
+
...(highlight_color && {
|
|
75
|
+
backgroundColor: highlight_color
|
|
76
|
+
}),
|
|
77
|
+
...(strikethrough && {
|
|
78
|
+
textDecoration: 'line-through'
|
|
44
79
|
})
|
|
45
80
|
};
|
|
46
81
|
return /*#__PURE__*/_react.default.createElement("span", Object.assign({}, attributes, {
|
|
@@ -16,7 +16,7 @@ const isMenuDisabled = (editor, readonly) => {
|
|
|
16
16
|
match: n => {
|
|
17
17
|
const type = (0, _core.getNodeType)(n);
|
|
18
18
|
if (type === _elementType.CODE_BLOCK) return true; // Code block
|
|
19
|
-
if (_slate.Editor.isVoid(editor, n)) return true; // void node
|
|
19
|
+
if (_slate.Editor.isVoid(editor, n) && (n === null || n === void 0 ? void 0 : n.type) !== _elementType.SEATABLE_COLUMN) return true; // void node
|
|
20
20
|
|
|
21
21
|
return false;
|
|
22
22
|
},
|
|
@@ -49,6 +49,10 @@ const TextStyleMenuList = _ref => {
|
|
|
49
49
|
return (0, _helpers2.isMenuDisabled)(editor, readonly);
|
|
50
50
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
51
|
}, [editor, readonly]);
|
|
52
|
+
const isSelectedSeaTableColumn = (0, _react.useCallback)(() => {
|
|
53
|
+
const entery = (0, _core.getSelectedNodeByType)(editor, _constants.SEATABLE_COLUMN);
|
|
54
|
+
return !!entery;
|
|
55
|
+
}, [editor]);
|
|
52
56
|
const openLinkDialog = (0, _react.useCallback)(() => {
|
|
53
57
|
const eventBus = _eventBus.default.getInstance();
|
|
54
58
|
eventBus.dispatch(_constants2.INTERNAL_EVENT.INSERT_ELEMENT, {
|
|
@@ -99,11 +103,16 @@ const TextStyleMenuList = _ref => {
|
|
|
99
103
|
}, [editor, selectedFontSize, selectedFontSizeValue]);
|
|
100
104
|
const getTextStyleList = (0, _react.useCallback)(key => {
|
|
101
105
|
return _constants.MENUS_CONFIG_MAP[key].map(item => {
|
|
106
|
+
let disable = isDisabled();
|
|
107
|
+
const disableTypes = [_constants.TEXT_STYLE_MAP.CODE, _constants.TEXT_STYLE_MAP.LINK, _constants.TEXT_STYLE_MAP.SUPERSCRIPT, _constants.TEXT_STYLE_MAP.SUBSCRIPT];
|
|
108
|
+
if (disableTypes.includes(item.type)) {
|
|
109
|
+
disable = isSelectedSeaTableColumn() ? true : disable;
|
|
110
|
+
}
|
|
102
111
|
let itemProps = {
|
|
103
112
|
isRichEditor,
|
|
104
113
|
className,
|
|
105
114
|
ariaLabel: item === null || item === void 0 ? void 0 : item.ariaLabel,
|
|
106
|
-
disabled:
|
|
115
|
+
disabled: disable,
|
|
107
116
|
isActive: isActive(item.type),
|
|
108
117
|
onMouseDown: item.isColor ? () => {} : onMouseDown
|
|
109
118
|
};
|
|
@@ -134,7 +134,8 @@ const isVoidNode = node => {
|
|
|
134
134
|
const isCodeBlock = node.type === _constants.CODE_BLOCK;
|
|
135
135
|
const isCallout = node.type === _constants.CALL_OUT;
|
|
136
136
|
const isSeaTableTable = node.type === _constants.SEATABLE_TABLE;
|
|
137
|
-
|
|
137
|
+
const isSeaTableColumn = node.type === _constants.SEATABLE_COLUMN;
|
|
138
|
+
return _slate.Node.string(node) === '' && !hasImage && !isVideo && !isTable && !isCodeBlock && !isCallout && !isSeaTableTable && !isSeaTableColumn;
|
|
138
139
|
};
|
|
139
140
|
exports.isVoidNode = isVoidNode;
|
|
140
141
|
const isNotSupportTransform = node => {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
10
|
+
const Svg = _ref => {
|
|
11
|
+
let {
|
|
12
|
+
t,
|
|
13
|
+
isSelected,
|
|
14
|
+
imageRef
|
|
15
|
+
} = _ref;
|
|
16
|
+
return /*#__PURE__*/_react.default.createElement("svg", {
|
|
17
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
18
|
+
viewBox: "0 0 360 360",
|
|
19
|
+
preserveAspectRatio: "xMinYMin meet",
|
|
20
|
+
className: (0, _classnames.default)('sdoc-image-placeholder-wrapper', {
|
|
21
|
+
'image-selected': isSelected
|
|
22
|
+
}),
|
|
23
|
+
ref: imageRef,
|
|
24
|
+
draggable: false
|
|
25
|
+
}, /*#__PURE__*/_react.default.createElement("rect", {
|
|
26
|
+
width: "100%",
|
|
27
|
+
height: "100%",
|
|
28
|
+
fill: "#f0f0f0"
|
|
29
|
+
}), /*#__PURE__*/_react.default.createElement("g", {
|
|
30
|
+
className: "sdoc-image-content-wrapper",
|
|
31
|
+
transform: "translate(180, 180) scale(1)"
|
|
32
|
+
}, /*#__PURE__*/_react.default.createElement("g", {
|
|
33
|
+
className: "sdoc-image-title",
|
|
34
|
+
transform: "translate(0, 0)"
|
|
35
|
+
}, /*#__PURE__*/_react.default.createElement("foreignObject", {
|
|
36
|
+
x: "-85",
|
|
37
|
+
y: "-16",
|
|
38
|
+
width: "20",
|
|
39
|
+
height: "28"
|
|
40
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
41
|
+
className: "sdocfont sdoc-exclamation-circle"
|
|
42
|
+
})), /*#__PURE__*/_react.default.createElement("text", {
|
|
43
|
+
className: "sdoc-image-tip-title",
|
|
44
|
+
transform: "translate(-55, 4)",
|
|
45
|
+
fontSize: "20",
|
|
46
|
+
fill: "red",
|
|
47
|
+
fontFamily: "Arial, sans-serif"
|
|
48
|
+
}, t('Image_copy_error'))), /*#__PURE__*/_react.default.createElement("text", {
|
|
49
|
+
className: "sdoc-image-tip-content",
|
|
50
|
+
transform: "translate(0, 35)",
|
|
51
|
+
fontSize: "12",
|
|
52
|
+
textAnchor: "middle",
|
|
53
|
+
fill: "black",
|
|
54
|
+
fontFamily: "Arial, sans-serif"
|
|
55
|
+
}, t('Image_cannot_be_copied_Please_download_the_source_image')), /*#__PURE__*/_react.default.createElement("text", {
|
|
56
|
+
className: "sdoc-image-tip-content",
|
|
57
|
+
transform: "translate(0, 55)",
|
|
58
|
+
fontSize: "12",
|
|
59
|
+
textAnchor: "middle",
|
|
60
|
+
fill: "black",
|
|
61
|
+
fontFamily: "Arial, sans-serif"
|
|
62
|
+
}, t('And_select_insert_-_image_to_upload'))));
|
|
63
|
+
};
|
|
64
|
+
var _default = exports.default = Svg;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seafile/sdoc-editor",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "This is a sdoc editor",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"remark-rehype": "11.0.0",
|
|
40
40
|
"remark-stringify": "11.0.0",
|
|
41
41
|
"slugid": "3.2.0",
|
|
42
|
-
"socket.io-client": "4.
|
|
42
|
+
"socket.io-client": "4.8.1",
|
|
43
43
|
"type-of": "2.0.1",
|
|
44
44
|
"unified": "11.0.3",
|
|
45
45
|
"url-join": "4.0.1",
|
|
@@ -99,6 +99,7 @@
|
|
|
99
99
|
"css-minimizer-webpack-plugin": "5.0.1",
|
|
100
100
|
"dotenv": "^10.0.0",
|
|
101
101
|
"dotenv-expand": "^5.1.0",
|
|
102
|
+
"dtable-sdk": "5.0.6",
|
|
102
103
|
"dtable-utils": "5.0.1",
|
|
103
104
|
"ejs": "3.1.10",
|
|
104
105
|
"eslint": "^8.3.0",
|
|
@@ -119,7 +120,7 @@
|
|
|
119
120
|
"koa-router": "7.3.0",
|
|
120
121
|
"koa-send": "5.0.1",
|
|
121
122
|
"koa2-cors": "2.0.6",
|
|
122
|
-
"lint-staged": "
|
|
123
|
+
"lint-staged": "15.4.3",
|
|
123
124
|
"mini-css-extract-plugin": "^2.4.5",
|
|
124
125
|
"node-polyfill-webpack-plugin": "2.0.1",
|
|
125
126
|
"postcss": "^8.4.31",
|
|
@@ -140,7 +141,7 @@
|
|
|
140
141
|
"react-router-dom": "7.1.3",
|
|
141
142
|
"release-it": "17.3.0",
|
|
142
143
|
"resolve": "^1.20.0",
|
|
143
|
-
"resolve-url-loader": "
|
|
144
|
+
"resolve-url-loader": "5.0.0",
|
|
144
145
|
"sass-loader": "^12.3.0",
|
|
145
146
|
"seafile-js": "0.2.235",
|
|
146
147
|
"source-map-loader": "^3.0.0",
|
|
@@ -149,8 +150,8 @@
|
|
|
149
150
|
"terser-webpack-plugin": "^5.2.5",
|
|
150
151
|
"url-loader": "^4.1.1",
|
|
151
152
|
"web-vitals": "2.1.4",
|
|
152
|
-
"webpack": "5.
|
|
153
|
-
"webpack-dev-server": "
|
|
153
|
+
"webpack": "5.98.0",
|
|
154
|
+
"webpack-dev-server": "5.2.0",
|
|
154
155
|
"webpack-manifest-plugin": "5.0.0",
|
|
155
156
|
"webpack-merge": "5.8.0",
|
|
156
157
|
"workbox-webpack-plugin": "7.0.0"
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Videolink hinzufügen",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,9 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error",
|
|
617
|
+
"Image_is_uploading": "Image is uploading..."
|
|
614
618
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Add video link",
|
|
611
611
|
"Link_Seafile_video_file": "Link Seafile video file",
|
|
612
612
|
"Select_video_file": "Select video file",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Image cannot be copied. Please download the source image,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "and select 「insert」 - 「image」 to upload.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,8 @@
|
|
|
610
610
|
"Add_video_link": "Добавить ссылку на видео",
|
|
611
611
|
"Link_Seafile_video_file": "Ссылка на видео файл Seafile",
|
|
612
612
|
"Select_video_file": "Выбрать видео файл",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "Support Youtube, Tencent, Bilibili and more",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "Изображение не может быть скопировано. Скачайте исходное изображение,",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "и выбрать 「вставить」 - 「изображение」 для загрузки.",
|
|
616
|
+
"Image_copy_error": "Image copy error"
|
|
614
617
|
}
|
|
@@ -610,5 +610,9 @@
|
|
|
610
610
|
"Add_video_link": "添加视频链接",
|
|
611
611
|
"Link_Seafile_video_file": "链接Seafile视频文件",
|
|
612
612
|
"Select_video_file": "选择视频文件",
|
|
613
|
-
"Support_Youtube_Tencent_Bilibili_and_more": "支持Youtube,腾讯视频,B站及其他平台"
|
|
613
|
+
"Support_Youtube_Tencent_Bilibili_and_more": "支持Youtube,腾讯视频,B站及其他平台",
|
|
614
|
+
"Image_cannot_be_copied_Please_download_the_source_image": "此照片不支持复制,请下载原图",
|
|
615
|
+
"And_select_insert_-_image_to_upload": "后点击工具栏「插入」- 「照片」上传",
|
|
616
|
+
"Image_copy_error": "图片复制错误",
|
|
617
|
+
"Image_is_uploading": "图片正在上传..."
|
|
614
618
|
}
|