@lexical/markdown 0.2.3 → 0.2.6

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.
@@ -7,13 +7,91 @@
7
7
  * @flow strict
8
8
  */
9
9
 
10
- import type {DecoratorNode, LexicalEditor} from 'lexical';
10
+ import type {
11
+ LexicalEditor,
12
+ LexicalNode,
13
+ ElementNode,
14
+ TextFormatType,
15
+ TextNode,
16
+ } from 'lexical';
11
17
 
12
- declare export function registerMarkdownShortcuts<T>(
18
+ export type Transformer =
19
+ | ElementTransformer
20
+ | TextFormatTransformer
21
+ | TextMatchTransformer;
22
+
23
+ export type ElementTransformer = {
24
+ export: (
25
+ node: LexicalNode,
26
+ traverseChildren: (node: ElementNode) => string,
27
+ ) => string | null,
28
+ regExp: RegExp,
29
+ replace: (
30
+ parentNode: ElementNode,
31
+ children: Array<LexicalNode>,
32
+ match: Array<string>,
33
+ isImport: boolean,
34
+ ) => void,
35
+ type: 'element',
36
+ };
37
+
38
+ export type TextFormatTransformer = $ReadOnly<{
39
+ format: $ReadOnlyArray<TextFormatType>,
40
+ tag: string,
41
+ type: 'text-format',
42
+ }>;
43
+
44
+ export type TextMatchTransformer = $ReadOnly<{
45
+ export: (
46
+ node: LexicalNode,
47
+ exportChildren: (node: ElementNode) => string,
48
+ exportFormat: (node: TextNode, textContent: string) => string,
49
+ ) => string | null,
50
+ importRegExp: RegExp,
51
+ regExp: RegExp,
52
+ replace: (node: TextNode, match: RegExp$matchResult) => void,
53
+ trigger: string,
54
+ type: 'text-match',
55
+ }>;
56
+ // TODO:
57
+ // transformers should be required argument, breaking change
58
+ declare export function registerMarkdownShortcuts(
13
59
  editor: LexicalEditor,
14
- createHorizontalRuleNode: () => DecoratorNode<T>,
60
+ transformers?: Array<Transformer>,
15
61
  ): () => void;
62
+
63
+ // TODO:
64
+ // transformers should be required argument, breaking change
16
65
  declare export function $convertFromMarkdownString(
17
- markdownString: string,
18
- editor: LexicalEditor,
66
+ markdown: string,
67
+ transformers?: Array<Transformer>,
19
68
  ): void;
69
+
70
+ // TODO:
71
+ // transformers should be required argument, breaking change
72
+ declare export function $convertToMarkdownString(
73
+ transformers?: Array<Transformer>,
74
+ ): string;
75
+
76
+ declare export var BOLD_ITALIC_STAR: TextFormatTransformer;
77
+ declare export var BOLD_ITALIC_UNDERSCORE: TextFormatTransformer;
78
+ declare export var BOLD_STAR: TextFormatTransformer;
79
+ declare export var BOLD_UNDERSCORE: TextFormatTransformer;
80
+ declare export var INLINE_CODE: TextFormatTransformer;
81
+ declare export var ITALIC_STAR: TextFormatTransformer;
82
+ declare export var ITALIC_UNDERSCORE: TextFormatTransformer;
83
+ declare export var STRIKETHROUGH: TextFormatTransformer;
84
+
85
+ declare export var UNORDERED_LIST: ElementTransformer;
86
+ declare export var CODE: ElementTransformer;
87
+ declare export var HEADING: ElementTransformer;
88
+ declare export var ORDERED_LIST: ElementTransformer;
89
+ declare export var QUOTE: ElementTransformer;
90
+ declare export var CHECK_LIST: ElementTransformer;
91
+
92
+ declare export var LINK: TextMatchTransformer;
93
+
94
+ declare export var TRANSFORMERS: Array<Transformer>;
95
+ declare export var ELEMENT_TRANSFORMERS: Array<ElementTransformer>;
96
+ declare export var TEXT_FORMAT_TRANSFORMERS: Array<TextFormatTransformer>;
97
+ declare export var TEXT_MATCH_TRANSFORMERS: Array<TextFormatTransformer>;
@@ -4,37 +4,23 @@
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
- var k=require("@lexical/code"),n=require("@lexical/list"),p=require("lexical"),u=require("@lexical/link"),v=require("@lexical/rich-text"),x=require("@lexical/text");function y(a){throw Error(`Minified Lexical error #${a}; see codes.json for the full message or `+"use the non-minified dev environment for full errors and additional helpful warnings.");}
8
- const z=[{triggerKind:"space_trigger",triggerString:" "}],A={markdownFormatKind:null,regEx:/(?:)/,regExForAutoFormatting:/(?:)/,requiresParagraphStart:!1},B={...A,requiresParagraphStart:!0},C={...B,markdownFormatKind:"paragraphCodeBlock",regEx:/^(```)$/,regExForAutoFormatting:/^(```)([a-z]*)( )/},D=[{...A,markdownFormatKind:"strikethrough_italic_bold",regEx:/(~~_\*\*)(\s*\b)([^~~_\*\*][^\*\*_~~]*)(\b\s*)(\*\*_~~)()/,regExForAutoFormatting:/(~~_\*\*)(\s*\b)([^~~_\*\*][^\*\*_~~]*)(\b\s*)(\*\*_~~)(\s)$/},
9
- {...A,markdownFormatKind:"italic_bold",regEx:/(_\*\*)(\s*\b)([^_\*\*][^\*\*_]*)(\b\s*)(\*\*_)/,regExForAutoFormatting:/(_\*\*)(\s*\b)([^_\*\*][^\*\*_]*)(\b\s*)(\*\*_)(\s)$/},{...A,markdownFormatKind:"strikethrough_italic",regEx:/(~~_)(\s*)([^~~_][^_~~]*)(\s*)(_~~)/,regExForAutoFormatting:/(~~_)(\s*)([^~~_][^_~~]*)(\s*)(_~~)(\s)$/},{...A,markdownFormatKind:"strikethrough_bold",regEx:/(~~\*\*)(\s*\b)([^~~\*\*][^\*\*~~]*)(\b\s*)(\*\*~~)/,regExForAutoFormatting:/(~~\*\*)(\s*\b)([^~~\*\*][^\*\*~~]*)(\b\s*)(\*\*~~)(\s)$/},
10
- {...A,markdownFormatKind:"code",regEx:/(`)([^`]*)(`)/,regExForAutoFormatting:/(`)(\s*\b)([^`]*)(\b\s*)(`)(\s)$/},{...A,markdownFormatKind:"bold",regEx:/(\*\*)(\s*)([^\*\*]*)(\s*)(\*\*)()/,regExForAutoFormatting:/(\*\*)(\s*\b)([^\*\*]*)(\b\s*)(\*\*)(\s)$/},{...A,markdownFormatKind:"italic",regEx:/(\*)(\s*)([^\*]*)(\s*)(\*)()/,regExForAutoFormatting:/(\*)(\s*\b)([^\*]*)(\b\s*)(\*)(\s)$/},{...A,markdownFormatKind:"bold",regEx:/(__)(\s*)([^__]*)(\s*)(__)()/,regExForAutoFormatting:/(__)(\s*)([^__]*)(\s*)(__)(\s)$/},
11
- {...A,markdownFormatKind:"italic",regEx:/(_)()([^_]*)()(_)()/,regExForAutoFormatting:/(_)()([^_]*)()(_)(\s)$/},{...A,markdownFormatKind:"underline",regEx:/(<u>)(\s*)([^<]*)(\s*)(<\/u>)()/,regExForAutoFormatting:/(<u>)(\s*\b)([^<]*)(\b\s*)(<\/u>)(\s)$/},{...A,markdownFormatKind:"strikethrough",regEx:/(~~)(\s*)([^~~]*)(\s*)(~~)()/,regExForAutoFormatting:/(~~)(\s*\b)([^~~]*)(\b\s*)(~~)(\s)$/},{...A,markdownFormatKind:"link",regEx:/(\[)([^\]]*)(\]\()([^)]*)(\)*)()/,regExForAutoFormatting:/(\[)([^\]]*)(\]\()([^)]*)(\)*)(\s)$/}],
12
- E=[{...B,markdownFormatKind:"paragraphH1",regEx:/^(?:# )/,regExForAutoFormatting:/^(?:# )/},{...B,markdownFormatKind:"paragraphH2",regEx:/^(?:## )/,regExForAutoFormatting:/^(?:## )/},{...B,markdownFormatKind:"paragraphH3",regEx:/^(?:### )/,regExForAutoFormatting:/^(?:### )/},{...B,markdownFormatKind:"paragraphH4",regEx:/^(?:#### )/,regExForAutoFormatting:/^(?:#### )/},{...B,markdownFormatKind:"paragraphH5",regEx:/^(?:##### )/,regExForAutoFormatting:/^(?:##### )/},{...B,markdownFormatKind:"paragraphBlockQuote",
13
- regEx:/^(?:> )/,regExForAutoFormatting:/^(?:> )/},{...B,markdownFormatKind:"paragraphUnorderedList",regEx:/^(\s{0,10})(?:- )/,regExForAutoFormatting:/^(\s{0,10})(?:- )/},{...B,markdownFormatKind:"paragraphUnorderedList",regEx:/^(\s{0,10})(?:\* )/,regExForAutoFormatting:/^(\s{0,10})(?:\* )/},{...B,markdownFormatKind:"paragraphOrderedList",regEx:/^(\s{0,10})(\d+)\.\s/,regExForAutoFormatting:/^(\s{0,10})(\d+)\.\s/},C,{...B,markdownFormatKind:"horizontalRule",regEx:/^(?:\*\*\*)$/,regExForAutoFormatting:/^(?:\*\*\* )/},
14
- {...B,markdownFormatKind:"horizontalRule",regEx:/^(?:---)$/,regExForAutoFormatting:/^(?:--- )/}],F=[...E,...D];function G(a,d,c,b){return{currentElementNode:null,editor:a,isAutoFormatting:d,isWithinCodeBlock:!1,joinedText:null,markdownCriteria:{markdownFormatKind:"noTransformation",regEx:/(?:)/,regExForAutoFormatting:/(?:)/,requiresParagraphStart:null},patternMatchResults:{regExCaptureGroups:[]},textNodeWithOffset:c,triggerState:b}}
15
- function H(a){a.joinedText=null;a.markdownCriteria={markdownFormatKind:"noTransformation",regEx:/(?:)/,regExForAutoFormatting:/(?:)/,requiresParagraphStart:null};a.patternMatchResults={regExCaptureGroups:[]};a.triggerState=null;a.textNodeWithOffset=null;return a}
16
- function I(a,d,c){if(!0===a.requiresParagraphStart)return c=J(d),null===c.node.getPreviousSibling()?(c=c.node.getTextContent(),a=K(c,!0,!1,d.isAutoFormatting?a.regExForAutoFormatting:a.regEx)):a=null,a;null==d.joinedText&&(p.$isElementNode(c)?null==d.joinedText&&(d.joinedText=x.$joinTextNodesInElementNode(c,"\u0004",J(d))):y(52,c.__key));return K(d.joinedText,!1,!0===a.regExForAutoFormatting,d.isAutoFormatting?a.regExForAutoFormatting:a.regEx)}
17
- function K(a,d,c,b){const e={regExCaptureGroups:[]};b=a.match(b);if(null!==b&&0<b.length&&(!1===d||0===b.index)&&(!1===c||b.index+b[0].length===a.length)){a=b.length;d=b.index;for(c=0;c<a;c++){const f=b[c];e.regExCaptureGroups.push({offsetInParent:d,text:f});0<c&&(d+=f.length)}return e}return null}function J(a){a=a.textNodeWithOffset;null==a&&y(82);return a}
18
- function L(a,d,c){var b=null,e=d.getChildren();const f=a.markdownCriteria,g=a.patternMatchResults;if(null!=f.markdownFormatKind)switch(f.markdownFormatKind){case "paragraphH1":b=v.$createHeadingNode("h1");b.append(...e);break;case "paragraphH2":b=v.$createHeadingNode("h2");b.append(...e);break;case "paragraphH3":b=v.$createHeadingNode("h3");b.append(...e);break;case "paragraphH4":b=v.$createHeadingNode("h4");b.append(...e);break;case "paragraphH5":b=v.$createHeadingNode("h5");b.append(...e);break;
19
- case "paragraphBlockQuote":b=v.$createQuoteNode();b.append(...e);break;case "paragraphUnorderedList":return M(d,e,g,"ul"),{newNode:null,shouldDelete:!1};case "paragraphOrderedList":return b=1<g.regExCaptureGroups.length?g.regExCaptureGroups[g.regExCaptureGroups.length-1].text:"1",a=a.isAutoFormatting?parseInt(b,10):void 0,M(d,e,g,"ol",a),{newNode:null,shouldDelete:!1};case "paragraphCodeBlock":if(!1===a.isAutoFormatting){if(0<a.patternMatchResults.regExCaptureGroups.length)return a.isWithinCodeBlock=
20
- !0!==a.isWithinCodeBlock,a.currentElementNode=null,{newNode:null,shouldDelete:!0};if(a.isWithinCodeBlock){if(null==a.currentElementNode)return d=k.$createCodeNode(),d.append(...e),a.currentElementNode=d,{newNode:d,shouldDelete:!1};null!=a.currentElementNode&&(d=a.currentElementNode,a=p.$createLineBreakNode(),d.append(a),e.length&&d.append(a),d.append(...e))}return{newNode:null,shouldDelete:!0}}null!=a.triggerState&&a.triggerState.isCodeBlock?b=p.$createParagraphNode():(b=k.$createCodeNode(),d=3<=
21
- g.regExCaptureGroups.length?g.regExCaptureGroups[2].text:null,null!=d&&0<d.length&&b.setLanguage(d));b.append(...e);break;case "horizontalRule":null!=c&&(e=c(),d.insertBefore(e))}return{newNode:b,shouldDelete:!1}}
22
- function M(a,d,c,b,e){const f=n.$createListItemNode();c=(c=c.regExCaptureGroups[0].text.match(/^\s*/))?Math.floor(c[0].length/4):0;f.append(...d);d=a.getPreviousSibling();n.$isListNode(d)&&d.getTag()===b?(d.append(f),a.remove()):(b=n.$createListNode(b,e),b.append(f),a.replace(b));c&&f.setIndent(c)}
23
- function N(a,d,c){if(!0===a.markdownCriteria.requiresParagraphStart){if(null!=a.textNodeWithOffset){var b=J(a);0<a.patternMatchResults.regExCaptureGroups.length&&(b=b.node.spliceText(0,a.patternMatchResults.regExCaptureGroups[0].text.length,"",!0),""===b.getTextContent()&&(b.selectPrevious(),b.remove()))}const {newNode:g,shouldDelete:h}=L(a,d,c);h?d.remove():null!==g&&d.replace(g)}else if(c=a.markdownCriteria,null!=c.markdownFormatKind)if(b=O(c.markdownFormatKind),null!=b){if(c=b,7===a.patternMatchResults.regExCaptureGroups.length){Q(5,
24
- 5,a,d);Q(1,1,a,d);b=a.patternMatchResults.regExCaptureGroups;3<b.length||y(65);if(0!==b[3].text.length&&(b=R(3,3,!1,!0,a,d),null!=b&&(p.$setSelection(b),b=p.$getSelection(),p.$isRangeSelection(b))))for(var e=0;e<c.length;e++)b.formatText(c[e]);S(a,d)}}else if("link"===c.markdownFormatKind&&(c=a.patternMatchResults.regExCaptureGroups,7===c.length&&(e=c[2].text,c=c[4].text,0!==e.length&&0!==c.length))){Q(1,5,a,d);b=a.patternMatchResults.regExCaptureGroups;if(!(1>=b.length)){e={offsetInParent:b[1].offsetInParent,
25
- text:e};var f=R(1,1,!1,!1,a,d);if(null!=f&&(p.$setSelection(f),f=p.$getSelection(),null!=f&&p.$isRangeSelection(f)&&f.isCollapsed())){f.insertText(e.text);b.splice(1,0,e);e=e.text.length;f=b.length;for(let g=2;g<f;g++)b[g].offsetInParent+=e}}b=R(1,1,!1,!0,a,d);null!=b&&(p.$setSelection(b),a.editor.dispatchCommand(u.TOGGLE_LINK_COMMAND,c),S(a,d))}}
26
- function O(a){switch(a){case "italic":case "bold":case "underline":case "strikethrough":case "code":return[a];case "strikethrough_italic_bold":return["strikethrough","italic","bold"];case "italic_bold":return["italic","bold"];case "strikethrough_italic":return["strikethrough","italic"];case "strikethrough_bold":return["strikethrough","bold"]}return null}
27
- function R(a,d,c,b,e,f){var g=e.patternMatchResults;e=g.regExCaptureGroups;var h=e.length;if(a>=h||d>=h)return null;h=g.regExCaptureGroups.length;2>h?g=0:(--h,g=g.regExCaptureGroups[h].offsetInParent+g.regExCaptureGroups[h].text.length);a=e[a];d=e[d];b=b?d.offsetInParent+d.text.length:d.offsetInParent;c=x.$findNodeWithOffsetFromJoinedText(c?a.offsetInParent+a.text.length:a.offsetInParent,g,1,f);b=x.$findNodeWithOffsetFromJoinedText(b,g,1,f);if(null==c&&null==b&&0===f.getChildren().length)return c=
28
- p.$createRangeSelection(),c.anchor.set(f.getKey(),0,"element"),c.focus.set(f.getKey(),0,"element"),c;if(null==c||null==b)return null;f=p.$createRangeSelection();f.anchor.set(c.node.getKey(),c.offset,"text");f.focus.set(b.node.getKey(),b.offset,"text");return f}
29
- function Q(a,d,c,b){const e=c.patternMatchResults.regExCaptureGroups;c=R(a,d,!1,!0,c,b);if(null!=c&&(p.$setSelection(c),c=p.$getSelection(),null!=c&&p.$isRangeSelection(c)&&!1===c.isCollapsed())){c.removeText();c=0;b=e.length;for(let f=a;f<b;f++){const g=e[f];f>a&&(g.offsetInParent-=c);f<=d&&(c+=g.text.length,g.text="")}}}function S(a,d){var c=a.patternMatchResults.regExCaptureGroups.length;2>c||(--c,a=R(c,c,!0,!0,a,d),null!=a&&p.$setSelection(a))}
30
- function T(a,d,c){a.update(()=>{const b=J(d).node.getParentOrThrow();N(d,b,c)},{tag:"history-push"})}
31
- function U(a,d){let c=null;a.getEditorState().read(()=>{var b=p.$getSelection();if(p.$isRangeSelection(b)){var e=b.anchor.getNode();b=p.$isTextNode(e)?{node:e,offset:b.anchor.offset}:null}else b=null;if(null!==b){b=G(a,!0,b,d);a:{e=!1===d.isParentAListItemNode?F:D;const f=b.triggerState,g=e.length;for(let h=0;h<g;h++){const l=e[h];if(null!=f&&!1===f.isCodeBlock||"paragraphCodeBlock"===l.markdownFormatKind){const m=I(l,b,J(b).node.getParentOrThrow());if(null!=m){e={markdownCriteria:l,patternMatchResults:m};
32
- break a}}}e={markdownCriteria:null,patternMatchResults:null}}null!==e.markdownCriteria&&null!==e.patternMatchResults&&(c=b,c.markdownCriteria=e.markdownCriteria,c.patternMatchResults=e.patternMatchResults)}});return c}
33
- function V(a){let d=null;a.read(()=>{const c=p.$getSelection();if(p.$isRangeSelection(c)&&c.isCollapsed()){var b=c.anchor.getNode(),e=b.getParent(),f=n.$isListItemNode(e);d={anchorOffset:c.anchor.offset,hasParentNode:null!==e,isCodeBlock:k.$isCodeNode(b),isParentAListItemNode:f,isSelectionCollapsed:!0,isSimpleText:p.$isTextNode(b)&&b.isSimpleText(),nodeKey:b.getKey(),textContent:b.getTextContent()}}});return d}
34
- function W(a,d,c){var b=d.getFirstChild();if(p.$isTextNode(b))a:{H(a);b=D.length;var e=d.getTextContent(),f=0===e.length;let m=0;for(;!f;){f=!0;for(let t=m;t<b;t++){var g=D[t];if(null==a.textNodeWithOffset){b:{var h=d.getChildren();var l=h.length;for(--l;0<=l;l--)if(p.$isTextNode(h[l])){h=h[l];break b}h=null}if(null==h)break a;a.textNodeWithOffset={node:h,offset:h.getTextContent().length}}h=I(g,a,d);if(null!=h){a.markdownCriteria=g;a.patternMatchResults=h;N(a,d,c);H(a);g=d.getTextContent();if(0===
35
- g.length)break a;if(g!==e){e=g;m=t;f=!1;break}}}}}else for(d=d.getChildren(),b=d.length,e=0;e<b;e++)f=d[e],p.$isElementNode(f)&&W(a,f,c)}
36
- exports.$convertFromMarkdownString=function(a,d,c){if(a.length){var b=[];a=a.split("\n");var e=a.length;for(var f=0;f<e;f++)0<a[f].length?b.push(p.$createParagraphNode().append(p.$createTextNode(a[f]))):b.push(p.$createParagraphNode());b.length?(a=p.$getRoot(),a.clear(),a.append(...b),b=a):b=null}else b=null;if(null!=b){d=G(d,!1,null,null);b=p.$getRoot();a=!1;for(e=0;!a;){a=!0;var g=b.getChildren(),h=g.length;for(var l=e;l<h;l++){var m=g[l];if(p.$isElementNode(m)){f=d;var t=c;var r=m.getTextContent();
37
- if(p.$isParagraphNode(m)){var q=m.getFirstChild(),w=p.$isTextNode(q);if(!0===f.isWithinCodeBlock)null!=q&&w&&(f.textNodeWithOffset={node:q,offset:0},q=C,r=K(r,!0,!1,f.isAutoFormatting?q.regExForAutoFormatting:q.regEx),null!=r&&(f.patternMatchResults=r)),f.markdownCriteria=C,N(f,m,t);else if(m.getChildren().length)for(r=E.length,f.joinedText=m.getTextContent(),null!=q&&w||y(80),f.textNodeWithOffset={node:q,offset:0},q=0;q<r;q++){w=E[q];if(!1===w.requiresParagraphStart)break;const P=I(w,f,J(f).node.getParentOrThrow());
38
- if(null!=P){f.markdownCriteria=w;f.patternMatchResults=P;N(f,m,t);break}}}}H(d);if(b.getChildren().length!==h){e=l;a=!1;break}}}a=!1;for(e=0;!a;)for(a=!0,f=b.getChildren(),g=f.length,h=e;h<g;h++)l=f[h],p.$isElementNode(l)&&W(d,l,c),H(d)}};
39
- exports.registerMarkdownShortcuts=function(a,d){let c=null;return a.registerUpdateListener(({tags:b})=>{if(!1===b.has("historic")){b=V(a.getEditorState());if(null==b)var e=null;else a:{e=b;var f=c;if(null==e||null==f)e=null;else{var g=z.length;for(let h=0;h<g;h++){const l=z[h].triggerString,m=l.length,t=e.textContent.length,r=e.anchorOffset-m;if(!1===(!0===e.hasParentNode&&e.isSimpleText&&e.isSelectionCollapsed&&e.anchorOffset!==f.anchorOffset&&0<=r&&r+m<=t&&e.textContent.substr(r,m)===l&&e.textContent!==
40
- f.textContent)){e=null;break a}}e=U(a,e)}}null!=e&&T(a,e,d);c=b}else c=null})};
7
+ 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){const c={};for(const d of a)a=b(d),c[a]?c[a].push(d):c[a]=[d];return c}function I(a){a=G(a,b=>b.type);return{element:a.element,textFormat:a["text-format"],textMatch:a["text-match"]}}
8
+ function aa(a){const b=I(a),c=b.textFormat.filter(d=>1===d.format.length);return()=>{const d=[];var e=n.$getRoot().getChildren();for(const 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(const e of b)if(b=e.export(a,f=>J(f,c,d)),null!=b)return b;return n.$isElementNode(a)?J(a,c,d):null}
9
+ function J(a,b,c){const d=[];a=a.getChildren();a:for(const e of a)if(n.$isLineBreakNode(e))d.push("\n");else if(n.$isTextNode(e))d.push(K(e,e.getTextContent(),b));else{for(const f of c)if(a=f.export(e,k=>J(k,b,c),(k,h)=>K(k,h,b)),null!=a){d.push(a);continue a}n.$isElementNode(e)&&d.push(J(e,b,c))}return d.join("")}function K(a,b,c){const d=new Set;for(const f of c){c=f.format[0];const k=f.tag;if(L(a,c)&&!d.has(c)){d.add(c);var e=M(a,!0);L(e,c)||(b=k+b);e=M(a,!1);L(e,c)||(b+=k)}}return b}
10
+ function M(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}return null}function L(a,b){return n.$isTextNode(a)&&a.hasFormat(b)}const N=/^```(\w{1,10})?\s?$/;
11
+ function ca(a){const b=I(a),c=da(b.textFormat);return d=>{d=d.split("\n");const e=d.length,f=n.$getRoot();f.clear();for(let q=0;q<e;q++){var k=d[q];a:{var h=d,r=q;var u=f;var p=h[r].match(N);if(p)for(var t=r,m=h.length;++t<m;)if(h[t].match(N)){p=y.$createCodeNode(p[1]);h=n.$createTextNode(h.slice(r+1,t).join("\n"));p.append(h);u.append(p);u=[p,t];break a}u=[null,r]}const [l,g]=u;if(null!=l)q=g;else{p=f;m=b.element;u=c;t=b.textMatch;h=n.$createTextNode(k);r=n.$createParagraphNode();r.append(h);p.append(r);
12
+ for(const {regExp:w,replace:v}of m)if(p=k.match(w)){h.setTextContent(k.slice(p[0].length));v(r,[h],p,!0);break}O(h,u,t)}}f.selectEnd()}}
13
+ function O(a,b,c){const d=a.getTextContent();a:{var e=d.match(b.openTagsRegExp);if(null!=e)for(f of e)if(e=b.fullMatchRegExpByTag[f.replace(/^\s/,"")],null!=e&&(e=d.match(e),null!=e)){var f=e;break a}f=null}if(f){if(f[0]===d)var k=a;else{var h=f.index,r=h+f[0].length;0===h?[k,p]=a.splitText(r):[,k,p]=a.splitText(h,r)}k.setTextContent(f[2]);if(h=b.transformersByTag[f[1]])for(var u of h.format)k.hasFormat(u)||k.toggleFormat(u);k.hasFormat("code")||O(k,b,c);p&&O(p,b,c)}else a:for(b=a;b;){for(h of c)if(k=
14
+ b.getTextContent().match(h.importRegExp)){var p=k.index;u=p+k[0].length;0===p?[r,b]=b.splitText(u):[,r,b]=b.splitText(p,u);h.replace(r,k);continue a}break}}function da(a){const b={},c={},d=[];for(const e of a){({tag:a}=e);b[a]=e;const 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}}
15
+ function P(a,b,c){const d=c.length;for(;b>=d;b--){const e=b-d;if(Q(a,e,c,0,d)&&" "!==a[e+d])return e}return-1}function Q(a,b,c,d,e){for(let f=0;f<e;f++)if(a[b+f]!==c[d+f])return!1;return!0}
16
+ const R=a=>(b,c,d)=>{d=a(d);d.append(...c);b.replace(d);d.select(0,0)},S=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)},T=(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()&&
17
+ (e=h.getFirstChild(),E.$isListNode(e))){d.push(T(e,b,c+1));continue}e=" ".repeat(4*c);var k=a.getListType();k="number"===k?`${a.getStart()+f}. `:"check"===k?`- [${h.getChecked()?"x":" "}] `:"- ";d.push(e+k+b(h));f++}return d.join("\n")},U={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:R(a=>F.$createHeadingNode("h"+a[1].length)),type:"element"},V={export:(a,b)=>F.$isQuoteNode(a)?"> "+b(a):null,regExp:/^>\s/,
18
+ replace:R(()=>F.$createQuoteNode()),type:"element"},W={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:R(a=>y.$createCodeNode(a?a[1]:void 0)),type:"element"},X={export:(a,b)=>E.$isListNode(a)?T(a,b,0):null,regExp:/^(\s*)[-*+]\s/,replace:S("bullet"),type:"element"},ea={export:(a,b)=>E.$isListNode(a)?T(a,b,0):null,regExp:/^(\s*)(?:-\s)?\s?(\[(\s|x)?\])\s/i,replace:S("check"),type:"element"},
19
+ Y={export:(a,b)=>E.$isListNode(a)?T(a,b,0):null,regExp:/^(\s*)(\d{1,})\.\s/,replace:S("number"),type:"element"},fa={format:["code"],tag:"`",type:"text-format"},ha={format:["bold","italic"],tag:"***",type:"text-format"},ia={format:["bold","italic"],tag:"___",type:"text-format"},ja={format:["bold"],tag:"**",type:"text-format"},ka={format:["bold"],tag:"__",type:"text-format"},la={format:["strikethrough"],tag:"~~",type:"text-format"},ma={format:["italic"],tag:"*",type:"text-format"},na={format:["italic"],
20
+ tag:"_",type:"text-format"},oa={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"},pa=[U,V,W,X,Y],qa=[fa,ha,ia,ja,ka,ma,
21
+ na,la],ra=[oa],Z=[...pa,...qa,...ra];exports.$convertFromMarkdownString=function(a,b=Z){return ca(b)(a)};exports.$convertToMarkdownString=function(a=Z){return aa(a)()};exports.BOLD_ITALIC_STAR=ha;exports.BOLD_ITALIC_UNDERSCORE=ia;exports.BOLD_STAR=ja;exports.BOLD_UNDERSCORE=ka;exports.CHECK_LIST=ea;exports.CODE=W;exports.ELEMENT_TRANSFORMERS=pa;exports.HEADING=U;exports.INLINE_CODE=fa;exports.ITALIC_STAR=ma;exports.ITALIC_UNDERSCORE=na;exports.LINK=oa;exports.ORDERED_LIST=Y;exports.QUOTE=V;
22
+ exports.STRIKETHROUGH=la;exports.TEXT_FORMAT_TRANSFORMERS=qa;exports.TEXT_MATCH_TRANSFORMERS=ra;exports.TRANSFORMERS=Z;exports.UNORDERED_LIST=X;
23
+ exports.registerMarkdownShortcuts=function(a,b){const c=I(b),d=G(c.textFormat,({tag:f})=>f[f.length-1]),e=G(c.textMatch,({trigger:f})=>f);return a.registerUpdateListener(({tags:f,dirtyLeaves:k,editorState:h,prevEditorState:r})=>{if(!f.has("historic")){var u=h.read(n.$getSelection);f=r.read(n.$getSelection);if(n.$isRangeSelection(f)&&n.$isRangeSelection(u)&&u.isCollapsed()){r=u.anchor.key;var p=u.anchor.offset,t=h._nodeMap.get(r);n.$isTextNode(t)&&k.has(r)&&(1===p||p===f.anchor.offset+1)&&a.update(()=>
24
+ {if(!t.hasFormat("code")){var m=t.getParent();if(null!==m&&!y.$isCodeNode(m)){var q=u.anchor.offset;b:{var l=c.element,g=m.getParent();if(n.$isRootNode(g)&&m.getFirstChild()===t&&(g=t.getTextContent()," "===g[q-1]))for(const {regExp:H,replace:B}of l)if((l=g.match(H))&&l[0].length===q){g=t.getNextSiblings();const [z,x]=t.splitText(q);z.remove();g=x?[x,...g]:g;B(m,g,l,!1);m=!0;break b}m=!1}if(!m){b:{l=t.getTextContent();m=e[l[q-1]];if(null!=m){q<l.length&&(l=l.slice(0,q));for(v of m)if(m=l.match(v.regExp),
25
+ null!==m){l=m.index;g=l+m[0].length;var w=void 0;0===l?[w]=t.splitText(g):[,w]=t.splitText(l,g);w.selectNext();v.replace(w,m);var v=!0;break b}}v=!1}if(!v)b:{g=t.getTextContent();--q;const H=g[q];if(v=d[H])for(const B of v){var {tag:A}=B;m=A.length;const z=q-m+1;if(1<m&&!Q(g,z,A,0,m))continue;if(" "===g[z-1])continue;w=v=t;l=P(g,z,A);let x=w;for(;0>l&&(x=x.getPreviousSibling())&&!n.$isLineBreakNode(x);)n.$isTextNode(x)&&(l=x.getTextContent(),w=x,l=P(l,l.length,A));if(!(0>l||w===v&&l+m===z||(A=w.getTextContent(),
26
+ 0<l&&A[l-1]===H))){g=v.getTextContent();g=g.slice(0,z)+g.slice(q+1);v.setTextContent(g);g=w===v?g:A;w.setTextContent(g.slice(0,l)+g.slice(l+m));g=n.$createRangeSelection();n.$setSelection(g);q=q-m*(w===v?2:1)+1;g.anchor.set(w.__key,l,"text");g.focus.set(v.__key,q,"text");for(const C of B.format)g.hasFormat(C)||g.formatText(C);g.anchor.set(g.focus.key,g.focus.offset,g.focus.type);for(const C of B.format)g.hasFormat(C)&&g.toggleFormat(C);break b}}}}}}})}}})};
package/README.md CHANGED
@@ -1,11 +1,93 @@
1
1
  # `@lexical/markdown`
2
2
 
3
- This package contains markdown helpers and functionality for Lexical.
3
+ This package contains markdown helpers for Lexical: import, export and shortcuts.
4
4
 
5
- The package focuses on markdown conversion.
5
+ ## Import and export
6
+ ```js
7
+ import {
8
+ $convertFromMarkdownString,
9
+ $convertToMarkdownString,
10
+ TRANSFORMERS,
11
+ } from '@lexical/markdown';
6
12
 
7
- The package has 3 main functions:
13
+ editor.update(() => {
14
+ const markdown = $convertToMarkdownString(TRANSFORMERS);
15
+ ...
16
+ });
8
17
 
9
- 1. It imports a string and converts into Lexical and then converts markup within the imported nodes. See convertFromPlainTextUtils.js
10
- 2. It exports Lexical to a plain text with markup. See convertToPlainTextUtils.js
11
- 3. It autoformats newly typed text by converting the markdown + some trigger to the appropriate stylized text. See autoFormatUtils.js
18
+ editor.update(() => {
19
+ $convertFromMarkdownString(markdown, TRANSFORMERS);
20
+ });
21
+ ```
22
+
23
+ It can also be used for initializing editor's state from markdown string. Here's an example with react `<RichTextPlugin>`
24
+ ```jsx
25
+ <LexicalComposer>
26
+ <RichTextPlugin initialEditorState={() => {
27
+ $convertFromMarkdownString(markdown, TRANSFORMERS);
28
+ }} />
29
+ </LexicalComposer>
30
+ ```
31
+
32
+ ## Shortcuts
33
+ Can use `<LexicalMarkdownShortcutPlugin>` if using React
34
+ ```jsx
35
+ import { TRANSFORMERS } from '@lexical/markdown';
36
+ import LexicalMarkdownShortcutPlugin from '@lexical/react/LexicalMarkdownShortcutPlugin';
37
+
38
+ <LexicalComposer>
39
+ <LexicalMarkdownShortcutPlugin transformers={TRANSFORMERS} />
40
+ </LexicalComposer>
41
+ ```
42
+
43
+ Or `registerMarkdownShortcuts` to register it manually:
44
+ ```js
45
+ import {
46
+ registerMarkdownShortcuts,
47
+ TRANSFORMERS,
48
+ } from '@lexical/markdown';
49
+
50
+ const editor = createEditor(...);
51
+ registerMarkdownShortcuts(editor, TRANSFORMERS);
52
+ ```
53
+
54
+ ## Transformers
55
+ Markdown functionality relies on transformers configuration. It's an array of objects that define how certain text or nodes
56
+ are processed during import, export or while typing. `@lexical/markdown` package provides set of built-in transformers:
57
+ ```js
58
+ // Element transformers
59
+ UNORDERED_LIST
60
+ CODE
61
+ HEADING
62
+ ORDERED_LIST
63
+ QUOTE
64
+
65
+ // Text format transformers
66
+ BOLD_ITALIC_STAR
67
+ BOLD_ITALIC_UNDERSCORE
68
+ BOLD_STAR
69
+ BOLD_UNDERSCORE
70
+ INLINE_CODE
71
+ ITALIC_STAR
72
+ ITALIC_UNDERSCORE
73
+ STRIKETHROUGH
74
+
75
+ // Text match transformers
76
+ LINK
77
+ ```
78
+
79
+ And bundles of commonly used transformers:
80
+ - `TRANSFORMERS` - all built-in transformers
81
+ - `ELEMENT_TRANSFORMERS` - all built-in element transformers
82
+ - `TEXT_FORMAT_TRANSFORMERS` - all built-in text format trasnformers
83
+ - `TEXT_MATCH_TRANSFORMERS` - all built-in text match trasnformers
84
+
85
+ Transformers are explicitly passed to markdown API allowing application-specific subset of markdown or custom transformers.
86
+
87
+ There're three types of transformers:
88
+
89
+ - **Element transformer** handles top level elements (lists, headings, quotes, tables or code blocks)
90
+ - **Text format transformer** applies text range formats defined in `TextFormatType` (bold, italic, underline, strikethrough, code, subscript and superscript)
91
+ - **Text match transformer** relies on matching leaf text node content
92
+
93
+ See `MarkdownTransformers.js` for transformer implementation examples
package/package.json CHANGED
@@ -8,18 +8,18 @@
8
8
  "markdown"
9
9
  ],
10
10
  "license": "MIT",
11
- "version": "0.2.3",
11
+ "version": "0.2.6",
12
12
  "main": "LexicalMarkdown.js",
13
13
  "peerDependencies": {
14
- "lexical": "0.2.3"
14
+ "lexical": "0.2.6"
15
15
  },
16
16
  "dependencies": {
17
- "@lexical/utils": "0.2.3",
18
- "@lexical/code": "0.2.3",
19
- "@lexical/text": "0.2.3",
20
- "@lexical/rich-text": "0.2.3",
21
- "@lexical/list": "0.2.3",
22
- "@lexical/link": "0.2.3"
17
+ "@lexical/utils": "0.2.6",
18
+ "@lexical/code": "0.2.6",
19
+ "@lexical/text": "0.2.6",
20
+ "@lexical/rich-text": "0.2.6",
21
+ "@lexical/list": "0.2.6",
22
+ "@lexical/link": "0.2.6"
23
23
  },
24
24
  "repository": {
25
25
  "type": "git",