@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.
- package/DEPRECATED_useLexical.dev.js +3 -38
- package/DEPRECATED_useLexical.prod.js +1 -2
- package/DEPRECATED_useLexicalAutoFormatter.dev.js +202 -74
- package/DEPRECATED_useLexicalAutoFormatter.prod.js +21 -16
- package/DEPRECATED_useLexicalCanShowPlaceholder.prod.js +1 -1
- package/DEPRECATED_useLexicalCharacterLimit.dev.js +23 -21
- package/DEPRECATED_useLexicalCharacterLimit.prod.js +8 -8
- package/DEPRECATED_useLexicalDecorators.prod.js +1 -1
- package/DEPRECATED_useLexicalEditor.dev.js +1 -25
- package/DEPRECATED_useLexicalEditor.prod.js +1 -1
- package/DEPRECATED_useLexicalEditorEvents.prod.js +1 -1
- package/DEPRECATED_useLexicalHistory.dev.js +18 -15
- package/DEPRECATED_useLexicalHistory.prod.js +7 -7
- package/DEPRECATED_useLexicalList.dev.js +6 -0
- package/DEPRECATED_useLexicalList.prod.js +1 -1
- package/DEPRECATED_useLexicalPlainText.dev.js +79 -70
- package/DEPRECATED_useLexicalPlainText.prod.js +15 -16
- package/DEPRECATED_useLexicalRichText.dev.js +124 -250
- package/DEPRECATED_useLexicalRichText.prod.js +25 -29
- package/LexicalAutoFormatterPlugin.dev.js +202 -74
- package/LexicalAutoFormatterPlugin.js.flow +10 -0
- package/LexicalAutoFormatterPlugin.prod.js +21 -17
- package/LexicalAutoLinkPlugin.js.flow +23 -0
- package/LexicalAutoLinkPlugin.prod.js +4 -4
- package/LexicalCharacterLimitPlugin.dev.js +23 -21
- package/LexicalCharacterLimitPlugin.js.flow +12 -0
- package/LexicalCharacterLimitPlugin.prod.js +9 -8
- package/LexicalClearEditorPlugin.dev.js +52 -0
- package/LexicalClearEditorPlugin.js +9 -0
- package/LexicalClearEditorPlugin.js.flow +14 -0
- package/LexicalClearEditorPlugin.prod.js +7 -0
- package/LexicalCollaborationPlugin.dev.js +31 -36
- package/LexicalCollaborationPlugin.js.flow +55 -0
- package/LexicalCollaborationPlugin.prod.js +7 -8
- package/LexicalComposer.dev.js +8 -6
- package/LexicalComposer.js.flow +23 -0
- package/LexicalComposer.prod.js +3 -3
- package/LexicalComposerContext.js.flow +27 -0
- package/LexicalComposerContext.prod.js +1 -1
- package/LexicalContentEditable.dev.js +14 -8
- package/LexicalContentEditable.js.flow +35 -0
- package/LexicalContentEditable.prod.js +3 -3
- package/LexicalHashtagPlugin.js.flow +20 -0
- package/LexicalHashtagPlugin.prod.js +1 -1
- package/LexicalHistoryPlugin.dev.js +18 -15
- package/LexicalHistoryPlugin.js.flow +34 -0
- package/LexicalHistoryPlugin.prod.js +7 -7
- package/LexicalHorizontalRuleNode.dev.js +66 -0
- package/LexicalHorizontalRuleNode.js +9 -0
- package/LexicalHorizontalRuleNode.js.flow +25 -0
- package/LexicalHorizontalRuleNode.prod.js +8 -0
- package/LexicalLinkPlugin.dev.js +0 -1
- package/LexicalLinkPlugin.js.flow +10 -0
- package/LexicalLinkPlugin.prod.js +3 -3
- package/LexicalListPlugin.dev.js +6 -0
- package/LexicalListPlugin.js.flow +10 -0
- package/LexicalListPlugin.prod.js +2 -2
- package/LexicalNestedComposer.js.flow +21 -0
- package/LexicalNestedComposer.prod.js +1 -1
- package/LexicalOnChangePlugin.js.flow +14 -0
- package/LexicalOnChangePlugin.prod.js +1 -1
- package/LexicalPlainTextPlugin.dev.js +72 -44
- package/LexicalPlainTextPlugin.js.flow +18 -0
- package/LexicalPlainTextPlugin.prod.js +12 -11
- package/LexicalRichTextPlugin.dev.js +115 -222
- package/LexicalRichTextPlugin.js.flow +18 -0
- package/LexicalRichTextPlugin.prod.js +21 -25
- package/LexicalTablePlugin.dev.js +43 -39
- package/LexicalTablePlugin.js.flow +10 -0
- package/LexicalTablePlugin.prod.js +4 -3
- package/LexicalTreeView.dev.js +10 -2
- package/LexicalTreeView.js.flow +19 -0
- package/LexicalTreeView.prod.js +9 -8
- package/README.md +0 -1
- package/package.json +5 -4
- package/useLexicalDecoratorMap.js.flow +16 -0
- package/useLexicalDecoratorMap.prod.js +1 -1
- package/useLexicalIsTextContentEmpty.js.flow +15 -0
- package/useLexicalIsTextContentEmpty.prod.js +1 -1
- package/useLexicalNodeSelection.dev.js +70 -0
- package/useLexicalNodeSelection.js +9 -0
- package/useLexicalNodeSelection.js.flow +14 -0
- package/useLexicalNodeSelection.prod.js +8 -0
- package/withSubscriptions.js.flow +13 -0
- package/withSubscriptions.prod.js +1 -1
- package/LexicalBootstrapPlugin.dev.js +0 -124
- package/LexicalBootstrapPlugin.js +0 -9
- package/LexicalBootstrapPlugin.prod.js +0 -8
- package/LexicalHorizontalRulePlugin.dev.js +0 -51
- package/LexicalHorizontalRulePlugin.js +0 -9
- 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
|
-
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
function
|
|
11
|
-
function
|
|
12
|
-
{tag:"historic"})}return!0;case "redo":return
|
|
13
|
-
r=null===m?null:m.editorState;if(null===m||
|
|
14
|
-
function
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
(
|
|
20
|
-
{w.$
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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
|
-
|
|
157
|
-
|
|
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: '
|
|
162
|
-
|
|
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
|
|
171
|
-
|
|
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
|
|
226
|
+
function getMatchResultContextWithRegEx(textToSearch, matchMustAppearAtStartOfString, matchMustAppearAtEndOfString, regEx) {
|
|
180
227
|
const matchResultContext = {
|
|
181
|
-
|
|
182
|
-
|
|
228
|
+
offsetInJoinedTextForCollapsedSelection: 0,
|
|
229
|
+
regExCaptureGroups: []
|
|
183
230
|
};
|
|
184
231
|
const regExMatches = textToSearch.match(regEx);
|
|
185
232
|
|
|
186
|
-
if (regExMatches !== null && regExMatches.length > 0 &&
|
|
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
|
|
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
|
-
}
|
|
241
|
-
|
|
286
|
+
}
|
|
242
287
|
|
|
243
|
-
return
|
|
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(
|
|
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 (
|
|
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
|
|
335
|
-
if (autoFormatCriteria.requiresParagraphStart) {
|
|
336
|
-
transformTextNodeForParagraphs(scanningContext
|
|
390
|
+
function transformTextNodeForAutoFormatCriteria(scanningContext) {
|
|
391
|
+
if (scanningContext.autoFormatCriteria.requiresParagraphStart) {
|
|
392
|
+
transformTextNodeForParagraphs(scanningContext);
|
|
337
393
|
} else {
|
|
338
|
-
transformTextNodeForText(scanningContext
|
|
394
|
+
transformTextNodeForText(scanningContext);
|
|
339
395
|
}
|
|
340
396
|
}
|
|
341
397
|
|
|
342
|
-
function transformTextNodeForParagraphs(scanningContext
|
|
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(
|
|
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
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
484
|
-
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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(),
|
|
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
|
-
|
|
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
|
|
685
|
+
function findScanningContext(editorState, currentTriggerState, priorTriggerState) {
|
|
565
686
|
if (currentTriggerState == null || priorTriggerState == null) {
|
|
566
|
-
return
|
|
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
|
-
|
|
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
|
|
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
|
|
743
|
+
const editorState = editor.getEditorState();
|
|
744
|
+
const currentTriggerState = getTriggerState(editorState);
|
|
745
|
+
const scanningContext = currentTriggerState == null ? null : findScanningContext(editorState, currentTriggerState, priorTriggerState);
|
|
618
746
|
|
|
619
|
-
if (
|
|
620
|
-
updateAutoFormatting(editor,
|
|
747
|
+
if (scanningContext != null) {
|
|
748
|
+
updateAutoFormatting(editor, scanningContext);
|
|
621
749
|
}
|
|
622
750
|
|
|
623
751
|
priorTriggerState = currentTriggerState;
|