@lexical/react 0.1.8 → 0.1.11

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.
Files changed (91) hide show
  1. package/DEPRECATED_useLexical.dev.js +3 -38
  2. package/DEPRECATED_useLexical.prod.js +1 -2
  3. package/DEPRECATED_useLexicalAutoFormatter.dev.js +202 -74
  4. package/DEPRECATED_useLexicalAutoFormatter.prod.js +21 -16
  5. package/DEPRECATED_useLexicalCanShowPlaceholder.prod.js +1 -1
  6. package/DEPRECATED_useLexicalCharacterLimit.dev.js +23 -21
  7. package/DEPRECATED_useLexicalCharacterLimit.prod.js +8 -8
  8. package/DEPRECATED_useLexicalDecorators.prod.js +1 -1
  9. package/DEPRECATED_useLexicalEditor.dev.js +1 -25
  10. package/DEPRECATED_useLexicalEditor.prod.js +1 -1
  11. package/DEPRECATED_useLexicalEditorEvents.prod.js +1 -1
  12. package/DEPRECATED_useLexicalHistory.dev.js +18 -15
  13. package/DEPRECATED_useLexicalHistory.prod.js +7 -7
  14. package/DEPRECATED_useLexicalList.dev.js +6 -0
  15. package/DEPRECATED_useLexicalList.prod.js +1 -1
  16. package/DEPRECATED_useLexicalPlainText.dev.js +79 -70
  17. package/DEPRECATED_useLexicalPlainText.prod.js +15 -16
  18. package/DEPRECATED_useLexicalRichText.dev.js +124 -250
  19. package/DEPRECATED_useLexicalRichText.prod.js +25 -29
  20. package/LexicalAutoFormatterPlugin.dev.js +202 -74
  21. package/LexicalAutoFormatterPlugin.js.flow +10 -0
  22. package/LexicalAutoFormatterPlugin.prod.js +21 -17
  23. package/LexicalAutoLinkPlugin.js.flow +23 -0
  24. package/LexicalAutoLinkPlugin.prod.js +4 -4
  25. package/LexicalCharacterLimitPlugin.dev.js +23 -21
  26. package/LexicalCharacterLimitPlugin.js.flow +12 -0
  27. package/LexicalCharacterLimitPlugin.prod.js +9 -8
  28. package/LexicalClearEditorPlugin.dev.js +52 -0
  29. package/LexicalClearEditorPlugin.js +9 -0
  30. package/LexicalClearEditorPlugin.js.flow +14 -0
  31. package/LexicalClearEditorPlugin.prod.js +7 -0
  32. package/LexicalCollaborationPlugin.dev.js +31 -36
  33. package/LexicalCollaborationPlugin.js.flow +55 -0
  34. package/LexicalCollaborationPlugin.prod.js +7 -8
  35. package/LexicalComposer.dev.js +8 -6
  36. package/LexicalComposer.js.flow +23 -0
  37. package/LexicalComposer.prod.js +3 -3
  38. package/LexicalComposerContext.js.flow +27 -0
  39. package/LexicalComposerContext.prod.js +1 -1
  40. package/LexicalContentEditable.dev.js +14 -8
  41. package/LexicalContentEditable.js.flow +35 -0
  42. package/LexicalContentEditable.prod.js +3 -3
  43. package/LexicalHashtagPlugin.js.flow +20 -0
  44. package/LexicalHashtagPlugin.prod.js +1 -1
  45. package/LexicalHistoryPlugin.dev.js +18 -15
  46. package/LexicalHistoryPlugin.js.flow +34 -0
  47. package/LexicalHistoryPlugin.prod.js +7 -7
  48. package/LexicalHorizontalRuleNode.dev.js +66 -0
  49. package/LexicalHorizontalRuleNode.js +9 -0
  50. package/LexicalHorizontalRuleNode.js.flow +25 -0
  51. package/LexicalHorizontalRuleNode.prod.js +8 -0
  52. package/LexicalLinkPlugin.dev.js +0 -1
  53. package/LexicalLinkPlugin.js.flow +10 -0
  54. package/LexicalLinkPlugin.prod.js +3 -3
  55. package/LexicalListPlugin.dev.js +6 -0
  56. package/LexicalListPlugin.js.flow +10 -0
  57. package/LexicalListPlugin.prod.js +2 -2
  58. package/LexicalNestedComposer.js.flow +21 -0
  59. package/LexicalNestedComposer.prod.js +1 -1
  60. package/LexicalOnChangePlugin.js.flow +14 -0
  61. package/LexicalOnChangePlugin.prod.js +1 -1
  62. package/LexicalPlainTextPlugin.dev.js +72 -44
  63. package/LexicalPlainTextPlugin.js.flow +18 -0
  64. package/LexicalPlainTextPlugin.prod.js +12 -11
  65. package/LexicalRichTextPlugin.dev.js +115 -222
  66. package/LexicalRichTextPlugin.js.flow +18 -0
  67. package/LexicalRichTextPlugin.prod.js +21 -25
  68. package/LexicalTablePlugin.dev.js +43 -39
  69. package/LexicalTablePlugin.js.flow +10 -0
  70. package/LexicalTablePlugin.prod.js +4 -3
  71. package/LexicalTreeView.dev.js +10 -2
  72. package/LexicalTreeView.js.flow +19 -0
  73. package/LexicalTreeView.prod.js +9 -8
  74. package/README.md +0 -1
  75. package/package.json +5 -4
  76. package/useLexicalDecoratorMap.js.flow +16 -0
  77. package/useLexicalDecoratorMap.prod.js +1 -1
  78. package/useLexicalIsTextContentEmpty.js.flow +15 -0
  79. package/useLexicalIsTextContentEmpty.prod.js +1 -1
  80. package/useLexicalNodeSelection.dev.js +70 -0
  81. package/useLexicalNodeSelection.js +9 -0
  82. package/useLexicalNodeSelection.js.flow +14 -0
  83. package/useLexicalNodeSelection.prod.js +8 -0
  84. package/withSubscriptions.js.flow +13 -0
  85. package/withSubscriptions.prod.js +1 -1
  86. package/LexicalBootstrapPlugin.dev.js +0 -124
  87. package/LexicalBootstrapPlugin.js +0 -9
  88. package/LexicalBootstrapPlugin.prod.js +0 -8
  89. package/LexicalHorizontalRulePlugin.dev.js +0 -51
  90. package/LexicalHorizontalRulePlugin.js +0 -9
  91. package/LexicalHorizontalRulePlugin.prod.js +0 -7
@@ -4,32 +4,28 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- 'use strict';var k=require("@lexical/react/withSubscriptions"),w=require("lexical"),x=require("react"),z=require("@lexical/list"),A=require("lexical/CodeNode"),B=require("lexical/HeadingNode"),C=require("lexical/LinkNode");
8
- function D(a,d,e,b,c){if(null===a||0===e.size&&0===b.size)return 0;var f=d._selection,h=a._selection;if(c)return 1;if(null===f||null===h||!h.isCollapsed()||!f.isCollapsed())return 0;var g=Array.from(e);b=Array.from(b);e=d._nodeMap;c=[];for(var l=0;l<g.length;l++){const n=e.get(g[l]);void 0!==n&&c.push(n)}for(g=0;g<b.length;g++)b[g][1]&&(l=e.get(b[g][0]),void 0===l||w.$isRootNode(l)||c.push(l));if(0===c.length)return 0;if(1<c.length)return b=d._nodeMap,d=b.get(f.anchor.key),h=b.get(h.anchor.key),d&&
9
- h&&!a._nodeMap.has(d.__key)&&w.$isTextNode(d)&&1===d.__text.length&&1===f.anchor.offset?2:0;d=c[0];a=a._nodeMap.get(d.__key);if(!w.$isTextNode(a)||!w.$isTextNode(d)||a.__mode!==d.__mode)return 0;a=a.__text;d=d.__text;if(a===d)return 0;f=f.anchor;h=h.anchor;if(f.key!==h.key||"text"!==f.type)return 0;f=f.offset;h=h.offset;a=d.length-a.length;return 1===a&&h===f-1?2:-1===a&&h===f+1?3:-1===a&&h===f?4:0}
10
- function E(a,d){let e=Date.now(),b=0;return(c,f,h,g,l,n)=>{const p=Date.now();if(n.has("historic"))return b=0,e=p,2;const m=D(c,f,g,l,a.isComposing()),t=(()=>{if(n.has("without-history"))return 0;if(null===c)return 1;var q=f._selection;const r=c._selection;if(!(0<g.size||0<l.size))return null===r&&null!==q?0:2;q=null===h||h.editor===a;return 0!==m&&m===b&&p<e+d&&q?0:1})();e=p;b=m;return t}}
11
- function F(a,d,e=1E3){const b=x.useMemo(()=>d||{current:null,redoStack:[],undoStack:[]},[d]),c=x.useCallback(()=>{b.undoStack=[];b.redoStack=[];b.current=null},[b]);x.useEffect(()=>{const f=E(a,e);return k(a.addListener("command",h=>{switch(h){case "undo":h=b.redoStack;var g=b.undoStack;if(0!==g.length){var l=b.current;const n=g.pop();null!==l&&(h.push(l),a.execCommand("canRedo",!0));0===g.length&&a.execCommand("canUndo",!1);b.current=n;n.editor.setEditorState(n.editorState.clone(n.undoSelection),
12
- {tag:"historic"})}return!0;case "redo":return h=b.redoStack,g=b.undoStack,0!==h.length&&(l=b.current,null!==l&&(g.push(l),a.execCommand("canUndo",!0)),g=h.pop(),0===h.length&&a.execCommand("canRedo",!1),b.current=g,g.editor.setEditorState(g.editorState,{tag:"historic"})),!0;case "clearEditor":return c(),!1;case "clearHistory":return c(),!0;default:return!1}},0),a.addListener("update",({editorState:h,prevEditorState:g,dirtyLeaves:l,dirtyElements:n,tags:p})=>{const m=b.current,t=b.redoStack,q=b.undoStack,
13
- r=null===m?null:m.editorState;if(null===m||h!==r){l=f(g,h,m,l,n,p);if(1===l)0!==t.length&&(b.redoStack=[]),null!==m&&(q.push({...m,undoSelection:g.read(w.$getSelection)}),a.execCommand("canUndo",!0));else if(2===l)return;b.current={editor:a,editorState:h}}}))},[c,e,a,b])}function G(a,d,e=1E3){return F(a,d,e)}
14
- function H(a){a=a.getLatest();const d=a.constructor.clone(a);d.__parent=a.__parent;w.$isElementNode(a)&&w.$isElementNode(d)?(d.__children=Array.from(a.__children),d.__format=a.__format,d.__indent=a.__indent,d.__dir=a.__dir):w.$isTextNode(a)&&w.$isTextNode(d)?(d.__format=a.__format,d.__style=a.__style,d.__mode=a.__mode,d.__detail=a.__detail):w.$isDecoratorNode(a)&&w.$isDecoratorNode(d)&&(d.__state=a.__state);return d}
15
- function I(a,d,e,b,c){for(var f=d;null!==a;){for(d=a.getParent();null!==d&&d.excludeFromCopy();)d=d.getParent();if(null===d)break;if(!w.$isElementNode(a)||!a.excludeFromCopy()){const h=a.getKey();let g=c.get(h);const l=void 0===g;l&&(g=H(a),c.set(h,g));!w.$isTextNode(g)||g.isSegmented()||g.isToken()?w.$isElementNode(g)&&(g.__children=g.__children.slice(e?f:0,e?void 0:f+1)):g.__text=g.__text.slice(e?f:0,e?void 0:f);if(w.$isRootNode(d)){l&&b.push(h);break}}f=c.get(d.getKey());f=w.$isElementNode(f)?
16
- f.__children.indexOf(a.getKey()):a.getIndexWithinParent();a=d}}
17
- const J={"#text":a=>({node:w.$createTextNode(a.textContent)}),a:a=>({node:a instanceof HTMLAnchorElement?C.$createLinkNode(a.href):w.$createTextNode(a.textContent)}),b:a=>{const d="normal"===a.style.fontWeight;return{forChild:e=>{w.$isTextNode(e)&&!d&&e.toggleFormat("bold")},node:null}},br:()=>({node:w.$createLineBreakNode()}),div:a=>({after:d=>{const e=a.parentNode;null!=e&&a!==e.lastChild&&d.push(w.$createLineBreakNode());return d},node:null!==a.style.fontFamily.match("monospace")?A.$createCodeNode():
18
- null}),em:()=>({forChild:a=>{w.$isTextNode(a)&&a.toggleFormat("italic")},node:null}),h1:()=>({node:B.$createHeadingNode("h1")}),h2:()=>({node:B.$createHeadingNode("h2")}),h3:()=>({node:B.$createHeadingNode("h3")}),h4:()=>({node:B.$createHeadingNode("h4")}),h5:()=>({node:B.$createHeadingNode("h5")}),i:()=>({forChild:a=>{w.$isTextNode(a)&&a.toggleFormat("italic")},node:null}),li:()=>({node:z.$createListItemNode()}),ol:()=>({node:z.$createListNode("ol")}),p:()=>({node:w.$createParagraphNode()}),pre:()=>
19
- ({node:A.$createCodeNode()}),span:a=>{const d="700"===a.style.fontWeight;return{forChild:e=>{w.$isTextNode(e)&&d&&e.toggleFormat("bold")},node:null}},strong:()=>({forChild:a=>{w.$isTextNode(a)&&a.toggleFormat("bold")},node:null}),table:a=>({node:a.classList.contains("js-file-line-container")?A.$createCodeNode():null}),td:a=>{const d=a.classList.contains("js-file-line");return{after:e=>{d&&a.parentNode&&a.parentNode.nextSibling&&e.push(w.$createLineBreakNode());return e},node:null}},u:()=>({forChild:a=>
20
- {w.$isTextNode(a)&&a.toggleFormat("underline")},node:null}),ul:()=>({node:z.$createListNode("ul")})};
21
- function K(a,d,e,b=new Map){let c=[],f=null;var h=a.nodeName.toLowerCase(),g=(e._config.htmlTransforms||{})[h]||d[h],l=g?g(a):null;g=null;if(null!==l){g=l.after;f=l.node;if(null!==f){c.push(f);const n=Array.from(b.values());for(let p=0;p<n.length;p++)n[p](f)}null!=l.forChild&&b.set(h,l.forChild)}a=a.childNodes;h=[];for(l=0;l<a.length;l++)h.push(...K(a[l],d,e,b));null!=g&&(h=g(h));null==f?c=c.concat(h):w.$isElementNode(f)&&f.append(...h);return c}
22
- function L(a,d,e){var b=a.getData("application/x-lexical-editor");if(b){var c=e._config.namespace;try{const l=JSON.parse(b);if(l.namespace===c){const {range:n,nodeMap:p}=l.state;var f=new Map(p);b=[];for(c=0;c<n.length;c++){var h=f.get(n[c]);if(void 0!==h){var g=w.$createNodeFromParse(h,f);b.push(g)}}d.insertNodes(b);return}}catch(l){}}if(f=a.getData("text/html")){f=(new DOMParser).parseFromString(f,"text/html");a=[];f=f.body?Array.from(f.body.childNodes):[];h=f.length;for(g=0;g<h;g++)b=K(f[g],J,
23
- e),null!==b&&(a=a.concat(b));e=a;a=[];f=null;for(h=0;h<e.length;h++)g=e[h],!w.$isElementNode(g)||g.isInline()?(null===f&&(f=w.$createParagraphNode(),a.push(f)),null!==f&&f.append(g)):(a.push(g),f=null);d.insertNodes(a)}else e=a.getData("text/plain"),null!=e&&d.insertRawText(e)}
24
- function M(a,d){var e=a.focus;a=e.offset;"element"===e.type?d=e.getNode().getChildAtIndex(d?a-1:a):(e=e.getNode(),d=d&&0===a||!d&&a===e.getTextContentSize()?d?e.getPreviousSibling():e.getNextSibling():null);return w.$isDecoratorNode(d)}function N(a,d){a.preventDefault();d.update(()=>{w.$log("onPasteForRichText");const e=w.$getSelection(),b=a.clipboardData;null!=b&&null!==e&&L(b,e,d)})}
25
- function O(a,d){P(a,d);d.update(()=>{w.$log("onCutForRichText");const e=w.$getSelection();null!==e&&e.removeText()})}
26
- function P(a,d){a.preventDefault();d.update(()=>{w.$log("onCopyForRichText");const e=a.clipboardData;var b=w.$getSelection();if(null!==b&&null!=e){var c=window.getSelection();if(!c.isCollapsed){var f=c.getRangeAt(0);f&&(c=document.createElement("div"),f=f.cloneContents(),c.appendChild(f),e.setData("text/html",c.innerHTML));e.setData("text/plain",b.getTextContent());c=d._config.namespace;f=e.setData;var h=JSON,g=h.stringify;{var l=b.anchor,n=b.focus;var p=l.getCharacterOffset();const y=n.getCharacterOffset();
27
- var m=l.getNode(),t=n.getNode(),q=m.getParentOrThrow();if(m===t&&w.$isTextNode(m)&&(q.canBeEmpty()||1<q.getChildrenSize()))b=H(m),m=y>p,b.__text=b.__text.slice(m?p:y,m?y:p),p=b.getKey(),p={nodeMap:[[p,b]],range:[p]};else if(b=b.getNodes(),0===b.length)p={nodeMap:[],range:[]};else{m=b.length;t=b[0];q=t.getParent();if(null!==q&&!q.canBeEmpty()){var r=q.__children;if(r.length===m){var u=!0;for(var v=0;v<r.length;v++)if(r[v]!==b[v].__key){u=!1;break}u&&(m++,b.push(q))}}q=b[m-1];l=l.isBefore(n);n=new Map;
28
- r=[];I(t,l?p:y,!0,r,n);for(t=0;t<m;t++)if(u=b[t],v=u.getKey(),!(n.has(v)||w.$isElementNode(u)&&u.excludeFromCopy())){const Q=H(u);w.$isRootNode(u.getParent())&&r.push(u.getKey());n.set(v,Q)}I(q,l?y:p,!1,r,n);p={nodeMap:Array.from(n.entries()),range:r}}}f.call(e,"application/x-lexical-editor",g.call(h,{namespace:c,state:p}))}}})}var R="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?x.useLayoutEffect:x.useEffect;
29
- function S(a){x.useEffect(()=>{const d=e=>{var b=a.getRootElement();if(document.activeElement===b&&(b=e.data,"string"===typeof b)){try{var c=JSON.parse(b)}catch(f){return}if(c&&"nuanria_messaging"===c.protocol&&"request"===c.type&&(c=c.payload)&&"makeChanges"===c.functionId&&(c=c.args)){const [f,h,g,l,n]=c;a.update(()=>{w.$log("useLexicalDragonSupport");const p=w.$getSelection();if(null!==p){var m=p.anchor;let t=m.getNode(),q=0,r=0;w.$isTextNode(t)&&0<=f&&0<=h&&(q=f,r=f+h,p.setTextNodeRange(t,q,t,
30
- r));if(q!==r||""!==g)p.insertRawText(g),t=m.getNode();w.$isTextNode(t)&&(q=l,r=l+n,m=t.getTextContentSize(),q=q>m?m:q,r=r>m?m:r,p.setTextNodeRange(t,q,t,r));e.stopImmediatePropagation()}})}}};window.addEventListener("message",d,!0);return()=>{window.removeEventListener("message",d,!0)}},[a])}
31
- function T(a){R(()=>{const d=a.addListener("command",(e,b)=>{var c=w.$getSelection();if(null===c)return!1;switch(e){case "deleteCharacter":return c.deleteCharacter(b),!0;case "deleteWord":return c.deleteWord(b),!0;case "deleteLine":return c.deleteLine(b),!0;case "insertText":return"string"===typeof b?c.insertText(b):(e=b.dataTransfer,null!=e?L(e,c,a):(b=b.data)&&c.insertText(b)),!0;case "removeText":return c.removeText(),!0;case "formatText":return c.formatText(b),!0;case "formatElement":return c=
32
- c.anchor.getNode(),(w.$isElementNode(c)?c:c.getParentOrThrow()).setFormat(b),!0;case "insertLineBreak":return c.insertLineBreak(b),!0;case "insertParagraph":return c.insertParagraph(),!0;case "indentContent":return c=c.anchor,c="element"===c.type?c.getNode():c.getNode().getParentOrThrow(),c.canInsertTab()?a.execCommand("insertText","\t"):10!==c.getIndent()&&c.setIndent(c.getIndent()+1),!0;case "outdentContent":return c=c.anchor,b=c.getNode(),e="element"===c.type?c.getNode():c.getNode().getParentOrThrow(),
33
- e.canInsertTab()?"\t"===b.getTextContent()[c.offset-1]&&a.execCommand("deleteCharacter",!0):0!==e.getIndent()&&e.setIndent(e.getIndent()-1),!0;case "keyArrowLeft":e=b.shiftKey;if(M(c,!0))return b.preventDefault(),b=e,e="rtl"===c.anchor.getNode().getParentOrThrow().getDirection(),c.modify(b?"extend":"move",!e,"character"),!0;break;case "keyArrowRight":e=b.shiftKey;if(M(c,!1))return b.preventDefault(),b=e,e="rtl"===c.anchor.getNode().getParentOrThrow().getDirection(),c.modify(b?"extend":"move",e,"character"),
34
- !0;break;case "keyBackspace":return b.preventDefault(),{anchor:b}=c,c.isCollapsed()&&0===b.offset&&0<("element"===b.type?b.getNode():b.getNode().getParentOrThrow()).getIndent()?a.execCommand("outdentContent"):a.execCommand("deleteCharacter",!0);case "keyDelete":return b.preventDefault(),a.execCommand("deleteCharacter",!1);case "keyEnter":return b.preventDefault(),b.shiftKey?a.execCommand("insertLineBreak"):a.execCommand("insertParagraph");case "keyTab":return b.preventDefault(),a.execCommand(b.shiftKey?
35
- "outdentContent":"indentContent");case "keyEscape":return a.blur(),!0;case "copy":return P(b,a),!0;case "cut":return O(b,a),!0;case "paste":return N(b,a),!0;case "drop":case "dragstart":return b.preventDefault(),!0}return!1},0);a.execCommand("bootstrapEditor");return d},[a]);S(a)}module.exports=function(a,d){T(a);G(a,d)};
7
+ var k=require("@lexical/react/withSubscriptions"),w=require("lexical"),y=require("react");
8
+ function z(a,e,f,c,d){if(null===a||0===f.size&&0===c.size)return 0;var b=e._selection,g=a._selection;if(d)return 1;if(!(w.$isRangeSelection(b)&&w.$isRangeSelection(g)&&g.isCollapsed()&&b.isCollapsed()))return 0;var h=Array.from(f);c=Array.from(c);f=e._nodeMap;d=[];for(var l=0;l<h.length;l++){const n=f.get(h[l]);void 0!==n&&d.push(n)}for(h=0;h<c.length;h++)c[h][1]&&(l=f.get(c[h][0]),void 0===l||w.$isRootNode(l)||d.push(l));if(0===d.length)return 0;if(1<d.length)return c=e._nodeMap,e=c.get(b.anchor.key),
9
+ g=c.get(g.anchor.key),e&&g&&!a._nodeMap.has(e.__key)&&w.$isTextNode(e)&&1===e.__text.length&&1===b.anchor.offset?2:0;e=d[0];a=a._nodeMap.get(e.__key);if(!w.$isTextNode(a)||!w.$isTextNode(e)||a.__mode!==e.__mode)return 0;a=a.__text;e=e.__text;if(a===e)return 0;b=b.anchor;g=g.anchor;if(b.key!==g.key||"text"!==b.type)return 0;b=b.offset;g=g.offset;a=e.length-a.length;return 1===a&&g===b-1?2:-1===a&&g===b+1?3:-1===a&&g===b?4:0}
10
+ function A(a,e){let f=Date.now(),c=0;return(d,b,g,h,l,n)=>{const p=Date.now();if(n.has("historic"))return c=0,f=p,2;const m=z(d,b,h,l,a.isComposing()),t=(()=>{const q=n.has("history-push");if(!q&&n.has("history-merge"))return 0;if(null===d)return 1;var r=b._selection;const u=d._selection;if(!(0<h.size||0<l.size))return null===u&&null!==r?0:2;r=null===g||g.editor===a;return!1===q&&0!==m&&m===c&&p<f+e&&r?0:1})();f=p;c=m;return t}}
11
+ function B(a,e,f=1E3){const c=y.useMemo(()=>e||{current:null,redoStack:[],undoStack:[]},[e]),d=y.useCallback(()=>{c.undoStack=[];c.redoStack=[];c.current=null},[c]);y.useEffect(()=>{const b=A(a,f);return k(a.addListener("command",g=>{switch(g){case "undo":g=c.redoStack;var h=c.undoStack;if(0!==h.length){var l=c.current;const n=h.pop();null!==l&&(g.push(l),a.execCommand("canRedo",!0));0===h.length&&a.execCommand("canUndo",!1);c.current=n;n.editor.setEditorState(n.editorState.clone(n.undoSelection),
12
+ {tag:"historic"})}return!0;case "redo":return g=c.redoStack,h=c.undoStack,0!==g.length&&(l=c.current,null!==l&&(h.push(l),a.execCommand("canUndo",!0)),h=g.pop(),0===g.length&&a.execCommand("canRedo",!1),c.current=h,h.editor.setEditorState(h.editorState,{tag:"historic"})),!0;case "clearEditor":return d(),!1;case "clearHistory":return d(),!0;default:return!1}},0),a.addListener("update",({editorState:g,prevEditorState:h,dirtyLeaves:l,dirtyElements:n,tags:p})=>{const m=c.current,t=c.redoStack,q=c.undoStack,
13
+ r=null===m?null:m.editorState;if(null===m||g!==r){l=b(h,g,m,l,n,p);if(1===l)0!==t.length&&(c.redoStack=[]),null!==m&&(q.push({...m,undoSelection:h.read(w.$getSelection)}),a.execCommand("canUndo",!0));else if(2===l)return;c.current={editor:a,editorState:g}}}))},[d,f,a,c])}function C(a,e,f=1E3){return B(a,e,f)}
14
+ function D(a){a=a.getLatest();const e=a.constructor.clone(a);e.__parent=a.__parent;w.$isElementNode(a)&&w.$isElementNode(e)?(e.__children=Array.from(a.__children),e.__format=a.__format,e.__indent=a.__indent,e.__dir=a.__dir):w.$isTextNode(a)&&w.$isTextNode(e)?(e.__format=a.__format,e.__style=a.__style,e.__mode=a.__mode,e.__detail=a.__detail):w.$isDecoratorNode(a)&&w.$isDecoratorNode(e)&&(e.__state=a.__state);return e}
15
+ function E(a,e,f,c,d){for(var b=e;null!==a;){for(e=a.getParent();null!==e&&e.excludeFromCopy();)e=e.getParent();if(null===e)break;if(!w.$isElementNode(a)||!a.excludeFromCopy()){const g=a.getKey();let h=d.get(g);const l=void 0===h;l&&(h=D(a),d.set(g,h));!w.$isTextNode(h)||h.isSegmented()||h.isToken()?w.$isElementNode(h)&&(h.__children=h.__children.slice(f?b:0,f?void 0:b+1)):h.__text=h.__text.slice(f?b:0,f?void 0:b);if(w.$isRootNode(e)){l&&c.push(g);break}}b=d.get(e.getKey());b=w.$isElementNode(b)?
16
+ b.__children.indexOf(a.getKey()):a.getIndexWithinParent();a=e}}function F(a){a=a.anchor.getNode();return"rtl"===(w.$isRootNode(a)?a:a.getParentOrThrow()).getDirection()}function G(a,e){const {nodeName:f}=a;e=e._htmlConversions.get(f.toLowerCase());let c=null;void 0!==e&&e.forEach(d=>{d=d(a);null!==d&&(null===c||c.priority<d.priority)&&(c=d)});return null!==c?c.conversion:null}
17
+ function H(a,e,f=new Map){let c=[],d=null;var b=G(a,e),g=b?b(a):null;b=null;if(null!==g){b=g.after;d=g.node;if(null!==d){c.push(d);var h=Array.from(f.values());for(let l=0;l<h.length;l++)h[l](d)}null!=g.forChild&&f.set(a.nodeName,g.forChild)}a=a.childNodes;g=[];for(h=0;h<a.length;h++)g.push(...H(a[h],e,f));null!=b&&(g=b(g));null==d?c=c.concat(g):w.$isElementNode(d)&&d.append(...g);return c}
18
+ function I(a,e,f){var c=a.getData("application/x-lexical-editor");if(c){var d=f._config.namespace;try{const l=JSON.parse(c);if(l.namespace===d){const {range:n,nodeMap:p}=l.state;var b=new Map(p);c=[];for(d=0;d<n.length;d++){var g=b.get(n[d]);if(void 0!==g){var h=w.$createNodeFromParse(g,b);c.push(h)}}e.insertNodes(c);return}}catch(l){}}if(b=a.getData("text/html")){b=(new DOMParser).parseFromString(b,"text/html");a=[];b=b.body?Array.from(b.body.childNodes):[];g=b.length;for(h=0;h<g;h++)c=H(b[h],f),
19
+ null!==c&&(a=a.concat(c));f=a;a=[];b=null;for(g=0;g<f.length;g++)h=f[g],!w.$isElementNode(h)||h.isInline()?(null===b&&(b=w.$createParagraphNode(),a.push(b)),null!==b&&b.append(h)):(a.push(h),b=null);e.insertNodes(a)}else f=a.getData("text/plain"),null!=f&&e.insertRawText(f)}function J(a,e){a=w.$getDecoratorNode(a.focus,e);return w.$isDecoratorNode(a)&&!a.isIsolated()}
20
+ function K(a,e){a.preventDefault();e.update(()=>{const f=w.$getSelection(),c=a.clipboardData;null!=c&&w.$isRangeSelection(f)&&I(c,f,e)})}function L(a,e){M(a,e);e.update(()=>{const f=w.$getSelection();w.$isRangeSelection(f)&&f.removeText()})}
21
+ function M(a,e){a.preventDefault();e.update(()=>{const f=a.clipboardData;var c=w.$getSelection();if(null!==c&&null!=f){var d=window.getSelection();if(!d.isCollapsed){var b=d.getRangeAt(0);b&&(d=document.createElement("div"),b=b.cloneContents(),d.appendChild(b),f.setData("text/html",d.innerHTML));f.setData("text/plain",c.getTextContent());d=e._config.namespace;b=f.setData;var g=JSON,h=g.stringify;{if(!w.$isRangeSelection(c))throw Error("Minified Lexical error #68; see codes.json for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");
22
+ var l=c.anchor,n=c.focus;var p=l.getCharacterOffset();const x=n.getCharacterOffset();var m=l.getNode(),t=n.getNode(),q=m.getParentOrThrow();if(m===t&&w.$isTextNode(m)&&(q.canBeEmpty()||1<q.getChildrenSize()))c=D(m),m=x>p,c.__text=c.__text.slice(m?p:x,m?x:p),p=c.getKey(),p={nodeMap:[[p,c]],range:[p]};else if(c=c.getNodes(),0===c.length)p={nodeMap:[],range:[]};else{m=c.length;t=c[0];q=t.getParent();if(null!==q&&(!q.canBeEmpty()||w.$isRootNode(q))){var r=q.__children;if(r.length===m){var u=!0;for(var v=
23
+ 0;v<r.length;v++)if(r[v]!==c[v].__key){u=!1;break}u&&(m++,c.push(q))}}q=c[m-1];l=l.isBefore(n);n=new Map;r=[];E(t,l?p:x,!0,r,n);for(t=0;t<m;t++)if(u=c[t],v=u.getKey(),!(n.has(v)||w.$isElementNode(u)&&u.excludeFromCopy())){const O=D(u);w.$isRootNode(u.getParent())&&r.push(u.getKey());n.set(v,O)}E(q,l?x:p,!1,r,n);p={nodeMap:Array.from(n.entries()),range:r}}}b.call(f,"application/x-lexical-editor",h.call(g,{namespace:d,state:p}))}}})}const N={tag:"history-merge"};
24
+ function P(a,e){if(null!==e)if(void 0===e)a.update(()=>{var f=w.$getRoot();if(null===f.getFirstChild()){const c=w.$createParagraphNode();f.append(c);f=document.activeElement;(null!==w.$getSelection()||null!==f&&f===a.getRootElement())&&c.select()}},N);else if(null!==e)switch(typeof e){case "string":e=a.parseEditorState(e);a.setEditorState(e,N);break;case "object":a.setEditorState(e,N);break;case "function":a.update(e,N)}}
25
+ function Q(a){y.useEffect(()=>{const e=f=>{var c=a.getRootElement();if(document.activeElement===c&&(c=f.data,"string"===typeof c)){try{var d=JSON.parse(c)}catch(b){return}if(d&&"nuanria_messaging"===d.protocol&&"request"===d.type&&(d=d.payload)&&"makeChanges"===d.functionId&&(d=d.args)){const [b,g,h,l,n]=d;a.update(()=>{const p=w.$getSelection();if(w.$isRangeSelection(p)){var m=p.anchor;let t=m.getNode(),q=0,r=0;w.$isTextNode(t)&&0<=b&&0<=g&&(q=b,r=b+g,p.setTextNodeRange(t,q,t,r));if(q!==r||""!==
26
+ h)p.insertRawText(h),t=m.getNode();w.$isTextNode(t)&&(q=l,r=l+n,m=t.getTextContentSize(),q=q>m?m:q,r=r>m?m:r,p.setTextNodeRange(t,q,t,r));f.stopImmediatePropagation()}})}}};window.addEventListener("message",e,!0);return()=>{window.removeEventListener("message",e,!0)}},[a])}
27
+ function R(a,e){y.useLayoutEffect(()=>{const f=a.addListener("command",(c,d)=>{var b=w.$getSelection();if("click"===c&&w.$isNodeSelection(b))return b.clear(),!0;if(!w.$isRangeSelection(b))return!1;switch(c){case "deleteCharacter":return b.deleteCharacter(d),!0;case "deleteWord":return b.deleteWord(d),!0;case "deleteLine":return b.deleteLine(d),!0;case "insertText":return"string"===typeof d?b.insertText(d):(c=d.dataTransfer,null!=c?I(c,b,a):(d=d.data)&&b.insertText(d)),!0;case "removeText":return b.removeText(),
28
+ !0;case "formatText":return b.formatText(d),!0;case "formatElement":return b=b.anchor.getNode(),(w.$isElementNode(b)?b:b.getParentOrThrow()).setFormat(d),!0;case "insertLineBreak":return b.insertLineBreak(d),!0;case "insertParagraph":return b.insertParagraph(),!0;case "indentContent":return b=b.anchor,b="element"===b.type?b.getNode():b.getNode().getParentOrThrow(),b.canInsertTab()?a.execCommand("insertText","\t"):10!==b.getIndent()&&b.setIndent(b.getIndent()+1),!0;case "outdentContent":return b=b.anchor,
29
+ d=b.getNode(),c="element"===b.type?b.getNode():b.getNode().getParentOrThrow(),c.canInsertTab()?"\t"===d.getTextContent()[b.offset-1]&&a.execCommand("deleteCharacter",!0):0!==c.getIndent()&&c.setIndent(c.getIndent()-1),!0;case "keyArrowLeft":c=d.shiftKey;if(J(b,!0))return d.preventDefault(),d=c,c=F(b),b.modify(d?"extend":"move",!c,"character"),!0;break;case "keyArrowRight":c=d.shiftKey;if(J(b,!1))return d.preventDefault(),d=c,c=F(b),b.modify(d?"extend":"move",c,"character"),!0;break;case "keyBackspace":return d.preventDefault(),
30
+ {anchor:d}=b,b.isCollapsed()&&0===d.offset&&0<("element"===d.type?d.getNode():d.getNode().getParentOrThrow()).getIndent()?a.execCommand("outdentContent"):a.execCommand("deleteCharacter",!0);case "keyDelete":return d.preventDefault(),a.execCommand("deleteCharacter",!1);case "keyEnter":return d.preventDefault(),d.shiftKey?a.execCommand("insertLineBreak"):a.execCommand("insertParagraph");case "keyTab":return d.preventDefault(),a.execCommand(d.shiftKey?"outdentContent":"indentContent");case "keyEscape":return a.blur(),
31
+ !0;case "copy":return M(d,a),!0;case "cut":return L(d,a),!0;case "paste":return K(d,a),!0;case "drop":case "dragstart":return d.preventDefault(),!0}return!1},0);P(a,e);return f},[a]);Q(a)}module.exports=function(a,e,f){R(a,f);C(a,e)};
@@ -11,6 +11,7 @@ var list = require('@lexical/list');
11
11
  var lexical = require('lexical');
12
12
  var CodeNode = require('lexical/CodeNode');
13
13
  var react = require('react');
14
+ var LexicalHorizontalRuleNode = require('@lexical/react/LexicalHorizontalRuleNode');
14
15
  var HeadingNode = require('lexical/HeadingNode');
15
16
  var QuoteNode = require('lexical/QuoteNode');
16
17
 
@@ -73,17 +74,26 @@ function $findNodeWithOffsetFromJoinedText(elementNode, joinedTextLength, offset
73
74
  const children = elementNode.getChildren();
74
75
  const childrenLength = children.length;
75
76
  let runningLength = 0;
77
+ let isPriorNodeTextNode = false;
76
78
 
77
79
  for (let i = 0; i < childrenLength; ++i) {
78
- if (runningLength >= joinedTextLength) {
80
+ // We must examine the offsetInJoinedText that is located
81
+ // at the length of the string.
82
+ // For example, given "hello", the length is 5, yet
83
+ // the caller still wants the node + offset at the
84
+ // right edge of the "o".
85
+ if (runningLength > joinedTextLength) {
79
86
  break;
80
87
  }
81
88
 
82
89
  const child = children[i];
83
- const childContentLength = lexical.$isTextNode(child) ? child.getTextContent().length : separatorLength;
90
+ const isChildNodeTestNode = lexical.$isTextNode(child);
91
+ const childContentLength = isChildNodeTestNode ? child.getTextContent().length : separatorLength;
84
92
  const newRunningLength = runningLength + childContentLength;
93
+ const isJoinedOffsetWithinNode = isPriorNodeTextNode === false && runningLength === offsetInJoinedText || runningLength === 0 && runningLength === offsetInJoinedText || runningLength < offsetInJoinedText && offsetInJoinedText <= newRunningLength;
85
94
 
86
- if (runningLength <= offsetInJoinedText && offsetInJoinedText < newRunningLength && lexical.$isTextNode(child)) {
95
+ if (isJoinedOffsetWithinNode && lexical.$isTextNode(child)) {
96
+ // Check isTextNode again for flow.
87
97
  return {
88
98
  node: child,
89
99
  offset: offsetInJoinedText - runningLength
@@ -91,6 +101,7 @@ function $findNodeWithOffsetFromJoinedText(elementNode, joinedTextLength, offset
91
101
  }
92
102
 
93
103
  runningLength = newRunningLength;
104
+ isPriorNodeTextNode = isChildNodeTestNode;
94
105
  }
95
106
 
96
107
  return null;
@@ -115,8 +126,6 @@ const SEPARATOR_BETWEEN_TEXT_AND_NON_TEXT_NODES = '\u0004'; // Select an unused
115
126
  const autoFormatBase = {
116
127
  nodeTransformationKind: null,
117
128
  regEx: /(?:)/,
118
- regExCaptureGroupsToDelete: null,
119
- regExExpectedCaptureGroupCount: 1,
120
129
  requiresParagraphStart: false
121
130
  };
122
131
  const paragraphStartBase = { ...autoFormatBase,
@@ -152,38 +161,77 @@ const markdownCodeBlock = { ...paragraphStartBase,
152
161
  };
153
162
  const markdownOrderedList = { ...paragraphStartBase,
154
163
  nodeTransformationKind: 'paragraphOrderedList',
155
- regEx: /^(\d+)\.\s/,
156
- regExExpectedCaptureGroupCount: 2
157
- /*e.g. '321. ' returns '321. ' & '321'*/
158
-
164
+ regEx: /^(\d+)\.\s/
165
+ };
166
+ const markdownHorizontalRule = { ...paragraphStartBase,
167
+ nodeTransformationKind: 'horizontalRule',
168
+ regEx: /(?:\*\*\* )/
169
+ };
170
+ const markdownHorizontalRuleUsingDashes = { ...paragraphStartBase,
171
+ nodeTransformationKind: 'horizontalRule',
172
+ regEx: /(?:--- )/
173
+ };
174
+ const markdownItalic = { ...autoFormatBase,
175
+ nodeTransformationKind: 'italic',
176
+ regEx: /(\*)(\s*\b)([^\*]*)(\b\s*)(\*\s)$/
159
177
  };
160
178
  const markdownBold = { ...autoFormatBase,
161
- nodeTransformationKind: 'textBold',
162
- // regEx: /(\*)(?:\s*\b)(?:[^\*]*)(?:\b\s*)(\*\s)$/, // The $ will find the target at the end of the string.
163
- regEx: /(\*)(\s*\b)([^\*]*)(\b\s*)(\*\s)$/,
164
- // Remove the first and last capture groups. Remeber, the 0th capture group is the entire string.
165
- // e.g. "*Hello* " requires removing both "*" as well as bolding "Hello".
166
- regExCaptureGroupsToDelete: [1, 5],
167
- // The $ will find the target at the end of the string.
168
- regExExpectedCaptureGroupCount: 6
179
+ nodeTransformationKind: 'bold',
180
+ regEx: /(\*\*)(\s*\b)([^\*\*]*)(\b\s*)(\*\*\s)$/
169
181
  };
170
- const allAutoFormatCriteriaForTextNodes = [markdownBold];
171
- const allAutoFormatCriteria = [markdownHeader1, markdownHeader2, markdownHeader3, markdownBlockQuote, markdownUnorderedListDash, markdownUnorderedListAsterisk, markdownOrderedList, markdownCodeBlock, ...allAutoFormatCriteriaForTextNodes];
182
+ const markdownBoldWithUnderlines = { ...autoFormatBase,
183
+ nodeTransformationKind: 'bold',
184
+ regEx: /(__)(\s*)([^__]*)(\s*)(__\s)$/
185
+ };
186
+ const markdownBoldItalic = { ...autoFormatBase,
187
+ nodeTransformationKind: 'bold_italic',
188
+ regEx: /(\*\*\*)(\s*\b)([^\*\*\*]*)(\b\s*)(\*\*\*\s)$/
189
+ }; // Markdown does not support underline, but we can allow folks to use
190
+ // the HTML tags for underline.
191
+
192
+ const fakeMarkdownUnderline = { ...autoFormatBase,
193
+ nodeTransformationKind: 'underline',
194
+ regEx: /(\<u\>)(\s*\b)([^\<]*)(\b\s*)(\<\/u\>\s)$/
195
+ };
196
+ const markdownStrikethrough = { ...autoFormatBase,
197
+ nodeTransformationKind: 'strikethrough',
198
+ regEx: /(~~)(\s*\b)([^~~]*)(\b\s*)(~~\s)$/
199
+ };
200
+ const allAutoFormatCriteriaForTextNodes = [markdownBoldItalic, markdownItalic, markdownBold, markdownBoldWithUnderlines, fakeMarkdownUnderline, markdownStrikethrough];
201
+ const allAutoFormatCriteria = [markdownHeader1, markdownHeader2, markdownHeader3, markdownBlockQuote, markdownUnorderedListDash, markdownUnorderedListAsterisk, markdownOrderedList, markdownCodeBlock, markdownHorizontalRule, markdownHorizontalRuleUsingDashes, ...allAutoFormatCriteriaForTextNodes];
172
202
  function getAllAutoFormatCriteriaForTextNodes() {
173
203
  return allAutoFormatCriteriaForTextNodes;
174
204
  }
175
205
  function getAllAutoFormatCriteria() {
176
206
  return allAutoFormatCriteria;
177
207
  }
208
+ function getInitialScanningContext(textNodeWithOffset, triggerState) {
209
+ return {
210
+ autoFormatCriteria: {
211
+ nodeTransformationKind: 'noTransformation',
212
+ regEx: /(?:)/,
213
+ // Empty reg ex will do until the precise criteria is discovered.
214
+ requiresParagraphStart: null
215
+ },
216
+ joinedText: null,
217
+ matchResultContext: {
218
+ offsetInJoinedTextForCollapsedSelection: 0,
219
+ regExCaptureGroups: []
220
+ },
221
+ textNodeWithOffset,
222
+ triggerState
223
+ };
224
+ }
178
225
 
179
- function getMatchResultContextWithRegEx(textToSearch, matchMustAppearAtStartOfString, matchMustAppearAtEndOfString, regEx, regExExpectedCaptureGroupCount, scanningContext) {
226
+ function getMatchResultContextWithRegEx(textToSearch, matchMustAppearAtStartOfString, matchMustAppearAtEndOfString, regEx) {
180
227
  const matchResultContext = {
181
- regExCaptureGroups: [],
182
- triggerState: null
228
+ offsetInJoinedTextForCollapsedSelection: 0,
229
+ regExCaptureGroups: []
183
230
  };
184
231
  const regExMatches = textToSearch.match(regEx);
185
232
 
186
- if (regExMatches !== null && regExMatches.length > 0 && regExMatches.length === regExExpectedCaptureGroupCount && (matchMustAppearAtStartOfString === false || regExMatches.index === 0) && (matchMustAppearAtEndOfString === false || regExMatches.index + regExMatches[0].length === textToSearch.length)) {
233
+ if (regExMatches !== null && regExMatches.length > 0 && (matchMustAppearAtStartOfString === false || regExMatches.index === 0) && (matchMustAppearAtEndOfString === false || regExMatches.index + regExMatches[0].length === textToSearch.length)) {
234
+ matchResultContext.offsetInJoinedTextForCollapsedSelection = textToSearch.length;
187
235
  const captureGroupsCount = regExMatches.length;
188
236
  let runningLength = regExMatches.index;
189
237
 
@@ -215,7 +263,7 @@ function getMatchResultContextForParagraphs(autoFormatCriteria, scanningContext)
215
263
 
216
264
  if (textNodeWithOffset.node.getPreviousSibling() === null) {
217
265
  const textToSearch = scanningContext.textNodeWithOffset.node.getTextContent();
218
- return getMatchResultContextWithRegEx(textToSearch, true, false, autoFormatCriteria.regEx, autoFormatCriteria.regExExpectedCaptureGroupCount);
266
+ return getMatchResultContextWithRegEx(textToSearch, true, false, autoFormatCriteria.regEx);
219
267
  }
220
268
 
221
269
  return null;
@@ -230,17 +278,14 @@ function getMatchResultContextForText(autoFormatCriteria, scanningContext) {
230
278
  // Lazy calculate the text to search.
231
279
  scanningContext.joinedText = $joinTextNodesInElementNode(parentNode, SEPARATOR_BETWEEN_TEXT_AND_NON_TEXT_NODES, scanningContext.textNodeWithOffset);
232
280
  }
233
-
234
- return getMatchResultContextWithRegEx(scanningContext.joinedText, false, true, autoFormatCriteria.regEx, autoFormatCriteria.regExExpectedCaptureGroupCount);
235
281
  } else {
236
282
  {
237
283
  throw Error(`Expected node ${parentNode.__key} to to be a ElementNode.`);
238
284
  }
239
285
  }
240
- } // This is a placeholder function for following PR's related to character based transformations.
241
-
286
+ }
242
287
 
243
- return null;
288
+ return getMatchResultContextWithRegEx(scanningContext.joinedText, false, true, autoFormatCriteria.regEx);
244
289
  }
245
290
 
246
291
  function getMatchResultContextForCriteria(autoFormatCriteria, scanningContext) {
@@ -251,8 +296,11 @@ function getMatchResultContextForCriteria(autoFormatCriteria, scanningContext) {
251
296
  return getMatchResultContextForText(autoFormatCriteria, scanningContext);
252
297
  }
253
298
 
254
- function getNewNodeForCriteria(autoFormatCriteria, matchResultContext, children) {
299
+ function getNewNodeForCriteria(scanningContext, element) {
255
300
  let newNode = null;
301
+ const children = element.getChildren();
302
+ const autoFormatCriteria = scanningContext.autoFormatCriteria;
303
+ const matchResultContext = scanningContext.matchResultContext;
256
304
 
257
305
  if (autoFormatCriteria.nodeTransformationKind != null) {
258
306
  switch (autoFormatCriteria.nodeTransformationKind) {
@@ -307,7 +355,7 @@ function getNewNodeForCriteria(autoFormatCriteria, matchResultContext, children)
307
355
  case 'paragraphCodeBlock':
308
356
  {
309
357
  // Toggle code and paragraph nodes.
310
- if (matchResultContext.triggerState != null && matchResultContext.triggerState.isCodeBlock) {
358
+ if (scanningContext.triggerState != null && scanningContext.triggerState.isCodeBlock) {
311
359
  newNode = lexical.$createParagraphNode();
312
360
  } else {
313
361
  newNode = CodeNode.$createCodeNode();
@@ -316,6 +364,14 @@ function getNewNodeForCriteria(autoFormatCriteria, matchResultContext, children)
316
364
  newNode.append(...children);
317
365
  return newNode;
318
366
  }
367
+
368
+ case 'horizontalRule':
369
+ {
370
+ // return null for newNode. Insert the HR here.
371
+ const horizontalRuleNode = LexicalHorizontalRuleNode.$createHorizontalRuleNode();
372
+ element.insertBefore(horizontalRuleNode);
373
+ break;
374
+ }
319
375
  }
320
376
  }
321
377
 
@@ -331,41 +387,70 @@ function updateTextNode(node, count) {
331
387
  }
332
388
  }
333
389
 
334
- function transformTextNodeForAutoFormatCriteria(scanningContext, autoFormatCriteria, matchResultContext) {
335
- if (autoFormatCriteria.requiresParagraphStart) {
336
- transformTextNodeForParagraphs(scanningContext, autoFormatCriteria, matchResultContext);
390
+ function transformTextNodeForAutoFormatCriteria(scanningContext) {
391
+ if (scanningContext.autoFormatCriteria.requiresParagraphStart) {
392
+ transformTextNodeForParagraphs(scanningContext);
337
393
  } else {
338
- transformTextNodeForText(scanningContext, autoFormatCriteria, matchResultContext);
394
+ transformTextNodeForText(scanningContext);
339
395
  }
340
396
  }
341
397
 
342
- function transformTextNodeForParagraphs(scanningContext, autoFormatCriteria, matchResultContext) {
398
+ function transformTextNodeForParagraphs(scanningContext) {
343
399
  const textNodeWithOffset = scanningContext.textNodeWithOffset;
344
400
  const element = textNodeWithOffset.node.getParentOrThrow();
345
- const text = matchResultContext.regExCaptureGroups[0].text;
401
+ const text = scanningContext.matchResultContext.regExCaptureGroups[0].text;
346
402
  updateTextNode(textNodeWithOffset.node, text.length);
347
- const elementNode = getNewNodeForCriteria(autoFormatCriteria, matchResultContext, element.getChildren());
403
+ const elementNode = getNewNodeForCriteria(scanningContext, element);
348
404
 
349
405
  if (elementNode !== null) {
350
406
  element.replace(elementNode);
351
407
  }
352
408
  }
353
409
 
354
- function transformTextNodeForText(scanningContext, autoFormatCriteria, matchResultContext) {
410
+ function getTextFormatType(nodeTransformationKind) {
411
+ switch (nodeTransformationKind) {
412
+ case 'italic':
413
+ case 'bold':
414
+ case 'underline':
415
+ case 'strikethrough':
416
+ return [nodeTransformationKind];
417
+
418
+ case 'bold_italic':
419
+ {
420
+ return ['bold', 'italic'];
421
+ }
422
+ }
423
+
424
+ return null;
425
+ }
426
+
427
+ function transformTextNodeForText(scanningContext) {
428
+ const autoFormatCriteria = scanningContext.autoFormatCriteria;
429
+ const matchResultContext = scanningContext.matchResultContext;
430
+
355
431
  if (autoFormatCriteria.nodeTransformationKind != null) {
356
- switch (autoFormatCriteria.nodeTransformationKind) {
357
- case 'textBold':
358
- {
359
- matchResultContext.regExCaptureGroups = getCaptureGroupsByResolvingAllDetails(scanningContext, autoFormatCriteria, matchResultContext);
432
+ if (matchResultContext.regExCaptureGroups.length !== 6) {
433
+ // For BIUS and other formatts which have a pattern + text + pattern,
434
+ // the expected reg ex pattern should have 6 groups.
435
+ // If it does not, then break and fail silently.
436
+ // e2e tests validate the regEx pattern.
437
+ return;
438
+ }
360
439
 
361
- if (autoFormatCriteria.regExCaptureGroupsToDelete != null) {
362
- // Remove unwanted text in reg ex patterh.
363
- removeTextInCaptureGroups(autoFormatCriteria.regExCaptureGroupsToDelete, matchResultContext);
364
- formatTextInCaptureGroupIndex('bold', 3, matchResultContext);
365
- }
440
+ const formatting = getTextFormatType(autoFormatCriteria.nodeTransformationKind);
366
441
 
367
- break;
368
- }
442
+ if (formatting != null) {
443
+ const captureGroupsToDelete = [1, 5];
444
+ const formatCaptureGroup = 3;
445
+ matchResultContext.regExCaptureGroups = getCaptureGroupsByResolvingAllDetails(scanningContext);
446
+
447
+ if (captureGroupsToDelete.length > 0) {
448
+ // Remove unwanted text in reg ex pattern.
449
+ removeTextInCaptureGroups(captureGroupsToDelete, matchResultContext);
450
+ }
451
+
452
+ formatTextInCaptureGroupIndex(formatting, formatCaptureGroup, matchResultContext);
453
+ makeCollapsedSelectionAtOffsetInJoinedText(matchResultContext.offsetInJoinedTextForCollapsedSelection, matchResultContext.offsetInJoinedTextForCollapsedSelection + 1, scanningContext.textNodeWithOffset.node.getParentOrThrow());
369
454
  }
370
455
  }
371
456
  } // Some Capture Group Details were left lazily unresolved as their calculation
@@ -373,7 +458,9 @@ function transformTextNodeForText(scanningContext, autoFormatCriteria, matchResu
373
458
  // known, the details may be fully resolved without incurring unwasted performance cost.
374
459
 
375
460
 
376
- function getCaptureGroupsByResolvingAllDetails(scanningContext, autoFormatCriteria, matchResultContext) {
461
+ function getCaptureGroupsByResolvingAllDetails(scanningContext) {
462
+ const autoFormatCriteria = scanningContext.autoFormatCriteria;
463
+ const matchResultContext = scanningContext.matchResultContext;
377
464
  const textNodeWithOffset = scanningContext.textNodeWithOffset;
378
465
  const regExCaptureGroups = matchResultContext.regExCaptureGroups;
379
466
  const captureGroupsCount = regExCaptureGroups.length;
@@ -420,7 +507,7 @@ function removeTextInCaptureGroups(regExCaptureGroupsToDelete, matchResultContex
420
507
  lexical.$setSelection(newSelection);
421
508
  const currentSelection = lexical.$getSelection();
422
509
 
423
- if (currentSelection != null) {
510
+ if (lexical.$isRangeSelection(currentSelection)) {
424
511
  currentSelection.removeText(); // Shift offsets for capture groups which are within the same node
425
512
 
426
513
  if (anchorTextNodeWithOffset.node.getKey() === focusTextNodeWithOffset.node.getKey()) {
@@ -445,6 +532,12 @@ function removeTextInCaptureGroups(regExCaptureGroupsToDelete, matchResultContex
445
532
  }
446
533
 
447
534
  function shiftCaptureGroupOffsets(delta, applyAtOrAfterOffset, node, startingCaptureGroupIndex, matchResultContext) {
535
+ matchResultContext.offsetInJoinedTextForCollapsedSelection += delta;
536
+
537
+ if (!(matchResultContext.offsetInJoinedTextForCollapsedSelection > 0)) {
538
+ throw Error(`The text content string length does not correlate with insertions/deletions of new text.`);
539
+ }
540
+
448
541
  const regExCaptureGroups = matchResultContext.regExCaptureGroups;
449
542
  const regExCaptureGroupsCount = regExCaptureGroups.length;
450
543
 
@@ -461,7 +554,7 @@ function shiftCaptureGroupOffsets(delta, applyAtOrAfterOffset, node, startingCap
461
554
  }
462
555
  }
463
556
 
464
- function formatTextInCaptureGroupIndex(formatType, captureGroupIndex, matchResultContext) {
557
+ function formatTextInCaptureGroupIndex(formatTypes, captureGroupIndex, matchResultContext) {
465
558
  const regExCaptureGroups = matchResultContext.regExCaptureGroups;
466
559
  const regExCaptureGroupsCount = regExCaptureGroups.length;
467
560
 
@@ -480,12 +573,30 @@ function formatTextInCaptureGroupIndex(formatType, captureGroupIndex, matchResul
480
573
  lexical.$setSelection(newSelection);
481
574
  const currentSelection = lexical.$getSelection();
482
575
 
483
- if (currentSelection != null) {
484
- currentSelection.formatText(formatType);
576
+ if (lexical.$isRangeSelection(currentSelection)) {
577
+ for (let i = 0; i < formatTypes.length; i++) {
578
+ currentSelection.formatText(formatTypes[i]);
579
+ }
580
+
581
+ const finalSelection = lexical.$createRangeSelection();
582
+ finalSelection.anchor.set(focusTextNodeWithOffset.node.getKey(), focusTextNodeWithOffset.offset + 1, 'text');
583
+ finalSelection.focus.set(focusTextNodeWithOffset.node.getKey(), focusTextNodeWithOffset.offset + 1, 'text');
584
+ lexical.$setSelection(finalSelection);
485
585
  }
486
586
  }
487
587
  }
488
588
 
589
+ function makeCollapsedSelectionAtOffsetInJoinedText(offsetInJoinedText, joinedTextLength, parentElementNode) {
590
+ const textNodeWithOffset = $findNodeWithOffsetFromJoinedText(parentElementNode, joinedTextLength, offsetInJoinedText, TRIGGER_STRING_LENGTH);
591
+
592
+ if (textNodeWithOffset != null) {
593
+ const newSelection = lexical.$createRangeSelection();
594
+ newSelection.anchor.set(textNodeWithOffset.node.getKey(), textNodeWithOffset.offset, 'text');
595
+ newSelection.focus.set(textNodeWithOffset.node.getKey(), textNodeWithOffset.offset, 'text');
596
+ lexical.$setSelection(newSelection);
597
+ }
598
+ }
599
+
489
600
  /**
490
601
  * Copyright (c) Meta Platforms, Inc. and affiliates.
491
602
  *
@@ -495,17 +606,17 @@ function formatTextInCaptureGroupIndex(formatType, captureGroupIndex, matchResul
495
606
  *
496
607
  */
497
608
 
498
- function getCriteriaWithMatchResultContext(autoFormatCriteriaArray, currentTriggerState, scanningContext) {
609
+ function getCriteriaWithMatchResultContext(autoFormatCriteriaArray, scanningContext) {
610
+ const currentTriggerState = scanningContext.triggerState;
499
611
  const count = autoFormatCriteriaArray.length;
500
612
 
501
613
  for (let i = 0; i < count; i++) {
502
614
  const autoFormatCriteria = autoFormatCriteriaArray[i]; // Skip code block nodes, unless the nodeTransformationKind calls for toggling the code block.
503
615
 
504
- if (currentTriggerState.isCodeBlock === false || autoFormatCriteria.nodeTransformationKind === 'paragraphCodeBlock') {
616
+ if (currentTriggerState != null && currentTriggerState.isCodeBlock === false || autoFormatCriteria.nodeTransformationKind === 'paragraphCodeBlock') {
505
617
  const matchResultContext = getMatchResultContextForCriteria(autoFormatCriteria, scanningContext);
506
618
 
507
619
  if (matchResultContext != null) {
508
- matchResultContext.triggerState = currentTriggerState;
509
620
  return {
510
621
  autoFormatCriteria: autoFormatCriteria,
511
622
  matchResultContext
@@ -521,7 +632,7 @@ function getCriteriaWithMatchResultContext(autoFormatCriteriaArray, currentTrigg
521
632
  }
522
633
 
523
634
  function getTextNodeForAutoFormatting(selection) {
524
- if (selection == null) {
635
+ if (!lexical.$isRangeSelection(selection)) {
525
636
  return null;
526
637
  }
527
638
 
@@ -537,8 +648,17 @@ function getTextNodeForAutoFormatting(selection) {
537
648
  };
538
649
  }
539
650
 
540
- function updateAutoFormatting(editor, currentTriggerState) {
651
+ function updateAutoFormatting(editor, scanningContext) {
541
652
  editor.update(() => {
653
+ transformTextNodeForAutoFormatCriteria(scanningContext);
654
+ }, {
655
+ tag: 'history-push'
656
+ });
657
+ }
658
+
659
+ function findScanningContextWithValidMatch(editorState, currentTriggerState) {
660
+ let scanningContext = null;
661
+ editorState.read(() => {
542
662
  const textNodeWithOffset = getTextNodeForAutoFormatting(lexical.$getSelection());
543
663
 
544
664
  if (textNodeWithOffset === null) {
@@ -546,24 +666,25 @@ function updateAutoFormatting(editor, currentTriggerState) {
546
666
  } // Please see the declaration of ScanningContext for a detailed explanation.
547
667
 
548
668
 
549
- const scanningContext = {
550
- joinedText: null,
551
- textNodeWithOffset
552
- };
669
+ const initialScanningContext = getInitialScanningContext(textNodeWithOffset, currentTriggerState);
553
670
  const criteriaWithMatchResultContext = getCriteriaWithMatchResultContext( // Do not apply paragraph node changes like blockQuote or H1 to listNodes. Also, do not attempt to transform a list into a list using * or -.
554
- currentTriggerState.isParentAListItemNode === false ? getAllAutoFormatCriteria() : getAllAutoFormatCriteriaForTextNodes(), currentTriggerState, scanningContext);
671
+ currentTriggerState.isParentAListItemNode === false ? getAllAutoFormatCriteria() : getAllAutoFormatCriteriaForTextNodes(), initialScanningContext);
555
672
 
556
673
  if (criteriaWithMatchResultContext.autoFormatCriteria === null || criteriaWithMatchResultContext.matchResultContext === null) {
557
674
  return;
558
675
  }
559
676
 
560
- transformTextNodeForAutoFormatCriteria(scanningContext, criteriaWithMatchResultContext.autoFormatCriteria, criteriaWithMatchResultContext.matchResultContext);
677
+ scanningContext = initialScanningContext; // Lazy fill-in the particular format criteria and any matching result information.
678
+
679
+ scanningContext.autoFormatCriteria = criteriaWithMatchResultContext.autoFormatCriteria;
680
+ scanningContext.matchResultContext = criteriaWithMatchResultContext.matchResultContext;
561
681
  });
682
+ return scanningContext;
562
683
  }
563
684
 
564
- function shouldAttemptToAutoFormat(currentTriggerState, priorTriggerState) {
685
+ function findScanningContext(editorState, currentTriggerState, priorTriggerState) {
565
686
  if (currentTriggerState == null || priorTriggerState == null) {
566
- return false;
687
+ return null;
567
688
  } // The below checks needs to execute relativey quickly, so perform the light-weight ones first.
568
689
  // The substr check is a quick way to avoid autoformat parsing in that it looks for the autoformat
569
690
  // trigger which is the trigger string (" ").
@@ -572,7 +693,12 @@ function shouldAttemptToAutoFormat(currentTriggerState, priorTriggerState) {
572
693
  const triggerStringLength = TRIGGER_STRING.length;
573
694
  const currentTextContentLength = currentTriggerState.textContent.length;
574
695
  const triggerOffset = currentTriggerState.anchorOffset - triggerStringLength;
575
- return currentTriggerState.hasParentNode === true && currentTriggerState.isSimpleText && currentTriggerState.isSelectionCollapsed && currentTriggerState.nodeKey === priorTriggerState.nodeKey && currentTriggerState.anchorOffset !== priorTriggerState.anchorOffset && triggerOffset >= 0 && triggerOffset + triggerStringLength <= currentTextContentLength && currentTriggerState.textContent.substr(triggerOffset, triggerStringLength) === TRIGGER_STRING && currentTriggerState.textContent !== priorTriggerState.textContent;
696
+
697
+ if ((currentTriggerState.hasParentNode === true && currentTriggerState.isSimpleText && currentTriggerState.isSelectionCollapsed && currentTriggerState.nodeKey === priorTriggerState.nodeKey && currentTriggerState.anchorOffset !== priorTriggerState.anchorOffset && triggerOffset >= 0 && triggerOffset + triggerStringLength <= currentTextContentLength && currentTriggerState.textContent.substr(triggerOffset, triggerStringLength) === TRIGGER_STRING && currentTriggerState.textContent !== priorTriggerState.textContent) === false) {
698
+ return null;
699
+ }
700
+
701
+ return findScanningContextWithValidMatch(editorState, currentTriggerState);
576
702
  }
577
703
 
578
704
  function getTriggerState(editorState) {
@@ -580,7 +706,7 @@ function getTriggerState(editorState) {
580
706
  editorState.read(() => {
581
707
  const selection = lexical.$getSelection();
582
708
 
583
- if (selection == null || !selection.isCollapsed()) {
709
+ if (!lexical.$isRangeSelection(selection) || !selection.isCollapsed()) {
584
710
  return;
585
711
  }
586
712
 
@@ -609,15 +735,17 @@ function useAutoFormatter(editor) {
609
735
  // For example, typing "#" and then " ", shoud trigger an format.
610
736
  // However, given "#A B", where the user delets "A" should not.
611
737
  let priorTriggerState = null;
612
- editor.addListener('update', ({
738
+ return editor.addListener('update', ({
613
739
  tags
614
740
  }) => {
615
741
  // Examine historic so that we are not running autoformatting within markdown.
616
742
  if (tags.has('historic') === false) {
617
- const currentTriggerState = getTriggerState(editor.getEditorState());
743
+ const editorState = editor.getEditorState();
744
+ const currentTriggerState = getTriggerState(editorState);
745
+ const scanningContext = currentTriggerState == null ? null : findScanningContext(editorState, currentTriggerState, priorTriggerState);
618
746
 
619
- if (shouldAttemptToAutoFormat(currentTriggerState, priorTriggerState) && currentTriggerState != null) {
620
- updateAutoFormatting(editor, currentTriggerState);
747
+ if (scanningContext != null) {
748
+ updateAutoFormatting(editor, scanningContext);
621
749
  }
622
750
 
623
751
  priorTriggerState = currentTriggerState;