@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.
- package/LexicalMarkdown.dev.js +110 -29
- package/LexicalMarkdown.prod.js +22 -22
- package/README.md +3 -3
- package/package.json +8 -8
package/LexicalMarkdown.dev.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
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 = {
|
package/LexicalMarkdown.prod.js
CHANGED
|
@@ -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
|
|
8
|
-
function
|
|
9
|
-
function K(a,b,c){let d=[];a=a.getChildren();a:for(let e of a)
|
|
10
|
-
function
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function P(a,b,c){let d=a.getTextContent(),e=
|
|
15
|
-
function
|
|
16
|
-
function
|
|
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
|
|
18
|
-
(e=
|
|
19
|
-
replace:
|
|
20
|
-
|
|
21
|
-
pa={format:["italic"],intraword:!1,tag:"_",type:"text-format"},
|
|
22
|
-
[V,W,X,Y,
|
|
23
|
-
exports.ORDERED_LIST=
|
|
24
|
-
exports.registerMarkdownShortcuts=function(a,b=Z){let c=
|
|
25
|
-
{if(!
|
|
26
|
-
null!==l){
|
|
27
|
-
|
|
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
|
|
26
|
-
|
|
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.
|
|
11
|
+
"version": "0.3.8",
|
|
12
12
|
"main": "LexicalMarkdown.js",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"lexical": "0.3.
|
|
14
|
+
"lexical": "0.3.8"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lexical/utils": "0.3.
|
|
18
|
-
"@lexical/code": "0.3.
|
|
19
|
-
"@lexical/text": "0.3.
|
|
20
|
-
"@lexical/rich-text": "0.3.
|
|
21
|
-
"@lexical/list": "0.3.
|
|
22
|
-
"@lexical/link": "0.3.
|
|
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",
|