@lexical/markdown 0.8.0 → 0.9.0

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