@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
10 lines (8 loc) • 4.88 kB
JavaScript
/**
* 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{AutoLinkNode as t,$isAutoLinkNode as e,$isLinkNode as n,TOGGLE_LINK_COMMAND as r,$createAutoLinkNode as l}from"@lexical/link";import{useLexicalComposerContext as i}from"@lexical/react/LexicalComposerContext";import{mergeRegister as o}from"@lexical/utils";import{TextNode as s,$getSelection as u,$isRangeSelection as g,COMMAND_PRIORITY_LOW as c,$isTextNode as a,$isElementNode as f,$isLineBreakNode as x,$createTextNode as h,$isNodeSelection as p}from"lexical";import{useEffect as d}from"react";function m(t,e=(t=>t)){return n=>{const r=t.exec(n);return null===r?null:{index:r.index,length:r[0].length,text:r[0],url:e(r[0])}}}function T(t,e){for(let n=0;n<e.length;n++){const r=e[n](t);if(r)return r}return null}const C=/[.,;\s]/;function S(t){return C.test(t)}function b(t){return S(t[t.length-1])}function U(t){return S(t[0])}function v(t){let e=t.getPreviousSibling();return f(e)&&(e=e.getLastDescendant()),null===e||x(e)||a(e)&&b(e.getTextContent())}function L(t){let e=t.getNextSibling();return f(e)&&(e=e.getFirstDescendant()),null===e||x(e)||a(e)&&U(e.getTextContent())}function R(t,e,n,r){if(!(t>0?S(n[t-1]):v(r[0])))return!1;return e<n.length?S(n[e]):L(r[r.length-1])}function k(t,e,n){const r=[],l=[],i=[];let o=0,s=0;const u=[...t];for(;u.length>0;){const t=u[0],g=t.getTextContent().length,c=s;s+g<=e?(r.push(t),o+=g):c>=n?i.push(t):l.push(t),s+=g,u.shift()}return[o,r,l,i]}function D(t,e,n,r){const i=l(r.url,r.attributes);if(1===t.length){let l,o=t[0];0===e?[l,o]=o.splitText(n):[,l,o]=o.splitText(e,n);const s=h(r.text);return s.setFormat(l.getFormat()),s.setDetail(l.getDetail()),s.setStyle(l.getStyle()),i.append(s),l.replace(i),o}if(t.length>1){const r=t[0];let l,o=r.getTextContent().length;0===e?l=r:[,l]=r.splitText(e);const s=[];let c;for(let e=1;e<t.length;e++){const r=t[e],l=r.getTextContent().length,i=o;if(i<n)if(o+l<=n)s.push(r);else{const[t,e]=r.splitText(n-i);s.push(t),c=e}o+=l}const f=u(),x=f?f.getNodes().find(a):void 0,d=h(l.getTextContent());return d.setFormat(l.getFormat()),d.setDetail(l.getDetail()),d.setStyle(l.getStyle()),i.append(d,...s),x&&x===l&&(g(f)?d.select(f.anchor.offset,f.focus.offset):p(f)&&d.select(0,d.getTextContent().length)),l.replace(i),c}}function N(t,e,n){const r=t.getChildren(),l=r.length;for(let e=0;e<l;e++){const l=r[e];if(!a(l)||!l.isSimpleText())return I(t),void n(null,t.getURL())}const i=t.getTextContent(),o=T(i,e);if(null===o||o.text!==i)return I(t),void n(null,t.getURL());if(!v(t)||!L(t))return I(t),void n(null,t.getURL());const s=t.getURL();if(s!==o.url&&(t.setURL(o.url),n(o.url,s)),o.attributes){const e=t.getRel();e!==o.attributes.rel&&(t.setRel(o.attributes.rel||null),n(o.attributes.rel||null,e));const r=t.getTarget();r!==o.attributes.target&&(t.setTarget(o.attributes.target||null),n(o.attributes.target||null,r))}}function I(t){const e=t.getChildren();for(let n=e.length-1;n>=0;n--)t.insertAfter(e[n]);return t.remove(),e.map((t=>t.getLatest()))}function P(l,i,f){d((()=>{l.hasNodes([t])||function(t,...e){const n=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",t);for(const t of e)r.append("v",t);throw n.search=r.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.`)}(77);const x=(t,e)=>{f&&f(t,e)};return o(l.registerNodeTransform(s,(t=>{const r=t.getParentOrThrow(),l=t.getPreviousSibling();if(e(r)&&!r.getIsUnlinked())N(r,i,x);else if(!n(r)){if(t.isSimpleText()&&(U(t.getTextContent())||!e(l))){const e=function(t){const e=[t];let n=t.getNextSibling();for(;null!==n&&a(n)&&n.isSimpleText()&&(e.push(n),!/[\s]/.test(n.getTextContent()));)n=n.getNextSibling();return e}(t);!function(t,e,n){let r=[...t];const l=r.map((t=>t.getTextContent())).join("");let i,o=l,s=0;for(;(i=T(o,e))&&null!==i;){const t=i.index,e=t+i.length;if(R(s+t,s+e,l,r)){const[l,,o,u]=k(r,s+t,s+e),g=D(o,s+t-l,s+e-l,i);r=g?[g,...u]:u,n(i.url,null),s=0}else s+=e;o=o.substring(e)}}(e,i,x)}!function(t,n,r){const l=t.getPreviousSibling(),i=t.getNextSibling(),o=t.getTextContent();var s;!e(l)||l.getIsUnlinked()||U(o)&&(s=o,!(l.isEmailURI()?/^\.[a-zA-Z]{2,}/.test(s):/^\.[a-zA-Z0-9]{1,}/.test(s)))||(l.append(t),N(l,n,r),r(null,l.getURL())),!e(i)||i.getIsUnlinked()||b(o)||(I(i),N(i,n,r),r(null,i.getURL()))}(t,i,x)}})),l.registerCommand(r,(t=>{const n=u();if(null!==t||!g(n))return!1;return n.extract().forEach((t=>{const n=t.getParent();if(e(n))return n.setIsUnlinked(!n.getIsUnlinked()),n.markDirty(),!0})),!1}),c))}),[l,i,f])}function w({matchers:t,onChange:e}){const[n]=i();return P(n,t,e),null}export{w as AutoLinkPlugin,m as createLinkMatcherWithRegExp};