@seafile/sdoc-editor 0.4.35 → 0.4.37
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/api/seafile-api.js +5 -4
- package/dist/basic-sdk/comment/components/global-comment/index.js +1 -2
- package/dist/basic-sdk/comment/helper.js +2 -2
- package/dist/basic-sdk/comment/utils/index.js +16 -13
- package/dist/basic-sdk/editor/editable-article.js +1 -1
- package/dist/basic-sdk/editor/sdoc-editor.js +1 -2
- package/dist/basic-sdk/extension/commons/element-popover/index.js +3 -2
- package/dist/basic-sdk/extension/commons/history-files/index.js +13 -1
- package/dist/basic-sdk/extension/commons/menu/menu-group.js +3 -2
- package/dist/basic-sdk/extension/constants/font.js +1 -0
- package/dist/basic-sdk/extension/constants/index.js +1 -0
- package/dist/basic-sdk/extension/core/utils/index.js +8 -0
- package/dist/basic-sdk/extension/plugins/blockquote/menu/index.js +7 -6
- package/dist/basic-sdk/extension/plugins/callout/render-elem/index.js +2 -0
- package/dist/basic-sdk/extension/plugins/check-list/menu/index.js +7 -6
- package/dist/basic-sdk/extension/plugins/check-list/render-elem.js +3 -2
- package/dist/basic-sdk/extension/plugins/code-block/helpers.js +4 -2
- package/dist/basic-sdk/extension/plugins/code-block/render-elem.js +2 -0
- package/dist/basic-sdk/extension/plugins/file-link/helpers.js +1 -0
- package/dist/basic-sdk/extension/plugins/header/menu/index.js +21 -20
- package/dist/basic-sdk/extension/plugins/html/helper.js +1 -0
- package/dist/basic-sdk/extension/plugins/image/dialogs/image-previewer.js +7 -6
- package/dist/basic-sdk/extension/plugins/image/helpers.js +13 -8
- package/dist/basic-sdk/extension/plugins/image/hover-menu/index.js +3 -3
- package/dist/basic-sdk/extension/plugins/link/helpers.js +1 -0
- package/dist/basic-sdk/extension/plugins/link/render-elem.js +13 -12
- package/dist/basic-sdk/extension/plugins/list/menu/index.js +9 -8
- package/dist/basic-sdk/extension/plugins/sdoc-link/helpers.js +1 -1
- package/dist/basic-sdk/extension/plugins/table/helpers.js +1 -0
- package/dist/basic-sdk/extension/plugins/table/menu/active-table-menu/common-menu.js +9 -8
- package/dist/basic-sdk/extension/plugins/table/menu/table-context-menu/index.js +13 -12
- package/dist/basic-sdk/extension/plugins/table/menu/table-context-menu/insert-table-element.js +9 -8
- package/dist/basic-sdk/extension/plugins/table/render/render-cell.js +9 -9
- package/dist/basic-sdk/extension/plugins/table/render/resize-handlers/column-resize-handler.js +1 -1
- package/dist/basic-sdk/extension/plugins/table/render/resize-handlers/row-resize-handler.js +2 -3
- package/dist/basic-sdk/extension/plugins/table/render/table-header/index.css +4 -1
- package/dist/basic-sdk/extension/plugins/table/render/table-header/rows-header/row-header.js +1 -1
- package/dist/basic-sdk/extension/toolbar/header-toolbar/redo-undo.js +7 -6
- package/dist/basic-sdk/extension/toolbar/side-toolbar/helpers.js +1 -0
- package/dist/basic-sdk/outline/outline-item.js +7 -6
- package/dist/basic-sdk/socket/socket-client.js +49 -48
- package/dist/basic-sdk/socket/socket-manager.js +53 -52
- package/dist/basic-sdk/utils/diff-text.js +21 -20
- package/dist/basic-sdk/utils/dom-utils.js +2 -2
- package/dist/basic-sdk/utils/event-handler.js +8 -7
- package/dist/basic-sdk/utils/object-utils.js +5 -4
- package/dist/components/doc-operations/collaborators-operation/index.js +5 -4
- package/dist/components/draft-dropdown/index.js +11 -10
- package/dist/components/tip-message/index.js +21 -20
- package/dist/components/toast/toast.js +17 -16
- package/dist/components/toast/toastManager.js +14 -13
- package/dist/components/toast/toaster.js +19 -18
- package/dist/context.js +5 -4
- package/dist/slate-convert/html-to-slate/constants.js +34 -0
- package/dist/slate-convert/html-to-slate/helper.js +54 -0
- package/dist/slate-convert/html-to-slate/index.js +131 -0
- package/dist/slate-convert/html-to-slate/rules/blockquote.js +17 -0
- package/dist/slate-convert/html-to-slate/rules/check-list.js +20 -0
- package/dist/slate-convert/html-to-slate/rules/code-block.js +83 -0
- package/dist/slate-convert/html-to-slate/rules/header.js +17 -0
- package/dist/slate-convert/html-to-slate/rules/image.js +22 -0
- package/dist/slate-convert/html-to-slate/rules/index.js +11 -0
- package/dist/slate-convert/html-to-slate/rules/link.js +22 -0
- package/dist/slate-convert/html-to-slate/rules/list.js +50 -0
- package/dist/slate-convert/html-to-slate/rules/paragraph.js +17 -0
- package/dist/slate-convert/html-to-slate/rules/table.js +38 -0
- package/dist/slate-convert/html-to-slate/rules/text.js +56 -0
- package/dist/slate-convert/index.js +8 -0
- package/dist/slate-convert/md-to-html/index.js +48 -0
- package/dist/slate-convert/md-to-html/sanitize-schema.js +17 -0
- package/dist/slate-convert/md-to-slate/index.js +38 -0
- package/dist/slate-convert/md-to-slate/transform.js +360 -0
- package/dist/slate-convert/slate-to-md/index.js +37 -0
- package/dist/slate-convert/slate-to-md/transform.js +311 -0
- package/dist/utils/get-event-transfer.js +3 -1
- package/dist/utils/index.js +6 -6
- package/dist/utils/is-punctuation-mark.js +44 -0
- package/package.json +21 -6
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import slugid from 'slugid';
|
|
3
|
+
import { generateDefaultText } from '../../basic-sdk/extension/core';
|
|
4
|
+
import { BLOCKQUOTE, HEADER, IMAGE, LINK, PARAGRAPH, TABLE, CODE_BLOCK, LIST_ITEM, ORDERED_LIST, UNORDERED_LIST, CHECK_LIST_ITEM, CODE_LINE, TABLE_ROW, TABLE_CELL } from '../../basic-sdk/extension/constants/element-type';
|
|
5
|
+
import deserializeHtml from '../html-to-slate';
|
|
6
|
+
const INLINE_KEY_MAP = {
|
|
7
|
+
strong: 'bold',
|
|
8
|
+
emphasis: 'italic'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// <strong><em>aa<em>bb<em></strong>
|
|
12
|
+
const applyMarkForInlineItem = function (result, item) {
|
|
13
|
+
let textNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
14
|
+
const {
|
|
15
|
+
type,
|
|
16
|
+
children,
|
|
17
|
+
value
|
|
18
|
+
} = item;
|
|
19
|
+
if (type === LINK) {
|
|
20
|
+
const child = children.length === 0 ? {
|
|
21
|
+
type: 'text',
|
|
22
|
+
value: ''
|
|
23
|
+
} : children[0];
|
|
24
|
+
const linkChildren = [{
|
|
25
|
+
id: slugid.nice(),
|
|
26
|
+
text: child.value
|
|
27
|
+
}];
|
|
28
|
+
const link = {
|
|
29
|
+
id: slugid.nice(),
|
|
30
|
+
type: LINK,
|
|
31
|
+
url: item.url,
|
|
32
|
+
title: item.title,
|
|
33
|
+
children: linkChildren
|
|
34
|
+
};
|
|
35
|
+
result.push([generateDefaultText(), link, generateDefaultText()]);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
if (type === IMAGE) {
|
|
39
|
+
const data = _objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
40
|
+
src: item.url
|
|
41
|
+
}, item.title && {
|
|
42
|
+
title: item.title
|
|
43
|
+
}), item.alt && {
|
|
44
|
+
alt: item.alt
|
|
45
|
+
}), item.width && {
|
|
46
|
+
width: item.width
|
|
47
|
+
}), item.height && {
|
|
48
|
+
height: item.height
|
|
49
|
+
});
|
|
50
|
+
const image = {
|
|
51
|
+
id: slugid.nice(),
|
|
52
|
+
data: data,
|
|
53
|
+
type: IMAGE,
|
|
54
|
+
children: [generateDefaultText()]
|
|
55
|
+
};
|
|
56
|
+
result.push([generateDefaultText(), image, generateDefaultText()]);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Handle special images
|
|
61
|
+
if (type === 'html') {
|
|
62
|
+
const nodes = transformHtml(item);
|
|
63
|
+
result.push(nodes);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
if (!textNode.id) {
|
|
67
|
+
textNode['id'] = slugid.nice();
|
|
68
|
+
}
|
|
69
|
+
if (type === 'text') {
|
|
70
|
+
textNode['text'] = value || '';
|
|
71
|
+
result.push(textNode);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (type === 'inlineCode') {
|
|
75
|
+
textNode['code'] = true;
|
|
76
|
+
textNode['text'] = value || '';
|
|
77
|
+
result.push(textNode);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const attr_key = INLINE_KEY_MAP[type];
|
|
81
|
+
if (!Array.isArray(children) || children.length === 0 || !attr_key) {
|
|
82
|
+
textNode['text'] = value || '';
|
|
83
|
+
result.push(textNode);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
textNode[attr_key] = true;
|
|
87
|
+
children.forEach(item => {
|
|
88
|
+
applyMarkForInlineItem(result, item, textNode);
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
const transformNodeWithInlineChildren = node => {
|
|
92
|
+
const {
|
|
93
|
+
children
|
|
94
|
+
} = node;
|
|
95
|
+
const defaultChildren = [generateDefaultText()];
|
|
96
|
+
if (!children || !Array.isArray(children) || children.length === 0) {
|
|
97
|
+
return defaultChildren;
|
|
98
|
+
}
|
|
99
|
+
const result = [];
|
|
100
|
+
children.forEach(item => applyMarkForInlineItem(result, item));
|
|
101
|
+
return result.flat();
|
|
102
|
+
};
|
|
103
|
+
export const transformHeader = node => {
|
|
104
|
+
const {
|
|
105
|
+
depth
|
|
106
|
+
} = node;
|
|
107
|
+
const type = "".concat(HEADER).concat(depth);
|
|
108
|
+
return {
|
|
109
|
+
id: slugid.nice(),
|
|
110
|
+
type: type,
|
|
111
|
+
children: transformNodeWithInlineChildren(node)
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
export const transformParagraph = node => {
|
|
115
|
+
return {
|
|
116
|
+
id: slugid.nice(),
|
|
117
|
+
type: PARAGRAPH,
|
|
118
|
+
children: transformNodeWithInlineChildren(node)
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
export const transformBlockquote = node => {
|
|
122
|
+
const {
|
|
123
|
+
children
|
|
124
|
+
} = node;
|
|
125
|
+
return {
|
|
126
|
+
id: slugid.nice(),
|
|
127
|
+
type: BLOCKQUOTE,
|
|
128
|
+
children: children.map(child => {
|
|
129
|
+
const handler = elementHandlers[child.type];
|
|
130
|
+
return handler(child);
|
|
131
|
+
}).flat() // flat
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const transformListContent = node => {
|
|
136
|
+
return {
|
|
137
|
+
id: slugid.nice(),
|
|
138
|
+
type: PARAGRAPH,
|
|
139
|
+
children: transformNodeWithInlineChildren(node)
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
export const transformListItem = node => {
|
|
143
|
+
const {
|
|
144
|
+
children
|
|
145
|
+
} = node;
|
|
146
|
+
if (children.length === 0) {
|
|
147
|
+
return {
|
|
148
|
+
id: slugid.nice(),
|
|
149
|
+
type: LIST_ITEM,
|
|
150
|
+
// eslint-disable-next-line array-callback-return
|
|
151
|
+
children: [transformListContent({})]
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
id: slugid.nice(),
|
|
156
|
+
type: LIST_ITEM,
|
|
157
|
+
// eslint-disable-next-line array-callback-return
|
|
158
|
+
children: children.map(child => {
|
|
159
|
+
if (child.type === PARAGRAPH) {
|
|
160
|
+
return transformListContent(child);
|
|
161
|
+
} else if (child.type === 'code') {
|
|
162
|
+
return transformCodeBlock(child);
|
|
163
|
+
} else if (child.type === 'blockquote') {
|
|
164
|
+
return transformBlockquote(child);
|
|
165
|
+
} else if (child.type === 'list') {
|
|
166
|
+
return transformList(child);
|
|
167
|
+
} else if (child.type === 'html') {
|
|
168
|
+
// patch
|
|
169
|
+
return transformBlockHtml(child);
|
|
170
|
+
}
|
|
171
|
+
}).flat()
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
export const transformOrderedList = node => {
|
|
175
|
+
const {
|
|
176
|
+
children
|
|
177
|
+
} = node;
|
|
178
|
+
return {
|
|
179
|
+
id: slugid.nice(),
|
|
180
|
+
type: ORDERED_LIST,
|
|
181
|
+
children: children.map(child => transformListItem(child))
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
export const transformUnorderedList = node => {
|
|
185
|
+
const {
|
|
186
|
+
children
|
|
187
|
+
} = node;
|
|
188
|
+
return {
|
|
189
|
+
id: slugid.nice(),
|
|
190
|
+
type: UNORDERED_LIST,
|
|
191
|
+
children: children.map(child => transformListItem(child))
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
export const transformCheckListItem = node => {
|
|
195
|
+
const {
|
|
196
|
+
children,
|
|
197
|
+
checked
|
|
198
|
+
} = node;
|
|
199
|
+
return {
|
|
200
|
+
id: slugid.nice(),
|
|
201
|
+
type: CHECK_LIST_ITEM,
|
|
202
|
+
checked: checked,
|
|
203
|
+
children: children.map(child => transformNodeWithInlineChildren(child)).flat()
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
export const transformCheckList = node => {
|
|
207
|
+
const {
|
|
208
|
+
children
|
|
209
|
+
} = node;
|
|
210
|
+
return children.map(child => transformCheckListItem(child));
|
|
211
|
+
};
|
|
212
|
+
export const transformList = node => {
|
|
213
|
+
const {
|
|
214
|
+
ordered,
|
|
215
|
+
children
|
|
216
|
+
} = node;
|
|
217
|
+
const firstChild = children[0];
|
|
218
|
+
if (ordered === true) {
|
|
219
|
+
return transformOrderedList(node);
|
|
220
|
+
}
|
|
221
|
+
if (ordered === false && firstChild.checked === null) {
|
|
222
|
+
return transformUnorderedList(node);
|
|
223
|
+
}
|
|
224
|
+
return transformCheckList(node);
|
|
225
|
+
};
|
|
226
|
+
export const transformTableCell = (cell, align) => {
|
|
227
|
+
return {
|
|
228
|
+
id: slugid.nice(),
|
|
229
|
+
type: TABLE_CELL,
|
|
230
|
+
align: align || null,
|
|
231
|
+
children: transformNodeWithInlineChildren(cell)
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
export const transformTableRow = (row, align) => {
|
|
235
|
+
const {
|
|
236
|
+
children: cells
|
|
237
|
+
} = row;
|
|
238
|
+
return {
|
|
239
|
+
id: slugid.nice(),
|
|
240
|
+
type: TABLE_ROW,
|
|
241
|
+
children: cells.map(cell => transformTableCell(cell, align))
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
export const transformTable = node => {
|
|
245
|
+
const {
|
|
246
|
+
children: rows,
|
|
247
|
+
align = []
|
|
248
|
+
} = node;
|
|
249
|
+
return {
|
|
250
|
+
id: slugid.nice(),
|
|
251
|
+
type: TABLE,
|
|
252
|
+
children: rows.map((row, index) => transformTableRow(row, align[index]))
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
export const transformCodeLine = text => {
|
|
256
|
+
return {
|
|
257
|
+
id: slugid.nice(),
|
|
258
|
+
type: CODE_LINE,
|
|
259
|
+
children: [{
|
|
260
|
+
id: slugid.nice(),
|
|
261
|
+
text: text
|
|
262
|
+
}]
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
export const transformCodeBlock = node => {
|
|
266
|
+
const {
|
|
267
|
+
lang,
|
|
268
|
+
value
|
|
269
|
+
} = node;
|
|
270
|
+
let children = value.split('\n').filter(Boolean);
|
|
271
|
+
if (children.length === 0) {
|
|
272
|
+
children = [''];
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
id: slugid.nice(),
|
|
276
|
+
type: CODE_BLOCK,
|
|
277
|
+
lang: lang,
|
|
278
|
+
children: children.map(text => transformCodeLine(text))
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
export const transformHr = node => {
|
|
282
|
+
return {
|
|
283
|
+
id: slugid.nice(),
|
|
284
|
+
type: 'hr',
|
|
285
|
+
children: [generateDefaultText()]
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
export const transformHtml = node => {
|
|
289
|
+
const defaultTextNode = generateDefaultText();
|
|
290
|
+
if (node.value.slice(0, 4).toLowerCase() === '<img') {
|
|
291
|
+
const {
|
|
292
|
+
body
|
|
293
|
+
} = new DOMParser().parseFromString(node.value, 'text/html');
|
|
294
|
+
const img = body.firstChild;
|
|
295
|
+
const src = img.getAttribute('src');
|
|
296
|
+
if (!src) return [defaultTextNode];
|
|
297
|
+
const alt = img.getAttribute('alt');
|
|
298
|
+
const title = img.getAttribute('title');
|
|
299
|
+
const width = img.getAttribute('width');
|
|
300
|
+
const height = img.getAttribute('height');
|
|
301
|
+
const data = _objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
302
|
+
src: src
|
|
303
|
+
}, alt && {
|
|
304
|
+
alt
|
|
305
|
+
}), title && {
|
|
306
|
+
title
|
|
307
|
+
}), !isNaN(width) && width > 0 && {
|
|
308
|
+
width
|
|
309
|
+
}), !isNaN(height) && height > 0 && {
|
|
310
|
+
height
|
|
311
|
+
});
|
|
312
|
+
const image = {
|
|
313
|
+
id: slugid.nice(),
|
|
314
|
+
data: data,
|
|
315
|
+
type: IMAGE,
|
|
316
|
+
children: [generateDefaultText()]
|
|
317
|
+
};
|
|
318
|
+
return [generateDefaultText(), image, generateDefaultText()];
|
|
319
|
+
}
|
|
320
|
+
return [defaultTextNode];
|
|
321
|
+
};
|
|
322
|
+
export const transformBlockHtml = node => {
|
|
323
|
+
if (node.value.slice(0, 4).toLowerCase() === '<img') {
|
|
324
|
+
return {
|
|
325
|
+
id: slugid.nice(),
|
|
326
|
+
type: PARAGRAPH,
|
|
327
|
+
children: transformHtml(node)
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return deserializeHtml(node.value);
|
|
331
|
+
};
|
|
332
|
+
export const transformMath = node => {
|
|
333
|
+
return {
|
|
334
|
+
id: slugid.nice(),
|
|
335
|
+
type: 'formula',
|
|
336
|
+
data: {
|
|
337
|
+
formula: node.value
|
|
338
|
+
},
|
|
339
|
+
children: [generateDefaultText()]
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
const elementHandlers = {
|
|
343
|
+
'paragraph': transformParagraph,
|
|
344
|
+
'heading': transformHeader,
|
|
345
|
+
'blockquote': transformBlockquote,
|
|
346
|
+
'table': transformTable,
|
|
347
|
+
'list': transformList,
|
|
348
|
+
// ordered_list | unordered_list | check_list_item
|
|
349
|
+
'code': transformCodeBlock,
|
|
350
|
+
'thematicBreak': transformHr,
|
|
351
|
+
'math': transformMath,
|
|
352
|
+
'html': transformBlockHtml
|
|
353
|
+
};
|
|
354
|
+
export const formatMdToSlate = children => {
|
|
355
|
+
const validChildren = children.filter(child => elementHandlers[child.type]);
|
|
356
|
+
return validChildren.map(child => {
|
|
357
|
+
const handler = elementHandlers[child.type];
|
|
358
|
+
return handler(child);
|
|
359
|
+
}).flat();
|
|
360
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { unified } from 'unified';
|
|
2
|
+
import markdown from 'remark-parse';
|
|
3
|
+
import gfm from 'remark-gfm';
|
|
4
|
+
import remarkStringify from 'remark-stringify';
|
|
5
|
+
import remarkMath from 'remark-math';
|
|
6
|
+
import { formatSlateToMd } from './transform';
|
|
7
|
+
const isContentValid = value => {
|
|
8
|
+
if (!value || !Array.isArray(value)) return false;
|
|
9
|
+
return true;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// slateNode -> mdast -> mdString
|
|
13
|
+
const slateToMdString = value => {
|
|
14
|
+
if (!isContentValid(value)) return '';
|
|
15
|
+
// slateNode -> mdast
|
|
16
|
+
// https://github.com/syntax-tree/mdast#phrasingcontent
|
|
17
|
+
const mdASTNodes = formatSlateToMd(value);
|
|
18
|
+
const root = {
|
|
19
|
+
type: 'root',
|
|
20
|
+
children: mdASTNodes
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// convert slate value to md
|
|
24
|
+
const stringifyOptions = {
|
|
25
|
+
rule: '-',
|
|
26
|
+
ruleSpaces: false,
|
|
27
|
+
bullet: '*',
|
|
28
|
+
commonmarks: true,
|
|
29
|
+
fences: true
|
|
30
|
+
};
|
|
31
|
+
const res = unified().use(markdown).use(gfm).use(remarkStringify, stringifyOptions).use(remarkMath).stringify(root);
|
|
32
|
+
return res;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// transform rules: https://github.com/syntax-tree/mdast
|
|
36
|
+
|
|
37
|
+
export default slateToMdString;
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
|
|
2
|
+
import isLastCharPunctuation from '../../utils/is-punctuation-mark';
|
|
3
|
+
const generateDefaultText = () => {
|
|
4
|
+
return {
|
|
5
|
+
type: 'text',
|
|
6
|
+
value: ''
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
const transformTextNode = textNode => {
|
|
10
|
+
let mdNode = {
|
|
11
|
+
type: 'text',
|
|
12
|
+
value: textNode.text
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// code = true, override text type
|
|
16
|
+
if (textNode['code']) {
|
|
17
|
+
mdNode = _objectSpread(_objectSpread({}, mdNode), {}, {
|
|
18
|
+
type: 'inlineCode'
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// blob = true, add strong parent
|
|
23
|
+
if (textNode['bold']) {
|
|
24
|
+
mdNode['value'] = mdNode.value ? mdNode.value.trim() : '';
|
|
25
|
+
if (isLastCharPunctuation(mdNode.value)) {
|
|
26
|
+
const value = mdNode.value;
|
|
27
|
+
const mdNode1 = _objectSpread(_objectSpread({}, mdNode), {}, {
|
|
28
|
+
value: value.substring(0, value.length - 1)
|
|
29
|
+
});
|
|
30
|
+
const mdNode2 = {
|
|
31
|
+
type: 'text',
|
|
32
|
+
value: value.substring(value.length - 1)
|
|
33
|
+
};
|
|
34
|
+
mdNode = [{
|
|
35
|
+
type: 'strong',
|
|
36
|
+
children: [mdNode1]
|
|
37
|
+
}, mdNode2];
|
|
38
|
+
} else {
|
|
39
|
+
mdNode = {
|
|
40
|
+
type: 'strong',
|
|
41
|
+
children: [mdNode]
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// italic = true, add emphasis parent
|
|
47
|
+
if (textNode['italic'] && mdNode.type === 'strong') {
|
|
48
|
+
mdNode = {
|
|
49
|
+
type: 'emphasis',
|
|
50
|
+
children: [mdNode]
|
|
51
|
+
};
|
|
52
|
+
} else if (textNode['italic']) {
|
|
53
|
+
mdNode['value'] = mdNode.value ? mdNode.value.trim() : '';
|
|
54
|
+
if (isLastCharPunctuation(mdNode.value)) {
|
|
55
|
+
const value = mdNode.value;
|
|
56
|
+
const mdNode1 = _objectSpread(_objectSpread({}, mdNode), {}, {
|
|
57
|
+
value: value.substring(0, value.length - 1)
|
|
58
|
+
});
|
|
59
|
+
const mdNode2 = {
|
|
60
|
+
type: 'text',
|
|
61
|
+
value: value.substring(value.length - 1)
|
|
62
|
+
};
|
|
63
|
+
mdNode = [{
|
|
64
|
+
type: 'emphasis',
|
|
65
|
+
children: [mdNode1]
|
|
66
|
+
}, mdNode2];
|
|
67
|
+
} else {
|
|
68
|
+
mdNode = {
|
|
69
|
+
type: 'emphasis',
|
|
70
|
+
children: [mdNode]
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return mdNode;
|
|
75
|
+
};
|
|
76
|
+
const transformInlineChildren = (result, item) => {
|
|
77
|
+
// image
|
|
78
|
+
if (item.type && item.type === 'image') {
|
|
79
|
+
const {
|
|
80
|
+
data
|
|
81
|
+
} = item;
|
|
82
|
+
let image = {
|
|
83
|
+
type: 'image',
|
|
84
|
+
url: data.src,
|
|
85
|
+
alt: data.alt || null,
|
|
86
|
+
title: data.title || null
|
|
87
|
+
};
|
|
88
|
+
if (data.height || data.width) {
|
|
89
|
+
image = {
|
|
90
|
+
type: 'html',
|
|
91
|
+
value: "<img src=\"".concat(data.src, "\" alt=\"").concat(data.alt, "\" title=\"").concat(data.title, "\" width=\"").concat(data.width, "\" height=\"").concat(data.height, "\" />")
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
result.push(image);
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// link
|
|
99
|
+
if (item.type && item.type === 'link') {
|
|
100
|
+
const link = {
|
|
101
|
+
type: 'link',
|
|
102
|
+
url: item.url,
|
|
103
|
+
title: item.title || null,
|
|
104
|
+
children: [transformTextNode(item.children[0])]
|
|
105
|
+
};
|
|
106
|
+
result.push(link);
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
if (item.type && item.type === 'column') {
|
|
110
|
+
const data = item.data;
|
|
111
|
+
const newNode = {
|
|
112
|
+
text: "{".concat(data.name, "}")
|
|
113
|
+
};
|
|
114
|
+
const column = transformTextNode(newNode);
|
|
115
|
+
result.push(column);
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// text
|
|
120
|
+
const nodes = transformTextNode(item);
|
|
121
|
+
result.push(nodes);
|
|
122
|
+
return result;
|
|
123
|
+
};
|
|
124
|
+
const transformNodeWithInlineChildren = node => {
|
|
125
|
+
const {
|
|
126
|
+
children
|
|
127
|
+
} = node;
|
|
128
|
+
const defaultChildren = [generateDefaultText()];
|
|
129
|
+
if (!children || !Array.isArray(children) || children.length === 0) {
|
|
130
|
+
return defaultChildren;
|
|
131
|
+
}
|
|
132
|
+
const result = [];
|
|
133
|
+
children.forEach(item => transformInlineChildren(result, item));
|
|
134
|
+
return result.flat();
|
|
135
|
+
};
|
|
136
|
+
const transformHeader = node => {
|
|
137
|
+
const level = node.type.replace('header', '');
|
|
138
|
+
return {
|
|
139
|
+
type: 'heading',
|
|
140
|
+
depth: parseInt(level),
|
|
141
|
+
children: transformNodeWithInlineChildren(node)
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
const transformParagraph = node => {
|
|
145
|
+
return {
|
|
146
|
+
type: 'paragraph',
|
|
147
|
+
children: transformNodeWithInlineChildren(node)
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
const transformBlockquote = node => {
|
|
151
|
+
const {
|
|
152
|
+
children
|
|
153
|
+
} = node;
|
|
154
|
+
return {
|
|
155
|
+
type: 'blockquote',
|
|
156
|
+
children: children.map(child => {
|
|
157
|
+
const handler = elementHandlers[child.type];
|
|
158
|
+
return handler(child);
|
|
159
|
+
}).flat() // flat
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const transformCheckList = node => {
|
|
164
|
+
return {
|
|
165
|
+
type: 'list',
|
|
166
|
+
ordered: false,
|
|
167
|
+
start: null,
|
|
168
|
+
spread: false,
|
|
169
|
+
children: [{
|
|
170
|
+
type: 'listItem',
|
|
171
|
+
spread: false,
|
|
172
|
+
checked: node.checked,
|
|
173
|
+
children: [transformParagraph(node)]
|
|
174
|
+
}]
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
const transformListContent = node => {
|
|
178
|
+
return transformParagraph(node);
|
|
179
|
+
};
|
|
180
|
+
const transformListItem = node => {
|
|
181
|
+
let loose = false;
|
|
182
|
+
const {
|
|
183
|
+
children
|
|
184
|
+
} = node;
|
|
185
|
+
// eslint-disable-next-line array-callback-return
|
|
186
|
+
const newChildren = children.map(child => {
|
|
187
|
+
if (child.type === 'paragraph') {
|
|
188
|
+
return transformListContent(child);
|
|
189
|
+
}
|
|
190
|
+
if (child.type === 'code_block') {
|
|
191
|
+
return transformCodeBlock(child);
|
|
192
|
+
}
|
|
193
|
+
if (child.type === 'blockquote') {
|
|
194
|
+
return transformBlockquote(child);
|
|
195
|
+
}
|
|
196
|
+
if (child.type === 'unordered_list' || child.type === 'ordered_list') {
|
|
197
|
+
return transformList(child);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
if (newChildren.length === 1) {
|
|
201
|
+
loose = false;
|
|
202
|
+
} else if (newChildren.length === 2 && newChildren[1].type === 'list') {
|
|
203
|
+
loose = true;
|
|
204
|
+
} else {
|
|
205
|
+
loose = true;
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
type: 'listItem',
|
|
209
|
+
loose: loose,
|
|
210
|
+
checked: null,
|
|
211
|
+
children: newChildren
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
const transformList = node => {
|
|
215
|
+
const {
|
|
216
|
+
children
|
|
217
|
+
} = node;
|
|
218
|
+
const newChildren = children.map(child => transformListItem(child));
|
|
219
|
+
let loose = false;
|
|
220
|
+
for (let node of newChildren) {
|
|
221
|
+
if (node.loose === true) {
|
|
222
|
+
loose = true;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
type: 'list',
|
|
228
|
+
ordered: node.type === 'ordered_list',
|
|
229
|
+
// ordered_list | unordered_list
|
|
230
|
+
start: 1,
|
|
231
|
+
loose: loose,
|
|
232
|
+
children: newChildren
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
const transformTableCell = cell => {
|
|
236
|
+
return {
|
|
237
|
+
type: 'tableCell',
|
|
238
|
+
children: transformNodeWithInlineChildren(cell)
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
const transformTableRow = row => {
|
|
242
|
+
const {
|
|
243
|
+
children: cells
|
|
244
|
+
} = row;
|
|
245
|
+
return {
|
|
246
|
+
type: 'tableRow',
|
|
247
|
+
children: cells.map(cell => transformTableCell(cell))
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
const transformTable = node => {
|
|
251
|
+
const {
|
|
252
|
+
children: rows
|
|
253
|
+
} = node;
|
|
254
|
+
const align = rows.map(row => {
|
|
255
|
+
var _cells$;
|
|
256
|
+
const {
|
|
257
|
+
children: cells
|
|
258
|
+
} = row;
|
|
259
|
+
return ((_cells$ = cells[0]) === null || _cells$ === void 0 ? void 0 : _cells$.align) || null;
|
|
260
|
+
});
|
|
261
|
+
return {
|
|
262
|
+
type: 'table',
|
|
263
|
+
align: align,
|
|
264
|
+
children: rows.map(row => transformTableRow(row))
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
const transformCodeLine = node => {
|
|
268
|
+
var _node$children$;
|
|
269
|
+
const text = ((_node$children$ = node.children[0]) === null || _node$children$ === void 0 ? void 0 : _node$children$.text) || '';
|
|
270
|
+
return text;
|
|
271
|
+
};
|
|
272
|
+
const transformCodeBlock = node => {
|
|
273
|
+
const {
|
|
274
|
+
children
|
|
275
|
+
} = node;
|
|
276
|
+
return {
|
|
277
|
+
type: 'code',
|
|
278
|
+
lang: node.lang ? node.lang : null,
|
|
279
|
+
value: children.map(child => transformCodeLine(child)).join('\n')
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
const transformFormula = node => {
|
|
283
|
+
const data = node.data;
|
|
284
|
+
return {
|
|
285
|
+
type: 'math',
|
|
286
|
+
value: data.formula
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
const elementHandlers = {
|
|
290
|
+
'paragraph': transformParagraph,
|
|
291
|
+
'header1': transformHeader,
|
|
292
|
+
'header2': transformHeader,
|
|
293
|
+
'header3': transformHeader,
|
|
294
|
+
'header4': transformHeader,
|
|
295
|
+
'header5': transformHeader,
|
|
296
|
+
'header6': transformHeader,
|
|
297
|
+
'blockquote': transformBlockquote,
|
|
298
|
+
'table': transformTable,
|
|
299
|
+
'check_list_item': transformCheckList,
|
|
300
|
+
'ordered_list': transformList,
|
|
301
|
+
'unordered_list': transformList,
|
|
302
|
+
'code_block': transformCodeBlock,
|
|
303
|
+
'formula': transformFormula
|
|
304
|
+
};
|
|
305
|
+
export const formatSlateToMd = children => {
|
|
306
|
+
const validChildren = children.filter(child => elementHandlers[child.type]);
|
|
307
|
+
return validChildren.map(child => {
|
|
308
|
+
const handler = elementHandlers[child.type];
|
|
309
|
+
return handler(child);
|
|
310
|
+
}).flat();
|
|
311
|
+
};
|