@seafile/sea-email-editor 0.0.6 → 0.0.8-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editor/index.js +2 -1
- package/dist/editor/main/index.js +3 -1
- package/dist/extension/constants/element-default-style.js +2 -2
- package/dist/extension/constants/menus-config.js +5 -1
- package/dist/extension/plugins/image/render-element/index.js +7 -2
- package/dist/extension/plugins/table/helper.js +0 -1
- package/dist/extension/plugins/text-style/menu/index.js +7 -9
- package/dist/locale/lang/en.json +2 -1
- package/dist/slate-convert/index.js +8 -1
- package/dist/slate-convert/md-to-slate/index.js +49 -0
- package/dist/slate-convert/md-to-slate/transform.js +451 -0
- package/dist/slate-convert/slate-to-html/index.js +4 -1
- package/dist/utils/common.js +1 -0
- package/package.json +1 -1
package/dist/editor/index.js
CHANGED
|
@@ -17,6 +17,7 @@ const SeaEmailEditor = _ref => {
|
|
|
17
17
|
let {
|
|
18
18
|
value: initValue,
|
|
19
19
|
options = {},
|
|
20
|
+
isHtmlValue = true,
|
|
20
21
|
...rest
|
|
21
22
|
} = _ref;
|
|
22
23
|
const [isLoading, setLoading] = (0, _react.useState)(true);
|
|
@@ -37,7 +38,7 @@ const SeaEmailEditor = _ref => {
|
|
|
37
38
|
});
|
|
38
39
|
}, [options.lang]);
|
|
39
40
|
(0, _react.useEffect)(() => {
|
|
40
|
-
setValue((0, _slateConvert.deserializeHtml)(initValue));
|
|
41
|
+
setValue(isHtmlValue ? (0, _slateConvert.deserializeHtml)(initValue) : (0, _slateConvert.mdStringToSlate)(initValue));
|
|
41
42
|
setLoading(false);
|
|
42
43
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
44
|
}, []);
|
|
@@ -28,6 +28,7 @@ const Main = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
|
28
28
|
autoFocus = true,
|
|
29
29
|
value,
|
|
30
30
|
editorApi,
|
|
31
|
+
assetURLPrefix,
|
|
31
32
|
onSave,
|
|
32
33
|
onChange,
|
|
33
34
|
onLinkClick
|
|
@@ -43,11 +44,12 @@ const Main = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
|
43
44
|
return editor;
|
|
44
45
|
}, (0, _slateHistory.withHistory)((0, _slateReact.withReact)((0, _slate.createEditor)())));
|
|
45
46
|
_editor._id = (0, _slugid.nice)();
|
|
47
|
+
_editor.assetURLPrefix = assetURLPrefix;
|
|
46
48
|
return (0, _withPropsEditor.default)(_editor, {
|
|
47
49
|
editorApi,
|
|
48
50
|
onSave
|
|
49
51
|
});
|
|
50
|
-
}, [editorApi, onSave]);
|
|
52
|
+
}, [editorApi, assetURLPrefix, onSave]);
|
|
51
53
|
const eventProxy = (0, _react.useMemo)(() => {
|
|
52
54
|
return new _eventHandler.default(editor);
|
|
53
55
|
}, [editor]);
|
|
@@ -8,10 +8,10 @@ exports.ELEMENT_DEFAULT_STYLE = void 0;
|
|
|
8
8
|
var ElementTypes = _interopRequireWildcard(require("./element-types"));
|
|
9
9
|
const ELEMENT_DEFAULT_STYLE = exports.ELEMENT_DEFAULT_STYLE = {
|
|
10
10
|
[ElementTypes.BLOCKQUOTE]: {
|
|
11
|
-
borderLeft: '
|
|
11
|
+
borderLeft: '2px solid rgba(0, 40, 100, .12)',
|
|
12
12
|
color: '#666',
|
|
13
13
|
margin: '1.2em 0',
|
|
14
|
-
padding: '0
|
|
14
|
+
padding: '0 16px'
|
|
15
15
|
},
|
|
16
16
|
[ElementTypes.CHECK_LIST_ITEM]: {
|
|
17
17
|
margin: '0.5rem 0'
|
|
@@ -19,7 +19,11 @@ const TEXT_STYLE_MAP = exports.TEXT_STYLE_MAP = {
|
|
|
19
19
|
CODE: CODE,
|
|
20
20
|
DELETE: DELETE,
|
|
21
21
|
ADD: ADD,
|
|
22
|
-
BOLD_ITALIC: `${BOLD}_${ITALIC}
|
|
22
|
+
BOLD_ITALIC: `${BOLD}_${ITALIC}`,
|
|
23
|
+
FONT: 'font',
|
|
24
|
+
FONT_SIZE: 'font_size',
|
|
25
|
+
COLOR: 'color',
|
|
26
|
+
BG_COLOR: 'bg_color'
|
|
23
27
|
};
|
|
24
28
|
const TABLE_SUBMENU_MAP = exports.TABLE_SUBMENU_MAP = {
|
|
25
29
|
TABLE_ALIGN_LEFT: 'table_align_left',
|
|
@@ -13,6 +13,7 @@ var _classnames = _interopRequireDefault(require("classnames"));
|
|
|
13
13
|
var _helper = require("../helper");
|
|
14
14
|
var _imagePreviewer = _interopRequireDefault(require("./image-previewer"));
|
|
15
15
|
var _components = require("../../../../components");
|
|
16
|
+
var _common = require("../../../../utils/common");
|
|
16
17
|
require("./index.css");
|
|
17
18
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
18
19
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
@@ -101,6 +102,10 @@ const renderImage = (_ref, editor) => {
|
|
|
101
102
|
event.preventDefault();
|
|
102
103
|
setIsFullScreening(false);
|
|
103
104
|
}, []);
|
|
105
|
+
let src = (element === null || element === void 0 ? void 0 : (_element$data2 = element.data) === null || _element$data2 === void 0 ? void 0 : _element$data2.src) || '';
|
|
106
|
+
if (src && editor !== null && editor !== void 0 && editor.assetURLPrefix && !(0, _common.isUrl)(src) && !src.startsWith('data:image')) {
|
|
107
|
+
src = editor.assetURLPrefix + (src.startsWith('/') ? src.slice(1) : src);
|
|
108
|
+
}
|
|
104
109
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
|
|
105
110
|
...attributes,
|
|
106
111
|
contentEditable: false,
|
|
@@ -113,8 +118,8 @@ const renderImage = (_ref, editor) => {
|
|
|
113
118
|
'selected': isSelected,
|
|
114
119
|
'error': isError
|
|
115
120
|
}),
|
|
116
|
-
alt: (element === null || element === void 0 ? void 0 : (_element$
|
|
117
|
-
src:
|
|
121
|
+
alt: (element === null || element === void 0 ? void 0 : (_element$data3 = element.data) === null || _element$data3 === void 0 ? void 0 : _element$data3.alt) || ' ' + (0, _constants.gettext)('Image loading failed'),
|
|
122
|
+
src: src,
|
|
118
123
|
width: element === null || element === void 0 ? void 0 : element.data.width,
|
|
119
124
|
height: element === null || element === void 0 ? void 0 : element.data.height
|
|
120
125
|
}), isSelected && !isLoadingImage && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
@@ -23,15 +23,13 @@ const TextStyleMenu = _ref => {
|
|
|
23
23
|
const onClick = (0, _react.useCallback)((e, toggleType) => {
|
|
24
24
|
(0, _helpers.toggleTextStyle)(editor, type);
|
|
25
25
|
}, [editor, type]);
|
|
26
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
...config
|
|
34
|
-
})
|
|
26
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarItem, {
|
|
27
|
+
editor: editor,
|
|
28
|
+
disabled: isDisabled,
|
|
29
|
+
isActive: isActive,
|
|
30
|
+
className: className,
|
|
31
|
+
onClick: onClick,
|
|
32
|
+
...config
|
|
35
33
|
});
|
|
36
34
|
};
|
|
37
35
|
var _default = exports.default = TextStyleMenu;
|
package/dist/locale/lang/en.json
CHANGED
|
@@ -10,6 +10,12 @@ Object.defineProperty(exports, "deserializeHtml", {
|
|
|
10
10
|
return _htmlToSlate.default;
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
+
Object.defineProperty(exports, "mdStringToSlate", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _mdToSlate.default;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
13
19
|
Object.defineProperty(exports, "slateToHtml", {
|
|
14
20
|
enumerable: true,
|
|
15
21
|
get: function () {
|
|
@@ -17,4 +23,5 @@ Object.defineProperty(exports, "slateToHtml", {
|
|
|
17
23
|
}
|
|
18
24
|
});
|
|
19
25
|
var _slateToHtml = _interopRequireDefault(require("./slate-to-html"));
|
|
20
|
-
var _htmlToSlate = _interopRequireDefault(require("./html-to-slate"));
|
|
26
|
+
var _htmlToSlate = _interopRequireDefault(require("./html-to-slate"));
|
|
27
|
+
var _mdToSlate = _interopRequireDefault(require("./md-to-slate"));
|
|
@@ -0,0 +1,49 @@
|
|
|
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 _unified = require("unified");
|
|
9
|
+
var _remarkParse = _interopRequireDefault(require("remark-parse"));
|
|
10
|
+
var _remarkGfm = _interopRequireDefault(require("remark-gfm"));
|
|
11
|
+
var _remarkMath = _interopRequireDefault(require("remark-math"));
|
|
12
|
+
var _core = require("../../extension/core");
|
|
13
|
+
var _transform = require("./transform");
|
|
14
|
+
// md string -> md ast
|
|
15
|
+
const getProcessor = () => {
|
|
16
|
+
const processor = (0, _unified.unified)().use(_remarkParse.default) // Handles markdown basic syntax
|
|
17
|
+
.use(_remarkGfm.default) // Handle markdown extension syntax
|
|
18
|
+
.use(_remarkMath.default); // Handles markdown math formulas
|
|
19
|
+
|
|
20
|
+
return processor;
|
|
21
|
+
};
|
|
22
|
+
const reconciledSlateNodes = nodes => {
|
|
23
|
+
return nodes;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// md string --> md ast --> slate ast
|
|
27
|
+
// https://github.com/syntax-tree/mdast
|
|
28
|
+
const mdStringToSlate = mdString => {
|
|
29
|
+
if (!mdString) return [(0, _core.generateDefaultParagraph)()];
|
|
30
|
+
let content = mdString;
|
|
31
|
+
if (typeof mdString === 'number') {
|
|
32
|
+
content = mdString + '';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// md string --> md ast
|
|
36
|
+
const root = getProcessor().parse(content);
|
|
37
|
+
|
|
38
|
+
// the mdString is '\r\n'
|
|
39
|
+
if (root.children.length === 0) {
|
|
40
|
+
return [(0, _core.generateDefaultParagraph)()];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// md ast --> slate ast
|
|
44
|
+
const slateNodes = (0, _transform.formatMdToSlate)(root.children);
|
|
45
|
+
|
|
46
|
+
// Format the document
|
|
47
|
+
return reconciledSlateNodes(slateNodes);
|
|
48
|
+
};
|
|
49
|
+
var _default = exports.default = mdStringToSlate;
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.transformUnorderedList = exports.transformTableRow = exports.transformTableCell = exports.transformTable = exports.transformParagraph = exports.transformOrderedList = exports.transformMath = exports.transformListItem = exports.transformListContent = exports.transformList = exports.transformHtml = exports.transformHr = exports.transformHeader = exports.transformCodeLine = exports.transformCodeBlock = exports.transformCheckListItem = exports.transformCheckList = exports.transformBlockquote = exports.transformBlockHtml = exports.formatMdToSlate = void 0;
|
|
8
|
+
var _slugid = _interopRequireDefault(require("slugid"));
|
|
9
|
+
var _core = require("../../extension/core");
|
|
10
|
+
var _elementTypes = require("../../extension/constants/element-types");
|
|
11
|
+
var _htmlToSlate = _interopRequireDefault(require("../html-to-slate"));
|
|
12
|
+
const INLINE_KEY_MAP = {
|
|
13
|
+
strong: 'bold',
|
|
14
|
+
emphasis: 'italic'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// <strong><em>aa<em>bb<em></strong>
|
|
18
|
+
const applyMarkForInlineItem = function (result, item) {
|
|
19
|
+
let textNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
20
|
+
const {
|
|
21
|
+
type,
|
|
22
|
+
children,
|
|
23
|
+
value
|
|
24
|
+
} = item;
|
|
25
|
+
if (type === _elementTypes.LINK) {
|
|
26
|
+
const child = children.length === 0 ? {
|
|
27
|
+
type: 'text',
|
|
28
|
+
value: ''
|
|
29
|
+
} : children[0];
|
|
30
|
+
const linkChildren = [{
|
|
31
|
+
id: _slugid.default.nice(),
|
|
32
|
+
text: child.value || ''
|
|
33
|
+
}];
|
|
34
|
+
const link = {
|
|
35
|
+
id: _slugid.default.nice(),
|
|
36
|
+
type: _elementTypes.LINK,
|
|
37
|
+
url: item.url,
|
|
38
|
+
title: item.title,
|
|
39
|
+
children: linkChildren
|
|
40
|
+
};
|
|
41
|
+
result.push([(0, _core.generateDefaultText)(), link, (0, _core.generateDefaultText)()]);
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
if (type === _elementTypes.IMAGE) {
|
|
45
|
+
const data = {
|
|
46
|
+
src: item.url,
|
|
47
|
+
...(item.title && {
|
|
48
|
+
title: item.title
|
|
49
|
+
}),
|
|
50
|
+
...(item.alt && {
|
|
51
|
+
alt: item.alt
|
|
52
|
+
}),
|
|
53
|
+
...(item.width && {
|
|
54
|
+
width: item.width
|
|
55
|
+
}),
|
|
56
|
+
...(item.height && {
|
|
57
|
+
height: item.height
|
|
58
|
+
})
|
|
59
|
+
};
|
|
60
|
+
const image = {
|
|
61
|
+
id: _slugid.default.nice(),
|
|
62
|
+
data: data,
|
|
63
|
+
type: _elementTypes.IMAGE,
|
|
64
|
+
children: [(0, _core.generateDefaultText)()]
|
|
65
|
+
};
|
|
66
|
+
result.push([(0, _core.generateDefaultText)(), image, (0, _core.generateDefaultText)()]);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Handle special images
|
|
71
|
+
if (type === 'html') {
|
|
72
|
+
const nodes = transformHtml(item);
|
|
73
|
+
result.push(nodes);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
if (!textNode.id) {
|
|
77
|
+
textNode['id'] = _slugid.default.nice();
|
|
78
|
+
}
|
|
79
|
+
if (type === 'text') {
|
|
80
|
+
// https://symbl.cc/en/200B/
|
|
81
|
+
const formatValue = value && value !== '' ? value : '';
|
|
82
|
+
textNode['text'] = formatValue;
|
|
83
|
+
result.push({
|
|
84
|
+
...textNode
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// reset testNode
|
|
88
|
+
textNode = {};
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (type === 'inlineCode') {
|
|
92
|
+
textNode['code'] = true;
|
|
93
|
+
textNode['text'] = value || '';
|
|
94
|
+
result.push({
|
|
95
|
+
...textNode
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// reset testNode
|
|
99
|
+
textNode = {};
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const attr_key = INLINE_KEY_MAP[type];
|
|
103
|
+
if (!Array.isArray(children) || children.length === 0 || !attr_key) {
|
|
104
|
+
textNode['text'] = value || '';
|
|
105
|
+
result.push({
|
|
106
|
+
...textNode
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// reset testNode
|
|
110
|
+
textNode = {};
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
textNode[attr_key] = true;
|
|
114
|
+
children.forEach(item => {
|
|
115
|
+
applyMarkForInlineItem(result, item, {
|
|
116
|
+
...textNode
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
const transformNodeWithInlineChildren = node => {
|
|
121
|
+
const {
|
|
122
|
+
children
|
|
123
|
+
} = node;
|
|
124
|
+
const defaultChildren = [(0, _core.generateDefaultText)()];
|
|
125
|
+
if (!children || !Array.isArray(children) || children.length === 0) {
|
|
126
|
+
return defaultChildren;
|
|
127
|
+
}
|
|
128
|
+
const result = [];
|
|
129
|
+
children.forEach(item => applyMarkForInlineItem(result, item));
|
|
130
|
+
return result.flat();
|
|
131
|
+
};
|
|
132
|
+
const transformHeader = node => {
|
|
133
|
+
const {
|
|
134
|
+
depth
|
|
135
|
+
} = node;
|
|
136
|
+
const type = `${_elementTypes.HEADER}${depth}`;
|
|
137
|
+
return {
|
|
138
|
+
id: _slugid.default.nice(),
|
|
139
|
+
type: type,
|
|
140
|
+
children: transformNodeWithInlineChildren(node)
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
exports.transformHeader = transformHeader;
|
|
144
|
+
const transformParagraph = node => {
|
|
145
|
+
return {
|
|
146
|
+
id: _slugid.default.nice(),
|
|
147
|
+
type: _elementTypes.PARAGRAPH,
|
|
148
|
+
children: transformNodeWithInlineChildren(node)
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
exports.transformParagraph = transformParagraph;
|
|
152
|
+
const transformBlockquote = node => {
|
|
153
|
+
const {
|
|
154
|
+
children
|
|
155
|
+
} = node;
|
|
156
|
+
return {
|
|
157
|
+
id: _slugid.default.nice(),
|
|
158
|
+
type: _elementTypes.BLOCKQUOTE,
|
|
159
|
+
children: Array.isArray(children) && children.length > 0 ? children.map(child => {
|
|
160
|
+
const handler = elementHandlers[child.type];
|
|
161
|
+
return handler(child); // flat
|
|
162
|
+
}).flat() : [{
|
|
163
|
+
id: _slugid.default.nice(),
|
|
164
|
+
type: _elementTypes.PARAGRAPH,
|
|
165
|
+
children: [{
|
|
166
|
+
id: _slugid.default.nice(),
|
|
167
|
+
text: ''
|
|
168
|
+
}]
|
|
169
|
+
}]
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
exports.transformBlockquote = transformBlockquote;
|
|
173
|
+
const transformListContent = node => {
|
|
174
|
+
return {
|
|
175
|
+
id: _slugid.default.nice(),
|
|
176
|
+
type: _elementTypes.PARAGRAPH,
|
|
177
|
+
children: transformNodeWithInlineChildren(node)
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
exports.transformListContent = transformListContent;
|
|
181
|
+
const transformListItem = node => {
|
|
182
|
+
const {
|
|
183
|
+
children
|
|
184
|
+
} = node;
|
|
185
|
+
if (children.length === 0) {
|
|
186
|
+
return {
|
|
187
|
+
id: _slugid.default.nice(),
|
|
188
|
+
type: _elementTypes.LIST_ITEM,
|
|
189
|
+
// eslint-disable-next-line array-callback-return
|
|
190
|
+
children: [transformListContent({})]
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
id: _slugid.default.nice(),
|
|
195
|
+
type: _elementTypes.LIST_ITEM,
|
|
196
|
+
// eslint-disable-next-line array-callback-return
|
|
197
|
+
children: children.map(child => {
|
|
198
|
+
if (child.type === _elementTypes.PARAGRAPH) {
|
|
199
|
+
return transformListContent(child);
|
|
200
|
+
} else if (child.type === 'code') {
|
|
201
|
+
return transformCodeBlock(child);
|
|
202
|
+
} else if (child.type === 'blockquote') {
|
|
203
|
+
return transformBlockquote(child);
|
|
204
|
+
} else if (child.type === 'list') {
|
|
205
|
+
const hasParent = true;
|
|
206
|
+
return transformList(child, hasParent);
|
|
207
|
+
} else if (child.type === 'heading') {
|
|
208
|
+
return transformParagraph(child);
|
|
209
|
+
} else if (child.type === 'html') {
|
|
210
|
+
// patch
|
|
211
|
+
return transformBlockHtml(child);
|
|
212
|
+
} else if (child.type === 'thematicBreak') {
|
|
213
|
+
// patch
|
|
214
|
+
return transformParagraph(child);
|
|
215
|
+
} else {
|
|
216
|
+
console.warn('Unhandled child type in list item:', child);
|
|
217
|
+
return (0, _core.generateDefaultParagraph)();
|
|
218
|
+
}
|
|
219
|
+
}).flat()
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
exports.transformListItem = transformListItem;
|
|
223
|
+
const transformOrderedList = node => {
|
|
224
|
+
const {
|
|
225
|
+
children
|
|
226
|
+
} = node;
|
|
227
|
+
return {
|
|
228
|
+
id: _slugid.default.nice(),
|
|
229
|
+
type: _elementTypes.ORDERED_LIST,
|
|
230
|
+
children: children.map(child => transformListItem(child))
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
exports.transformOrderedList = transformOrderedList;
|
|
234
|
+
const transformUnorderedList = node => {
|
|
235
|
+
const {
|
|
236
|
+
children
|
|
237
|
+
} = node;
|
|
238
|
+
return {
|
|
239
|
+
id: _slugid.default.nice(),
|
|
240
|
+
type: _elementTypes.UNORDERED_LIST,
|
|
241
|
+
children: children.map(child => transformListItem(child))
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
exports.transformUnorderedList = transformUnorderedList;
|
|
245
|
+
const transformCheckListItem = node => {
|
|
246
|
+
const {
|
|
247
|
+
children,
|
|
248
|
+
checked
|
|
249
|
+
} = node;
|
|
250
|
+
if (children.length === 0) {
|
|
251
|
+
return {
|
|
252
|
+
id: _slugid.default.nice(),
|
|
253
|
+
type: _elementTypes.CHECK_LIST_ITEM,
|
|
254
|
+
checked: checked ? true : false,
|
|
255
|
+
children: transformNodeWithInlineChildren({})
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
if (children.length === 1) {
|
|
259
|
+
return {
|
|
260
|
+
id: _slugid.default.nice(),
|
|
261
|
+
type: _elementTypes.CHECK_LIST_ITEM,
|
|
262
|
+
checked: checked ? true : false,
|
|
263
|
+
children: children.map(child => transformNodeWithInlineChildren(child)).flat()
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
const [child, ...reset] = children;
|
|
267
|
+
const firstChild = {
|
|
268
|
+
id: _slugid.default.nice(),
|
|
269
|
+
type: _elementTypes.CHECK_LIST_ITEM,
|
|
270
|
+
checked: checked,
|
|
271
|
+
children: transformNodeWithInlineChildren(child)
|
|
272
|
+
};
|
|
273
|
+
const resetChildren = formatMdToSlate(reset);
|
|
274
|
+
return [firstChild, ...resetChildren];
|
|
275
|
+
};
|
|
276
|
+
exports.transformCheckListItem = transformCheckListItem;
|
|
277
|
+
const transformCheckList = node => {
|
|
278
|
+
const {
|
|
279
|
+
children
|
|
280
|
+
} = node;
|
|
281
|
+
return children.map(child => transformCheckListItem(child)).flat();
|
|
282
|
+
};
|
|
283
|
+
exports.transformCheckList = transformCheckList;
|
|
284
|
+
const transformList = (node, hasParent) => {
|
|
285
|
+
const {
|
|
286
|
+
ordered,
|
|
287
|
+
children
|
|
288
|
+
} = node;
|
|
289
|
+
const firstChild = children[0];
|
|
290
|
+
if (ordered === true) {
|
|
291
|
+
return transformOrderedList(node);
|
|
292
|
+
}
|
|
293
|
+
if (ordered === false && firstChild.checked === null) {
|
|
294
|
+
return transformUnorderedList(node);
|
|
295
|
+
}
|
|
296
|
+
// patch tasklist in list
|
|
297
|
+
if (hasParent) {
|
|
298
|
+
return transformUnorderedList(node);
|
|
299
|
+
}
|
|
300
|
+
return transformCheckList(node);
|
|
301
|
+
};
|
|
302
|
+
exports.transformList = transformList;
|
|
303
|
+
const transformTableCell = (cell, align) => {
|
|
304
|
+
return {
|
|
305
|
+
id: _slugid.default.nice(),
|
|
306
|
+
type: _elementTypes.TABLE_CELL,
|
|
307
|
+
children: transformNodeWithInlineChildren(cell)
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
exports.transformTableCell = transformTableCell;
|
|
311
|
+
const transformTableRow = row => {
|
|
312
|
+
const {
|
|
313
|
+
children: cells
|
|
314
|
+
} = row;
|
|
315
|
+
return {
|
|
316
|
+
id: _slugid.default.nice(),
|
|
317
|
+
type: _elementTypes.TABLE_ROW,
|
|
318
|
+
children: cells.map(cell => transformTableCell(cell))
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
exports.transformTableRow = transformTableRow;
|
|
322
|
+
const transformTable = node => {
|
|
323
|
+
const {
|
|
324
|
+
children: rows,
|
|
325
|
+
align = []
|
|
326
|
+
} = node;
|
|
327
|
+
return {
|
|
328
|
+
id: _slugid.default.nice(),
|
|
329
|
+
type: _elementTypes.TABLE,
|
|
330
|
+
align: align,
|
|
331
|
+
children: rows.map((row, index) => transformTableRow(row))
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
exports.transformTable = transformTable;
|
|
335
|
+
const transformCodeLine = text => {
|
|
336
|
+
return {
|
|
337
|
+
id: _slugid.default.nice(),
|
|
338
|
+
type: _elementTypes.CODE_LINE,
|
|
339
|
+
children: [{
|
|
340
|
+
id: _slugid.default.nice(),
|
|
341
|
+
text: text
|
|
342
|
+
}]
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
exports.transformCodeLine = transformCodeLine;
|
|
346
|
+
const transformCodeBlock = node => {
|
|
347
|
+
const {
|
|
348
|
+
lang,
|
|
349
|
+
value
|
|
350
|
+
} = node;
|
|
351
|
+
let children = value.split('\n');
|
|
352
|
+
if (children.length === 0) {
|
|
353
|
+
children = [''];
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
id: _slugid.default.nice(),
|
|
357
|
+
type: _elementTypes.CODE_BLOCK,
|
|
358
|
+
lang: lang,
|
|
359
|
+
children: children.map(text => transformCodeLine(text))
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
exports.transformCodeBlock = transformCodeBlock;
|
|
363
|
+
const transformHr = node => {
|
|
364
|
+
return {
|
|
365
|
+
id: _slugid.default.nice(),
|
|
366
|
+
type: _elementTypes.DIVIDER,
|
|
367
|
+
children: [(0, _core.generateDefaultText)()]
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
exports.transformHr = transformHr;
|
|
371
|
+
const transformHtml = node => {
|
|
372
|
+
const defaultTextNode = (0, _core.generateDefaultText)();
|
|
373
|
+
if (node.value.slice(0, 4).toLowerCase() === '<img') {
|
|
374
|
+
const {
|
|
375
|
+
body
|
|
376
|
+
} = new DOMParser().parseFromString(node.value, 'text/html');
|
|
377
|
+
const img = body.firstChild;
|
|
378
|
+
const src = img.getAttribute('src');
|
|
379
|
+
if (!src) return [defaultTextNode];
|
|
380
|
+
const alt = img.getAttribute('alt');
|
|
381
|
+
const title = img.getAttribute('title');
|
|
382
|
+
const width = img.getAttribute('width');
|
|
383
|
+
const height = img.getAttribute('height');
|
|
384
|
+
const data = {
|
|
385
|
+
src: src,
|
|
386
|
+
...(alt && {
|
|
387
|
+
alt
|
|
388
|
+
}),
|
|
389
|
+
...(title && {
|
|
390
|
+
title
|
|
391
|
+
}),
|
|
392
|
+
...(!isNaN(width) && width > 0 && {
|
|
393
|
+
width
|
|
394
|
+
}),
|
|
395
|
+
...(!isNaN(height) && height > 0 && {
|
|
396
|
+
height
|
|
397
|
+
})
|
|
398
|
+
};
|
|
399
|
+
const image = {
|
|
400
|
+
id: _slugid.default.nice(),
|
|
401
|
+
data: data,
|
|
402
|
+
type: _elementTypes.IMAGE,
|
|
403
|
+
children: [(0, _core.generateDefaultText)()]
|
|
404
|
+
};
|
|
405
|
+
return [(0, _core.generateDefaultText)(), image, (0, _core.generateDefaultText)()];
|
|
406
|
+
}
|
|
407
|
+
return [defaultTextNode];
|
|
408
|
+
};
|
|
409
|
+
exports.transformHtml = transformHtml;
|
|
410
|
+
const transformBlockHtml = node => {
|
|
411
|
+
if (node.value.slice(0, 4).toLowerCase() === '<img') {
|
|
412
|
+
return {
|
|
413
|
+
id: _slugid.default.nice(),
|
|
414
|
+
type: _elementTypes.PARAGRAPH,
|
|
415
|
+
children: transformHtml(node)
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return (0, _htmlToSlate.default)(node.value);
|
|
419
|
+
};
|
|
420
|
+
exports.transformBlockHtml = transformBlockHtml;
|
|
421
|
+
const transformMath = node => {
|
|
422
|
+
return {
|
|
423
|
+
id: _slugid.default.nice(),
|
|
424
|
+
type: 'formula',
|
|
425
|
+
data: {
|
|
426
|
+
formula: node.value
|
|
427
|
+
},
|
|
428
|
+
children: [(0, _core.generateDefaultText)()]
|
|
429
|
+
};
|
|
430
|
+
};
|
|
431
|
+
exports.transformMath = transformMath;
|
|
432
|
+
const elementHandlers = {
|
|
433
|
+
'paragraph': transformParagraph,
|
|
434
|
+
'heading': transformHeader,
|
|
435
|
+
'blockquote': transformBlockquote,
|
|
436
|
+
'table': transformTable,
|
|
437
|
+
'list': transformList,
|
|
438
|
+
// ordered_list | unordered_list | check_list_item
|
|
439
|
+
'code': transformCodeBlock,
|
|
440
|
+
'thematicBreak': transformHr,
|
|
441
|
+
'math': transformMath,
|
|
442
|
+
'html': transformBlockHtml
|
|
443
|
+
};
|
|
444
|
+
const formatMdToSlate = children => {
|
|
445
|
+
const validChildren = children.filter(child => elementHandlers[child.type]);
|
|
446
|
+
return validChildren.map(child => {
|
|
447
|
+
const handler = elementHandlers[child.type];
|
|
448
|
+
return handler(child);
|
|
449
|
+
}).flat();
|
|
450
|
+
};
|
|
451
|
+
exports.formatMdToSlate = formatMdToSlate;
|
|
@@ -95,7 +95,7 @@ const element2Html = (value, element, path) => {
|
|
|
95
95
|
return `<div ${className}${style}><div style="width: 100%; height: 1px; background-color: #ccc; margin: 5px 0;"></div></div>`;
|
|
96
96
|
}
|
|
97
97
|
if (Array.isArray(children) && tag) {
|
|
98
|
-
|
|
98
|
+
let childrenDom = children.map((child, index) => element2Html(value, child, [...path, index])).join('');
|
|
99
99
|
if (tag === 'a') return `<${tag}${className}${style} href="${element.url}">${childrenDom}</${tag}>`;
|
|
100
100
|
if (tag === 'table') return `<${tag}${className}${style}><tbody>${childrenDom}</tbody></${tag}>`;
|
|
101
101
|
if (type === _constants.ElementTypes.CHECK_LIST_ITEM) {
|
|
@@ -106,6 +106,9 @@ const element2Html = (value, element, path) => {
|
|
|
106
106
|
return `<div${className}${style}><span style="margin-right: 6px;">${inputDom}</span><span>${childrenDom}</span></div>`;
|
|
107
107
|
}
|
|
108
108
|
if (type === _constants.ElementTypes.CODE_BLOCK) return `<div${className}${style}><pre><code>${childrenDom}</code></pre></div>`;
|
|
109
|
+
if (type === _constants.ElementTypes.PARAGRAPH && !childrenDom) {
|
|
110
|
+
childrenDom = ' ';
|
|
111
|
+
}
|
|
109
112
|
return `<${tag}${className}${style}>${childrenDom}</${tag}>`;
|
|
110
113
|
}
|
|
111
114
|
const {
|
package/dist/utils/common.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.isMac = isMac;
|
|
|
15
15
|
const IMAGE_TYPES = exports.IMAGE_TYPES = ['png', 'jpg', 'gif'];
|
|
16
16
|
const isImage = url => {
|
|
17
17
|
if (!url) return false;
|
|
18
|
+
if (url.startsWith('data:image')) return true;
|
|
18
19
|
if (!isUrl(url)) return false;
|
|
19
20
|
const fileName = url.slice(url.lastIndexOf('/') + 1); // http://xx/mm/*.png
|
|
20
21
|
const suffix = fileName.split('.')[1];
|