@seafile/seafile-editor 1.0.80 → 1.0.82-alpha

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.
Files changed (31) hide show
  1. package/dist/editors/simple-slate-editor /index.js +16 -6
  2. package/dist/extension/commons/expand-editor-menu.js +29 -0
  3. package/dist/extension/commons/index.js +15 -1
  4. package/dist/extension/commons/more-menu/index.css +4 -0
  5. package/dist/extension/commons/more-menu/index.js +46 -0
  6. package/dist/extension/constants/menus-config.js +13 -1
  7. package/dist/extension/index.js +6 -0
  8. package/dist/extension/plugins/html/plugin.js +46 -29
  9. package/dist/extension/plugins/image/render-element/index.js +1 -1
  10. package/dist/extension/toolbar/index.js +8 -1
  11. package/dist/extension/toolbar/inline-toolbar/index.css +40 -0
  12. package/dist/extension/toolbar/inline-toolbar/index.js +83 -0
  13. package/dist/pages/inline-longtext-editor/index.css +0 -0
  14. package/dist/pages/inline-longtext-editor/index.js +122 -0
  15. package/dist/pages/simple-editor.js +6 -2
  16. package/package.json +1 -1
  17. package/public/locales/cs/seafile-editor.json +2 -1
  18. package/public/locales/de/seafile-editor.json +2 -1
  19. package/public/locales/en/seafile-editor.json +2 -1
  20. package/public/locales/es/seafile-editor.json +2 -1
  21. package/public/locales/fr/seafile-editor.json +2 -1
  22. package/public/locales/it/seafile-editor.json +2 -1
  23. package/public/locales/ru/seafile-editor.json +2 -1
  24. package/public/locales/zh_CN/seafile-editor.json +2 -1
  25. package/public/media/seafile-editor-font/iconfont.eot +0 -0
  26. package/public/media/seafile-editor-font/iconfont.svg +2 -0
  27. package/public/media/seafile-editor-font/iconfont.ttf +0 -0
  28. package/public/media/seafile-editor-font/iconfont.woff +0 -0
  29. package/public/media/seafile-editor-font/iconfont.woff2 +0 -0
  30. package/public/media/seafile-editor-font.css +10 -6
  31. package/readme.md +203 -9
@@ -5,7 +5,7 @@ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWild
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.default = SimpleSlateEditor;
8
+ exports.default = void 0;
9
9
  var _react = _interopRequireWildcard(require("react"));
10
10
  var _slateReact = require("slate-react");
11
11
  var _slate = require("slate");
@@ -17,14 +17,16 @@ var _core = require("../../extension/core");
17
17
  var _common = require("../../utils/common");
18
18
  require("./style.css");
19
19
  const isMacOS = (0, _common.isMac)();
20
- function SimpleSlateEditor(_ref) {
20
+ const SimpleSlateEditor = _ref => {
21
21
  let {
22
+ isInline,
22
23
  value,
23
24
  editorApi,
24
25
  onSave,
25
26
  columns,
26
27
  onContentChanged,
27
- isSupportFormula
28
+ isSupportFormula,
29
+ onExpandEditorToggle
28
30
  } = _ref;
29
31
  const [slateValue, setSlateValue] = (0, _react.useState)(value);
30
32
  const editor = (0, _react.useMemo)(() => (0, _withPropsEditor.default)(_extension.baseEditor, {
@@ -36,6 +38,9 @@ function SimpleSlateEditor(_ref) {
36
38
  return new _eventHandler.default(editor);
37
39
  }, [editor]);
38
40
  const decorate = (0, _extension.useHighlight)(editor);
41
+ const ToolbarComponent = (0, _react.useMemo)(() => {
42
+ return isInline ? _extension.InlineToolbar : _extension.Toolbar;
43
+ }, [isInline]);
39
44
  const onChange = (0, _react.useCallback)(value => {
40
45
  setSlateValue(value);
41
46
  if (editor.forceNormalize) return;
@@ -113,10 +118,11 @@ function SimpleSlateEditor(_ref) {
113
118
  }, [editor, focusFirstNode]);
114
119
  return /*#__PURE__*/_react.default.createElement("div", {
115
120
  className: "sf-simple-slate-editor-container"
116
- }, /*#__PURE__*/_react.default.createElement(_extension.Toolbar, {
121
+ }, /*#__PURE__*/_react.default.createElement(ToolbarComponent, {
117
122
  editor: editor,
118
123
  isSupportFormula: isSupportFormula,
119
- isSupportColumn: !!columns
124
+ isSupportColumn: !!columns,
125
+ onExpandEditorToggle: onExpandEditorToggle
120
126
  }), /*#__PURE__*/_react.default.createElement("div", {
121
127
  className: "sf-slate-editor-content",
122
128
  onClick: onEditorClick
@@ -137,4 +143,8 @@ function SimpleSlateEditor(_ref) {
137
143
  onKeyDown: eventProxy.onKeyDown,
138
144
  onCopy: eventProxy.onCopy
139
145
  })))))));
140
- }
146
+ };
147
+ SimpleSlateEditor.defaultProps = {
148
+ isInline: false
149
+ };
150
+ var _default = exports.default = SimpleSlateEditor;
@@ -0,0 +1,29 @@
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 _constants = require("../constants");
10
+ var _menu = require("./menu");
11
+ require("./index.css");
12
+ const ExpandEditorMenu = _ref => {
13
+ let {
14
+ readonly,
15
+ isRichEditor,
16
+ onExpandEditorToggle,
17
+ className
18
+ } = _ref;
19
+ const config = _constants.MENUS_CONFIG_MAP[_constants.EXPAND_EDITOR];
20
+ return /*#__PURE__*/_react.default.createElement(_menu.MenuItem, Object.assign({
21
+ disabled: readonly,
22
+ isActive: false,
23
+ isRichEditor: isRichEditor,
24
+ type: _constants.EXPAND_EDITOR,
25
+ onMouseDown: onExpandEditorToggle,
26
+ className: className
27
+ }, config));
28
+ };
29
+ var _default = exports.default = ExpandEditorMenu;
@@ -10,6 +10,12 @@ Object.defineProperty(exports, "ElementPopover", {
10
10
  return _elementPopover.default;
11
11
  }
12
12
  });
13
+ Object.defineProperty(exports, "ExpandEditorMenu", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _expandEditorMenu.default;
17
+ }
18
+ });
13
19
  Object.defineProperty(exports, "MenuGroup", {
14
20
  enumerable: true,
15
21
  get: function () {
@@ -22,6 +28,12 @@ Object.defineProperty(exports, "MenuItem", {
22
28
  return _menu.MenuItem;
23
29
  }
24
30
  });
31
+ Object.defineProperty(exports, "MoreMenu", {
32
+ enumerable: true,
33
+ get: function () {
34
+ return _moreMenu.default;
35
+ }
36
+ });
25
37
  Object.defineProperty(exports, "Select", {
26
38
  enumerable: true,
27
39
  get: function () {
@@ -30,4 +42,6 @@ Object.defineProperty(exports, "Select", {
30
42
  });
31
43
  var _elementPopover = _interopRequireDefault(require("./element-popover"));
32
44
  var _menu = require("./menu");
33
- var _select = _interopRequireDefault(require("./select"));
45
+ var _select = _interopRequireDefault(require("./select"));
46
+ var _moreMenu = _interopRequireDefault(require("./more-menu"));
47
+ var _expandEditorMenu = _interopRequireDefault(require("./expand-editor-menu"));
@@ -0,0 +1,4 @@
1
+ .sf-editor-menu-popover {
2
+ padding: 8px 0;
3
+ min-width: 12rem;
4
+ }
@@ -0,0 +1,46 @@
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
+ var _reactstrap = require("reactstrap");
11
+ var _constants = require("../../constants");
12
+ require("./index.css");
13
+ const MoreMenu = _ref => {
14
+ let {
15
+ className,
16
+ disabled,
17
+ isRichEditor,
18
+ children
19
+ } = _ref;
20
+ const validClassName = (0, _classnames.default)(className, {
21
+ 'sf-rich-editor': isRichEditor,
22
+ 'sf-icon-btn': true,
23
+ 'sf-icon-btn-disabled': disabled,
24
+ 'sf-icon-btn-hover': !disabled
25
+ });
26
+ const config = _constants.MENUS_CONFIG_MAP[_constants.MORE_OPERATION];
27
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("button", {
28
+ className: validClassName,
29
+ type: "button",
30
+ id: config.id
31
+ }, /*#__PURE__*/_react.default.createElement("i", {
32
+ className: config.iconClass
33
+ })), /*#__PURE__*/_react.default.createElement(_reactstrap.UncontrolledPopover, {
34
+ target: config.id,
35
+ className: "sf-editor-menu-popover",
36
+ trigger: "legacy",
37
+ placement: "bottom-end",
38
+ hideArrow: true,
39
+ fade: false
40
+ }, children));
41
+ };
42
+ MoreMenu.defaultProps = {
43
+ isRichEditor: true,
44
+ className: 'sf-menu-group-item'
45
+ };
46
+ var _default = exports.default = MoreMenu;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.TEXT_STYLE_MAP = exports.TABLE_SUBMENU_MAP = exports.MENUS_CONFIG_MAP = exports.CLEAR_FORMAT = void 0;
6
+ exports.TEXT_STYLE_MAP = exports.TABLE_SUBMENU_MAP = exports.MORE_OPERATION = exports.MENUS_CONFIG_MAP = exports.EXPAND_EDITOR = exports.CLEAR_FORMAT = void 0;
7
7
  var _elementTypes = require("./element-types");
8
8
  const BOLD = 'bold';
9
9
  const ITALIC = 'italic';
@@ -12,6 +12,8 @@ const CODE = 'code';
12
12
  const DELETE = 'delete';
13
13
  const ADD = 'add';
14
14
  const CLEAR_FORMAT = exports.CLEAR_FORMAT = 'clear_format';
15
+ const MORE_OPERATION = exports.MORE_OPERATION = 'more_operation';
16
+ const EXPAND_EDITOR = exports.EXPAND_EDITOR = 'expand_editor';
15
17
  const TEXT_STYLE_MAP = exports.TEXT_STYLE_MAP = {
16
18
  BOLD: BOLD,
17
19
  ITALIC: ITALIC,
@@ -142,5 +144,15 @@ const MENUS_CONFIG_MAP = exports.MENUS_CONFIG_MAP = {
142
144
  id: "seafile_".concat(_elementTypes.COLUMN),
143
145
  iconClass: 'iconfont icon-choose-column',
144
146
  text: 'Insert_column'
147
+ },
148
+ [MORE_OPERATION]: {
149
+ id: "seafile_".concat(MORE_OPERATION),
150
+ iconClass: 'iconfont icon-more',
151
+ text: ''
152
+ },
153
+ [EXPAND_EDITOR]: {
154
+ id: "seafile_".concat(EXPAND_EDITOR),
155
+ iconClass: 'iconfont icon-fullscreen',
156
+ text: 'Expand_editor'
145
157
  }
146
158
  };
@@ -10,6 +10,12 @@ Object.defineProperty(exports, "ELementTypes", {
10
10
  return _constants.ELementTypes;
11
11
  }
12
12
  });
13
+ Object.defineProperty(exports, "InlineToolbar", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _toolbar.InlineToolbar;
17
+ }
18
+ });
13
19
  Object.defineProperty(exports, "SetNodeToDecorations", {
14
20
  enumerable: true,
15
21
  get: function () {
@@ -8,44 +8,61 @@ exports.default = void 0;
8
8
  var _isUrl = _interopRequireDefault(require("is-url"));
9
9
  var _slugid = _interopRequireDefault(require("slugid"));
10
10
  var _slateConvert = require("../../../slate-convert");
11
- var _core = require("../../core");
12
11
  var _elementTypes = require("../../constants/element-types");
12
+ var _helpers = require("../code-block/helpers");
13
13
  const withHtml = editor => {
14
14
  const {
15
15
  insertData
16
16
  } = editor;
17
17
  const newEditor = editor;
18
18
  newEditor.insertData = data => {
19
- if (!newEditor.insertFragmentData(data)) {
20
- // Other document paste content into code block
21
- if (!data.types.includes('text/code-block') && (0, _core.getSelectedNodeByType)(editor, _elementTypes.CODE_BLOCK)) {
22
- const plaintext = data.getData('text/plain') || '';
23
- if (plaintext) {
24
- let fragmentData = [];
25
- plaintext.split('\n').forEach(item => {
26
- const codeLine = {
27
- id: _slugid.default.nice(),
28
- type: _elementTypes.CODE_LINE,
29
- children: [{
30
- text: item,
31
- id: _slugid.default.nice()
32
- }]
33
- };
34
- fragmentData.push(codeLine);
35
- });
36
- newEditor.insertFragment(fragmentData);
37
- }
38
- return;
39
- }
40
- const htmlContent = data.getData('text/html') || '';
41
- const text = data.getData('text/plain') || '';
42
- if (!(0, _isUrl.default)(text) && htmlContent) {
43
- const content = (0, _slateConvert.deserializeHtml)(htmlContent);
44
- editor.insertFragment(content);
45
- return;
46
- }
19
+ // If the text is a link and is not within the code_block block, it is processed as link
20
+ const text = data.getData('text/plain') || '';
21
+ if ((0, _isUrl.default)(text) && !(0, _helpers.isInCodeBlock)(newEditor)) {
22
+ insertData(data);
23
+ return;
24
+ }
25
+
26
+ // If the copied content contains files, proceed as shown in the image
27
+ if (data.types.includes('Files')) {
47
28
  insertData(data);
29
+ return;
30
+ }
31
+
32
+ // If code_block is selected, the copied content will be processed according to code_block
33
+ if (!data.types.includes('text/code-block') && (0, _helpers.isInCodeBlock)(newEditor)) {
34
+ const plaintext = data.getData('text/plain') || '';
35
+ if (plaintext) {
36
+ let fragmentData = [];
37
+ plaintext.split('\n').forEach(item => {
38
+ const codeLine = {
39
+ id: _slugid.default.nice(),
40
+ type: _elementTypes.CODE_LINE,
41
+ children: [{
42
+ text: item,
43
+ id: _slugid.default.nice()
44
+ }]
45
+ };
46
+ fragmentData.push(codeLine);
47
+ });
48
+ newEditor.insertFragment(fragmentData);
49
+ }
50
+ return;
51
+ }
52
+
53
+ // If it is in slate format, it will be processed in slate format.
54
+ if (newEditor.insertFragmentData(data)) {
55
+ return;
56
+ }
57
+
58
+ // If it is in html format, it will be processed in html format.
59
+ const htmlContent = data.getData('text/html') || '';
60
+ if (htmlContent) {
61
+ const content = (0, _slateConvert.deserializeHtml)(htmlContent);
62
+ editor.insertFragment(content);
63
+ return;
48
64
  }
65
+ insertData(data);
49
66
  };
50
67
  return newEditor;
51
68
  };
@@ -111,7 +111,7 @@ const renderImage = (_ref, editor) => {
111
111
  'selected': isSelected,
112
112
  'error': isError
113
113
  }),
114
- alt: (element === null || element === void 0 ? void 0 : (_element$data2 = element.data) === null || _element$data2 === void 0 ? void 0 : _element$data2.alt) || '',
114
+ alt: (element === null || element === void 0 ? void 0 : (_element$data2 = element.data) === null || _element$data2 === void 0 ? void 0 : _element$data2.alt) || ' ' + t('Image_loading_failed'),
115
115
  src: element === null || element === void 0 ? void 0 : (_element$data3 = element.data) === null || _element$data3 === void 0 ? void 0 : _element$data3.src,
116
116
  width: element === null || element === void 0 ? void 0 : element.data.width,
117
117
  height: element === null || element === void 0 ? void 0 : element.data.height
@@ -4,10 +4,17 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
+ Object.defineProperty(exports, "InlineToolbar", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _inlineToolbar.default;
11
+ }
12
+ });
7
13
  Object.defineProperty(exports, "Toolbar", {
8
14
  enumerable: true,
9
15
  get: function () {
10
16
  return _headerToolbar.default;
11
17
  }
12
18
  });
13
- var _headerToolbar = _interopRequireDefault(require("./header-toolbar"));
19
+ var _headerToolbar = _interopRequireDefault(require("./header-toolbar"));
20
+ var _inlineToolbar = _interopRequireDefault(require("./inline-toolbar"));
@@ -0,0 +1,40 @@
1
+ .sf-slate-editor-toolbar {
2
+ background-color: #fcfcfc !important;
3
+ }
4
+
5
+ .sf-slate-editor-toolbar .sf-slate-article-info-control {
6
+ position: absolute;
7
+ right: 20px;
8
+ height: 30px;
9
+ width: 30px;
10
+ line-height: 30px;
11
+ display: flex;
12
+ justify-content: center;
13
+ cursor: pointer;
14
+ color: #555;
15
+ }
16
+
17
+ .sf-slate-editor-toolbar .sf-slate-article-info-control:hover {
18
+ background-color: #e5e5e5;
19
+ }
20
+
21
+ .sf-slate-editor-toolbar .sf-slate-help-info-control {
22
+ position: absolute;
23
+ right: 20px;
24
+ height: 30px;
25
+ width: 30px;
26
+ line-height: 30px;
27
+ display: flex;
28
+ justify-content: center;
29
+ cursor: pointer;
30
+ color: #555;
31
+ }
32
+
33
+ .sf-slate-editor-toolbar .sf-slate-help-info-control > span:hover {
34
+ cursor: pointer;
35
+ color: #333;
36
+ }
37
+
38
+ .sf-slate-editor-toolbar .sf-slate-article-info-control .iconfont {
39
+ font-size: 13px;
40
+ }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _useSelectionUpdate = _interopRequireDefault(require("../../../hooks/use-selection-update"));
11
+ var _commons = require("../../commons");
12
+ var _menu = _interopRequireDefault(require("../../plugins/blockquote/menu"));
13
+ var _menu2 = _interopRequireDefault(require("../../plugins/header/menu"));
14
+ var _menu3 = _interopRequireDefault(require("../../plugins/text-style/menu"));
15
+ var _menu4 = _interopRequireDefault(require("../../plugins/link/menu"));
16
+ var _constants = require("../../constants");
17
+ var _menu5 = _interopRequireDefault(require("../../plugins/image/menu"));
18
+ var _menu6 = _interopRequireDefault(require("../../plugins/code-block/menu"));
19
+ var _menu7 = _interopRequireDefault(require("../../plugins/check-list/menu"));
20
+ var _menu8 = _interopRequireDefault(require("../../plugins/list/menu"));
21
+ var _elementTypes = require("../../constants/element-types");
22
+ var _tableOperator = require("../../plugins/table/menu/table-operator");
23
+ var _helper = require("../../plugins/table/helper");
24
+ var _menu9 = _interopRequireDefault(require("../../plugins/clear-format/menu"));
25
+ var _shortcutDialog = _interopRequireDefault(require("../user-help/shortcut-dialog"));
26
+ require("./index.css");
27
+ // import TableMenu from '../../plugins/table/menu';
28
+ // import FormulaMenu from '../../plugins/formula/menu';
29
+ // import ColumnMenu from '../../plugins/column/menu';
30
+
31
+ const InlineToolbar = _ref => {
32
+ let {
33
+ editor,
34
+ readonly = false,
35
+ isRichEditor = false,
36
+ isSupportFormula = false,
37
+ isSupportInsertSeafileImage = false,
38
+ isSupportColumn = false,
39
+ onExpandEditorToggle
40
+ } = _ref;
41
+ (0, _useSelectionUpdate.default)();
42
+
43
+ // eslint-disable-next-line react-hooks/exhaustive-deps
44
+ const isShowSubTableMenu = (0, _react.useMemo)(() => (0, _helper.isInTable)(editor), [editor.selection]);
45
+ const [isShowHelpModal, setIsShowHelpModal] = (0, _react.useState)(false);
46
+ const onHelpIconToggle = (0, _react.useCallback)(() => {
47
+ setIsShowHelpModal(!isShowHelpModal);
48
+ }, [isShowHelpModal]);
49
+ const commonProps = {
50
+ editor,
51
+ readonly,
52
+ isRichEditor
53
+ };
54
+ return /*#__PURE__*/_react.default.createElement("div", {
55
+ className: "sf-slate-editor-toolbar"
56
+ }, isRichEditor && /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null), /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null, /*#__PURE__*/_react.default.createElement(_menu2.default, commonProps)), /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null, /*#__PURE__*/_react.default.createElement(_menu3.default, Object.assign({}, commonProps, {
57
+ type: _constants.TEXT_STYLE_MAP.BOLD
58
+ })), /*#__PURE__*/_react.default.createElement(_menu3.default, Object.assign({}, commonProps, {
59
+ type: _constants.TEXT_STYLE_MAP.ITALIC
60
+ })), /*#__PURE__*/_react.default.createElement(_menu3.default, Object.assign({}, commonProps, {
61
+ type: _constants.TEXT_STYLE_MAP.CODE
62
+ })), /*#__PURE__*/_react.default.createElement(_menu4.default, commonProps)), /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null, /*#__PURE__*/_react.default.createElement(_menu.default, commonProps), /*#__PURE__*/_react.default.createElement(_menu7.default, commonProps), /*#__PURE__*/_react.default.createElement(_menu8.default, Object.assign({}, commonProps, {
63
+ type: _elementTypes.ORDERED_LIST
64
+ })), /*#__PURE__*/_react.default.createElement(_menu8.default, Object.assign({}, commonProps, {
65
+ type: _elementTypes.UNORDERED_LIST
66
+ }))), /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null, /*#__PURE__*/_react.default.createElement(_menu6.default, commonProps), /*#__PURE__*/_react.default.createElement(_commons.MoreMenu, commonProps, /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null, /*#__PURE__*/_react.default.createElement(_menu5.default, Object.assign({}, commonProps, {
67
+ isSupportInsertSeafileImage: isSupportInsertSeafileImage
68
+ }))), isShowSubTableMenu && /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, {
69
+ className: "sf-menu-group sf-table-operations-group"
70
+ }, /*#__PURE__*/_react.default.createElement(_tableOperator.AlignmentDropDown, commonProps), /*#__PURE__*/_react.default.createElement(_tableOperator.ColumnOperationDropDownList, commonProps), /*#__PURE__*/_react.default.createElement(_tableOperator.RowOperationDropDownList, commonProps), /*#__PURE__*/_react.default.createElement(_tableOperator.RemoveTableMenu, commonProps)), /*#__PURE__*/_react.default.createElement(_commons.MenuGroup, null, /*#__PURE__*/_react.default.createElement(_menu9.default, commonProps)), !isRichEditor && /*#__PURE__*/_react.default.createElement("div", {
71
+ className: "sf-slate-help-info-control",
72
+ onClick: onHelpIconToggle
73
+ }, /*#__PURE__*/_react.default.createElement("span", {
74
+ className: "iconfont icon-use-help"
75
+ })))), onExpandEditorToggle && /*#__PURE__*/_react.default.createElement(_commons.ExpandEditorMenu, commonProps), isShowHelpModal && /*#__PURE__*/_react.default.createElement(_shortcutDialog.default, {
76
+ isRichEditor: isRichEditor,
77
+ toggleShortcutDialog: onHelpIconToggle
78
+ }));
79
+ };
80
+ InlineToolbar.defaultProps = {
81
+ readonly: false
82
+ };
83
+ var _default = exports.default = InlineToolbar;
File without changes
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _classnames = _interopRequireDefault(require("classnames"));
11
+ var _simpleEditor = _interopRequireDefault(require("../simple-editor"));
12
+ var _getPreviewContent = _interopRequireDefault(require("../../utils/get-preview-content"));
13
+ var _getBrowserInfo = _interopRequireDefault(require("../../utils/get-browser-Info"));
14
+ var _markdownPreview = _interopRequireDefault(require("../markdown-preview"));
15
+ var _longtextEditorDialog = _interopRequireDefault(require("../longtext-editor-dialog"));
16
+ require("./index.css");
17
+ const InlineLongTextEditor = _ref => {
18
+ let {
19
+ lang,
20
+ headerName,
21
+ value,
22
+ autoSave = true,
23
+ saveDelay = 60000,
24
+ isCheckBrowser = false,
25
+ editorApi,
26
+ onSaveEditorValue,
27
+ onEditorValueChanged
28
+ } = _ref;
29
+ const editorRef = useRef(null);
30
+ const [isValueChanged, setValueChanged] = (0, _react.useState)(false);
31
+ const [showExpandEditor, setShowExpandEditor] = (0, _react.useState)(false);
32
+ const {
33
+ isValidBrowser,
34
+ isWindowsWechat
35
+ } = useMemo(() => {
36
+ return (0, _getBrowserInfo.default)(isCheckBrowser);
37
+ }, [isCheckBrowser]);
38
+ const onUpdateEditorValue = (0, _react.useCallback)(() => {
39
+ var _editorRef$current, _editorRef$current2;
40
+ if (!isValueChanged) return;
41
+ const markdownString = (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.getValue();
42
+ const slateNodes = (_editorRef$current2 = editorRef.current) === null || _editorRef$current2 === void 0 ? void 0 : _editorRef$current2.getSlateValue();
43
+ const {
44
+ previewText,
45
+ images,
46
+ links,
47
+ checklist
48
+ } = (0, _getPreviewContent.default)(slateNodes, false);
49
+ onSaveEditorValue({
50
+ text: markdownString,
51
+ preview: previewText,
52
+ images: images,
53
+ links: links,
54
+ checklist
55
+ });
56
+ setValueChanged(false);
57
+ }, [isValueChanged, onSaveEditorValue]);
58
+ const onContentChanged = (0, _react.useCallback)(() => {
59
+ // delay to update editor's content
60
+ setTimeout(() => {
61
+ // update parent's component cache value
62
+ if (onEditorValueChanged && typeof onEditorValueChanged === 'function') {
63
+ var _editorRef$current3, _editorRef$current4;
64
+ const markdownString = (_editorRef$current3 = editorRef.current) === null || _editorRef$current3 === void 0 ? void 0 : _editorRef$current3.getValue();
65
+ const slateNodes = (_editorRef$current4 = editorRef.current) === null || _editorRef$current4 === void 0 ? void 0 : _editorRef$current4.getSlateValue();
66
+ const {
67
+ previewText,
68
+ images,
69
+ links,
70
+ checklist
71
+ } = (0, _getPreviewContent.default)(slateNodes, false);
72
+ onEditorValueChanged({
73
+ text: markdownString,
74
+ preview: previewText,
75
+ images: images,
76
+ links: links,
77
+ checklist
78
+ });
79
+ }
80
+ setValueChanged(true);
81
+ }, 0);
82
+ }, [onEditorValueChanged]);
83
+ const openEditorDialog = (0, _react.useCallback)(() => {
84
+ setShowExpandEditor(true);
85
+ }, []);
86
+ const onCloseEditorDialog = (0, _react.useCallback)(() => {
87
+ onUpdateEditorValue();
88
+ setShowExpandEditor(false);
89
+ }, [onUpdateEditorValue]);
90
+ useEffect(() => {
91
+ let timer = null;
92
+ if (autoSave) {
93
+ timer = setTimeout(() => {
94
+ onUpdateEditorValue();
95
+ }, saveDelay);
96
+ }
97
+ return () => {
98
+ timer && clearTimeout(timer);
99
+ };
100
+ }, [autoSave, saveDelay, onUpdateEditorValue]);
101
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", null, !readOnly && !isWindowsWechat && /*#__PURE__*/_react.default.createElement(_simpleEditor.default, {
102
+ isInline: true,
103
+ ref: editorRef,
104
+ value: value,
105
+ editorApi: editorApi,
106
+ onContentChanged: onContentChanged,
107
+ onExpandEditorToggle: openEditorDialog
108
+ })), showExpandEditor && /*#__PURE__*/_react.default.createElement(_longtextEditorDialog.default, {
109
+ lang: lang,
110
+ readOnly: false,
111
+ headerName: headerName,
112
+ value: value,
113
+ autoSave: autoSave,
114
+ saveDelay: saveDelay,
115
+ isCheckBrowser: isCheckBrowser,
116
+ editorApi: editorApi,
117
+ onSaveEditorValue: onSaveEditorValue,
118
+ onEditorValueChanged: onEditorValueChanged,
119
+ onCloseEditorDialog: onCloseEditorDialog
120
+ }));
121
+ };
122
+ var _default = exports.default = InlineLongTextEditor;
@@ -13,12 +13,14 @@ var _useMathjax = _interopRequireDefault(require("../hooks/use-mathjax"));
13
13
  var _simpleSlateEditor = _interopRequireDefault(require("../editors/simple-slate-editor "));
14
14
  const SimpleEditor = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
15
15
  let {
16
+ isInline,
16
17
  isFetching,
17
18
  value,
18
19
  editorApi,
19
20
  mathJaxSource,
20
21
  onSave: propsOnSave,
21
- onContentChanged: propsOnContentChanged
22
+ onContentChanged: propsOnContentChanged,
23
+ ...otherProps
22
24
  } = _ref;
23
25
  const [richValue, setRichValue] = (0, _react.useState)([]);
24
26
  const [isLoading, setIsLoading] = (0, _react.useState)(true);
@@ -49,11 +51,13 @@ const SimpleEditor = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
49
51
  propsOnContentChanged && propsOnContentChanged();
50
52
  }, [propsOnContentChanged]);
51
53
  const props = {
54
+ isInline,
52
55
  isSupportFormula: !!mathJaxSource,
53
56
  value: richValue,
54
57
  editorApi: editorApi,
55
58
  onSave: propsOnSave,
56
- onContentChanged: onContentChanged
59
+ onContentChanged: onContentChanged,
60
+ ...otherProps
57
61
  };
58
62
  if (isFetching || isLoading || isLoadingMathJax) {
59
63
  return /*#__PURE__*/_react.default.createElement(_loading.default, null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/seafile-editor",
3
- "version": "1.0.80",
3
+ "version": "1.0.82alpha",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Vyberte pole",
222
222
  "Font_style": "Styl písma",
223
223
  "Open_link": "Open link",
224
- "Image_is_uploading": "Image is uploading"
224
+ "Image_is_uploading": "Image is uploading",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Feld auswählen",
222
222
  "Font_style": "Schriftschnitt",
223
223
  "Open_link": "Open link",
224
- "Image_is_uploading": "Image is uploading"
224
+ "Image_is_uploading": "Image is uploading",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Select field",
222
222
  "Font_style": "Font style",
223
223
  "Open_link": "Open link",
224
- "Image_is_uploading": "Image is uploading"
224
+ "Image_is_uploading": "Image is uploading",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Select field",
222
222
  "Font_style": "Font style",
223
223
  "Open_link": "Open link",
224
- "Image_is_uploading": "Image is uploading"
224
+ "Image_is_uploading": "Image is uploading",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Select field",
222
222
  "Font_style": "Font style",
223
223
  "Open_link": "Ouvrir le lien",
224
- "Image_is_uploading": "Image is uploading"
224
+ "Image_is_uploading": "Image is uploading",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Select field",
222
222
  "Font_style": "Font style",
223
223
  "Open_link": "Open link",
224
- "Image_is_uploading": "Image is uploading"
224
+ "Image_is_uploading": "Image is uploading",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "Выбрать поле",
222
222
  "Font_style": "Стиль шрифта",
223
223
  "Open_link": "Открыть ссылку",
224
- "Image_is_uploading": "Изображение загружается"
224
+ "Image_is_uploading": "Изображение загружается",
225
+ "Image_loading_failed": "Image loading failed"
225
226
  }
@@ -221,5 +221,6 @@
221
221
  "Select_field": "选中字段",
222
222
  "Font_style": "字体样式",
223
223
  "Open_link": "打开链接",
224
- "Image_is_uploading": "图片正在上传"
224
+ "Image_is_uploading": "图片正在上传",
225
+ "Image_loading_failed": "图片加载失败"
225
226
  }
@@ -14,6 +14,8 @@
14
14
  />
15
15
  <missing-glyph />
16
16
 
17
+ <glyph glyph-name="more" unicode="&#58918;" d="M835.2 387.2c0-54.4 41.6-96 96-96s96 41.6 96 96-41.6 96-96 96c-51.2 0-96-41.6-96-96z m-416 0c0-54.4 41.6-96 96-96s96 41.6 96 96-41.6 96-96 96c-51.2 0-96-41.6-96-96z m-416 0c0-54.4 41.6-96 96-96s96 41.6 96 96-41.6 96-96 96c-51.2 0-96-41.6-96-96z" horiz-adv-x="1027" />
18
+
17
19
  <glyph glyph-name="drop-down" unicode="&#59013;" d="M550.4 169.6l265.6 336c32 38.4 6.4 102.4-38.4 102.4H246.4c-44.8 0-70.4-60.8-38.4-102.4l265.6-336c19.2-25.6 57.6-25.6 76.8 0z" horiz-adv-x="1024" />
18
20
 
19
21
  <glyph glyph-name="caret-up" unicode="&#59014;" d="M550.4 588.8l265.6-336c32-38.4 6.4-102.4-38.4-102.4H246.4c-44.8 0-70.4 60.8-38.4 102.4l265.6 336c19.2 25.6 57.6 25.6 76.8 0z" horiz-adv-x="1024" />
@@ -1,11 +1,11 @@
1
1
  @font-face {
2
2
  font-family: "iconfont"; /* Project id 4375832 */
3
- src: url('./seafile-editor-font/iconfont.eot?t=1709878601328'); /* IE9 */
4
- src: url('./seafile-editor-font/iconfont.eot?t=1709878601328#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
- url('./seafile-editor-font/iconfont.woff2?t=1709878601328') format('woff2'),
6
- url('./seafile-editor-font/iconfont.woff?t=1709878601328') format('woff'),
7
- url('./seafile-editor-font/iconfont.ttf?t=1709878601328') format('truetype'),
8
- url('./seafile-editor-font/iconfont.svg?t=1709878601328#iconfont') format('svg');
3
+ src: url('./seafile-editor-font/iconfont.eot?t=1714979485064'); /* IE9 */
4
+ src: url('./seafile-editor-font/iconfont.eot?t=1714979485064#iefix') format('embedded-opentype'), /* IE6-IE8 */
5
+ url('./seafile-editor-font/iconfont.woff2?t=1714979485064') format('woff2'),
6
+ url('./seafile-editor-font/iconfont.woff?t=1714979485064') format('woff'),
7
+ url('./seafile-editor-font/iconfont.ttf?t=1714979485064') format('truetype'),
8
+ url('./seafile-editor-font/iconfont.svg?t=1714979485064#iconfont') format('svg');
9
9
  }
10
10
 
11
11
  .iconfont {
@@ -16,6 +16,10 @@
16
16
  -moz-osx-font-smoothing: grayscale;
17
17
  }
18
18
 
19
+ .icon-more:before {
20
+ content: "\e626";
21
+ }
22
+
19
23
  .icon-drop-down:before {
20
24
  content: "\e685";
21
25
  }
package/readme.md CHANGED
@@ -2,25 +2,219 @@
2
2
 
3
3
  SeaMarkdown editor is a WYSIWYG Markdown editor based on slate.js. It is used in Seafile and SeaTable project.
4
4
 
5
- ## Provide components
5
+ ## Markdown editor UI
6
+ ![markdown editor](./assets/imgs/demo-markdown-editor.png)
6
7
 
8
+ ## Integrated markdown editor UI
9
+ > An integrated demo. You can customize it according to the style you design.
10
+
11
+ ![markdown editor](./assets/imgs/markdown-editor.png)
12
+
13
+ ## Installation
14
+ To install via npm:
15
+
16
+ ```bash
17
+ npm install @seafile/seafile-editor --save
18
+ ```
19
+
20
+ Import the library into your project:
21
+ ```javascript
22
+ import { MarkdownEditor } from '@seafile/seafile-editor';
23
+ ```
24
+
25
+ ## Provide components and functions
26
+
27
+ ### Components
28
+
29
+ |Name|Explain|
30
+ |-|-|
31
+ |MarkdownEditor|Markdown rich text editor component|
32
+ |MarkdownViewer|Markdown content preview component|
33
+
34
+ ### Functions
7
35
  |Name|Explain|
8
36
  |-|-|
9
- |MarkdownEditor|markdown Rich text editor component|
10
- |MarkdownViewer|markdown Content preview component|
37
+ |mdStringToSlate|Convert markdown strings to the data format used by the editor|
38
+ |slateToMdString|Convert the data format used by the editor to a markdown string|
39
+ |processor|Convert markdown string to html format content|
40
+
41
+ ## MarkdownEditor usage
42
+
43
+ ### Define api
44
+
45
+ ```javascript
46
+ import axios from 'axios';
47
+
48
+ class API {
49
+
50
+ getFileContent() {
51
+ const fileUrl = '';
52
+ return axios.get(fileUrl);
53
+ }
54
+
55
+ saveFileContent(content) {
56
+ const updateLink = '';
57
+ const formData = new FormData();
58
+ const blob = new Blob([data], { type: 'text/plain' });
59
+ formData.append('file', blob);
60
+ axios.post(updateLink, formData);
61
+ }
62
+
63
+ uploadLocalImage(file) {
64
+ const uploadLink = '';
65
+ const formData = new FormData();
66
+ formData.append('file', file);
67
+ return axios.post(uploadLink, formData);
68
+ }
11
69
 
12
- ## Instructions
70
+ }
71
+
72
+ const editorApi = new API();
73
+
74
+ export default editorApi;
75
+ ```
13
76
 
14
- 1. npm install @seafile/seafile-editor
15
- 2. code demo
77
+ ### Integrate simple into your own page
16
78
  ```javascript
79
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
80
+ import { Button } from 'reactstrap';
17
81
  import { MarkdownEditor } from '@seafile/seafile-editor';
82
+ import editorApi from './api';
18
83
 
19
- export default Editor = (props) => {
84
+ export default function SimpleMarkdownEditor() {
20
85
 
21
- return <MarkdownEditor {...props} />;
22
-
86
+ const editorRef = useRef(null);
87
+ const [fileContent, setFileContent] = useState('');
88
+ const [isFetching, setIsFetching] = useState(true);
89
+ const [contentVersion, setContentVersion] = useState(0);
90
+
91
+ const mathJaxSource = '';
92
+
93
+ useEffect(() => {
94
+ editorApi.getFileContent().then(res => {
95
+ setFileContent(res.data);
96
+ setIsFetching(false);
97
+ });
98
+ }, []);
99
+
100
+ const onSave = useCallback(() => {
101
+ const content = editorRef.current.getValue();
102
+ editorApi.saveFileContent(content).then(res => {
103
+ window.alert('Saved successfully')
104
+ });
105
+ }, []);
106
+
107
+ const onContentChanged = useCallback(() => {
108
+ setContentVersion(contentVersion + 1);
109
+ }, [contentVersion]);
110
+
111
+ return (
112
+ <div className='seafile-editor'>
113
+ <MarkdownEditor
114
+ ref={editorRef}
115
+ isFetching={isFetching}
116
+ value={fileContent}
117
+ initValue={''}
118
+ editorApi={editorApi}
119
+ onSave={onSave}
120
+ onContentChanged={onContentChanged}
121
+ mathJaxSource={mathJaxSource}
122
+ />
123
+ </div>
124
+ );
23
125
  }
126
+
127
+ ```
128
+
129
+ ### Props
130
+
131
+ Common props you may want to specify include:
132
+
133
+ * ref: A reference to the editor, used to obtain the current content in the editor
134
+ * ref.current.getValue: Get the current markdown string value in the editor
135
+ * ref.current.getSlateValue: Get the value of the current slate data format in the editor
136
+ * isFetching: Whether the value of the editor is being obtained, if the loading effect is displayed while obtaining, and if the acquisition is completed, the corresponding content obtained is displayed in the editor.
137
+ * value: The text content obtained
138
+ * initValue: If value does not exist, a default value can be provided via initValue
139
+ * onSave: When the editor content changes, the onSave callback event is triggered externally. The user can save the document by implementing this callback function.
140
+ * onContentChanged: When the editor content changes, a change event is triggered to facilitate the user to record whether the document
141
+ * mathJaxSource: Supports inserting formulas. If you want to support inserting formulas, please provide a path that can load formula resources. If support is not required, you can ignore this parameter. [math-jax document](https://docs.mathjax.org/en/stable/start.html)
142
+
143
+ ## Functions
144
+
145
+ ### `mdStringToSlate(mdString)`
146
+ Convert markdown string to data structure supported by editor (slate)
147
+
148
+ **Params**
149
+
150
+ * mdString: markdown string
151
+
152
+ **Returns**
153
+
154
+ &emsp; Slate nodes
155
+
156
+
157
+ ### `slateToMdString(slateNodes)`
158
+ Convert editor (slate) supported data structures to markdown string
159
+
160
+ **Params**
161
+
162
+ * slateNodes: slate nodes
163
+
164
+ **Returns**
165
+
166
+ &emsp; Markdown string
167
+
168
+ ### `processor` processor.process(mdString)
169
+ Convert markdown string to html
170
+
171
+ **Params**
172
+
173
+ * mdString: markdown string
174
+
175
+ **Returns**
176
+
177
+ &emsp;Promise
178
+
179
+ Demo
180
+ ```javascript
181
+ const string = '# Hello, I am first level title'
182
+ processor.process(string).then(result => {
183
+ const html = String(result);
184
+ ...
185
+ })
186
+
24
187
  ```
25
188
 
26
189
 
190
+ ## 🖥 Environment Support
191
+
192
+ * Modern browsers
193
+ * Software built-in browser
194
+
195
+ ### Modern browsers
196
+
197
+ | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br>Safari |
198
+ | --- | --- | --- | --- |
199
+ | Edge | false | last 2 versions | false |
200
+
201
+
202
+ ### Software built-in browser
203
+
204
+ **Mac OS**
205
+
206
+ | software | browser | version | internal | isSupport |
207
+ |-|-|-|-|-|
208
+ |<img src="./assets/imgs/wechat.png" width='16'> WeChat| Chrome |107.0.0.0| AppleWebKit/537.36 |false|
209
+ |<img src="./assets/imgs/wecom.png" width='16'> WeCom|Safari||AppleWebKit/605.1.15 |false|
210
+
211
+ **Windows OS**
212
+ > windows 11
213
+
214
+ | software | browser | version | internal | isSupport |
215
+ |-|-|-|-|-|
216
+ |<img src="./assets/imgs/wechat.png" width='16'> WeChat| Chrome |106.0.0.0| AppleWebKit/537.36 |false|
217
+ |<img src="./assets/imgs/wecom.png" width='16'> WeCom|Chrome|108.0.5993.119|AppleWebKit/537.36 |false|
218
+
219
+
220
+