@seafile/seafile-editor 1.0.16 → 1.0.18
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/extension/constants/menus-config.js +2 -1
- package/dist/extension/plugins/index.js +3 -2
- package/dist/extension/plugins/markdown/index.js +5 -0
- package/dist/extension/plugins/markdown/plugin.js +188 -0
- package/dist/slate-convert/md-to-slate/transform.js +2 -0
- package/dist/slate-convert/slate-to-md/transform.js +3 -0
- package/package.json +1 -1
|
@@ -11,10 +11,11 @@ import ListPlugin from './list';
|
|
|
11
11
|
import TablePlugin from './table';
|
|
12
12
|
import FormulaPlugin from './formula';
|
|
13
13
|
import ColumnPlugin from './column';
|
|
14
|
-
|
|
14
|
+
import MarkDownPlugin from './markdown';
|
|
15
|
+
const Plugins = [BlockquotePlugin, ParagraphPlugin, TextPlugin, HeaderPlugin, ImagePlugin, LinkPlugin, CodeBlockPlugin, CheckListPlugin, ListPlugin, TablePlugin, FormulaPlugin, MarkDownPlugin, ColumnPlugin,
|
|
15
16
|
// put at the end
|
|
16
17
|
NodeIdPlugin];
|
|
17
18
|
export default Plugins;
|
|
18
|
-
export { BlockquotePlugin, ParagraphPlugin, TextPlugin, HeaderPlugin, ImagePlugin, LinkPlugin, CodeBlockPlugin, CheckListPlugin, ListPlugin, TablePlugin, FormulaPlugin, ColumnPlugin,
|
|
19
|
+
export { BlockquotePlugin, ParagraphPlugin, TextPlugin, HeaderPlugin, ImagePlugin, LinkPlugin, CodeBlockPlugin, CheckListPlugin, ListPlugin, TablePlugin, FormulaPlugin, MarkDownPlugin, ColumnPlugin,
|
|
19
20
|
// put at the end
|
|
20
21
|
NodeIdPlugin };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { Editor, Transforms, Range } from 'slate';
|
|
2
|
+
import { transformsToList } from '../list/transforms';
|
|
3
|
+
import { getSelectedNodeByType } from '../../core';
|
|
4
|
+
import { TEXT_STYLE_MAP } from '../../constants';
|
|
5
|
+
import { HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, UNORDERED_LIST, BLOCKQUOTE, PARAGRAPH } from '../../constants/element-types';
|
|
6
|
+
import { setBlockQuoteType } from '../blockquote/helpers';
|
|
7
|
+
const KEY_TO_TYPE_FOR_SPACE = {
|
|
8
|
+
// Title shortcut
|
|
9
|
+
'#': HEADER1,
|
|
10
|
+
'##': HEADER2,
|
|
11
|
+
'###': HEADER3,
|
|
12
|
+
'####': HEADER4,
|
|
13
|
+
'#####': HEADER5,
|
|
14
|
+
'######': HEADER6,
|
|
15
|
+
// List shortcut
|
|
16
|
+
'*': UNORDERED_LIST,
|
|
17
|
+
'-': UNORDERED_LIST,
|
|
18
|
+
// Reference shortcut key
|
|
19
|
+
'>': BLOCKQUOTE
|
|
20
|
+
};
|
|
21
|
+
const KEY_TO_INLINE_TYPE_FOR_SPACE = {
|
|
22
|
+
// Inline shortcut keys
|
|
23
|
+
'**': TEXT_STYLE_MAP.BOLD,
|
|
24
|
+
'*': TEXT_STYLE_MAP.ITALIC,
|
|
25
|
+
'***': TEXT_STYLE_MAP.BOLD_ITALIC
|
|
26
|
+
};
|
|
27
|
+
const getBeforeText = editor => {
|
|
28
|
+
const {
|
|
29
|
+
selection
|
|
30
|
+
} = editor;
|
|
31
|
+
if (selection == null) return {
|
|
32
|
+
beforeText: '',
|
|
33
|
+
range: null
|
|
34
|
+
};
|
|
35
|
+
const {
|
|
36
|
+
anchor
|
|
37
|
+
} = selection;
|
|
38
|
+
// Find the block element above the current text
|
|
39
|
+
const block = Editor.above(editor, {
|
|
40
|
+
match: n => Editor.isBlock(editor, n)
|
|
41
|
+
});
|
|
42
|
+
if (block == null) return {
|
|
43
|
+
beforeText: '',
|
|
44
|
+
range: null
|
|
45
|
+
};
|
|
46
|
+
const blockPath = block[1];
|
|
47
|
+
const blockStart = Editor.start(editor, blockPath); // The starting position of the block element
|
|
48
|
+
const range = {
|
|
49
|
+
anchor,
|
|
50
|
+
focus: blockStart
|
|
51
|
+
};
|
|
52
|
+
const beforeText = Editor.string(editor, range) || '';
|
|
53
|
+
return {
|
|
54
|
+
beforeText,
|
|
55
|
+
range
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const withMarkDown = editor => {
|
|
59
|
+
const {
|
|
60
|
+
insertText
|
|
61
|
+
} = editor;
|
|
62
|
+
const newEditor = editor;
|
|
63
|
+
|
|
64
|
+
// When entering a space, convert markdown
|
|
65
|
+
newEditor.insertText = text => {
|
|
66
|
+
const {
|
|
67
|
+
selection
|
|
68
|
+
} = editor;
|
|
69
|
+
if (selection == null) return insertText(text);
|
|
70
|
+
if (Range.isExpanded(selection)) return insertText(text);
|
|
71
|
+
if (getSelectedNodeByType(editor, PARAGRAPH) == null) return insertText(text); // It must be in paragraph
|
|
72
|
+
if (text !== ' ') return insertText(text); // The value must be an input space
|
|
73
|
+
|
|
74
|
+
// Gets the text before the space
|
|
75
|
+
const {
|
|
76
|
+
beforeText,
|
|
77
|
+
range
|
|
78
|
+
} = getBeforeText(editor);
|
|
79
|
+
if (!beforeText || !range) return insertText(text);
|
|
80
|
+
|
|
81
|
+
// Based on the keyword, find the type of element you want to convert
|
|
82
|
+
const type = KEY_TO_TYPE_FOR_SPACE[beforeText.trim()];
|
|
83
|
+
const italicAndBoldType = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-3)];
|
|
84
|
+
const boldType = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-2)];
|
|
85
|
+
const italicType = KEY_TO_INLINE_TYPE_FOR_SPACE[beforeText.slice(-1)];
|
|
86
|
+
if (!type && !boldType && !italicType && !italicAndBoldType) return insertText(text);
|
|
87
|
+
if (italicAndBoldType === TEXT_STYLE_MAP.BOLD_ITALIC) {
|
|
88
|
+
const restStr = beforeText === null || beforeText === void 0 ? void 0 : beforeText.slice(0, beforeText.length - 3);
|
|
89
|
+
const startOffset = restStr === null || restStr === void 0 ? void 0 : restStr.lastIndexOf('***');
|
|
90
|
+
const endOffset = (beforeText === null || beforeText === void 0 ? void 0 : beforeText.lastIndexOf('***')) + 3;
|
|
91
|
+
console.log(startOffset);
|
|
92
|
+
console.log(endOffset);
|
|
93
|
+
if (startOffset === -1) {
|
|
94
|
+
return insertText(text);
|
|
95
|
+
}
|
|
96
|
+
if (startOffset !== -3) {
|
|
97
|
+
Transforms.delete(editor, {
|
|
98
|
+
at: {
|
|
99
|
+
anchor: {
|
|
100
|
+
path: range.focus.path,
|
|
101
|
+
offset: startOffset
|
|
102
|
+
},
|
|
103
|
+
focus: {
|
|
104
|
+
...selection.focus
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
voids: true
|
|
108
|
+
});
|
|
109
|
+
const newText = beforeText.slice(startOffset + 3, endOffset - 3);
|
|
110
|
+
Editor.addMark(editor, TEXT_STYLE_MAP.BOLD, true);
|
|
111
|
+
Editor.addMark(editor, TEXT_STYLE_MAP.ITALIC, true);
|
|
112
|
+
return insertText(newText);
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (boldType === TEXT_STYLE_MAP.BOLD) {
|
|
117
|
+
const restStr = beforeText.slice(0, beforeText.length - 2);
|
|
118
|
+
const startOffset = restStr.lastIndexOf('**');
|
|
119
|
+
const endOffset = beforeText.lastIndexOf('**') + 2;
|
|
120
|
+
if (startOffset === -1) {
|
|
121
|
+
return insertText(text);
|
|
122
|
+
}
|
|
123
|
+
Transforms.delete(editor, {
|
|
124
|
+
at: {
|
|
125
|
+
anchor: {
|
|
126
|
+
path: range.focus.path,
|
|
127
|
+
offset: startOffset
|
|
128
|
+
},
|
|
129
|
+
focus: {
|
|
130
|
+
...selection.focus
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
voids: true
|
|
134
|
+
});
|
|
135
|
+
const newType = boldType.toLowerCase();
|
|
136
|
+
const newText = beforeText.slice(startOffset + 2, endOffset - 2);
|
|
137
|
+
Editor.addMark(editor, newType, true);
|
|
138
|
+
return insertText(newText);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// demos
|
|
142
|
+
// 1 '*'
|
|
143
|
+
// 2 'acd * add *'
|
|
144
|
+
if (italicType === TEXT_STYLE_MAP.ITALIC) {
|
|
145
|
+
const restStr = beforeText === null || beforeText === void 0 ? void 0 : beforeText.slice(0, beforeText.length - 1);
|
|
146
|
+
const startOffset = restStr === null || restStr === void 0 ? void 0 : restStr.lastIndexOf('*');
|
|
147
|
+
const endOffset = (beforeText === null || beforeText === void 0 ? void 0 : beforeText.lastIndexOf('*')) + 1;
|
|
148
|
+
if (startOffset === -1 && restStr.length > 0) {
|
|
149
|
+
return insertText(text);
|
|
150
|
+
}
|
|
151
|
+
if (startOffset !== -1) {
|
|
152
|
+
Transforms.delete(editor, {
|
|
153
|
+
at: {
|
|
154
|
+
anchor: {
|
|
155
|
+
path: range.focus.path,
|
|
156
|
+
offset: startOffset
|
|
157
|
+
},
|
|
158
|
+
focus: {
|
|
159
|
+
...selection.focus
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
voids: true
|
|
163
|
+
});
|
|
164
|
+
const newType = italicType.toLowerCase();
|
|
165
|
+
const newText = beforeText.slice(startOffset + 1, endOffset - 1);
|
|
166
|
+
Editor.addMark(editor, newType, true);
|
|
167
|
+
return insertText(newText);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Delete element
|
|
172
|
+
Transforms.select(editor, range);
|
|
173
|
+
Transforms.delete(editor);
|
|
174
|
+
if (type === UNORDERED_LIST) {
|
|
175
|
+
transformsToList(editor, type);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (type === BLOCKQUOTE) {
|
|
179
|
+
setBlockQuoteType(editor, false);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
Transforms.setNodes(editor, {
|
|
183
|
+
type
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
return newEditor;
|
|
187
|
+
};
|
|
188
|
+
export default withMarkDown;
|
|
@@ -154,6 +154,8 @@ export const transformListItem = node => {
|
|
|
154
154
|
return transformListContent(child);
|
|
155
155
|
} else if (child.type === 'code') {
|
|
156
156
|
return transformCodeBlock(child);
|
|
157
|
+
} else if (child.type === 'blockquote') {
|
|
158
|
+
return transformBlockquote(child);
|
|
157
159
|
} else if (child.type === 'list') {
|
|
158
160
|
return transformList(child);
|
|
159
161
|
} else if (child.type === 'html') {
|
|
@@ -151,6 +151,9 @@ const transformListItem = node => {
|
|
|
151
151
|
if (child.type === 'code_block') {
|
|
152
152
|
return transformCodeBlock(child);
|
|
153
153
|
}
|
|
154
|
+
if (child.type === 'blockquote') {
|
|
155
|
+
return transformBlockquote(child);
|
|
156
|
+
}
|
|
154
157
|
if (child.type === 'unordered_list' || child.type === 'ordered_list') {
|
|
155
158
|
return transformList(child);
|
|
156
159
|
}
|