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