@seafile/sdoc-editor 0.1.4 → 0.1.6
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/assets/css/code-block.css +22 -0
- package/dist/assets/css/{sdoc-editor.css → layout.css} +4 -4
- package/dist/assets/css/sdoc-editor-content.css +10 -0
- package/dist/assets/css/sdoc-editor-toolbar.css +1 -1
- package/dist/editor.js +6 -7
- package/dist/extension/constants/index.js +19 -3
- package/dist/extension/core/queries/index.js +13 -0
- package/dist/extension/menu/menu-item.js +1 -1
- package/dist/extension/plugins/check-list/helpers.js +1 -1
- package/dist/extension/plugins/code-block/helpers.js +106 -0
- package/dist/extension/plugins/code-block/index.js +12 -0
- package/dist/extension/plugins/code-block/menu/index.js +65 -0
- package/dist/extension/plugins/code-block/model.js +11 -0
- package/dist/extension/plugins/code-block/plugin.js +89 -0
- package/dist/extension/plugins/code-block/render-elem.js +107 -0
- package/dist/extension/plugins/header/helpers.js +3 -3
- package/dist/extension/plugins/index.js +3 -2
- package/dist/extension/plugins/link/helpers.js +1 -1
- package/dist/extension/plugins/link/menu/add-link-dialog.js +1 -1
- package/dist/extension/plugins/list/helpers.js +1 -1
- package/dist/extension/plugins/list/render-elem.js +1 -1
- package/dist/extension/plugins/text-style/helpers.js +52 -0
- package/dist/extension/plugins/text-style/menu/index.js +81 -0
- package/dist/extension/render/render-element.js +8 -2
- package/dist/extension/toolbar/index.js +8 -2
- package/dist/socket/helpers.js +7 -5
- package/dist/socket/socket-client.js +1 -2
- package/dist/socket/socket-manager.js +2 -3
- package/dist/utils/debug.js +5 -0
- package/dist/viewer.js +2 -1
- package/package.json +1 -1
- package/public/locales/zh-CN/sdoc-editor.json +225 -0
- /package/public/locales/cs/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/de/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/en/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/es/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/es-AR/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/es-MX/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/fr/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/it/{seafile-editor.json → sdoc-editor.json} +0 -0
- /package/public/locales/ru/{seafile-editor.json → sdoc-editor.json} +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.code-block-container {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.language-type {
|
|
6
|
+
font-size: 12px;
|
|
7
|
+
position: absolute;
|
|
8
|
+
right: 0;
|
|
9
|
+
top: 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.language-type select {
|
|
13
|
+
background-color: #eeeeee;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
appearance: none;
|
|
16
|
+
outline: none;
|
|
17
|
+
-moz-appearance: none;
|
|
18
|
+
-webkit-appearance: none;
|
|
19
|
+
border: none;
|
|
20
|
+
border-radius: 4px;
|
|
21
|
+
padding: 0 5px;
|
|
22
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
padding-inline-start: 24px;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.
|
|
6
|
+
.sdoc-editor-container {
|
|
7
7
|
flex: 1;
|
|
8
8
|
display: flex;
|
|
9
9
|
flex-direction: column;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
min-height: 0;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
.
|
|
14
|
+
.sdoc-editor-container .sdoc-editor-toolbar {
|
|
15
15
|
display: flex;
|
|
16
16
|
justify-content: center;
|
|
17
17
|
height: 39px;
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
box-shadow: 0 3px 2px -2px rgb(200 200 200 / 15%)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
.
|
|
26
|
+
.sdoc-editor-container .sdoc-editor-content {
|
|
27
27
|
flex: 1;
|
|
28
28
|
height: 100%;
|
|
29
29
|
overflow: auto;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
.
|
|
32
|
+
.sdoc-editor-container .sdoc-editor-content .article {
|
|
33
33
|
max-width: 950px;
|
|
34
34
|
min-height: calc(100% - 40px);
|
|
35
35
|
margin: 20px auto;
|
package/dist/editor.js
CHANGED
|
@@ -8,7 +8,8 @@ import isHotkey from 'is-hotkey';
|
|
|
8
8
|
import editor, { renderLeaf as _renderLeaf, renderElement as _renderElement, Toolbar } from './extension';
|
|
9
9
|
import { SocketManager, withSocketIO } from './socket';
|
|
10
10
|
import withNodeId from './node-id';
|
|
11
|
-
import './assets/css/
|
|
11
|
+
import './assets/css/layout.css';
|
|
12
|
+
import './assets/css/sdoc-editor-content.css';
|
|
12
13
|
var SDocEditor = /*#__PURE__*/function (_React$Component) {
|
|
13
14
|
_inherits(SDocEditor, _React$Component);
|
|
14
15
|
var _super = _createSuper(SDocEditor);
|
|
@@ -51,21 +52,19 @@ var SDocEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
51
52
|
key: "render",
|
|
52
53
|
value: function render() {
|
|
53
54
|
var _this2 = this;
|
|
54
|
-
var
|
|
55
|
-
slateValue = _this$state.slateValue,
|
|
56
|
-
isEditorBlur = _this$state.isEditorBlur;
|
|
55
|
+
var slateValue = this.state.slateValue;
|
|
57
56
|
return /*#__PURE__*/React.createElement("div", {
|
|
58
|
-
className: "
|
|
57
|
+
className: "sdoc-editor-container"
|
|
59
58
|
}, /*#__PURE__*/React.createElement(Toolbar, {
|
|
60
59
|
editor: this.editor
|
|
61
60
|
}), /*#__PURE__*/React.createElement("div", {
|
|
62
|
-
className: "
|
|
61
|
+
className: "sdoc-editor-content"
|
|
63
62
|
}, /*#__PURE__*/React.createElement(Slate, {
|
|
64
63
|
editor: this.editor,
|
|
65
64
|
value: slateValue,
|
|
66
65
|
onChange: this.onChange
|
|
67
66
|
}, /*#__PURE__*/React.createElement("div", {
|
|
68
|
-
className: "
|
|
67
|
+
className: "article"
|
|
69
68
|
}, /*#__PURE__*/React.createElement(Editable, {
|
|
70
69
|
placeholder: "Enter some text...",
|
|
71
70
|
renderElement: function renderElement(props) {
|
|
@@ -2,7 +2,8 @@ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
|
2
2
|
var _MENUS_CONFIG_MAP, _HEADER_TITLE_MAP;
|
|
3
3
|
// extension plugin
|
|
4
4
|
export var BLOCKQUOTE = 'blockquote';
|
|
5
|
-
export var
|
|
5
|
+
export var BOLD = 'blod';
|
|
6
|
+
export var ITALIC = 'italic';
|
|
6
7
|
export var HEADER = 'header';
|
|
7
8
|
export var HEADER1 = 'header1';
|
|
8
9
|
export var HEADER2 = 'header2';
|
|
@@ -27,6 +28,7 @@ export var TABLE_CELL = 'table-cell';
|
|
|
27
28
|
export var TABLE_ROW = 'table-row';
|
|
28
29
|
export var FORMULA = 'formula';
|
|
29
30
|
export var COLUMN = 'column';
|
|
31
|
+
export var TEXTSTYLE = 'text-style';
|
|
30
32
|
|
|
31
33
|
// menus config
|
|
32
34
|
export var MENUS_CONFIG_MAP = (_MENUS_CONFIG_MAP = {}, _defineProperty(_MENUS_CONFIG_MAP, BLOCKQUOTE, {
|
|
@@ -45,9 +47,23 @@ export var MENUS_CONFIG_MAP = (_MENUS_CONFIG_MAP = {}, _defineProperty(_MENUS_CO
|
|
|
45
47
|
id: CHECK_LIST,
|
|
46
48
|
iconClass: 'iconfont icon-check-square',
|
|
47
49
|
text: 'check_list_item'
|
|
50
|
+
}), _defineProperty(_MENUS_CONFIG_MAP, CODE_BLOCK, {
|
|
51
|
+
id: CODE_BLOCK,
|
|
52
|
+
iconClass: 'iconfont icon-code-block',
|
|
53
|
+
text: 'code-block'
|
|
48
54
|
}), _defineProperty(_MENUS_CONFIG_MAP, LINK, {
|
|
49
55
|
id: LINK,
|
|
50
56
|
iconClass: 'iconfont icon-link',
|
|
51
57
|
text: 'link'
|
|
52
|
-
}), _MENUS_CONFIG_MAP
|
|
53
|
-
|
|
58
|
+
}), _defineProperty(_MENUS_CONFIG_MAP, TEXTSTYLE, [{
|
|
59
|
+
id: ITALIC,
|
|
60
|
+
iconClass: 'iconfont icon-italic',
|
|
61
|
+
text: 'italic',
|
|
62
|
+
type: 'ITALIC'
|
|
63
|
+
}, {
|
|
64
|
+
id: BOLD,
|
|
65
|
+
iconClass: 'iconfont icon-bold',
|
|
66
|
+
text: 'bold',
|
|
67
|
+
type: 'BOLD'
|
|
68
|
+
}]), _MENUS_CONFIG_MAP);
|
|
69
|
+
export var HEADER_TITLE_MAP = (_HEADER_TITLE_MAP = {}, _defineProperty(_HEADER_TITLE_MAP, HEADER1, 'header_1'), _defineProperty(_HEADER_TITLE_MAP, HEADER2, 'header_2'), _defineProperty(_HEADER_TITLE_MAP, HEADER3, 'header_3'), _defineProperty(_HEADER_TITLE_MAP, HEADER4, 'header_4'), _defineProperty(_HEADER_TITLE_MAP, HEADER5, 'header_5'), _defineProperty(_HEADER_TITLE_MAP, HEADER6, 'header_6'), _defineProperty(_HEADER_TITLE_MAP, PARAGRAPH, 'paragraph'), _HEADER_TITLE_MAP);
|
|
@@ -153,6 +153,14 @@ export var getSelectedElems = function getSelectedElems(editor) {
|
|
|
153
153
|
}
|
|
154
154
|
return elems;
|
|
155
155
|
};
|
|
156
|
+
export var genEmptyParagraph = function genEmptyParagraph() {
|
|
157
|
+
return {
|
|
158
|
+
type: 'paragraph',
|
|
159
|
+
children: [{
|
|
160
|
+
text: ''
|
|
161
|
+
}]
|
|
162
|
+
};
|
|
163
|
+
};
|
|
156
164
|
|
|
157
165
|
// siblings
|
|
158
166
|
export var getNextSiblingNodes = function getNextSiblingNodes(ancestorEntry, path) {
|
|
@@ -324,4 +332,9 @@ export var isSelectionAtBlockStart = function isSelectionAtBlockStart(editor, op
|
|
|
324
332
|
var path = (_getAboveBlockNode2 = getAboveBlockNode(editor, options)) === null || _getAboveBlockNode2 === void 0 ? void 0 : _getAboveBlockNode2[1];
|
|
325
333
|
if (!path) return false;
|
|
326
334
|
return isStartPoint(editor, selection.focus, path) || Range.isExpanded(editor.selection) && isStartPoint(editor, selection.anchor, path);
|
|
335
|
+
};
|
|
336
|
+
export var isLastNode = function isLastNode(editor, node) {
|
|
337
|
+
var editorChildren = editor.children || [];
|
|
338
|
+
var editorChildrenLength = editorChildren.length;
|
|
339
|
+
return editorChildren[editorChildrenLength - 1] === node;
|
|
327
340
|
};
|
|
@@ -13,7 +13,7 @@ var MenuItem = /*#__PURE__*/function (_React$Component) {
|
|
|
13
13
|
_this = _super.call(this, props);
|
|
14
14
|
_this.onMouseDown = function (event) {
|
|
15
15
|
if (_this.props.disabled) return;
|
|
16
|
-
_this.props.onMouseDown(event);
|
|
16
|
+
_this.props.onMouseDown(event, _this.props.type);
|
|
17
17
|
};
|
|
18
18
|
_this.onClick = function (event) {
|
|
19
19
|
event.stopPropagation();
|
|
@@ -26,7 +26,7 @@ export var isMenuDisabled = function isMenuDisabled(editor) {
|
|
|
26
26
|
var notMatch = selectedElements.some(function (element) {
|
|
27
27
|
if (Editor.isVoid(editor, element) && Editor.isBlock(editor, element)) return true;
|
|
28
28
|
var type = element.type;
|
|
29
|
-
if (['
|
|
29
|
+
if (['code-line', 'code-block', 'list-item'].includes(type)) return true;
|
|
30
30
|
return false;
|
|
31
31
|
});
|
|
32
32
|
if (notMatch) return true;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
|
|
3
|
+
import { Transforms, Editor, Node } from '@seafile/slate';
|
|
4
|
+
import { CODE_BLOCK, PARAGRAPH } from '../../constants';
|
|
5
|
+
import { getNodeType, getSelectedNodeByType, getSelectedElems } from '../../core';
|
|
6
|
+
export var isMenuDisabled = function isMenuDisabled(editor) {
|
|
7
|
+
var selection = editor.selection;
|
|
8
|
+
if (selection == null) return true;
|
|
9
|
+
var selectedElems = getSelectedElems(editor);
|
|
10
|
+
var hasVoid = selectedElems.some(function (elem) {
|
|
11
|
+
return editor.isVoid(elem);
|
|
12
|
+
});
|
|
13
|
+
if (hasVoid) return true;
|
|
14
|
+
var isMatch = selectedElems.some(function (elem) {
|
|
15
|
+
var type = getNodeType(elem);
|
|
16
|
+
if (type === CODE_BLOCK || type === PARAGRAPH) return true;
|
|
17
|
+
return false;
|
|
18
|
+
});
|
|
19
|
+
if (isMatch) return false; // enable
|
|
20
|
+
return true; // disable
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export var getSelectCodeElem = function getSelectCodeElem(editor) {
|
|
24
|
+
var codeNode = getSelectedNodeByType(editor, CODE_BLOCK);
|
|
25
|
+
if (codeNode == null) return null;
|
|
26
|
+
return codeNode;
|
|
27
|
+
};
|
|
28
|
+
export var updateLanguageSetting = function updateLanguageSetting(editor, language) {
|
|
29
|
+
Transforms.setNodes(editor, {
|
|
30
|
+
language: language
|
|
31
|
+
}, {
|
|
32
|
+
mode: 'highest'
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
export var changeToCodeBlock = function changeToCodeBlock(editor, language) {
|
|
36
|
+
// Summarizes the strings for the selected highest-level node
|
|
37
|
+
var strArr = [];
|
|
38
|
+
var nodeEntries = Editor.nodes(editor, {
|
|
39
|
+
match: function match(n) {
|
|
40
|
+
return editor.children.includes(n);
|
|
41
|
+
},
|
|
42
|
+
// Matches the selected node at the highest level
|
|
43
|
+
universal: true
|
|
44
|
+
});
|
|
45
|
+
var _iterator = _createForOfIteratorHelper(nodeEntries),
|
|
46
|
+
_step;
|
|
47
|
+
try {
|
|
48
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
49
|
+
var nodeEntry = _step.value;
|
|
50
|
+
var _nodeEntry = _slicedToArray(nodeEntry, 1),
|
|
51
|
+
n = _nodeEntry[0];
|
|
52
|
+
if (n) strArr.push(Node.string(n));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Deletes the selected node at the highest level
|
|
56
|
+
} catch (err) {
|
|
57
|
+
_iterator.e(err);
|
|
58
|
+
} finally {
|
|
59
|
+
_iterator.f();
|
|
60
|
+
}
|
|
61
|
+
Transforms.removeNodes(editor, {
|
|
62
|
+
mode: 'highest'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Insert the codeBlockNode node
|
|
66
|
+
var newCodeBlockNode = {
|
|
67
|
+
type: CODE_BLOCK,
|
|
68
|
+
children: [{
|
|
69
|
+
type: 'code-line',
|
|
70
|
+
children: [{
|
|
71
|
+
text: strArr.join('\n')
|
|
72
|
+
} // Select the plain text of the node
|
|
73
|
+
]
|
|
74
|
+
}],
|
|
75
|
+
|
|
76
|
+
language: language
|
|
77
|
+
};
|
|
78
|
+
Transforms.insertNodes(editor, newCodeBlockNode, {
|
|
79
|
+
mode: 'highest'
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
export var changeToPlainText = function changeToPlainText(editor) {
|
|
83
|
+
var elem = getSelectCodeElem(editor);
|
|
84
|
+
if (elem == null) return;
|
|
85
|
+
|
|
86
|
+
// Get code text
|
|
87
|
+
var str = Node.string(elem);
|
|
88
|
+
|
|
89
|
+
// Delete the highest level node, -> "the code-block node"
|
|
90
|
+
Transforms.removeNodes(editor, {
|
|
91
|
+
mode: 'highest'
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Insert p node
|
|
95
|
+
var pList = str.split('\n').map(function (s) {
|
|
96
|
+
return {
|
|
97
|
+
type: 'paragraph',
|
|
98
|
+
children: [{
|
|
99
|
+
text: s
|
|
100
|
+
}]
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
Transforms.insertNodes(editor, pList, {
|
|
104
|
+
mode: 'highest'
|
|
105
|
+
});
|
|
106
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CODE_BLOCK } from '../../constants';
|
|
2
|
+
import CodeBlockMenu from './menu';
|
|
3
|
+
import withCodeBlock from './plugin';
|
|
4
|
+
import { renderCodeBlock } from './render-elem';
|
|
5
|
+
var CodeBlockPlugin = {
|
|
6
|
+
type: CODE_BLOCK,
|
|
7
|
+
nodeType: 'element',
|
|
8
|
+
editorMenus: [CodeBlockMenu],
|
|
9
|
+
editorPlugin: withCodeBlock,
|
|
10
|
+
renderElements: [renderCodeBlock]
|
|
11
|
+
};
|
|
12
|
+
export default CodeBlockPlugin;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
3
|
+
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
4
|
+
import _inherits from "@babel/runtime/helpers/esm/inherits";
|
|
5
|
+
import _createSuper from "@babel/runtime/helpers/esm/createSuper";
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { focusEditor } from '../../../core';
|
|
8
|
+
import { CODE_BLOCK, MENUS_CONFIG_MAP } from '../../../constants';
|
|
9
|
+
import { MenuItem } from '../../../menu';
|
|
10
|
+
import { getSelectCodeElem, isMenuDisabled, changeToCodeBlock, changeToPlainText } from '../helpers';
|
|
11
|
+
var CodeBlockMenu = /*#__PURE__*/function (_React$Component) {
|
|
12
|
+
_inherits(CodeBlockMenu, _React$Component);
|
|
13
|
+
var _super = _createSuper(CodeBlockMenu);
|
|
14
|
+
function CodeBlockMenu() {
|
|
15
|
+
var _this;
|
|
16
|
+
_classCallCheck(this, CodeBlockMenu);
|
|
17
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
18
|
+
args[_key] = arguments[_key];
|
|
19
|
+
}
|
|
20
|
+
_this = _super.call.apply(_super, [this].concat(args));
|
|
21
|
+
_this.isActive = function () {
|
|
22
|
+
var editor = _this.props.editor;
|
|
23
|
+
var elem = getSelectCodeElem(editor);
|
|
24
|
+
return !!elem;
|
|
25
|
+
};
|
|
26
|
+
_this.isDisabled = function () {
|
|
27
|
+
return isMenuDisabled(_this.props.editor);
|
|
28
|
+
};
|
|
29
|
+
_this.onMouseDown = function (e) {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
var editor = _this.props.editor;
|
|
33
|
+
var active = _this.isActive(editor);
|
|
34
|
+
if (active) {
|
|
35
|
+
// It is currently in a code-block and needs to be converted to plain text
|
|
36
|
+
changeToPlainText(editor);
|
|
37
|
+
} else {
|
|
38
|
+
// It is not currently in code-block, so it needs to be converted to code-block
|
|
39
|
+
changeToCodeBlock(editor, 'text');
|
|
40
|
+
}
|
|
41
|
+
focusEditor(editor);
|
|
42
|
+
};
|
|
43
|
+
return _this;
|
|
44
|
+
}
|
|
45
|
+
_createClass(CodeBlockMenu, [{
|
|
46
|
+
key: "render",
|
|
47
|
+
value: function render() {
|
|
48
|
+
var _this$props = this.props,
|
|
49
|
+
isRichEditor = _this$props.isRichEditor,
|
|
50
|
+
className = _this$props.className;
|
|
51
|
+
var menuConfig = MENUS_CONFIG_MAP[CODE_BLOCK];
|
|
52
|
+
var props = _objectSpread(_objectSpread({
|
|
53
|
+
isRichEditor: isRichEditor,
|
|
54
|
+
className: className
|
|
55
|
+
}, menuConfig), {}, {
|
|
56
|
+
disabled: this.isDisabled(),
|
|
57
|
+
isActive: this.isActive(),
|
|
58
|
+
onMouseDown: this.onMouseDown
|
|
59
|
+
});
|
|
60
|
+
return /*#__PURE__*/React.createElement(MenuItem, props);
|
|
61
|
+
}
|
|
62
|
+
}]);
|
|
63
|
+
return CodeBlockMenu;
|
|
64
|
+
}(React.Component);
|
|
65
|
+
export default CodeBlockMenu;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
3
|
+
import { BLOCKQUOTE } from '../../constants';
|
|
4
|
+
var Blockquote = /*#__PURE__*/_createClass(function Blockquote(options) {
|
|
5
|
+
_classCallCheck(this, Blockquote);
|
|
6
|
+
this.type = options.type || BLOCKQUOTE;
|
|
7
|
+
this.children = options.children || [{
|
|
8
|
+
text: ''
|
|
9
|
+
}];
|
|
10
|
+
});
|
|
11
|
+
export default Blockquote;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import { Editor, Transforms, Node } from '@seafile/slate';
|
|
3
|
+
import { getSelectedNodeByType, getNodeType, isLastNode, genEmptyParagraph } from '../../core';
|
|
4
|
+
import { CODE_BLOCK } from '../../constants';
|
|
5
|
+
var getLastTextLineBeforeSelection = function getLastTextLineBeforeSelection(codeNode, editor) {
|
|
6
|
+
var selection = editor.selection;
|
|
7
|
+
if (selection == null) return '';
|
|
8
|
+
var codeText = Node.string(codeNode);
|
|
9
|
+
var anchorOffset = selection.anchor.offset;
|
|
10
|
+
var textBeforeAnchor = codeText.slice(0, anchorOffset); // The text before the selection
|
|
11
|
+
var arr = textBeforeAnchor.split('\n'); // text before selection, split by line break
|
|
12
|
+
var length = arr.length;
|
|
13
|
+
if (length === 0) return '';
|
|
14
|
+
return arr[length - 1];
|
|
15
|
+
};
|
|
16
|
+
var withCodeBlock = function withCodeBlock(editor) {
|
|
17
|
+
var insertBreak = editor.insertBreak,
|
|
18
|
+
normalizeNode = editor.normalizeNode,
|
|
19
|
+
insertData = editor.insertData;
|
|
20
|
+
var newEditor = editor;
|
|
21
|
+
|
|
22
|
+
// Rewrite insertBreak
|
|
23
|
+
newEditor.insertBreak = function () {
|
|
24
|
+
var codeNode = getSelectedNodeByType(newEditor, CODE_BLOCK);
|
|
25
|
+
if (codeNode == null) {
|
|
26
|
+
insertBreak(); // Perform the default line feed
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// When press Enter, the space is automatically inserted according to the space in the current line
|
|
31
|
+
var lastLineBeforeSelection = getLastTextLineBeforeSelection(codeNode, newEditor);
|
|
32
|
+
if (lastLineBeforeSelection) {
|
|
33
|
+
var arr = lastLineBeforeSelection.match(/^\s+/); // The space at the beginning of a line
|
|
34
|
+
if (arr != null && arr[0] != null) {
|
|
35
|
+
var spaces = arr[0];
|
|
36
|
+
newEditor.insertText("\n".concat(spaces)); // Insert a space after a newline
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Normal line feed
|
|
42
|
+
newEditor.insertText('\n');
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Rewrite normalizeNode
|
|
46
|
+
newEditor.normalizeNode = function (_ref) {
|
|
47
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
48
|
+
node = _ref2[0],
|
|
49
|
+
path = _ref2[1];
|
|
50
|
+
var type = getNodeType(node);
|
|
51
|
+
if (type === CODE_BLOCK) {
|
|
52
|
+
// code-block is the last node in the editor and needs to be followed by a p node
|
|
53
|
+
var isLast = isLastNode(newEditor, node);
|
|
54
|
+
if (isLast) {
|
|
55
|
+
Transforms.insertNodes(newEditor, genEmptyParagraph(), {
|
|
56
|
+
at: [path[0] + 1]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// There must be a code node below code-block
|
|
61
|
+
if (getNodeType(node.children[0]) !== 'code-line') {
|
|
62
|
+
Transforms.unwrapNodes(newEditor);
|
|
63
|
+
Transforms.setNodes(newEditor, {
|
|
64
|
+
type: 'paragraph'
|
|
65
|
+
}, {
|
|
66
|
+
mode: 'highest'
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Perform default behavior
|
|
72
|
+
return normalizeNode([node, path]);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Rewrite insertData - Paste text
|
|
76
|
+
newEditor.insertData = function (data) {
|
|
77
|
+
var codeNode = getSelectedNodeByType(newEditor, CODE_BLOCK);
|
|
78
|
+
if (codeNode == null) {
|
|
79
|
+
insertData(data); // Perform default insertData
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Gets the text and inserts it into the code block
|
|
84
|
+
var text = data.getData('text/plain');
|
|
85
|
+
Editor.insertText(newEditor, text);
|
|
86
|
+
};
|
|
87
|
+
return newEditor;
|
|
88
|
+
};
|
|
89
|
+
export default withCodeBlock;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
3
|
+
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
4
|
+
import _inherits from "@babel/runtime/helpers/esm/inherits";
|
|
5
|
+
import _createSuper from "@babel/runtime/helpers/esm/createSuper";
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { updateLanguageSetting } from './helpers';
|
|
8
|
+
import { getSelectedNodeByType } from '../../core';
|
|
9
|
+
import { CODE_BLOCK } from '../../constants';
|
|
10
|
+
import '../../../assets/css/code-block.css';
|
|
11
|
+
var LanguageSet = /*#__PURE__*/function (_React$PureComponent) {
|
|
12
|
+
_inherits(LanguageSet, _React$PureComponent);
|
|
13
|
+
var _super = _createSuper(LanguageSet);
|
|
14
|
+
function LanguageSet() {
|
|
15
|
+
var _this;
|
|
16
|
+
_classCallCheck(this, LanguageSet);
|
|
17
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
18
|
+
args[_key] = arguments[_key];
|
|
19
|
+
}
|
|
20
|
+
_this = _super.call.apply(_super, [this].concat(args));
|
|
21
|
+
_this.stopPropagation = function (event) {
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
};
|
|
24
|
+
return _this;
|
|
25
|
+
}
|
|
26
|
+
_createClass(LanguageSet, [{
|
|
27
|
+
key: "componentDidMount",
|
|
28
|
+
value: function componentDidMount() {
|
|
29
|
+
// Compat chrome browser in windows, stop propagation to prevent emit the click event added to document
|
|
30
|
+
this.selector.addEventListener('click', this.stopPropagation);
|
|
31
|
+
}
|
|
32
|
+
}, {
|
|
33
|
+
key: "componentWillUnmount",
|
|
34
|
+
value: function componentWillUnmount() {
|
|
35
|
+
this.selector.removeEventListener('click', this.stopPropagation);
|
|
36
|
+
}
|
|
37
|
+
}, {
|
|
38
|
+
key: "render",
|
|
39
|
+
value: function render() {
|
|
40
|
+
var _this2 = this;
|
|
41
|
+
var _this$props = this.props,
|
|
42
|
+
language = _this$props.language,
|
|
43
|
+
onChange = _this$props.onChange;
|
|
44
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
45
|
+
contentEditable: false,
|
|
46
|
+
className: "language-type"
|
|
47
|
+
}, /*#__PURE__*/React.createElement("select", {
|
|
48
|
+
ref: function ref(_ref) {
|
|
49
|
+
return _this2.selector = _ref;
|
|
50
|
+
},
|
|
51
|
+
value: language,
|
|
52
|
+
name: "language",
|
|
53
|
+
onInput: function onInput(event) {
|
|
54
|
+
return event.stopPropagation();
|
|
55
|
+
},
|
|
56
|
+
onChange: onChange
|
|
57
|
+
}, /*#__PURE__*/React.createElement("option", {
|
|
58
|
+
value: "none"
|
|
59
|
+
}, "Text")));
|
|
60
|
+
}
|
|
61
|
+
}]);
|
|
62
|
+
return LanguageSet;
|
|
63
|
+
}(React.PureComponent);
|
|
64
|
+
var CodeBlock = /*#__PURE__*/function (_React$PureComponent2) {
|
|
65
|
+
_inherits(CodeBlock, _React$PureComponent2);
|
|
66
|
+
var _super2 = _createSuper(CodeBlock);
|
|
67
|
+
function CodeBlock() {
|
|
68
|
+
var _this3;
|
|
69
|
+
_classCallCheck(this, CodeBlock);
|
|
70
|
+
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
71
|
+
args[_key2] = arguments[_key2];
|
|
72
|
+
}
|
|
73
|
+
_this3 = _super2.call.apply(_super2, [this].concat(args));
|
|
74
|
+
_this3.onChange = function (event) {
|
|
75
|
+
var editor = _this3.props.editor;
|
|
76
|
+
var language = event.target.value;
|
|
77
|
+
updateLanguageSetting(editor, language);
|
|
78
|
+
};
|
|
79
|
+
return _this3;
|
|
80
|
+
}
|
|
81
|
+
_createClass(CodeBlock, [{
|
|
82
|
+
key: "render",
|
|
83
|
+
value: function render() {
|
|
84
|
+
var _this$props2 = this.props,
|
|
85
|
+
codeBlockProps = _this$props2.codeBlockProps,
|
|
86
|
+
editor = _this$props2.editor;
|
|
87
|
+
var attributes = codeBlockProps.attributes,
|
|
88
|
+
children = codeBlockProps.children,
|
|
89
|
+
element = codeBlockProps.element;
|
|
90
|
+
var language = element.language;
|
|
91
|
+
var codeNode = getSelectedNodeByType(editor, CODE_BLOCK);
|
|
92
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
93
|
+
className: 'code-block-container'
|
|
94
|
+
}, /*#__PURE__*/React.createElement("pre", attributes, children), (codeNode === null || codeNode === void 0 ? void 0 : codeNode.id) === (element === null || element === void 0 ? void 0 : element.id) && /*#__PURE__*/React.createElement(LanguageSet, {
|
|
95
|
+
language: language,
|
|
96
|
+
onChange: this.onChange
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
}]);
|
|
100
|
+
return CodeBlock;
|
|
101
|
+
}(React.PureComponent);
|
|
102
|
+
export var renderCodeBlock = function renderCodeBlock(props, editor) {
|
|
103
|
+
return /*#__PURE__*/React.createElement(CodeBlock, {
|
|
104
|
+
codeBlockProps: _objectSpread({}, props),
|
|
105
|
+
editor: editor
|
|
106
|
+
});
|
|
107
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
-
import { Editor, Transforms } from
|
|
3
|
-
import { getNodeType } from
|
|
2
|
+
import { Editor, Transforms } from '@seafile/slate';
|
|
3
|
+
import { getNodeType } from '../../core';
|
|
4
4
|
export var isMenuDisabled = function isMenuDisabled(editor) {
|
|
5
5
|
if (!editor.selection) return true;
|
|
6
6
|
var _Editor$nodes = Editor.nodes(editor, {
|
|
7
7
|
match: function match(n) {
|
|
8
8
|
var type = getNodeType(n);
|
|
9
|
-
if (
|
|
9
|
+
if (['code-line', 'code-block', 'paragraph'].includes(type)) return true;
|
|
10
10
|
if (type.startsWith('header')) return true;
|
|
11
11
|
return false;
|
|
12
12
|
},
|
|
@@ -4,6 +4,7 @@ import BlockquotePlugin from './blockquote';
|
|
|
4
4
|
import ListPlugin from './list';
|
|
5
5
|
import CheckListPlugin from './check-list';
|
|
6
6
|
import TextPlugin from './text-style';
|
|
7
|
-
|
|
7
|
+
import CodeBlockPlugin from './code-block';
|
|
8
|
+
var Plugins = [HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, TextPlugin, CodeBlockPlugin];
|
|
8
9
|
export default Plugins;
|
|
9
|
-
export { HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, TextPlugin };
|
|
10
|
+
export { HeaderPlugin, LinkPlugin, BlockquotePlugin, ListPlugin, CheckListPlugin, TextPlugin, CodeBlockPlugin };
|
|
@@ -10,7 +10,7 @@ export var isMenuDisabled = function isMenuDisabled(editor) {
|
|
|
10
10
|
var notMatch = selectedElems.some(function (elem) {
|
|
11
11
|
var type = elem.type;
|
|
12
12
|
if (editor.isVoid(elem)) return true;
|
|
13
|
-
if (['
|
|
13
|
+
if (['code-block', 'code-line', 'link'].includes(type)) return true;
|
|
14
14
|
return false;
|
|
15
15
|
});
|
|
16
16
|
if (notMatch) return true; // disabled
|
|
@@ -143,4 +143,4 @@ var AddLinkDialog = /*#__PURE__*/function (_React$PureComponent) {
|
|
|
143
143
|
}]);
|
|
144
144
|
return AddLinkDialog;
|
|
145
145
|
}(React.PureComponent);
|
|
146
|
-
export default withTranslation('
|
|
146
|
+
export default withTranslation('sdoc-editor')(AddLinkDialog);
|
|
@@ -27,7 +27,7 @@ export var isMenuDisabled = function isMenuDisabled(editor) {
|
|
|
27
27
|
var notMatch = selectedElements.some(function (element) {
|
|
28
28
|
if (Editor.isVoid(editor, element) && Editor.isBlock(editor, element)) return true;
|
|
29
29
|
var type = element.type;
|
|
30
|
-
if (['
|
|
30
|
+
if (['code-line', 'code-block', 'table', 'check-list-item'].includes(type)) return true;
|
|
31
31
|
return false;
|
|
32
32
|
});
|
|
33
33
|
if (notMatch) return true;
|
|
@@ -7,7 +7,7 @@ var renderList = function renderList(props, editor) {
|
|
|
7
7
|
var Tag = node.type === ORDERED_LIST ? 'ol' : 'ul';
|
|
8
8
|
return /*#__PURE__*/React.createElement(Tag, Object.assign({
|
|
9
9
|
"data-id": node.id,
|
|
10
|
-
className: "
|
|
10
|
+
className: "list-container"
|
|
11
11
|
}, attributes), children);
|
|
12
12
|
};
|
|
13
13
|
var renderListItem = function renderListItem(props, editor) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
+
import { Editor, Transforms } from '@seafile/slate';
|
|
3
|
+
import { getNodeType } from '../../core';
|
|
4
|
+
export var isMenuDisabled = function isMenuDisabled(editor) {
|
|
5
|
+
if (editor.selection == null) return true;
|
|
6
|
+
var _Editor$nodes = Editor.nodes(editor, {
|
|
7
|
+
match: function match(n) {
|
|
8
|
+
var type = getNodeType(n);
|
|
9
|
+
if (type === 'code-block') return true; // Code block
|
|
10
|
+
if (Editor.isVoid(editor, n)) return true; // void node
|
|
11
|
+
|
|
12
|
+
return false;
|
|
13
|
+
},
|
|
14
|
+
universal: true
|
|
15
|
+
}),
|
|
16
|
+
_Editor$nodes2 = _slicedToArray(_Editor$nodes, 1),
|
|
17
|
+
match = _Editor$nodes2[0];
|
|
18
|
+
|
|
19
|
+
// If yes, it is disabled
|
|
20
|
+
if (match) return true;
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
export var addMark = function addMark(editor, type) {
|
|
24
|
+
Editor.addMark(editor, type, true);
|
|
25
|
+
};
|
|
26
|
+
export var removeMark = function removeMark(editor, type) {
|
|
27
|
+
Editor.removeMark(editor, type);
|
|
28
|
+
Transforms.setNodes(editor, {
|
|
29
|
+
type: 'paragraph'
|
|
30
|
+
}, {
|
|
31
|
+
mode: 'highest'
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Whether mark is included
|
|
36
|
+
export var getValue = function getValue(editor, mark) {
|
|
37
|
+
var curMarks = Editor.marks(editor);
|
|
38
|
+
|
|
39
|
+
// If curMarks exists, you need to set this parameter manually. curMarks prevails
|
|
40
|
+
if (curMarks) {
|
|
41
|
+
return curMarks[mark];
|
|
42
|
+
} else {
|
|
43
|
+
var _Editor$nodes3 = Editor.nodes(editor, {
|
|
44
|
+
match: function match(n) {
|
|
45
|
+
return n[mark] === true;
|
|
46
|
+
}
|
|
47
|
+
}),
|
|
48
|
+
_Editor$nodes4 = _slicedToArray(_Editor$nodes3, 1),
|
|
49
|
+
match = _Editor$nodes4[0];
|
|
50
|
+
return !!match;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
3
|
+
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
4
|
+
import _inherits from "@babel/runtime/helpers/esm/inherits";
|
|
5
|
+
import _createSuper from "@babel/runtime/helpers/esm/createSuper";
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { TEXTSTYLE, MENUS_CONFIG_MAP } from '../../../constants';
|
|
8
|
+
import { focusEditor } from '../../../core';
|
|
9
|
+
import { MenuItem } from '../../../menu';
|
|
10
|
+
import { getValue, isMenuDisabled, addMark, removeMark } from '../helpers';
|
|
11
|
+
var TextStyleMenuList = /*#__PURE__*/function (_React$Component) {
|
|
12
|
+
_inherits(TextStyleMenuList, _React$Component);
|
|
13
|
+
var _super = _createSuper(TextStyleMenuList);
|
|
14
|
+
function TextStyleMenuList(props) {
|
|
15
|
+
var _this;
|
|
16
|
+
_classCallCheck(this, TextStyleMenuList);
|
|
17
|
+
_this = _super.call(this, props);
|
|
18
|
+
_this.isActive = function (editor, type) {
|
|
19
|
+
var isMark = getValue(editor, type);
|
|
20
|
+
return !!isMark;
|
|
21
|
+
};
|
|
22
|
+
_this.isDisabled = function () {
|
|
23
|
+
var editor = _this.props.editor;
|
|
24
|
+
return isMenuDisabled(editor);
|
|
25
|
+
};
|
|
26
|
+
_this.onMouseDown = function (e, type) {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
e.stopPropagation();
|
|
29
|
+
if (_this.isDisabled()) return;
|
|
30
|
+
var editor = _this.props.editor;
|
|
31
|
+
var active = _this.isActive(editor, type);
|
|
32
|
+
if (active) {
|
|
33
|
+
removeMark(editor, type);
|
|
34
|
+
} else {
|
|
35
|
+
addMark(editor, type);
|
|
36
|
+
}
|
|
37
|
+
focusEditor(editor);
|
|
38
|
+
};
|
|
39
|
+
_this.state = {
|
|
40
|
+
isShowLinkDialog: false
|
|
41
|
+
};
|
|
42
|
+
return _this;
|
|
43
|
+
}
|
|
44
|
+
_createClass(TextStyleMenuList, [{
|
|
45
|
+
key: "getTextStyleMenuList",
|
|
46
|
+
value: function getTextStyleMenuList() {
|
|
47
|
+
var _this$props = this.props,
|
|
48
|
+
isRichEditor = _this$props.isRichEditor,
|
|
49
|
+
className = _this$props.className,
|
|
50
|
+
editor = _this$props.editor;
|
|
51
|
+
var textStyleMenuList = [{
|
|
52
|
+
isRichEditor: isRichEditor,
|
|
53
|
+
className: className,
|
|
54
|
+
disabled: this.isDisabled(),
|
|
55
|
+
isActive: this.isActive(editor, 'ITALIC'),
|
|
56
|
+
onMouseDown: this.onMouseDown
|
|
57
|
+
}, {
|
|
58
|
+
isRichEditor: isRichEditor,
|
|
59
|
+
className: className,
|
|
60
|
+
disabled: this.isDisabled(),
|
|
61
|
+
isActive: this.isActive(editor, 'BOLD'),
|
|
62
|
+
onMouseDown: this.onMouseDown
|
|
63
|
+
}];
|
|
64
|
+
return textStyleMenuList;
|
|
65
|
+
}
|
|
66
|
+
}, {
|
|
67
|
+
key: "render",
|
|
68
|
+
value: function render() {
|
|
69
|
+
var textStyleMenuList = this.getTextStyleMenuList();
|
|
70
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, textStyleMenuList.map(function (menuItem, index) {
|
|
71
|
+
var menuItemConfig = MENUS_CONFIG_MAP[TEXTSTYLE][index];
|
|
72
|
+
var menuItemProps = _objectSpread(_objectSpread({}, menuItem), menuItemConfig);
|
|
73
|
+
return /*#__PURE__*/React.createElement(MenuItem, Object.assign({
|
|
74
|
+
key: index
|
|
75
|
+
}, menuItemProps));
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
}]);
|
|
79
|
+
return TextStyleMenuList;
|
|
80
|
+
}(React.Component);
|
|
81
|
+
export default TextStyleMenuList;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, LIST_LIC, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST } from '../constants';
|
|
4
|
-
import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin } from '../plugins';
|
|
3
|
+
import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, LIST_LIC, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK } from '../constants';
|
|
4
|
+
import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin, CodeBlockPlugin } from '../plugins';
|
|
5
5
|
var renderElement = function renderElement(props, editor) {
|
|
6
6
|
var attributes = props.attributes,
|
|
7
7
|
children = props.children,
|
|
@@ -61,6 +61,12 @@ var renderElement = function renderElement(props, editor) {
|
|
|
61
61
|
editor: editor
|
|
62
62
|
}));
|
|
63
63
|
}
|
|
64
|
+
case CODE_BLOCK:
|
|
65
|
+
{
|
|
66
|
+
var _CodeBlockPlugin$rend = _slicedToArray(CodeBlockPlugin.renderElements, 1),
|
|
67
|
+
renderCodeBlock = _CodeBlockPlugin$rend[0];
|
|
68
|
+
return renderCodeBlock(props, editor);
|
|
69
|
+
}
|
|
64
70
|
default:
|
|
65
71
|
{
|
|
66
72
|
return /*#__PURE__*/React.createElement("p", Object.assign({
|
|
@@ -10,6 +10,8 @@ import { ORDERED_LIST, UNORDERED_LIST } from '../constants';
|
|
|
10
10
|
import HeaderMenu from '../plugins/header/menu';
|
|
11
11
|
import CheckListMenu from '../plugins/check-list/menu';
|
|
12
12
|
import { MenuGroup } from '../menu';
|
|
13
|
+
import TextStyleMenuList from '../plugins/text-style/menu';
|
|
14
|
+
import CodeBlockMenu from '../plugins/code-block/menu';
|
|
13
15
|
import '../../assets/css/sdoc-editor-toolbar.css';
|
|
14
16
|
var Toolbar = /*#__PURE__*/function (_React$Component) {
|
|
15
17
|
_inherits(Toolbar, _React$Component);
|
|
@@ -22,10 +24,12 @@ var Toolbar = /*#__PURE__*/function (_React$Component) {
|
|
|
22
24
|
key: "render",
|
|
23
25
|
value: function render() {
|
|
24
26
|
return /*#__PURE__*/React.createElement("div", {
|
|
25
|
-
className: "
|
|
27
|
+
className: "sdoc-editor-toolbar"
|
|
26
28
|
}, /*#__PURE__*/React.createElement(HeaderMenu, {
|
|
27
29
|
editor: this.props.editor
|
|
28
|
-
}), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(
|
|
30
|
+
}), /*#__PURE__*/React.createElement(MenuGroup, null, /*#__PURE__*/React.createElement(TextStyleMenuList, {
|
|
31
|
+
editor: this.props.editor
|
|
32
|
+
}), /*#__PURE__*/React.createElement(LinkMenu, {
|
|
29
33
|
editor: this.props.editor
|
|
30
34
|
}), /*#__PURE__*/React.createElement(QuoteMenu, {
|
|
31
35
|
editor: this.props.editor
|
|
@@ -37,6 +41,8 @@ var Toolbar = /*#__PURE__*/function (_React$Component) {
|
|
|
37
41
|
type: ORDERED_LIST
|
|
38
42
|
}), /*#__PURE__*/React.createElement(CheckListMenu, {
|
|
39
43
|
editor: this.props.editor
|
|
44
|
+
}), /*#__PURE__*/React.createElement(CodeBlockMenu, {
|
|
45
|
+
editor: this.props.editor
|
|
40
46
|
})));
|
|
41
47
|
}
|
|
42
48
|
}]);
|
package/dist/socket/helpers.js
CHANGED
|
@@ -61,11 +61,13 @@ export var validateOperation = function validateOperation(editor, operation) {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// reset insert node path
|
|
64
|
-
var parentNode =
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
var parentNode = getNode(editor, _path);
|
|
65
|
+
if (parentNode) {
|
|
66
|
+
var childLength = parentNode.children.length;
|
|
67
|
+
var index = Math.min(_path[_path.length - 1], childLength);
|
|
68
|
+
newOperation.path = parentNodePath.concat([index]);
|
|
69
|
+
isValid = true;
|
|
70
|
+
}
|
|
69
71
|
break;
|
|
70
72
|
}
|
|
71
73
|
case OPERATION.REMOVE_NODE:
|
|
@@ -2,9 +2,8 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
3
3
|
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
4
4
|
import io from 'socket.io-client';
|
|
5
|
-
import Debug from 'debug';
|
|
6
5
|
import SocketManager from './socket-manager';
|
|
7
|
-
|
|
6
|
+
import debug from '../utils/debug';
|
|
8
7
|
var SocketClient = /*#__PURE__*/_createClass(function SocketClient(config) {
|
|
9
8
|
var _this = this;
|
|
10
9
|
_classCallCheck(this, SocketClient);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
2
2
|
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
3
|
-
import Debug from 'debug';
|
|
4
3
|
import EventBus from '../utils/event-bus';
|
|
5
4
|
import { syncRemoteOperations, reExecRevertOperationList, revertOperationList } from './helpers';
|
|
6
5
|
import SocketClient from './socket-client';
|
|
7
|
-
|
|
6
|
+
import debug from '../utils/debug';
|
|
8
7
|
var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, document, config) {
|
|
9
8
|
var _this = this;
|
|
10
9
|
_classCallCheck(this, SocketManager);
|
|
@@ -111,7 +110,7 @@ var SocketManager = /*#__PURE__*/_createClass(function SocketManager(editor, doc
|
|
|
111
110
|
_this.revertOperationList = [];
|
|
112
111
|
});
|
|
113
112
|
} else {
|
|
114
|
-
// conflict:
|
|
113
|
+
// conflict:
|
|
115
114
|
// remote operations is not empty, waiting until remote operations all executed
|
|
116
115
|
debug('remote operations is not empty, and local version is not match remote version.');
|
|
117
116
|
}
|
package/dist/viewer.js
CHANGED
|
@@ -8,7 +8,8 @@ import isHotkey from 'is-hotkey';
|
|
|
8
8
|
import editor, { renderLeaf as _renderLeaf, renderElement as _renderElement } from './extension';
|
|
9
9
|
import { SocketManager, withSocketIO } from './socket';
|
|
10
10
|
import withNodeId from './node-id';
|
|
11
|
-
import './assets/css/
|
|
11
|
+
import './assets/css/layout.css';
|
|
12
|
+
import './assets/css/sdoc-editor-content.css';
|
|
12
13
|
var SDocViewer = /*#__PURE__*/function (_React$Component) {
|
|
13
14
|
_inherits(SDocViewer, _React$Component);
|
|
14
15
|
var _super = _createSuper(SDocViewer);
|
package/package.json
CHANGED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bold": "粗体",
|
|
3
|
+
"italic": "斜体",
|
|
4
|
+
"inline_code": "代码",
|
|
5
|
+
"header_one": "一级标题",
|
|
6
|
+
"header_two": "二级标题",
|
|
7
|
+
"header_three": "三级标题",
|
|
8
|
+
"header_four": "四级标题",
|
|
9
|
+
"header_five": "五级标题",
|
|
10
|
+
"header_six": "六级标题",
|
|
11
|
+
"paragraph": "段落",
|
|
12
|
+
"quote": "引用",
|
|
13
|
+
"ordered_list": "有序列表",
|
|
14
|
+
"unordered_list": "无序列表",
|
|
15
|
+
"check_list_item": "任务列表",
|
|
16
|
+
"insert_image": "插入图片",
|
|
17
|
+
"insert_formula": "插入公式",
|
|
18
|
+
"formula": "公式",
|
|
19
|
+
"insert_file": "插入文件",
|
|
20
|
+
"code": "行内代码",
|
|
21
|
+
"code_block": "代码块",
|
|
22
|
+
"insert_link": "添加链接",
|
|
23
|
+
"insert_table": "添加表格",
|
|
24
|
+
"save": "保存",
|
|
25
|
+
"more": "更多",
|
|
26
|
+
"invalid_url": "无效链接",
|
|
27
|
+
"link_address": "链接地址",
|
|
28
|
+
"image_address": "图片地址",
|
|
29
|
+
"submit": "提交",
|
|
30
|
+
"cancel": "取消",
|
|
31
|
+
"switch_to_plain_text_editor": "切换至普通文本编辑器",
|
|
32
|
+
"switch_to_rich_text_editor": "切换至富文本编辑器",
|
|
33
|
+
"switch_to_viewer": "切换到只读模式",
|
|
34
|
+
"help": "帮助",
|
|
35
|
+
"remove_table": "删除表格",
|
|
36
|
+
"column": "列",
|
|
37
|
+
"row": "行",
|
|
38
|
+
"Insert_Row_Before": "上方插入行",
|
|
39
|
+
"Insert_Row_After": "下方插入行",
|
|
40
|
+
"Insert_Column_Before": "左边插入列",
|
|
41
|
+
"Insert_Column_After": "右边插入列",
|
|
42
|
+
"Remove_Row": "删除当前行",
|
|
43
|
+
"Remove_Column": "删除当前列",
|
|
44
|
+
"Insert_Row": "插入行",
|
|
45
|
+
"Insert_Column": "插入列",
|
|
46
|
+
"set_align": "对齐方式",
|
|
47
|
+
"left": "左对齐",
|
|
48
|
+
"center": "居中",
|
|
49
|
+
"right": "右对齐",
|
|
50
|
+
"file_saved": "保存文件成功",
|
|
51
|
+
"file_failed_to_save": "保存文件失败",
|
|
52
|
+
"star": "添加星标",
|
|
53
|
+
"unstar": "移除星标",
|
|
54
|
+
"back_to_parent_directory":"返回上级目录",
|
|
55
|
+
"edit": "编辑",
|
|
56
|
+
"copy": "复制",
|
|
57
|
+
"copied": "已复制",
|
|
58
|
+
"internal_link": "内部链接",
|
|
59
|
+
"copy_internal_link": "内部链接已复制到剪贴板",
|
|
60
|
+
"internal_link_desc": "内部链接是指向文件或目录的链接,只有对该文件或目录有访问权限的人可以访问。",
|
|
61
|
+
"share": "共享",
|
|
62
|
+
"share_link": "共享链接",
|
|
63
|
+
"generate": "生成链接",
|
|
64
|
+
"add_password_protection": "增加密码保护",
|
|
65
|
+
"password": "密码",
|
|
66
|
+
"at_least_8_characters": "至少8个字符",
|
|
67
|
+
"password_again": "请再次输入密码",
|
|
68
|
+
"add_auto_expiration": "增加自动过期",
|
|
69
|
+
"days": "天",
|
|
70
|
+
"please_enter_password": "请输入密码",
|
|
71
|
+
"greater_than_or_equal_to": "大于或等于",
|
|
72
|
+
"less_than_or_equal_to": "小于或等于",
|
|
73
|
+
"set_permission": "设置权限",
|
|
74
|
+
"preview_and_download": "预览与下载",
|
|
75
|
+
"preview_only": "仅查看",
|
|
76
|
+
"please_enter_valid_days": "请输入有效的天数",
|
|
77
|
+
"please_enter_a_non-negative_integer": "请输入一个非负整数",
|
|
78
|
+
"please_enter_days": "请输入天数",
|
|
79
|
+
"password_is_too_short": "密码长度太短",
|
|
80
|
+
"passwords_do_not_match": "两次输入的密码不一致",
|
|
81
|
+
"return_to_wiki_page": "返回维基页面",
|
|
82
|
+
"insert_network_image": "插入网络图片",
|
|
83
|
+
"upload_local_image": "上传本地图片",
|
|
84
|
+
"add_link": "加入链接",
|
|
85
|
+
"file_history": "文件历史",
|
|
86
|
+
"history_version": "历史版本",
|
|
87
|
+
"back_to_viewer": "返回查看页面",
|
|
88
|
+
"link_title": "链接标题",
|
|
89
|
+
"local_draft": "本地草稿",
|
|
90
|
+
"use_draft": "使用草稿",
|
|
91
|
+
"delete_draft": "删除草稿",
|
|
92
|
+
"you_have_an_unsaved_draft_do_you_like_to_use_it": "有未保存的草稿,使用草稿吗?",
|
|
93
|
+
"local_draft_saved": "本地草稿已保存",
|
|
94
|
+
"new_draft": "创建草稿",
|
|
95
|
+
"view_draft": "查看草稿",
|
|
96
|
+
"publish": "发布",
|
|
97
|
+
"this_file_has_a_draft": "这个文件有一个草稿.",
|
|
98
|
+
"delete": "删除",
|
|
99
|
+
"comments": "评论",
|
|
100
|
+
"add_a_comment": "增加评论",
|
|
101
|
+
"no_comment_yet": "还没有评论",
|
|
102
|
+
"Mark_as_Resolved": "标记为已解决",
|
|
103
|
+
"ask_for_review": "发起评审",
|
|
104
|
+
"review_already_exists": "评审已存在",
|
|
105
|
+
"view_review": "查看评审",
|
|
106
|
+
"there_is_an_associated_review_with_this_file": "有一个与此文件相关联的评审。",
|
|
107
|
+
"start_review": "开始评审",
|
|
108
|
+
"this_file_is_in_draft_stage": "该文件处于草稿阶段。",
|
|
109
|
+
"this_file_is_in_review_stage": "该文件处于评审阶段。",
|
|
110
|
+
"this_file_has_been_updated": "这个文件已被修改。",
|
|
111
|
+
"refresh": "刷新",
|
|
112
|
+
"related_files": "相关文件",
|
|
113
|
+
"related_file": "相关文件",
|
|
114
|
+
"no_tags": "没有标签",
|
|
115
|
+
"Date": "日期",
|
|
116
|
+
"Participants": "参与人",
|
|
117
|
+
"Meeting_note": "会议记录",
|
|
118
|
+
"Chooser_document_type": "选择文档类型",
|
|
119
|
+
"Empty": "空",
|
|
120
|
+
"no_related_files": "没有相关文件",
|
|
121
|
+
"no_out_line": "没有大纲",
|
|
122
|
+
"Editing_files_in_this_browser_can_lead_to_slight_display_problems": "在此浏览器中,编辑文件可能导致轻微的显示问题。",
|
|
123
|
+
"no_document_improvement_suggestion": "没有文档改进建议",
|
|
124
|
+
"Hide_side_panel": "隐藏侧旁栏",
|
|
125
|
+
"Show_side_panel": "显示侧旁栏",
|
|
126
|
+
"Show_resolved_comments": "显示已解决的评论",
|
|
127
|
+
"Update": "更新",
|
|
128
|
+
"Width": "宽度",
|
|
129
|
+
"Height": "高度",
|
|
130
|
+
"Full_screen": "全屏",
|
|
131
|
+
"Insert_library_image": "插入资料库图片",
|
|
132
|
+
"Size": "大小",
|
|
133
|
+
"Location": "位置",
|
|
134
|
+
"Last_Update": "更新时间",
|
|
135
|
+
"Tags": "标签",
|
|
136
|
+
"Related_Files": "相关文档",
|
|
137
|
+
"Add_participants": "增加文件参与人",
|
|
138
|
+
"markdownLint": {
|
|
139
|
+
"missing_h1": {
|
|
140
|
+
"description": "文档缺少一级标题",
|
|
141
|
+
"issue" : "缺少一级标题"
|
|
142
|
+
},
|
|
143
|
+
"heading_end_with_colon": {
|
|
144
|
+
"description": "标题末尾的标点符号不应该是冒号",
|
|
145
|
+
"issue": "标题末尾是冒号"
|
|
146
|
+
},
|
|
147
|
+
"heading_increase_irregular": {
|
|
148
|
+
"description": "标题级别一次只能增加一级",
|
|
149
|
+
"issue": "标题级别不规范"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"Shortcut_help": "快捷键帮助",
|
|
153
|
+
"userHelp": {
|
|
154
|
+
"title": "键盘快捷键",
|
|
155
|
+
"userHelpData": [
|
|
156
|
+
{
|
|
157
|
+
"shortcutType":"列表快捷键",
|
|
158
|
+
"shortcutData": {
|
|
159
|
+
"Make_list": "生成列表",
|
|
160
|
+
"Make_ordered_list": "生成有序列表",
|
|
161
|
+
"Insert_new_item": "插入列表项",
|
|
162
|
+
"Insert_child_in_item": "插入新段落",
|
|
163
|
+
"Increase_depth": "增加列表项深度"
|
|
164
|
+
}
|
|
165
|
+
}, {
|
|
166
|
+
"shortcutType": "标题快捷键",
|
|
167
|
+
"shortcutData": {
|
|
168
|
+
"Heading_1": "一级标题",
|
|
169
|
+
"Heading_2": "二级标题",
|
|
170
|
+
"Heading_3": "三级标题",
|
|
171
|
+
"Heading_4": "四级标题",
|
|
172
|
+
"Heading_5": "五级标题",
|
|
173
|
+
"Heading_6": "六级标题"
|
|
174
|
+
}
|
|
175
|
+
}, {
|
|
176
|
+
"shortcutType": "代码块快捷键",
|
|
177
|
+
"shortcutData": {
|
|
178
|
+
"Make_code_block": "生成代码块",
|
|
179
|
+
"Insert_new_line": "插入行",
|
|
180
|
+
"Escape_code_block": "退出代码块",
|
|
181
|
+
"Insert_indent": "缩进"
|
|
182
|
+
}
|
|
183
|
+
}, {
|
|
184
|
+
"shortcutType": "引用快捷键",
|
|
185
|
+
"shortcutData": {
|
|
186
|
+
"Make_Block_quote": "生成引用",
|
|
187
|
+
"Escape_Block_quote": "退出引用"
|
|
188
|
+
}
|
|
189
|
+
}, {
|
|
190
|
+
"shortcutType": "表格快捷键",
|
|
191
|
+
"shortcutData": {
|
|
192
|
+
"Insert_Table_Row": "插入行",
|
|
193
|
+
"Escape_table": "退出表格"
|
|
194
|
+
}
|
|
195
|
+
}, {
|
|
196
|
+
"shortcutType": "公式快捷键",
|
|
197
|
+
"shortcutData": {
|
|
198
|
+
"Insert_Formula": "插入公式"
|
|
199
|
+
}
|
|
200
|
+
}, {
|
|
201
|
+
"shortcutType":"行内快捷键",
|
|
202
|
+
"shortcutData": {
|
|
203
|
+
"Bold": "粗体",
|
|
204
|
+
"Italic": "斜体",
|
|
205
|
+
"Italic_Bold": "斜体粗体",
|
|
206
|
+
"Inline_code": "行内代码"
|
|
207
|
+
}
|
|
208
|
+
}, {
|
|
209
|
+
"shortcutType": "保存快捷键",
|
|
210
|
+
"shortcutData": {
|
|
211
|
+
"Save_file": "保存文件"
|
|
212
|
+
}
|
|
213
|
+
}, {
|
|
214
|
+
"shortcutType": "图片快捷键",
|
|
215
|
+
"shortcutData": {
|
|
216
|
+
"Paste_screen_shot": "粘贴屏幕截图",
|
|
217
|
+
"Drag_image_from_anywhere_to_upload_it": "从任意地方拖动图像以上传"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
"The_link_address_is_required": "链接地址是必填项。",
|
|
223
|
+
"The_link_title_is_required": "链接标题是必填项。",
|
|
224
|
+
"The_link_address_is_invalid": "链接地址不合法,请输入一个正确的链接地址。"
|
|
225
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|