UNPKG

@lexical/offset

Version:

This package contains selection offset helpers for Lexical.

10 lines (8 loc) 4.03 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import{$createChildrenArray as t,$getNodeByKey as e,$isTextNode as n,$createRangeSelection as o,$isElementNode as s}from"lexical";class l{_offsetMap;_firstNode;_blockOffsetSize;constructor(t,e,n=1){this._offsetMap=t,this._firstNode=e,this._blockOffsetSize=n}createSelectionFromOffsets(t,s,l){const f=this._firstNode;if(null===f)return null;let c=t,a=s,u=i(f,c,this._blockOffsetSize),d=i(f,a,this._blockOffsetSize);if(void 0!==l&&(c=r(c,u,l,this,this._blockOffsetSize),u=i(f,c,this._blockOffsetSize),a=r(a,d,l,this,this._blockOffsetSize),d=i(f,a,this._blockOffsetSize)),null===u||null===d)return null;let p=u.key,h=d.key;const g=e(p),k=e(h);if(null===g||null===k)return null;let y=0,v=0,_="element",x="element";if("text"===u.type){y=c-u.start,_="text";const t=g.getNextSibling();c!==a&&y===g.getTextContentSize()&&n(t)&&(y=0,p=t.__key)}else"inline"===u.type&&(p=g.getParentOrThrow().getKey(),y=a>u.start?u.end:u.start);"text"===d.type?(v=a-d.start,x="text"):"inline"===d.type&&(h=k.getParentOrThrow().getKey(),v=a>d.start?d.end:d.start);const S=o();return null===S?null:(S.anchor.set(p,y,_),S.focus.set(h,v,x),S)}getOffsetsFromSelection(t){const e=t.anchor,n=t.focus,o=this._offsetMap,s=e.offset,l=n.offset;let r=-1,i=-1;if("text"===e.type){const t=o.get(e.key);void 0!==t&&(r=t.start+s)}else{const t=e.getNode().getDescendantByIndex(s);if(null!==t){const e=o.get(t.getKey());if(void 0!==e){r=t.getIndexWithinParent()!==s?e.end:e.start}}}if("text"===n.type){const t=o.get(n.key);void 0!==t&&(i=t.start+n.offset)}else{const t=n.getNode().getDescendantByIndex(l);if(null!==t){const e=o.get(t.getKey());if(void 0!==e){i=t.getIndexWithinParent()!==l?e.end:e.start}}}return[r,i]}}function r(t,e,n,o,s){const l=n._offsetMap,r=o._offsetMap,f=new Set;let c=t,a=e;for(;null!==a;){const t=a.key,e=l.get(t),n=a.end-a.start;if(f.add(t),void 0===e)c+=n;else{const t=e.end-e.start;t!==n&&(c+=n-t)}const o=a.prev;if(null!==o){a=o;continue}let s=a.parent;for(;null!==s;){let t=s.prev;if(null!==t){const e=t.key,n=l.get(e),o=t.end-t.start;if(f.add(e),void 0===n)c+=o;else{const t=n.end-n.start;t!==o&&(c+=o-t)}t=t.prev}s=s.parent}break}const u=n._firstNode;if(null!==u){a=i(u,t,s);let e=!1;for(;null!==a;){if(!f.has(a.key)){e=!0;break}a=a.parent}if(!e)for(;null!==a;){const t=a.key;if(!f.has(t)){const e=r.get(t),n=a.end-a.start;if(void 0===e)c-=n;else{const t=e.end-e.start;n!==t&&(c+=t-n)}}a=a.prev}}return c}function i(t,e,n){let o=t;for(;null!==o;){if(e<o.end+("element"!==o.type||0===n?1:0)){const t=o.child;if(null!==t){o=t;continue}return o}const t=o.next;if(null===t)break;o=t}return null}function f(t,e,n,o,s,l){return{child:t,end:o,key:s,next:null,parent:l,prev:null,start:n,type:e}}function c(t,e,o,l,r,i){const c=l.get(e);void 0===c&&function(t,...e){const n=new URL("https://lexical.dev/docs/error"),o=new URLSearchParams;o.append("code",t);for(const t of e)o.append("v",t);throw n.search=o.toString(),Error(`Minified Lexical error #${t}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(3);const d=t.offset;if(s(c)){const n=u(c,l),s=0===n.length,p=s?null:a(t,n,null,l,r,i);t.prevIsBlock&&!s||(t.prevIsBlock=!0,t.offset+=i);const h=f(p,"element",d,d,e,o);null!==p&&(p.parent=h);const g=t.offset;return h.end=g,r.set(e,h),h}t.prevIsBlock=!1;const p=n(c),h=p?c.__text.length:1,g=f(null,p?"text":"inline",d,t.offset+=h,e,o);return r.set(e,g),g}function a(t,e,n,o,s,l){let r=null,i=null;const f=e.length;for(let a=0;a<f;a++){const f=c(t,e[a],n,o,s,l);null===i?r=f:(f.prev=i,i.next=f),i=f}return r}const u=t;function d(t,e=1,n){const o=(n||t._pendingEditorState||t._editorState)._nodeMap,s=o.get("root"),r=new Map,i=a({offset:0,prevIsBlock:!1},u(s,o),null,o,r,e);return new l(r,i,e)}export{u as $createChildrenArray,d as $createOffsetView,l as OffsetView};