@lexical/markdown 0.3.5 → 0.3.8

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.
@@ -8,9 +8,10 @@
8
8
 
9
9
  var lexical = require('lexical');
10
10
  var code = require('@lexical/code');
11
- var link = require('@lexical/link');
12
11
  var list = require('@lexical/list');
13
12
  var richText = require('@lexical/rich-text');
13
+ var utils = require('@lexical/utils');
14
+ var link = require('@lexical/link');
14
15
 
15
16
  /**
16
17
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -37,9 +38,9 @@ function indexBy(list, callback) {
37
38
  function transformersByType(transformers) {
38
39
  const byType = indexBy(transformers, t => t.type);
39
40
  return {
40
- element: byType.element,
41
- textFormat: byType['text-format'],
42
- textMatch: byType['text-match']
41
+ element: byType.element || [],
42
+ textFormat: byType['text-format'] || [],
43
+ textMatch: byType['text-match'] || []
43
44
  };
44
45
  }
45
46
  const PUNCTUATION_OR_SPACE = /[!-/:-@[-`{-~\s]/;
@@ -68,7 +69,7 @@ function createMarkdownExport(transformers) {
68
69
  }
69
70
  }
70
71
 
71
- return output.join('\n');
72
+ return output.join('\n\n');
72
73
  };
73
74
  }
74
75
 
@@ -89,23 +90,21 @@ function exportChildren(node, textTransformersIndex, textMatchTransformers) {
89
90
  const children = node.getChildren();
90
91
 
91
92
  mainLoop: for (const child of children) {
93
+ for (const transformer of textMatchTransformers) {
94
+ const result = transformer.export(child, parentNode => exportChildren(parentNode, textTransformersIndex, textMatchTransformers), (textNode, textContent) => exportTextFormat(textNode, textContent, textTransformersIndex));
95
+
96
+ if (result != null) {
97
+ output.push(result);
98
+ continue mainLoop;
99
+ }
100
+ }
101
+
92
102
  if (lexical.$isLineBreakNode(child)) {
93
103
  output.push('\n');
94
104
  } else if (lexical.$isTextNode(child)) {
95
105
  output.push(exportTextFormat(child, child.getTextContent(), textTransformersIndex));
96
- } else {
97
- for (const transformer of textMatchTransformers) {
98
- const result = transformer.export(child, parentNode => exportChildren(parentNode, textTransformersIndex, textMatchTransformers), (textNode, textContent) => exportTextFormat(textNode, textContent, textTransformersIndex));
99
-
100
- if (result != null) {
101
- output.push(result);
102
- continue mainLoop;
103
- }
104
- }
105
-
106
- if (lexical.$isElementNode(child)) {
107
- output.push(exportChildren(child, textTransformersIndex, textMatchTransformers));
108
- }
106
+ } else if (lexical.$isElementNode(child)) {
107
+ output.push(exportChildren(child, textTransformersIndex, textMatchTransformers));
109
108
  }
110
109
  }
111
110
 
@@ -199,6 +198,7 @@ function hasFormat(node, format) {
199
198
  * LICENSE file in the root directory of this source tree.
200
199
  *
201
200
  */
201
+ const MARKDOWN_EMPTY_LINE_REG_EXP = /^\s{0,3}$/;
202
202
  const CODE_BLOCK_REG_EXP = /^```(\w{1,10})?\s?$/;
203
203
  function createMarkdownImport(transformers) {
204
204
  const byType = transformersByType(transformers);
@@ -223,14 +223,34 @@ function createMarkdownImport(transformers) {
223
223
  }
224
224
 
225
225
  importBlocks(lineText, root, byType.element, textFormatTransformersIndex, byType.textMatch);
226
+ } // Removing empty paragraphs as md does not really
227
+ // allow empty lines and uses them as dilimiter
228
+
229
+
230
+ const children = root.getChildren();
231
+
232
+ for (const child of children) {
233
+ if (isEmptyParagraph(child)) {
234
+ child.remove();
235
+ }
226
236
  }
227
237
 
228
238
  root.selectEnd();
229
239
  };
230
240
  }
231
241
 
242
+ function isEmptyParagraph(node) {
243
+ if (!lexical.$isParagraphNode(node)) {
244
+ return false;
245
+ }
246
+
247
+ const firstChild = node.getFirstChild();
248
+ return firstChild == null || node.getChildrenSize() === 1 && lexical.$isTextNode(firstChild) && MARKDOWN_EMPTY_LINE_REG_EXP.test(firstChild.getTextContent());
249
+ }
250
+
232
251
  function importBlocks(lineText, rootNode, elementTransformers, textFormatTransformersIndex, textMatchTransformers) {
233
- const textNode = lexical.$createTextNode(lineText);
252
+ const lineTextTrimmed = lineText.trim();
253
+ const textNode = lexical.$createTextNode(lineTextTrimmed);
234
254
  const elementNode = lexical.$createParagraphNode();
235
255
  elementNode.append(textNode);
236
256
  rootNode.append(elementNode);
@@ -248,7 +268,32 @@ function importBlocks(lineText, rootNode, elementTransformers, textFormatTransfo
248
268
  }
249
269
  }
250
270
 
251
- importTextFormatTransformers(textNode, textFormatTransformersIndex, textMatchTransformers);
271
+ importTextFormatTransformers(textNode, textFormatTransformersIndex, textMatchTransformers); // If no transformer found and we left with original paragraph node
272
+ // can check if its content can be appended to the previous node
273
+ // if it's a paragraph, quote or list
274
+
275
+ if (elementNode.isAttached() && lineTextTrimmed.length > 0) {
276
+ const previousNode = elementNode.getPreviousSibling();
277
+
278
+ if (lexical.$isParagraphNode(previousNode) || richText.$isQuoteNode(previousNode) || list.$isListNode(previousNode)) {
279
+ let targetNode = previousNode;
280
+
281
+ if (list.$isListNode(previousNode)) {
282
+ const lastDescendant = previousNode.getLastDescendant();
283
+
284
+ if (lastDescendant == null) {
285
+ targetNode = null;
286
+ } else {
287
+ targetNode = utils.$findMatchingParent(lastDescendant, list.$isListItemNode);
288
+ }
289
+ }
290
+
291
+ if (targetNode != null && targetNode.getTextContentSize() > 0) {
292
+ targetNode.splice(targetNode.getChildrenSize(), 0, [lexical.$createLineBreakNode(), ...elementNode.getChildren()]);
293
+ elementNode.remove();
294
+ }
295
+ }
296
+ }
252
297
  }
253
298
 
254
299
  function importCodeBlock(lines, startLineIndex, rootNode) {
@@ -292,20 +337,20 @@ function importTextFormatTransformers(textNode, textFormatTransformersIndex, tex
292
337
  return;
293
338
  }
294
339
 
295
- let currentNode, remainderNode; // If matching full content there's no need to run splitText and can reuse existing textNode
340
+ let currentNode, remainderNode, leadingNode; // If matching full content there's no need to run splitText and can reuse existing textNode
296
341
  // to update its content and apply format. E.g. for **_Hello_** string after applying bold
297
342
  // format (**) it will reuse the same text node to apply italic (_)
298
343
 
299
344
  if (match[0] === textContent) {
300
345
  currentNode = textNode;
301
346
  } else {
302
- const startIndex = match.index;
347
+ const startIndex = match.index || 0;
303
348
  const endIndex = startIndex + match[0].length;
304
349
 
305
350
  if (startIndex === 0) {
306
351
  [currentNode, remainderNode] = textNode.splitText(endIndex);
307
352
  } else {
308
- [, currentNode, remainderNode] = textNode.splitText(startIndex, endIndex);
353
+ [leadingNode, currentNode, remainderNode] = textNode.splitText(startIndex, endIndex);
309
354
  }
310
355
  }
311
356
 
@@ -323,8 +368,12 @@ function importTextFormatTransformers(textNode, textFormatTransformersIndex, tex
323
368
 
324
369
  if (!currentNode.hasFormat('code')) {
325
370
  importTextFormatTransformers(currentNode, textFormatTransformersIndex, textMatchTransformers);
326
- } // Run over remaining text if any
371
+ } // Run over leading/remaining text if any
372
+
327
373
 
374
+ if (leadingNode) {
375
+ importTextFormatTransformers(leadingNode, textFormatTransformersIndex, textMatchTransformers);
376
+ }
328
377
 
329
378
  if (remainderNode) {
330
379
  importTextFormatTransformers(remainderNode, textFormatTransformersIndex, textMatchTransformers);
@@ -342,7 +391,7 @@ function importTextMatchTransformers(textNode_, textMatchTransformers) {
342
391
  continue;
343
392
  }
344
393
 
345
- const startIndex = match.index;
394
+ const startIndex = match.index || 0;
346
395
  const endIndex = startIndex + match[0].length;
347
396
  let replaceNode;
348
397
 
@@ -389,7 +438,7 @@ function findOutermostMatch(textContent, textTransformersIndex) {
389
438
 
390
439
 
391
440
  const {
392
- index
441
+ index = 0
393
442
  } = fullMatch;
394
443
  const beforeChar = textContent[index - 1];
395
444
  const afterChar = textContent[index + fullMatch[0].length];
@@ -494,7 +543,7 @@ function runTextMatchTransformers(anchorNode, anchorOffset, transformersByTrigge
494
543
  continue;
495
544
  }
496
545
 
497
- const startIndex = match.index;
546
+ const startIndex = match.index || 0;
498
547
  const endIndex = startIndex + match[0].length;
499
548
  let replaceNode;
500
549
 
@@ -598,6 +647,7 @@ function runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransform
598
647
  closeNode.setTextContent(closeNodeText);
599
648
  const openNodeText = openNode === closeNode ? closeNodeText : prevOpenNodeText;
600
649
  openNode.setTextContent(openNodeText.slice(0, openTagStartIndex) + openNodeText.slice(openTagStartIndex + tagLength));
650
+ const selection = lexical.$getSelection();
601
651
  const nextSelection = lexical.$createRangeSelection();
602
652
  lexical.$setSelection(nextSelection); // Adjust offset based on deleted chars
603
653
 
@@ -620,6 +670,10 @@ function runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransform
620
670
  }
621
671
  }
622
672
 
673
+ if (lexical.$isRangeSelection(selection)) {
674
+ nextSelection.format = selection.format;
675
+ }
676
+
623
677
  return true;
624
678
  }
625
679
 
@@ -806,10 +860,37 @@ const HEADING = {
806
860
  };
807
861
  const QUOTE = {
808
862
  export: (node, exportChildren) => {
809
- return richText.$isQuoteNode(node) ? '> ' + exportChildren(node) : null;
863
+ if (!richText.$isQuoteNode(node)) {
864
+ return null;
865
+ }
866
+
867
+ const lines = exportChildren(node).split('\n');
868
+ const output = [];
869
+
870
+ for (const line of lines) {
871
+ output.push('> ' + line);
872
+ }
873
+
874
+ return output.join('\n');
810
875
  },
811
876
  regExp: /^>\s/,
812
- replace: replaceWithBlock(() => richText.$createQuoteNode()),
877
+ replace: (parentNode, children, _match, isImport) => {
878
+ if (isImport) {
879
+ const previousNode = parentNode.getPreviousSibling();
880
+
881
+ if (richText.$isQuoteNode(previousNode)) {
882
+ previousNode.splice(previousNode.getChildrenSize(), 0, [lexical.$createLineBreakNode(), ...children]);
883
+ previousNode.select(0, 0);
884
+ parentNode.remove();
885
+ return;
886
+ }
887
+ }
888
+
889
+ const node = richText.$createQuoteNode();
890
+ node.append(...children);
891
+ parentNode.replace(node);
892
+ node.select(0, 0);
893
+ },
813
894
  type: 'element'
814
895
  };
815
896
  const CODE = {
@@ -4,25 +4,25 @@
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 n=require("lexical"),y=require("@lexical/code"),D=require("@lexical/link"),E=require("@lexical/list"),F=require("@lexical/rich-text");function G(a,b){let c={};for(let d of a)a=b(d),c[a]?c[a].push(d):c[a]=[d];return c}function H(a){a=G(a,b=>b.type);return{element:a.element,textFormat:a["text-format"],textMatch:a["text-match"]}}let I=/[!-/:-@[-`{-~\s]/;
8
- function aa(a){let b=H(a),c=b.textFormat.filter(d=>1===d.format.length);return()=>{let d=[];var e=n.$getRoot().getChildren();for(let f of e)e=ba(f,b.element,c,b.textMatch),null!=e&&d.push(e);return d.join("\n")}}function ba(a,b,c,d){for(let e of b)if(b=e.export(a,f=>K(f,c,d)),null!=b)return b;return n.$isElementNode(a)?K(a,c,d):null}
9
- function K(a,b,c){let d=[];a=a.getChildren();a:for(let e of a)if(n.$isLineBreakNode(e))d.push("\n");else if(n.$isTextNode(e))d.push(L(e,e.getTextContent(),b));else{for(let f of c)if(a=f.export(e,m=>K(m,b,c),(m,h)=>L(m,h,b)),null!=a){d.push(a);continue a}n.$isElementNode(e)&&d.push(K(e,b,c))}return d.join("")}
10
- function L(a,b,c){let d=b.trim(),e=d,f=new Set;for(let h of c){c=h.format[0];let p=h.tag;if(M(a,c)&&!f.has(c)){f.add(c);var m=N(a,!0);M(m,c)||(e=p+e);m=N(a,!1);M(m,c)||(e+=p)}}return b.replace(d,e)}
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(n.$isElementNode(c)){if(!c.isInline())break;a=b?c.getLastDescendant():c.getFirstDescendant();if(n.$isTextNode(a))return a;c=b?c.getPreviousSibling():c.getNextSibling()}if(n.$isTextNode(c))return c;if(!n.$isElementNode(c))break}return null}function M(a,b){return n.$isTextNode(a)&&a.hasFormat(b)}let O=/^```(\w{1,10})?\s?$/;
12
- function ca(a){let b=H(a),c=da(b.textFormat);return d=>{d=d.split("\n");let e=d.length,f=n.$getRoot();f.clear();for(let q=0;q<e;q++){var m=d[q];a:{var h=d,p=q;var r=f;var w=h[p].match(O);if(w)for(var t=p,l=h.length;++t<l;)if(h[t].match(O)){w=y.$createCodeNode(w[1]);h=n.$createTextNode(h.slice(p+1,t).join("\n"));w.append(h);r.append(w);r=[w,t];break a}r=[null,p]}let [k,g]=r;if(null!=k)q=g;else{w=f;l=b.element;r=c;t=b.textMatch;h=n.$createTextNode(m);p=n.$createParagraphNode();p.append(h);w.append(p);
13
- for(let {regExp:u,replace:v}of l)if(w=m.match(u)){h.setTextContent(m.slice(w[0].length));v(p,[h],w,!0);break}P(h,r,t)}}f.selectEnd()}}
14
- function P(a,b,c){let d=a.getTextContent(),e=ea(d,b);if(e){if(e[0]===d)var f=a;else{var m=e.index,h=m+e[0].length;0===m?[f,r]=a.splitText(h):[,f,r]=a.splitText(m,h)}f.setTextContent(e[2]);if(m=b.transformersByTag[e[1]])for(var p of m.format)f.hasFormat(p)||f.toggleFormat(p);f.hasFormat("code")||P(f,b,c);r&&P(r,b,c)}else a:for(b=a;b;){for(m of c)if(f=b.getTextContent().match(m.importRegExp)){var r=f.index;p=r+f[0].length;0===r?[h,b]=b.splitText(p):[,h,b]=b.splitText(r,p);m.replace(h,f);continue a}break}}
15
- function ea(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}=c;d=a[e-1];e=a[e+c[0].length];if(!(d&&!I.test(d)||e&&!I.test(e)))return c}}return null}
16
- function da(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]=new RegExp(`(${f})(?![${f}\\s])(.*?[^${f}\\s])${f}(?!${f})`)}return{fullMatchRegExpByTag:c,openTagsRegExp:new RegExp("("+d.join("|")+")","g"),transformersByTag:b}}function Q(a,b,c){let d=c.length;for(;b>=d;b--){let e=b-d;if(R(a,e,c,0,d)&&" "!==a[e+d])return e}return-1}function R(a,b,c,d,e){for(let f=0;f<e;f++)if(a[b+f]!==c[d+f])return!1;return!0}
17
- let S=a=>(b,c,d)=>{d=a(d);d.append(...c);b.replace(d);d.select(0,0)},T=a=>(b,c,d)=>{var e=b.getPreviousSibling();const f=E.$createListItemNode("check"===a?"x"===d[3]:void 0);E.$isListNode(e)&&e.getListType()===a?(e.append(f),b.remove()):(e=E.$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)},U=(a,b,c)=>{const d=[];var e=a.getChildren();let f=0;for(const h of e)if(E.$isListItemNode(h)){if(1===h.getChildrenSize()&&
18
- (e=h.getFirstChild(),E.$isListNode(e))){d.push(U(e,b,c+1));continue}e=" ".repeat(4*c);var m=a.getListType();m="number"===m?`${a.getStart()+f}. `:"check"===m?`- [${h.getChecked()?"x":" "}] `:"- ";d.push(e+m+b(h));f++}return d.join("\n")},V={export:(a,b)=>{if(!F.$isHeadingNode(a))return null;const c=Number(a.getTag().slice(1));return"#".repeat(c)+" "+b(a)},regExp:/^(#{1,6})\s/,replace:S(a=>F.$createHeadingNode("h"+a[1].length)),type:"element"},W={export:(a,b)=>F.$isQuoteNode(a)?"> "+b(a):null,regExp:/^>\s/,
19
- replace:S(()=>F.$createQuoteNode()),type:"element"},X={export:a=>{if(!y.$isCodeNode(a))return null;const b=a.getTextContent();return"```"+(a.getLanguage()||"")+(b?"\n"+b:"")+"\n```"},regExp:/^```(\w{1,10})?\s/,replace:S(a=>y.$createCodeNode(a?a[1]:void 0)),type:"element"},Y={export:(a,b)=>E.$isListNode(a)?U(a,b,0):null,regExp:/^(\s*)[-*+]\s/,replace:T("bullet"),type:"element"},fa={export:(a,b)=>E.$isListNode(a)?U(a,b,0):null,regExp:/^(\s*)(?:-\s)?\s?(\[(\s|x)?\])\s/i,replace:T("check"),type:"element"},
20
- ha={export:(a,b)=>E.$isListNode(a)?U(a,b,0):null,regExp:/^(\s*)(\d{1,})\.\s/,replace:T("number"),type:"element"},ia={format:["code"],tag:"`",type:"text-format"},ja={format:["bold","italic"],tag:"***",type:"text-format"},ka={format:["bold","italic"],intraword:!1,tag:"___",type:"text-format"},la={format:["bold"],tag:"**",type:"text-format"},ma={format:["bold"],intraword:!1,tag:"__",type:"text-format"},na={format:["strikethrough"],tag:"~~",type:"text-format"},oa={format:["italic"],tag:"*",type:"text-format"},
21
- pa={format:["italic"],intraword:!1,tag:"_",type:"text-format"},qa={export:(a,b,c)=>{if(!D.$isLinkNode(a))return null;b=`[${a.getTextContent()}](${a.getURL()})`;const d=a.getFirstChild();return 1===a.getChildrenSize()&&n.$isTextNode(d)?c(d,b):b},importRegExp:/(?:\[([^[]+)\])(?:\(([^(]+)\))/,regExp:/(?:\[([^[]+)\])(?:\(([^(]+)\))$/,replace:(a,b)=>{const [,c,d]=b;b=D.$createLinkNode(d);const e=n.$createTextNode(c);e.setFormat(a.getFormat());b.append(e);a.replace(b)},trigger:")",type:"text-match"},ra=
22
- [V,W,X,Y,ha],sa=[ia,ja,ka,la,ma,oa,pa,na],ta=[qa],Z=[...ra,...sa,...ta];exports.$convertFromMarkdownString=function(a,b=Z){return ca(b)(a)};exports.$convertToMarkdownString=function(a=Z){return aa(a)()};exports.BOLD_ITALIC_STAR=ja;exports.BOLD_ITALIC_UNDERSCORE=ka;exports.BOLD_STAR=la;exports.BOLD_UNDERSCORE=ma;exports.CHECK_LIST=fa;exports.CODE=X;exports.ELEMENT_TRANSFORMERS=ra;exports.HEADING=V;exports.INLINE_CODE=ia;exports.ITALIC_STAR=oa;exports.ITALIC_UNDERSCORE=pa;exports.LINK=qa;
23
- exports.ORDERED_LIST=ha;exports.QUOTE=W;exports.STRIKETHROUGH=na;exports.TEXT_FORMAT_TRANSFORMERS=sa;exports.TEXT_MATCH_TRANSFORMERS=ta;exports.TRANSFORMERS=Z;exports.UNORDERED_LIST=Y;
24
- exports.registerMarkdownShortcuts=function(a,b=Z){let c=H(b),d=G(c.textFormat,({tag:f})=>f[f.length-1]),e=G(c.textMatch,({trigger:f})=>f);return a.registerUpdateListener(({tags:f,dirtyLeaves:m,editorState:h,prevEditorState:p})=>{if(!f.has("historic")){var r=h.read(n.$getSelection);f=p.read(n.$getSelection);if(n.$isRangeSelection(f)&&n.$isRangeSelection(r)&&r.isCollapsed()){p=r.anchor.key;var w=r.anchor.offset,t=h._nodeMap.get(p);n.$isTextNode(t)&&m.has(p)&&(1===w||w===f.anchor.offset+1)&&a.update(()=>
25
- {if(!t.hasFormat("code")){var l=t.getParent();if(null!==l&&!y.$isCodeNode(l)){var q=r.anchor.offset;b:{var k=c.element,g=l.getParent();if(n.$isRootNode(g)&&l.getFirstChild()===t&&(g=t.getTextContent()," "===g[q-1]))for(let {regExp:J,replace:B}of k)if((k=g.match(J))&&k[0].length===q){g=t.getNextSiblings();let [C,z]=t.splitText(q);C.remove();g=z?[z,...g]:g;B(l,g,k,!1);l=!0;break b}l=!1}if(!l){b:{k=t.getTextContent();l=e[k[q-1]];if(null!=l){q<k.length&&(k=k.slice(0,q));for(v of l)if(l=k.match(v.regExp),
26
- null!==l){k=l.index;g=k+l[0].length;var u=void 0;0===k?[u]=t.splitText(g):[,u]=t.splitText(k,g);u.selectNext();v.replace(u,l);var v=!0;break b}}v=!1}if(!v)b:{g=t.getTextContent();--q;let J=g[q];if(v=d[J])for(let B of v){var {tag:A}=B;v=A.length;let C=q-v+1;if(!(1<v&&!R(g,C,A,0,v)||" "===g[C-1])&&(u=g[q+1],!1!==B.intraword||!u||I.test(u))){l=u=t;k=Q(g,C,A);for(var x=l;0>k&&(x=x.getPreviousSibling())&&!n.$isLineBreakNode(x);)n.$isTextNode(x)&&(k=x.getTextContent(),l=x,k=Q(k,k.length,A));if(!(0>k||l===
27
- u&&k+v===C||(A=l.getTextContent(),0<k&&A[k-1]===J||(x=A[k-1],!1===B.intraword&&x&&!I.test(x))))){g=u.getTextContent();g=g.slice(0,C)+g.slice(q+1);u.setTextContent(g);g=l===u?g:A;l.setTextContent(g.slice(0,k)+g.slice(k+v));g=n.$createRangeSelection();n.$setSelection(g);q=q-v*(l===u?2:1)+1;g.anchor.set(l.__key,k,"text");g.focus.set(u.__key,q,"text");for(let z of B.format)g.hasFormat(z)||g.formatText(z);g.anchor.set(g.focus.key,g.focus.offset,g.focus.type);for(let z of B.format)g.hasFormat(z)&&g.toggleFormat(z);
28
- break b}}}}}}}})}}})}
7
+ 'use strict';var h=require("lexical"),y=require("@lexical/code"),E=require("@lexical/list"),F=require("@lexical/rich-text"),aa=require("@lexical/utils"),G=require("@lexical/link");function H(a,b){let c={};for(let d of a)a=b(d),c[a]?c[a].push(d):c[a]=[d];return c}function I(a){a=H(a,b=>b.type);return{element:a.element||[],textFormat:a["text-format"]||[],textMatch:a["text-match"]||[]}}let J=/[!-/:-@[-`{-~\s]/;
8
+ function ba(a){let b=I(a),c=b.textFormat.filter(d=>1===d.format.length);return()=>{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):null}
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,k=>K(k,b,c),(k,p)=>L(k,p,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))}return d.join("")}function L(a,b,c){let d=b.trim(),e=d,f=new Set;for(let p of c){c=p.format[0];let r=p.tag;if(M(a,c)&&!f.has(c)){f.add(c);var k=N(a,!0);M(k,c)||(e=r+e);k=N(a,!1);M(k,c)||(e+=r)}}return b.replace(d,e)}
10
+ 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)}let da=/^\s{0,3}$/,O=/^```(\w{1,10})?\s?$/;
11
+ function ea(a){let b=I(a),c=fa(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 k=e[g];a:{var p=e,r=g;var n=d;var t=p[r].match(O);if(t)for(var q=r,l=p.length;++q<l;)if(p[q].match(O)){t=y.$createCodeNode(t[1]);p=h.$createTextNode(p.slice(r+1,q).join("\n"));t.append(p);n.append(t);n=[t,q];break a}n=[null,r]}let [m,v]=n;if(null!=m)g=v;else{n=k;l=d;var w=b.element;q=c;p=b.textMatch;r=n.trim();t=h.$createTextNode(r);k=h.$createParagraphNode();k.append(t);
12
+ l.append(k);for(let {regExp:x,replace:u}of w)if(l=n.match(x)){t.setTextContent(n.slice(l[0].length));u(k,[t],l,!0);break}P(t,q,p);k.isAttached()&&0<r.length&&(n=k.getPreviousSibling(),h.$isParagraphNode(n)||F.$isQuoteNode(n)||E.$isListNode(n))&&(q=n,E.$isListNode(n)&&(n=n.getLastDescendant(),q=null==n?null:aa.$findMatchingParent(n,E.$isListItemNode)),null!=q&&0<q.getTextContentSize()&&(q.splice(q.getChildrenSize(),0,[h.$createLineBreakNode(),...k.getChildren()]),k.remove()))}}e=d.getChildren();for(let g of e)e=
13
+ g,h.$isParagraphNode(e)?(f=e.getFirstChild(),e=null==f||1===e.getChildrenSize()&&h.$isTextNode(f)&&da.test(f.getTextContent())):e=!1,e&&g.remove();d.selectEnd()}}
14
+ function P(a,b,c){let d=a.getTextContent(),e=ha(d,b);if(e){if(e[0]===d)var f=a;else{var k=e.index||0,p=k+e[0].length;0===k?[f,r]=a.splitText(p):[n,f,r]=a.splitText(k,p)}f.setTextContent(e[2]);if(k=b.transformersByTag[e[1]])for(let t of k.format)f.hasFormat(t)||f.toggleFormat(t);f.hasFormat("code")||P(f,b,c);n&&P(n,b,c);r&&P(r,b,c)}else a:for(b=a;b;){for(k of c)if(f=b.getTextContent().match(k.importRegExp)){var r=f.index||0;var n=r+f[0].length;0===r?[p,b]=b.splitText(n):[,p,b]=b.splitText(r,n);k.replace(p,
15
+ f);continue a}break}}function ha(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}
16
+ function fa(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]=new RegExp(`(${f})(?![${f}\\s])(.*?[^${f}\\s])${f}(?!${f})`)}return{fullMatchRegExpByTag:c,openTagsRegExp:new RegExp("("+d.join("|")+")","g"),transformersByTag:b}}function Q(a,b,c){let d=c.length;for(;b>=d;b--){let e=b-d;if(R(a,e,c,0,d)&&" "!==a[e+d])return e}return-1}function R(a,b,c,d,e){for(let f=0;f<e;f++)if(a[b+f]!==c[d+f])return!1;return!0}
17
+ let S=a=>(b,c,d)=>{d=a(d);d.append(...c);b.replace(d);d.select(0,0)},T=a=>(b,c,d)=>{var e=b.getPreviousSibling();const f=E.$createListItemNode("check"===a?"x"===d[3]:void 0);E.$isListNode(e)&&e.getListType()===a?(e.append(f),b.remove()):(e=E.$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)},U=(a,b,c)=>{const d=[];var e=a.getChildren();let f=0;for(const p of e)if(E.$isListItemNode(p)){if(1===p.getChildrenSize()&&
18
+ (e=p.getFirstChild(),E.$isListNode(e))){d.push(U(e,b,c+1));continue}e=" ".repeat(4*c);var k=a.getListType();k="number"===k?`${a.getStart()+f}. `:"check"===k?`- [${p.getChecked()?"x":" "}] `:"- ";d.push(e+k+b(p));f++}return d.join("\n")},V={export:(a,b)=>{if(!F.$isHeadingNode(a))return null;const c=Number(a.getTag().slice(1));return"#".repeat(c)+" "+b(a)},regExp:/^(#{1,6})\s/,replace:S(a=>F.$createHeadingNode("h"+a[1].length)),type:"element"},W={export:(a,b)=>{if(!F.$isQuoteNode(a))return null;a=b(a).split("\n");
19
+ 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(),F.$isQuoteNode(c))){c.splice(c.getChildrenSize(),0,[h.$createLineBreakNode(),...b]);c.select(0,0);a.remove();return}c=F.$createQuoteNode();c.append(...b);a.replace(c);c.select(0,0)},type:"element"},X={export:a=>{if(!y.$isCodeNode(a))return null;const b=a.getTextContent();return"```"+(a.getLanguage()||"")+(b?"\n"+b:"")+"\n```"},regExp:/^```(\w{1,10})?\s/,replace:S(a=>y.$createCodeNode(a?
20
+ a[1]:void 0)),type:"element"},Y={export:(a,b)=>E.$isListNode(a)?U(a,b,0):null,regExp:/^(\s*)[-*+]\s/,replace:T("bullet"),type:"element"},ia={export:(a,b)=>E.$isListNode(a)?U(a,b,0):null,regExp:/^(\s*)(?:-\s)?\s?(\[(\s|x)?\])\s/i,replace:T("check"),type:"element"},ja={export:(a,b)=>E.$isListNode(a)?U(a,b,0):null,regExp:/^(\s*)(\d{1,})\.\s/,replace:T("number"),type:"element"},ka={format:["code"],tag:"`",type:"text-format"},la={format:["bold","italic"],tag:"***",type:"text-format"},ma={format:["bold",
21
+ "italic"],intraword:!1,tag:"___",type:"text-format"},na={format:["bold"],tag:"**",type:"text-format"},pa={format:["bold"],intraword:!1,tag:"__",type:"text-format"},qa={format:["strikethrough"],tag:"~~",type:"text-format"},ra={format:["italic"],tag:"*",type:"text-format"},sa={format:["italic"],intraword:!1,tag:"_",type:"text-format"},ta={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)?
22
+ 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());b.append(e);a.replace(b)},trigger:")",type:"text-match"},ua=[V,W,X,Y,ja],va=[ka,la,ma,na,pa,ra,sa,qa],wa=[ta],Z=[...ua,...va,...wa];exports.$convertFromMarkdownString=function(a,b=Z){return ea(b)(a)};exports.$convertToMarkdownString=function(a=Z){return ba(a)()};exports.BOLD_ITALIC_STAR=la;
23
+ exports.BOLD_ITALIC_UNDERSCORE=ma;exports.BOLD_STAR=na;exports.BOLD_UNDERSCORE=pa;exports.CHECK_LIST=ia;exports.CODE=X;exports.ELEMENT_TRANSFORMERS=ua;exports.HEADING=V;exports.INLINE_CODE=ka;exports.ITALIC_STAR=ra;exports.ITALIC_UNDERSCORE=sa;exports.LINK=ta;exports.ORDERED_LIST=ja;exports.QUOTE=W;exports.STRIKETHROUGH=qa;exports.TEXT_FORMAT_TRANSFORMERS=va;exports.TEXT_MATCH_TRANSFORMERS=wa;exports.TRANSFORMERS=Z;exports.UNORDERED_LIST=Y;
24
+ 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);return a.registerUpdateListener(({tags:f,dirtyLeaves:k,editorState:p,prevEditorState:r})=>{if(!f.has("historic")){var n=p.read(h.$getSelection);f=r.read(h.$getSelection);if(h.$isRangeSelection(f)&&h.$isRangeSelection(n)&&n.isCollapsed()){r=n.anchor.key;var t=n.anchor.offset,q=p._nodeMap.get(r);h.$isTextNode(q)&&k.has(r)&&(1===t||t===f.anchor.offset+1)&&a.update(()=>
25
+ {if(!q.hasFormat("code")){var l=q.getParent();if(null!==l&&!y.$isCodeNode(l)){var w=n.anchor.offset;b:{var g=c.element,m=l.getParent();if(h.$isRootNode(m)&&l.getFirstChild()===q&&(m=q.getTextContent()," "===m[w-1]))for(let {regExp:B,replace:C}of g)if((g=m.match(B))&&g[0].length===w){m=q.getNextSiblings();let [D,oa]=q.splitText(w);D.remove();m=oa?[oa,...m]:m;C(l,m,g,!1);l=!0;break b}l=!1}if(!l){b:{g=q.getTextContent();l=e[g[w-1]];if(null!=l){w<g.length&&(g=g.slice(0,w));for(x of l)if(l=g.match(x.regExp),
26
+ null!==l){g=l.index||0;m=g+l[0].length;var v=void 0;0===g?[v]=q.splitText(m):[,v]=q.splitText(g,m);v.selectNext();x.replace(v,l);var x=!0;break b}}x=!1}if(!x)b:{m=q.getTextContent();--w;var u=m[w];if(x=d[u])for(let B of x){var {tag:A}=B;x=A.length;let C=w-x+1;if(!(1<x&&!R(m,C,A,0,x)||" "===m[C-1])&&(v=m[w+1],!1!==B.intraword||!v||J.test(v))){l=v=q;g=Q(m,C,A);for(var z=l;0>g&&(z=z.getPreviousSibling())&&!h.$isLineBreakNode(z);)h.$isTextNode(z)&&(g=z.getTextContent(),l=z,g=Q(g,g.length,A));if(!(0>g||
27
+ l===v&&g+x===C||(A=l.getTextContent(),0<g&&A[g-1]===u||(z=A[g-1],!1===B.intraword&&z&&!J.test(z))))){m=v.getTextContent();m=m.slice(0,C)+m.slice(w+1);v.setTextContent(m);m=l===v?m:A;l.setTextContent(m.slice(0,g)+m.slice(g+x));m=h.$getSelection();u=h.$createRangeSelection();h.$setSelection(u);w=w-x*(l===v?2:1)+1;u.anchor.set(l.__key,g,"text");u.focus.set(v.__key,w,"text");for(let D of B.format)u.hasFormat(D)||u.formatText(D);u.anchor.set(u.focus.key,u.focus.offset,u.focus.type);for(let D of B.format)u.hasFormat(D)&&
28
+ u.toggleFormat(D);h.$isRangeSelection(m)&&(u.format=m.format);break b}}}}}}}})}}})}
package/README.md CHANGED
@@ -22,9 +22,9 @@ editor.update(() => {
22
22
 
23
23
  It can also be used for initializing editor's state from markdown string. Here's an example with react `<RichTextPlugin>`
24
24
  ```jsx
25
- <LexicalComposer initialEditorState={() => {
26
- $convertFromMarkdownString(markdown, TRANSFORMERS);
27
- }}>
25
+ <LexicalComposer initialConfig={{
26
+ editorState: () => $convertFromMarkdownString(markdown, TRANSFORMERS)
27
+ }}>
28
28
  <RichTextPlugin />
29
29
  </LexicalComposer>
30
30
  ```
package/package.json CHANGED
@@ -8,18 +8,18 @@
8
8
  "markdown"
9
9
  ],
10
10
  "license": "MIT",
11
- "version": "0.3.5",
11
+ "version": "0.3.8",
12
12
  "main": "LexicalMarkdown.js",
13
13
  "peerDependencies": {
14
- "lexical": "0.3.5"
14
+ "lexical": "0.3.8"
15
15
  },
16
16
  "dependencies": {
17
- "@lexical/utils": "0.3.5",
18
- "@lexical/code": "0.3.5",
19
- "@lexical/text": "0.3.5",
20
- "@lexical/rich-text": "0.3.5",
21
- "@lexical/list": "0.3.5",
22
- "@lexical/link": "0.3.5"
17
+ "@lexical/utils": "0.3.8",
18
+ "@lexical/code": "0.3.8",
19
+ "@lexical/text": "0.3.8",
20
+ "@lexical/rich-text": "0.3.8",
21
+ "@lexical/list": "0.3.8",
22
+ "@lexical/link": "0.3.8"
23
23
  },
24
24
  "repository": {
25
25
  "type": "git",