@ekz/lexical-markdown 0.40.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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ 'use strict'
10
+ const EkzLexicalMarkdown = process.env.NODE_ENV !== 'production' ? require('./EkzLexicalMarkdown.dev.js') : require('./EkzLexicalMarkdown.prod.js');
11
+ module.exports = EkzLexicalMarkdown;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import * as modDev from './EkzLexicalMarkdown.dev.mjs';
10
+ import * as modProd from './EkzLexicalMarkdown.prod.mjs';
11
+ const mod = process.env.NODE_ENV !== 'production' ? modDev : modProd;
12
+ export const $convertFromMarkdownString = mod.$convertFromMarkdownString;
13
+ export const $convertToMarkdownString = mod.$convertToMarkdownString;
14
+ export const BOLD_ITALIC_STAR = mod.BOLD_ITALIC_STAR;
15
+ export const BOLD_ITALIC_UNDERSCORE = mod.BOLD_ITALIC_UNDERSCORE;
16
+ export const BOLD_STAR = mod.BOLD_STAR;
17
+ export const BOLD_UNDERSCORE = mod.BOLD_UNDERSCORE;
18
+ export const CHECK_LIST = mod.CHECK_LIST;
19
+ export const CODE = mod.CODE;
20
+ export const ELEMENT_TRANSFORMERS = mod.ELEMENT_TRANSFORMERS;
21
+ export const HEADING = mod.HEADING;
22
+ export const HIGHLIGHT = mod.HIGHLIGHT;
23
+ export const INLINE_CODE = mod.INLINE_CODE;
24
+ export const ITALIC_STAR = mod.ITALIC_STAR;
25
+ export const ITALIC_UNDERSCORE = mod.ITALIC_UNDERSCORE;
26
+ export const LINK = mod.LINK;
27
+ export const MULTILINE_ELEMENT_TRANSFORMERS = mod.MULTILINE_ELEMENT_TRANSFORMERS;
28
+ export const ORDERED_LIST = mod.ORDERED_LIST;
29
+ export const QUOTE = mod.QUOTE;
30
+ export const STRIKETHROUGH = mod.STRIKETHROUGH;
31
+ export const TEXT_FORMAT_TRANSFORMERS = mod.TEXT_FORMAT_TRANSFORMERS;
32
+ export const TEXT_MATCH_TRANSFORMERS = mod.TEXT_MATCH_TRANSFORMERS;
33
+ export const TRANSFORMERS = mod.TRANSFORMERS;
34
+ export const UNORDERED_LIST = mod.UNORDERED_LIST;
35
+ export const registerMarkdownShortcuts = mod.registerMarkdownShortcuts;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ const mod = await (process.env.NODE_ENV !== 'production' ? import('./EkzLexicalMarkdown.dev.mjs') : import('./EkzLexicalMarkdown.prod.mjs'));
10
+ export const $convertFromMarkdownString = mod.$convertFromMarkdownString;
11
+ export const $convertToMarkdownString = mod.$convertToMarkdownString;
12
+ export const BOLD_ITALIC_STAR = mod.BOLD_ITALIC_STAR;
13
+ export const BOLD_ITALIC_UNDERSCORE = mod.BOLD_ITALIC_UNDERSCORE;
14
+ export const BOLD_STAR = mod.BOLD_STAR;
15
+ export const BOLD_UNDERSCORE = mod.BOLD_UNDERSCORE;
16
+ export const CHECK_LIST = mod.CHECK_LIST;
17
+ export const CODE = mod.CODE;
18
+ export const ELEMENT_TRANSFORMERS = mod.ELEMENT_TRANSFORMERS;
19
+ export const HEADING = mod.HEADING;
20
+ export const HIGHLIGHT = mod.HIGHLIGHT;
21
+ export const INLINE_CODE = mod.INLINE_CODE;
22
+ export const ITALIC_STAR = mod.ITALIC_STAR;
23
+ export const ITALIC_UNDERSCORE = mod.ITALIC_UNDERSCORE;
24
+ export const LINK = mod.LINK;
25
+ export const MULTILINE_ELEMENT_TRANSFORMERS = mod.MULTILINE_ELEMENT_TRANSFORMERS;
26
+ export const ORDERED_LIST = mod.ORDERED_LIST;
27
+ export const QUOTE = mod.QUOTE;
28
+ export const STRIKETHROUGH = mod.STRIKETHROUGH;
29
+ export const TEXT_FORMAT_TRANSFORMERS = mod.TEXT_FORMAT_TRANSFORMERS;
30
+ export const TEXT_MATCH_TRANSFORMERS = mod.TEXT_MATCH_TRANSFORMERS;
31
+ export const TRANSFORMERS = mod.TRANSFORMERS;
32
+ export const UNORDERED_LIST = mod.UNORDERED_LIST;
33
+ export const registerMarkdownShortcuts = mod.registerMarkdownShortcuts;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ "use strict";var e=require("@ekz/lexical"),t=require("@ekz/lexical-list"),n=require("@ekz/lexical-rich-text"),o=require("@ekz/lexical-utils"),r=require("@ekz/lexical-code"),s=require("@ekz/lexical-link");function i(e,t){const n={};for(const o of e){const e=t(o);e&&(n[e]?n[e].push(o):n[e]=[o])}return n}function c(e){const t=i(e,e=>e.type);return{element:t.element||[],multilineElement:t["multiline-element"]||[],textFormat:t["text-format"]||[],textMatch:t["text-match"]||[]}}const l=/[!-/:-@[-`{-~\s]/,a=/[ \t\n\r\f]/,f=/[!"#$%&'()*+,\-./:;<=>?@[\]^_`{|}~]/,d=/^\s{0,3}$/;function g(t){if(!e.$isParagraphNode(t))return!1;const n=t.getFirstChild();return null==n||1===t.getChildrenSize()&&e.$isTextNode(n)&&d.test(n.getTextContent())}function u(t,n,o,r){for(const e of n){if(!e.export)continue;const n=e.export(t,e=>p(e,o,r));if(null!=n)return n}return e.$isElementNode(t)?p(t,o,r):e.$isDecoratorNode(t)?t.getTextContent():null}function p(t,n,o,r,s){const i=[],c=t.getChildren();r||(r=[]),s||(s=[]);e:for(const t of c){for(const e of o){if(!e.export)continue;const c=e.export(t,e=>p(e,n,o,r,[...s,...r]),(e,t)=>x(e,t,n,r,s));if(null!=c){i.push(c);continue e}}e.$isLineBreakNode(t)?i.push("\n"):e.$isTextNode(t)?i.push(x(t,t.getTextContent(),n,r,s)):e.$isElementNode(t)?i.push(p(t,n,o,r,s)):e.$isDecoratorNode(t)&&i.push(t.getTextContent())}return i.join("")}function x(e,t,n,o,r){let s=0===e.getFormat()?t:function(e){return e.replace(/^\s+|\s+$/g,e=>[...e].map(e=>"&#"+e.codePointAt(0)+";").join(""))}(t);e.hasFormat("code")||(s=s.replace(/([*_`~\\])/g,"\\$1"));let i="",c="",l="";const a=h(e,!0),f=h(e,!1),d=new Set;for(const t of n){const n=t.format[0],r=t.tag;m(e,n)&&!d.has(n)&&(d.add(n),m(a,n)&&o.find(e=>e.tag===r)||(o.push({format:n,tag:r}),i+=r))}for(let t=0;t<o.length;t++){const n=m(e,o[t].format),s=m(f,o[t].format);if(n&&s)continue;const i=[...o];for(;i.length>t;){const e=i.pop();r&&e&&r.find(t=>t.tag===e.tag)||(e&&"string"==typeof e.tag&&(n?s||(l+=e.tag):c+=e.tag),o.pop())}break}return s=i+s+l,c+s}function h(t,n){const o=n?t.getPreviousSibling():t.getNextSibling();return e.$isTextNode(o)?o:null}function m(t,n){return e.$isTextNode(t)&&t.hasFormat(n)}function $(e,t){const n=e.getTextContent(),o=t.fullMatchRegExpByTag["`"],r=t.transformersByTag["`"],s=[];let i=null;if(o&&r){const e=new RegExp(o.source,"g"),t=Array.from(n.matchAll(e));for(const e of t){const t=e.index,n=t+e[0].length;i||(i={content:e[2],endIndex:n,startIndex:t,tag:"`"}),s.push({end:n,start:t})}}const c=function(e,t,n=[]){const o=[],r=new Set(Object.keys(t.transformersByTag).filter(e=>"`"!==e[0]).map(e=>e[0])),s=t=>{let n=0;for(let o=t-1;o>=0&&"\\"===e[o];o--)n++;return n%2==1},i=e=>n.some(t=>e>=t.start&&e<t.end);let c=0;for(;c<e.length;){const t=e[c];if(!r.has(t)||s(c)||i(c)){c++;continue}let n=1;for(;c+n<e.length&&e[c+n]===t;)n++;const l=N(t,e,c,n,!0),a=N(t,e,c,n,!1);(l||a)&&o.push({active:!0,canClose:a,canOpen:l,char:t,index:c,length:n,originalLength:n}),c+=n}return o}(n,t,s),l=c.length>0?function(e,t,n){const o={};let r=0,s=null;for(;r<t.length;){const i=t[r];if(!i.active||!i.canClose||0===i.length){r++;continue}const c=`${i.char}${i.canOpen}`,l=o[c]??-1;let a=!1;for(let o=r-1;o>l;o--){const c=t[o];if(!c.active||!c.canOpen||0===c.length||c.char!==i.char)continue;if(c.canClose||i.canOpen){if((c.originalLength+i.originalLength)%3==0&&c.originalLength%3!=0&&i.originalLength%3!=0)continue}const l=Math.min(c.length,i.length),f=Object.keys(n.transformersByTag).filter(e=>e[0]===c.char&&e.length<=l).sort((e,t)=>t.length-e.length)[0];if(!f)continue;a=!0;const d=f.length,g={content:e.slice(c.index+c.length,i.index),endIndex:i.index+d,startIndex:c.index+(c.length-d),tag:f};(!s||g.startIndex<s.startIndex||g.startIndex===s.startIndex&&g.endIndex>s.endIndex)&&(s=g);for(let e=o+1;e<r;e++)t[e].active=!1;c.length-=d,i.length-=d,c.active=c.length>0,i.length>0?i.index+=d:(i.active=!1,r++);break}a||(o[c]=r-1,i.canOpen||(i.active=!1),r++)}return s}(n,c,t):null;let a=null,f=null;if(i&&l?l.startIndex<=i.startIndex&&l.endIndex>=i.endIndex?(a=l,f=t.transformersByTag[l.tag]):(a=i,f=r):i?(a=i,f=r):l&&(a=l,f=t.transformersByTag[l.tag]),!a||!f)return null;const d=[n.slice(a.startIndex,a.endIndex),a.tag,a.content];return d.index=a.startIndex,d.input=n,{endIndex:a.endIndex,match:d,startIndex:a.startIndex,transformer:f}}function N(e,t,n,o,r){if(!T(t,n,o,r))return!1;if("*"===e)return!0;if("_"===e){if(!T(t,n,o,!r))return!0;const e=r?t[n-1]:t[n+o];return void 0!==e&&f.test(e)}return!0}function T(e,t,n,o){const r=e[t-1],s=e[t+n],[i,c]=o?[s,r]:[r,s];return void 0!==i&&!a.test(i)&&(!f.test(i)||(void 0===c||a.test(c)||f.test(c)))}function E(t){return e.$isTextNode(t)&&!t.hasFormat("code")}function S(e,t,n){let o=$(e,t),r=function(e,t){const n=e;let o,r,s,i;for(const e of t){if(!e.replace||!e.importRegExp)continue;const t=n.getTextContent().match(e.importRegExp);if(!t)continue;const c=t.index||0,l=e.getEndIndex?e.getEndIndex(n,t):c+t[0].length;!1!==l&&(void 0===o||void 0===r||c<o&&(l>r||l<=o))&&(o=c,r=l,s=e,i=t)}return void 0===o||void 0===r||void 0===s||void 0===i?null:{endIndex:r,match:i,startIndex:o,transformer:s}}(e,n);if(o&&r&&(o.startIndex<=r.startIndex&&o.endIndex>=r.endIndex||r.startIndex>o.endIndex?r=null:o=null),o){const r=function(e,t,n,o,r){const s=e.getTextContent();let i,c,l;if(r[0]===s?i=e:0===t?[i,c]=e.splitText(n):[l,i,c]=e.splitText(t,n),i.setTextContent(r[2]),o)for(const e of o.format)i.hasFormat(e)||i.toggleFormat(e);return{nodeAfter:c,nodeBefore:l,transformedNode:i}}(e,o.startIndex,o.endIndex,o.transformer,o.match);E(r.nodeAfter)&&S(r.nodeAfter,t,n),E(r.nodeBefore)&&S(r.nodeBefore,t,n),E(r.transformedNode)&&S(r.transformedNode,t,n)}else if(r){const o=function(e,t,n,o,r){let s,i,c;return 0===t?[s,i]=e.splitText(n):[c,s,i]=e.splitText(t,n),o.replace?{nodeAfter:i,nodeBefore:c,transformedNode:o.replace(s,r)||void 0}:null}(e,r.startIndex,r.endIndex,r.transformer,r.match);if(!o)return;E(o.nodeAfter)&&S(o.nodeAfter,t,n),E(o.nodeBefore)&&S(o.nodeBefore,t,n),E(o.transformedNode)&&S(o.transformedNode,t,n)}const s=e.getTextContent().replace(/\\([*_`~\\])/g,"$1").replace(/&#(\d+);/g,(e,t)=>String.fromCodePoint(t));e.setTextContent(s)}function I(t,n=!1){const o=c(t),r=function(e){const t={},n={},o=[],r="(?<![\\\\])";for(const r of e){const{tag:e}=r;t[e]=r;const s=e.replace(/(\*|\^|\+)/g,"\\$1");o.push(s),1===e.length?n[e]="`"===e?new RegExp("(?<![\\\\`])(`)((?:\\\\`|[^`])+?)(`)(?!`)"):new RegExp(`(?<![\\\\${s}])(${s})((\\\\${s})?.*?[^${s}\\s](\\\\${s})?)((?<!\\\\)|(?<=\\\\\\\\))(${s})(?![\\\\${s}])`):n[e]=new RegExp(`(?<!\\\\)(${s})((\\\\${s})?.*?[^\\s](\\\\${s})?)((?<!\\\\)|(?<=\\\\\\\\))(${s})(?!\\\\)`)}return{fullMatchRegExpByTag:n,openTagsRegExp:new RegExp(`${r}(${o.join("|")})`,"g"),transformersByTag:t}}(o.textFormat);return(t,s)=>{const i=t.split("\n"),c=i.length,l=s||e.$getRoot();l.clear();for(let e=0;e<c;e++){const t=i[e],[s,c]=C(i,e,o.multilineElement,l);s?e=c:L(t,l,o.element,r,o.textMatch,n)}const a=l.getChildren();for(const e of a)!n&&g(e)&&l.getChildrenSize()>1&&e.remove();null!==e.$getSelection()&&l.selectStart()}}function C(e,t,n,o){for(const r of n){const{handleImportAfterStartMatch:n,regExpEnd:s,regExpStart:i,replace:c}=r,l=e[t].match(i);if(!l)continue;if(n){const s=n({lines:e,rootNode:o,startLineIndex:t,startMatch:l,transformer:r});if(null===s)continue;if(s)return s}const a="object"==typeof s&&"regExp"in s?s.regExp:s,f=s&&"object"==typeof s&&"optional"in s?s.optional:!s;let d=t;const g=e.length;for(;d<g;){const n=a?e[d].match(a):null;if(!n&&(!f||f&&d<g-1)){d++;continue}if(n&&t===d&&n.index===l.index){d++;continue}const r=[];if(n&&t===d)r.push(e[t].slice(l[0].length,-n[0].length));else for(let o=t;o<=d;o++)if(o===t){const t=e[o].slice(l[0].length);r.push(t)}else if(o===d&&n){const t=e[o].slice(0,-n[0].length);r.push(t)}else r.push(e[o]);if(!1!==c(o,null,l,n,r,!0))return[!0,d];break}}return[!1,t]}function L(r,s,i,c,l,a){const f=e.$createTextNode(r),d=e.$createParagraphNode();d.append(f),s.append(d);for(const{regExp:e,replace:t}of i){const n=r.match(e);if(n&&(f.setTextContent(r.slice(n[0].length)),!1!==t(d,[f],n,!0)))break}if(S(f,c,l),d.isAttached()&&r.length>0){const r=d.getPreviousSibling();if(!a&&(e.$isParagraphNode(r)||n.$isQuoteNode(r)||t.$isListNode(r))){let n=r;if(t.$isListNode(r)){const e=r.getLastDescendant();n=null==e?null:o.$findMatchingParent(e,t.$isListItemNode)}null!=n&&n.getTextContentSize()>0&&(n.splice(n.getChildrenSize(),0,[e.$createLineBreakNode(),...d.getChildren()]),d.remove())}}}function R(e,...t){const n=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",e);for(const e of t)o.append("v",e);throw n.search=o.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const v=/^(\s*)(\d{1,})\.\s/,y=/^(\s*)[-*+]\s/,_=/^(\s*)(?:[-*+]\s)?\s?(\[(\s|x)?\])\s/i,k=/^(#{1,6})\s/,O=/^>\s/,A=/^([ \t]*`{3,})([\w-]+)?[ \t]?/,b=/^[ \t]*`{3,}$/,M=/^[ \t]*```[^`]+(?:(?:`{1,2}|`{4,})[^`]+)*```(?:[^`]|$)/,F=/^(?:\|)(.+)(?:\|)\s?$/,w=/^(\| ?:?-*:? ?)+\|\s?$/,B=/^<[a-z_][\w-]*(?:\s[^<>]*)?\/?>/i,D=/^<\/[a-z_][\w-]*\s*>/i,P=e=>new RegExp(`(?:${e.source})$`,e.flags),z=e.createState("mdListMarker",{parse:e=>"string"==typeof e&&/^[-*+]$/.test(e)?e:"-"}),j=e.createState("mdCodeFence",{parse:e=>"string"==typeof e&&/^`{3,}$/.test(e)?e:"```"}),H=e=>(t,n,o,r)=>{const s=e(o);s.append(...n),t.replace(s),r||s.select(0,0)};const U=n=>(o,r,s,i)=>{const c=o.getPreviousSibling(),l=o.getNextSibling(),a=t.$createListItemNode("check"===n?"x"===s[3]:void 0),f=s[0].trim()[0],d="bullet"!==n&&"check"!==n||f!==z.parse(f)?void 0:f;if(t.$isListNode(l)&&l.getListType()===n){d&&e.$setState(l,z,d);const t=l.getFirstChild();null!==t?t.insertBefore(a):l.append(a),o.remove()}else if(t.$isListNode(c)&&c.getListType()===n)d&&e.$setState(c,z,d),c.append(a),o.remove();else{const r=t.$createListNode(n,"number"===n?Number(s[2]):void 0);d&&e.$setState(r,z,d),r.append(a),o.replace(r)}a.append(...r),i||a.select(0,0);const g=function(e){const t=e.match(/\t/g),n=e.match(/ /g);let o=0;return t&&(o+=t.length),n&&(o+=Math.floor(n.length/4)),o}(s[1]);g&&a.setIndent(g)},q=(n,o,r)=>{const s=[],i=n.getChildren();let c=0;for(const l of i)if(t.$isListItemNode(l)){if(1===l.getChildrenSize()){const e=l.getFirstChild();if(t.$isListNode(e)){s.push(q(e,o,r+1));continue}}const i=" ".repeat(4*r),a=n.getListType(),f=e.$getState(n,z),d="number"===a?`${n.getStart()+c}. `:"check"===a?`${f} [${l.getChecked()?"x":" "}] `:f+" ";s.push(i+d+o(l)),c++}return s.join("\n")},G={dependencies:[n.HeadingNode],export:(e,t)=>{if(!n.$isHeadingNode(e))return null;const o=Number(e.getTag().slice(1));return"#".repeat(o)+" "+t(e)},regExp:k,replace:H(e=>{const t="h"+e[1].length;return n.$createHeadingNode(t)}),type:"element"},Q={dependencies:[n.QuoteNode],export:(e,t)=>{if(!n.$isQuoteNode(e))return null;const o=t(e).split("\n"),r=[];for(const e of o)r.push("> "+e);return r.join("\n")},regExp:O,replace:(t,o,r,s)=>{if(s){const r=t.getPreviousSibling();if(n.$isQuoteNode(r))return r.splice(r.getChildrenSize(),0,[e.$createLineBreakNode(),...o]),void t.remove()}const i=n.$createQuoteNode();i.append(...o),t.replace(i),s||i.select(0,0)},type:"element"},W={dependencies:[r.CodeNode],export:t=>{if(!r.$isCodeNode(t))return null;const n=t.getTextContent();let o=e.$getState(t,j);if(n.indexOf(o)>-1){const e=n.match(/`{3,}/g);if(e){const t=Math.max(...e.map(e=>e.length));o="`".repeat(t+1)}}return o+(t.getLanguage()||"")+(n?"\n"+n:"")+"\n"+o},handleImportAfterStartMatch:({lines:e,rootNode:t,startLineIndex:n,startMatch:o})=>{const r=o[1],s=r.trim().length,i=e[n],c=o.index+r.length,l=i.slice(c),a=new RegExp(`\`{${s},}$`);if(a.test(l)){const e=l.match(a),r=l.slice(0,l.lastIndexOf(e[0])),s=[...o];return s[2]="",W.replace(t,null,s,e,[r],!0),[!0,n]}const f=new RegExp(`^[ \\t]*\`{${s},}$`);for(let r=n+1;r<e.length;r++){const s=e[r];if(f.test(s)){const c=s.match(f),l=e.slice(n+1,r),a=i.slice(o[0].length);return a.length>0&&l.unshift(a),W.replace(t,null,o,c,l,!0),[!0,r]}}const d=e.slice(n+1),g=i.slice(o[0].length);return g.length>0&&d.unshift(g),W.replace(t,null,o,null,d,!0),[!0,e.length-1]},regExpEnd:{optional:!0,regExp:b},regExpStart:A,replace:(t,n,o,s,i,c)=>{let l,a;const f=o[1]?o[1].trim():"```",d=o[2]||void 0;if(!n&&i){if(1===i.length)s?(l=r.$createCodeNode(d),a=i[0]):(l=r.$createCodeNode(d),a=i[0].startsWith(" ")?i[0].slice(1):i[0]);else{for(l=r.$createCodeNode(d),i.length>0&&(0===i[0].trim().length?i.shift():i[0].startsWith(" ")&&(i[0]=i[0].slice(1)));i.length>0&&!i[i.length-1].length;)i.pop();a=i.join("\n")}e.$setState(l,j,f);const n=e.$createTextNode(a);l.append(n),t.append(l)}else n&&H(e=>r.$createCodeNode(e?e[2]:void 0))(t,n,o,c)},type:"multiline-element"},K={dependencies:[t.ListNode,t.ListItemNode],export:(e,n)=>t.$isListNode(e)?q(e,n,0):null,regExp:y,replace:U("bullet"),type:"element"},X={dependencies:[t.ListNode,t.ListItemNode],export:(e,n)=>t.$isListNode(e)?q(e,n,0):null,regExp:_,replace:U("check"),type:"element"},J={dependencies:[t.ListNode,t.ListItemNode],export:(e,n)=>t.$isListNode(e)?q(e,n,0):null,regExp:v,replace:U("number"),type:"element"},V={format:["code"],tag:"`",type:"text-format"},Y={format:["highlight"],tag:"==",type:"text-format"},Z={format:["bold","italic"],tag:"***",type:"text-format"},ee={format:["bold","italic"],intraword:!1,tag:"___",type:"text-format"},te={format:["bold"],tag:"**",type:"text-format"},ne={format:["bold"],intraword:!1,tag:"__",type:"text-format"},oe={format:["strikethrough"],tag:"~~",type:"text-format"},re={format:["italic"],tag:"*",type:"text-format"},se={format:["italic"],intraword:!1,tag:"_",type:"text-format"},ie={dependencies:[s.LinkNode],export:(e,t,n)=>{if(!s.$isLinkNode(e)||s.$isAutoLinkNode(e))return null;const o=e.getTitle(),r=t(e);return o?`[${r}](${e.getURL()} "${o}")`:`[${r}](${e.getURL()})`},importRegExp:/(?:\[(.+?)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))/,regExp:/(?:\[(.+?)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))$/,replace:(t,n)=>{const[,o,r,i]=n,c=s.$createLinkNode(r,{title:i}),l=o.split("[").length-1,a=o.split("]").length-1;let f=o,d="";if(l<a)return;if(l>a){const e=o.split("[");d="["+e[0],f=e.slice(1).join("[")}const g=e.$createTextNode(f);return g.setFormat(t.getFormat()),c.append(g),t.replace(c),d&&c.insertBefore(e.$createTextNode(d)),g},trigger:")",type:"text-match"},ce=[G,Q,K,J],le=[W],ae=[V,Z,ee,te,ne,Y,re,se,oe],fe=[ie],de=[...ce,...le,...ae,...fe];function ge(e,t,n){const o=n.length;for(let r=t;r>=o;r--){const t=r-o;if(ue(e,t,n,0,o)&&" "!==e[t+o])return t}return-1}function ue(e,t,n,o,r){for(let s=0;s<r;s++)if(e[t+s]!==n[o+s])return!1;return!0}exports.$convertFromMarkdownString=function(e,t=de,n,o=!1,r=!1){const s=o?e:function(e,t=!1){const n=e.split("\n");let o=!1;const r=[];for(let e=0;e<n.length;e++){const s=n[e].trimEnd(),i=r[r.length-1];M.test(s)?r.push(s):A.test(s)||b.test(s)?(o=!o,r.push(s)):o||""===s||""===i||!i||k.test(i)||k.test(s)||O.test(s)||v.test(s)||y.test(s)||_.test(s)||F.test(s)||w.test(s)||!t||B.test(s)||D.test(s)||P(D).test(i)||P(B).test(i)||b.test(i)?r.push(s):r[r.length-1]=i+" "+s.trimStart()}return r.join("\n")}(e,r);return I(t,o)(s,n)},exports.$convertToMarkdownString=function(t=de,n,o=!1){return function(t,n=!1){const o=c(t),r=[...o.multilineElement,...o.element],s=!n,i=o.textFormat.filter(e=>1===e.format.length).sort((e,t)=>Number(e.format.includes("code"))-Number(t.format.includes("code")));return t=>{const n=[],c=(t||e.$getRoot()).getChildren();for(let e=0;e<c.length;e++){const t=c[e],l=u(t,r,i,o.textMatch);null!=l&&n.push(s&&e>0&&!g(t)&&!g(c[e-1])?"\n".concat(l):l)}return n.join("\n")}}(t,o)(n)},exports.BOLD_ITALIC_STAR=Z,exports.BOLD_ITALIC_UNDERSCORE=ee,exports.BOLD_STAR=te,exports.BOLD_UNDERSCORE=ne,exports.CHECK_LIST=X,exports.CODE=W,exports.ELEMENT_TRANSFORMERS=ce,exports.HEADING=G,exports.HIGHLIGHT=Y,exports.INLINE_CODE=V,exports.ITALIC_STAR=re,exports.ITALIC_UNDERSCORE=se,exports.LINK=ie,exports.MULTILINE_ELEMENT_TRANSFORMERS=le,exports.ORDERED_LIST=J,exports.QUOTE=Q,exports.STRIKETHROUGH=oe,exports.TEXT_FORMAT_TRANSFORMERS=ae,exports.TEXT_MATCH_TRANSFORMERS=fe,exports.TRANSFORMERS=de,exports.UNORDERED_LIST=K,exports.registerMarkdownShortcuts=function(t,n=de){const o=c(n),s=i(o.textFormat,({tag:e})=>e[e.length-1]),a=i(o.textMatch,({trigger:e})=>e);for(const e of n){const n=e.type;if("element"===n||"text-match"===n||"multiline-element"===n){const n=e.dependencies;for(const e of n)t.hasNode(e)||R(173,e.getType())}}const f=(t,n,r)=>{(function(t,n,o,r){const s=t.getParent();if(!e.$isRootOrShadowRoot(s)||t.getFirstChild()!==n)return!1;const i=n.getTextContent();if(" "!==i[o-1])return!1;for(const{regExp:e,replace:s}of r){const r=i.match(e);if(r&&r[0].length===(r[0].endsWith(" ")?o:o-1)){const e=n.getNextSiblings(),[i,c]=n.splitText(o);if(!1!==s(t,c?[c,...e]:e,r,!1))return i.remove(),!0}}return!1})(t,n,r,o.element)||function(t,n,o,r){const s=t.getParent();if(!e.$isRootOrShadowRoot(s)||t.getFirstChild()!==n)return!1;const i=n.getTextContent();if(" "!==i[o-1])return!1;for(const{regExpStart:e,replace:s,regExpEnd:c}of r){if(c&&!("optional"in c)||c&&"optional"in c&&!c.optional)continue;const r=i.match(e);if(r&&r[0].length===(r[0].endsWith(" ")?o:o-1)){const e=n.getNextSiblings(),[i,c]=n.splitText(o);if(!1!==s(t,c?[c,...e]:e,r,null,null,!1))return i.remove(),!0}}return!1}(t,n,r,o.multilineElement)||function(e,t,n){let o=e.getTextContent();const r=n[o[t-1]];if(null==r)return!1;t<o.length&&(o=o.slice(0,t));for(const t of r){if(!t.replace||!t.regExp)continue;const n=o.match(t.regExp);if(null===n)continue;const r=n.index||0,s=r+n[0].length;let i;return 0===r?[i]=e.splitText(s):[,i]=e.splitText(r,s),i.selectNext(0,0),t.replace(i,n),!0}return!1}(n,r,a)||function(t,n,o){const r=t.getTextContent(),s=n-1,i=r[s],c=o[i];if(!c)return!1;for(const n of c){const{tag:o}=n,c=o.length,a=s-c+1;if(c>1&&!ue(r,a,o,0,c))continue;if(" "===r[a-1])continue;const f=r[s+1];if(!1===n.intraword&&f&&!l.test(f))continue;const d=t;let g=d,u=ge(r,a,o),p=g;for(;u<0&&(p=p.getPreviousSibling())&&!e.$isLineBreakNode(p);)if(e.$isTextNode(p)){if(p.hasFormat("code"))continue;const e=p.getTextContent();g=p,u=ge(e,e.length,o)}if(u<0)continue;if(g===d&&u+c===a)continue;const x=g.getTextContent();if(u>0&&x[u-1]===i)continue;const h=x[u-1];if(!1===n.intraword&&h&&!l.test(h))continue;const m=d.getTextContent(),$=m.slice(0,a)+m.slice(s+1);d.setTextContent($);const N=g===d?$:x;g.setTextContent(N.slice(0,u)+N.slice(u+c));const T=e.$getSelection(),E=e.$createRangeSelection();e.$setSelection(E);const S=s-c*(g===d?2:1)+1;E.anchor.set(g.__key,u,"text"),E.focus.set(d.__key,S,"text");for(const e of n.format)E.hasFormat(e)||E.formatText(e);E.anchor.set(E.focus.key,E.focus.offset,E.focus.type);for(const e of n.format)E.hasFormat(e)&&E.toggleFormat(e);return e.$isRangeSelection(T)&&(E.format=T.format),!0}}(n,r,s)};return t.registerUpdateListener(({tags:n,dirtyLeaves:o,editorState:s,prevEditorState:i})=>{if(n.has(e.COLLABORATION_TAG)||n.has(e.HISTORIC_TAG))return;if(t.isComposing())return;const c=s.read(e.$getSelection),l=i.read(e.$getSelection);if(!e.$isRangeSelection(l)||!e.$isRangeSelection(c)||!c.isCollapsed()||c.is(l))return;const a=c.anchor.key,d=c.anchor.offset,g=s._nodeMap.get(a);!e.$isTextNode(g)||!o.has(a)||1!==d&&d>l.anchor.offset+1||t.update(()=>{if(!E(g))return;const e=g.getParent();null===e||r.$isCodeNode(e)||f(e,g,c.anchor.offset)})})};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import{$isParagraphNode as t,$isTextNode as e,$getRoot as n,$isElementNode as o,$isDecoratorNode as r,$isLineBreakNode as s,$getSelection as i,$createTextNode as l,$createParagraphNode as c,$createLineBreakNode as a,createState as f,$setState as g,$getState as u,COLLABORATION_TAG as p,HISTORIC_TAG as d,$isRangeSelection as h,$isRootOrShadowRoot as x,$createRangeSelection as m,$setSelection as T}from"@ekz/lexical";import{$isListNode as C,$isListItemNode as E,ListNode as y,ListItemNode as $,$createListItemNode as v,$createListNode as I}from"@ekz/lexical-list";import{$isQuoteNode as S,HeadingNode as b,QuoteNode as k,$createHeadingNode as w,$isHeadingNode as F,$createQuoteNode as L}from"@ekz/lexical-rich-text";import{$findMatchingParent as N}from"@ekz/lexical-utils";import{CodeNode as R,$createCodeNode as _,$isCodeNode as B}from"@ekz/lexical-code";import{LinkNode as M,$createLinkNode as z,$isLinkNode as j,$isAutoLinkNode as A}from"@ekz/lexical-link";function P(t,e){const n={};for(const o of t){const t=e(o);t&&(n[t]?n[t].push(o):n[t]=[o])}return n}function O(t){const e=P(t,t=>t.type);return{element:e.element||[],multilineElement:e["multiline-element"]||[],textFormat:e["text-format"]||[],textMatch:e["text-match"]||[]}}const U=/[!-/:-@[-`{-~\s]/,W=/[ \t\n\r\f]/,D=/[!"#$%&'()*+,\-./:;<=>?@[\]^_`{|}~]/,q=/^\s{0,3}$/;function G(n){if(!t(n))return!1;const o=n.getFirstChild();return null==o||1===n.getChildrenSize()&&e(o)&&q.test(o.getTextContent())}function H(t,e,n,s){for(const o of e){if(!o.export)continue;const e=o.export(t,t=>J(t,n,s));if(null!=e)return e}return o(t)?J(t,n,s):r(t)?t.getTextContent():null}function J(t,n,i,l,c){const a=[],f=t.getChildren();l||(l=[]),c||(c=[]);t:for(const t of f){for(const e of i){if(!e.export)continue;const o=e.export(t,t=>J(t,n,i,l,[...c,...l]),(t,e)=>K(t,e,n,l,c));if(null!=o){a.push(o);continue t}}s(t)?a.push("\n"):e(t)?a.push(K(t,t.getTextContent(),n,l,c)):o(t)?a.push(J(t,n,i,l,c)):r(t)&&a.push(t.getTextContent())}return a.join("")}function K(t,e,n,o,r){let s=0===t.getFormat()?e:function(t){return t.replace(/^\s+|\s+$/g,t=>[...t].map(t=>"&#"+t.codePointAt(0)+";").join(""))}(e);t.hasFormat("code")||(s=s.replace(/([*_`~\\])/g,"\\$1"));let i="",l="",c="";const a=Q(t,!0),f=Q(t,!1),g=new Set;for(const e of n){const n=e.format[0],r=e.tag;V(t,n)&&!g.has(n)&&(g.add(n),V(a,n)&&o.find(t=>t.tag===r)||(o.push({format:n,tag:r}),i+=r))}for(let e=0;e<o.length;e++){const n=V(t,o[e].format),s=V(f,o[e].format);if(n&&s)continue;const i=[...o];for(;i.length>e;){const t=i.pop();r&&t&&r.find(e=>e.tag===t.tag)||(t&&"string"==typeof t.tag&&(n?s||(c+=t.tag):l+=t.tag),o.pop())}break}return s=i+s+c,l+s}function Q(t,n){const o=n?t.getPreviousSibling():t.getNextSibling();return e(o)?o:null}function V(t,n){return e(t)&&t.hasFormat(n)}function X(t,e){const n=t.getTextContent(),o=e.fullMatchRegExpByTag["`"],r=e.transformersByTag["`"],s=[];let i=null;if(o&&r){const t=new RegExp(o.source,"g"),e=Array.from(n.matchAll(t));for(const t of e){const e=t.index,n=e+t[0].length;i||(i={content:t[2],endIndex:n,startIndex:e,tag:"`"}),s.push({end:n,start:e})}}const l=function(t,e,n=[]){const o=[],r=new Set(Object.keys(e.transformersByTag).filter(t=>"`"!==t[0]).map(t=>t[0])),s=e=>{let n=0;for(let o=e-1;o>=0&&"\\"===t[o];o--)n++;return n%2==1},i=t=>n.some(e=>t>=e.start&&t<e.end);let l=0;for(;l<t.length;){const e=t[l];if(!r.has(e)||s(l)||i(l)){l++;continue}let n=1;for(;l+n<t.length&&t[l+n]===e;)n++;const c=Y(e,t,l,n,!0),a=Y(e,t,l,n,!1);(c||a)&&o.push({active:!0,canClose:a,canOpen:c,char:e,index:l,length:n,originalLength:n}),l+=n}return o}(n,e,s),c=l.length>0?function(t,e,n){const o={};let r=0,s=null;for(;r<e.length;){const i=e[r];if(!i.active||!i.canClose||0===i.length){r++;continue}const l=`${i.char}${i.canOpen}`,c=o[l]??-1;let a=!1;for(let o=r-1;o>c;o--){const l=e[o];if(!l.active||!l.canOpen||0===l.length||l.char!==i.char)continue;if(l.canClose||i.canOpen){if((l.originalLength+i.originalLength)%3==0&&l.originalLength%3!=0&&i.originalLength%3!=0)continue}const c=Math.min(l.length,i.length),f=Object.keys(n.transformersByTag).filter(t=>t[0]===l.char&&t.length<=c).sort((t,e)=>e.length-t.length)[0];if(!f)continue;a=!0;const g=f.length,u={content:t.slice(l.index+l.length,i.index),endIndex:i.index+g,startIndex:l.index+(l.length-g),tag:f};(!s||u.startIndex<s.startIndex||u.startIndex===s.startIndex&&u.endIndex>s.endIndex)&&(s=u);for(let t=o+1;t<r;t++)e[t].active=!1;l.length-=g,i.length-=g,l.active=l.length>0,i.length>0?i.index+=g:(i.active=!1,r++);break}a||(o[l]=r-1,i.canOpen||(i.active=!1),r++)}return s}(n,l,e):null;let a=null,f=null;if(i&&c?c.startIndex<=i.startIndex&&c.endIndex>=i.endIndex?(a=c,f=e.transformersByTag[c.tag]):(a=i,f=r):i?(a=i,f=r):c&&(a=c,f=e.transformersByTag[c.tag]),!a||!f)return null;const g=[n.slice(a.startIndex,a.endIndex),a.tag,a.content];return g.index=a.startIndex,g.input=n,{endIndex:a.endIndex,match:g,startIndex:a.startIndex,transformer:f}}function Y(t,e,n,o,r){if(!Z(e,n,o,r))return!1;if("*"===t)return!0;if("_"===t){if(!Z(e,n,o,!r))return!0;const t=r?e[n-1]:e[n+o];return void 0!==t&&D.test(t)}return!0}function Z(t,e,n,o){const r=t[e-1],s=t[e+n],[i,l]=o?[s,r]:[r,s];return void 0!==i&&!W.test(i)&&(!D.test(i)||(void 0===l||W.test(l)||D.test(l)))}function tt(t){return e(t)&&!t.hasFormat("code")}function et(t,e,n){let o=X(t,e),r=function(t,e){const n=t;let o,r,s,i;for(const t of e){if(!t.replace||!t.importRegExp)continue;const e=n.getTextContent().match(t.importRegExp);if(!e)continue;const l=e.index||0,c=t.getEndIndex?t.getEndIndex(n,e):l+e[0].length;!1!==c&&(void 0===o||void 0===r||l<o&&(c>r||c<=o))&&(o=l,r=c,s=t,i=e)}return void 0===o||void 0===r||void 0===s||void 0===i?null:{endIndex:r,match:i,startIndex:o,transformer:s}}(t,n);if(o&&r&&(o.startIndex<=r.startIndex&&o.endIndex>=r.endIndex||r.startIndex>o.endIndex?r=null:o=null),o){const r=function(t,e,n,o,r){const s=t.getTextContent();let i,l,c;if(r[0]===s?i=t:0===e?[i,l]=t.splitText(n):[c,i,l]=t.splitText(e,n),i.setTextContent(r[2]),o)for(const t of o.format)i.hasFormat(t)||i.toggleFormat(t);return{nodeAfter:l,nodeBefore:c,transformedNode:i}}(t,o.startIndex,o.endIndex,o.transformer,o.match);tt(r.nodeAfter)&&et(r.nodeAfter,e,n),tt(r.nodeBefore)&&et(r.nodeBefore,e,n),tt(r.transformedNode)&&et(r.transformedNode,e,n)}else if(r){const o=function(t,e,n,o,r){let s,i,l;return 0===e?[s,i]=t.splitText(n):[l,s,i]=t.splitText(e,n),o.replace?{nodeAfter:i,nodeBefore:l,transformedNode:o.replace(s,r)||void 0}:null}(t,r.startIndex,r.endIndex,r.transformer,r.match);if(!o)return;tt(o.nodeAfter)&&et(o.nodeAfter,e,n),tt(o.nodeBefore)&&et(o.nodeBefore,e,n),tt(o.transformedNode)&&et(o.transformedNode,e,n)}const s=t.getTextContent().replace(/\\([*_`~\\])/g,"$1").replace(/&#(\d+);/g,(t,e)=>String.fromCodePoint(e));t.setTextContent(s)}function nt(t,e=!1){const o=O(t),r=function(t){const e={},n={},o=[],r="(?<![\\\\])";for(const r of t){const{tag:t}=r;e[t]=r;const s=t.replace(/(\*|\^|\+)/g,"\\$1");o.push(s),1===t.length?n[t]="`"===t?new RegExp("(?<![\\\\`])(`)((?:\\\\`|[^`])+?)(`)(?!`)"):new RegExp(`(?<![\\\\${s}])(${s})((\\\\${s})?.*?[^${s}\\s](\\\\${s})?)((?<!\\\\)|(?<=\\\\\\\\))(${s})(?![\\\\${s}])`):n[t]=new RegExp(`(?<!\\\\)(${s})((\\\\${s})?.*?[^\\s](\\\\${s})?)((?<!\\\\)|(?<=\\\\\\\\))(${s})(?!\\\\)`)}return{fullMatchRegExpByTag:n,openTagsRegExp:new RegExp(`${r}(${o.join("|")})`,"g"),transformersByTag:e}}(o.textFormat);return(t,s)=>{const l=t.split("\n"),c=l.length,a=s||n();a.clear();for(let t=0;t<c;t++){const n=l[t],[s,i]=ot(l,t,o.multilineElement,a);s?t=i:rt(n,a,o.element,r,o.textMatch,e)}const f=a.getChildren();for(const t of f)!e&&G(t)&&a.getChildrenSize()>1&&t.remove();null!==i()&&a.selectStart()}}function ot(t,e,n,o){for(const r of n){const{handleImportAfterStartMatch:n,regExpEnd:s,regExpStart:i,replace:l}=r,c=t[e].match(i);if(!c)continue;if(n){const s=n({lines:t,rootNode:o,startLineIndex:e,startMatch:c,transformer:r});if(null===s)continue;if(s)return s}const a="object"==typeof s&&"regExp"in s?s.regExp:s,f=s&&"object"==typeof s&&"optional"in s?s.optional:!s;let g=e;const u=t.length;for(;g<u;){const n=a?t[g].match(a):null;if(!n&&(!f||f&&g<u-1)){g++;continue}if(n&&e===g&&n.index===c.index){g++;continue}const r=[];if(n&&e===g)r.push(t[e].slice(c[0].length,-n[0].length));else for(let o=e;o<=g;o++)if(o===e){const e=t[o].slice(c[0].length);r.push(e)}else if(o===g&&n){const e=t[o].slice(0,-n[0].length);r.push(e)}else r.push(t[o]);if(!1!==l(o,null,c,n,r,!0))return[!0,g];break}}return[!1,e]}function rt(e,n,o,r,s,i){const f=l(e),g=c();g.append(f),n.append(g);for(const{regExp:t,replace:n}of o){const o=e.match(t);if(o&&(f.setTextContent(e.slice(o[0].length)),!1!==n(g,[f],o,!0)))break}if(et(f,r,s),g.isAttached()&&e.length>0){const e=g.getPreviousSibling();if(!i&&(t(e)||S(e)||C(e))){let t=e;if(C(e)){const n=e.getLastDescendant();t=null==n?null:N(n,E)}null!=t&&t.getTextContentSize()>0&&(t.splice(t.getChildrenSize(),0,[a(),...g.getChildren()]),g.remove())}}}function st(t,...e){const n=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const t of e)o.append("v",t);throw n.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}const it=/^(\s*)(\d{1,})\.\s/,lt=/^(\s*)[-*+]\s/,ct=/^(\s*)(?:[-*+]\s)?\s?(\[(\s|x)?\])\s/i,at=/^(#{1,6})\s/,ft=/^>\s/,gt=/^([ \t]*`{3,})([\w-]+)?[ \t]?/,ut=/^[ \t]*`{3,}$/,pt=/^[ \t]*```[^`]+(?:(?:`{1,2}|`{4,})[^`]+)*```(?:[^`]|$)/,dt=/^(?:\|)(.+)(?:\|)\s?$/,ht=/^(\| ?:?-*:? ?)+\|\s?$/,xt=/^<[a-z_][\w-]*(?:\s[^<>]*)?\/?>/i,mt=/^<\/[a-z_][\w-]*\s*>/i,Tt=t=>new RegExp(`(?:${t.source})$`,t.flags),Ct=f("mdListMarker",{parse:t=>"string"==typeof t&&/^[-*+]$/.test(t)?t:"-"}),Et=f("mdCodeFence",{parse:t=>"string"==typeof t&&/^`{3,}$/.test(t)?t:"```"}),yt=t=>(e,n,o,r)=>{const s=t(o);s.append(...n),e.replace(s),r||s.select(0,0)};const $t=t=>(e,n,o,r)=>{const s=e.getPreviousSibling(),i=e.getNextSibling(),l=v("check"===t?"x"===o[3]:void 0),c=o[0].trim()[0],a="bullet"!==t&&"check"!==t||c!==Ct.parse(c)?void 0:c;if(C(i)&&i.getListType()===t){a&&g(i,Ct,a);const t=i.getFirstChild();null!==t?t.insertBefore(l):i.append(l),e.remove()}else if(C(s)&&s.getListType()===t)a&&g(s,Ct,a),s.append(l),e.remove();else{const n=I(t,"number"===t?Number(o[2]):void 0);a&&g(n,Ct,a),n.append(l),e.replace(n)}l.append(...n),r||l.select(0,0);const f=function(t){const e=t.match(/\t/g),n=t.match(/ /g);let o=0;return e&&(o+=e.length),n&&(o+=Math.floor(n.length/4)),o}(o[1]);f&&l.setIndent(f)},vt=(t,e,n)=>{const o=[],r=t.getChildren();let s=0;for(const i of r)if(E(i)){if(1===i.getChildrenSize()){const t=i.getFirstChild();if(C(t)){o.push(vt(t,e,n+1));continue}}const r=" ".repeat(4*n),l=t.getListType(),c=u(t,Ct),a="number"===l?`${t.getStart()+s}. `:"check"===l?`${c} [${i.getChecked()?"x":" "}] `:c+" ";o.push(r+a+e(i)),s++}return o.join("\n")},It={dependencies:[b],export:(t,e)=>{if(!F(t))return null;const n=Number(t.getTag().slice(1));return"#".repeat(n)+" "+e(t)},regExp:at,replace:yt(t=>{const e="h"+t[1].length;return w(e)}),type:"element"},St={dependencies:[k],export:(t,e)=>{if(!S(t))return null;const n=e(t).split("\n"),o=[];for(const t of n)o.push("> "+t);return o.join("\n")},regExp:ft,replace:(t,e,n,o)=>{if(o){const n=t.getPreviousSibling();if(S(n))return n.splice(n.getChildrenSize(),0,[a(),...e]),void t.remove()}const r=L();r.append(...e),t.replace(r),o||r.select(0,0)},type:"element"},bt={dependencies:[R],export:t=>{if(!B(t))return null;const e=t.getTextContent();let n=u(t,Et);if(e.indexOf(n)>-1){const t=e.match(/`{3,}/g);if(t){const e=Math.max(...t.map(t=>t.length));n="`".repeat(e+1)}}return n+(t.getLanguage()||"")+(e?"\n"+e:"")+"\n"+n},handleImportAfterStartMatch:({lines:t,rootNode:e,startLineIndex:n,startMatch:o})=>{const r=o[1],s=r.trim().length,i=t[n],l=o.index+r.length,c=i.slice(l),a=new RegExp(`\`{${s},}$`);if(a.test(c)){const t=c.match(a),r=c.slice(0,c.lastIndexOf(t[0])),s=[...o];return s[2]="",bt.replace(e,null,s,t,[r],!0),[!0,n]}const f=new RegExp(`^[ \\t]*\`{${s},}$`);for(let r=n+1;r<t.length;r++){const s=t[r];if(f.test(s)){const l=s.match(f),c=t.slice(n+1,r),a=i.slice(o[0].length);return a.length>0&&c.unshift(a),bt.replace(e,null,o,l,c,!0),[!0,r]}}const g=t.slice(n+1),u=i.slice(o[0].length);return u.length>0&&g.unshift(u),bt.replace(e,null,o,null,g,!0),[!0,t.length-1]},regExpEnd:{optional:!0,regExp:ut},regExpStart:gt,replace:(t,e,n,o,r,s)=>{let i,c;const a=n[1]?n[1].trim():"```",f=n[2]||void 0;if(!e&&r){if(1===r.length)o?(i=_(f),c=r[0]):(i=_(f),c=r[0].startsWith(" ")?r[0].slice(1):r[0]);else{for(i=_(f),r.length>0&&(0===r[0].trim().length?r.shift():r[0].startsWith(" ")&&(r[0]=r[0].slice(1)));r.length>0&&!r[r.length-1].length;)r.pop();c=r.join("\n")}g(i,Et,a);const e=l(c);i.append(e),t.append(i)}else e&&yt(t=>_(t?t[2]:void 0))(t,e,n,s)},type:"multiline-element"},kt={dependencies:[y,$],export:(t,e)=>C(t)?vt(t,e,0):null,regExp:lt,replace:$t("bullet"),type:"element"},wt={dependencies:[y,$],export:(t,e)=>C(t)?vt(t,e,0):null,regExp:ct,replace:$t("check"),type:"element"},Ft={dependencies:[y,$],export:(t,e)=>C(t)?vt(t,e,0):null,regExp:it,replace:$t("number"),type:"element"},Lt={format:["code"],tag:"`",type:"text-format"},Nt={format:["highlight"],tag:"==",type:"text-format"},Rt={format:["bold","italic"],tag:"***",type:"text-format"},_t={format:["bold","italic"],intraword:!1,tag:"___",type:"text-format"},Bt={format:["bold"],tag:"**",type:"text-format"},Mt={format:["bold"],intraword:!1,tag:"__",type:"text-format"},zt={format:["strikethrough"],tag:"~~",type:"text-format"},jt={format:["italic"],tag:"*",type:"text-format"},At={format:["italic"],intraword:!1,tag:"_",type:"text-format"},Pt={dependencies:[M],export:(t,e,n)=>{if(!j(t)||A(t))return null;const o=t.getTitle(),r=e(t);return o?`[${r}](${t.getURL()} "${o}")`:`[${r}](${t.getURL()})`},importRegExp:/(?:\[(.+?)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))/,regExp:/(?:\[(.+?)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))$/,replace:(t,e)=>{const[,n,o,r]=e,s=z(o,{title:r}),i=n.split("[").length-1,c=n.split("]").length-1;let a=n,f="";if(i<c)return;if(i>c){const t=n.split("[");f="["+t[0],a=t.slice(1).join("[")}const g=l(a);return g.setFormat(t.getFormat()),s.append(g),t.replace(s),f&&s.insertBefore(l(f)),g},trigger:")",type:"text-match"},Ot=[It,St,kt,Ft],Ut=[bt],Wt=[Lt,Rt,_t,Bt,Mt,Nt,jt,At,zt],Dt=[Pt],qt=[...Ot,...Ut,...Wt,...Dt];function Gt(t,e,n){const o=n.length;for(let r=e;r>=o;r--){const e=r-o;if(Ht(t,e,n,0,o)&&" "!==t[e+o])return e}return-1}function Ht(t,e,n,o,r){for(let s=0;s<r;s++)if(t[e+s]!==n[o+s])return!1;return!0}function Jt(t,n=qt){const o=O(n),r=P(o.textFormat,({tag:t})=>t[t.length-1]),l=P(o.textMatch,({trigger:t})=>t);for(const e of n){const n=e.type;if("element"===n||"text-match"===n||"multiline-element"===n){const n=e.dependencies;for(const e of n)t.hasNode(e)||st(173,e.getType())}}const c=(t,n,c)=>{(function(t,e,n,o){const r=t.getParent();if(!x(r)||t.getFirstChild()!==e)return!1;const s=e.getTextContent();if(" "!==s[n-1])return!1;for(const{regExp:r,replace:i}of o){const o=s.match(r);if(o&&o[0].length===(o[0].endsWith(" ")?n:n-1)){const r=e.getNextSiblings(),[s,l]=e.splitText(n);if(!1!==i(t,l?[l,...r]:r,o,!1))return s.remove(),!0}}return!1})(t,n,c,o.element)||function(t,e,n,o){const r=t.getParent();if(!x(r)||t.getFirstChild()!==e)return!1;const s=e.getTextContent();if(" "!==s[n-1])return!1;for(const{regExpStart:r,replace:i,regExpEnd:l}of o){if(l&&!("optional"in l)||l&&"optional"in l&&!l.optional)continue;const o=s.match(r);if(o&&o[0].length===(o[0].endsWith(" ")?n:n-1)){const r=e.getNextSiblings(),[s,l]=e.splitText(n);if(!1!==i(t,l?[l,...r]:r,o,null,null,!1))return s.remove(),!0}}return!1}(t,n,c,o.multilineElement)||function(t,e,n){let o=t.getTextContent();const r=n[o[e-1]];if(null==r)return!1;e<o.length&&(o=o.slice(0,e));for(const e of r){if(!e.replace||!e.regExp)continue;const n=o.match(e.regExp);if(null===n)continue;const r=n.index||0,s=r+n[0].length;let i;return 0===r?[i]=t.splitText(s):[,i]=t.splitText(r,s),i.selectNext(0,0),e.replace(i,n),!0}return!1}(n,c,l)||function(t,n,o){const r=t.getTextContent(),l=n-1,c=r[l],a=o[c];if(!a)return!1;for(const n of a){const{tag:o}=n,a=o.length,f=l-a+1;if(a>1&&!Ht(r,f,o,0,a))continue;if(" "===r[f-1])continue;const g=r[l+1];if(!1===n.intraword&&g&&!U.test(g))continue;const u=t;let p=u,d=Gt(r,f,o),x=p;for(;d<0&&(x=x.getPreviousSibling())&&!s(x);)if(e(x)){if(x.hasFormat("code"))continue;const t=x.getTextContent();p=x,d=Gt(t,t.length,o)}if(d<0)continue;if(p===u&&d+a===f)continue;const C=p.getTextContent();if(d>0&&C[d-1]===c)continue;const E=C[d-1];if(!1===n.intraword&&E&&!U.test(E))continue;const y=u.getTextContent(),$=y.slice(0,f)+y.slice(l+1);u.setTextContent($);const v=p===u?$:C;p.setTextContent(v.slice(0,d)+v.slice(d+a));const I=i(),S=m();T(S);const b=l-a*(p===u?2:1)+1;S.anchor.set(p.__key,d,"text"),S.focus.set(u.__key,b,"text");for(const t of n.format)S.hasFormat(t)||S.formatText(t);S.anchor.set(S.focus.key,S.focus.offset,S.focus.type);for(const t of n.format)S.hasFormat(t)&&S.toggleFormat(t);return h(I)&&(S.format=I.format),!0}}(n,c,r)};return t.registerUpdateListener(({tags:n,dirtyLeaves:o,editorState:r,prevEditorState:s})=>{if(n.has(p)||n.has(d))return;if(t.isComposing())return;const l=r.read(i),a=s.read(i);if(!h(a)||!h(l)||!l.isCollapsed()||l.is(a))return;const f=l.anchor.key,g=l.anchor.offset,u=r._nodeMap.get(f);!e(u)||!o.has(f)||1!==g&&g>a.anchor.offset+1||t.update(()=>{if(!tt(u))return;const t=u.getParent();null===t||B(t)||c(t,u,l.anchor.offset)})})}function Kt(t,e=qt,n,o=!1,r=!1){const s=o?t:function(t,e=!1){const n=t.split("\n");let o=!1;const r=[];for(let t=0;t<n.length;t++){const s=n[t].trimEnd(),i=r[r.length-1];pt.test(s)?r.push(s):gt.test(s)||ut.test(s)?(o=!o,r.push(s)):o||""===s||""===i||!i||at.test(i)||at.test(s)||ft.test(s)||it.test(s)||lt.test(s)||ct.test(s)||dt.test(s)||ht.test(s)||!e||xt.test(s)||mt.test(s)||Tt(mt).test(i)||Tt(xt).test(i)||ut.test(i)?r.push(s):r[r.length-1]=i+" "+s.trimStart()}return r.join("\n")}(t,r);return nt(e,o)(s,n)}function Qt(t=qt,e,o=!1){const r=function(t,e=!1){const o=O(t),r=[...o.multilineElement,...o.element],s=!e,i=o.textFormat.filter(t=>1===t.format.length).sort((t,e)=>Number(t.format.includes("code"))-Number(e.format.includes("code")));return t=>{const e=[],l=(t||n()).getChildren();for(let t=0;t<l.length;t++){const n=l[t],c=H(n,r,i,o.textMatch);null!=c&&e.push(s&&t>0&&!G(n)&&!G(l[t-1])?"\n".concat(c):c)}return e.join("\n")}}(t,o);return r(e)}export{Kt as $convertFromMarkdownString,Qt as $convertToMarkdownString,Rt as BOLD_ITALIC_STAR,_t as BOLD_ITALIC_UNDERSCORE,Bt as BOLD_STAR,Mt as BOLD_UNDERSCORE,wt as CHECK_LIST,bt as CODE,Ot as ELEMENT_TRANSFORMERS,It as HEADING,Nt as HIGHLIGHT,Lt as INLINE_CODE,jt as ITALIC_STAR,At as ITALIC_UNDERSCORE,Pt as LINK,Ut as MULTILINE_ELEMENT_TRANSFORMERS,Ft as ORDERED_LIST,St as QUOTE,zt as STRIKETHROUGH,Wt as TEXT_FORMAT_TRANSFORMERS,Dt as TEXT_MATCH_TRANSFORMERS,qt as TRANSFORMERS,kt as UNORDERED_LIST,Jt as registerMarkdownShortcuts};
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Meta Platforms, Inc. and affiliates.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ */
9
+
10
+ import type {
11
+ LexicalEditor,
12
+ LexicalNode,
13
+ ElementNode,
14
+ TextFormatType,
15
+ TextNode,
16
+ } from '@ekz/lexical';
17
+
18
+ export type Transformer =
19
+ | ElementTransformer
20
+ | MultilineElementTransformer
21
+ | TextFormatTransformer
22
+ | TextMatchTransformer;
23
+
24
+ export type ElementTransformer = {
25
+ dependencies: Array<Class<LexicalNode>>,
26
+ export: (
27
+ node: LexicalNode,
28
+ traverseChildren: (node: ElementNode) => string,
29
+ ) => string | null,
30
+ regExp: RegExp,
31
+ replace: (
32
+ parentNode: ElementNode,
33
+ children: Array<LexicalNode>,
34
+ match: Array<string>,
35
+ isImport: boolean,
36
+ ) => boolean | void,
37
+ type: 'element',
38
+ };
39
+
40
+ export type MultilineElementTransformer = {
41
+ dependencies: Array<Class<LexicalNode>>;
42
+ export?: (
43
+ node: LexicalNode,
44
+ traverseChildren: (node: ElementNode) => string,
45
+ ) => string | null;
46
+ handleImportAfterStartMatch?: (args: {
47
+ lines: Array<string>;
48
+ rootNode: ElementNode;
49
+ startLineIndex: number;
50
+ startMatch: RegExp$matchResult;
51
+ transformer: MultilineElementTransformer;
52
+ }) => [boolean, number] | null | void;
53
+ regExpStart: RegExp;
54
+ regExpEnd?:
55
+ | RegExp
56
+ | {
57
+ optional?: true;
58
+ regExp: RegExp;
59
+ };
60
+ replace: (
61
+ rootNode: ElementNode,
62
+ children: Array<LexicalNode> | null,
63
+ startMatch: Array<string>,
64
+ endMatch: Array<string> | null,
65
+ linesInBetween: Array<string> | null,
66
+ isImport: boolean,
67
+ ) => boolean | void;
68
+ type: 'multiline-element';
69
+ };
70
+
71
+ export type TextFormatTransformer = $ReadOnly<{
72
+ format: $ReadOnlyArray<TextFormatType>,
73
+ tag: string,
74
+ intraword?: boolean,
75
+ type: 'text-format',
76
+ }>;
77
+
78
+ export type TextMatchTransformer = $ReadOnly<{
79
+ dependencies: Array<Class<LexicalNode>>,
80
+ export?: (
81
+ node: LexicalNode,
82
+ exportChildren: (node: ElementNode) => string,
83
+ exportFormat: (node: TextNode, textContent: string) => string,
84
+ ) => string | null,
85
+ getEndIndex?: (node: TextNode, match: RegExp$matchResult) => number | false;
86
+ importRegExp?: RegExp,
87
+ regExp: RegExp,
88
+ replace?: (node: TextNode, match: RegExp$matchResult) => void | TextNode,
89
+ trigger?: string,
90
+ type: 'text-match',
91
+ }>;
92
+
93
+ declare export function registerMarkdownShortcuts(
94
+ editor: LexicalEditor,
95
+ transformers?: Array<Transformer>,
96
+ ): () => void;
97
+
98
+ declare export function $convertFromMarkdownString(
99
+ markdown: string,
100
+ transformers?: Array<Transformer>,
101
+ node?: ElementNode,
102
+ shouldPreserveNewLines?: boolean,
103
+ shouldMergeAdjacentLines?: boolean,
104
+ ): void;
105
+
106
+ declare export function $convertToMarkdownString(
107
+ transformers?: Array<Transformer>,
108
+ node?: ElementNode,
109
+ shouldPreserveNewLines?: boolean,
110
+ ): string;
111
+
112
+ declare export var INLINE_CODE: TextFormatTransformer;
113
+ declare export var HIGHLIGHT: TextFormatTransformer;
114
+ declare export var BOLD_ITALIC_STAR: TextFormatTransformer;
115
+ declare export var BOLD_ITALIC_UNDERSCORE: TextFormatTransformer;
116
+ declare export var BOLD_STAR: TextFormatTransformer;
117
+ declare export var BOLD_UNDERSCORE: TextFormatTransformer;
118
+ declare export var STRIKETHROUGH: TextFormatTransformer;
119
+ declare export var ITALIC_STAR: TextFormatTransformer;
120
+ declare export var ITALIC_UNDERSCORE: TextFormatTransformer;
121
+
122
+ declare export var HEADING: ElementTransformer;
123
+ declare export var QUOTE: ElementTransformer;
124
+ declare export var CODE: MultilineElementTransformer;
125
+ declare export var UNORDERED_LIST: ElementTransformer;
126
+ declare export var CHECK_LIST: ElementTransformer;
127
+ declare export var ORDERED_LIST: ElementTransformer;
128
+
129
+ declare export var LINK: TextMatchTransformer;
130
+
131
+ declare export var TRANSFORMERS: Array<Transformer>;
132
+ declare export var ELEMENT_TRANSFORMERS: Array<ElementTransformer>;
133
+ declare export var MULTILINE_ELEMENT_TRANSFORMERS: Array<MultilineElementTransformer>;
134
+ declare export var TEXT_FORMAT_TRANSFORMERS: Array<TextFormatTransformer>;
135
+ declare export var TEXT_MATCH_TRANSFORMERS: Array<TextFormatTransformer>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { ElementNode } from '@ekz/lexical';
9
+ import { Transformer } from './MarkdownTransformers';
10
+ /**
11
+ * Renders string from markdown. The selection is moved to the start after the operation.
12
+ */
13
+ export declare function createMarkdownExport(transformers: Array<Transformer>, shouldPreserveNewLines?: boolean): (node?: ElementNode) => string;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { TextFormatTransformer, Transformer } from './MarkdownTransformers';
9
+ import { ElementNode } from '@ekz/lexical';
10
+ export type TextFormatTransformersIndex = Readonly<{
11
+ fullMatchRegExpByTag: Readonly<Record<string, RegExp>>;
12
+ openTagsRegExp: RegExp;
13
+ transformersByTag: Readonly<Record<string, TextFormatTransformer>>;
14
+ }>;
15
+ /**
16
+ * Renders markdown from a string. The selection is moved to the start after the operation.
17
+ */
18
+ export declare function createMarkdownImport(transformers: Array<Transformer>, shouldPreserveNewLines?: boolean): (markdownString: string, node?: ElementNode) => void;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { Transformer } from './MarkdownTransformers';
9
+ import type { LexicalEditor } from '@ekz/lexical';
10
+ export declare function registerMarkdownShortcuts(editor: LexicalEditor, transformers?: Array<Transformer>): () => void;
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import { ElementNode, Klass, LexicalNode, TextFormatType, TextNode } from '@ekz/lexical';
9
+ export type Transformer = ElementTransformer | MultilineElementTransformer | TextFormatTransformer | TextMatchTransformer;
10
+ export type ElementTransformer = {
11
+ dependencies: Array<Klass<LexicalNode>>;
12
+ /**
13
+ * `export` is called when the `$convertToMarkdownString` is called to convert the editor state into markdown.
14
+ *
15
+ * @return return null to cancel the export, even though the regex matched. Lexical will then search for the next transformer.
16
+ */
17
+ export: (node: LexicalNode, traverseChildren: (node: ElementNode) => string) => string | null;
18
+ regExp: RegExp;
19
+ /**
20
+ * `replace` is called when markdown is imported or typed in the editor
21
+ *
22
+ * @return return false to cancel the transform, even though the regex matched. Lexical will then search for the next transformer.
23
+ */
24
+ replace: (parentNode: ElementNode, children: Array<LexicalNode>, match: Array<string>,
25
+ /**
26
+ * Whether the match is from an import operation (e.g. through `$convertFromMarkdownString`) or not (e.g. through typing in the editor).
27
+ */
28
+ isImport: boolean) => boolean | void;
29
+ type: 'element';
30
+ };
31
+ export type MultilineElementTransformer = {
32
+ /**
33
+ * Use this function to manually handle the import process, once the `regExpStart` has matched successfully.
34
+ * Without providing this function, the default behavior is to match until `regExpEnd` is found, or until the end of the document if `regExpEnd.optional` is true.
35
+ *
36
+ * @returns a tuple or null. The first element of the returned tuple is a boolean indicating if a multiline element was imported. The second element is the index of the last line that was processed. If null is returned, the next multilineElementTransformer will be tried. If undefined is returned, the default behavior will be used.
37
+ */
38
+ handleImportAfterStartMatch?: (args: {
39
+ lines: Array<string>;
40
+ rootNode: ElementNode;
41
+ startLineIndex: number;
42
+ startMatch: RegExpMatchArray;
43
+ transformer: MultilineElementTransformer;
44
+ }) => [boolean, number] | null | undefined;
45
+ dependencies: Array<Klass<LexicalNode>>;
46
+ /**
47
+ * `export` is called when the `$convertToMarkdownString` is called to convert the editor state into markdown.
48
+ *
49
+ * @return return null to cancel the export, even though the regex matched. Lexical will then search for the next transformer.
50
+ */
51
+ export?: (node: LexicalNode, traverseChildren: (node: ElementNode) => string) => string | null;
52
+ /**
53
+ * This regex determines when to start matching
54
+ */
55
+ regExpStart: RegExp;
56
+ /**
57
+ * This regex determines when to stop matching. Anything in between regExpStart and regExpEnd will be matched
58
+ */
59
+ regExpEnd?: RegExp | {
60
+ /**
61
+ * Whether the end match is optional. If true, the end match is not required to match for the transformer to be triggered.
62
+ * The entire text from regexpStart to the end of the document will then be matched.
63
+ */
64
+ optional?: true;
65
+ regExp: RegExp;
66
+ };
67
+ /**
68
+ * `replace` is called only when markdown is imported in the editor, not when it's typed
69
+ *
70
+ * @return return false to cancel the transform, even though the regex matched. Lexical will then search for the next transformer.
71
+ */
72
+ replace: (rootNode: ElementNode,
73
+ /**
74
+ * During markdown shortcut transforms, children nodes may be provided to the transformer. If this is the case, no `linesInBetween` will be provided and
75
+ * the children nodes should be used instead of the `linesInBetween` to create the new node.
76
+ */
77
+ children: Array<LexicalNode> | null, startMatch: Array<string>, endMatch: Array<string> | null,
78
+ /**
79
+ * linesInBetween includes the text between the start & end matches, split up by lines, not including the matches themselves.
80
+ * This is null when the transformer is triggered through markdown shortcuts (by typing in the editor)
81
+ */
82
+ linesInBetween: Array<string> | null,
83
+ /**
84
+ * Whether the match is from an import operation (e.g. through `$convertFromMarkdownString`) or not (e.g. through typing in the editor).
85
+ */
86
+ isImport: boolean) => boolean | void;
87
+ type: 'multiline-element';
88
+ };
89
+ export type TextFormatTransformer = Readonly<{
90
+ format: ReadonlyArray<TextFormatType>;
91
+ tag: string;
92
+ intraword?: boolean;
93
+ type: 'text-format';
94
+ }>;
95
+ export type TextMatchTransformer = Readonly<{
96
+ dependencies: Array<Klass<LexicalNode>>;
97
+ /**
98
+ * Determines how a node should be exported to markdown
99
+ */
100
+ export?: (node: LexicalNode, exportChildren: (node: ElementNode) => string, exportFormat: (node: TextNode, textContent: string) => string) => string | null;
101
+ /**
102
+ * This regex determines what text is matched during markdown imports
103
+ */
104
+ importRegExp?: RegExp;
105
+ /**
106
+ * This regex determines what text is matched for markdown shortcuts while typing in the editor
107
+ */
108
+ regExp: RegExp;
109
+ /**
110
+ * Determines how the matched markdown text should be transformed into a node during the markdown import process
111
+ *
112
+ * @returns nothing, or a TextNode that may be a child of the new node that is created.
113
+ * If a TextNode is returned, text format matching will be applied to it (e.g. bold, italic, etc.)
114
+ */
115
+ replace?: (node: TextNode, match: RegExpMatchArray) => void | TextNode;
116
+ /**
117
+ * For import operations, this function can be used to determine the end index of the match, after `importRegExp` has matched.
118
+ * Without this function, the end index will be determined by the length of the match from `importRegExp`. Manually determining the end index can be useful if
119
+ * the match from `importRegExp` is not the entire text content of the node. That way, `importRegExp` can be used to match only the start of the node, and `getEndIndex`
120
+ * can be used to match the end of the node.
121
+ *
122
+ * @returns The end index of the match, or false if the match was unsuccessful and a different transformer should be tried.
123
+ */
124
+ getEndIndex?: (node: TextNode, match: RegExpMatchArray) => number | false;
125
+ /**
126
+ * Single character that allows the transformer to trigger when typed in the editor. This does not affect markdown imports outside of the markdown shortcut plugin.
127
+ * If the trigger is matched, the `regExp` will be used to match the text in the second step.
128
+ */
129
+ trigger?: string;
130
+ type: 'text-match';
131
+ }>;
132
+ export declare const listMarkerState: import("@ekz/lexical").StateConfig<"mdListMarker", string>;
133
+ export declare const codeFenceState: import("@ekz/lexical").StateConfig<string, string>;
134
+ export declare const HEADING: ElementTransformer;
135
+ export declare const QUOTE: ElementTransformer;
136
+ export declare const CODE: MultilineElementTransformer;
137
+ export declare const UNORDERED_LIST: ElementTransformer;
138
+ export declare const CHECK_LIST: ElementTransformer;
139
+ export declare const ORDERED_LIST: ElementTransformer;
140
+ export declare const INLINE_CODE: TextFormatTransformer;
141
+ export declare const HIGHLIGHT: TextFormatTransformer;
142
+ export declare const BOLD_ITALIC_STAR: TextFormatTransformer;
143
+ export declare const BOLD_ITALIC_UNDERSCORE: TextFormatTransformer;
144
+ export declare const BOLD_STAR: TextFormatTransformer;
145
+ export declare const BOLD_UNDERSCORE: TextFormatTransformer;
146
+ export declare const STRIKETHROUGH: TextFormatTransformer;
147
+ export declare const ITALIC_STAR: TextFormatTransformer;
148
+ export declare const ITALIC_UNDERSCORE: TextFormatTransformer;
149
+ export declare const LINK: TextMatchTransformer;
150
+ export declare const ELEMENT_TRANSFORMERS: Array<ElementTransformer>;
151
+ export declare const MULTILINE_ELEMENT_TRANSFORMERS: Array<MultilineElementTransformer>;
152
+ export declare const TEXT_FORMAT_TRANSFORMERS: Array<TextFormatTransformer>;
153
+ export declare const TEXT_MATCH_TRANSFORMERS: Array<TextMatchTransformer>;
154
+ export declare const TRANSFORMERS: Array<Transformer>;
155
+ export declare function normalizeMarkdown(input: string, shouldMergeAdjacentLines?: boolean): string;
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # `@lexical/markdown`
2
+
3
+ [![See API Documentation](https://lexical.dev/img/see-api-documentation.svg)](https://lexical.dev/docs/api/modules/lexical_markdown)
4
+
5
+ This package contains markdown helpers for Lexical: import, export and shortcuts.
6
+
7
+ ## Import and export
8
+ ```js
9
+ import {
10
+ $convertFromMarkdownString,
11
+ $convertToMarkdownString,
12
+ TRANSFORMERS,
13
+ } from '@ekz/lexical-markdown';
14
+
15
+ editor.update(() => {
16
+ const markdown = $convertToMarkdownString(TRANSFORMERS);
17
+ ...
18
+ });
19
+
20
+ editor.update(() => {
21
+ $convertFromMarkdownString(markdown, TRANSFORMERS);
22
+ });
23
+ ```
24
+
25
+ It can also be used for initializing editor's state from markdown string. Here's an example with react `<RichTextPlugin>`
26
+ ```jsx
27
+ <LexicalComposer initialConfig={{
28
+ editorState: () => $convertFromMarkdownString(markdown, TRANSFORMERS)
29
+ }}>
30
+ <RichTextPlugin />
31
+ </LexicalComposer>
32
+ ```
33
+
34
+ ## Shortcuts
35
+ Can use `<MarkdownShortcutPlugin>` if using React
36
+ ```jsx
37
+ import { TRANSFORMERS } from '@ekz/lexical-markdown';
38
+ import {MarkdownShortcutPlugin} from '@ekz/lexical-react/LexicalMarkdownShortcutPlugin';
39
+
40
+ <LexicalComposer>
41
+ <MarkdownShortcutPlugin transformers={TRANSFORMERS} />
42
+ </LexicalComposer>
43
+ ```
44
+
45
+ Or `registerMarkdownShortcuts` to register it manually:
46
+ ```js
47
+ import {
48
+ registerMarkdownShortcuts,
49
+ TRANSFORMERS,
50
+ } from '@ekz/lexical-markdown';
51
+
52
+ const editor = createEditor(...);
53
+ registerMarkdownShortcuts(editor, TRANSFORMERS);
54
+ ```
55
+
56
+ ## Transformers
57
+ Markdown functionality relies on transformers configuration. It's an array of objects that define how certain text or nodes
58
+ are processed during import, export or while typing. `@lexical/markdown` package provides set of built-in transformers:
59
+ ```js
60
+ // Element transformers
61
+ UNORDERED_LIST
62
+ CODE
63
+ HEADING
64
+ ORDERED_LIST
65
+ QUOTE
66
+
67
+ // Text format transformers
68
+ BOLD_ITALIC_STAR
69
+ BOLD_ITALIC_UNDERSCORE
70
+ BOLD_STAR
71
+ BOLD_UNDERSCORE
72
+ INLINE_CODE
73
+ ITALIC_STAR
74
+ ITALIC_UNDERSCORE
75
+ STRIKETHROUGH
76
+
77
+ // Text match transformers
78
+ LINK
79
+ ```
80
+
81
+ And bundles of commonly used transformers:
82
+ - `TRANSFORMERS` - all built-in transformers
83
+ - `ELEMENT_TRANSFORMERS` - all built-in element transformers
84
+ - `MULTILINE_ELEMENT_TRANSFORMERS` - all built-in multiline element transformers
85
+ - `TEXT_FORMAT_TRANSFORMERS` - all built-in text format transformers
86
+ - `TEXT_MATCH_TRANSFORMERS` - all built-in text match transformers
87
+
88
+ Transformers are explicitly passed to markdown API allowing application-specific subset of markdown or custom transformers.
89
+
90
+ There're three types of transformers:
91
+
92
+ - **Element transformer** handles top level elements (lists, headings, quotes, tables or code blocks)
93
+ - **Text format transformer** applies text range formats defined in `TextFormatType` (bold, italic, underline, strikethrough, code, subscript and superscript)
94
+ - **Text match transformer** relies on matching leaf text node content
95
+
96
+ See `MarkdownTransformers.js` for transformer implementation examples