@lexical/link 0.47.1-nightly.20260715.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/LexicalLink.dev.js
CHANGED
|
@@ -111,6 +111,7 @@ class LinkNode extends lexical.ElementNode {
|
|
|
111
111
|
return super.updateFromJSON(serializedNode).setURL(serializedNode.url).setRel(serializedNode.rel || null).setTarget(serializedNode.target || null).setTitle(serializedNode.title || null);
|
|
112
112
|
}
|
|
113
113
|
sanitizeUrl(url) {
|
|
114
|
+
const rawUrl = url;
|
|
114
115
|
url = formatUrl(url);
|
|
115
116
|
try {
|
|
116
117
|
const parsedUrl = new URL(formatUrl(url));
|
|
@@ -118,7 +119,34 @@ class LinkNode extends lexical.ElementNode {
|
|
|
118
119
|
return 'about:blank';
|
|
119
120
|
}
|
|
120
121
|
} catch (_unused) {
|
|
121
|
-
|
|
122
|
+
// `new URL()` threw, so we could not verify the protocol via the
|
|
123
|
+
// parser. Preserve fail-secure behavior: default unparseable URLs to
|
|
124
|
+
// `about:blank` and only allow through inputs that positively match an
|
|
125
|
+
// allowlisted scheme.
|
|
126
|
+
//
|
|
127
|
+
// Check the ORIGINAL input, not the `formatUrl()` output: `formatUrl()`
|
|
128
|
+
// prepends `https://` to anything it does not recognize as already
|
|
129
|
+
// having a scheme, which would mask a control-character-obfuscated
|
|
130
|
+
// scheme (e.g. `java\x00script:` becomes `https://java\x00script:`).
|
|
131
|
+
//
|
|
132
|
+
// Before extracting the scheme, strip C0 control characters, DEL and
|
|
133
|
+
// whitespace, mirroring how browsers ignore these when resolving a
|
|
134
|
+
// scheme. Without this, control-character-obfuscated schemes that throw
|
|
135
|
+
// in `new URL()` but are still navigated by some browsers would slip
|
|
136
|
+
// past a naive scheme check and retain their original, attacker-
|
|
137
|
+
// controlled value. Stripping C0 control characters and DEL is the
|
|
138
|
+
// intended, security-relevant behavior here.
|
|
139
|
+
// eslint-disable-next-line no-control-regex
|
|
140
|
+
const normalizedUrl = rawUrl.replace(/[\u0000-\u001F\u007F\s]/g, '');
|
|
141
|
+
const schemeMatch = normalizedUrl.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
142
|
+
if (schemeMatch != null && !SUPPORTED_URL_PROTOCOLS.has(`${schemeMatch[1].toLowerCase()}:`)) {
|
|
143
|
+
// An explicit, non-allowlisted scheme survived normalization (e.g.
|
|
144
|
+
// `javascript:`, `data:`) — neutralize it. Inputs with no scheme
|
|
145
|
+
// (relative URLs such as `/path` or `#anchor`) or an allowlisted
|
|
146
|
+
// scheme are left unchanged: they cannot carry a dangerous scheme
|
|
147
|
+
// and are handled elsewhere.
|
|
148
|
+
return 'about:blank';
|
|
149
|
+
}
|
|
122
150
|
}
|
|
123
151
|
return url;
|
|
124
152
|
}
|
|
@@ -922,12 +950,14 @@ function registerClickableLink(editor, stores, eventOptions = {}) {
|
|
|
922
950
|
}
|
|
923
951
|
let url = null;
|
|
924
952
|
let urlTarget = null;
|
|
953
|
+
let isUnlinkedAutolink = false;
|
|
925
954
|
nearestEditor.update(() => {
|
|
926
955
|
const clickedNode = lexical.$getNearestNodeFromDOMNode(target);
|
|
927
956
|
if (clickedNode !== null) {
|
|
928
957
|
const maybeLinkNode = lexical.$findMatchingParent(clickedNode, lexical.$isElementNode);
|
|
929
958
|
if (!stores.disabled.peek()) {
|
|
930
959
|
if ($isLinkNode(maybeLinkNode)) {
|
|
960
|
+
isUnlinkedAutolink = $isAutoLinkNode(maybeLinkNode) && maybeLinkNode.getIsUnlinked();
|
|
931
961
|
url = maybeLinkNode.sanitizeUrl(maybeLinkNode.getURL());
|
|
932
962
|
urlTarget = maybeLinkNode.getTarget();
|
|
933
963
|
} else {
|
|
@@ -940,7 +970,7 @@ function registerClickableLink(editor, stores, eventOptions = {}) {
|
|
|
940
970
|
}
|
|
941
971
|
}
|
|
942
972
|
});
|
|
943
|
-
if (url === null || url === '') {
|
|
973
|
+
if (url === null || url === '' || isUnlinkedAutolink) {
|
|
944
974
|
return;
|
|
945
975
|
}
|
|
946
976
|
|
package/dist/LexicalLink.dev.mjs
CHANGED
|
@@ -109,6 +109,7 @@ class LinkNode extends ElementNode {
|
|
|
109
109
|
return super.updateFromJSON(serializedNode).setURL(serializedNode.url).setRel(serializedNode.rel || null).setTarget(serializedNode.target || null).setTitle(serializedNode.title || null);
|
|
110
110
|
}
|
|
111
111
|
sanitizeUrl(url) {
|
|
112
|
+
const rawUrl = url;
|
|
112
113
|
url = formatUrl(url);
|
|
113
114
|
try {
|
|
114
115
|
const parsedUrl = new URL(formatUrl(url));
|
|
@@ -116,7 +117,34 @@ class LinkNode extends ElementNode {
|
|
|
116
117
|
return 'about:blank';
|
|
117
118
|
}
|
|
118
119
|
} catch (_unused) {
|
|
119
|
-
|
|
120
|
+
// `new URL()` threw, so we could not verify the protocol via the
|
|
121
|
+
// parser. Preserve fail-secure behavior: default unparseable URLs to
|
|
122
|
+
// `about:blank` and only allow through inputs that positively match an
|
|
123
|
+
// allowlisted scheme.
|
|
124
|
+
//
|
|
125
|
+
// Check the ORIGINAL input, not the `formatUrl()` output: `formatUrl()`
|
|
126
|
+
// prepends `https://` to anything it does not recognize as already
|
|
127
|
+
// having a scheme, which would mask a control-character-obfuscated
|
|
128
|
+
// scheme (e.g. `java\x00script:` becomes `https://java\x00script:`).
|
|
129
|
+
//
|
|
130
|
+
// Before extracting the scheme, strip C0 control characters, DEL and
|
|
131
|
+
// whitespace, mirroring how browsers ignore these when resolving a
|
|
132
|
+
// scheme. Without this, control-character-obfuscated schemes that throw
|
|
133
|
+
// in `new URL()` but are still navigated by some browsers would slip
|
|
134
|
+
// past a naive scheme check and retain their original, attacker-
|
|
135
|
+
// controlled value. Stripping C0 control characters and DEL is the
|
|
136
|
+
// intended, security-relevant behavior here.
|
|
137
|
+
// eslint-disable-next-line no-control-regex
|
|
138
|
+
const normalizedUrl = rawUrl.replace(/[\u0000-\u001F\u007F\s]/g, '');
|
|
139
|
+
const schemeMatch = normalizedUrl.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
140
|
+
if (schemeMatch != null && !SUPPORTED_URL_PROTOCOLS.has(`${schemeMatch[1].toLowerCase()}:`)) {
|
|
141
|
+
// An explicit, non-allowlisted scheme survived normalization (e.g.
|
|
142
|
+
// `javascript:`, `data:`) — neutralize it. Inputs with no scheme
|
|
143
|
+
// (relative URLs such as `/path` or `#anchor`) or an allowlisted
|
|
144
|
+
// scheme are left unchanged: they cannot carry a dangerous scheme
|
|
145
|
+
// and are handled elsewhere.
|
|
146
|
+
return 'about:blank';
|
|
147
|
+
}
|
|
120
148
|
}
|
|
121
149
|
return url;
|
|
122
150
|
}
|
|
@@ -920,12 +948,14 @@ function registerClickableLink(editor, stores, eventOptions = {}) {
|
|
|
920
948
|
}
|
|
921
949
|
let url = null;
|
|
922
950
|
let urlTarget = null;
|
|
951
|
+
let isUnlinkedAutolink = false;
|
|
923
952
|
nearestEditor.update(() => {
|
|
924
953
|
const clickedNode = $getNearestNodeFromDOMNode(target);
|
|
925
954
|
if (clickedNode !== null) {
|
|
926
955
|
const maybeLinkNode = $findMatchingParent(clickedNode, $isElementNode);
|
|
927
956
|
if (!stores.disabled.peek()) {
|
|
928
957
|
if ($isLinkNode(maybeLinkNode)) {
|
|
958
|
+
isUnlinkedAutolink = $isAutoLinkNode(maybeLinkNode) && maybeLinkNode.getIsUnlinked();
|
|
929
959
|
url = maybeLinkNode.sanitizeUrl(maybeLinkNode.getURL());
|
|
930
960
|
urlTarget = maybeLinkNode.getTarget();
|
|
931
961
|
} else {
|
|
@@ -938,7 +968,7 @@ function registerClickableLink(editor, stores, eventOptions = {}) {
|
|
|
938
968
|
}
|
|
939
969
|
}
|
|
940
970
|
});
|
|
941
|
-
if (url === null || url === '') {
|
|
971
|
+
if (url === null || url === '' || isUnlinkedAutolink) {
|
|
942
972
|
return;
|
|
943
973
|
}
|
|
944
974
|
|
package/dist/LexicalLink.prod.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("@lexical/extension"),t=require("lexical"),n=require("@lexical/html"),r=require("@lexical/utils");const i=new Set(["http:","https:","mailto:","sms:","tel:"]);class s extends t.ElementNode{__url;__target;__rel;__title;static getType(){return"link"}static clone(e){return new s(e.__url,{rel:e.__rel,target:e.__target,title:e.__title},e.__key)}constructor(e="",t={},n){super(n);const{target:r=null,rel:i=null,title:s=null}=t;this.__url=e,this.__target=r,this.__rel=i,this.__title=s}afterCloneFrom(e){super.afterCloneFrom(e),this.__url=e.__url,this.__rel=e.__rel,this.__target=e.__target,this.__title=e.__title}createDOM(e){const n=t.$getDocument().createElement("a");return this.updateLinkDOM(null,n,e),t.addClassNamesToElement(n,e.theme.link),n}updateLinkDOM(e,n,r){if(t.isHTMLAnchorElement(n)){e&&e.__url===this.__url||(n.href=this.sanitizeUrl(this.__url));for(const t of["target","rel","title"]){const r=`__${t}`,i=this[r];e&&e[r]===i||(i?n[t]=i:n.removeAttribute(t))}}}updateDOM(e,t,n){return this.updateLinkDOM(e,t,n),!1}static importDOM(){return{a:e=>({conversion:u,priority:1})}}static importJSON(e){return c().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setURL(e.url).setRel(e.rel||null).setTarget(e.target||null).setTitle(e.title||null)}sanitizeUrl(e){e=N(e);try{const t=new URL(N(e));if(!i.has(t.protocol))return"about:blank"}catch(t){return e}return e}exportJSON(){return{...super.exportJSON(),rel:this.getRel(),target:this.getTarget(),title:this.getTitle(),url:this.getURL()}}getURL(){return this.getLatest().__url}setURL(e){const t=this.getWritable();return t.__url=e,t}getTarget(){return this.getLatest().__target}setTarget(e){const t=this.getWritable();return t.__target=e,t}getRel(){return this.getLatest().__rel}setRel(e){const t=this.getWritable();return t.__rel=e,t}getTitle(){return this.getLatest().__title}setTitle(e){const t=this.getWritable();return t.__title=e,t}insertNewAfter(e,n=!0){const r=t.$copyNode(this);return this.insertAfter(r,n),r}canInsertTextBefore(){return!1}canInsertTextAfter(){return!1}canBeEmpty(){return!1}isInline(){return!0}extractWithChild(e,n,r){if(!t.$isRangeSelection(n))return!1;const i=n.anchor.getNode(),s=n.focus.getNode();return(this.is(i)||this.isParentOf(i))&&(this.is(s)||this.isParentOf(s))&&n.getTextContent().length>0}isEmailURI(){return this.__url.startsWith("mailto:")}isWebSiteURI(){return this.__url.startsWith("https://")||this.__url.startsWith("http://")}shouldMergeAdjacentLink(e){return this.getType()===e.getType()&&this.__url===e.__url&&this.__target===e.__target&&this.__rel===e.__rel&&this.__title===e.__title}}function l(e){const n=t.$caretFromPoint(e,"next");return[n,n.getFlipped()]}function o(e,n){for(const r of n)if(r.origin.isAttached()){const n=t.$normalizeCaret(r);return void t.$setPointFromCaret(e,n)}}function a(e){const n=t.$getSelection();let r=null,i=null;function s(){t.$isRangeSelection(n)&&(o(n.anchor,r),o(n.focus,i),t.$normalizeSelection__EXPERIMENTAL(n))}t.$isRangeSelection(n)&&(r=l(n.anchor),i=l(n.focus));let a=!1;for(const n of t.$getChildCaret(e,"next")){const r=n.origin;if(t.$isElementNode(r)&&!r.isInline()){const i=r.getChildren();if(i.length>0){const n=t.$copyNode(e);n.append(...i),r.append(n),a=!0}t.$insertNodeToNearestRootAtCaret(r,t.$rewindSiblingCaret(n),{$shouldSplit:()=>!1})}}function u(e,n,r){const[i,s]=e,l=e=>t.$isSiblingCaret(e)&&e.origin.is(n);if(!l(i)&&!l(s))return e;const o=t.$normalizeCaret(t.$getChildCaret(r,"next"));return[o,o.getFlipped()]}if(e.isAttached()){const t=e.getPreviousSibling();if(g(t)&&t.shouldMergeAdjacentLink(e))return r&&(r=u(r,t,e)),i&&(i=u(i,t,e)),t.append(...e.getChildren()),e.remove(),void s();const n=e.getNextSibling();g(n)&&e.shouldMergeAdjacentLink(n)&&(r&&(r=u(r,e,n)),i&&(i=u(i,e,n)),e.append(...n.getChildren()),n.remove(),a=!0)}if(a){if(!e.canBeEmpty()&&e.isEmpty()){const t=e.getParent();e.remove(),t&&t.isEmpty()&&t.remove()}s()}}function u(e){let n=null;if(t.isHTMLAnchorElement(e)){const t=e.textContent;(null!==t&&""!==t||e.children.length>0)&&(n=c(e.getAttribute("href")||"",{rel:e.getAttribute("rel"),target:e.getAttribute("target"),title:e.getAttribute("title")}))}return{node:n}}function c(e="",n){return t.$applyNodeReplacement(new s(e,n))}function g(e){return e instanceof s}class d extends s{__isUnlinked;constructor(e="",t={},n){super(e,t,n),this.__isUnlinked=void 0!==t.isUnlinked&&null!==t.isUnlinked&&t.isUnlinked}afterCloneFrom(e){super.afterCloneFrom(e),this.__isUnlinked=e.__isUnlinked}static getType(){return"autolink"}static clone(e){return new d(e.__url,{isUnlinked:e.__isUnlinked,rel:e.__rel,target:e.__target,title:e.__title},e.__key)}shouldMergeAdjacentLink(e){return!1}getIsUnlinked(){return this.__isUnlinked}setIsUnlinked(e){const t=this.getWritable();return t.__isUnlinked=e,t}createDOM(e){return this.__isUnlinked?t.$getDocument().createElement("span"):super.createDOM(e)}updateDOM(e,t,n){return super.updateDOM(e,t,n)||e.__isUnlinked!==this.__isUnlinked}static importJSON(e){return f().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setIsUnlinked(e.isUnlinked||!1)}static importDOM(){return null}exportJSON(){return{...super.exportJSON(),isUnlinked:this.__isUnlinked}}insertNewAfter(e,t=!0){const n=f(this.__url,{isUnlinked:this.__isUnlinked,rel:this.__rel,target:this.__target,title:this.__title});return this.insertAfter(n,t),n}}function f(e="",n){return t.$applyNodeReplacement(new d(e,n))}function h(e){return e instanceof d}const p=/* @__PURE__ */t.createCommand("TOGGLE_LINK_COMMAND");function _(e,n){if("element"===e.type){const r=e.getNode();t.$isElementNode(r)||function(e,...t){const n=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",e);for(const e of t)r.append("v",e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(252);return r.getChildren()[e.offset+n]||null}return null}function m(e,n={}){let r;if(e&&"object"==typeof e){const{url:t,...i}=e;r=t,n={...i,...n}}else r=e;const{target:i,title:s}=n,l=void 0===n.rel?"noreferrer":n.rel,o=t.$getSelection();if(null===o||!t.$isRangeSelection(o)&&!t.$isNodeSelection(o))return;if(t.$isNodeSelection(o)){const e=o.getNodes();if(0===e.length)return;return void e.forEach(e=>{if(null===r){const n=t.$findMatchingParent(e,e=>!h(e)&&g(e));n&&(n.insertBefore(e),0===n.getChildren().length&&n.remove())}else{const n=t.$findMatchingParent(e,e=>!h(e)&&g(e));if(n)n.setURL(r),void 0!==i&&n.setTarget(i),void 0!==l&&n.setRel(l);else{const t=c(r,{rel:l,target:i});e.insertBefore(t),t.append(e)}}})}if(o.isCollapsed()&&null===r)for(const e of o.getNodes()){const n=t.$findMatchingParent(e,e=>!h(e)&&g(e));return void(null!==n&&(n.getParentOrThrow().splice(n.getIndexWithinParent(),0,n.getChildren()),n.remove()))}const a=o.extract();if(null===r){const e=new Set;return void a.forEach(n=>{const r=t.$findMatchingParent(n,e=>!h(e)&&g(e));if(null!==r){const n=r.getKey();if(e.has(n))return;!function(e,n){const r=new Set(n.filter(t=>e.isParentOf(t)).map(e=>e.getKey())),i=e.getChildren(),s=i=>r.has(i.getKey())||t.$isElementNode(i)&&n.some(t=>e.isParentOf(t)&&i.isParentOf(t)),l=i.filter(s);if(l.length===i.length)return i.forEach(t=>e.insertBefore(t)),void e.remove();const o=i.findIndex(s),a=i.findLastIndex(s),u=0===o,c=a===i.length-1;if(u)l.forEach(t=>e.insertBefore(t));else if(c)for(let t=l.length-1;t>=0;t--)e.insertAfter(l[t]);else{for(let t=l.length-1;t>=0;t--)e.insertAfter(l[t]);const n=i.slice(a+1);if(n.length>0){const r=t.$copyNode(e);l[l.length-1].insertAfter(r),n.forEach(e=>r.append(e))}}}(r,a),e.add(n)}})}const u=new Set,d=e=>{u.has(e.getKey())||(u.add(e.getKey()),e.setURL(r),void 0!==i&&e.setTarget(i),void 0!==l&&e.setRel(l),void 0!==s&&e.setTitle(s))};if(1===a.length){const e=a[0],n=t.$findMatchingParent(e,g);if(null!==n)return d(n)}!function(e){const n=t.$getSelection();if(!t.$isRangeSelection(n))return e();const r=t.$normalizeSelection__EXPERIMENTAL(n),i=r.isBackward(),s=_(r.anchor,i?-1:0),l=_(r.focus,i?0:-1),o=e();if(s||l){const e=t.$getSelection();if(t.$isRangeSelection(e)){const n=e.clone();if(s){const e=s.getParent();e&&n.anchor.set(e.getKey(),s.getIndexWithinParent()+(i?1:0),"element")}if(l){const e=l.getParent();e&&n.focus.set(e.getKey(),l.getIndexWithinParent()+(i?0:1),"element")}t.$setSelection(t.$normalizeSelection__EXPERIMENTAL(n))}}}(()=>{let e=null;for(const n of a){if(!n.isAttached())continue;const o=t.$findMatchingParent(n,g);if(o){d(o);continue}if(t.$isElementNode(n)){if(!n.isInline())continue;if(g(n)){if(!(h(n)||null!==e&&e.getParentOrThrow().isParentOf(n))){d(n),e=n;continue}for(const e of n.getChildren())n.insertBefore(e);n.remove();continue}}const a=n.getPreviousSibling();g(a)&&a.is(e)?a.append(n):(e=c(r,{rel:l,target:i,title:s}),n.insertAfter(e),e.append(n))}})}const x=/^\+?[0-9\s()-]{5,}$/;function N(e){return e.match(/^[a-z][a-z0-9+.-]*:/i)||e.match(/^[/#.]/)?e:e.includes("@")?`mailto:${e}`:x.test(e)?`tel:${e}`:`https://${e}`}const $=[/* @__PURE__ */n.defineImportRule({$import:(e,t)=>{if(!t.textContent&&0===t.children.length)return[];const r=t.getAttribute("href")||"",i={rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.getAttribute("title")};return n.$distributeInlineWrapper(e.$importChildren(t),()=>c(r,i))},match:n.sel.tag("a"),name:"@lexical/link/a"})],k={attributes:void 0,validateUrl:void 0};function L(n,i){return t.mergeRegister(n.registerNodeTransform(s,a),n.registerCommand(p,e=>{const t=i.validateUrl.peek(),n=i.attributes.peek();if(null===e)return m(null),!0;if("string"==typeof e)return!(void 0!==t&&!t(e))&&(m(e,n),!0);{const{url:t,target:r,rel:i,title:s}=e;return m(t,{...n,rel:i,target:r,title:s}),!0}},t.COMMAND_PRIORITY_EDITOR),e.effect(()=>{const e=i.validateUrl.value;if(!e)return;const s=i.attributes.value;return n.registerCommand(t.PASTE_COMMAND,i=>{const l=t.$getSelection();if(!t.$isRangeSelection(l)||l.isCollapsed()||!r.objectKlassEquals(i,ClipboardEvent))return!1;if(null===i.clipboardData)return!1;const o=i.clipboardData.getData("text");if(!e(o))return!1;return!l.getNodes().some(e=>t.$isElementNode(e)||t.$isTextNode(e)&&!e.isSimpleText())&&(n.dispatchCommand(p,{...s,url:o}),i.preventDefault(),!0)},t.COMMAND_PRIORITY_LOW)}))}const T=/* @__PURE__ */t.defineExtension({build:(t,n,r)=>e.namedSignals(n),config:k,dependencies:[n.CoreImportExtension,/* @__PURE__ */t.configExtension(n.DOMImportExtension,{rules:$})],mergeConfig(e,n){const r=t.shallowMergeConfig(e,n);return e.attributes&&(r.attributes=t.shallowMergeConfig(e.attributes,r.attributes)),r},name:"@lexical/link/Link",nodes:()=>[s],register:(e,t,n)=>L(e,n.getOutput())}),S=/* @__PURE__ */t.defineExtension({dependencies:[T],name:"@lexical/link/Import"});function b(e,n,r={}){const i=r=>{const i=r.target;if(!t.isDOMNode(i))return;const s=t.getNearestEditorFromDOMNode(i);if(null===s)return;let l=null,o=null;if(s.update(()=>{const e=t.$getNearestNodeFromDOMNode(i);if(null!==e){const r=t.$findMatchingParent(e,t.$isElementNode);if(!n.disabled.peek())if(g(r))l=r.sanitizeUrl(r.getURL()),o=r.getTarget();else{const e=function(e,t){let n=e;for(;null!=n;){if(t(n))return n;n=n.parentNode}return null}(i,t.isHTMLAnchorElement);null!==e&&(l=e.href,o=e.target)}}}),null===l||""===l)return;const a=e.read("latest",t.$getSelection);if(t.$isRangeSelection(a)&&!a.isCollapsed())return void r.preventDefault();const u="auxclick"===r.type&&1===r.button;window.open(l,n.newTab.peek()||u||r.metaKey||r.ctrlKey||"_blank"===o?"_blank":"_self"),r.preventDefault()},s=e=>{1===e.button&&i(e)};return e.registerRootListener(e=>{if(e)return t.registerEventListeners(e,{click:i,mouseup:s},r)})}const C=/* @__PURE__ */t.defineExtension({build:(t,n,r)=>e.namedSignals(n),config:/* @__PURE__ */t.safeCast({disabled:!1,newTab:!1}),dependencies:[T],name:"@lexical/link/ClickableLink",register:(e,t,n)=>b(e,n.getOutput())});function R(e,t=e=>e){return n=>{const r=e.exec(n);return null===r?null:{index:r.index,length:r[0].length,text:r[0],url:t(r[0])}}}const E=/((https?:\/\/(www\.)?)|(www\.))[-\p{L}\p{N}@:%._+~#=]{1,256}\.[\p{L}\p{N}]{1,6}(?:[-\p{L}\p{N}()@:%_+.~#?&//=]*[\p{L}\p{N}()@_~#?&//=])?/u,U=R(/(([^<>()[\]\\.,;:\s@"]{1,64}(\.[^<>()[\]\\.,;:\s@"]{1,64}){0,63})|(".{1,255}"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]{1,63}\.){1,127}[a-zA-Z]{2,63}))/,e=>`mailto:${e}`);function v(e,t){for(let n=0;n<t.length;n++){const r=t[n](e);if(r)return r}return null}const A=/[.,;\s]/;function O(e,t){return t.test(e)}function M(e,t){return O(e[e.length-1],t)}function P(e,t){return O(e[0],t)}function I(e,n){let r=e.getPreviousSibling();return t.$isElementNode(r)&&(r=r.getLastDescendant()),null===r||t.$isLineBreakNode(r)||t.$isTextNode(r)&&M(r.getTextContent(),n)}function y(e,n){let r=e.getNextSibling();return t.$isElementNode(r)&&(r=r.getFirstDescendant()),null===r||t.$isLineBreakNode(r)||t.$isTextNode(r)&&P(r.getTextContent(),n)}function D(e,t,n,r,i){if(!(e>0?O(r[e-1],n):I(i[0],n)))return!1;return t<r.length?O(r[t],n):y(i[i.length-1],n)}function w(e,t,n){const r=[],i=[],s=[];let l=0,o=0;const a=[...e];for(;a.length>0;){const e=a[0],u=e.getTextContent().length,c=o;o+u<=t?(r.push(e),l+=u):c>=n?s.push(e):i.push(e),o+=u,a.shift()}return[l,r,i,s]}function F(e,n,r,i){const s=f(i.url,i.attributes);if(1===e.length){let l,o=e[0];0===n?[l,o]=o.splitText(r):[,l,o]=o.splitText(n,r);const a=t.$createTextNode(i.text);return a.setFormat(l.getFormat()),a.setDetail(l.getDetail()),a.setStyle(l.getStyle()),s.append(a),l.replace(s),o}if(e.length>1){const i=e[0];let l,o=i.getTextContent().length;0===n?l=i:[,l]=i.splitText(n);const a=[];let u;for(let t=1;t<e.length;t++){const n=e[t],i=n.getTextContent().length,s=o;if(s<r)if(o+i<=r)a.push(n);else{const[e,t]=n.splitText(r-s);a.push(e),u=t}o+=i}const c=t.$getSelection(),g=c?c.getNodes().find(t.$isTextNode):void 0,d=t.$createTextNode(l.getTextContent());return d.setFormat(l.getFormat()),d.setDetail(l.getDetail()),d.setStyle(l.getStyle()),s.append(d,...a),g&&g===l&&(t.$isRangeSelection(c)?d.select(c.anchor.offset,c.focus.offset):t.$isNodeSelection(c)&&d.select(0,d.getTextContent().length)),l.replace(s),u}}function W(e,n,r,i){const s=e.getChildren(),l=s.length;for(let n=0;n<l;n++){const i=s[n];if(!t.$isTextNode(i)||!i.isSimpleText())return z(e),void r(null,e.getURL())}const o=e.getTextContent(),a=v(o,n);if(null===a||a.text!==o)return z(e),void r(null,e.getURL());if(!I(e,i)||!y(e,i))return z(e),void r(null,e.getURL());const u=e.getURL();if(u!==a.url&&(e.setURL(a.url),r(a.url,u)),a.attributes){const t=e.getRel();t!==a.attributes.rel&&(e.setRel(a.attributes.rel||null),r(a.attributes.rel||null,t));const n=e.getTarget();n!==a.attributes.target&&(e.setTarget(a.attributes.target||null),r(a.attributes.target||null,n))}}function z(e){const t=e.getChildren();for(let n=t.length-1;n>=0;n--)e.insertAfter(t[n]);return e.remove(),t.map(e=>e.getLatest())}const J={changeHandlers:[],excludeParents:[],matchers:[],separatorRegex:A};function K(e,n=J){const{matchers:r,changeHandlers:i,excludeParents:s,separatorRegex:l=A}=n,o=(e,t)=>{for(const n of i)n(e,t)};return t.mergeRegister(e.registerNodeTransform(t.TextNode,e=>{const n=e.getParentOrThrow(),i=e.getPreviousSibling();if(h(n))W(n,r,o,l);else if(!g(n)&&!s.some(e=>e(n))){if(e.isSimpleText()&&(P(e.getTextContent(),l)||!h(i))){const n=function(e){const n=[e];let r=e.getNextSibling();for(;null!==r&&t.$isTextNode(r)&&r.isSimpleText()&&(n.push(r),!/[\s]/.test(r.getTextContent()));)r=r.getNextSibling();return n}(e);!function(e,t,n,r){for(const t of e){const e=t.getParent();if(h(e)&&!e.getIsUnlinked())return}let i=[...e];const s=i.map(e=>e.getTextContent()).join("");let l,o=s,a=0;for(;(l=v(o,t))&&null!==l;){const e=l.index,t=e+l.length;if(D(a+e,a+t,r,s,i)){const[r,,s,u]=w(i,a+e,a+t);let c=!1;for(const e of s){const t=e.getParent();if(h(t)&&!t.getIsUnlinked()){c=!0;break}}if(c){a+=t,o=o.substring(t);continue}const g=F(s,a+e-r,a+t-r,l);i=g?[g,...u]:u,n(l.url,null),a=0}else a+=t;o=o.substring(t)}}(n,r,o,l)}!function(e,t,n,r){const i=e.getParent(),s=e.getPreviousSibling(),l=e.getNextSibling(),o=e.getTextContent();if(!h(i)||i.getIsUnlinked()){if(h(s)&&!s.getIsUnlinked()&&s.is(e.getPreviousSibling())&&e.getParent()===s.getParent()){if(!P(o,r))return z(s),void n(null,s.getURL());if(a=o,s.isEmailURI()?/^\.[a-zA-Z]{2,}/.test(a):/^\.[a-zA-Z0-9]{1,}/.test(a)){const i=s.getTextContent()+o,l=v(i,t);null!==l&&l.text===i&&(s.append(e),W(s,t,n,r),n(null,s.getURL()))}}var a;!h(l)||l.getIsUnlinked()||M(o,r)||l.is(e.getNextSibling())&&e.getParent()===l.getParent()&&(z(l),n(null,l.getURL()))}}(e,r,o,l)}}),e.registerCommand(p,e=>{const n=t.$getSelection();if(null!==e||!t.$isRangeSelection(n))return!1;return n.extract().forEach(e=>{const t=e.getParent();h(t)&&(t.setIsUnlinked(!t.getIsUnlinked()),t.markDirty())}),!1},t.COMMAND_PRIORITY_LOW))}const B=/* @__PURE__ */t.defineExtension({config:J,dependencies:[T],mergeConfig(e,n){const r=t.shallowMergeConfig(e,n);for(const t of["matchers","changeHandlers","excludeParents"]){const i=n[t];Array.isArray(i)&&(r[t]=[...e[t],...i])}return r},name:"@lexical/link/AutoLink",nodes:[d],register:K});exports.$createAutoLinkNode=f,exports.$createLinkNode=c,exports.$isAutoLinkNode=h,exports.$isLinkNode=g,exports.$toggleLink=m,exports.AutoLinkExtension=B,exports.AutoLinkNode=d,exports.ClickableLinkExtension=C,exports.LinkExtension=T,exports.LinkImportExtension=S,exports.LinkImportRules=$,exports.LinkNode=s,exports.TOGGLE_LINK_COMMAND=p,exports.autoLinkEmailMatcher=U,exports.autoLinkUrlMatcher=e=>{const t=E.exec(e);if(null===t)return null;let n=t[0],r=0;for(const e of n)"("===e?r++:")"===e&&r--;for(;r<0&&n.endsWith(")");)n=n.slice(0,-1),r++;return{index:t.index,length:n.length,text:n,url:n.startsWith("http")?n:`https://${n}`}},exports.createLinkMatcherWithRegExp=R,exports.formatUrl=N,exports.registerAutoLink=K,exports.registerClickableLink=b,exports.registerLink=L;
|
|
9
|
+
"use strict";var e=require("@lexical/extension"),t=require("lexical"),n=require("@lexical/html"),r=require("@lexical/utils");const i=new Set(["http:","https:","mailto:","sms:","tel:"]);class s extends t.ElementNode{__url;__target;__rel;__title;static getType(){return"link"}static clone(e){return new s(e.__url,{rel:e.__rel,target:e.__target,title:e.__title},e.__key)}constructor(e="",t={},n){super(n);const{target:r=null,rel:i=null,title:s=null}=t;this.__url=e,this.__target=r,this.__rel=i,this.__title=s}afterCloneFrom(e){super.afterCloneFrom(e),this.__url=e.__url,this.__rel=e.__rel,this.__target=e.__target,this.__title=e.__title}createDOM(e){const n=t.$getDocument().createElement("a");return this.updateLinkDOM(null,n,e),t.addClassNamesToElement(n,e.theme.link),n}updateLinkDOM(e,n,r){if(t.isHTMLAnchorElement(n)){e&&e.__url===this.__url||(n.href=this.sanitizeUrl(this.__url));for(const t of["target","rel","title"]){const r=`__${t}`,i=this[r];e&&e[r]===i||(i?n[t]=i:n.removeAttribute(t))}}}updateDOM(e,t,n){return this.updateLinkDOM(e,t,n),!1}static importDOM(){return{a:e=>({conversion:u,priority:1})}}static importJSON(e){return c().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setURL(e.url).setRel(e.rel||null).setTarget(e.target||null).setTitle(e.title||null)}sanitizeUrl(e){const t=e;e=N(e);try{const t=new URL(N(e));if(!i.has(t.protocol))return"about:blank"}catch(e){const n=t.replace(/[\u0000-\u001F\u007F\s]/g,"").match(/^([a-z][a-z0-9+.-]*):/i);if(null!=n&&!i.has(`${n[1].toLowerCase()}:`))return"about:blank"}return e}exportJSON(){return{...super.exportJSON(),rel:this.getRel(),target:this.getTarget(),title:this.getTitle(),url:this.getURL()}}getURL(){return this.getLatest().__url}setURL(e){const t=this.getWritable();return t.__url=e,t}getTarget(){return this.getLatest().__target}setTarget(e){const t=this.getWritable();return t.__target=e,t}getRel(){return this.getLatest().__rel}setRel(e){const t=this.getWritable();return t.__rel=e,t}getTitle(){return this.getLatest().__title}setTitle(e){const t=this.getWritable();return t.__title=e,t}insertNewAfter(e,n=!0){const r=t.$copyNode(this);return this.insertAfter(r,n),r}canInsertTextBefore(){return!1}canInsertTextAfter(){return!1}canBeEmpty(){return!1}isInline(){return!0}extractWithChild(e,n,r){if(!t.$isRangeSelection(n))return!1;const i=n.anchor.getNode(),s=n.focus.getNode();return(this.is(i)||this.isParentOf(i))&&(this.is(s)||this.isParentOf(s))&&n.getTextContent().length>0}isEmailURI(){return this.__url.startsWith("mailto:")}isWebSiteURI(){return this.__url.startsWith("https://")||this.__url.startsWith("http://")}shouldMergeAdjacentLink(e){return this.getType()===e.getType()&&this.__url===e.__url&&this.__target===e.__target&&this.__rel===e.__rel&&this.__title===e.__title}}function l(e){const n=t.$caretFromPoint(e,"next");return[n,n.getFlipped()]}function o(e,n){for(const r of n)if(r.origin.isAttached()){const n=t.$normalizeCaret(r);return void t.$setPointFromCaret(e,n)}}function a(e){const n=t.$getSelection();let r=null,i=null;function s(){t.$isRangeSelection(n)&&(o(n.anchor,r),o(n.focus,i),t.$normalizeSelection__EXPERIMENTAL(n))}t.$isRangeSelection(n)&&(r=l(n.anchor),i=l(n.focus));let a=!1;for(const n of t.$getChildCaret(e,"next")){const r=n.origin;if(t.$isElementNode(r)&&!r.isInline()){const i=r.getChildren();if(i.length>0){const n=t.$copyNode(e);n.append(...i),r.append(n),a=!0}t.$insertNodeToNearestRootAtCaret(r,t.$rewindSiblingCaret(n),{$shouldSplit:()=>!1})}}function u(e,n,r){const[i,s]=e,l=e=>t.$isSiblingCaret(e)&&e.origin.is(n);if(!l(i)&&!l(s))return e;const o=t.$normalizeCaret(t.$getChildCaret(r,"next"));return[o,o.getFlipped()]}if(e.isAttached()){const t=e.getPreviousSibling();if(g(t)&&t.shouldMergeAdjacentLink(e))return r&&(r=u(r,t,e)),i&&(i=u(i,t,e)),t.append(...e.getChildren()),e.remove(),void s();const n=e.getNextSibling();g(n)&&e.shouldMergeAdjacentLink(n)&&(r&&(r=u(r,e,n)),i&&(i=u(i,e,n)),e.append(...n.getChildren()),n.remove(),a=!0)}if(a){if(!e.canBeEmpty()&&e.isEmpty()){const t=e.getParent();e.remove(),t&&t.isEmpty()&&t.remove()}s()}}function u(e){let n=null;if(t.isHTMLAnchorElement(e)){const t=e.textContent;(null!==t&&""!==t||e.children.length>0)&&(n=c(e.getAttribute("href")||"",{rel:e.getAttribute("rel"),target:e.getAttribute("target"),title:e.getAttribute("title")}))}return{node:n}}function c(e="",n){return t.$applyNodeReplacement(new s(e,n))}function g(e){return e instanceof s}class d extends s{__isUnlinked;constructor(e="",t={},n){super(e,t,n),this.__isUnlinked=void 0!==t.isUnlinked&&null!==t.isUnlinked&&t.isUnlinked}afterCloneFrom(e){super.afterCloneFrom(e),this.__isUnlinked=e.__isUnlinked}static getType(){return"autolink"}static clone(e){return new d(e.__url,{isUnlinked:e.__isUnlinked,rel:e.__rel,target:e.__target,title:e.__title},e.__key)}shouldMergeAdjacentLink(e){return!1}getIsUnlinked(){return this.__isUnlinked}setIsUnlinked(e){const t=this.getWritable();return t.__isUnlinked=e,t}createDOM(e){return this.__isUnlinked?t.$getDocument().createElement("span"):super.createDOM(e)}updateDOM(e,t,n){return super.updateDOM(e,t,n)||e.__isUnlinked!==this.__isUnlinked}static importJSON(e){return f().updateFromJSON(e)}updateFromJSON(e){return super.updateFromJSON(e).setIsUnlinked(e.isUnlinked||!1)}static importDOM(){return null}exportJSON(){return{...super.exportJSON(),isUnlinked:this.__isUnlinked}}insertNewAfter(e,t=!0){const n=f(this.__url,{isUnlinked:this.__isUnlinked,rel:this.__rel,target:this.__target,title:this.__title});return this.insertAfter(n,t),n}}function f(e="",n){return t.$applyNodeReplacement(new d(e,n))}function h(e){return e instanceof d}const p=/* @__PURE__ */t.createCommand("TOGGLE_LINK_COMMAND");function _(e,n){if("element"===e.type){const r=e.getNode();t.$isElementNode(r)||function(e,...t){const n=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",e);for(const e of t)r.append("v",e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(252);return r.getChildren()[e.offset+n]||null}return null}function m(e,n={}){let r;if(e&&"object"==typeof e){const{url:t,...i}=e;r=t,n={...i,...n}}else r=e;const{target:i,title:s}=n,l=void 0===n.rel?"noreferrer":n.rel,o=t.$getSelection();if(null===o||!t.$isRangeSelection(o)&&!t.$isNodeSelection(o))return;if(t.$isNodeSelection(o)){const e=o.getNodes();if(0===e.length)return;return void e.forEach(e=>{if(null===r){const n=t.$findMatchingParent(e,e=>!h(e)&&g(e));n&&(n.insertBefore(e),0===n.getChildren().length&&n.remove())}else{const n=t.$findMatchingParent(e,e=>!h(e)&&g(e));if(n)n.setURL(r),void 0!==i&&n.setTarget(i),void 0!==l&&n.setRel(l);else{const t=c(r,{rel:l,target:i});e.insertBefore(t),t.append(e)}}})}if(o.isCollapsed()&&null===r)for(const e of o.getNodes()){const n=t.$findMatchingParent(e,e=>!h(e)&&g(e));return void(null!==n&&(n.getParentOrThrow().splice(n.getIndexWithinParent(),0,n.getChildren()),n.remove()))}const a=o.extract();if(null===r){const e=new Set;return void a.forEach(n=>{const r=t.$findMatchingParent(n,e=>!h(e)&&g(e));if(null!==r){const n=r.getKey();if(e.has(n))return;!function(e,n){const r=new Set(n.filter(t=>e.isParentOf(t)).map(e=>e.getKey())),i=e.getChildren(),s=i=>r.has(i.getKey())||t.$isElementNode(i)&&n.some(t=>e.isParentOf(t)&&i.isParentOf(t)),l=i.filter(s);if(l.length===i.length)return i.forEach(t=>e.insertBefore(t)),void e.remove();const o=i.findIndex(s),a=i.findLastIndex(s),u=0===o,c=a===i.length-1;if(u)l.forEach(t=>e.insertBefore(t));else if(c)for(let t=l.length-1;t>=0;t--)e.insertAfter(l[t]);else{for(let t=l.length-1;t>=0;t--)e.insertAfter(l[t]);const n=i.slice(a+1);if(n.length>0){const r=t.$copyNode(e);l[l.length-1].insertAfter(r),n.forEach(e=>r.append(e))}}}(r,a),e.add(n)}})}const u=new Set,d=e=>{u.has(e.getKey())||(u.add(e.getKey()),e.setURL(r),void 0!==i&&e.setTarget(i),void 0!==l&&e.setRel(l),void 0!==s&&e.setTitle(s))};if(1===a.length){const e=a[0],n=t.$findMatchingParent(e,g);if(null!==n)return d(n)}!function(e){const n=t.$getSelection();if(!t.$isRangeSelection(n))return e();const r=t.$normalizeSelection__EXPERIMENTAL(n),i=r.isBackward(),s=_(r.anchor,i?-1:0),l=_(r.focus,i?0:-1),o=e();if(s||l){const e=t.$getSelection();if(t.$isRangeSelection(e)){const n=e.clone();if(s){const e=s.getParent();e&&n.anchor.set(e.getKey(),s.getIndexWithinParent()+(i?1:0),"element")}if(l){const e=l.getParent();e&&n.focus.set(e.getKey(),l.getIndexWithinParent()+(i?0:1),"element")}t.$setSelection(t.$normalizeSelection__EXPERIMENTAL(n))}}}(()=>{let e=null;for(const n of a){if(!n.isAttached())continue;const o=t.$findMatchingParent(n,g);if(o){d(o);continue}if(t.$isElementNode(n)){if(!n.isInline())continue;if(g(n)){if(!(h(n)||null!==e&&e.getParentOrThrow().isParentOf(n))){d(n),e=n;continue}for(const e of n.getChildren())n.insertBefore(e);n.remove();continue}}const a=n.getPreviousSibling();g(a)&&a.is(e)?a.append(n):(e=c(r,{rel:l,target:i,title:s}),n.insertAfter(e),e.append(n))}})}const x=/^\+?[0-9\s()-]{5,}$/;function N(e){return e.match(/^[a-z][a-z0-9+.-]*:/i)||e.match(/^[/#.]/)?e:e.includes("@")?`mailto:${e}`:x.test(e)?`tel:${e}`:`https://${e}`}const k=[/* @__PURE__ */n.defineImportRule({$import:(e,t)=>{if(!t.textContent&&0===t.children.length)return[];const r=t.getAttribute("href")||"",i={rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.getAttribute("title")};return n.$distributeInlineWrapper(e.$importChildren(t),()=>c(r,i))},match:n.sel.tag("a"),name:"@lexical/link/a"})],$={attributes:void 0,validateUrl:void 0};function L(n,i){return t.mergeRegister(n.registerNodeTransform(s,a),n.registerCommand(p,e=>{const t=i.validateUrl.peek(),n=i.attributes.peek();if(null===e)return m(null),!0;if("string"==typeof e)return!(void 0!==t&&!t(e))&&(m(e,n),!0);{const{url:t,target:r,rel:i,title:s}=e;return m(t,{...n,rel:i,target:r,title:s}),!0}},t.COMMAND_PRIORITY_EDITOR),e.effect(()=>{const e=i.validateUrl.value;if(!e)return;const s=i.attributes.value;return n.registerCommand(t.PASTE_COMMAND,i=>{const l=t.$getSelection();if(!t.$isRangeSelection(l)||l.isCollapsed()||!r.objectKlassEquals(i,ClipboardEvent))return!1;if(null===i.clipboardData)return!1;const o=i.clipboardData.getData("text");if(!e(o))return!1;return!l.getNodes().some(e=>t.$isElementNode(e)||t.$isTextNode(e)&&!e.isSimpleText())&&(n.dispatchCommand(p,{...s,url:o}),i.preventDefault(),!0)},t.COMMAND_PRIORITY_LOW)}))}const T=/* @__PURE__ */t.defineExtension({build:(t,n,r)=>e.namedSignals(n),config:$,dependencies:[n.CoreImportExtension,/* @__PURE__ */t.configExtension(n.DOMImportExtension,{rules:k})],mergeConfig(e,n){const r=t.shallowMergeConfig(e,n);return e.attributes&&(r.attributes=t.shallowMergeConfig(e.attributes,r.attributes)),r},name:"@lexical/link/Link",nodes:()=>[s],register:(e,t,n)=>L(e,n.getOutput())}),S=/* @__PURE__ */t.defineExtension({dependencies:[T],name:"@lexical/link/Import"});function b(e,n,r={}){const i=r=>{const i=r.target;if(!t.isDOMNode(i))return;const s=t.getNearestEditorFromDOMNode(i);if(null===s)return;let l=null,o=null,a=!1;if(s.update(()=>{const e=t.$getNearestNodeFromDOMNode(i);if(null!==e){const r=t.$findMatchingParent(e,t.$isElementNode);if(!n.disabled.peek())if(g(r))a=h(r)&&r.getIsUnlinked(),l=r.sanitizeUrl(r.getURL()),o=r.getTarget();else{const e=function(e,t){let n=e;for(;null!=n;){if(t(n))return n;n=n.parentNode}return null}(i,t.isHTMLAnchorElement);null!==e&&(l=e.href,o=e.target)}}}),null===l||""===l||a)return;const u=e.read("latest",t.$getSelection);if(t.$isRangeSelection(u)&&!u.isCollapsed())return void r.preventDefault();const c="auxclick"===r.type&&1===r.button;window.open(l,n.newTab.peek()||c||r.metaKey||r.ctrlKey||"_blank"===o?"_blank":"_self"),r.preventDefault()},s=e=>{1===e.button&&i(e)};return e.registerRootListener(e=>{if(e)return t.registerEventListeners(e,{click:i,mouseup:s},r)})}const C=/* @__PURE__ */t.defineExtension({build:(t,n,r)=>e.namedSignals(n),config:/* @__PURE__ */t.safeCast({disabled:!1,newTab:!1}),dependencies:[T],name:"@lexical/link/ClickableLink",register:(e,t,n)=>b(e,n.getOutput())});function R(e,t=e=>e){return n=>{const r=e.exec(n);return null===r?null:{index:r.index,length:r[0].length,text:r[0],url:t(r[0])}}}const U=/((https?:\/\/(www\.)?)|(www\.))[-\p{L}\p{N}@:%._+~#=]{1,256}\.[\p{L}\p{N}]{1,6}(?:[-\p{L}\p{N}()@:%_+.~#?&//=]*[\p{L}\p{N}()@_~#?&//=])?/u,E=R(/(([^<>()[\]\\.,;:\s@"]{1,64}(\.[^<>()[\]\\.,;:\s@"]{1,64}){0,63})|(".{1,255}"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]{1,63}\.){1,127}[a-zA-Z]{2,63}))/,e=>`mailto:${e}`);function v(e,t){for(let n=0;n<t.length;n++){const r=t[n](e);if(r)return r}return null}const A=/[.,;\s]/;function O(e,t){return t.test(e)}function M(e,t){return O(e[e.length-1],t)}function P(e,t){return O(e[0],t)}function I(e,n){let r=e.getPreviousSibling();return t.$isElementNode(r)&&(r=r.getLastDescendant()),null===r||t.$isLineBreakNode(r)||t.$isTextNode(r)&&M(r.getTextContent(),n)}function y(e,n){let r=e.getNextSibling();return t.$isElementNode(r)&&(r=r.getFirstDescendant()),null===r||t.$isLineBreakNode(r)||t.$isTextNode(r)&&P(r.getTextContent(),n)}function D(e,t,n,r,i){if(!(e>0?O(r[e-1],n):I(i[0],n)))return!1;return t<r.length?O(r[t],n):y(i[i.length-1],n)}function w(e,t,n){const r=[],i=[],s=[];let l=0,o=0;const a=[...e];for(;a.length>0;){const e=a[0],u=e.getTextContent().length,c=o;o+u<=t?(r.push(e),l+=u):c>=n?s.push(e):i.push(e),o+=u,a.shift()}return[l,r,i,s]}function F(e,n,r,i){const s=f(i.url,i.attributes);if(1===e.length){let l,o=e[0];0===n?[l,o]=o.splitText(r):[,l,o]=o.splitText(n,r);const a=t.$createTextNode(i.text);return a.setFormat(l.getFormat()),a.setDetail(l.getDetail()),a.setStyle(l.getStyle()),s.append(a),l.replace(s),o}if(e.length>1){const i=e[0];let l,o=i.getTextContent().length;0===n?l=i:[,l]=i.splitText(n);const a=[];let u;for(let t=1;t<e.length;t++){const n=e[t],i=n.getTextContent().length,s=o;if(s<r)if(o+i<=r)a.push(n);else{const[e,t]=n.splitText(r-s);a.push(e),u=t}o+=i}const c=t.$getSelection(),g=c?c.getNodes().find(t.$isTextNode):void 0,d=t.$createTextNode(l.getTextContent());return d.setFormat(l.getFormat()),d.setDetail(l.getDetail()),d.setStyle(l.getStyle()),s.append(d,...a),g&&g===l&&(t.$isRangeSelection(c)?d.select(c.anchor.offset,c.focus.offset):t.$isNodeSelection(c)&&d.select(0,d.getTextContent().length)),l.replace(s),u}}function W(e,n,r,i){const s=e.getChildren(),l=s.length;for(let n=0;n<l;n++){const i=s[n];if(!t.$isTextNode(i)||!i.isSimpleText())return z(e),void r(null,e.getURL())}const o=e.getTextContent(),a=v(o,n);if(null===a||a.text!==o)return z(e),void r(null,e.getURL());if(!I(e,i)||!y(e,i))return z(e),void r(null,e.getURL());const u=e.getURL();if(u!==a.url&&(e.setURL(a.url),r(a.url,u)),a.attributes){const t=e.getRel();t!==a.attributes.rel&&(e.setRel(a.attributes.rel||null),r(a.attributes.rel||null,t));const n=e.getTarget();n!==a.attributes.target&&(e.setTarget(a.attributes.target||null),r(a.attributes.target||null,n))}}function z(e){const t=e.getChildren();for(let n=t.length-1;n>=0;n--)e.insertAfter(t[n]);return e.remove(),t.map(e=>e.getLatest())}const J={changeHandlers:[],excludeParents:[],matchers:[],separatorRegex:A};function K(e,n=J){const{matchers:r,changeHandlers:i,excludeParents:s,separatorRegex:l=A}=n,o=(e,t)=>{for(const n of i)n(e,t)};return t.mergeRegister(e.registerNodeTransform(t.TextNode,e=>{const n=e.getParentOrThrow(),i=e.getPreviousSibling();if(h(n))W(n,r,o,l);else if(!g(n)&&!s.some(e=>e(n))){if(e.isSimpleText()&&(P(e.getTextContent(),l)||!h(i))){const n=function(e){const n=[e];let r=e.getNextSibling();for(;null!==r&&t.$isTextNode(r)&&r.isSimpleText()&&(n.push(r),!/[\s]/.test(r.getTextContent()));)r=r.getNextSibling();return n}(e);!function(e,t,n,r){for(const t of e){const e=t.getParent();if(h(e)&&!e.getIsUnlinked())return}let i=[...e];const s=i.map(e=>e.getTextContent()).join("");let l,o=s,a=0;for(;(l=v(o,t))&&null!==l;){const e=l.index,t=e+l.length;if(D(a+e,a+t,r,s,i)){const[r,,s,u]=w(i,a+e,a+t);let c=!1;for(const e of s){const t=e.getParent();if(h(t)&&!t.getIsUnlinked()){c=!0;break}}if(c){a+=t,o=o.substring(t);continue}const g=F(s,a+e-r,a+t-r,l);i=g?[g,...u]:u,n(l.url,null),a=0}else a+=t;o=o.substring(t)}}(n,r,o,l)}!function(e,t,n,r){const i=e.getParent(),s=e.getPreviousSibling(),l=e.getNextSibling(),o=e.getTextContent();if(!h(i)||i.getIsUnlinked()){if(h(s)&&!s.getIsUnlinked()&&s.is(e.getPreviousSibling())&&e.getParent()===s.getParent()){if(!P(o,r))return z(s),void n(null,s.getURL());if(a=o,s.isEmailURI()?/^\.[a-zA-Z]{2,}/.test(a):/^\.[a-zA-Z0-9]{1,}/.test(a)){const i=s.getTextContent()+o,l=v(i,t);null!==l&&l.text===i&&(s.append(e),W(s,t,n,r),n(null,s.getURL()))}}var a;!h(l)||l.getIsUnlinked()||M(o,r)||l.is(e.getNextSibling())&&e.getParent()===l.getParent()&&(z(l),n(null,l.getURL()))}}(e,r,o,l)}}),e.registerCommand(p,e=>{const n=t.$getSelection();if(null!==e||!t.$isRangeSelection(n))return!1;return n.extract().forEach(e=>{const t=e.getParent();h(t)&&(t.setIsUnlinked(!t.getIsUnlinked()),t.markDirty())}),!1},t.COMMAND_PRIORITY_LOW))}const B=/* @__PURE__ */t.defineExtension({config:J,dependencies:[T],mergeConfig(e,n){const r=t.shallowMergeConfig(e,n);for(const t of["matchers","changeHandlers","excludeParents"]){const i=n[t];Array.isArray(i)&&(r[t]=[...e[t],...i])}return r},name:"@lexical/link/AutoLink",nodes:[d],register:K});exports.$createAutoLinkNode=f,exports.$createLinkNode=c,exports.$isAutoLinkNode=h,exports.$isLinkNode=g,exports.$toggleLink=m,exports.AutoLinkExtension=B,exports.AutoLinkNode=d,exports.ClickableLinkExtension=C,exports.LinkExtension=T,exports.LinkImportExtension=S,exports.LinkImportRules=k,exports.LinkNode=s,exports.TOGGLE_LINK_COMMAND=p,exports.autoLinkEmailMatcher=E,exports.autoLinkUrlMatcher=e=>{const t=U.exec(e);if(null===t)return null;let n=t[0],r=0;for(const e of n)"("===e?r++:")"===e&&r--;for(;r<0&&n.endsWith(")");)n=n.slice(0,-1),r++;return{index:t.index,length:n.length,text:n,url:n.startsWith("http")?n:`https://${n}`}},exports.createLinkMatcherWithRegExp=R,exports.formatUrl=N,exports.registerAutoLink=K,exports.registerClickableLink=b,exports.registerLink=L;
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{namedSignals as t,effect as e}from"@lexical/extension";import{ElementNode as n,$getDocument as r,addClassNamesToElement as i,isHTMLAnchorElement as l,$copyNode as s,$isRangeSelection as o,$applyNodeReplacement as u,createCommand as a,$getSelection as c,$isNodeSelection as g,$findMatchingParent as f,$normalizeSelection__EXPERIMENTAL as d,$setSelection as h,$getChildCaret as p,$isElementNode as _,$insertNodeToNearestRootAtCaret as m,$rewindSiblingCaret as x,$caretFromPoint as b,$normalizeCaret as k,$isSiblingCaret as U,$setPointFromCaret as v,defineExtension as T,shallowMergeConfig as C,configExtension as L,mergeRegister as S,COMMAND_PRIORITY_EDITOR as N,PASTE_COMMAND as O,$isTextNode as A,COMMAND_PRIORITY_LOW as P,safeCast as y,registerEventListeners as R,isDOMNode as w,getNearestEditorFromDOMNode as D,$getNearestNodeFromDOMNode as I,TextNode as M,$isLineBreakNode as E,$createTextNode as F}from"lexical";import{defineImportRule as W,sel as J,$distributeInlineWrapper as $,CoreImportExtension as K,DOMImportExtension as z}from"@lexical/html";import{objectKlassEquals as B}from"@lexical/utils";const j=new Set(["http:","https:","mailto:","sms:","tel:"]);class Z extends n{__url;__target;__rel;__title;static getType(){return"link"}static clone(t){return new Z(t.__url,{rel:t.__rel,target:t.__target,title:t.__title},t.__key)}constructor(t="",e={},n){super(n);const{target:r=null,rel:i=null,title:l=null}=e;this.__url=t,this.__target=r,this.__rel=i,this.__title=l}afterCloneFrom(t){super.afterCloneFrom(t),this.__url=t.__url,this.__rel=t.__rel,this.__target=t.__target,this.__title=t.__title}createDOM(t){const e=r().createElement("a");return this.updateLinkDOM(null,e,t),i(e,t.theme.link),e}updateLinkDOM(t,e,n){if(l(e)){t&&t.__url===this.__url||(e.href=this.sanitizeUrl(this.__url));for(const n of["target","rel","title"]){const r=`__${n}`,i=this[r];t&&t[r]===i||(i?e[n]=i:e.removeAttribute(n))}}}updateDOM(t,e,n){return this.updateLinkDOM(t,e,n),!1}static importDOM(){return{a:t=>({conversion:Q,priority:1})}}static importJSON(t){return V().updateFromJSON(t)}updateFromJSON(t){return super.updateFromJSON(t).setURL(t.url).setRel(t.rel||null).setTarget(t.target||null).setTitle(t.title||null)}sanitizeUrl(t){t=st(t);try{const e=new URL(st(t));if(!j.has(e.protocol))return"about:blank"}catch(e){return t}return t}exportJSON(){return{...super.exportJSON(),rel:this.getRel(),target:this.getTarget(),title:this.getTitle(),url:this.getURL()}}getURL(){return this.getLatest().__url}setURL(t){const e=this.getWritable();return e.__url=t,e}getTarget(){return this.getLatest().__target}setTarget(t){const e=this.getWritable();return e.__target=t,e}getRel(){return this.getLatest().__rel}setRel(t){const e=this.getWritable();return e.__rel=t,e}getTitle(){return this.getLatest().__title}setTitle(t){const e=this.getWritable();return e.__title=t,e}insertNewAfter(t,e=!0){const n=s(this);return this.insertAfter(n,e),n}canInsertTextBefore(){return!1}canInsertTextAfter(){return!1}canBeEmpty(){return!1}isInline(){return!0}extractWithChild(t,e,n){if(!o(e))return!1;const r=e.anchor.getNode(),i=e.focus.getNode();return(this.is(r)||this.isParentOf(r))&&(this.is(i)||this.isParentOf(i))&&e.getTextContent().length>0}isEmailURI(){return this.__url.startsWith("mailto:")}isWebSiteURI(){return this.__url.startsWith("https://")||this.__url.startsWith("http://")}shouldMergeAdjacentLink(t){return this.getType()===t.getType()&&this.__url===t.__url&&this.__target===t.__target&&this.__rel===t.__rel&&this.__title===t.__title}}function H(t){const e=b(t,"next");return[e,e.getFlipped()]}function G(t,e){for(const n of e)if(n.origin.isAttached()){const e=k(n);return void v(t,e)}}function q(t){const e=c();let n=null,r=null;function i(){o(e)&&(G(e.anchor,n),G(e.focus,r),d(e))}o(e)&&(n=H(e.anchor),r=H(e.focus));let l=!1;for(const e of p(t,"next")){const n=e.origin;if(_(n)&&!n.isInline()){const r=n.getChildren();if(r.length>0){const e=s(t);e.append(...r),n.append(e),l=!0}m(n,x(e),{$shouldSplit:()=>!1})}}function u(t,e,n){const[r,i]=t,l=t=>U(t)&&t.origin.is(e);if(!l(r)&&!l(i))return t;const s=k(p(n,"next"));return[s,s.getFlipped()]}if(t.isAttached()){const e=t.getPreviousSibling();if(X(e)&&e.shouldMergeAdjacentLink(t))return n&&(n=u(n,e,t)),r&&(r=u(r,e,t)),e.append(...t.getChildren()),t.remove(),void i();const s=t.getNextSibling();X(s)&&t.shouldMergeAdjacentLink(s)&&(n&&(n=u(n,t,s)),r&&(r=u(r,t,s)),t.append(...s.getChildren()),s.remove(),l=!0)}if(l){if(!t.canBeEmpty()&&t.isEmpty()){const e=t.getParent();t.remove(),e&&e.isEmpty()&&e.remove()}i()}}function Q(t){let e=null;if(l(t)){const n=t.textContent;(null!==n&&""!==n||t.children.length>0)&&(e=V(t.getAttribute("href")||"",{rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.getAttribute("title")}))}return{node:e}}function V(t="",e){return u(new Z(t,e))}function X(t){return t instanceof Z}class Y extends Z{__isUnlinked;constructor(t="",e={},n){super(t,e,n),this.__isUnlinked=void 0!==e.isUnlinked&&null!==e.isUnlinked&&e.isUnlinked}afterCloneFrom(t){super.afterCloneFrom(t),this.__isUnlinked=t.__isUnlinked}static getType(){return"autolink"}static clone(t){return new Y(t.__url,{isUnlinked:t.__isUnlinked,rel:t.__rel,target:t.__target,title:t.__title},t.__key)}shouldMergeAdjacentLink(t){return!1}getIsUnlinked(){return this.__isUnlinked}setIsUnlinked(t){const e=this.getWritable();return e.__isUnlinked=t,e}createDOM(t){return this.__isUnlinked?r().createElement("span"):super.createDOM(t)}updateDOM(t,e,n){return super.updateDOM(t,e,n)||t.__isUnlinked!==this.__isUnlinked}static importJSON(t){return tt().updateFromJSON(t)}updateFromJSON(t){return super.updateFromJSON(t).setIsUnlinked(t.isUnlinked||!1)}static importDOM(){return null}exportJSON(){return{...super.exportJSON(),isUnlinked:this.__isUnlinked}}insertNewAfter(t,e=!0){const n=tt(this.__url,{isUnlinked:this.__isUnlinked,rel:this.__rel,target:this.__target,title:this.__title});return this.insertAfter(n,e),n}}function tt(t="",e){return u(new Y(t,e))}function et(t){return t instanceof Y}const nt=/* @__PURE__ */a("TOGGLE_LINK_COMMAND");function rt(t,e){if("element"===t.type){const n=t.getNode();_(n)||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.`)}(252);return n.getChildren()[t.offset+e]||null}return null}function it(t,e={}){let n;if(t&&"object"==typeof t){const{url:r,...i}=t;n=r,e={...i,...e}}else n=t;const{target:r,title:i}=e,l=void 0===e.rel?"noreferrer":e.rel,u=c();if(null===u||!o(u)&&!g(u))return;if(g(u)){const t=u.getNodes();if(0===t.length)return;return void t.forEach(t=>{if(null===n){const e=f(t,t=>!et(t)&&X(t));e&&(e.insertBefore(t),0===e.getChildren().length&&e.remove())}else{const e=f(t,t=>!et(t)&&X(t));if(e)e.setURL(n),void 0!==r&&e.setTarget(r),void 0!==l&&e.setRel(l);else{const e=V(n,{rel:l,target:r});t.insertBefore(e),e.append(t)}}})}if(u.isCollapsed()&&null===n)for(const t of u.getNodes()){const e=f(t,t=>!et(t)&&X(t));return void(null!==e&&(e.getParentOrThrow().splice(e.getIndexWithinParent(),0,e.getChildren()),e.remove()))}const a=u.extract();if(null===n){const t=new Set;return void a.forEach(e=>{const n=f(e,t=>!et(t)&&X(t));if(null!==n){const e=n.getKey();if(t.has(e))return;!function(t,e){const n=new Set(e.filter(e=>t.isParentOf(e)).map(t=>t.getKey())),r=t.getChildren(),i=r=>n.has(r.getKey())||_(r)&&e.some(e=>t.isParentOf(e)&&r.isParentOf(e)),l=r.filter(i);if(l.length===r.length)return r.forEach(e=>t.insertBefore(e)),void t.remove();const o=r.findIndex(i),u=r.findLastIndex(i),a=0===o,c=u===r.length-1;if(a)l.forEach(e=>t.insertBefore(e));else if(c)for(let e=l.length-1;e>=0;e--)t.insertAfter(l[e]);else{for(let e=l.length-1;e>=0;e--)t.insertAfter(l[e]);const e=r.slice(u+1);if(e.length>0){const n=s(t);l[l.length-1].insertAfter(n),e.forEach(t=>n.append(t))}}}(n,a),t.add(e)}})}const p=new Set,m=t=>{p.has(t.getKey())||(p.add(t.getKey()),t.setURL(n),void 0!==r&&t.setTarget(r),void 0!==l&&t.setRel(l),void 0!==i&&t.setTitle(i))};if(1===a.length){const t=a[0],e=f(t,X);if(null!==e)return m(e)}!function(t){const e=c();if(!o(e))return t();const n=d(e),r=n.isBackward(),i=rt(n.anchor,r?-1:0),l=rt(n.focus,r?0:-1),s=t();if(i||l){const t=c();if(o(t)){const e=t.clone();if(i){const t=i.getParent();t&&e.anchor.set(t.getKey(),i.getIndexWithinParent()+(r?1:0),"element")}if(l){const t=l.getParent();t&&e.focus.set(t.getKey(),l.getIndexWithinParent()+(r?0:1),"element")}h(d(e))}}}(()=>{let t=null;for(const e of a){if(!e.isAttached())continue;const s=f(e,X);if(s){m(s);continue}if(_(e)){if(!e.isInline())continue;if(X(e)){if(!(et(e)||null!==t&&t.getParentOrThrow().isParentOf(e))){m(e),t=e;continue}for(const t of e.getChildren())e.insertBefore(t);e.remove();continue}}const o=e.getPreviousSibling();X(o)&&o.is(t)?o.append(e):(t=V(n,{rel:l,target:r,title:i}),e.insertAfter(t),t.append(e))}})}const lt=/^\+?[0-9\s()-]{5,}$/;function st(t){return t.match(/^[a-z][a-z0-9+.-]*:/i)||t.match(/^[/#.]/)?t:t.includes("@")?`mailto:${t}`:lt.test(t)?`tel:${t}`:`https://${t}`}const ot=[/* @__PURE__ */W({$import:(t,e)=>{if(!e.textContent&&0===e.children.length)return[];const n=e.getAttribute("href")||"",r={rel:e.getAttribute("rel"),target:e.getAttribute("target"),title:e.getAttribute("title")};return $(t.$importChildren(e),()=>V(n,r))},match:J.tag("a"),name:"@lexical/link/a"})];function ut(t,n){return S(t.registerNodeTransform(Z,q),t.registerCommand(nt,t=>{const e=n.validateUrl.peek(),r=n.attributes.peek();if(null===t)return it(null),!0;if("string"==typeof t)return!(void 0!==e&&!e(t))&&(it(t,r),!0);{const{url:e,target:n,rel:i,title:l}=t;return it(e,{...r,rel:i,target:n,title:l}),!0}},N),e(()=>{const e=n.validateUrl.value;if(!e)return;const r=n.attributes.value;return t.registerCommand(O,n=>{const i=c();if(!o(i)||i.isCollapsed()||!B(n,ClipboardEvent))return!1;if(null===n.clipboardData)return!1;const l=n.clipboardData.getData("text");if(!e(l))return!1;return!i.getNodes().some(t=>_(t)||A(t)&&!t.isSimpleText())&&(t.dispatchCommand(nt,{...r,url:l}),n.preventDefault(),!0)},P)}))}const at=/* @__PURE__ */T({build:(e,n,r)=>t(n),config:{attributes:void 0,validateUrl:void 0},dependencies:[K,/* @__PURE__ */L(z,{rules:ot})],mergeConfig(t,e){const n=C(t,e);return t.attributes&&(n.attributes=C(t.attributes,n.attributes)),n},name:"@lexical/link/Link",nodes:()=>[Z],register:(t,e,n)=>ut(t,n.getOutput())}),ct=/* @__PURE__ */T({dependencies:[at],name:"@lexical/link/Import"});function gt(t,e,n={}){const r=n=>{const r=n.target;if(!w(r))return;const i=D(r);if(null===i)return;let s=null,u=null;if(i.update(()=>{const t=I(r);if(null!==t){const n=f(t,_);if(!e.disabled.peek())if(X(n))s=n.sanitizeUrl(n.getURL()),u=n.getTarget();else{const t=function(t,e){let n=t;for(;null!=n;){if(e(n))return n;n=n.parentNode}return null}(r,l);null!==t&&(s=t.href,u=t.target)}}}),null===s||""===s)return;const a=t.read("latest",c);if(o(a)&&!a.isCollapsed())return void n.preventDefault();const g="auxclick"===n.type&&1===n.button;window.open(s,e.newTab.peek()||g||n.metaKey||n.ctrlKey||"_blank"===u?"_blank":"_self"),n.preventDefault()},i=t=>{1===t.button&&r(t)};return t.registerRootListener(t=>{if(t)return R(t,{click:r,mouseup:i},n)})}const ft=/* @__PURE__ */T({build:(e,n,r)=>t(n),config:/* @__PURE__ */y({disabled:!1,newTab:!1}),dependencies:[at],name:"@lexical/link/ClickableLink",register:(t,e,n)=>gt(t,n.getOutput())});function dt(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])}}}const ht=/((https?:\/\/(www\.)?)|(www\.))[-\p{L}\p{N}@:%._+~#=]{1,256}\.[\p{L}\p{N}]{1,6}(?:[-\p{L}\p{N}()@:%_+.~#?&//=]*[\p{L}\p{N}()@_~#?&//=])?/u,pt=t=>{const e=ht.exec(t);if(null===e)return null;let n=e[0],r=0;for(const t of n)"("===t?r++:")"===t&&r--;for(;r<0&&n.endsWith(")");)n=n.slice(0,-1),r++;return{index:e.index,length:n.length,text:n,url:n.startsWith("http")?n:`https://${n}`}},_t=dt(/(([^<>()[\]\\.,;:\s@"]{1,64}(\.[^<>()[\]\\.,;:\s@"]{1,64}){0,63})|(".{1,255}"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]{1,63}\.){1,127}[a-zA-Z]{2,63}))/,t=>`mailto:${t}`);function mt(t,e){for(let n=0;n<e.length;n++){const r=e[n](t);if(r)return r}return null}const xt=/[.,;\s]/;function bt(t,e){return e.test(t)}function kt(t,e){return bt(t[t.length-1],e)}function Ut(t,e){return bt(t[0],e)}function vt(t,e){let n=t.getPreviousSibling();return _(n)&&(n=n.getLastDescendant()),null===n||E(n)||A(n)&&kt(n.getTextContent(),e)}function Tt(t,e){let n=t.getNextSibling();return _(n)&&(n=n.getFirstDescendant()),null===n||E(n)||A(n)&&Ut(n.getTextContent(),e)}function Ct(t,e,n,r,i){if(!(t>0?bt(r[t-1],n):vt(i[0],n)))return!1;return e<r.length?bt(r[e],n):Tt(i[i.length-1],n)}function Lt(t,e,n){const r=[],i=[],l=[];let s=0,o=0;const u=[...t];for(;u.length>0;){const t=u[0],a=t.getTextContent().length,c=o;o+a<=e?(r.push(t),s+=a):c>=n?l.push(t):i.push(t),o+=a,u.shift()}return[s,r,i,l]}function St(t,e,n,r){const i=tt(r.url,r.attributes);if(1===t.length){let l,s=t[0];0===e?[l,s]=s.splitText(n):[,l,s]=s.splitText(e,n);const o=F(r.text);return o.setFormat(l.getFormat()),o.setDetail(l.getDetail()),o.setStyle(l.getStyle()),i.append(o),l.replace(i),s}if(t.length>1){const r=t[0];let l,s=r.getTextContent().length;0===e?l=r:[,l]=r.splitText(e);const u=[];let a;for(let e=1;e<t.length;e++){const r=t[e],i=r.getTextContent().length,l=s;if(l<n)if(s+i<=n)u.push(r);else{const[t,e]=r.splitText(n-l);u.push(t),a=e}s+=i}const f=c(),d=f?f.getNodes().find(A):void 0,h=F(l.getTextContent());return h.setFormat(l.getFormat()),h.setDetail(l.getDetail()),h.setStyle(l.getStyle()),i.append(h,...u),d&&d===l&&(o(f)?h.select(f.anchor.offset,f.focus.offset):g(f)&&h.select(0,h.getTextContent().length)),l.replace(i),a}}function Nt(t,e,n,r){const i=t.getChildren(),l=i.length;for(let e=0;e<l;e++){const r=i[e];if(!A(r)||!r.isSimpleText())return Ot(t),void n(null,t.getURL())}const s=t.getTextContent(),o=mt(s,e);if(null===o||o.text!==s)return Ot(t),void n(null,t.getURL());if(!vt(t,r)||!Tt(t,r))return Ot(t),void n(null,t.getURL());const u=t.getURL();if(u!==o.url&&(t.setURL(o.url),n(o.url,u)),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 Ot(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())}const At={changeHandlers:[],excludeParents:[],matchers:[],separatorRegex:xt};function Pt(t,e=At){const{matchers:n,changeHandlers:r,excludeParents:i,separatorRegex:l=xt}=e,s=(t,e)=>{for(const n of r)n(t,e)};return S(t.registerNodeTransform(M,t=>{const e=t.getParentOrThrow(),r=t.getPreviousSibling();if(et(e))Nt(e,n,s,l);else if(!X(e)&&!i.some(t=>t(e))){if(t.isSimpleText()&&(Ut(t.getTextContent(),l)||!et(r))){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,r){for(const e of t){const t=e.getParent();if(et(t)&&!t.getIsUnlinked())return}let i=[...t];const l=i.map(t=>t.getTextContent()).join("");let s,o=l,u=0;for(;(s=mt(o,e))&&null!==s;){const t=s.index,e=t+s.length;if(Ct(u+t,u+e,r,l,i)){const[r,,l,a]=Lt(i,u+t,u+e);let c=!1;for(const t of l){const e=t.getParent();if(et(e)&&!e.getIsUnlinked()){c=!0;break}}if(c){u+=e,o=o.substring(e);continue}const g=St(l,u+t-r,u+e-r,s);i=g?[g,...a]:a,n(s.url,null),u=0}else u+=e;o=o.substring(e)}}(e,n,s,l)}!function(t,e,n,r){const i=t.getParent(),l=t.getPreviousSibling(),s=t.getNextSibling(),o=t.getTextContent();if(!et(i)||i.getIsUnlinked()){if(et(l)&&!l.getIsUnlinked()&&l.is(t.getPreviousSibling())&&t.getParent()===l.getParent()){if(!Ut(o,r))return Ot(l),void n(null,l.getURL());if(u=o,l.isEmailURI()?/^\.[a-zA-Z]{2,}/.test(u):/^\.[a-zA-Z0-9]{1,}/.test(u)){const i=l.getTextContent()+o,s=mt(i,e);null!==s&&s.text===i&&(l.append(t),Nt(l,e,n,r),n(null,l.getURL()))}}var u;!et(s)||s.getIsUnlinked()||kt(o,r)||s.is(t.getNextSibling())&&t.getParent()===s.getParent()&&(Ot(s),n(null,s.getURL()))}}(t,n,s,l)}}),t.registerCommand(nt,t=>{const e=c();if(null!==t||!o(e))return!1;return e.extract().forEach(t=>{const e=t.getParent();et(e)&&(e.setIsUnlinked(!e.getIsUnlinked()),e.markDirty())}),!1},P))}const yt=/* @__PURE__ */T({config:At,dependencies:[at],mergeConfig(t,e){const n=C(t,e);for(const r of["matchers","changeHandlers","excludeParents"]){const i=e[r];Array.isArray(i)&&(n[r]=[...t[r],...i])}return n},name:"@lexical/link/AutoLink",nodes:[Y],register:Pt});export{tt as $createAutoLinkNode,V as $createLinkNode,et as $isAutoLinkNode,X as $isLinkNode,it as $toggleLink,yt as AutoLinkExtension,Y as AutoLinkNode,ft as ClickableLinkExtension,at as LinkExtension,ct as LinkImportExtension,ot as LinkImportRules,Z as LinkNode,nt as TOGGLE_LINK_COMMAND,_t as autoLinkEmailMatcher,pt as autoLinkUrlMatcher,dt as createLinkMatcherWithRegExp,st as formatUrl,Pt as registerAutoLink,gt as registerClickableLink,ut as registerLink};
|
|
9
|
+
import{namedSignals as t,effect as e}from"@lexical/extension";import{ElementNode as n,$getDocument as r,addClassNamesToElement as i,isHTMLAnchorElement as l,$copyNode as s,$isRangeSelection as o,$applyNodeReplacement as u,createCommand as a,$getSelection as c,$isNodeSelection as g,$findMatchingParent as f,$normalizeSelection__EXPERIMENTAL as d,$setSelection as h,$getChildCaret as p,$isElementNode as _,$insertNodeToNearestRootAtCaret as m,$rewindSiblingCaret as x,$caretFromPoint as b,$normalizeCaret as k,$isSiblingCaret as U,$setPointFromCaret as v,defineExtension as T,shallowMergeConfig as C,configExtension as L,mergeRegister as S,COMMAND_PRIORITY_EDITOR as N,PASTE_COMMAND as O,$isTextNode as A,COMMAND_PRIORITY_LOW as P,safeCast as y,registerEventListeners as R,isDOMNode as w,getNearestEditorFromDOMNode as I,$getNearestNodeFromDOMNode as D,TextNode as F,$isLineBreakNode as M,$createTextNode as E}from"lexical";import{defineImportRule as W,sel as $,$distributeInlineWrapper as J,CoreImportExtension as z,DOMImportExtension as K}from"@lexical/html";import{objectKlassEquals as B}from"@lexical/utils";const j=new Set(["http:","https:","mailto:","sms:","tel:"]);class Z extends n{__url;__target;__rel;__title;static getType(){return"link"}static clone(t){return new Z(t.__url,{rel:t.__rel,target:t.__target,title:t.__title},t.__key)}constructor(t="",e={},n){super(n);const{target:r=null,rel:i=null,title:l=null}=e;this.__url=t,this.__target=r,this.__rel=i,this.__title=l}afterCloneFrom(t){super.afterCloneFrom(t),this.__url=t.__url,this.__rel=t.__rel,this.__target=t.__target,this.__title=t.__title}createDOM(t){const e=r().createElement("a");return this.updateLinkDOM(null,e,t),i(e,t.theme.link),e}updateLinkDOM(t,e,n){if(l(e)){t&&t.__url===this.__url||(e.href=this.sanitizeUrl(this.__url));for(const n of["target","rel","title"]){const r=`__${n}`,i=this[r];t&&t[r]===i||(i?e[n]=i:e.removeAttribute(n))}}}updateDOM(t,e,n){return this.updateLinkDOM(t,e,n),!1}static importDOM(){return{a:t=>({conversion:Q,priority:1})}}static importJSON(t){return V().updateFromJSON(t)}updateFromJSON(t){return super.updateFromJSON(t).setURL(t.url).setRel(t.rel||null).setTarget(t.target||null).setTitle(t.title||null)}sanitizeUrl(t){const e=t;t=st(t);try{const e=new URL(st(t));if(!j.has(e.protocol))return"about:blank"}catch(t){const n=e.replace(/[\u0000-\u001F\u007F\s]/g,"").match(/^([a-z][a-z0-9+.-]*):/i);if(null!=n&&!j.has(`${n[1].toLowerCase()}:`))return"about:blank"}return t}exportJSON(){return{...super.exportJSON(),rel:this.getRel(),target:this.getTarget(),title:this.getTitle(),url:this.getURL()}}getURL(){return this.getLatest().__url}setURL(t){const e=this.getWritable();return e.__url=t,e}getTarget(){return this.getLatest().__target}setTarget(t){const e=this.getWritable();return e.__target=t,e}getRel(){return this.getLatest().__rel}setRel(t){const e=this.getWritable();return e.__rel=t,e}getTitle(){return this.getLatest().__title}setTitle(t){const e=this.getWritable();return e.__title=t,e}insertNewAfter(t,e=!0){const n=s(this);return this.insertAfter(n,e),n}canInsertTextBefore(){return!1}canInsertTextAfter(){return!1}canBeEmpty(){return!1}isInline(){return!0}extractWithChild(t,e,n){if(!o(e))return!1;const r=e.anchor.getNode(),i=e.focus.getNode();return(this.is(r)||this.isParentOf(r))&&(this.is(i)||this.isParentOf(i))&&e.getTextContent().length>0}isEmailURI(){return this.__url.startsWith("mailto:")}isWebSiteURI(){return this.__url.startsWith("https://")||this.__url.startsWith("http://")}shouldMergeAdjacentLink(t){return this.getType()===t.getType()&&this.__url===t.__url&&this.__target===t.__target&&this.__rel===t.__rel&&this.__title===t.__title}}function H(t){const e=b(t,"next");return[e,e.getFlipped()]}function G(t,e){for(const n of e)if(n.origin.isAttached()){const e=k(n);return void v(t,e)}}function q(t){const e=c();let n=null,r=null;function i(){o(e)&&(G(e.anchor,n),G(e.focus,r),d(e))}o(e)&&(n=H(e.anchor),r=H(e.focus));let l=!1;for(const e of p(t,"next")){const n=e.origin;if(_(n)&&!n.isInline()){const r=n.getChildren();if(r.length>0){const e=s(t);e.append(...r),n.append(e),l=!0}m(n,x(e),{$shouldSplit:()=>!1})}}function u(t,e,n){const[r,i]=t,l=t=>U(t)&&t.origin.is(e);if(!l(r)&&!l(i))return t;const s=k(p(n,"next"));return[s,s.getFlipped()]}if(t.isAttached()){const e=t.getPreviousSibling();if(X(e)&&e.shouldMergeAdjacentLink(t))return n&&(n=u(n,e,t)),r&&(r=u(r,e,t)),e.append(...t.getChildren()),t.remove(),void i();const s=t.getNextSibling();X(s)&&t.shouldMergeAdjacentLink(s)&&(n&&(n=u(n,t,s)),r&&(r=u(r,t,s)),t.append(...s.getChildren()),s.remove(),l=!0)}if(l){if(!t.canBeEmpty()&&t.isEmpty()){const e=t.getParent();t.remove(),e&&e.isEmpty()&&e.remove()}i()}}function Q(t){let e=null;if(l(t)){const n=t.textContent;(null!==n&&""!==n||t.children.length>0)&&(e=V(t.getAttribute("href")||"",{rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.getAttribute("title")}))}return{node:e}}function V(t="",e){return u(new Z(t,e))}function X(t){return t instanceof Z}class Y extends Z{__isUnlinked;constructor(t="",e={},n){super(t,e,n),this.__isUnlinked=void 0!==e.isUnlinked&&null!==e.isUnlinked&&e.isUnlinked}afterCloneFrom(t){super.afterCloneFrom(t),this.__isUnlinked=t.__isUnlinked}static getType(){return"autolink"}static clone(t){return new Y(t.__url,{isUnlinked:t.__isUnlinked,rel:t.__rel,target:t.__target,title:t.__title},t.__key)}shouldMergeAdjacentLink(t){return!1}getIsUnlinked(){return this.__isUnlinked}setIsUnlinked(t){const e=this.getWritable();return e.__isUnlinked=t,e}createDOM(t){return this.__isUnlinked?r().createElement("span"):super.createDOM(t)}updateDOM(t,e,n){return super.updateDOM(t,e,n)||t.__isUnlinked!==this.__isUnlinked}static importJSON(t){return tt().updateFromJSON(t)}updateFromJSON(t){return super.updateFromJSON(t).setIsUnlinked(t.isUnlinked||!1)}static importDOM(){return null}exportJSON(){return{...super.exportJSON(),isUnlinked:this.__isUnlinked}}insertNewAfter(t,e=!0){const n=tt(this.__url,{isUnlinked:this.__isUnlinked,rel:this.__rel,target:this.__target,title:this.__title});return this.insertAfter(n,e),n}}function tt(t="",e){return u(new Y(t,e))}function et(t){return t instanceof Y}const nt=/* @__PURE__ */a("TOGGLE_LINK_COMMAND");function rt(t,e){if("element"===t.type){const n=t.getNode();_(n)||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.`)}(252);return n.getChildren()[t.offset+e]||null}return null}function it(t,e={}){let n;if(t&&"object"==typeof t){const{url:r,...i}=t;n=r,e={...i,...e}}else n=t;const{target:r,title:i}=e,l=void 0===e.rel?"noreferrer":e.rel,u=c();if(null===u||!o(u)&&!g(u))return;if(g(u)){const t=u.getNodes();if(0===t.length)return;return void t.forEach(t=>{if(null===n){const e=f(t,t=>!et(t)&&X(t));e&&(e.insertBefore(t),0===e.getChildren().length&&e.remove())}else{const e=f(t,t=>!et(t)&&X(t));if(e)e.setURL(n),void 0!==r&&e.setTarget(r),void 0!==l&&e.setRel(l);else{const e=V(n,{rel:l,target:r});t.insertBefore(e),e.append(t)}}})}if(u.isCollapsed()&&null===n)for(const t of u.getNodes()){const e=f(t,t=>!et(t)&&X(t));return void(null!==e&&(e.getParentOrThrow().splice(e.getIndexWithinParent(),0,e.getChildren()),e.remove()))}const a=u.extract();if(null===n){const t=new Set;return void a.forEach(e=>{const n=f(e,t=>!et(t)&&X(t));if(null!==n){const e=n.getKey();if(t.has(e))return;!function(t,e){const n=new Set(e.filter(e=>t.isParentOf(e)).map(t=>t.getKey())),r=t.getChildren(),i=r=>n.has(r.getKey())||_(r)&&e.some(e=>t.isParentOf(e)&&r.isParentOf(e)),l=r.filter(i);if(l.length===r.length)return r.forEach(e=>t.insertBefore(e)),void t.remove();const o=r.findIndex(i),u=r.findLastIndex(i),a=0===o,c=u===r.length-1;if(a)l.forEach(e=>t.insertBefore(e));else if(c)for(let e=l.length-1;e>=0;e--)t.insertAfter(l[e]);else{for(let e=l.length-1;e>=0;e--)t.insertAfter(l[e]);const e=r.slice(u+1);if(e.length>0){const n=s(t);l[l.length-1].insertAfter(n),e.forEach(t=>n.append(t))}}}(n,a),t.add(e)}})}const p=new Set,m=t=>{p.has(t.getKey())||(p.add(t.getKey()),t.setURL(n),void 0!==r&&t.setTarget(r),void 0!==l&&t.setRel(l),void 0!==i&&t.setTitle(i))};if(1===a.length){const t=a[0],e=f(t,X);if(null!==e)return m(e)}!function(t){const e=c();if(!o(e))return t();const n=d(e),r=n.isBackward(),i=rt(n.anchor,r?-1:0),l=rt(n.focus,r?0:-1),s=t();if(i||l){const t=c();if(o(t)){const e=t.clone();if(i){const t=i.getParent();t&&e.anchor.set(t.getKey(),i.getIndexWithinParent()+(r?1:0),"element")}if(l){const t=l.getParent();t&&e.focus.set(t.getKey(),l.getIndexWithinParent()+(r?0:1),"element")}h(d(e))}}}(()=>{let t=null;for(const e of a){if(!e.isAttached())continue;const s=f(e,X);if(s){m(s);continue}if(_(e)){if(!e.isInline())continue;if(X(e)){if(!(et(e)||null!==t&&t.getParentOrThrow().isParentOf(e))){m(e),t=e;continue}for(const t of e.getChildren())e.insertBefore(t);e.remove();continue}}const o=e.getPreviousSibling();X(o)&&o.is(t)?o.append(e):(t=V(n,{rel:l,target:r,title:i}),e.insertAfter(t),t.append(e))}})}const lt=/^\+?[0-9\s()-]{5,}$/;function st(t){return t.match(/^[a-z][a-z0-9+.-]*:/i)||t.match(/^[/#.]/)?t:t.includes("@")?`mailto:${t}`:lt.test(t)?`tel:${t}`:`https://${t}`}const ot=[/* @__PURE__ */W({$import:(t,e)=>{if(!e.textContent&&0===e.children.length)return[];const n=e.getAttribute("href")||"",r={rel:e.getAttribute("rel"),target:e.getAttribute("target"),title:e.getAttribute("title")};return J(t.$importChildren(e),()=>V(n,r))},match:$.tag("a"),name:"@lexical/link/a"})];function ut(t,n){return S(t.registerNodeTransform(Z,q),t.registerCommand(nt,t=>{const e=n.validateUrl.peek(),r=n.attributes.peek();if(null===t)return it(null),!0;if("string"==typeof t)return!(void 0!==e&&!e(t))&&(it(t,r),!0);{const{url:e,target:n,rel:i,title:l}=t;return it(e,{...r,rel:i,target:n,title:l}),!0}},N),e(()=>{const e=n.validateUrl.value;if(!e)return;const r=n.attributes.value;return t.registerCommand(O,n=>{const i=c();if(!o(i)||i.isCollapsed()||!B(n,ClipboardEvent))return!1;if(null===n.clipboardData)return!1;const l=n.clipboardData.getData("text");if(!e(l))return!1;return!i.getNodes().some(t=>_(t)||A(t)&&!t.isSimpleText())&&(t.dispatchCommand(nt,{...r,url:l}),n.preventDefault(),!0)},P)}))}const at=/* @__PURE__ */T({build:(e,n,r)=>t(n),config:{attributes:void 0,validateUrl:void 0},dependencies:[z,/* @__PURE__ */L(K,{rules:ot})],mergeConfig(t,e){const n=C(t,e);return t.attributes&&(n.attributes=C(t.attributes,n.attributes)),n},name:"@lexical/link/Link",nodes:()=>[Z],register:(t,e,n)=>ut(t,n.getOutput())}),ct=/* @__PURE__ */T({dependencies:[at],name:"@lexical/link/Import"});function gt(t,e,n={}){const r=n=>{const r=n.target;if(!w(r))return;const i=I(r);if(null===i)return;let s=null,u=null,a=!1;if(i.update(()=>{const t=D(r);if(null!==t){const n=f(t,_);if(!e.disabled.peek())if(X(n))a=et(n)&&n.getIsUnlinked(),s=n.sanitizeUrl(n.getURL()),u=n.getTarget();else{const t=function(t,e){let n=t;for(;null!=n;){if(e(n))return n;n=n.parentNode}return null}(r,l);null!==t&&(s=t.href,u=t.target)}}}),null===s||""===s||a)return;const g=t.read("latest",c);if(o(g)&&!g.isCollapsed())return void n.preventDefault();const d="auxclick"===n.type&&1===n.button;window.open(s,e.newTab.peek()||d||n.metaKey||n.ctrlKey||"_blank"===u?"_blank":"_self"),n.preventDefault()},i=t=>{1===t.button&&r(t)};return t.registerRootListener(t=>{if(t)return R(t,{click:r,mouseup:i},n)})}const ft=/* @__PURE__ */T({build:(e,n,r)=>t(n),config:/* @__PURE__ */y({disabled:!1,newTab:!1}),dependencies:[at],name:"@lexical/link/ClickableLink",register:(t,e,n)=>gt(t,n.getOutput())});function dt(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])}}}const ht=/((https?:\/\/(www\.)?)|(www\.))[-\p{L}\p{N}@:%._+~#=]{1,256}\.[\p{L}\p{N}]{1,6}(?:[-\p{L}\p{N}()@:%_+.~#?&//=]*[\p{L}\p{N}()@_~#?&//=])?/u,pt=t=>{const e=ht.exec(t);if(null===e)return null;let n=e[0],r=0;for(const t of n)"("===t?r++:")"===t&&r--;for(;r<0&&n.endsWith(")");)n=n.slice(0,-1),r++;return{index:e.index,length:n.length,text:n,url:n.startsWith("http")?n:`https://${n}`}},_t=dt(/(([^<>()[\]\\.,;:\s@"]{1,64}(\.[^<>()[\]\\.,;:\s@"]{1,64}){0,63})|(".{1,255}"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]{1,63}\.){1,127}[a-zA-Z]{2,63}))/,t=>`mailto:${t}`);function mt(t,e){for(let n=0;n<e.length;n++){const r=e[n](t);if(r)return r}return null}const xt=/[.,;\s]/;function bt(t,e){return e.test(t)}function kt(t,e){return bt(t[t.length-1],e)}function Ut(t,e){return bt(t[0],e)}function vt(t,e){let n=t.getPreviousSibling();return _(n)&&(n=n.getLastDescendant()),null===n||M(n)||A(n)&&kt(n.getTextContent(),e)}function Tt(t,e){let n=t.getNextSibling();return _(n)&&(n=n.getFirstDescendant()),null===n||M(n)||A(n)&&Ut(n.getTextContent(),e)}function Ct(t,e,n,r,i){if(!(t>0?bt(r[t-1],n):vt(i[0],n)))return!1;return e<r.length?bt(r[e],n):Tt(i[i.length-1],n)}function Lt(t,e,n){const r=[],i=[],l=[];let s=0,o=0;const u=[...t];for(;u.length>0;){const t=u[0],a=t.getTextContent().length,c=o;o+a<=e?(r.push(t),s+=a):c>=n?l.push(t):i.push(t),o+=a,u.shift()}return[s,r,i,l]}function St(t,e,n,r){const i=tt(r.url,r.attributes);if(1===t.length){let l,s=t[0];0===e?[l,s]=s.splitText(n):[,l,s]=s.splitText(e,n);const o=E(r.text);return o.setFormat(l.getFormat()),o.setDetail(l.getDetail()),o.setStyle(l.getStyle()),i.append(o),l.replace(i),s}if(t.length>1){const r=t[0];let l,s=r.getTextContent().length;0===e?l=r:[,l]=r.splitText(e);const u=[];let a;for(let e=1;e<t.length;e++){const r=t[e],i=r.getTextContent().length,l=s;if(l<n)if(s+i<=n)u.push(r);else{const[t,e]=r.splitText(n-l);u.push(t),a=e}s+=i}const f=c(),d=f?f.getNodes().find(A):void 0,h=E(l.getTextContent());return h.setFormat(l.getFormat()),h.setDetail(l.getDetail()),h.setStyle(l.getStyle()),i.append(h,...u),d&&d===l&&(o(f)?h.select(f.anchor.offset,f.focus.offset):g(f)&&h.select(0,h.getTextContent().length)),l.replace(i),a}}function Nt(t,e,n,r){const i=t.getChildren(),l=i.length;for(let e=0;e<l;e++){const r=i[e];if(!A(r)||!r.isSimpleText())return Ot(t),void n(null,t.getURL())}const s=t.getTextContent(),o=mt(s,e);if(null===o||o.text!==s)return Ot(t),void n(null,t.getURL());if(!vt(t,r)||!Tt(t,r))return Ot(t),void n(null,t.getURL());const u=t.getURL();if(u!==o.url&&(t.setURL(o.url),n(o.url,u)),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 Ot(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())}const At={changeHandlers:[],excludeParents:[],matchers:[],separatorRegex:xt};function Pt(t,e=At){const{matchers:n,changeHandlers:r,excludeParents:i,separatorRegex:l=xt}=e,s=(t,e)=>{for(const n of r)n(t,e)};return S(t.registerNodeTransform(F,t=>{const e=t.getParentOrThrow(),r=t.getPreviousSibling();if(et(e))Nt(e,n,s,l);else if(!X(e)&&!i.some(t=>t(e))){if(t.isSimpleText()&&(Ut(t.getTextContent(),l)||!et(r))){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,r){for(const e of t){const t=e.getParent();if(et(t)&&!t.getIsUnlinked())return}let i=[...t];const l=i.map(t=>t.getTextContent()).join("");let s,o=l,u=0;for(;(s=mt(o,e))&&null!==s;){const t=s.index,e=t+s.length;if(Ct(u+t,u+e,r,l,i)){const[r,,l,a]=Lt(i,u+t,u+e);let c=!1;for(const t of l){const e=t.getParent();if(et(e)&&!e.getIsUnlinked()){c=!0;break}}if(c){u+=e,o=o.substring(e);continue}const g=St(l,u+t-r,u+e-r,s);i=g?[g,...a]:a,n(s.url,null),u=0}else u+=e;o=o.substring(e)}}(e,n,s,l)}!function(t,e,n,r){const i=t.getParent(),l=t.getPreviousSibling(),s=t.getNextSibling(),o=t.getTextContent();if(!et(i)||i.getIsUnlinked()){if(et(l)&&!l.getIsUnlinked()&&l.is(t.getPreviousSibling())&&t.getParent()===l.getParent()){if(!Ut(o,r))return Ot(l),void n(null,l.getURL());if(u=o,l.isEmailURI()?/^\.[a-zA-Z]{2,}/.test(u):/^\.[a-zA-Z0-9]{1,}/.test(u)){const i=l.getTextContent()+o,s=mt(i,e);null!==s&&s.text===i&&(l.append(t),Nt(l,e,n,r),n(null,l.getURL()))}}var u;!et(s)||s.getIsUnlinked()||kt(o,r)||s.is(t.getNextSibling())&&t.getParent()===s.getParent()&&(Ot(s),n(null,s.getURL()))}}(t,n,s,l)}}),t.registerCommand(nt,t=>{const e=c();if(null!==t||!o(e))return!1;return e.extract().forEach(t=>{const e=t.getParent();et(e)&&(e.setIsUnlinked(!e.getIsUnlinked()),e.markDirty())}),!1},P))}const yt=/* @__PURE__ */T({config:At,dependencies:[at],mergeConfig(t,e){const n=C(t,e);for(const r of["matchers","changeHandlers","excludeParents"]){const i=e[r];Array.isArray(i)&&(n[r]=[...t[r],...i])}return n},name:"@lexical/link/AutoLink",nodes:[Y],register:Pt});export{tt as $createAutoLinkNode,V as $createLinkNode,et as $isAutoLinkNode,X as $isLinkNode,it as $toggleLink,yt as AutoLinkExtension,Y as AutoLinkNode,ft as ClickableLinkExtension,at as LinkExtension,ct as LinkImportExtension,ot as LinkImportRules,Z as LinkNode,nt as TOGGLE_LINK_COMMAND,_t as autoLinkEmailMatcher,pt as autoLinkUrlMatcher,dt as createLinkMatcherWithRegExp,st as formatUrl,Pt as registerAutoLink,gt as registerClickableLink,ut as registerLink};
|
package/package.json
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
"link"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.48.0",
|
|
12
12
|
"main": "./dist/LexicalLink.js",
|
|
13
13
|
"types": "./dist/typescript-too-old.d.ts",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@lexical/extension": "0.
|
|
16
|
-
"@lexical/html": "0.
|
|
17
|
-
"@lexical/internal": "0.
|
|
18
|
-
"
|
|
19
|
-
"lexical": "0.
|
|
15
|
+
"@lexical/extension": "0.48.0",
|
|
16
|
+
"@lexical/html": "0.48.0",
|
|
17
|
+
"@lexical/internal": "0.48.0",
|
|
18
|
+
"lexical": "0.48.0",
|
|
19
|
+
"@lexical/utils": "0.48.0"
|
|
20
20
|
},
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from 'lexical';
|
|
24
24
|
|
|
25
25
|
import {LinkExtension} from './LexicalLinkExtension';
|
|
26
|
-
import {$isLinkNode} from './LexicalLinkNode';
|
|
26
|
+
import {$isAutoLinkNode, $isLinkNode} from './LexicalLinkNode';
|
|
27
27
|
|
|
28
28
|
function findMatchingDOM<T extends Node>(
|
|
29
29
|
startNode: Node,
|
|
@@ -64,12 +64,15 @@ export function registerClickableLink(
|
|
|
64
64
|
|
|
65
65
|
let url = null;
|
|
66
66
|
let urlTarget = null;
|
|
67
|
+
let isUnlinkedAutolink = false;
|
|
67
68
|
nearestEditor.update(() => {
|
|
68
69
|
const clickedNode = $getNearestNodeFromDOMNode(target);
|
|
69
70
|
if (clickedNode !== null) {
|
|
70
71
|
const maybeLinkNode = $findMatchingParent(clickedNode, $isElementNode);
|
|
71
72
|
if (!stores.disabled.peek()) {
|
|
72
73
|
if ($isLinkNode(maybeLinkNode)) {
|
|
74
|
+
isUnlinkedAutolink =
|
|
75
|
+
$isAutoLinkNode(maybeLinkNode) && maybeLinkNode.getIsUnlinked();
|
|
73
76
|
url = maybeLinkNode.sanitizeUrl(maybeLinkNode.getURL());
|
|
74
77
|
urlTarget = maybeLinkNode.getTarget();
|
|
75
78
|
} else {
|
|
@@ -83,7 +86,7 @@ export function registerClickableLink(
|
|
|
83
86
|
}
|
|
84
87
|
});
|
|
85
88
|
|
|
86
|
-
if (url === null || url === '') {
|
|
89
|
+
if (url === null || url === '' || isUnlinkedAutolink) {
|
|
87
90
|
return;
|
|
88
91
|
}
|
|
89
92
|
|
package/src/LexicalLinkNode.ts
CHANGED
|
@@ -178,6 +178,7 @@ export class LinkNode extends ElementNode {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
sanitizeUrl(url: string): string {
|
|
181
|
+
const rawUrl = url;
|
|
181
182
|
url = formatUrl(url);
|
|
182
183
|
try {
|
|
183
184
|
const parsedUrl = new URL(formatUrl(url));
|
|
@@ -186,7 +187,37 @@ export class LinkNode extends ElementNode {
|
|
|
186
187
|
return 'about:blank';
|
|
187
188
|
}
|
|
188
189
|
} catch {
|
|
189
|
-
|
|
190
|
+
// `new URL()` threw, so we could not verify the protocol via the
|
|
191
|
+
// parser. Preserve fail-secure behavior: default unparseable URLs to
|
|
192
|
+
// `about:blank` and only allow through inputs that positively match an
|
|
193
|
+
// allowlisted scheme.
|
|
194
|
+
//
|
|
195
|
+
// Check the ORIGINAL input, not the `formatUrl()` output: `formatUrl()`
|
|
196
|
+
// prepends `https://` to anything it does not recognize as already
|
|
197
|
+
// having a scheme, which would mask a control-character-obfuscated
|
|
198
|
+
// scheme (e.g. `java\x00script:` becomes `https://java\x00script:`).
|
|
199
|
+
//
|
|
200
|
+
// Before extracting the scheme, strip C0 control characters, DEL and
|
|
201
|
+
// whitespace, mirroring how browsers ignore these when resolving a
|
|
202
|
+
// scheme. Without this, control-character-obfuscated schemes that throw
|
|
203
|
+
// in `new URL()` but are still navigated by some browsers would slip
|
|
204
|
+
// past a naive scheme check and retain their original, attacker-
|
|
205
|
+
// controlled value. Stripping C0 control characters and DEL is the
|
|
206
|
+
// intended, security-relevant behavior here.
|
|
207
|
+
// eslint-disable-next-line no-control-regex
|
|
208
|
+
const normalizedUrl = rawUrl.replace(/[\u0000-\u001F\u007F\s]/g, '');
|
|
209
|
+
const schemeMatch = normalizedUrl.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
210
|
+
if (
|
|
211
|
+
schemeMatch != null &&
|
|
212
|
+
!SUPPORTED_URL_PROTOCOLS.has(`${schemeMatch[1].toLowerCase()}:`)
|
|
213
|
+
) {
|
|
214
|
+
// An explicit, non-allowlisted scheme survived normalization (e.g.
|
|
215
|
+
// `javascript:`, `data:`) — neutralize it. Inputs with no scheme
|
|
216
|
+
// (relative URLs such as `/path` or `#anchor`) or an allowlisted
|
|
217
|
+
// scheme are left unchanged: they cannot carry a dangerous scheme
|
|
218
|
+
// and are handled elsewhere.
|
|
219
|
+
return 'about:blank';
|
|
220
|
+
}
|
|
190
221
|
}
|
|
191
222
|
return url;
|
|
192
223
|
}
|