@lexical/link 0.44.1-nightly.20260519.0 → 0.45.1-dev.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/{LexicalLink.dev.js → dist/LexicalLink.dev.js} +60 -2
- package/{LexicalLink.dev.mjs → dist/LexicalLink.dev.mjs} +60 -4
- package/{LexicalLink.mjs → dist/LexicalLink.mjs} +2 -0
- package/{LexicalLink.node.mjs → dist/LexicalLink.node.mjs} +2 -0
- package/dist/LexicalLink.prod.js +9 -0
- package/dist/LexicalLink.prod.mjs +9 -0
- package/dist/LinkImportExtension.d.ts +23 -0
- package/{index.d.ts → dist/index.d.ts} +1 -0
- package/package.json +33 -17
- package/src/ClickableLinkExtension.ts +142 -0
- package/src/LexicalAutoLinkExtension.ts +639 -0
- package/src/LexicalLinkExtension.ts +164 -0
- package/src/LexicalLinkNode.ts +964 -0
- package/src/LinkImportExtension.ts +67 -0
- package/src/index.ts +43 -0
- package/LexicalLink.prod.js +0 -9
- package/LexicalLink.prod.mjs +0 -9
- /package/{ClickableLinkExtension.d.ts → dist/ClickableLinkExtension.d.ts} +0 -0
- /package/{LexicalAutoLinkExtension.d.ts → dist/LexicalAutoLinkExtension.d.ts} +0 -0
- /package/{LexicalLink.js → dist/LexicalLink.js} +0 -0
- /package/{LexicalLink.js.flow → dist/LexicalLink.js.flow} +0 -0
- /package/{LexicalLinkExtension.d.ts → dist/LexicalLinkExtension.d.ts} +0 -0
- /package/{LexicalLinkNode.d.ts → dist/LexicalLinkNode.d.ts} +0 -0
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
var utils = require('@lexical/utils');
|
|
12
12
|
var lexical = require('lexical');
|
|
13
13
|
var extension = require('@lexical/extension');
|
|
14
|
+
var html = require('@lexical/html');
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -787,8 +788,9 @@ function registerLink(editor, stores) {
|
|
|
787
788
|
if (!validateUrl(clipboardText)) {
|
|
788
789
|
return false;
|
|
789
790
|
}
|
|
790
|
-
//
|
|
791
|
-
|
|
791
|
+
// Skip link wrapping for non-simple text nodes (e.g. code blocks).
|
|
792
|
+
const nodes = selection.getNodes();
|
|
793
|
+
if (!nodes.some(node => lexical.$isElementNode(node) || lexical.$isTextNode(node) && !node.isSimpleText())) {
|
|
792
794
|
editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
|
|
793
795
|
...attributes,
|
|
794
796
|
url: clipboardText
|
|
@@ -1344,6 +1346,60 @@ const AutoLinkExtension = lexical.defineExtension({
|
|
|
1344
1346
|
register: registerAutoLink
|
|
1345
1347
|
});
|
|
1346
1348
|
|
|
1349
|
+
/**
|
|
1350
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1351
|
+
*
|
|
1352
|
+
* This source code is licensed under the MIT license found in the
|
|
1353
|
+
* LICENSE file in the root directory of this source tree.
|
|
1354
|
+
*
|
|
1355
|
+
*/
|
|
1356
|
+
|
|
1357
|
+
const AnchorRule = html.defineImportRule({
|
|
1358
|
+
$import: (ctx, el) => {
|
|
1359
|
+
if (!el.textContent && el.children.length === 0) {
|
|
1360
|
+
return [];
|
|
1361
|
+
}
|
|
1362
|
+
// Use no schema here: when the `<a>` contains block descendants
|
|
1363
|
+
// (e.g. `<a><h1>x</h1><div>y</div></a>`), we want them lifted so each
|
|
1364
|
+
// block becomes a sibling at the link's level, with the link wrapping
|
|
1365
|
+
// its inline content. $distributeInlineWrapper handles both the
|
|
1366
|
+
// common all-inline case (single LinkNode wrapping the run) and the
|
|
1367
|
+
// mixed-block case (per-block recursion).
|
|
1368
|
+
const href = el.getAttribute('href') || '';
|
|
1369
|
+
const attrs = {
|
|
1370
|
+
rel: el.getAttribute('rel'),
|
|
1371
|
+
target: el.getAttribute('target'),
|
|
1372
|
+
title: el.getAttribute('title')
|
|
1373
|
+
};
|
|
1374
|
+
return html.$distributeInlineWrapper(ctx.$importChildren(el), () => $createLinkNode(href, attrs));
|
|
1375
|
+
},
|
|
1376
|
+
match: html.sel.tag('a'),
|
|
1377
|
+
name: '@lexical/link/a'
|
|
1378
|
+
});
|
|
1379
|
+
|
|
1380
|
+
/**
|
|
1381
|
+
* Import rules for {@link LinkNode}.
|
|
1382
|
+
*
|
|
1383
|
+
* @experimental
|
|
1384
|
+
*/
|
|
1385
|
+
const LinkImportRules = [AnchorRule];
|
|
1386
|
+
|
|
1387
|
+
/**
|
|
1388
|
+
* Bundles {@link LinkImportRules} together with the runtime
|
|
1389
|
+
* {@link LinkExtension}. The application is expected to already have
|
|
1390
|
+
* `CoreImportExtension` (or some equivalent) in its dependency graph —
|
|
1391
|
+
* the core/text/paragraph/inline-format rules are a shared baseline,
|
|
1392
|
+
* not something this leaf importer should re-declare.
|
|
1393
|
+
*
|
|
1394
|
+
* @experimental
|
|
1395
|
+
*/
|
|
1396
|
+
const LinkImportExtension = lexical.defineExtension({
|
|
1397
|
+
dependencies: [LinkExtension, lexical.configExtension(html.DOMImportExtension, {
|
|
1398
|
+
rules: LinkImportRules
|
|
1399
|
+
})],
|
|
1400
|
+
name: '@lexical/link/Import'
|
|
1401
|
+
});
|
|
1402
|
+
|
|
1347
1403
|
/**
|
|
1348
1404
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1349
1405
|
*
|
|
@@ -1365,6 +1421,8 @@ exports.AutoLinkExtension = AutoLinkExtension;
|
|
|
1365
1421
|
exports.AutoLinkNode = AutoLinkNode;
|
|
1366
1422
|
exports.ClickableLinkExtension = ClickableLinkExtension;
|
|
1367
1423
|
exports.LinkExtension = LinkExtension;
|
|
1424
|
+
exports.LinkImportExtension = LinkImportExtension;
|
|
1425
|
+
exports.LinkImportRules = LinkImportRules;
|
|
1368
1426
|
exports.LinkNode = LinkNode;
|
|
1369
1427
|
exports.TOGGLE_LINK_COMMAND = TOGGLE_LINK_COMMAND;
|
|
1370
1428
|
exports.createLinkMatcherWithRegExp = createLinkMatcherWithRegExp;
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { addClassNamesToElement, isHTMLAnchorElement, $findMatchingParent, $insertNodeToNearestRootAtCaret, mergeRegister, objectKlassEquals } from '@lexical/utils';
|
|
10
|
-
import { ElementNode, $copyNode, $isRangeSelection, $applyNodeReplacement, createCommand, $getSelection, $isNodeSelection, $normalizeSelection__EXPERIMENTAL, $setSelection, $getChildCaret, $isElementNode, $rewindSiblingCaret, $caretFromPoint, $normalizeCaret, $isSiblingCaret, $setPointFromCaret, defineExtension, shallowMergeConfig, COMMAND_PRIORITY_EDITOR, PASTE_COMMAND, COMMAND_PRIORITY_LOW, safeCast, isDOMNode, getNearestEditorFromDOMNode, $getNearestNodeFromDOMNode, TextNode, $
|
|
10
|
+
import { ElementNode, $copyNode, $isRangeSelection, $applyNodeReplacement, createCommand, $getSelection, $isNodeSelection, $normalizeSelection__EXPERIMENTAL, $setSelection, $getChildCaret, $isElementNode, $rewindSiblingCaret, $caretFromPoint, $normalizeCaret, $isSiblingCaret, $setPointFromCaret, defineExtension, shallowMergeConfig, COMMAND_PRIORITY_EDITOR, PASTE_COMMAND, $isTextNode, COMMAND_PRIORITY_LOW, safeCast, isDOMNode, getNearestEditorFromDOMNode, $getNearestNodeFromDOMNode, TextNode, $isLineBreakNode, $createTextNode, configExtension } from 'lexical';
|
|
11
11
|
import { namedSignals, effect } from '@lexical/extension';
|
|
12
|
+
import { DOMImportExtension, defineImportRule, sel, $distributeInlineWrapper } from '@lexical/html';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -785,8 +786,9 @@ function registerLink(editor, stores) {
|
|
|
785
786
|
if (!validateUrl(clipboardText)) {
|
|
786
787
|
return false;
|
|
787
788
|
}
|
|
788
|
-
//
|
|
789
|
-
|
|
789
|
+
// Skip link wrapping for non-simple text nodes (e.g. code blocks).
|
|
790
|
+
const nodes = selection.getNodes();
|
|
791
|
+
if (!nodes.some(node => $isElementNode(node) || $isTextNode(node) && !node.isSimpleText())) {
|
|
790
792
|
editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
|
|
791
793
|
...attributes,
|
|
792
794
|
url: clipboardText
|
|
@@ -1342,6 +1344,60 @@ const AutoLinkExtension = defineExtension({
|
|
|
1342
1344
|
register: registerAutoLink
|
|
1343
1345
|
});
|
|
1344
1346
|
|
|
1347
|
+
/**
|
|
1348
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1349
|
+
*
|
|
1350
|
+
* This source code is licensed under the MIT license found in the
|
|
1351
|
+
* LICENSE file in the root directory of this source tree.
|
|
1352
|
+
*
|
|
1353
|
+
*/
|
|
1354
|
+
|
|
1355
|
+
const AnchorRule = defineImportRule({
|
|
1356
|
+
$import: (ctx, el) => {
|
|
1357
|
+
if (!el.textContent && el.children.length === 0) {
|
|
1358
|
+
return [];
|
|
1359
|
+
}
|
|
1360
|
+
// Use no schema here: when the `<a>` contains block descendants
|
|
1361
|
+
// (e.g. `<a><h1>x</h1><div>y</div></a>`), we want them lifted so each
|
|
1362
|
+
// block becomes a sibling at the link's level, with the link wrapping
|
|
1363
|
+
// its inline content. $distributeInlineWrapper handles both the
|
|
1364
|
+
// common all-inline case (single LinkNode wrapping the run) and the
|
|
1365
|
+
// mixed-block case (per-block recursion).
|
|
1366
|
+
const href = el.getAttribute('href') || '';
|
|
1367
|
+
const attrs = {
|
|
1368
|
+
rel: el.getAttribute('rel'),
|
|
1369
|
+
target: el.getAttribute('target'),
|
|
1370
|
+
title: el.getAttribute('title')
|
|
1371
|
+
};
|
|
1372
|
+
return $distributeInlineWrapper(ctx.$importChildren(el), () => $createLinkNode(href, attrs));
|
|
1373
|
+
},
|
|
1374
|
+
match: sel.tag('a'),
|
|
1375
|
+
name: '@lexical/link/a'
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
/**
|
|
1379
|
+
* Import rules for {@link LinkNode}.
|
|
1380
|
+
*
|
|
1381
|
+
* @experimental
|
|
1382
|
+
*/
|
|
1383
|
+
const LinkImportRules = [AnchorRule];
|
|
1384
|
+
|
|
1385
|
+
/**
|
|
1386
|
+
* Bundles {@link LinkImportRules} together with the runtime
|
|
1387
|
+
* {@link LinkExtension}. The application is expected to already have
|
|
1388
|
+
* `CoreImportExtension` (or some equivalent) in its dependency graph —
|
|
1389
|
+
* the core/text/paragraph/inline-format rules are a shared baseline,
|
|
1390
|
+
* not something this leaf importer should re-declare.
|
|
1391
|
+
*
|
|
1392
|
+
* @experimental
|
|
1393
|
+
*/
|
|
1394
|
+
const LinkImportExtension = defineExtension({
|
|
1395
|
+
dependencies: [LinkExtension, configExtension(DOMImportExtension, {
|
|
1396
|
+
rules: LinkImportRules
|
|
1397
|
+
})],
|
|
1398
|
+
name: '@lexical/link/Import'
|
|
1399
|
+
});
|
|
1400
|
+
|
|
1345
1401
|
/**
|
|
1346
1402
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1347
1403
|
*
|
|
@@ -1354,4 +1410,4 @@ const AutoLinkExtension = defineExtension({
|
|
|
1354
1410
|
/** @deprecated renamed to {@link $toggleLink} by @lexical/eslint-plugin rules-of-lexical */
|
|
1355
1411
|
const toggleLink = $toggleLink;
|
|
1356
1412
|
|
|
1357
|
-
export { $createAutoLinkNode, $createLinkNode, $isAutoLinkNode, $isLinkNode, $toggleLink, AutoLinkExtension, AutoLinkNode, ClickableLinkExtension, LinkExtension, LinkNode, TOGGLE_LINK_COMMAND, createLinkMatcherWithRegExp, formatUrl, registerAutoLink, registerClickableLink, registerLink, toggleLink };
|
|
1413
|
+
export { $createAutoLinkNode, $createLinkNode, $isAutoLinkNode, $isLinkNode, $toggleLink, AutoLinkExtension, AutoLinkNode, ClickableLinkExtension, LinkExtension, LinkImportExtension, LinkImportRules, LinkNode, TOGGLE_LINK_COMMAND, createLinkMatcherWithRegExp, formatUrl, registerAutoLink, registerClickableLink, registerLink, toggleLink };
|
|
@@ -18,6 +18,8 @@ export const AutoLinkExtension = mod.AutoLinkExtension;
|
|
|
18
18
|
export const AutoLinkNode = mod.AutoLinkNode;
|
|
19
19
|
export const ClickableLinkExtension = mod.ClickableLinkExtension;
|
|
20
20
|
export const LinkExtension = mod.LinkExtension;
|
|
21
|
+
export const LinkImportExtension = mod.LinkImportExtension;
|
|
22
|
+
export const LinkImportRules = mod.LinkImportRules;
|
|
21
23
|
export const LinkNode = mod.LinkNode;
|
|
22
24
|
export const TOGGLE_LINK_COMMAND = mod.TOGGLE_LINK_COMMAND;
|
|
23
25
|
export const createLinkMatcherWithRegExp = mod.createLinkMatcherWithRegExp;
|
|
@@ -16,6 +16,8 @@ export const AutoLinkExtension = mod.AutoLinkExtension;
|
|
|
16
16
|
export const AutoLinkNode = mod.AutoLinkNode;
|
|
17
17
|
export const ClickableLinkExtension = mod.ClickableLinkExtension;
|
|
18
18
|
export const LinkExtension = mod.LinkExtension;
|
|
19
|
+
export const LinkImportExtension = mod.LinkImportExtension;
|
|
20
|
+
export const LinkImportRules = mod.LinkImportRules;
|
|
19
21
|
export const LinkNode = mod.LinkNode;
|
|
20
22
|
export const TOGGLE_LINK_COMMAND = mod.TOGGLE_LINK_COMMAND;
|
|
21
23
|
export const createLinkMatcherWithRegExp = mod.createLinkMatcherWithRegExp;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
"use strict";var e=require("@lexical/utils"),t=require("lexical"),n=require("@lexical/extension"),r=require("@lexical/html");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(t){const n=document.createElement("a");return this.updateLinkDOM(null,n,t),e.addClassNamesToElement(n,t.theme.link),n}updateLinkDOM(t,n,r){if(e.isHTMLAnchorElement(n)){t&&t.__url===this.__url||(n.href=this.sanitizeUrl(this.__url));for(const e of["target","rel","title"]){const r=`__${e}`,i=this[r];t&&t[r]===i||(i?n[e]=i:n.removeAttribute(e))}}}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=k(e);try{const t=new URL(k(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.isParentOf(i)&&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(n){const r=t.$getSelection();let i=null,s=null;function a(){t.$isRangeSelection(r)&&(o(r.anchor,i),o(r.focus,s),t.$normalizeSelection__EXPERIMENTAL(r))}t.$isRangeSelection(r)&&(i=l(r.anchor),s=l(r.focus));let u=!1;for(const r of t.$getChildCaret(n,"next")){const i=r.origin;if(t.$isElementNode(i)&&!i.isInline()){const s=i.getChildren();if(s.length>0){const e=t.$copyNode(n);e.append(...s),i.append(e),u=!0}e.$insertNodeToNearestRootAtCaret(i,t.$rewindSiblingCaret(r),{$shouldSplit:()=>!1})}}function c(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(n.isAttached()){const e=n.getPreviousSibling();if(g(e)&&e.shouldMergeAdjacentLink(n))return i&&(i=c(i,e,n)),s&&(s=c(s,e,n)),e.append(...n.getChildren()),n.remove(),void a();const t=n.getNextSibling();g(t)&&n.shouldMergeAdjacentLink(t)&&(i&&(i=c(i,n,t)),s&&(s=c(s,n,t)),n.append(...t.getChildren()),t.remove(),u=!0)}if(u){if(!n.canBeEmpty()&&n.isEmpty()){const e=n.getParent();n.remove(),e&&e.isEmpty()&&e.remove()}a()}}function u(t){let n=null;if(e.isHTMLAnchorElement(t)){const e=t.textContent;(null!==e&&""!==e||t.children.length>0)&&(n=c(t.getAttribute("href")||"",{rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.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?document.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=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(n,r={}){let i;if(n&&"object"==typeof n){const{url:e,...t}=n;i=e,r={...t,...r}}else i=n;const{target:s,title:l}=r,o=void 0===r.rel?"noreferrer":r.rel,a=t.$getSelection();if(null===a||!t.$isRangeSelection(a)&&!t.$isNodeSelection(a))return;if(t.$isNodeSelection(a)){const t=a.getNodes();if(0===t.length)return;return void t.forEach(t=>{if(null===i){const n=e.$findMatchingParent(t,e=>!h(e)&&g(e));n&&(n.insertBefore(t),0===n.getChildren().length&&n.remove())}else{const n=e.$findMatchingParent(t,e=>!h(e)&&g(e));if(n)n.setURL(i),void 0!==s&&n.setTarget(s),void 0!==o&&n.setRel(o);else{const e=c(i,{rel:o,target:s});t.insertBefore(e),e.append(t)}}})}if(a.isCollapsed()&&null===i)for(const t of a.getNodes()){const n=e.$findMatchingParent(t,e=>!h(e)&&g(e));return void(null!==n&&(n.getParentOrThrow().splice(n.getIndexWithinParent(),0,n.getChildren()),n.remove()))}const u=a.extract();if(null===i){const n=new Set;return void u.forEach(r=>{const i=e.$findMatchingParent(r,e=>!h(e)&&g(e));if(null!==i){const e=i.getKey();if(n.has(e))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))}}}(i,u),n.add(e)}})}const d=new Set,f=e=>{d.has(e.getKey())||(d.add(e.getKey()),e.setURL(i),void 0!==s&&e.setTarget(s),void 0!==o&&e.setRel(o),void 0!==l&&e.setTitle(l))};if(1===u.length){const t=u[0],n=e.$findMatchingParent(t,g);if(null!==n)return f(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 n=null;for(const r of u){if(!r.isAttached())continue;const a=e.$findMatchingParent(r,g);if(a){f(a);continue}if(t.$isElementNode(r)){if(!r.isInline())continue;if(g(r)){if(!(h(r)||null!==n&&n.getParentOrThrow().isParentOf(r))){f(r),n=r;continue}for(const e of r.getChildren())r.insertBefore(e);r.remove();continue}}const u=r.getPreviousSibling();g(u)&&u.is(n)?u.append(r):(n=c(i,{rel:o,target:s,title:l}),r.insertAfter(n),n.append(r))}})}const x=/^\+?[0-9\s()-]{5,}$/;function k(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 N={attributes:void 0,validateUrl:void 0};function $(r,i){return e.mergeRegister(r.registerNodeTransform(s,a),r.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),n.effect(()=>{const n=i.validateUrl.value;if(!n)return;const s=i.attributes.value;return r.registerCommand(t.PASTE_COMMAND,i=>{const l=t.$getSelection();if(!t.$isRangeSelection(l)||l.isCollapsed()||!e.objectKlassEquals(i,ClipboardEvent))return!1;if(null===i.clipboardData)return!1;const o=i.clipboardData.getData("text");if(!n(o))return!1;return!l.getNodes().some(e=>t.$isElementNode(e)||t.$isTextNode(e)&&!e.isSimpleText())&&(r.dispatchCommand(p,{...s,url:o}),i.preventDefault(),!0)},t.COMMAND_PRIORITY_LOW)}))}const T=t.defineExtension({build:(e,t,r)=>n.namedSignals(t),config:N,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)=>$(e,n.getOutput())});function L(n,r,i={}){const s=i=>{const s=i.target;if(!t.isDOMNode(s))return;const l=t.getNearestEditorFromDOMNode(s);if(null===l)return;let o=null,a=null;if(l.update(()=>{const n=t.$getNearestNodeFromDOMNode(s);if(null!==n){const i=e.$findMatchingParent(n,t.$isElementNode);if(!r.disabled.peek())if(g(i))o=i.sanitizeUrl(i.getURL()),a=i.getTarget();else{const t=function(e,t){let n=e;for(;null!=n;){if(t(n))return n;n=n.parentNode}return null}(s,e.isHTMLAnchorElement);null!==t&&(o=t.href,a=t.target)}}}),null===o||""===o)return;const u=n.getEditorState().read(t.$getSelection,{editor:n});if(t.$isRangeSelection(u)&&!u.isCollapsed())return void i.preventDefault();const c="auxclick"===i.type&&1===i.button;window.open(o,r.newTab.peek()||c||i.metaKey||i.ctrlKey||"_blank"===a?"_blank":"_self"),i.preventDefault()},l=e=>{1===e.button&&s(e)};return n.registerRootListener(e=>{if(e)return e.addEventListener("click",s,i),e.addEventListener("mouseup",l,i),()=>{e.removeEventListener("click",s),e.removeEventListener("mouseup",l)}})}const S=t.defineExtension({build:(e,t,r)=>n.namedSignals(t),config:t.safeCast({disabled:!1,newTab:!1}),dependencies:[T],name:"@lexical/link/ClickableLink",register:(e,t,n)=>L(e,n.getOutput())});function b(e,t){for(let n=0;n<t.length;n++){const r=t[n](e);if(r)return r}return null}const C=/[.,;\s]/;function v(e,t){return t.test(e)}function E(e,t){return v(e[e.length-1],t)}function R(e,t){return v(e[0],t)}function U(e,n){let r=e.getPreviousSibling();return t.$isElementNode(r)&&(r=r.getLastDescendant()),null===r||t.$isLineBreakNode(r)||t.$isTextNode(r)&&E(r.getTextContent(),n)}function O(e,n){let r=e.getNextSibling();return t.$isElementNode(r)&&(r=r.getFirstDescendant()),null===r||t.$isLineBreakNode(r)||t.$isTextNode(r)&&R(r.getTextContent(),n)}function A(e,t,n,r,i){if(!(e>0?v(r[e-1],n):U(i[0],n)))return!1;return t<r.length?v(r[t],n):O(i[i.length-1],n)}function M(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 P(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 I(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 y(e),void r(null,e.getURL())}const o=e.getTextContent(),a=b(o,n);if(null===a||a.text!==o)return y(e),void r(null,e.getURL());if(!U(e,i)||!O(e,i))return y(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 y(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 D={changeHandlers:[],excludeParents:[],matchers:[],separatorRegex:C};function w(n,r=D){const{matchers:i,changeHandlers:s,excludeParents:l,separatorRegex:o=C}=r,a=(e,t)=>{for(const n of s)n(e,t)};return e.mergeRegister(n.registerNodeTransform(t.TextNode,e=>{const n=e.getParentOrThrow(),r=e.getPreviousSibling();if(h(n))I(n,i,a,o);else if(!g(n)&&!l.some(e=>e(n))){if(e.isSimpleText()&&(R(e.getTextContent(),o)||!h(r))){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=b(o,t))&&null!==l;){const e=l.index,t=e+l.length;if(A(a+e,a+t,r,s,i)){const[r,,s,u]=M(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=P(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,i,a,o)}!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(!R(o,r))return y(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=b(i,t);null!==l&&l.text===i&&(s.append(e),I(s,t,n,r),n(null,s.getURL()))}}var a;!h(l)||l.getIsUnlinked()||E(o,r)||l.is(e.getNextSibling())&&e.getParent()===l.getParent()&&(y(l),n(null,l.getURL()))}}(e,i,a,o)}}),n.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 F=t.defineExtension({config:D,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:w}),W=[r.defineImportRule({$import:(e,t)=>{if(!t.textContent&&0===t.children.length)return[];const n=t.getAttribute("href")||"",i={rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.getAttribute("title")};return r.$distributeInlineWrapper(e.$importChildren(t),()=>c(n,i))},match:r.sel.tag("a"),name:"@lexical/link/a"})],z=t.defineExtension({dependencies:[T,t.configExtension(r.DOMImportExtension,{rules:W})],name:"@lexical/link/Import"}),J=m;exports.$createAutoLinkNode=f,exports.$createLinkNode=c,exports.$isAutoLinkNode=h,exports.$isLinkNode=g,exports.$toggleLink=m,exports.AutoLinkExtension=F,exports.AutoLinkNode=d,exports.ClickableLinkExtension=S,exports.LinkExtension=T,exports.LinkImportExtension=z,exports.LinkImportRules=W,exports.LinkNode=s,exports.TOGGLE_LINK_COMMAND=p,exports.createLinkMatcherWithRegExp=function(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])}}},exports.formatUrl=k,exports.registerAutoLink=w,exports.registerClickableLink=L,exports.registerLink=$,exports.toggleLink=J;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import{addClassNamesToElement as t,isHTMLAnchorElement as e,$findMatchingParent as n,$insertNodeToNearestRootAtCaret as r,mergeRegister as i,objectKlassEquals as l}from"@lexical/utils";import{ElementNode as s,$copyNode as o,$isRangeSelection as u,$applyNodeReplacement as a,createCommand as c,$getSelection as g,$isNodeSelection as f,$normalizeSelection__EXPERIMENTAL as d,$setSelection as h,$getChildCaret as p,$isElementNode as _,$rewindSiblingCaret as m,$caretFromPoint as x,$normalizeCaret as k,$isSiblingCaret as b,$setPointFromCaret as v,defineExtension as U,shallowMergeConfig as T,COMMAND_PRIORITY_EDITOR as C,PASTE_COMMAND as L,$isTextNode as S,COMMAND_PRIORITY_LOW as O,safeCast as P,isDOMNode as y,getNearestEditorFromDOMNode as A,$getNearestNodeFromDOMNode as N,TextNode as R,$isLineBreakNode as D,$createTextNode as I,configExtension as w}from"lexical";import{namedSignals as E,effect as M}from"@lexical/extension";import{DOMImportExtension as F,defineImportRule as W,sel as J,$distributeInlineWrapper as K}from"@lexical/html";const $=new Set(["http:","https:","mailto:","sms:","tel:"]);class B extends s{__url;__target;__rel;__title;static getType(){return"link"}static clone(t){return new B(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(e){const n=document.createElement("a");return this.updateLinkDOM(null,n,e),t(n,e.theme.link),n}updateLinkDOM(t,n,r){if(e(n)){t&&t.__url===this.__url||(n.href=this.sanitizeUrl(this.__url));for(const e of["target","rel","title"]){const r=`__${e}`,i=this[r];t&&t[r]===i||(i?n[e]=i:n.removeAttribute(e))}}}updateDOM(t,e,n){return this.updateLinkDOM(t,e,n),!1}static importDOM(){return{a:t=>({conversion:G,priority:1})}}static importJSON(t){return Z().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=rt(t);try{const e=new URL(rt(t));if(!$.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=o(this);return this.insertAfter(n,e),n}canInsertTextBefore(){return!1}canInsertTextAfter(){return!1}canBeEmpty(){return!1}isInline(){return!0}extractWithChild(t,e,n){if(!u(e))return!1;const r=e.anchor.getNode(),i=e.focus.getNode();return this.isParentOf(r)&&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 z(t){const e=x(t,"next");return[e,e.getFlipped()]}function j(t,e){for(const n of e)if(n.origin.isAttached()){const e=k(n);return void v(t,e)}}function H(t){const e=g();let n=null,i=null;function l(){u(e)&&(j(e.anchor,n),j(e.focus,i),d(e))}u(e)&&(n=z(e.anchor),i=z(e.focus));let s=!1;for(const e of p(t,"next")){const n=e.origin;if(_(n)&&!n.isInline()){const i=n.getChildren();if(i.length>0){const e=o(t);e.append(...i),n.append(e),s=!0}r(n,m(e),{$shouldSplit:()=>!1})}}function a(t,e,n){const[r,i]=t,l=t=>b(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(q(e)&&e.shouldMergeAdjacentLink(t))return n&&(n=a(n,e,t)),i&&(i=a(i,e,t)),e.append(...t.getChildren()),t.remove(),void l();const r=t.getNextSibling();q(r)&&t.shouldMergeAdjacentLink(r)&&(n&&(n=a(n,t,r)),i&&(i=a(i,t,r)),t.append(...r.getChildren()),r.remove(),s=!0)}if(s){if(!t.canBeEmpty()&&t.isEmpty()){const e=t.getParent();t.remove(),e&&e.isEmpty()&&e.remove()}l()}}function G(t){let n=null;if(e(t)){const e=t.textContent;(null!==e&&""!==e||t.children.length>0)&&(n=Z(t.getAttribute("href")||"",{rel:t.getAttribute("rel"),target:t.getAttribute("target"),title:t.getAttribute("title")}))}return{node:n}}function Z(t="",e){return a(new B(t,e))}function q(t){return t instanceof B}class Q extends B{__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 Q(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?document.createElement("span"):super.createDOM(t)}updateDOM(t,e,n){return super.updateDOM(t,e,n)||t.__isUnlinked!==this.__isUnlinked}static importJSON(t){return V().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=V(this.__url,{isUnlinked:this.__isUnlinked,rel:this.__rel,target:this.__target,title:this.__title});return this.insertAfter(n,e),n}}function V(t="",e){return a(new Q(t,e))}function X(t){return t instanceof Q}const Y=c("TOGGLE_LINK_COMMAND");function tt(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 et(t,e={}){let r;if(t&&"object"==typeof t){const{url:n,...i}=t;r=n,e={...i,...e}}else r=t;const{target:i,title:l}=e,s=void 0===e.rel?"noreferrer":e.rel,a=g();if(null===a||!u(a)&&!f(a))return;if(f(a)){const t=a.getNodes();if(0===t.length)return;return void t.forEach(t=>{if(null===r){const e=n(t,t=>!X(t)&&q(t));e&&(e.insertBefore(t),0===e.getChildren().length&&e.remove())}else{const e=n(t,t=>!X(t)&&q(t));if(e)e.setURL(r),void 0!==i&&e.setTarget(i),void 0!==s&&e.setRel(s);else{const e=Z(r,{rel:s,target:i});t.insertBefore(e),e.append(t)}}})}if(a.isCollapsed()&&null===r)for(const t of a.getNodes()){const e=n(t,t=>!X(t)&&q(t));return void(null!==e&&(e.getParentOrThrow().splice(e.getIndexWithinParent(),0,e.getChildren()),e.remove()))}const c=a.extract();if(null===r){const t=new Set;return void c.forEach(e=>{const r=n(e,t=>!X(t)&&q(t));if(null!==r){const e=r.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 s=r.findIndex(i),u=r.findLastIndex(i),a=0===s,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=o(t);l[l.length-1].insertAfter(n),e.forEach(t=>n.append(t))}}}(r,c),t.add(e)}})}const p=new Set,m=t=>{p.has(t.getKey())||(p.add(t.getKey()),t.setURL(r),void 0!==i&&t.setTarget(i),void 0!==s&&t.setRel(s),void 0!==l&&t.setTitle(l))};if(1===c.length){const t=c[0],e=n(t,q);if(null!==e)return m(e)}!function(t){const e=g();if(!u(e))return t();const n=d(e),r=n.isBackward(),i=tt(n.anchor,r?-1:0),l=tt(n.focus,r?0:-1),s=t();if(i||l){const t=g();if(u(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 c){if(!e.isAttached())continue;const o=n(e,q);if(o){m(o);continue}if(_(e)){if(!e.isInline())continue;if(q(e)){if(!(X(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 u=e.getPreviousSibling();q(u)&&u.is(t)?u.append(e):(t=Z(r,{rel:s,target:i,title:l}),e.insertAfter(t),t.append(e))}})}const nt=/^\+?[0-9\s()-]{5,}$/;function rt(t){return t.match(/^[a-z][a-z0-9+.-]*:/i)||t.match(/^[/#.]/)?t:t.includes("@")?`mailto:${t}`:nt.test(t)?`tel:${t}`:`https://${t}`}function it(t,e){return i(t.registerNodeTransform(B,H),t.registerCommand(Y,t=>{const n=e.validateUrl.peek(),r=e.attributes.peek();if(null===t)return et(null),!0;if("string"==typeof t)return!(void 0!==n&&!n(t))&&(et(t,r),!0);{const{url:e,target:n,rel:i,title:l}=t;return et(e,{...r,rel:i,target:n,title:l}),!0}},C),M(()=>{const n=e.validateUrl.value;if(!n)return;const r=e.attributes.value;return t.registerCommand(L,e=>{const i=g();if(!u(i)||i.isCollapsed()||!l(e,ClipboardEvent))return!1;if(null===e.clipboardData)return!1;const s=e.clipboardData.getData("text");if(!n(s))return!1;return!i.getNodes().some(t=>_(t)||S(t)&&!t.isSimpleText())&&(t.dispatchCommand(Y,{...r,url:s}),e.preventDefault(),!0)},O)}))}const lt=U({build:(t,e,n)=>E(e),config:{attributes:void 0,validateUrl:void 0},mergeConfig(t,e){const n=T(t,e);return t.attributes&&(n.attributes=T(t.attributes,n.attributes)),n},name:"@lexical/link/Link",nodes:()=>[B],register:(t,e,n)=>it(t,n.getOutput())});function st(t,r,i={}){const l=i=>{const l=i.target;if(!y(l))return;const s=A(l);if(null===s)return;let o=null,a=null;if(s.update(()=>{const t=N(l);if(null!==t){const i=n(t,_);if(!r.disabled.peek())if(q(i))o=i.sanitizeUrl(i.getURL()),a=i.getTarget();else{const t=function(t,e){let n=t;for(;null!=n;){if(e(n))return n;n=n.parentNode}return null}(l,e);null!==t&&(o=t.href,a=t.target)}}}),null===o||""===o)return;const c=t.getEditorState().read(g,{editor:t});if(u(c)&&!c.isCollapsed())return void i.preventDefault();const f="auxclick"===i.type&&1===i.button;window.open(o,r.newTab.peek()||f||i.metaKey||i.ctrlKey||"_blank"===a?"_blank":"_self"),i.preventDefault()},s=t=>{1===t.button&&l(t)};return t.registerRootListener(t=>{if(t)return t.addEventListener("click",l,i),t.addEventListener("mouseup",s,i),()=>{t.removeEventListener("click",l),t.removeEventListener("mouseup",s)}})}const ot=U({build:(t,e,n)=>E(e),config:P({disabled:!1,newTab:!1}),dependencies:[lt],name:"@lexical/link/ClickableLink",register:(t,e,n)=>st(t,n.getOutput())});function ut(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 at(t,e){for(let n=0;n<e.length;n++){const r=e[n](t);if(r)return r}return null}const ct=/[.,;\s]/;function gt(t,e){return e.test(t)}function ft(t,e){return gt(t[t.length-1],e)}function dt(t,e){return gt(t[0],e)}function ht(t,e){let n=t.getPreviousSibling();return _(n)&&(n=n.getLastDescendant()),null===n||D(n)||S(n)&&ft(n.getTextContent(),e)}function pt(t,e){let n=t.getNextSibling();return _(n)&&(n=n.getFirstDescendant()),null===n||D(n)||S(n)&&dt(n.getTextContent(),e)}function _t(t,e,n,r,i){if(!(t>0?gt(r[t-1],n):ht(i[0],n)))return!1;return e<r.length?gt(r[e],n):pt(i[i.length-1],n)}function mt(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 xt(t,e,n,r){const i=V(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=I(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 o=[];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)o.push(r);else{const[t,e]=r.splitText(n-l);o.push(t),a=e}s+=i}const c=g(),d=c?c.getNodes().find(S):void 0,h=I(l.getTextContent());return h.setFormat(l.getFormat()),h.setDetail(l.getDetail()),h.setStyle(l.getStyle()),i.append(h,...o),d&&d===l&&(u(c)?h.select(c.anchor.offset,c.focus.offset):f(c)&&h.select(0,h.getTextContent().length)),l.replace(i),a}}function kt(t,e,n,r){const i=t.getChildren(),l=i.length;for(let e=0;e<l;e++){const r=i[e];if(!S(r)||!r.isSimpleText())return bt(t),void n(null,t.getURL())}const s=t.getTextContent(),o=at(s,e);if(null===o||o.text!==s)return bt(t),void n(null,t.getURL());if(!ht(t,r)||!pt(t,r))return bt(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 bt(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 vt={changeHandlers:[],excludeParents:[],matchers:[],separatorRegex:ct};function Ut(t,e=vt){const{matchers:n,changeHandlers:r,excludeParents:l,separatorRegex:s=ct}=e,o=(t,e)=>{for(const n of r)n(t,e)};return i(t.registerNodeTransform(R,t=>{const e=t.getParentOrThrow(),r=t.getPreviousSibling();if(X(e))kt(e,n,o,s);else if(!q(e)&&!l.some(t=>t(e))){if(t.isSimpleText()&&(dt(t.getTextContent(),s)||!X(r))){const e=function(t){const e=[t];let n=t.getNextSibling();for(;null!==n&&S(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(X(t)&&!t.getIsUnlinked())return}let i=[...t];const l=i.map(t=>t.getTextContent()).join("");let s,o=l,u=0;for(;(s=at(o,e))&&null!==s;){const t=s.index,e=t+s.length;if(_t(u+t,u+e,r,l,i)){const[r,,l,a]=mt(i,u+t,u+e);let c=!1;for(const t of l){const e=t.getParent();if(X(e)&&!e.getIsUnlinked()){c=!0;break}}if(c){u+=e,o=o.substring(e);continue}const g=xt(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,o,s)}!function(t,e,n,r){const i=t.getParent(),l=t.getPreviousSibling(),s=t.getNextSibling(),o=t.getTextContent();if(!X(i)||i.getIsUnlinked()){if(X(l)&&!l.getIsUnlinked()&&l.is(t.getPreviousSibling())&&t.getParent()===l.getParent()){if(!dt(o,r))return bt(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=at(i,e);null!==s&&s.text===i&&(l.append(t),kt(l,e,n,r),n(null,l.getURL()))}}var u;!X(s)||s.getIsUnlinked()||ft(o,r)||s.is(t.getNextSibling())&&t.getParent()===s.getParent()&&(bt(s),n(null,s.getURL()))}}(t,n,o,s)}}),t.registerCommand(Y,t=>{const e=g();if(null!==t||!u(e))return!1;return e.extract().forEach(t=>{const e=t.getParent();X(e)&&(e.setIsUnlinked(!e.getIsUnlinked()),e.markDirty())}),!1},O))}const Tt=U({config:vt,dependencies:[lt],mergeConfig(t,e){const n=T(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:[Q],register:Ut}),Ct=[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 K(t.$importChildren(e),()=>Z(n,r))},match:J.tag("a"),name:"@lexical/link/a"})],Lt=U({dependencies:[lt,w(F,{rules:Ct})],name:"@lexical/link/Import"}),St=et;export{V as $createAutoLinkNode,Z as $createLinkNode,X as $isAutoLinkNode,q as $isLinkNode,et as $toggleLink,Tt as AutoLinkExtension,Q as AutoLinkNode,ot as ClickableLinkExtension,lt as LinkExtension,Lt as LinkImportExtension,Ct as LinkImportRules,B as LinkNode,Y as TOGGLE_LINK_COMMAND,ut as createLinkMatcherWithRegExp,rt as formatUrl,Ut as registerAutoLink,st as registerClickableLink,it as registerLink,St as toggleLink};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Import rules for {@link LinkNode}.
|
|
10
|
+
*
|
|
11
|
+
* @experimental
|
|
12
|
+
*/
|
|
13
|
+
export declare const LinkImportRules: import("@lexical/html").DOMImportRule<import("@lexical/html").ElementSelectorBuilder<HTMLAnchorElement, Record<string, never>>>[];
|
|
14
|
+
/**
|
|
15
|
+
* Bundles {@link LinkImportRules} together with the runtime
|
|
16
|
+
* {@link LinkExtension}. The application is expected to already have
|
|
17
|
+
* `CoreImportExtension` (or some equivalent) in its dependency graph —
|
|
18
|
+
* the core/text/paragraph/inline-format rules are a shared baseline,
|
|
19
|
+
* not something this leaf importer should re-declare.
|
|
20
|
+
*
|
|
21
|
+
* @experimental
|
|
22
|
+
*/
|
|
23
|
+
export declare const LinkImportExtension: import("lexical").LexicalExtension<import("lexical").ExtensionConfigBase, "@lexical/link/Import", unknown, unknown>;
|
|
@@ -10,5 +10,6 @@ export { type ClickableLinkConfig, ClickableLinkExtension, registerClickableLink
|
|
|
10
10
|
export { type AutoLinkConfig, AutoLinkExtension, type ChangeHandler, createLinkMatcherWithRegExp, type LinkMatcher, registerAutoLink, } from './LexicalAutoLinkExtension';
|
|
11
11
|
export { LinkExtension, registerLink } from './LexicalLinkExtension';
|
|
12
12
|
export { $createAutoLinkNode, $createLinkNode, $isAutoLinkNode, $isLinkNode, $toggleLink, type AutoLinkAttributes, AutoLinkNode, formatUrl, type LinkAttributes, LinkNode, type SerializedAutoLinkNode, type SerializedLinkNode, TOGGLE_LINK_COMMAND, } from './LexicalLinkNode';
|
|
13
|
+
export { LinkImportExtension, LinkImportRules } from './LinkImportExtension';
|
|
13
14
|
/** @deprecated renamed to {@link $toggleLink} by @lexical/eslint-plugin rules-of-lexical */
|
|
14
15
|
export declare const toggleLink: typeof $toggleLink;
|
package/package.json
CHANGED
|
@@ -8,36 +8,52 @@
|
|
|
8
8
|
"link"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
12
|
-
"main": "LexicalLink.js",
|
|
13
|
-
"types": "index.d.ts",
|
|
11
|
+
"version": "0.45.1-dev.0",
|
|
12
|
+
"main": "./dist/LexicalLink.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@lexical/
|
|
16
|
-
"@lexical/
|
|
17
|
-
"lexical": "0.
|
|
15
|
+
"@lexical/html": "0.45.1-dev.0",
|
|
16
|
+
"@lexical/internal": "0.45.1-dev.0",
|
|
17
|
+
"@lexical/extension": "0.45.1-dev.0",
|
|
18
|
+
"@lexical/utils": "0.45.1-dev.0",
|
|
19
|
+
"lexical": "0.45.1-dev.0"
|
|
18
20
|
},
|
|
19
21
|
"repository": {
|
|
20
22
|
"type": "git",
|
|
21
23
|
"url": "git+https://github.com/facebook/lexical.git",
|
|
22
24
|
"directory": "packages/lexical-link"
|
|
23
25
|
},
|
|
24
|
-
"module": "LexicalLink.mjs",
|
|
26
|
+
"module": "./dist/LexicalLink.mjs",
|
|
25
27
|
"sideEffects": false,
|
|
26
28
|
"exports": {
|
|
27
29
|
".": {
|
|
30
|
+
"source": "./src/index.ts",
|
|
28
31
|
"import": {
|
|
29
|
-
"types": "./index.d.ts",
|
|
30
|
-
"development": "./LexicalLink.dev.mjs",
|
|
31
|
-
"production": "./LexicalLink.prod.mjs",
|
|
32
|
-
"node": "./LexicalLink.node.mjs",
|
|
33
|
-
"default": "./LexicalLink.mjs"
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"development": "./dist/LexicalLink.dev.mjs",
|
|
34
|
+
"production": "./dist/LexicalLink.prod.mjs",
|
|
35
|
+
"node": "./dist/LexicalLink.node.mjs",
|
|
36
|
+
"default": "./dist/LexicalLink.mjs"
|
|
34
37
|
},
|
|
35
38
|
"require": {
|
|
36
|
-
"types": "./index.d.ts",
|
|
37
|
-
"development": "./LexicalLink.dev.js",
|
|
38
|
-
"production": "./LexicalLink.prod.js",
|
|
39
|
-
"default": "./LexicalLink.js"
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"development": "./dist/LexicalLink.dev.js",
|
|
41
|
+
"production": "./dist/LexicalLink.prod.js",
|
|
42
|
+
"default": "./dist/LexicalLink.js"
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
|
-
}
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"src",
|
|
49
|
+
"!src/__tests__",
|
|
50
|
+
"!src/__bench__",
|
|
51
|
+
"!src/__mocks__",
|
|
52
|
+
"!src/**/*.test.ts",
|
|
53
|
+
"!src/**/*.test.tsx",
|
|
54
|
+
"!src/**/*.bench.ts",
|
|
55
|
+
"!src/**/*.bench.tsx",
|
|
56
|
+
"README.md",
|
|
57
|
+
"LICENSE"
|
|
58
|
+
]
|
|
43
59
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {namedSignals, NamedSignalsOutput} from '@lexical/extension';
|
|
10
|
+
import {$findMatchingParent, isHTMLAnchorElement} from '@lexical/utils';
|
|
11
|
+
import {
|
|
12
|
+
$getNearestNodeFromDOMNode,
|
|
13
|
+
$getSelection,
|
|
14
|
+
$isElementNode,
|
|
15
|
+
$isRangeSelection,
|
|
16
|
+
defineExtension,
|
|
17
|
+
getNearestEditorFromDOMNode,
|
|
18
|
+
isDOMNode,
|
|
19
|
+
LexicalEditor,
|
|
20
|
+
safeCast,
|
|
21
|
+
} from 'lexical';
|
|
22
|
+
|
|
23
|
+
import {LinkExtension} from './LexicalLinkExtension';
|
|
24
|
+
import {$isLinkNode} from './LexicalLinkNode';
|
|
25
|
+
|
|
26
|
+
function findMatchingDOM<T extends Node>(
|
|
27
|
+
startNode: Node,
|
|
28
|
+
predicate: (node: Node) => node is T,
|
|
29
|
+
): T | null {
|
|
30
|
+
let node: Node | null = startNode;
|
|
31
|
+
while (node != null) {
|
|
32
|
+
if (predicate(node)) {
|
|
33
|
+
return node;
|
|
34
|
+
}
|
|
35
|
+
node = node.parentNode;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ClickableLinkConfig {
|
|
41
|
+
/** Open clicked links in a new tab when true (default false) */
|
|
42
|
+
newTab: boolean;
|
|
43
|
+
/** Disable this extension when true (default false) */
|
|
44
|
+
disabled: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function registerClickableLink(
|
|
48
|
+
editor: LexicalEditor,
|
|
49
|
+
stores: NamedSignalsOutput<ClickableLinkConfig>,
|
|
50
|
+
eventOptions: Pick<AddEventListenerOptions, 'signal'> = {},
|
|
51
|
+
): () => void {
|
|
52
|
+
const onClick = (event: MouseEvent) => {
|
|
53
|
+
const target = event.target;
|
|
54
|
+
if (!isDOMNode(target)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const nearestEditor = getNearestEditorFromDOMNode(target);
|
|
58
|
+
|
|
59
|
+
if (nearestEditor === null) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let url = null;
|
|
64
|
+
let urlTarget = null;
|
|
65
|
+
nearestEditor.update(() => {
|
|
66
|
+
const clickedNode = $getNearestNodeFromDOMNode(target);
|
|
67
|
+
if (clickedNode !== null) {
|
|
68
|
+
const maybeLinkNode = $findMatchingParent(clickedNode, $isElementNode);
|
|
69
|
+
if (!stores.disabled.peek()) {
|
|
70
|
+
if ($isLinkNode(maybeLinkNode)) {
|
|
71
|
+
url = maybeLinkNode.sanitizeUrl(maybeLinkNode.getURL());
|
|
72
|
+
urlTarget = maybeLinkNode.getTarget();
|
|
73
|
+
} else {
|
|
74
|
+
const a = findMatchingDOM(target, isHTMLAnchorElement);
|
|
75
|
+
if (a !== null) {
|
|
76
|
+
url = a.href;
|
|
77
|
+
urlTarget = a.target;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (url === null || url === '') {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Allow user to select link text without following url
|
|
89
|
+
const selection = editor.getEditorState().read($getSelection, {editor});
|
|
90
|
+
if ($isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const isMiddle = event.type === 'auxclick' && event.button === 1;
|
|
96
|
+
window.open(
|
|
97
|
+
url,
|
|
98
|
+
stores.newTab.peek() ||
|
|
99
|
+
isMiddle ||
|
|
100
|
+
event.metaKey ||
|
|
101
|
+
event.ctrlKey ||
|
|
102
|
+
urlTarget === '_blank'
|
|
103
|
+
? '_blank'
|
|
104
|
+
: '_self',
|
|
105
|
+
);
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const onMouseUp = (event: MouseEvent) => {
|
|
110
|
+
if (event.button === 1) {
|
|
111
|
+
onClick(event);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return editor.registerRootListener(rootElement => {
|
|
116
|
+
if (rootElement) {
|
|
117
|
+
rootElement.addEventListener('click', onClick, eventOptions);
|
|
118
|
+
rootElement.addEventListener('mouseup', onMouseUp, eventOptions);
|
|
119
|
+
return () => {
|
|
120
|
+
rootElement.removeEventListener('click', onClick);
|
|
121
|
+
rootElement.removeEventListener('mouseup', onMouseUp);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Normally in a Lexical editor the `CLICK_COMMAND` on a LinkNode will cause the
|
|
129
|
+
* selection to change instead of opening a link. This extension can be used to
|
|
130
|
+
* restore the default behavior, e.g. when the editor is not editable.
|
|
131
|
+
*/
|
|
132
|
+
export const ClickableLinkExtension = defineExtension({
|
|
133
|
+
build(editor, config, state) {
|
|
134
|
+
return namedSignals(config);
|
|
135
|
+
},
|
|
136
|
+
config: safeCast<ClickableLinkConfig>({disabled: false, newTab: false}),
|
|
137
|
+
dependencies: [LinkExtension],
|
|
138
|
+
name: '@lexical/link/ClickableLink',
|
|
139
|
+
register(editor, config, state) {
|
|
140
|
+
return registerClickableLink(editor, state.getOutput());
|
|
141
|
+
},
|
|
142
|
+
});
|