@seafile/sdoc-editor 0.3.27 → 0.3.28

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.
@@ -22,6 +22,7 @@ export const LINK = 'link';
22
22
  export const SDOC_LINK = 'sdoc_link';
23
23
  export const FILE_LINK = 'file_link';
24
24
  export const IMAGE = 'image';
25
+ export const IMAGE_BLOCK = 'image_block';
25
26
  export const CALL_OUT = 'callout';
26
27
 
27
28
  // font
@@ -1,6 +1,6 @@
1
1
  // extension plugin
2
2
  import * as ELEMENT_TYPE from './element-type';
3
- import { BLOCKQUOTE, TITLE, SUBTITLE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE, TABLE, TABLE_CELL, TABLE_ROW, LINK, SDOC_LINK, FILE_LINK, IMAGE, TOP_LEVEL_TYPES, INLINE_LEVEL_TYPES, CALL_OUT } from './element-type';
3
+ import { BLOCKQUOTE, TITLE, SUBTITLE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE, TABLE, TABLE_CELL, TABLE_ROW, LINK, SDOC_LINK, FILE_LINK, IMAGE, IMAGE_BLOCK, TOP_LEVEL_TYPES, INLINE_LEVEL_TYPES, CALL_OUT } from './element-type';
4
4
  export { DEFAULT_COLORS, STANDARD_COLORS, DEFAULT_RECENT_USED_LIST, DEFAULT_FONT_COLOR, RECENT_USED_HIGHLIGHT_COLORS_KEY, RECENT_USED_FONT_COLORS_KEY, RECENT_USED_TABLE_CELL_BACKGROUND_COLORS_KEY, DEFAULT_LAST_USED_FONT_COLOR, DEFAULT_LAST_USED_HIGHLIGHT_COLOR, DEFAULT_LAST_USED_TABLE_CELL_BACKGROUND_COLOR } from './color';
5
5
  export { FONT_SIZE, DEFAULT_FONT, FONT, GOOGLE_FONT_CLASS, RECENT_USED_FONTS_KEY, SDOC_FONT_SIZE } from './font';
6
6
  export { DIFF_TYPE, ADDED_STYLE, DELETED_STYLE } from './diff-view';
@@ -55,4 +55,4 @@ export const MOUSE_ENTER_EVENT_DISABLED_MAP = {
55
55
  [HEADER6]: [CALL_OUT],
56
56
  [CALL_OUT]: [CALL_OUT]
57
57
  };
58
- export { ELEMENT_TYPE, BLOCKQUOTE, TITLE, SUBTITLE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE, TABLE, TABLE_CELL, TABLE_ROW, LINK, SDOC_LINK, FILE_LINK, IMAGE, TOP_LEVEL_TYPES, INLINE_LEVEL_TYPES, CALL_OUT };
58
+ export { ELEMENT_TYPE, BLOCKQUOTE, TITLE, SUBTITLE, HEADER, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, PARAGRAPH, ORDERED_LIST, UNORDERED_LIST, LIST_ITEM, CHECK_LIST_ITEM, CODE_BLOCK, CODE_LINE, TABLE, TABLE_CELL, TABLE_ROW, LINK, SDOC_LINK, FILE_LINK, IMAGE, IMAGE_BLOCK, TOP_LEVEL_TYPES, INLINE_LEVEL_TYPES, CALL_OUT };
@@ -1,7 +1,13 @@
1
1
  import blackBorder from '../../../../assets/images/black-border.png';
2
2
  import greyBorder from '../../../../assets/images/grey-border.png';
3
3
  import noBorder from '../../../../assets/images/no-border.png';
4
- export const IMAGE_DISPLAY_TYPE = ['Inline', 'Block'];
4
+ export const IMAGE_DISPLAY_TYPE = [{
5
+ text: 'Inline',
6
+ value: 'paragraph'
7
+ }, {
8
+ text: 'Block',
9
+ value: 'image_block'
10
+ }];
5
11
  export const IMAGE_BORDER_TYPE = [{
6
12
  type: 'none',
7
13
  imgUrl: noBorder,
@@ -1,31 +1,35 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import React, { useCallback, useEffect, useState } from 'react';
3
- import { Transforms } from '@seafile/slate';
3
+ import { Editor, Transforms } from '@seafile/slate';
4
4
  import { ReactEditor } from '@seafile/slate-react';
5
5
  import { withTranslation } from 'react-i18next';
6
6
  import classnames from 'classnames';
7
7
  import { ElementPopover } from '../../../commons';
8
8
  import Tooltip from '../../../../../components/tooltip';
9
9
  import ImagePreviewer from '../dialogs/image-previewer';
10
+ import { generateEmptyElement } from '../../../core';
10
11
  import { getImageURL } from '../helpers';
11
12
  import { IMAGE_DISPLAY_TYPE, IMAGE_BORDER_TYPE } from '../constants';
12
- import { MENUS_CONFIG_MAP, TEXT_ALIGN } from '../../../constants';
13
+ import { MENUS_CONFIG_MAP, TEXT_ALIGN, PARAGRAPH, IMAGE_BLOCK } from '../../../constants';
13
14
  import './index.css';
14
15
  const ImageHoverMenu = _ref => {
15
16
  let {
16
17
  editor,
17
18
  menuPosition,
18
19
  element,
20
+ parentNodeEntry,
19
21
  onHideImageHoverMenu,
20
22
  onShowCaption,
21
23
  t
22
24
  } = _ref;
23
25
  const {
24
26
  data,
25
- display_type = IMAGE_DISPLAY_TYPE[0],
26
- align,
27
27
  border_type = IMAGE_BORDER_TYPE[0].type
28
28
  } = element;
29
+ const {
30
+ align = 'left',
31
+ type
32
+ } = parentNodeEntry[0];
29
33
  const {
30
34
  caption = ''
31
35
  } = data;
@@ -55,11 +59,73 @@ const ImageHoverMenu = _ref => {
55
59
  event.stopPropagation();
56
60
  const path = ReactEditor.findPath(editor, element);
57
61
  if (path) {
58
- Transforms.setNodes(editor, props, {
59
- at: path
60
- });
62
+ if (props['display_type'] === IMAGE_BLOCK && type === PARAGRAPH) {
63
+ // Remove old node
64
+ const nodeEntry = Editor.node(editor, [path[0]]);
65
+ const newNodeEntry = JSON.parse(JSON.stringify(nodeEntry.slice(0)));
66
+ Transforms.removeNodes(editor, {
67
+ at: [path[0]]
68
+ });
69
+ // Insert new node
70
+ const index = newNodeEntry[0].children.findIndex(item => item.id === element.id);
71
+ const beforeLeaf = newNodeEntry[0].children.slice(0, index);
72
+ const imageLeaf = newNodeEntry[0].children.slice(index, index + 1);
73
+ const afterLeaf = newNodeEntry[0].children.slice(index + 1);
74
+ let beforeNode = null,
75
+ centerNode = null,
76
+ afterNode = null;
77
+ let p = path[0];
78
+ if (!beforeLeaf.every(item => item.text.length === 0)) {
79
+ beforeNode = generateEmptyElement(PARAGRAPH);
80
+ beforeNode.children = beforeLeaf;
81
+ Transforms.insertNodes(editor, beforeNode, {
82
+ at: [p]
83
+ });
84
+ p = p + 1;
85
+ }
86
+ centerNode = generateEmptyElement(IMAGE_BLOCK);
87
+ centerNode.children = imageLeaf;
88
+ Transforms.insertNodes(editor, centerNode, {
89
+ at: [p]
90
+ });
91
+ p = p + 1;
92
+ if (!afterLeaf.every(item => item.text.length === 0)) {
93
+ afterNode = generateEmptyElement(PARAGRAPH);
94
+ afterNode.children = afterLeaf;
95
+ Transforms.insertNodes(editor, afterNode, {
96
+ at: [p]
97
+ });
98
+ }
99
+ return;
100
+ }
101
+ if (props['display_type'] === PARAGRAPH && type === IMAGE_BLOCK) {
102
+ const nodeEntry = Editor.node(editor, [path[0]]);
103
+ const newNodeEntry = JSON.parse(JSON.stringify(nodeEntry.slice(0)));
104
+ Transforms.removeNodes(editor, {
105
+ at: [path[0]]
106
+ });
107
+ const newNode = generateEmptyElement(PARAGRAPH);
108
+ newNode.children = newNodeEntry[0].children;
109
+ Transforms.insertNodes(editor, newNode, {
110
+ at: [path[0]]
111
+ });
112
+ return;
113
+ }
114
+ if (props['align']) {
115
+ Transforms.setNodes(editor, props, {
116
+ at: [path[0]]
117
+ });
118
+ onHideImageHoverMenu();
119
+ return;
120
+ }
121
+ if (props['border_type']) {
122
+ Transforms.setNodes(editor, props, {
123
+ at: path
124
+ });
125
+ onHideImageHoverMenu();
126
+ return;
127
+ }
61
128
  }
62
- onHideImageHoverMenu();
63
129
  // eslint-disable-next-line react-hooks/exhaustive-deps
64
130
  }, []);
65
131
  return /*#__PURE__*/React.createElement(ElementPopover, null, /*#__PURE__*/React.createElement("div", {
@@ -79,11 +145,11 @@ const ImageHoverMenu = _ref => {
79
145
  }
80
146
  }, /*#__PURE__*/React.createElement("span", {
81
147
  className: "mr-1"
82
- }, t(display_type || IMAGE_DISPLAY_TYPE[0])), /*#__PURE__*/React.createElement("i", {
148
+ }, t(type === IMAGE_BLOCK ? 'Block' : 'Inline')), /*#__PURE__*/React.createElement("i", {
83
149
  className: "sdocfont sdoc-drop-down icon-font"
84
150
  }))), /*#__PURE__*/React.createElement("span", {
85
151
  className: "op-group-item"
86
- }, display_type === IMAGE_DISPLAY_TYPE[1] && /*#__PURE__*/React.createElement("span", {
152
+ }, type === IMAGE_BLOCK && /*#__PURE__*/React.createElement("span", {
87
153
  role: "button",
88
154
  className: classnames('op-item', {
89
155
  'active': popoverState.alignPopover
@@ -112,7 +178,7 @@ const ImageHoverMenu = _ref => {
112
178
  target: "sdoc_image_border",
113
179
  placement: "top",
114
180
  fade: true
115
- }, t('Image_border'))), display_type === IMAGE_DISPLAY_TYPE[1] && /*#__PURE__*/React.createElement("span", {
181
+ }, t('Image_border'))), type === IMAGE_BLOCK && /*#__PURE__*/React.createElement("span", {
116
182
  id: "sdoc_image_caption",
117
183
  role: "button",
118
184
  className: classnames('op-item', 'ml-1', {
@@ -147,16 +213,16 @@ const ImageHoverMenu = _ref => {
147
213
  className: "sdoc-image-popover sdoc-dropdown-menu"
148
214
  }, IMAGE_DISPLAY_TYPE.map(item => {
149
215
  return /*#__PURE__*/React.createElement("div", {
150
- key: item,
216
+ key: item.value,
151
217
  className: "sdoc-dropdown-menu-item sdoc-dropdown-item-with-left-icon pr-2",
152
218
  onClick: event => onSelect(event, {
153
- display_type: item
219
+ 'display_type': item.value
154
220
  })
155
221
  }, /*#__PURE__*/React.createElement("div", {
156
222
  className: "sdoc-dropdown-item-content"
157
223
  }, /*#__PURE__*/React.createElement("i", {
158
224
  className: "sdoc-dropdown-item-content-icon"
159
- }), /*#__PURE__*/React.createElement("span", null, t(item))), display_type === item && /*#__PURE__*/React.createElement("i", {
225
+ }), /*#__PURE__*/React.createElement("span", null, t(item.text))), type === item.value && /*#__PURE__*/React.createElement("i", {
160
226
  className: "sdocfont sdoc-check-mark sdoc-dropdown-item-right-icon"
161
227
  }));
162
228
  })), popoverState.alignPopover && /*#__PURE__*/React.createElement("div", {
@@ -2,13 +2,13 @@ import { IMAGE } from '../../constants';
2
2
  import ImageMenu from './menu';
3
3
  import Image from './model';
4
4
  import withImage from './plugin';
5
- import renderImage from './render-elem';
5
+ import { renderImage, renderImageBlock } from './render-elem';
6
6
  const ImagePlugin = {
7
7
  type: IMAGE,
8
8
  nodeType: 'element',
9
9
  model: Image,
10
10
  editorMenus: [ImageMenu],
11
11
  editorPlugin: withImage,
12
- renderElements: [renderImage]
12
+ renderElements: [renderImage, renderImageBlock]
13
13
  };
14
14
  export default ImagePlugin;
@@ -3,10 +3,10 @@ import toaster from '../../../../components/toast';
3
3
  import context from '../../../../context';
4
4
  import EventBus from '../../../utils/event-bus';
5
5
  import { insertImage, hasSdocImages, getImageData, queryCopyMoveProgressView, resetCursor, isSingleImage } from './helpers';
6
- import { focusEditor } from '../../core';
6
+ import { focusEditor, generateEmptyElement } from '../../core';
7
7
  import { getErrorMsg } from '../../../../utils';
8
8
  import { getSlateFragmentAttribute } from '../../../utils/document-utils';
9
- import { INSERT_POSITION, CLIPBOARD_FORMAT_KEY, CLIPBOARD_ORIGIN_SDOC_KEY, IMAGE } from '../../constants';
9
+ import { INSERT_POSITION, CLIPBOARD_FORMAT_KEY, CLIPBOARD_ORIGIN_SDOC_KEY, IMAGE, IMAGE_BLOCK, PARAGRAPH } from '../../constants';
10
10
  import { INTERNAL_EVENT } from '../../../constants';
11
11
  const withImage = editor => {
12
12
  const {
@@ -14,7 +14,8 @@ const withImage = editor => {
14
14
  isVoid,
15
15
  insertData,
16
16
  deleteBackward,
17
- insertFragment
17
+ insertFragment,
18
+ insertBreak
18
19
  } = editor;
19
20
  const newEditor = editor;
20
21
 
@@ -106,15 +107,42 @@ const withImage = editor => {
106
107
  }
107
108
  };
108
109
  newEditor.deleteBackward = unit => {
109
- deleteBackward(unit);
110
- // After the delete operation, if the selected image is selected, the cursor moves backward one position
111
110
  const {
112
111
  selection
113
112
  } = editor;
114
- const [node, path] = Editor.parent(editor, selection);
113
+ const point = Editor.before(editor, selection, {
114
+ distance: 2
115
+ });
116
+ const [node, path] = Editor.node(editor, [point.path[0], point.path[1]]);
115
117
  if (Element.isElement(node) && node.type === IMAGE) {
118
+ // If the wrapping element is image_block, delete the wrapping element
119
+ const [parentNode, p] = Editor.node(editor, [path[0]]);
120
+ if (parentNode.type === IMAGE_BLOCK) {
121
+ Transforms.removeNodes(editor, {
122
+ at: p
123
+ });
124
+ return;
125
+ }
116
126
  focusEditor(editor, Path.next(path));
117
127
  }
128
+ deleteBackward(unit);
129
+ };
130
+ newEditor.insertBreak = () => {
131
+ const {
132
+ selection
133
+ } = editor;
134
+ if (selection == null) return insertBreak();
135
+ const path = Editor.path(editor, selection);
136
+ const [node] = Editor.node(editor, [path[0]]);
137
+ if (node.type === IMAGE_BLOCK) {
138
+ const p = generateEmptyElement(PARAGRAPH);
139
+ Transforms.insertNodes(editor, p, {
140
+ at: [path[0] + 1]
141
+ });
142
+ focusEditor(editor, [path[0] + 1]);
143
+ return;
144
+ }
145
+ insertBreak();
118
146
  };
119
147
  return newEditor;
120
148
  };
@@ -1,7 +1,7 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import React, { useState, useCallback, useRef, useEffect } from 'react';
3
3
  import { ReactEditor, useSelected, useReadOnly } from '@seafile/slate-react';
4
- import { Transforms } from '@seafile/slate';
4
+ import { Transforms, Editor } from '@seafile/slate';
5
5
  import classNames from 'classnames';
6
6
  import { withTranslation } from 'react-i18next';
7
7
  import { getImageURL, updateImage } from './helpers';
@@ -25,15 +25,10 @@ const Image = _ref => {
25
25
  } = _ref;
26
26
  const {
27
27
  data,
28
- display_type,
29
- align,
30
28
  border_type = IMAGE_BORDER_TYPE[0].type
31
29
  } = element;
32
- const imageWrapStyle = _objectSpread(_objectSpread({}, style), {}, {
33
- display: display_type === 'Block' ? 'block' : 'inline-block',
34
- paddingTop: display_type === 'Block' ? '8px' : '',
35
- textAlign: display_type === 'Block' ? align : ''
36
- });
30
+ const path = ReactEditor.findPath(editor, element);
31
+ const nodeEntry = Editor.node(editor, [path[0]]);
37
32
  const imageStyle = {
38
33
  border: IMAGE_BORDER_TYPE.find(item => item.type === border_type).value
39
34
  };
@@ -195,7 +190,7 @@ const Image = _ref => {
195
190
  return /*#__PURE__*/React.createElement(React.Fragment, null, isShowImagePlaceholder && /*#__PURE__*/React.createElement("span", Object.assign({
196
191
  className: classNames('sdoc-image-wrapper', className)
197
192
  }, attributes, {
198
- style: imageWrapStyle
193
+ style: _objectSpread({}, style)
199
194
  }), /*#__PURE__*/React.createElement("img", {
200
195
  ref: imageRef,
201
196
  src: imagePlaceholder,
@@ -205,7 +200,7 @@ const Image = _ref => {
205
200
  }), children), !isShowImagePlaceholder && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", Object.assign({
206
201
  className: classNames('sdoc-image-wrapper', className)
207
202
  }, attributes, {
208
- style: imageWrapStyle
203
+ style: _objectSpread({}, style)
209
204
  }), /*#__PURE__*/React.createElement("span", {
210
205
  className: "sdoc-image-inner"
211
206
  }, /*#__PURE__*/React.createElement("span", {
@@ -230,7 +225,7 @@ const Image = _ref => {
230
225
  }), isResizing && /*#__PURE__*/React.createElement("span", {
231
226
  className: "image-size",
232
227
  contentEditable: false
233
- }, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(movingWidth || imageRef.current.clientWidth)), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), display_type === 'Block' && (isShowCaption || (data === null || data === void 0 ? void 0 : data.caption)) && /*#__PURE__*/React.createElement("input", {
228
+ }, /*#__PURE__*/React.createElement("span", null, t('Width'), ':', parseInt(movingWidth || imageRef.current.clientWidth)), /*#__PURE__*/React.createElement("span", null, "\xA0\xA0"), /*#__PURE__*/React.createElement("span", null, t('Height'), ':', imageRef.current.clientHeight))), nodeEntry[0].type === 'image_block' && (isShowCaption || (data === null || data === void 0 ? void 0 : data.caption)) && /*#__PURE__*/React.createElement("input", {
234
229
  className: "sdoc-image-caption-input-wrapper",
235
230
  style: {
236
231
  width: (data === null || data === void 0 ? void 0 : data.width) || imageRef.current.clientWidth
@@ -244,10 +239,11 @@ const Image = _ref => {
244
239
  onCompositionStart: e => {
245
240
  e.stopPropagation();
246
241
  }
247
- }))), children), isShowImageHoverMenu && !readOnly && /*#__PURE__*/React.createElement(ImageHoverMenu, {
242
+ }))), children), isSelected && isShowImageHoverMenu && !readOnly && /*#__PURE__*/React.createElement(ImageHoverMenu, {
248
243
  editor: editor,
249
244
  menuPosition: menuPosition,
250
245
  element: element,
246
+ parentNodeEntry: nodeEntry,
251
247
  onHideImageHoverMenu: () => {
252
248
  setIsShowImageHoverMenu(false);
253
249
  },
@@ -257,7 +253,7 @@ const Image = _ref => {
257
253
  })));
258
254
  };
259
255
  const SdocImage = withTranslation('sdoc-editor')(Image);
260
- function renderImage(props, editor) {
256
+ export function renderImage(props, editor) {
261
257
  // eslint-disable-next-line react-hooks/rules-of-hooks
262
258
  const isSelected = useSelected();
263
259
 
@@ -279,4 +275,25 @@ function renderImage(props, editor) {
279
275
  isSelected: isSelected
280
276
  }));
281
277
  }
282
- export default renderImage;
278
+ export function renderImageBlock(props, editor) {
279
+ const {
280
+ element,
281
+ children,
282
+ attributes
283
+ } = props;
284
+ const {
285
+ align
286
+ } = element;
287
+ let justifyContent = '';
288
+ if (align) {
289
+ justifyContent = align === 'left' ? 'start' : align === 'right' ? 'end' : align;
290
+ }
291
+ return /*#__PURE__*/React.createElement("div", Object.assign({
292
+ className: "sdoc-image-block-wrapper",
293
+ style: {
294
+ display: 'flex',
295
+ padding: '5px 0px',
296
+ justifyContent: "".concat(justifyContent)
297
+ }
298
+ }, attributes), children);
299
+ }
@@ -1,6 +1,6 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import { useReadOnly, useSlateStatic } from '@seafile/slate-react';
3
- import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK, CODE_LINE, IMAGE, ELEMENT_TYPE, SDOC_LINK, FILE_LINK, TITLE, SUBTITLE, CALL_OUT, SUPPORTED_SIDE_OPERATION_TYPE } from '../constants';
3
+ import { BLOCKQUOTE, LINK, CHECK_LIST_ITEM, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, LIST_ITEM, ORDERED_LIST, PARAGRAPH, UNORDERED_LIST, CODE_BLOCK, CODE_LINE, IMAGE, IMAGE_BLOCK, ELEMENT_TYPE, SDOC_LINK, FILE_LINK, TITLE, SUBTITLE, CALL_OUT, SUPPORTED_SIDE_OPERATION_TYPE } from '../constants';
4
4
  import { BlockquotePlugin, LinkPlugin, CheckListPlugin, HeaderPlugin, ListPlugin, CodeBlockPlugin, ImagePlugin, TablePlugin, SdocLinkPlugin, ParagraphPlugin, FileLinkPlugin, CalloutPlugin } from '../plugins';
5
5
  import { onDragOver, onDragLeave, onDrop } from '../toolbar/side-toolbar/event';
6
6
  import { getParentNode } from '../core';
@@ -101,6 +101,11 @@ const CustomRenderElement = props => {
101
101
  leaf
102
102
  }), editor);
103
103
  }
104
+ case IMAGE_BLOCK:
105
+ {
106
+ const [, renderImageBlock] = ImagePlugin.renderElements;
107
+ return renderImageBlock(_objectSpread({}, props), editor);
108
+ }
104
109
  case ELEMENT_TYPE.TABLE:
105
110
  {
106
111
  const [renderTable] = TablePlugin.renderElements;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "0.3.27",
3
+ "version": "0.3.28",
4
4
  "private": false,
5
5
  "description": "This is a sdoc editor",
6
6
  "main": "dist/index.js",