@lexical/markdown 0.8.1 → 0.9.1
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/LexicalMarkdown.dev.js +225 -96
- package/LexicalMarkdown.prod.js +5 -5
- package/MarkdownExport.d.ts +2 -1
- package/MarkdownImport.d.ts +2 -1
- package/index.d.ts +3 -2
- package/package.json +8 -8
- package/convertToMarkdown.d.ts +0 -8
package/LexicalMarkdown.dev.js
CHANGED
|
@@ -20,16 +20,20 @@ var link = require('@lexical/link');
|
|
|
20
20
|
* LICENSE file in the root directory of this source tree.
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
|
+
|
|
23
24
|
function indexBy(list, callback) {
|
|
24
25
|
const index = {};
|
|
26
|
+
|
|
25
27
|
for (const item of list) {
|
|
26
28
|
const key = callback(item);
|
|
29
|
+
|
|
27
30
|
if (index[key]) {
|
|
28
31
|
index[key].push(item);
|
|
29
32
|
} else {
|
|
30
33
|
index[key] = [item];
|
|
31
34
|
}
|
|
32
35
|
}
|
|
36
|
+
|
|
33
37
|
return index;
|
|
34
38
|
}
|
|
35
39
|
function transformersByType(transformers) {
|
|
@@ -50,30 +54,35 @@ const PUNCTUATION_OR_SPACE = /[!-/:-@[-`{-~\s]/;
|
|
|
50
54
|
*
|
|
51
55
|
*/
|
|
52
56
|
function createMarkdownExport(transformers) {
|
|
53
|
-
const byType = transformersByType(transformers);
|
|
54
|
-
|
|
55
|
-
// Export only uses text formats that are responsible for single format
|
|
57
|
+
const byType = transformersByType(transformers); // Export only uses text formats that are responsible for single format
|
|
56
58
|
// e.g. it will filter out *** (bold, italic) and instead use separate ** and *
|
|
59
|
+
|
|
57
60
|
const textFormatTransformers = byType.textFormat.filter(transformer => transformer.format.length === 1);
|
|
58
|
-
return
|
|
61
|
+
return node => {
|
|
59
62
|
const output = [];
|
|
60
|
-
const children = lexical.$getRoot().getChildren();
|
|
63
|
+
const children = (node || lexical.$getRoot()).getChildren();
|
|
64
|
+
|
|
61
65
|
for (const child of children) {
|
|
62
66
|
const result = exportTopLevelElements(child, byType.element, textFormatTransformers, byType.textMatch);
|
|
67
|
+
|
|
63
68
|
if (result != null) {
|
|
64
69
|
output.push(result);
|
|
65
70
|
}
|
|
66
71
|
}
|
|
72
|
+
|
|
67
73
|
return output.join('\n\n');
|
|
68
74
|
};
|
|
69
75
|
}
|
|
76
|
+
|
|
70
77
|
function exportTopLevelElements(node, elementTransformers, textTransformersIndex, textMatchTransformers) {
|
|
71
78
|
for (const transformer of elementTransformers) {
|
|
72
79
|
const result = transformer.export(node, _node => exportChildren(_node, textTransformersIndex, textMatchTransformers));
|
|
80
|
+
|
|
73
81
|
if (result != null) {
|
|
74
82
|
return result;
|
|
75
83
|
}
|
|
76
84
|
}
|
|
85
|
+
|
|
77
86
|
if (lexical.$isElementNode(node)) {
|
|
78
87
|
return exportChildren(node, textTransformersIndex, textMatchTransformers);
|
|
79
88
|
} else if (lexical.$isDecoratorNode(node)) {
|
|
@@ -82,17 +91,21 @@ function exportTopLevelElements(node, elementTransformers, textTransformersIndex
|
|
|
82
91
|
return null;
|
|
83
92
|
}
|
|
84
93
|
}
|
|
94
|
+
|
|
85
95
|
function exportChildren(node, textTransformersIndex, textMatchTransformers) {
|
|
86
96
|
const output = [];
|
|
87
97
|
const children = node.getChildren();
|
|
98
|
+
|
|
88
99
|
mainLoop: for (const child of children) {
|
|
89
100
|
for (const transformer of textMatchTransformers) {
|
|
90
101
|
const result = transformer.export(child, parentNode => exportChildren(parentNode, textTransformersIndex, textMatchTransformers), (textNode, textContent) => exportTextFormat(textNode, textContent, textTransformersIndex));
|
|
102
|
+
|
|
91
103
|
if (result != null) {
|
|
92
104
|
output.push(result);
|
|
93
105
|
continue mainLoop;
|
|
94
106
|
}
|
|
95
107
|
}
|
|
108
|
+
|
|
96
109
|
if (lexical.$isLineBreakNode(child)) {
|
|
97
110
|
output.push('\n');
|
|
98
111
|
} else if (lexical.$isTextNode(child)) {
|
|
@@ -103,8 +116,10 @@ function exportChildren(node, textTransformersIndex, textMatchTransformers) {
|
|
|
103
116
|
output.push(child.getTextContent());
|
|
104
117
|
}
|
|
105
118
|
}
|
|
119
|
+
|
|
106
120
|
return output.join('');
|
|
107
121
|
}
|
|
122
|
+
|
|
108
123
|
function exportTextFormat(node, textContent, textTransformers) {
|
|
109
124
|
// This function handles the case of a string looking like this: " foo "
|
|
110
125
|
// Where it would be invalid markdown to generate: "** foo **"
|
|
@@ -113,61 +128,74 @@ function exportTextFormat(node, textContent, textTransformers) {
|
|
|
113
128
|
const frozenString = textContent.trim();
|
|
114
129
|
let output = frozenString;
|
|
115
130
|
const applied = new Set();
|
|
131
|
+
|
|
116
132
|
for (const transformer of textTransformers) {
|
|
117
133
|
const format = transformer.format[0];
|
|
118
134
|
const tag = transformer.tag;
|
|
135
|
+
|
|
119
136
|
if (hasFormat(node, format) && !applied.has(format)) {
|
|
120
137
|
// Multiple tags might be used for the same format (*, _)
|
|
121
|
-
applied.add(format);
|
|
122
|
-
|
|
138
|
+
applied.add(format); // Prevent adding opening tag is already opened by the previous sibling
|
|
139
|
+
|
|
123
140
|
const previousNode = getTextSibling(node, true);
|
|
141
|
+
|
|
124
142
|
if (!hasFormat(previousNode, format)) {
|
|
125
143
|
output = tag + output;
|
|
126
|
-
}
|
|
144
|
+
} // Prevent adding closing tag if next sibling will do it
|
|
145
|
+
|
|
127
146
|
|
|
128
|
-
// Prevent adding closing tag if next sibling will do it
|
|
129
147
|
const nextNode = getTextSibling(node, false);
|
|
148
|
+
|
|
130
149
|
if (!hasFormat(nextNode, format)) {
|
|
131
150
|
output += tag;
|
|
132
151
|
}
|
|
133
152
|
}
|
|
134
|
-
}
|
|
153
|
+
} // Replace trimmed version of textContent ensuring surrounding whitespace is not modified
|
|
135
154
|
|
|
136
|
-
// Replace trimmed version of textContent ensuring surrounding whitespace is not modified
|
|
137
|
-
return textContent.replace(frozenString, output);
|
|
138
|
-
}
|
|
139
155
|
|
|
140
|
-
|
|
156
|
+
return textContent.replace(frozenString, output);
|
|
157
|
+
} // Get next or previous text sibling a text node, including cases
|
|
141
158
|
// when it's a child of inline element (e.g. link)
|
|
159
|
+
|
|
160
|
+
|
|
142
161
|
function getTextSibling(node, backward) {
|
|
143
162
|
let sibling = backward ? node.getPreviousSibling() : node.getNextSibling();
|
|
163
|
+
|
|
144
164
|
if (!sibling) {
|
|
145
165
|
const parent = node.getParentOrThrow();
|
|
166
|
+
|
|
146
167
|
if (parent.isInline()) {
|
|
147
168
|
sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling();
|
|
148
169
|
}
|
|
149
170
|
}
|
|
171
|
+
|
|
150
172
|
while (sibling) {
|
|
151
173
|
if (lexical.$isElementNode(sibling)) {
|
|
152
174
|
if (!sibling.isInline()) {
|
|
153
175
|
break;
|
|
154
176
|
}
|
|
177
|
+
|
|
155
178
|
const descendant = backward ? sibling.getLastDescendant() : sibling.getFirstDescendant();
|
|
179
|
+
|
|
156
180
|
if (lexical.$isTextNode(descendant)) {
|
|
157
181
|
return descendant;
|
|
158
182
|
} else {
|
|
159
183
|
sibling = backward ? sibling.getPreviousSibling() : sibling.getNextSibling();
|
|
160
184
|
}
|
|
161
185
|
}
|
|
186
|
+
|
|
162
187
|
if (lexical.$isTextNode(sibling)) {
|
|
163
188
|
return sibling;
|
|
164
189
|
}
|
|
190
|
+
|
|
165
191
|
if (!lexical.$isElementNode(sibling)) {
|
|
166
192
|
return null;
|
|
167
193
|
}
|
|
168
194
|
}
|
|
195
|
+
|
|
169
196
|
return null;
|
|
170
197
|
}
|
|
198
|
+
|
|
171
199
|
function hasFormat(node, format) {
|
|
172
200
|
return lexical.$isTextNode(node) && node.hasFormat(format);
|
|
173
201
|
}
|
|
@@ -179,7 +207,6 @@ function hasFormat(node, format) {
|
|
|
179
207
|
* LICENSE file in the root directory of this source tree.
|
|
180
208
|
*
|
|
181
209
|
*/
|
|
182
|
-
|
|
183
210
|
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
184
211
|
|
|
185
212
|
/**
|
|
@@ -194,12 +221,10 @@ CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
|
194
221
|
CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
|
|
195
222
|
CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
|
|
196
223
|
const IS_SAFARI = CAN_USE_DOM && /Version\/[\d.]+.*Safari/.test(navigator.userAgent);
|
|
197
|
-
const IS_IOS = CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
|
198
|
-
|
|
199
|
-
// Keep these in case we need to use them in the future.
|
|
224
|
+
const IS_IOS = CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; // Keep these in case we need to use them in the future.
|
|
200
225
|
// export const IS_WINDOWS: boolean = CAN_USE_DOM && /Win/.test(navigator.platform);
|
|
201
|
-
|
|
202
|
-
// export const canUseTextInputEvent: boolean = CAN_USE_DOM && 'TextEvent' in window && !documentMode;
|
|
226
|
+
|
|
227
|
+
const IS_CHROME = CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent); // export const canUseTextInputEvent: boolean = CAN_USE_DOM && 'TextEvent' in window && !documentMode;
|
|
203
228
|
|
|
204
229
|
const IS_APPLE_WEBKIT = CAN_USE_DOM && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && !IS_CHROME;
|
|
205
230
|
|
|
@@ -215,77 +240,89 @@ const CODE_BLOCK_REG_EXP = /^```(\w{1,10})?\s?$/;
|
|
|
215
240
|
function createMarkdownImport(transformers) {
|
|
216
241
|
const byType = transformersByType(transformers);
|
|
217
242
|
const textFormatTransformersIndex = createTextFormatTransformersIndex(byType.textFormat);
|
|
218
|
-
return markdownString => {
|
|
243
|
+
return (markdownString, node) => {
|
|
219
244
|
const lines = markdownString.split('\n');
|
|
220
245
|
const linesLength = lines.length;
|
|
221
|
-
const root = lexical.$getRoot();
|
|
246
|
+
const root = node || lexical.$getRoot();
|
|
222
247
|
root.clear();
|
|
248
|
+
|
|
223
249
|
for (let i = 0; i < linesLength; i++) {
|
|
224
|
-
const lineText = lines[i];
|
|
225
|
-
// Codeblocks are processed first as anything inside such block
|
|
250
|
+
const lineText = lines[i]; // Codeblocks are processed first as anything inside such block
|
|
226
251
|
// is ignored for further processing
|
|
227
252
|
// TODO:
|
|
228
253
|
// Abstract it to be dynamic as other transformers (add multiline match option)
|
|
254
|
+
|
|
229
255
|
const [codeBlockNode, shiftedIndex] = importCodeBlock(lines, i, root);
|
|
256
|
+
|
|
230
257
|
if (codeBlockNode != null) {
|
|
231
258
|
i = shiftedIndex;
|
|
232
259
|
continue;
|
|
233
260
|
}
|
|
234
|
-
importBlocks(lineText, root, byType.element, textFormatTransformersIndex, byType.textMatch);
|
|
235
|
-
}
|
|
236
261
|
|
|
237
|
-
|
|
262
|
+
importBlocks(lineText, root, byType.element, textFormatTransformersIndex, byType.textMatch);
|
|
263
|
+
} // Removing empty paragraphs as md does not really
|
|
238
264
|
// allow empty lines and uses them as dilimiter
|
|
265
|
+
|
|
266
|
+
|
|
239
267
|
const children = root.getChildren();
|
|
268
|
+
|
|
240
269
|
for (const child of children) {
|
|
241
270
|
if (isEmptyParagraph(child)) {
|
|
242
271
|
child.remove();
|
|
243
272
|
}
|
|
244
273
|
}
|
|
245
|
-
root.selectEnd();
|
|
246
274
|
};
|
|
247
275
|
}
|
|
276
|
+
|
|
248
277
|
function isEmptyParagraph(node) {
|
|
249
278
|
if (!lexical.$isParagraphNode(node)) {
|
|
250
279
|
return false;
|
|
251
280
|
}
|
|
281
|
+
|
|
252
282
|
const firstChild = node.getFirstChild();
|
|
253
283
|
return firstChild == null || node.getChildrenSize() === 1 && lexical.$isTextNode(firstChild) && MARKDOWN_EMPTY_LINE_REG_EXP.test(firstChild.getTextContent());
|
|
254
284
|
}
|
|
285
|
+
|
|
255
286
|
function importBlocks(lineText, rootNode, elementTransformers, textFormatTransformersIndex, textMatchTransformers) {
|
|
256
287
|
const lineTextTrimmed = lineText.trim();
|
|
257
288
|
const textNode = lexical.$createTextNode(lineTextTrimmed);
|
|
258
289
|
const elementNode = lexical.$createParagraphNode();
|
|
259
290
|
elementNode.append(textNode);
|
|
260
291
|
rootNode.append(elementNode);
|
|
292
|
+
|
|
261
293
|
for (const {
|
|
262
294
|
regExp,
|
|
263
295
|
replace
|
|
264
296
|
} of elementTransformers) {
|
|
265
297
|
const match = lineText.match(regExp);
|
|
298
|
+
|
|
266
299
|
if (match) {
|
|
267
300
|
textNode.setTextContent(lineText.slice(match[0].length));
|
|
268
301
|
replace(elementNode, [textNode], match, true);
|
|
269
302
|
break;
|
|
270
303
|
}
|
|
271
304
|
}
|
|
272
|
-
importTextFormatTransformers(textNode, textFormatTransformersIndex, textMatchTransformers);
|
|
273
305
|
|
|
274
|
-
// If no transformer found and we left with original paragraph node
|
|
306
|
+
importTextFormatTransformers(textNode, textFormatTransformersIndex, textMatchTransformers); // If no transformer found and we left with original paragraph node
|
|
275
307
|
// can check if its content can be appended to the previous node
|
|
276
308
|
// if it's a paragraph, quote or list
|
|
309
|
+
|
|
277
310
|
if (elementNode.isAttached() && lineTextTrimmed.length > 0) {
|
|
278
311
|
const previousNode = elementNode.getPreviousSibling();
|
|
312
|
+
|
|
279
313
|
if (lexical.$isParagraphNode(previousNode) || richText.$isQuoteNode(previousNode) || list.$isListNode(previousNode)) {
|
|
280
314
|
let targetNode = previousNode;
|
|
315
|
+
|
|
281
316
|
if (list.$isListNode(previousNode)) {
|
|
282
317
|
const lastDescendant = previousNode.getLastDescendant();
|
|
318
|
+
|
|
283
319
|
if (lastDescendant == null) {
|
|
284
320
|
targetNode = null;
|
|
285
321
|
} else {
|
|
286
322
|
targetNode = utils.$findMatchingParent(lastDescendant, list.$isListItemNode);
|
|
287
323
|
}
|
|
288
324
|
}
|
|
325
|
+
|
|
289
326
|
if (targetNode != null && targetNode.getTextContentSize() > 0) {
|
|
290
327
|
targetNode.splice(targetNode.getChildrenSize(), 0, [lexical.$createLineBreakNode(), ...elementNode.getChildren()]);
|
|
291
328
|
elementNode.remove();
|
|
@@ -293,13 +330,17 @@ function importBlocks(lineText, rootNode, elementTransformers, textFormatTransfo
|
|
|
293
330
|
}
|
|
294
331
|
}
|
|
295
332
|
}
|
|
333
|
+
|
|
296
334
|
function importCodeBlock(lines, startLineIndex, rootNode) {
|
|
297
335
|
const openMatch = lines[startLineIndex].match(CODE_BLOCK_REG_EXP);
|
|
336
|
+
|
|
298
337
|
if (openMatch) {
|
|
299
338
|
let endLineIndex = startLineIndex;
|
|
300
339
|
const linesLength = lines.length;
|
|
340
|
+
|
|
301
341
|
while (++endLineIndex < linesLength) {
|
|
302
342
|
const closeMatch = lines[endLineIndex].match(CODE_BLOCK_REG_EXP);
|
|
343
|
+
|
|
303
344
|
if (closeMatch) {
|
|
304
345
|
const codeBlockNode = code.$createCodeNode(openMatch[1]);
|
|
305
346
|
const textNode = lexical.$createTextNode(lines.slice(startLineIndex + 1, endLineIndex).join('\n'));
|
|
@@ -309,133 +350,157 @@ function importCodeBlock(lines, startLineIndex, rootNode) {
|
|
|
309
350
|
}
|
|
310
351
|
}
|
|
311
352
|
}
|
|
312
|
-
return [null, startLineIndex];
|
|
313
|
-
}
|
|
314
353
|
|
|
315
|
-
|
|
354
|
+
return [null, startLineIndex];
|
|
355
|
+
} // Processing text content and replaces text format tags.
|
|
316
356
|
// It takes outermost tag match and its content, creates text node with
|
|
317
357
|
// format based on tag and then recursively executed over node's content
|
|
318
358
|
//
|
|
319
359
|
// E.g. for "*Hello **world**!*" string it will create text node with
|
|
320
360
|
// "Hello **world**!" content and italic format and run recursively over
|
|
321
361
|
// its content to transform "**world**" part
|
|
362
|
+
|
|
363
|
+
|
|
322
364
|
function importTextFormatTransformers(textNode, textFormatTransformersIndex, textMatchTransformers) {
|
|
323
365
|
const textContent = textNode.getTextContent();
|
|
324
366
|
const match = findOutermostMatch(textContent, textFormatTransformersIndex);
|
|
367
|
+
|
|
325
368
|
if (!match) {
|
|
326
369
|
// Once text format processing is done run text match transformers, as it
|
|
327
370
|
// only can span within single text node (unline formats that can cover multiple nodes)
|
|
328
371
|
importTextMatchTransformers(textNode, textMatchTransformers);
|
|
329
372
|
return;
|
|
330
373
|
}
|
|
331
|
-
let currentNode, remainderNode, leadingNode;
|
|
332
374
|
|
|
333
|
-
// If matching full content there's no need to run splitText and can reuse existing textNode
|
|
375
|
+
let currentNode, remainderNode, leadingNode; // If matching full content there's no need to run splitText and can reuse existing textNode
|
|
334
376
|
// to update its content and apply format. E.g. for **_Hello_** string after applying bold
|
|
335
377
|
// format (**) it will reuse the same text node to apply italic (_)
|
|
378
|
+
|
|
336
379
|
if (match[0] === textContent) {
|
|
337
380
|
currentNode = textNode;
|
|
338
381
|
} else {
|
|
339
382
|
const startIndex = match.index || 0;
|
|
340
383
|
const endIndex = startIndex + match[0].length;
|
|
384
|
+
|
|
341
385
|
if (startIndex === 0) {
|
|
342
386
|
[currentNode, remainderNode] = textNode.splitText(endIndex);
|
|
343
387
|
} else {
|
|
344
388
|
[leadingNode, currentNode, remainderNode] = textNode.splitText(startIndex, endIndex);
|
|
345
389
|
}
|
|
346
390
|
}
|
|
391
|
+
|
|
347
392
|
currentNode.setTextContent(match[2]);
|
|
348
393
|
const transformer = textFormatTransformersIndex.transformersByTag[match[1]];
|
|
394
|
+
|
|
349
395
|
if (transformer) {
|
|
350
396
|
for (const format of transformer.format) {
|
|
351
397
|
if (!currentNode.hasFormat(format)) {
|
|
352
398
|
currentNode.toggleFormat(format);
|
|
353
399
|
}
|
|
354
400
|
}
|
|
355
|
-
}
|
|
401
|
+
} // Recursively run over inner text if it's not inline code
|
|
402
|
+
|
|
356
403
|
|
|
357
|
-
// Recursively run over inner text if it's not inline code
|
|
358
404
|
if (!currentNode.hasFormat('code')) {
|
|
359
405
|
importTextFormatTransformers(currentNode, textFormatTransformersIndex, textMatchTransformers);
|
|
360
|
-
}
|
|
406
|
+
} // Run over leading/remaining text if any
|
|
407
|
+
|
|
361
408
|
|
|
362
|
-
// Run over leading/remaining text if any
|
|
363
409
|
if (leadingNode) {
|
|
364
410
|
importTextFormatTransformers(leadingNode, textFormatTransformersIndex, textMatchTransformers);
|
|
365
411
|
}
|
|
412
|
+
|
|
366
413
|
if (remainderNode) {
|
|
367
414
|
importTextFormatTransformers(remainderNode, textFormatTransformersIndex, textMatchTransformers);
|
|
368
415
|
}
|
|
369
416
|
}
|
|
417
|
+
|
|
370
418
|
function importTextMatchTransformers(textNode_, textMatchTransformers) {
|
|
371
419
|
let textNode = textNode_;
|
|
420
|
+
|
|
372
421
|
mainLoop: while (textNode) {
|
|
373
422
|
for (const transformer of textMatchTransformers) {
|
|
374
423
|
const match = textNode.getTextContent().match(transformer.importRegExp);
|
|
424
|
+
|
|
375
425
|
if (!match) {
|
|
376
426
|
continue;
|
|
377
427
|
}
|
|
428
|
+
|
|
378
429
|
const startIndex = match.index || 0;
|
|
379
430
|
const endIndex = startIndex + match[0].length;
|
|
380
431
|
let replaceNode, leftTextNode, rightTextNode;
|
|
432
|
+
|
|
381
433
|
if (startIndex === 0) {
|
|
382
434
|
[replaceNode, textNode] = textNode.splitText(endIndex);
|
|
383
435
|
} else {
|
|
384
436
|
[leftTextNode, replaceNode, rightTextNode] = textNode.splitText(startIndex, endIndex);
|
|
385
437
|
}
|
|
438
|
+
|
|
386
439
|
if (leftTextNode) {
|
|
387
440
|
importTextMatchTransformers(leftTextNode, textMatchTransformers);
|
|
388
441
|
}
|
|
442
|
+
|
|
389
443
|
if (rightTextNode) {
|
|
390
444
|
textNode = rightTextNode;
|
|
391
445
|
}
|
|
446
|
+
|
|
392
447
|
transformer.replace(replaceNode, match);
|
|
393
448
|
continue mainLoop;
|
|
394
449
|
}
|
|
450
|
+
|
|
395
451
|
break;
|
|
396
452
|
}
|
|
397
|
-
}
|
|
453
|
+
} // Finds first "<tag>content<tag>" match that is not nested into another tag
|
|
454
|
+
|
|
398
455
|
|
|
399
|
-
// Finds first "<tag>content<tag>" match that is not nested into another tag
|
|
400
456
|
function findOutermostMatch(textContent, textTransformersIndex) {
|
|
401
457
|
const openTagsMatch = textContent.match(textTransformersIndex.openTagsRegExp);
|
|
458
|
+
|
|
402
459
|
if (openTagsMatch == null) {
|
|
403
460
|
return null;
|
|
404
461
|
}
|
|
462
|
+
|
|
405
463
|
for (const match of openTagsMatch) {
|
|
406
464
|
// Open tags reg exp might capture leading space so removing it
|
|
407
465
|
// before using match to find transformer
|
|
408
466
|
const tag = match.replace(/^\s/, '');
|
|
409
467
|
const fullMatchRegExp = textTransformersIndex.fullMatchRegExpByTag[tag];
|
|
468
|
+
|
|
410
469
|
if (fullMatchRegExp == null) {
|
|
411
470
|
continue;
|
|
412
471
|
}
|
|
472
|
+
|
|
413
473
|
const fullMatch = textContent.match(fullMatchRegExp);
|
|
414
474
|
const transformer = textTransformersIndex.transformersByTag[tag];
|
|
475
|
+
|
|
415
476
|
if (fullMatch != null && transformer != null) {
|
|
416
477
|
if (transformer.intraword !== false) {
|
|
417
478
|
return fullMatch;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// For non-intraword transformers checking if it's within a word
|
|
479
|
+
} // For non-intraword transformers checking if it's within a word
|
|
421
480
|
// or surrounded with space/punctuation/newline
|
|
481
|
+
|
|
482
|
+
|
|
422
483
|
const {
|
|
423
484
|
index = 0
|
|
424
485
|
} = fullMatch;
|
|
425
486
|
const beforeChar = textContent[index - 1];
|
|
426
487
|
const afterChar = textContent[index + fullMatch[0].length];
|
|
488
|
+
|
|
427
489
|
if ((!beforeChar || PUNCTUATION_OR_SPACE.test(beforeChar)) && (!afterChar || PUNCTUATION_OR_SPACE.test(afterChar))) {
|
|
428
490
|
return fullMatch;
|
|
429
491
|
}
|
|
430
492
|
}
|
|
431
493
|
}
|
|
494
|
+
|
|
432
495
|
return null;
|
|
433
496
|
}
|
|
497
|
+
|
|
434
498
|
function createTextFormatTransformersIndex(textTransformers) {
|
|
435
499
|
const transformersByTag = {};
|
|
436
500
|
const fullMatchRegExpByTag = {};
|
|
437
501
|
const openTagsRegExp = [];
|
|
438
502
|
const escapeRegExp = `(?<![\\\\])`;
|
|
503
|
+
|
|
439
504
|
for (const transformer of textTransformers) {
|
|
440
505
|
const {
|
|
441
506
|
tag
|
|
@@ -443,12 +508,14 @@ function createTextFormatTransformersIndex(textTransformers) {
|
|
|
443
508
|
transformersByTag[tag] = transformer;
|
|
444
509
|
const tagRegExp = tag.replace(/(\*|\^|\+)/g, '\\$1');
|
|
445
510
|
openTagsRegExp.push(tagRegExp);
|
|
511
|
+
|
|
446
512
|
if (IS_SAFARI || IS_IOS || IS_APPLE_WEBKIT) {
|
|
447
513
|
fullMatchRegExpByTag[tag] = new RegExp(`(${tagRegExp})(?![${tagRegExp}\\s])(.*?[^${tagRegExp}\\s])${tagRegExp}(?!${tagRegExp})`);
|
|
448
514
|
} else {
|
|
449
515
|
fullMatchRegExpByTag[tag] = new RegExp(`(?<![\\\\${tagRegExp}])(${tagRegExp})((\\\\${tagRegExp})?.*?[^${tagRegExp}\\s](\\\\${tagRegExp})?)((?<!\\\\)|(?<=\\\\\\\\))(${tagRegExp})(?![\\\\${tagRegExp}])`);
|
|
450
516
|
}
|
|
451
517
|
}
|
|
518
|
+
|
|
452
519
|
return {
|
|
453
520
|
// Reg exp to find open tag + content + close tag
|
|
454
521
|
fullMatchRegExpByTag,
|
|
@@ -465,27 +532,31 @@ function createTextFormatTransformersIndex(textTransformers) {
|
|
|
465
532
|
* LICENSE file in the root directory of this source tree.
|
|
466
533
|
*
|
|
467
534
|
*/
|
|
535
|
+
|
|
468
536
|
function runElementTransformers(parentNode, anchorNode, anchorOffset, elementTransformers) {
|
|
469
537
|
const grandParentNode = parentNode.getParent();
|
|
538
|
+
|
|
470
539
|
if (!lexical.$isRootOrShadowRoot(grandParentNode) || parentNode.getFirstChild() !== anchorNode) {
|
|
471
540
|
return false;
|
|
472
541
|
}
|
|
473
|
-
const textContent = anchorNode.getTextContent();
|
|
474
542
|
|
|
475
|
-
// Checking for anchorOffset position to prevent any checks for cases when caret is too far
|
|
543
|
+
const textContent = anchorNode.getTextContent(); // Checking for anchorOffset position to prevent any checks for cases when caret is too far
|
|
476
544
|
// from a line start to be a part of block-level markdown trigger.
|
|
477
545
|
//
|
|
478
546
|
// TODO:
|
|
479
547
|
// Can have a quick check if caret is close enough to the beginning of the string (e.g. offset less than 10-20)
|
|
480
548
|
// since otherwise it won't be a markdown shortcut, but tables are exception
|
|
549
|
+
|
|
481
550
|
if (textContent[anchorOffset - 1] !== ' ') {
|
|
482
551
|
return false;
|
|
483
552
|
}
|
|
553
|
+
|
|
484
554
|
for (const {
|
|
485
555
|
regExp,
|
|
486
556
|
replace
|
|
487
557
|
} of elementTransformers) {
|
|
488
558
|
const match = textContent.match(regExp);
|
|
559
|
+
|
|
489
560
|
if (match && match[0].length === anchorOffset) {
|
|
490
561
|
const nextSiblings = anchorNode.getNextSiblings();
|
|
491
562
|
const [leadingNode, remainderNode] = anchorNode.splitText(anchorOffset);
|
|
@@ -495,115 +566,131 @@ function runElementTransformers(parentNode, anchorNode, anchorOffset, elementTra
|
|
|
495
566
|
return true;
|
|
496
567
|
}
|
|
497
568
|
}
|
|
569
|
+
|
|
498
570
|
return false;
|
|
499
571
|
}
|
|
572
|
+
|
|
500
573
|
function runTextMatchTransformers(anchorNode, anchorOffset, transformersByTrigger) {
|
|
501
574
|
let textContent = anchorNode.getTextContent();
|
|
502
575
|
const lastChar = textContent[anchorOffset - 1];
|
|
503
576
|
const transformers = transformersByTrigger[lastChar];
|
|
577
|
+
|
|
504
578
|
if (transformers == null) {
|
|
505
579
|
return false;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// If typing in the middle of content, remove the tail to do
|
|
580
|
+
} // If typing in the middle of content, remove the tail to do
|
|
509
581
|
// reg exp match up to a string end (caret position)
|
|
582
|
+
|
|
583
|
+
|
|
510
584
|
if (anchorOffset < textContent.length) {
|
|
511
585
|
textContent = textContent.slice(0, anchorOffset);
|
|
512
586
|
}
|
|
587
|
+
|
|
513
588
|
for (const transformer of transformers) {
|
|
514
589
|
const match = textContent.match(transformer.regExp);
|
|
590
|
+
|
|
515
591
|
if (match === null) {
|
|
516
592
|
continue;
|
|
517
593
|
}
|
|
594
|
+
|
|
518
595
|
const startIndex = match.index || 0;
|
|
519
596
|
const endIndex = startIndex + match[0].length;
|
|
520
597
|
let replaceNode;
|
|
598
|
+
|
|
521
599
|
if (startIndex === 0) {
|
|
522
600
|
[replaceNode] = anchorNode.splitText(endIndex);
|
|
523
601
|
} else {
|
|
524
602
|
[, replaceNode] = anchorNode.splitText(startIndex, endIndex);
|
|
525
603
|
}
|
|
604
|
+
|
|
526
605
|
replaceNode.selectNext(0, 0);
|
|
527
606
|
transformer.replace(replaceNode, match);
|
|
528
607
|
return true;
|
|
529
608
|
}
|
|
609
|
+
|
|
530
610
|
return false;
|
|
531
611
|
}
|
|
612
|
+
|
|
532
613
|
function runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransformers) {
|
|
533
614
|
const textContent = anchorNode.getTextContent();
|
|
534
615
|
const closeTagEndIndex = anchorOffset - 1;
|
|
535
|
-
const closeChar = textContent[closeTagEndIndex];
|
|
536
|
-
|
|
616
|
+
const closeChar = textContent[closeTagEndIndex]; // Quick check if we're possibly at the end of inline markdown style
|
|
617
|
+
|
|
537
618
|
const matchers = textFormatTransformers[closeChar];
|
|
619
|
+
|
|
538
620
|
if (!matchers) {
|
|
539
621
|
return false;
|
|
540
622
|
}
|
|
623
|
+
|
|
541
624
|
for (const matcher of matchers) {
|
|
542
625
|
const {
|
|
543
626
|
tag
|
|
544
627
|
} = matcher;
|
|
545
628
|
const tagLength = tag.length;
|
|
546
|
-
const closeTagStartIndex = closeTagEndIndex - tagLength + 1;
|
|
629
|
+
const closeTagStartIndex = closeTagEndIndex - tagLength + 1; // If tag is not single char check if rest of it matches with text content
|
|
547
630
|
|
|
548
|
-
// If tag is not single char check if rest of it matches with text content
|
|
549
631
|
if (tagLength > 1) {
|
|
550
632
|
if (!isEqualSubString(textContent, closeTagStartIndex, tag, 0, tagLength)) {
|
|
551
633
|
continue;
|
|
552
634
|
}
|
|
553
|
-
}
|
|
635
|
+
} // Space before closing tag cancels inline markdown
|
|
636
|
+
|
|
554
637
|
|
|
555
|
-
// Space before closing tag cancels inline markdown
|
|
556
638
|
if (textContent[closeTagStartIndex - 1] === ' ') {
|
|
557
639
|
continue;
|
|
558
|
-
}
|
|
640
|
+
} // Some tags can not be used within words, hence should have newline/space/punctuation after it
|
|
641
|
+
|
|
559
642
|
|
|
560
|
-
// Some tags can not be used within words, hence should have newline/space/punctuation after it
|
|
561
643
|
const afterCloseTagChar = textContent[closeTagEndIndex + 1];
|
|
644
|
+
|
|
562
645
|
if (matcher.intraword === false && afterCloseTagChar && !PUNCTUATION_OR_SPACE.test(afterCloseTagChar)) {
|
|
563
646
|
continue;
|
|
564
647
|
}
|
|
648
|
+
|
|
565
649
|
const closeNode = anchorNode;
|
|
566
650
|
let openNode = closeNode;
|
|
567
|
-
let openTagStartIndex = getOpenTagStartIndex(textContent, closeTagStartIndex, tag);
|
|
568
|
-
|
|
569
|
-
// Go through text node siblings and search for opening tag
|
|
651
|
+
let openTagStartIndex = getOpenTagStartIndex(textContent, closeTagStartIndex, tag); // Go through text node siblings and search for opening tag
|
|
570
652
|
// if haven't found it within the same text node as closing tag
|
|
653
|
+
|
|
571
654
|
let sibling = openNode;
|
|
655
|
+
|
|
572
656
|
while (openTagStartIndex < 0 && (sibling = sibling.getPreviousSibling())) {
|
|
573
657
|
if (lexical.$isLineBreakNode(sibling)) {
|
|
574
658
|
break;
|
|
575
659
|
}
|
|
660
|
+
|
|
576
661
|
if (lexical.$isTextNode(sibling)) {
|
|
577
662
|
const siblingTextContent = sibling.getTextContent();
|
|
578
663
|
openNode = sibling;
|
|
579
664
|
openTagStartIndex = getOpenTagStartIndex(siblingTextContent, siblingTextContent.length, tag);
|
|
580
665
|
}
|
|
581
|
-
}
|
|
666
|
+
} // Opening tag is not found
|
|
667
|
+
|
|
582
668
|
|
|
583
|
-
// Opening tag is not found
|
|
584
669
|
if (openTagStartIndex < 0) {
|
|
585
670
|
continue;
|
|
586
|
-
}
|
|
671
|
+
} // No content between opening and closing tag
|
|
672
|
+
|
|
587
673
|
|
|
588
|
-
// No content between opening and closing tag
|
|
589
674
|
if (openNode === closeNode && openTagStartIndex + tagLength === closeTagStartIndex) {
|
|
590
675
|
continue;
|
|
591
|
-
}
|
|
676
|
+
} // Checking longer tags for repeating chars (e.g. *** vs **)
|
|
677
|
+
|
|
592
678
|
|
|
593
|
-
// Checking longer tags for repeating chars (e.g. *** vs **)
|
|
594
679
|
const prevOpenNodeText = openNode.getTextContent();
|
|
680
|
+
|
|
595
681
|
if (openTagStartIndex > 0 && prevOpenNodeText[openTagStartIndex - 1] === closeChar) {
|
|
596
682
|
continue;
|
|
597
|
-
}
|
|
683
|
+
} // Some tags can not be used within words, hence should have newline/space/punctuation before it
|
|
684
|
+
|
|
598
685
|
|
|
599
|
-
// Some tags can not be used within words, hence should have newline/space/punctuation before it
|
|
600
686
|
const beforeOpenTagChar = prevOpenNodeText[openTagStartIndex - 1];
|
|
687
|
+
|
|
601
688
|
if (matcher.intraword === false && beforeOpenTagChar && !PUNCTUATION_OR_SPACE.test(beforeOpenTagChar)) {
|
|
602
689
|
continue;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
// Clean text from opening and closing tags (starting from closing tag
|
|
690
|
+
} // Clean text from opening and closing tags (starting from closing tag
|
|
606
691
|
// to prevent any offset shifts if we start from opening one)
|
|
692
|
+
|
|
693
|
+
|
|
607
694
|
const prevCloseNodeText = closeNode.getTextContent();
|
|
608
695
|
const closeNodeText = prevCloseNodeText.slice(0, closeTagStartIndex) + prevCloseNodeText.slice(closeTagEndIndex + 1);
|
|
609
696
|
closeNode.setTextContent(closeNodeText);
|
|
@@ -611,55 +698,62 @@ function runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransform
|
|
|
611
698
|
openNode.setTextContent(openNodeText.slice(0, openTagStartIndex) + openNodeText.slice(openTagStartIndex + tagLength));
|
|
612
699
|
const selection = lexical.$getSelection();
|
|
613
700
|
const nextSelection = lexical.$createRangeSelection();
|
|
614
|
-
lexical.$setSelection(nextSelection);
|
|
615
|
-
|
|
701
|
+
lexical.$setSelection(nextSelection); // Adjust offset based on deleted chars
|
|
702
|
+
|
|
616
703
|
const newOffset = closeTagEndIndex - tagLength * (openNode === closeNode ? 2 : 1) + 1;
|
|
617
704
|
nextSelection.anchor.set(openNode.__key, openTagStartIndex, 'text');
|
|
618
|
-
nextSelection.focus.set(closeNode.__key, newOffset, 'text');
|
|
705
|
+
nextSelection.focus.set(closeNode.__key, newOffset, 'text'); // Apply formatting to selected text
|
|
619
706
|
|
|
620
|
-
// Apply formatting to selected text
|
|
621
707
|
for (const format of matcher.format) {
|
|
622
708
|
if (!nextSelection.hasFormat(format)) {
|
|
623
709
|
nextSelection.formatText(format);
|
|
624
710
|
}
|
|
625
|
-
}
|
|
711
|
+
} // Collapse selection up to the focus point
|
|
712
|
+
|
|
626
713
|
|
|
627
|
-
|
|
628
|
-
nextSelection.anchor.set(nextSelection.focus.key, nextSelection.focus.offset, nextSelection.focus.type);
|
|
714
|
+
nextSelection.anchor.set(nextSelection.focus.key, nextSelection.focus.offset, nextSelection.focus.type); // Remove formatting from collapsed selection
|
|
629
715
|
|
|
630
|
-
// Remove formatting from collapsed selection
|
|
631
716
|
for (const format of matcher.format) {
|
|
632
717
|
if (nextSelection.hasFormat(format)) {
|
|
633
718
|
nextSelection.toggleFormat(format);
|
|
634
719
|
}
|
|
635
720
|
}
|
|
721
|
+
|
|
636
722
|
if (lexical.$isRangeSelection(selection)) {
|
|
637
723
|
nextSelection.format = selection.format;
|
|
638
724
|
}
|
|
725
|
+
|
|
639
726
|
return true;
|
|
640
727
|
}
|
|
728
|
+
|
|
641
729
|
return false;
|
|
642
730
|
}
|
|
731
|
+
|
|
643
732
|
function getOpenTagStartIndex(string, maxIndex, tag) {
|
|
644
733
|
const tagLength = tag.length;
|
|
734
|
+
|
|
645
735
|
for (let i = maxIndex; i >= tagLength; i--) {
|
|
646
736
|
const startIndex = i - tagLength;
|
|
647
|
-
|
|
648
|
-
// Space after opening tag cancels transformation
|
|
737
|
+
|
|
738
|
+
if (isEqualSubString(string, startIndex, tag, 0, tagLength) && // Space after opening tag cancels transformation
|
|
649
739
|
string[startIndex + tagLength] !== ' ') {
|
|
650
740
|
return startIndex;
|
|
651
741
|
}
|
|
652
742
|
}
|
|
743
|
+
|
|
653
744
|
return -1;
|
|
654
745
|
}
|
|
746
|
+
|
|
655
747
|
function isEqualSubString(stringA, aStart, stringB, bStart, length) {
|
|
656
748
|
for (let i = 0; i < length; i++) {
|
|
657
749
|
if (stringA[aStart + i] !== stringB[bStart + i]) {
|
|
658
750
|
return false;
|
|
659
751
|
}
|
|
660
752
|
}
|
|
753
|
+
|
|
661
754
|
return true;
|
|
662
755
|
}
|
|
756
|
+
|
|
663
757
|
function registerMarkdownShortcuts(editor, transformers = TRANSFORMERS) {
|
|
664
758
|
const byType = transformersByType(transformers);
|
|
665
759
|
const textFormatTransformersIndex = indexBy(byType.textFormat, ({
|
|
@@ -668,10 +762,13 @@ function registerMarkdownShortcuts(editor, transformers = TRANSFORMERS) {
|
|
|
668
762
|
const textMatchTransformersIndex = indexBy(byType.textMatch, ({
|
|
669
763
|
trigger
|
|
670
764
|
}) => trigger);
|
|
765
|
+
|
|
671
766
|
for (const transformer of transformers) {
|
|
672
767
|
const type = transformer.type;
|
|
768
|
+
|
|
673
769
|
if (type === 'element' || type === 'text-match') {
|
|
674
770
|
const dependencies = transformer.dependencies;
|
|
771
|
+
|
|
675
772
|
if (!editor.hasNodes(dependencies)) {
|
|
676
773
|
{
|
|
677
774
|
throw Error(`MarkdownShortcuts: missing dependency for transformer. Ensure node dependency is included in editor initial config.`);
|
|
@@ -679,15 +776,19 @@ function registerMarkdownShortcuts(editor, transformers = TRANSFORMERS) {
|
|
|
679
776
|
}
|
|
680
777
|
}
|
|
681
778
|
}
|
|
779
|
+
|
|
682
780
|
const transform = (parentNode, anchorNode, anchorOffset) => {
|
|
683
781
|
if (runElementTransformers(parentNode, anchorNode, anchorOffset, byType.element)) {
|
|
684
782
|
return;
|
|
685
783
|
}
|
|
784
|
+
|
|
686
785
|
if (runTextMatchTransformers(anchorNode, anchorOffset, textMatchTransformersIndex)) {
|
|
687
786
|
return;
|
|
688
787
|
}
|
|
788
|
+
|
|
689
789
|
runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransformersIndex);
|
|
690
790
|
};
|
|
791
|
+
|
|
691
792
|
return editor.registerUpdateListener(({
|
|
692
793
|
tags,
|
|
693
794
|
dirtyLeaves,
|
|
@@ -698,26 +799,35 @@ function registerMarkdownShortcuts(editor, transformers = TRANSFORMERS) {
|
|
|
698
799
|
if (tags.has('historic')) {
|
|
699
800
|
return;
|
|
700
801
|
}
|
|
802
|
+
|
|
701
803
|
const selection = editorState.read(lexical.$getSelection);
|
|
702
804
|
const prevSelection = prevEditorState.read(lexical.$getSelection);
|
|
805
|
+
|
|
703
806
|
if (!lexical.$isRangeSelection(prevSelection) || !lexical.$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
704
807
|
return;
|
|
705
808
|
}
|
|
809
|
+
|
|
706
810
|
const anchorKey = selection.anchor.key;
|
|
707
811
|
const anchorOffset = selection.anchor.offset;
|
|
812
|
+
|
|
708
813
|
const anchorNode = editorState._nodeMap.get(anchorKey);
|
|
814
|
+
|
|
709
815
|
if (!lexical.$isTextNode(anchorNode) || !dirtyLeaves.has(anchorKey) || anchorOffset !== 1 && anchorOffset !== prevSelection.anchor.offset + 1) {
|
|
710
816
|
return;
|
|
711
817
|
}
|
|
818
|
+
|
|
712
819
|
editor.update(() => {
|
|
713
820
|
// Markdown is not available inside code
|
|
714
821
|
if (anchorNode.hasFormat('code')) {
|
|
715
822
|
return;
|
|
716
823
|
}
|
|
824
|
+
|
|
717
825
|
const parentNode = anchorNode.getParent();
|
|
826
|
+
|
|
718
827
|
if (parentNode === null || code.$isCodeNode(parentNode)) {
|
|
719
828
|
return;
|
|
720
829
|
}
|
|
830
|
+
|
|
721
831
|
transform(parentNode, anchorNode, selection.anchor.offset);
|
|
722
832
|
});
|
|
723
833
|
});
|
|
@@ -730,6 +840,7 @@ function registerMarkdownShortcuts(editor, transformers = TRANSFORMERS) {
|
|
|
730
840
|
* LICENSE file in the root directory of this source tree.
|
|
731
841
|
*
|
|
732
842
|
*/
|
|
843
|
+
|
|
733
844
|
const createBlockNode = createNode => {
|
|
734
845
|
return (parentNode, children, match) => {
|
|
735
846
|
const node = createNode(match);
|
|
@@ -737,15 +848,17 @@ const createBlockNode = createNode => {
|
|
|
737
848
|
parentNode.replace(node);
|
|
738
849
|
node.select(0, 0);
|
|
739
850
|
};
|
|
740
|
-
};
|
|
741
|
-
|
|
742
|
-
// Amount of spaces that define indentation level
|
|
851
|
+
}; // Amount of spaces that define indentation level
|
|
743
852
|
// TODO: should be an option
|
|
853
|
+
|
|
854
|
+
|
|
744
855
|
const LIST_INDENT_SIZE = 4;
|
|
856
|
+
|
|
745
857
|
const listReplace = listType => {
|
|
746
858
|
return (parentNode, children, match) => {
|
|
747
859
|
const previousNode = parentNode.getPreviousSibling();
|
|
748
860
|
const listItem = list.$createListItemNode(listType === 'check' ? match[3] === 'x' : undefined);
|
|
861
|
+
|
|
749
862
|
if (list.$isListNode(previousNode) && previousNode.getListType() === listType) {
|
|
750
863
|
previousNode.append(listItem);
|
|
751
864
|
parentNode.remove();
|
|
@@ -754,27 +867,33 @@ const listReplace = listType => {
|
|
|
754
867
|
list$1.append(listItem);
|
|
755
868
|
parentNode.replace(list$1);
|
|
756
869
|
}
|
|
870
|
+
|
|
757
871
|
listItem.append(...children);
|
|
758
872
|
listItem.select(0, 0);
|
|
759
873
|
const indent = Math.floor(match[1].length / LIST_INDENT_SIZE);
|
|
874
|
+
|
|
760
875
|
if (indent) {
|
|
761
876
|
listItem.setIndent(indent);
|
|
762
877
|
}
|
|
763
878
|
};
|
|
764
879
|
};
|
|
880
|
+
|
|
765
881
|
const listExport = (listNode, exportChildren, depth) => {
|
|
766
882
|
const output = [];
|
|
767
883
|
const children = listNode.getChildren();
|
|
768
884
|
let index = 0;
|
|
885
|
+
|
|
769
886
|
for (const listItemNode of children) {
|
|
770
887
|
if (list.$isListItemNode(listItemNode)) {
|
|
771
888
|
if (listItemNode.getChildrenSize() === 1) {
|
|
772
889
|
const firstChild = listItemNode.getFirstChild();
|
|
890
|
+
|
|
773
891
|
if (list.$isListNode(firstChild)) {
|
|
774
892
|
output.push(listExport(firstChild, exportChildren, depth + 1));
|
|
775
893
|
continue;
|
|
776
894
|
}
|
|
777
895
|
}
|
|
896
|
+
|
|
778
897
|
const indent = ' '.repeat(depth * LIST_INDENT_SIZE);
|
|
779
898
|
const listType = listNode.getListType();
|
|
780
899
|
const prefix = listType === 'number' ? `${listNode.getStart() + index}. ` : listType === 'check' ? `- [${listItemNode.getChecked() ? 'x' : ' '}] ` : '- ';
|
|
@@ -782,14 +901,17 @@ const listExport = (listNode, exportChildren, depth) => {
|
|
|
782
901
|
index++;
|
|
783
902
|
}
|
|
784
903
|
}
|
|
904
|
+
|
|
785
905
|
return output.join('\n');
|
|
786
906
|
};
|
|
907
|
+
|
|
787
908
|
const HEADING = {
|
|
788
909
|
dependencies: [richText.HeadingNode],
|
|
789
910
|
export: (node, exportChildren) => {
|
|
790
911
|
if (!richText.$isHeadingNode(node)) {
|
|
791
912
|
return null;
|
|
792
913
|
}
|
|
914
|
+
|
|
793
915
|
const level = Number(node.getTag().slice(1));
|
|
794
916
|
return '#'.repeat(level) + ' ' + exportChildren(node);
|
|
795
917
|
},
|
|
@@ -806,17 +928,21 @@ const QUOTE = {
|
|
|
806
928
|
if (!richText.$isQuoteNode(node)) {
|
|
807
929
|
return null;
|
|
808
930
|
}
|
|
931
|
+
|
|
809
932
|
const lines = exportChildren(node).split('\n');
|
|
810
933
|
const output = [];
|
|
934
|
+
|
|
811
935
|
for (const line of lines) {
|
|
812
936
|
output.push('> ' + line);
|
|
813
937
|
}
|
|
938
|
+
|
|
814
939
|
return output.join('\n');
|
|
815
940
|
},
|
|
816
941
|
regExp: /^>\s/,
|
|
817
942
|
replace: (parentNode, children, _match, isImport) => {
|
|
818
943
|
if (isImport) {
|
|
819
944
|
const previousNode = parentNode.getPreviousSibling();
|
|
945
|
+
|
|
820
946
|
if (richText.$isQuoteNode(previousNode)) {
|
|
821
947
|
previousNode.splice(previousNode.getChildrenSize(), 0, [lexical.$createLineBreakNode(), ...children]);
|
|
822
948
|
previousNode.select(0, 0);
|
|
@@ -824,6 +950,7 @@ const QUOTE = {
|
|
|
824
950
|
return;
|
|
825
951
|
}
|
|
826
952
|
}
|
|
953
|
+
|
|
827
954
|
const node = richText.$createQuoteNode();
|
|
828
955
|
node.append(...children);
|
|
829
956
|
parentNode.replace(node);
|
|
@@ -837,6 +964,7 @@ const CODE = {
|
|
|
837
964
|
if (!code.$isCodeNode(node)) {
|
|
838
965
|
return null;
|
|
839
966
|
}
|
|
967
|
+
|
|
840
968
|
const textContent = node.getTextContent();
|
|
841
969
|
return '```' + (node.getLanguage() || '') + (textContent ? '\n' + textContent : '') + '\n' + '```';
|
|
842
970
|
},
|
|
@@ -920,22 +1048,22 @@ const ITALIC_UNDERSCORE = {
|
|
|
920
1048
|
intraword: false,
|
|
921
1049
|
tag: '_',
|
|
922
1050
|
type: 'text-format'
|
|
923
|
-
};
|
|
924
|
-
|
|
925
|
-
// Order of text transformers matters:
|
|
1051
|
+
}; // Order of text transformers matters:
|
|
926
1052
|
//
|
|
927
1053
|
// - code should go first as it prevents any transformations inside
|
|
928
1054
|
// - then longer tags match (e.g. ** or __ should go before * or _)
|
|
1055
|
+
|
|
929
1056
|
const LINK = {
|
|
930
1057
|
dependencies: [link.LinkNode],
|
|
931
1058
|
export: (node, exportChildren, exportFormat) => {
|
|
932
1059
|
if (!link.$isLinkNode(node)) {
|
|
933
1060
|
return null;
|
|
934
1061
|
}
|
|
1062
|
+
|
|
935
1063
|
const linkContent = `[${node.getTextContent()}](${node.getURL()})`;
|
|
936
|
-
const firstChild = node.getFirstChild();
|
|
937
|
-
// Add text styles only if link has single text node inside. If it's more
|
|
1064
|
+
const firstChild = node.getFirstChild(); // Add text styles only if link has single text node inside. If it's more
|
|
938
1065
|
// then one we ignore it as markdown does not support nested styles for links
|
|
1066
|
+
|
|
939
1067
|
if (node.getChildrenSize() === 1 && lexical.$isTextNode(firstChild)) {
|
|
940
1068
|
return exportFormat(firstChild, linkContent);
|
|
941
1069
|
} else {
|
|
@@ -957,22 +1085,23 @@ const LINK = {
|
|
|
957
1085
|
};
|
|
958
1086
|
|
|
959
1087
|
/** @module @lexical/markdown */
|
|
960
|
-
const ELEMENT_TRANSFORMERS = [HEADING, QUOTE, CODE, UNORDERED_LIST, ORDERED_LIST];
|
|
961
|
-
|
|
962
|
-
// Order of text format transformers matters:
|
|
1088
|
+
const ELEMENT_TRANSFORMERS = [HEADING, QUOTE, CODE, UNORDERED_LIST, ORDERED_LIST]; // Order of text format transformers matters:
|
|
963
1089
|
//
|
|
964
1090
|
// - code should go first as it prevents any transformations inside
|
|
965
1091
|
// - then longer tags match (e.g. ** or __ should go before * or _)
|
|
1092
|
+
|
|
966
1093
|
const TEXT_FORMAT_TRANSFORMERS = [INLINE_CODE, BOLD_ITALIC_STAR, BOLD_ITALIC_UNDERSCORE, BOLD_STAR, BOLD_UNDERSCORE, HIGHLIGHT, ITALIC_STAR, ITALIC_UNDERSCORE, STRIKETHROUGH];
|
|
967
1094
|
const TEXT_MATCH_TRANSFORMERS = [LINK];
|
|
968
1095
|
const TRANSFORMERS = [...ELEMENT_TRANSFORMERS, ...TEXT_FORMAT_TRANSFORMERS, ...TEXT_MATCH_TRANSFORMERS];
|
|
969
|
-
|
|
1096
|
+
|
|
1097
|
+
function $convertFromMarkdownString(markdown, transformers = TRANSFORMERS, node) {
|
|
970
1098
|
const importMarkdown = createMarkdownImport(transformers);
|
|
971
|
-
return importMarkdown(markdown);
|
|
1099
|
+
return importMarkdown(markdown, node);
|
|
972
1100
|
}
|
|
973
|
-
|
|
1101
|
+
|
|
1102
|
+
function $convertToMarkdownString(transformers = TRANSFORMERS, node) {
|
|
974
1103
|
const exportMarkdown = createMarkdownExport(transformers);
|
|
975
|
-
return exportMarkdown();
|
|
1104
|
+
return exportMarkdown(node);
|
|
976
1105
|
}
|
|
977
1106
|
|
|
978
1107
|
exports.$convertFromMarkdownString = $convertFromMarkdownString;
|
package/LexicalMarkdown.prod.js
CHANGED
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
'use strict';var h=require("lexical"),t=require("@lexical/code"),A=require("@lexical/list"),B=require("@lexical/rich-text"),aa=require("@lexical/utils"),G=require("@lexical/link");function H(a,b){let c={};for(let d of a)a=b(d),c[a]?c[a].push(d):c[a]=[d];return c}function I(a){a=H(a,b=>b.type);return{element:a.element||[],textFormat:a["text-format"]||[],textMatch:a["text-match"]||[]}}let J=/[!-/:-@[-`{-~\s]/;
|
|
8
|
-
function ba(a){let b=I(a),c=b.textFormat.filter(d=>1===d.format.length);return
|
|
8
|
+
function ba(a){let b=I(a),c=b.textFormat.filter(d=>1===d.format.length);return d=>{let e=[];d=(d||h.$getRoot()).getChildren();for(let f of d)d=ca(f,b.element,c,b.textMatch),null!=d&&e.push(d);return e.join("\n\n")}}function ca(a,b,c,d){for(let e of b)if(b=e.export(a,f=>K(f,c,d)),null!=b)return b;return h.$isElementNode(a)?K(a,c,d):h.$isDecoratorNode(a)?a.getTextContent():null}
|
|
9
9
|
function K(a,b,c){let d=[];a=a.getChildren();a:for(let e of a){for(let f of c)if(a=f.export(e,l=>K(l,b,c),(l,k)=>L(l,k,b)),null!=a){d.push(a);continue a}h.$isLineBreakNode(e)?d.push("\n"):h.$isTextNode(e)?d.push(L(e,e.getTextContent(),b)):h.$isElementNode(e)?d.push(K(e,b,c)):h.$isDecoratorNode(e)&&d.push(e.getTextContent())}return d.join("")}
|
|
10
10
|
function L(a,b,c){let d=b.trim(),e=d,f=new Set;for(let k of c){c=k.format[0];let p=k.tag;if(M(a,c)&&!f.has(c)){f.add(c);var l=N(a,!0);M(l,c)||(e=p+e);l=N(a,!1);M(l,c)||(e+=p)}}return b.replace(d,e)}
|
|
11
11
|
function N(a,b){let c=b?a.getPreviousSibling():a.getNextSibling();c||(a=a.getParentOrThrow(),a.isInline()&&(c=b?a.getPreviousSibling():a.getNextSibling()));for(;c;){if(h.$isElementNode(c)){if(!c.isInline())break;a=b?c.getLastDescendant():c.getFirstDescendant();if(h.$isTextNode(a))return a;c=b?c.getPreviousSibling():c.getNextSibling()}if(h.$isTextNode(c))return c;if(!h.$isElementNode(c))break}return null}function M(a,b){return h.$isTextNode(a)&&a.hasFormat(b)}
|
|
12
12
|
let O="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement,da=O&&"documentMode"in document?document.documentMode:null;O&&/Mac|iPod|iPhone|iPad/.test(navigator.platform);O&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);O&&"InputEvent"in window&&!da?"getTargetRanges"in new window.InputEvent("input"):!1;
|
|
13
13
|
let P=O&&/Version\/[\d.]+.*Safari/.test(navigator.userAgent),Q=O&&/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream,ea=O&&/^(?=.*Chrome).*/i.test(navigator.userAgent),R=O&&/AppleWebKit\/[\d.]+/.test(navigator.userAgent)&&!ea,fa=/^\s{0,3}$/,S=/^```(\w{1,10})?\s?$/;
|
|
14
|
-
function ha(a){let b=I(a),c=ia(b.textFormat);return
|
|
15
|
-
m.append(l);for(let {regExp:x,replace:u}of w)if(m=r.match(x)){y.setTextContent(r.slice(m[0].length));u(l,[y],m,!0);break}T(y,q,k);l.isAttached()&&0<p.length&&(r=l.getPreviousSibling(),h.$isParagraphNode(r)||B.$isQuoteNode(r)||A.$isListNode(r))&&(q=r,A.$isListNode(r)&&(r=r.getLastDescendant(),q=null==r?null:aa.$findMatchingParent(r,A.$isListItemNode)),null!=q&&0<q.getTextContentSize()&&(q.splice(q.getChildrenSize(),0,[h.$createLineBreakNode(),...l.getChildren()]),l.remove()))}}e
|
|
16
|
-
g,h.$isParagraphNode(
|
|
14
|
+
function ha(a){let b=I(a),c=ia(b.textFormat);return(d,e)=>{d=d.split("\n");var f=d.length;e=e||h.$getRoot();e.clear();for(let g=0;g<f;g++){var l=d[g];a:{var k=d,p=g;var r=e;var y=k[p].match(S);if(y)for(var q=p,m=k.length;++q<m;)if(k[q].match(S)){y=t.$createCodeNode(y[1]);k=h.$createTextNode(k.slice(p+1,q).join("\n"));y.append(k);r.append(y);r=[y,q];break a}r=[null,p]}let [n,v]=r;if(null!=n)g=v;else{r=l;m=e;var w=b.element;q=c;k=b.textMatch;p=r.trim();y=h.$createTextNode(p);l=h.$createParagraphNode();
|
|
15
|
+
l.append(y);m.append(l);for(let {regExp:x,replace:u}of w)if(m=r.match(x)){y.setTextContent(r.slice(m[0].length));u(l,[y],m,!0);break}T(y,q,k);l.isAttached()&&0<p.length&&(r=l.getPreviousSibling(),h.$isParagraphNode(r)||B.$isQuoteNode(r)||A.$isListNode(r))&&(q=r,A.$isListNode(r)&&(r=r.getLastDescendant(),q=null==r?null:aa.$findMatchingParent(r,A.$isListItemNode)),null!=q&&0<q.getTextContentSize()&&(q.splice(q.getChildrenSize(),0,[h.$createLineBreakNode(),...l.getChildren()]),l.remove()))}}d=e.getChildren();
|
|
16
|
+
for(let g of d)d=g,h.$isParagraphNode(d)?(f=d.getFirstChild(),d=null==f||1===d.getChildrenSize()&&h.$isTextNode(f)&&fa.test(f.getTextContent())):d=!1,d&&g.remove()}}
|
|
17
17
|
function T(a,b,c){var d=a.getTextContent();let e=ja(d,b);if(e){var f,l;if(e[0]===d)var k=a;else{d=e.index||0;let p=d+e[0].length;0===d?[k,f]=a.splitText(p):[l,k,f]=a.splitText(d,p)}k.setTextContent(e[2]);if(a=b.transformersByTag[e[1]])for(let p of a.format)k.hasFormat(p)||k.toggleFormat(p);k.hasFormat("code")||T(k,b,c);l&&T(l,b,c);f&&T(f,b,c)}else U(a,c)}
|
|
18
18
|
function U(a,b){a:for(;a;){for(let c of b){let d=a.getTextContent().match(c.importRegExp);if(!d)continue;let e=d.index||0,f=e+d[0].length,l,k,p;0===e?[l,a]=a.splitText(f):[k,l,p]=a.splitText(e,f);k&&U(k,b);p&&(a=p);c.replace(l,d);continue a}break}}
|
|
19
19
|
function ja(a,b){var c=a.match(b.openTagsRegExp);if(null==c)return null;for(let f of c){var d=f.replace(/^\s/,"");c=b.fullMatchRegExpByTag[d];if(null!=c&&(c=a.match(c),d=b.transformersByTag[d],null!=c&&null!=d)){if(!1!==d.intraword)return c;var {index:e=0}=c;d=a[e-1];e=a[e+c[0].length];if(!(d&&!J.test(d)||e&&!J.test(e)))return c}}return null}
|
|
@@ -25,7 +25,7 @@ export:(a,b)=>{if(!B.$isQuoteNode(a))return null;a=b(a).split("\n");b=[];for(con
|
|
|
25
25
|
(a.getLanguage()||"")+(b?"\n"+b:"")+"\n```"},regExp:/^```(\w{1,10})?\s/,replace:ka(a=>t.$createCodeNode(a?a[1]:void 0)),type:"element"},oa={dependencies:[A.ListNode,A.ListItemNode],export:(a,b)=>A.$isListNode(a)?Y(a,b,0):null,regExp:/^(\s*)[-*+]\s/,replace:X("bullet"),type:"element"},pa={dependencies:[A.ListNode,A.ListItemNode],export:(a,b)=>A.$isListNode(a)?Y(a,b,0):null,regExp:/^(\s*)(?:-\s)?\s?(\[(\s|x)?\])\s/i,replace:X("check"),type:"element"},qa={dependencies:[A.ListNode,A.ListItemNode],export:(a,
|
|
26
26
|
b)=>A.$isListNode(a)?Y(a,b,0):null,regExp:/^(\s*)(\d{1,})\.\s/,replace:X("number"),type:"element"},ra={format:["code"],tag:"`",type:"text-format"},sa={format:["highlight"],tag:"==",type:"text-format"},ta={format:["bold","italic"],tag:"***",type:"text-format"},va={format:["bold","italic"],intraword:!1,tag:"___",type:"text-format"},wa={format:["bold"],tag:"**",type:"text-format"},xa={format:["bold"],intraword:!1,tag:"__",type:"text-format"},ya={format:["strikethrough"],tag:"~~",type:"text-format"},
|
|
27
27
|
za={format:["italic"],tag:"*",type:"text-format"},Aa={format:["italic"],intraword:!1,tag:"_",type:"text-format"},Ba={dependencies:[G.LinkNode],export:(a,b,c)=>{if(!G.$isLinkNode(a))return null;b=`[${a.getTextContent()}](${a.getURL()})`;const d=a.getFirstChild();return 1===a.getChildrenSize()&&h.$isTextNode(d)?c(d,b):b},importRegExp:/(?:\[([^[]+)\])(?:\(([^()]+)\))/,regExp:/(?:\[([^[]+)\])(?:\(([^()]+)\))$/,replace:(a,b)=>{const [,c,d]=b;b=G.$createLinkNode(d);const e=h.$createTextNode(c);e.setFormat(a.getFormat());
|
|
28
|
-
b.append(e);a.replace(b)},trigger:")",type:"text-match"},Ca=[la,ma,na,oa,qa],Da=[ra,ta,va,wa,xa,sa,za,Aa,ya],Ea=[Ba],Z=[...Ca,...Da,...Ea];exports.$convertFromMarkdownString=function(a,b=Z){return ha(b)(a)};exports.$convertToMarkdownString=function(a=Z){return ba(a)()};exports.BOLD_ITALIC_STAR=ta;exports.BOLD_ITALIC_UNDERSCORE=va;exports.BOLD_STAR=wa;exports.BOLD_UNDERSCORE=xa;exports.CHECK_LIST=pa;exports.CODE=na;exports.ELEMENT_TRANSFORMERS=Ca;exports.HEADING=la;exports.HIGHLIGHT=sa;
|
|
28
|
+
b.append(e);a.replace(b)},trigger:")",type:"text-match"},Ca=[la,ma,na,oa,qa],Da=[ra,ta,va,wa,xa,sa,za,Aa,ya],Ea=[Ba],Z=[...Ca,...Da,...Ea];exports.$convertFromMarkdownString=function(a,b=Z,c){return ha(b)(a,c)};exports.$convertToMarkdownString=function(a=Z,b){return ba(a)(b)};exports.BOLD_ITALIC_STAR=ta;exports.BOLD_ITALIC_UNDERSCORE=va;exports.BOLD_STAR=wa;exports.BOLD_UNDERSCORE=xa;exports.CHECK_LIST=pa;exports.CODE=na;exports.ELEMENT_TRANSFORMERS=Ca;exports.HEADING=la;exports.HIGHLIGHT=sa;
|
|
29
29
|
exports.INLINE_CODE=ra;exports.ITALIC_STAR=za;exports.ITALIC_UNDERSCORE=Aa;exports.LINK=Ba;exports.ORDERED_LIST=qa;exports.QUOTE=ma;exports.STRIKETHROUGH=ya;exports.TEXT_FORMAT_TRANSFORMERS=Da;exports.TEXT_MATCH_TRANSFORMERS=Ea;exports.TRANSFORMERS=Z;exports.UNORDERED_LIST=oa;
|
|
30
30
|
exports.registerMarkdownShortcuts=function(a,b=Z){let c=I(b),d=H(c.textFormat,({tag:f})=>f[f.length-1]),e=H(c.textMatch,({trigger:f})=>f);for(let f of b)if(b=f.type,("element"===b||"text-match"===b)&&!a.hasNodes(f.dependencies))throw Error("Minified Lexical error #79; visit https://lexical.dev/docs/error?code=79 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");return a.registerUpdateListener(({tags:f,dirtyLeaves:l,editorState:k,prevEditorState:p})=>
|
|
31
31
|
{if(!f.has("historic")){var r=k.read(h.$getSelection);f=p.read(h.$getSelection);if(h.$isRangeSelection(f)&&h.$isRangeSelection(r)&&r.isCollapsed()){p=r.anchor.key;var y=r.anchor.offset,q=k._nodeMap.get(p);h.$isTextNode(q)&&l.has(p)&&(1===y||y===f.anchor.offset+1)&&a.update(()=>{if(!q.hasFormat("code")){var m=q.getParent();if(null!==m&&!t.$isCodeNode(m)){var w=r.anchor.offset;b:{var g=c.element,n=m.getParent();if(h.$isRootOrShadowRoot(n)&&m.getFirstChild()===q&&(n=q.getTextContent()," "===n[w-1]))for(let {regExp:D,
|
package/MarkdownExport.d.ts
CHANGED
|
@@ -6,4 +6,5 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
import type { Transformer } from '@lexical/markdown';
|
|
9
|
-
|
|
9
|
+
import type { ElementNode } from 'lexical';
|
|
10
|
+
export declare function createMarkdownExport(transformers: Array<Transformer>): (node?: ElementNode) => string;
|
package/MarkdownImport.d.ts
CHANGED
|
@@ -6,4 +6,5 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
import type { Transformer } from '@lexical/markdown';
|
|
9
|
-
|
|
9
|
+
import { ElementNode } from 'lexical';
|
|
10
|
+
export declare function createMarkdownImport(transformers: Array<Transformer>): (markdownString: string, node?: ElementNode) => void;
|
package/index.d.ts
CHANGED
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
9
|
import type { ElementTransformer, TextFormatTransformer, TextMatchTransformer, Transformer } from './MarkdownTransformers';
|
|
10
|
+
import type { ElementNode } from 'lexical';
|
|
10
11
|
import { registerMarkdownShortcuts } from './MarkdownShortcuts';
|
|
11
12
|
import { BOLD_ITALIC_STAR, BOLD_ITALIC_UNDERSCORE, BOLD_STAR, BOLD_UNDERSCORE, CHECK_LIST, CODE, HEADING, HIGHLIGHT, INLINE_CODE, ITALIC_STAR, ITALIC_UNDERSCORE, LINK, ORDERED_LIST, QUOTE, STRIKETHROUGH, UNORDERED_LIST } from './MarkdownTransformers';
|
|
12
13
|
declare const ELEMENT_TRANSFORMERS: Array<ElementTransformer>;
|
|
13
14
|
declare const TEXT_FORMAT_TRANSFORMERS: Array<TextFormatTransformer>;
|
|
14
15
|
declare const TEXT_MATCH_TRANSFORMERS: Array<TextMatchTransformer>;
|
|
15
16
|
declare const TRANSFORMERS: Array<Transformer>;
|
|
16
|
-
declare function $convertFromMarkdownString(markdown: string, transformers?: Array<Transformer
|
|
17
|
-
declare function $convertToMarkdownString(transformers?: Array<Transformer
|
|
17
|
+
declare function $convertFromMarkdownString(markdown: string, transformers?: Array<Transformer>, node?: ElementNode): void;
|
|
18
|
+
declare function $convertToMarkdownString(transformers?: Array<Transformer>, node?: ElementNode): string;
|
|
18
19
|
export { $convertFromMarkdownString, $convertToMarkdownString, BOLD_ITALIC_STAR, BOLD_ITALIC_UNDERSCORE, BOLD_STAR, BOLD_UNDERSCORE, CHECK_LIST, CODE, ELEMENT_TRANSFORMERS, ElementTransformer, HEADING, HIGHLIGHT, INLINE_CODE, ITALIC_STAR, ITALIC_UNDERSCORE, LINK, ORDERED_LIST, QUOTE, registerMarkdownShortcuts, STRIKETHROUGH, TEXT_FORMAT_TRANSFORMERS, TEXT_MATCH_TRANSFORMERS, TextFormatTransformer, TextMatchTransformer, Transformer, TRANSFORMERS, UNORDERED_LIST, };
|
package/package.json
CHANGED
|
@@ -8,18 +8,18 @@
|
|
|
8
8
|
"markdown"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.9.1",
|
|
12
12
|
"main": "LexicalMarkdown.js",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"lexical": "0.
|
|
14
|
+
"lexical": "0.9.1"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lexical/utils": "0.
|
|
18
|
-
"@lexical/code": "0.
|
|
19
|
-
"@lexical/text": "0.
|
|
20
|
-
"@lexical/rich-text": "0.
|
|
21
|
-
"@lexical/list": "0.
|
|
22
|
-
"@lexical/link": "0.
|
|
17
|
+
"@lexical/utils": "0.9.1",
|
|
18
|
+
"@lexical/code": "0.9.1",
|
|
19
|
+
"@lexical/text": "0.9.1",
|
|
20
|
+
"@lexical/rich-text": "0.9.1",
|
|
21
|
+
"@lexical/list": "0.9.1",
|
|
22
|
+
"@lexical/link": "0.9.1"
|
|
23
23
|
},
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
package/convertToMarkdown.d.ts
DELETED