@seafile/sea-email-editor 0.0.4 → 0.0.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.
Files changed (29) hide show
  1. package/dist/assets/icons/divider.svg +1 -0
  2. package/dist/extension/constants/element-default-style.js +7 -0
  3. package/dist/extension/constants/element-types.js +2 -1
  4. package/dist/extension/constants/menus-config.js +5 -0
  5. package/dist/extension/plugins/code-block/menu/index.js +15 -12
  6. package/dist/extension/plugins/divider/helper.js +38 -0
  7. package/dist/extension/plugins/divider/index.js +17 -0
  8. package/dist/extension/plugins/divider/menu/index.js +61 -0
  9. package/dist/extension/plugins/divider/plugin.js +87 -0
  10. package/dist/extension/plugins/divider/render-elem/index.css +4 -0
  11. package/dist/extension/plugins/divider/render-elem/index.js +44 -0
  12. package/dist/extension/plugins/image/menu/index.js +15 -12
  13. package/dist/extension/plugins/image/render-element/image-previewer.js +4 -1
  14. package/dist/extension/plugins/index.js +8 -1
  15. package/dist/extension/plugins/table/context-menu/index.css +1 -1
  16. package/dist/extension/plugins/table/context-menu/index.js +9 -3
  17. package/dist/extension/plugins/table/menu/index.js +15 -12
  18. package/dist/extension/plugins/table/render-elem/index.js +8 -3
  19. package/dist/extension/render/render-element.js +5 -0
  20. package/dist/extension/toolbar/insert-toolbar.js +3 -0
  21. package/dist/locale/lang/en.json +2 -1
  22. package/dist/slate-convert/html-to-slate/constants.js +7 -1
  23. package/dist/slate-convert/html-to-slate/index.js +18 -0
  24. package/dist/slate-convert/html-to-slate/rules/hr.js +23 -0
  25. package/dist/slate-convert/html-to-slate/rules/index.js +2 -1
  26. package/dist/slate-convert/html-to-slate/rules/list.js +39 -13
  27. package/dist/slate-convert/html-to-slate/rules/table.js +6 -2
  28. package/dist/slate-convert/slate-to-html/index.js +9 -4
  29. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1774854103046" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2163" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M960 464v96H64v-96h896z" fill="#000000" p-id="2164"></path></svg>
@@ -74,5 +74,12 @@ const ELEMENT_DEFAULT_STYLE = exports.ELEMENT_DEFAULT_STYLE = {
74
74
  },
75
75
  [ElementTypes.PARAGRAPH]: {
76
76
  lineHeight: 1.5
77
+ },
78
+ [ElementTypes.DIVIDER]: {
79
+ display: 'flex',
80
+ alignItems: 'center',
81
+ height: '13px',
82
+ width: '100%',
83
+ cursor: 'pointer'
77
84
  }
78
85
  };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.UNORDERED_LIST = exports.TABLE_ROW = exports.TABLE_CELL = exports.TABLE = exports.PARAGRAPH = exports.P = exports.ORDERED_LIST = exports.LIST_ITEM = exports.LINK = exports.IMAGE = exports.HEADER6 = exports.HEADER5 = exports.HEADER4 = exports.HEADER3 = exports.HEADER2 = exports.HEADER1 = exports.HEADER = exports.FORMULA = exports.CODE_LINE = exports.CODE_BLOCK = exports.CODE = exports.CHECK_LIST_ITEM = exports.BR = exports.BLOCKQUOTE = void 0;
6
+ exports.UNORDERED_LIST = exports.TABLE_ROW = exports.TABLE_CELL = exports.TABLE = exports.PARAGRAPH = exports.P = exports.ORDERED_LIST = exports.LIST_ITEM = exports.LINK = exports.IMAGE = exports.HEADER6 = exports.HEADER5 = exports.HEADER4 = exports.HEADER3 = exports.HEADER2 = exports.HEADER1 = exports.HEADER = exports.FORMULA = exports.DIVIDER = exports.CODE_LINE = exports.CODE_BLOCK = exports.CODE = exports.CHECK_LIST_ITEM = exports.BR = exports.BLOCKQUOTE = void 0;
7
7
  const BLOCKQUOTE = exports.BLOCKQUOTE = 'blockquote';
8
8
  const HEADER = exports.HEADER = 'header';
9
9
  // each header type should be start with HEADER, all of justices should based on HEADER
@@ -26,6 +26,7 @@ const TABLE_CELL = exports.TABLE_CELL = 'table_cell';
26
26
  const IMAGE = exports.IMAGE = 'image';
27
27
  const LINK = exports.LINK = 'link';
28
28
  const FORMULA = exports.FORMULA = 'formula';
29
+ const DIVIDER = exports.DIVIDER = 'divider';
29
30
  const P = exports.P = 'p';
30
31
  const BR = exports.BR = 'br';
31
32
 
@@ -138,5 +138,10 @@ const MENUS_CONFIG_MAP = exports.MENUS_CONFIG_MAP = {
138
138
  id: `sea_email_${CLEAR_FORMAT}`,
139
139
  icon: 'clear-format',
140
140
  text: 'Clear format'
141
+ },
142
+ [_elementTypes.DIVIDER]: {
143
+ id: `sea_email_${_elementTypes.DIVIDER}`,
144
+ icon: 'divider',
145
+ text: 'Divider'
141
146
  }
142
147
  };
@@ -35,18 +35,21 @@ const CodeBlockMenu = _ref => {
35
35
  }),
36
36
  id: menuConfig.id,
37
37
  onClick: onClick,
38
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
39
- icon: menuConfig.icon,
40
- className: "no-hover-bg sea-email-option-editor-option-icon",
41
- style: {
42
- marginLeft: 0,
43
- marginRight: 8
44
- },
45
- size: 16
46
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
47
- className: "text-truncate",
48
- title: (0, _constants2.gettext)(menuConfig.text),
49
- children: (0, _constants2.gettext)(menuConfig.text)
38
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
39
+ className: "sea-email-option-editor-option-content",
40
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
41
+ icon: menuConfig.icon,
42
+ className: "no-hover-bg sea-email-option-editor-option-icon",
43
+ style: {
44
+ marginLeft: 0,
45
+ marginRight: 8
46
+ },
47
+ size: 16
48
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
49
+ className: "text-truncate",
50
+ title: (0, _constants2.gettext)(menuConfig.text),
51
+ children: (0, _constants2.gettext)(menuConfig.text)
52
+ })]
50
53
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
51
54
  icon: '',
52
55
  className: "sea-email-option-editor-option-check-btn no-hover-bg",
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.transformToDivider = exports.isDisabled = exports.insertDivider = void 0;
7
+ var _slate = require("slate");
8
+ var _core = require("../../core");
9
+ var _constants = require("../../constants");
10
+ const isDisabled = (editor, readonly) => {
11
+ const {
12
+ selection
13
+ } = editor;
14
+ if (readonly || !selection) return true;
15
+ const disableTypes = [_constants.ElementTypes.TABLE, _constants.ElementTypes.TABLE_ROW, _constants.ElementTypes.TABLE_CELL, _constants.ElementTypes.FORMULA, _constants.ElementTypes.CODE_BLOCK, _constants.ElementTypes.BLOCKQUOTE, _constants.ElementTypes.UNORDERED_LIST, _constants.ElementTypes.ORDERED_LIST, _constants.ElementTypes.LIST_ITEM];
16
+ const [nodeEntry] = _slate.Editor.nodes(editor, {
17
+ match: n => disableTypes.includes(n.type),
18
+ mode: 'highest'
19
+ });
20
+ if (nodeEntry) return true;
21
+ return false;
22
+ };
23
+ exports.isDisabled = isDisabled;
24
+ const transformToDivider = editor => {
25
+ if (!editor.selection) return;
26
+ _slate.Transforms.setNodes(editor, {
27
+ type: _constants.ElementTypes.DIVIDER
28
+ });
29
+ (0, _core.focusEditor)(editor);
30
+ };
31
+ exports.transformToDivider = transformToDivider;
32
+ const insertDivider = editor => {
33
+ if (!editor.selection) return;
34
+ const dividerNode = (0, _core.generateElement)(_constants.ElementTypes.DIVIDER);
35
+ _slate.Transforms.insertNodes(editor, dividerNode);
36
+ (0, _core.focusEditor)(editor);
37
+ };
38
+ exports.insertDivider = insertDivider;
@@ -0,0 +1,17 @@
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 _elementTypes = require("../../constants/element-types");
9
+ var _plugin = _interopRequireDefault(require("./plugin"));
10
+ var _renderElem = _interopRequireDefault(require("./render-elem"));
11
+ const DividerPlugin = {
12
+ type: _elementTypes.DIVIDER,
13
+ nodeType: 'element',
14
+ editorPlugin: _plugin.default,
15
+ renderElements: [_renderElem.default]
16
+ };
17
+ var _default = exports.default = DividerPlugin;
@@ -0,0 +1,61 @@
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 _elementTypes = require("../../../constants/element-types");
12
+ var _constants = require("../../../constants");
13
+ var _components = require("../../../../components");
14
+ var _constants2 = require("../../../../constants");
15
+ var _helper = require("../helper");
16
+ var _jsxRuntime = require("react/jsx-runtime");
17
+ const menuConfig = _constants.MENUS_CONFIG_MAP[_elementTypes.DIVIDER];
18
+ const DividerMenu = _ref => {
19
+ let {
20
+ readonly,
21
+ editor,
22
+ toggle
23
+ } = _ref;
24
+ const disabled = (0, _react.useMemo)(() => (0, _helper.isDisabled)(editor, readonly), [readonly, editor]);
25
+ const onClick = (0, _react.useCallback)(e => {
26
+ if (disabled) return;
27
+ e.preventDefault();
28
+ (0, _helper.insertDivider)(editor);
29
+ toggle && toggle();
30
+ }, [disabled, editor, toggle]);
31
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
32
+ className: (0, _classnames.default)('sea-email-option-editor-option', {
33
+ 'disabled': disabled
34
+ }),
35
+ id: menuConfig.id,
36
+ onClick: onClick,
37
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
38
+ className: "sea-email-option-editor-option-content",
39
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
40
+ icon: menuConfig.icon,
41
+ className: "no-hover-bg sea-email-option-editor-option-icon",
42
+ style: {
43
+ marginLeft: 0,
44
+ marginRight: 8
45
+ },
46
+ size: 16
47
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
48
+ className: "text-truncate",
49
+ title: (0, _constants2.gettext)(menuConfig.text),
50
+ children: (0, _constants2.gettext)(menuConfig.text)
51
+ })]
52
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
53
+ icon: '',
54
+ className: "sea-email-option-editor-option-check-btn no-hover-bg",
55
+ style: {
56
+ marginLeft: 12
57
+ }
58
+ })]
59
+ });
60
+ };
61
+ var _default = exports.default = DividerMenu;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _slate = require("slate");
8
+ var _constants = require("../../constants");
9
+ var _core = require("../../core");
10
+ var _elementTypes = require("../../constants/element-types");
11
+ const HR_PATTERNS = ['---', '***', '___'];
12
+ const withDivider = editor => {
13
+ const {
14
+ isVoid,
15
+ insertText,
16
+ normalizeNode
17
+ } = editor;
18
+ const newEditor = editor;
19
+ newEditor.isVoid = element => {
20
+ const {
21
+ type
22
+ } = element;
23
+ if (type === _constants.ElementTypes.DIVIDER) return true;
24
+ return isVoid(element);
25
+ };
26
+ newEditor.insertText = text => {
27
+ const {
28
+ selection
29
+ } = newEditor;
30
+ if (!selection || !_slate.Range.isCollapsed(selection)) {
31
+ insertText(text);
32
+ return;
33
+ }
34
+ const [blockEntry] = _slate.Editor.nodes(newEditor, {
35
+ at: selection,
36
+ match: n => _slate.Element.isElement(n) && (n.type === _constants.ElementTypes.PARAGRAPH || n.type === _constants.ElementTypes.P)
37
+ });
38
+ if (!blockEntry) {
39
+ insertText(text);
40
+ return;
41
+ }
42
+ const [blockNode, blockPath] = blockEntry;
43
+ const blockText = _slate.Node.string(blockNode);
44
+ const nextText = blockText + text;
45
+ if (HR_PATTERNS.includes(nextText)) {
46
+ _slate.Editor.withoutNormalizing(newEditor, () => {
47
+ _slate.Transforms.removeNodes(newEditor, {
48
+ at: blockPath
49
+ });
50
+ _slate.Transforms.insertNodes(newEditor, (0, _core.generateEmptyElement)(_constants.ElementTypes.DIVIDER), {
51
+ at: blockPath
52
+ });
53
+ const nextPath = _slate.Path.next(blockPath);
54
+ _slate.Transforms.insertNodes(newEditor, (0, _core.generateEmptyElement)(_constants.ElementTypes.PARAGRAPH), {
55
+ at: nextPath
56
+ });
57
+ _slate.Transforms.select(newEditor, _slate.Editor.start(newEditor, nextPath));
58
+ });
59
+ return;
60
+ }
61
+ return insertText(text);
62
+ };
63
+ newEditor.normalizeNode = _ref => {
64
+ let [node, path] = _ref;
65
+ if (node.type === _elementTypes.DIVIDER) {
66
+ const isLast = (0, _core.isLastNode)(newEditor, node);
67
+ if (isLast) {
68
+ const paragraph = (0, _core.generateEmptyElement)(_elementTypes.PARAGRAPH);
69
+ _slate.Transforms.insertNodes(newEditor, paragraph, {
70
+ at: [path[0] + 1]
71
+ });
72
+ return;
73
+ }
74
+ const isFirst = (0, _core.isFirstNode)(newEditor, node);
75
+ if (isFirst) {
76
+ const paragraph = (0, _core.generateEmptyElement)(_elementTypes.PARAGRAPH);
77
+ _slate.Transforms.insertNodes(newEditor, paragraph, {
78
+ at: [path[0]]
79
+ });
80
+ return;
81
+ }
82
+ }
83
+ return normalizeNode([node, path]);
84
+ };
85
+ return newEditor;
86
+ };
87
+ var _default = exports.default = withDivider;
@@ -0,0 +1,4 @@
1
+ .sea-email-editor-divider-highlight {
2
+ border-radius: 4px;
3
+ background-color: Highlight;
4
+ }
@@ -0,0 +1,44 @@
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 _slateReact = require("slate-react");
10
+ var _classnames = _interopRequireDefault(require("classnames"));
11
+ var _constants = require("../../../constants");
12
+ require("./index.css");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ /* eslint-disable react-hooks/rules-of-hooks */
15
+
16
+ const renderDivider = _ref => {
17
+ let {
18
+ attributes,
19
+ children,
20
+ element
21
+ } = _ref;
22
+ const isSelected = (0, _slateReact.useSelected)();
23
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
24
+ "data-id": element.id,
25
+ className: (0, _classnames.default)(element.className, {
26
+ 'sea-email-editor-divider-highlight': isSelected
27
+ }),
28
+ ...attributes,
29
+ style: {
30
+ ...(_constants.ELEMENT_DEFAULT_STYLE[element.type] || {}),
31
+ ...((element === null || element === void 0 ? void 0 : element.style) || {})
32
+ },
33
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
34
+ style: {
35
+ width: '100%',
36
+ height: 1,
37
+ backgroundColor: '#ccc',
38
+ margin: '5px 0'
39
+ },
40
+ contentEditable: false
41
+ }), children]
42
+ });
43
+ };
44
+ var _default = exports.default = renderDivider;
@@ -47,18 +47,21 @@ const ImageMenu = _ref => {
47
47
  }),
48
48
  ref: domRef,
49
49
  id: menuConfig.id,
50
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
51
- icon: menuConfig.icon,
52
- className: "no-hover-bg sea-email-option-editor-option-icon",
53
- style: {
54
- marginLeft: 0,
55
- marginRight: 8
56
- },
57
- size: 16
58
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
59
- className: "text-truncate",
60
- title: (0, _constants.gettext)(menuConfig.text),
61
- children: (0, _constants.gettext)(menuConfig.text)
50
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
51
+ className: "sea-email-option-editor-option-content",
52
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
53
+ icon: menuConfig.icon,
54
+ className: "no-hover-bg sea-email-option-editor-option-icon",
55
+ style: {
56
+ marginLeft: 0,
57
+ marginRight: 8
58
+ },
59
+ size: 16
60
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
61
+ className: "text-truncate",
62
+ title: (0, _constants.gettext)(menuConfig.text),
63
+ children: (0, _constants.gettext)(menuConfig.text)
64
+ })]
62
65
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
63
66
  icon: readonly ? '' : 'arrow-right',
64
67
  className: "sea-email-option-editor-option-check-btn no-hover-bg",
@@ -10,6 +10,7 @@ var _react = _interopRequireWildcard(require("react"));
10
10
  var _slateReact = require("slate-react");
11
11
  var _reactImageLightbox = _interopRequireDefault(require("@seafile/react-image-lightbox"));
12
12
  var _helper = require("../helper");
13
+ var _constants = require("../../../../constants");
13
14
  require("@seafile/react-image-lightbox/style.css");
14
15
  require("./index.css");
15
16
  var _jsxRuntime = require("react/jsx-runtime");
@@ -56,7 +57,9 @@ const ImagePreviewer = _ref => {
56
57
  overlay: {
57
58
  zIndex: 1071
58
59
  }
59
- }
60
+ },
61
+ zoomInTip: (0, _constants.gettext)('Zoom in'),
62
+ zoomOutTip: (0, _constants.gettext)('Zoom out')
60
63
  });
61
64
  };
62
65
  var _default = exports.default = ImagePreviewer;
@@ -22,6 +22,12 @@ Object.defineProperty(exports, "CodeBlockPlugin", {
22
22
  return _codeBlock.default;
23
23
  }
24
24
  });
25
+ Object.defineProperty(exports, "DividerPlugin", {
26
+ enumerable: true,
27
+ get: function () {
28
+ return _divider.default;
29
+ }
30
+ });
25
31
  Object.defineProperty(exports, "FormulaPlugin", {
26
32
  enumerable: true,
27
33
  get: function () {
@@ -110,7 +116,8 @@ var _formula = _interopRequireDefault(require("./formula"));
110
116
  var _markdown = _interopRequireDefault(require("./markdown"));
111
117
  var _html = _interopRequireDefault(require("./html"));
112
118
  var _p = _interopRequireDefault(require("./p"));
113
- const Plugins = [_paragraph.default, _textStyle.default, _header.default, _image.default, _checkList.default, _list.default, _codeBlock.default, _table.default, _blockquote.default, _link.default, _formula.default, _markdown.default, _html.default, _p.default,
119
+ var _divider = _interopRequireDefault(require("./divider"));
120
+ const Plugins = [_paragraph.default, _textStyle.default, _header.default, _image.default, _checkList.default, _list.default, _codeBlock.default, _table.default, _blockquote.default, _link.default, _formula.default, _markdown.default, _html.default, _p.default, _divider.default,
114
121
  // put at the end
115
122
  _nodeId.default];
116
123
  var _default = exports.default = Plugins;
@@ -1,7 +1,7 @@
1
1
  .sea-email-table-context-menu {
2
2
  height: fit-content;
3
3
  width: fit-content;
4
- position: absolute;
4
+ position: fixed;
5
5
  }
6
6
 
7
7
  .sea-email-table-context-menu .popover {
@@ -45,9 +45,15 @@ const ContextMenu = _ref => {
45
45
  top,
46
46
  left
47
47
  } = position;
48
+ const {
49
+ width,
50
+ height
51
+ } = contextMenuRef.current.getBoundingClientRect();
52
+ const validTop = window.innerHeight - top >= height ? top : window.innerHeight - height;
53
+ const validLeft = window.innerWidth - left >= width ? left : window.innerWidth - width;
48
54
  setContextMenuStyle({
49
- top,
50
- left,
55
+ top: validTop,
56
+ left: validLeft,
51
57
  zIndex: '1071',
52
58
  display: 'block'
53
59
  });
@@ -66,11 +72,11 @@ const ContextMenu = _ref => {
66
72
  };
67
73
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
68
74
  contentEditable: false,
69
- ref: contextMenuRef,
70
75
  style: contextMenuStyle,
71
76
  className: "sea-email-option-editor-popover show sea-email-table-context-menu",
72
77
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
73
78
  className: "popover show bs-popover-auto",
79
+ ref: contextMenuRef,
74
80
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
75
81
  className: "popover-inner",
76
82
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
@@ -32,18 +32,21 @@ const TableMenu = _ref => {
32
32
  }),
33
33
  ref: domRef,
34
34
  id: menuConfig.id,
35
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
36
- icon: menuConfig.icon,
37
- className: "no-hover-bg sea-email-option-editor-option-icon",
38
- style: {
39
- marginLeft: 0,
40
- marginRight: 8
41
- },
42
- size: 16
43
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
44
- className: "text-truncate",
45
- title: (0, _constants2.gettext)(menuConfig.text),
46
- children: (0, _constants2.gettext)(menuConfig.text)
35
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
36
+ className: "sea-email-option-editor-option-content",
37
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
38
+ icon: menuConfig.icon,
39
+ className: "no-hover-bg sea-email-option-editor-option-icon",
40
+ style: {
41
+ marginLeft: 0,
42
+ marginRight: 8
43
+ },
44
+ size: 16
45
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
46
+ className: "text-truncate",
47
+ title: (0, _constants2.gettext)(menuConfig.text),
48
+ children: (0, _constants2.gettext)(menuConfig.text)
49
+ })]
47
50
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.IconButton, {
48
51
  icon: disabled ? '' : 'arrow-right',
49
52
  className: "sea-email-option-editor-option-check-btn no-hover-bg",
@@ -12,7 +12,6 @@ var _slate = require("slate");
12
12
  var _classnames = _interopRequireDefault(require("classnames"));
13
13
  var _constant = require("../constant");
14
14
  var _contextMenu = _interopRequireDefault(require("../context-menu"));
15
- var _helper = require("../helper");
16
15
  var _core = require("../../../core");
17
16
  var _constants = require("../../../constants");
18
17
  var _eventBus = _interopRequireDefault(require("../../../../utils/event-bus"));
@@ -165,8 +164,14 @@ const RenderTableContainer = (_ref, editor) => {
165
164
  }
166
165
  e.preventDefault();
167
166
  e.stopPropagation();
168
- const position = (0, _helper.getContextMenuPosition)(e, tableRef);
169
- setContextMenuPosition(position);
167
+ const {
168
+ clientY,
169
+ clientX
170
+ } = e;
171
+ setContextMenuPosition({
172
+ left: clientX,
173
+ top: clientY
174
+ });
170
175
  setIsShowContextMenu(true);
171
176
  }, []);
172
177
  const handleCloseContextMenu = () => {
@@ -100,6 +100,11 @@ const SlateElement = _ref => {
100
100
  const [renderP] = _plugins.PPlugin.renderElements;
101
101
  return renderP(props);
102
102
  }
103
+ case _constants.ElementTypes.DIVIDER:
104
+ {
105
+ const [renderDivider] = _plugins.DividerPlugin.renderElements;
106
+ return renderDivider(props);
107
+ }
103
108
  default:
104
109
  {
105
110
  const [renderParagraph] = _plugins.ParagraphPlugin.renderElements;
@@ -10,6 +10,7 @@ var _react = _interopRequireWildcard(require("react"));
10
10
  var _menu = _interopRequireDefault(require("../plugins/image/menu"));
11
11
  var _menu2 = _interopRequireDefault(require("../plugins/table/menu"));
12
12
  var _menu3 = _interopRequireDefault(require("../plugins/code-block/menu"));
13
+ var _menu4 = _interopRequireDefault(require("../plugins/divider/menu"));
13
14
  var _constants = require("../../constants");
14
15
  var _components = require("../../components");
15
16
  var _jsxRuntime = require("react/jsx-runtime");
@@ -69,6 +70,8 @@ const InsertToolbar = _ref => {
69
70
  ...props
70
71
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_menu3.default, {
71
72
  ...props
73
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_menu4.default, {
74
+ ...props
72
75
  })]
73
76
  })
74
77
  })
@@ -79,5 +79,6 @@
79
79
  "Underline": "Underline",
80
80
  "Row number": "Row number",
81
81
  "Column number": "Column number",
82
- "Copy link": "Copy link"
82
+ "Copy link": "Copy link",
83
+ "Divider": "Divider"
83
84
  }
@@ -33,6 +33,12 @@ Object.defineProperty(exports, "CODE_LINE", {
33
33
  return _elementTypes.CODE_LINE;
34
34
  }
35
35
  });
36
+ Object.defineProperty(exports, "DIVIDER", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _elementTypes.DIVIDER;
40
+ }
41
+ });
36
42
  Object.defineProperty(exports, "HEADER1", {
37
43
  enumerable: true,
38
44
  get: function () {
@@ -133,7 +139,7 @@ Object.defineProperty(exports, "UNORDERED_LIST", {
133
139
  }
134
140
  });
135
141
  var _elementTypes = require("../../extension/constants/element-types");
136
- const TOP_LEVEL_TYPES = exports.TOP_LEVEL_TYPES = [_elementTypes.BLOCKQUOTE, _elementTypes.HEADER1, _elementTypes.HEADER2, _elementTypes.HEADER3, _elementTypes.HEADER4, _elementTypes.HEADER5, _elementTypes.HEADER6, _elementTypes.ORDERED_LIST, _elementTypes.UNORDERED_LIST, _elementTypes.CHECK_LIST_ITEM, _elementTypes.PARAGRAPH, _elementTypes.CODE_BLOCK, _elementTypes.TABLE];
142
+ const TOP_LEVEL_TYPES = exports.TOP_LEVEL_TYPES = [_elementTypes.BLOCKQUOTE, _elementTypes.HEADER1, _elementTypes.HEADER2, _elementTypes.HEADER3, _elementTypes.HEADER4, _elementTypes.HEADER5, _elementTypes.HEADER6, _elementTypes.ORDERED_LIST, _elementTypes.UNORDERED_LIST, _elementTypes.CHECK_LIST_ITEM, _elementTypes.PARAGRAPH, _elementTypes.CODE_BLOCK, _elementTypes.TABLE, _elementTypes.P, _elementTypes.BR, _elementTypes.DIVIDER];
137
143
  const INLINE_LEVEL_TYPES = exports.INLINE_LEVEL_TYPES = [_elementTypes.IMAGE, _elementTypes.LINK];
138
144
  const HEADER_LIST = exports.HEADER_LIST = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
139
145
  const HEADER_TYPE_MAP = exports.HEADER_TYPE_MAP = {
@@ -78,6 +78,24 @@ const deserializeElements = function () {
78
78
  });
79
79
  return (0, _helper.formatInlineNodes)(nodes);
80
80
  };
81
+
82
+ // const formatTableNode = (node, path) => {
83
+ // if (node.type === TABLE) {
84
+ // const columnsCount = Math.max(...node.children.map(row => row.children.length));
85
+ // node.children = node.children.map(row => {
86
+ // for (let i = row.children.length; i < columnsCount; i++) {
87
+ // row.children.push(generateTableCell());
88
+ // }
89
+ // return row;
90
+ // });
91
+ // return node;
92
+ // }
93
+ // if (Array.isArray(node.children)) {
94
+ // node.children = node.children.map((child, index) => formatTableNode(child, [...path, index]));
95
+ // }
96
+ // return node;
97
+ // };
98
+
81
99
  const formatElementNodes = nodes => {
82
100
  if (nodes.length === 0) {
83
101
  return [{
@@ -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 = void 0;
8
+ var _slugid = _interopRequireDefault(require("slugid"));
9
+ var _constants = require("../constants");
10
+ const hrRule = element => {
11
+ if (element.nodeName === 'HR') {
12
+ return {
13
+ id: _slugid.default.nice(),
14
+ type: _constants.DIVIDER,
15
+ children: [{
16
+ id: _slugid.default.nice(),
17
+ text: ''
18
+ }]
19
+ };
20
+ }
21
+ return;
22
+ };
23
+ var _default = exports.default = hrRule;
@@ -16,5 +16,6 @@ var _table = _interopRequireDefault(require("./table"));
16
16
  var _text = _interopRequireDefault(require("./text"));
17
17
  var _br = _interopRequireDefault(require("./br"));
18
18
  var _p = _interopRequireDefault(require("./p"));
19
- const rules = [_blockquote.default, _codeBlock.default, _header.default, _image.default, _link.default, _list.default, _table.default, _paragraph.default, _text.default, _br.default, _p.default];
19
+ var _hr = _interopRequireDefault(require("./hr"));
20
+ const rules = [_blockquote.default, _codeBlock.default, _header.default, _image.default, _link.default, _list.default, _table.default, _paragraph.default, _text.default, _br.default, _p.default, _hr.default];
20
21
  var _default = exports.default = rules;
@@ -33,23 +33,49 @@ const listRule = (element, parseChild) => {
33
33
  };
34
34
  return (0, _helper.mergeElementOther2SlateNode)(element, node);
35
35
  }
36
- if (nodeName === 'LI' && firstChild && PARAGRAPH_TAGS.includes(firstChild.nodeName)) {
37
- const node = {
38
- id: _slugid.default.nice(),
39
- type: _constants.LIST_ITEM,
40
- children: parseChild(childNodes)
36
+ if (nodeName === 'LI') {
37
+ const parsedChildren = parseChild(childNodes);
38
+ const normalizedChildren = Array.isArray(parsedChildren) ? parsedChildren : parsedChildren ? [parsedChildren] : [];
39
+ const listItemChildren = [];
40
+ let inlineChildren = [];
41
+ const appendInlineParagraph = () => {
42
+ if (inlineChildren.length === 0) return;
43
+ listItemChildren.push({
44
+ id: _slugid.default.nice(),
45
+ type: _constants.PARAGRAPH,
46
+ children: inlineChildren
47
+ });
48
+ inlineChildren = [];
41
49
  };
42
- return (0, _helper.mergeElementOther2SlateNode)(element, node);
43
- }
44
- if (nodeName === 'LI' && firstChild && !PARAGRAPH_TAGS.includes(firstChild.nodeName)) {
50
+ normalizedChildren.forEach(child => {
51
+ if (!child) return;
52
+ const isInlineNode = !child.type || _constants.INLINE_LEVEL_TYPES.includes(child.type);
53
+ if (isInlineNode) {
54
+ inlineChildren.push(child);
55
+ return;
56
+ }
57
+ appendInlineParagraph();
58
+ listItemChildren.push(child);
59
+ });
60
+ appendInlineParagraph();
61
+ if (listItemChildren.length === 0) {
62
+ listItemChildren.push({
63
+ id: _slugid.default.nice(),
64
+ type: _constants.PARAGRAPH,
65
+ children: [(0, _core.generateDefaultText)()]
66
+ });
67
+ } else if ([_constants.UNORDERED_LIST, _constants.ORDERED_LIST].includes(listItemChildren[0].type)) {
68
+ // Ensure nested list item content starts with a paragraph.
69
+ listItemChildren.unshift({
70
+ id: _slugid.default.nice(),
71
+ type: _constants.PARAGRAPH,
72
+ children: [(0, _core.generateDefaultText)()]
73
+ });
74
+ }
45
75
  const node = {
46
76
  id: _slugid.default.nice(),
47
77
  type: _constants.LIST_ITEM,
48
- children: [{
49
- id: _slugid.default.nice(),
50
- type: _constants.PARAGRAPH,
51
- children: parseChild(childNodes)
52
- }]
78
+ children: listItemChildren
53
79
  };
54
80
  return (0, _helper.mergeElementOther2SlateNode)(element, node);
55
81
  }
@@ -39,7 +39,7 @@ const tableRule = (element, parseChild) => {
39
39
  }
40
40
  if (nodeName === 'TH' || nodeName === 'TD') {
41
41
  const children = Array.from(childNodes);
42
- const cellChildren = children.flatMap(child => {
42
+ const cellChildren = children.length > 0 ? children.flatMap(child => {
43
43
  // Replace paragraph node with text node
44
44
  if (child.nodeName === 'P') {
45
45
  const textContent = Array.from(child.childNodes).map(child => child.textContent).join('');
@@ -51,7 +51,11 @@ const tableRule = (element, parseChild) => {
51
51
  return (0, _helper.mergeElementOther2SlateNode)(child, node);
52
52
  }
53
53
  return parseChild([child]);
54
- });
54
+ }) : [{
55
+ id: _slugid.default.nice(),
56
+ type: 'text',
57
+ text: ''
58
+ }];
55
59
  const node = {
56
60
  id: _slugid.default.nice(),
57
61
  type: _constants.TABLE_CELL,
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.findElementByPath = exports.default = void 0;
7
7
  var _slate = require("slate");
8
8
  var _constants = require("../../extension/constants");
9
9
  const isContentValid = value => {
@@ -70,11 +70,13 @@ const ELEMENT_HTML_TAG = {
70
70
  [_constants.ElementTypes.LINK]: 'a',
71
71
  [_constants.ElementTypes.TABLE]: 'table',
72
72
  [_constants.ElementTypes.TABLE_ROW]: 'tr',
73
- [_constants.ElementTypes.TABLE_CELL]: 'td'
73
+ [_constants.ElementTypes.TABLE_CELL]: 'td',
74
+ [_constants.ElementTypes.DIVIDER]: 'div'
74
75
  };
75
76
  const findElementByPath = (value, path) => {
76
- return path.reduce((element, pathIndex) => element[pathIndex], value);
77
+ return path.reduce((element, pathIndex, currentIndex) => currentIndex === 0 ? element[pathIndex] : element === null || element === void 0 ? void 0 : element.children[pathIndex], value);
77
78
  };
79
+ exports.findElementByPath = findElementByPath;
78
80
  const element2Html = (value, element, path) => {
79
81
  const {
80
82
  type
@@ -85,10 +87,13 @@ const element2Html = (value, element, path) => {
85
87
  style,
86
88
  children
87
89
  } = translateElement(value, element, path);
88
- if (tag === 'img') {
90
+ if (type === _constants.ElementTypes.IMAGE) {
89
91
  var _element$data, _element$data2;
90
92
  return `<img src="${element === null || element === void 0 ? void 0 : (_element$data = element.data) === null || _element$data === void 0 ? void 0 : _element$data.src}" width="${element === null || element === void 0 ? void 0 : element.data.width}" height="${element === null || element === void 0 ? void 0 : element.data.height}" alt="${(element === null || element === void 0 ? void 0 : (_element$data2 = element.data) === null || _element$data2 === void 0 ? void 0 : _element$data2.alt) || ''}" />`;
91
93
  }
94
+ if (type === _constants.ElementTypes.DIVIDER) {
95
+ return `<div ${className}${style}><div style="width: 100%; height: 1px; background-color: #ccc; margin: 5px 0;"></div></div>`;
96
+ }
92
97
  if (Array.isArray(children) && tag) {
93
98
  const childrenDom = children.map((child, index) => element2Html(value, child, [...path, index])).join('');
94
99
  if (tag === 'a') return `<${tag}${className}${style} href="${element.url}">${childrenDom}</${tag}>`;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@seafile/sea-email-editor",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "dependencies": {
7
- "@seafile/react-image-lightbox": "4.0.2",
7
+ "@seafile/react-image-lightbox": "^5.0.4",
8
8
  "classnames": "2.3.2",
9
9
  "copy-to-clipboard": "3.3.1",
10
10
  "deep-copy": "1.4.2",