Skip to main content

Overview

The @lexical/link package provides link functionality for Lexical, including manual links, auto-links, and clickable link behavior.

Installation

npm install @lexical/link

Nodes

LinkNode

Represents a hyperlink element.
url
string
required
The link URL
target
string
Link target attribute (e.g., ‘_blank’)
rel
string
Link rel attribute (e.g., ‘noopener noreferrer’)
title
string
Link title attribute
Methods:
getURL()
string
Returns the link URL
setURL(url)
this
Sets the link URL
getTarget()
string | null
Returns the link target
setTarget(target)
this
Sets the link target

AutoLinkNode

Represents an automatically detected link.
isUnlinked
boolean
Whether the auto-link has been manually unlinked

Factory Functions

$createLinkNode

Creates a new LinkNode.
function $createLinkNode(
  url: string,
  attributes?: LinkAttributes
): LinkNode
url
string
required
The link URL
attributes
LinkAttributes
Additional attributes (target, rel, title)
Example:
import { $createLinkNode } from '@lexical/link';

editor.update(() => {
  const link = $createLinkNode('https://example.com', {
    target: '_blank',
    rel: 'noopener noreferrer'
  });
  link.append($createTextNode('Visit Example'));
  $getRoot().append($createParagraphNode().append(link));
});

$createAutoLinkNode

Creates a new AutoLinkNode.
function $createAutoLinkNode(
  url: string,
  attributes?: AutoLinkAttributes
): AutoLinkNode

Type Guards

$isLinkNode

function $isLinkNode(node: LexicalNode | null | undefined): node is LinkNode

$isAutoLinkNode

function $isAutoLinkNode(
  node: LexicalNode | null | undefined
): node is AutoLinkNode

Commands

Toggles link on the current selection.
const TOGGLE_LINK_COMMAND: LexicalCommand<
  string | { url: string; target?: string; rel?: string; title?: string } | null
>
Example:
// Add link
editor.dispatchCommand(TOGGLE_LINK_COMMAND, 'https://example.com');

// Add link with attributes
editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
  url: 'https://example.com',
  target: '_blank',
  rel: 'noopener noreferrer'
});

// Remove link
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);

Utilities

Toggles a link on the current selection.
function $toggleLink(
  url: string | null,
  attributes?: LinkAttributes
): void
url
string | null
required
URL to link to, or null to remove link
attributes
LinkAttributes
Additional link attributes

formatUrl

Formats a URL by adding protocol if missing.
function formatUrl(url: string): string
Example:
formatUrl('example.com'); // Returns 'https://example.com'
formatUrl('http://example.com'); // Returns 'http://example.com'
Registers automatic link detection.
function registerAutoLink(
  editor: LexicalEditor,
  config: AutoLinkConfig
): () => void
config.matchers
LinkMatcher[]
required
Array of link matchers to detect URLs
Returns: Cleanup function

LinkMatcher

Defines a pattern for auto-detecting links.
type LinkMatcher = {
  // Regular expression or function to match URLs
  match: RegExp | ((text: string) => MatchResult | null);
  
  // Optional function to transform matched text to URL
  url?: (match: string) => string;
  
  // Optional function to get link attributes
  attributes?: (match: string) => LinkAttributes;
}

createLinkMatcherWithRegExp

Creates a link matcher from a regular expression.
function createLinkMatcherWithRegExp(
  regExp: RegExp,
  urlTransformer?: (text: string) => string
): LinkMatcher
Example:
import { 
  registerAutoLink, 
  createLinkMatcherWithRegExp 
} from '@lexical/link';

const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*)/;

const EMAIL_REGEX = /([\w.+-]+@[\w-]+\.[\w.-]+)/;

const unregister = registerAutoLink(editor, {
  matchers: [
    createLinkMatcherWithRegExp(URL_REGEX),
    createLinkMatcherWithRegExp(
      EMAIL_REGEX, 
      (text) => `mailto:${text}`
    )
  ]
});
Makes links clickable with customizable behavior.
function registerClickableLink(
  editor: LexicalEditor,
  config: ClickableLinkConfig
): () => void
config.onClick
(event: MouseEvent, url: string) => void
Custom click handler
config.newTab
boolean
default:"true"
Whether to open links in new tab
Example:
import { registerClickableLink } from '@lexical/link';

const unregister = registerClickableLink(editor, {
  newTab: true,
  onClick: (event, url) => {
    console.log('Link clicked:', url);
    // Custom handling (analytics, etc.)
  }
});

Extensions

LinkExtension

Core link extension with LinkNode and AutoLinkNode.
import { createEditor } from 'lexical';
import { LinkExtension } from '@lexical/link';

const editor = createEditor({
  extensions: [LinkExtension]
});

AutoLinkExtension

Adds automatic link detection.
import { LinkExtension, AutoLinkExtension } from '@lexical/link';

const editor = createEditor({
  extensions: [
    LinkExtension,
    AutoLinkExtension.configure({
      matchers: [
        createLinkMatcherWithRegExp(URL_REGEX),
        createLinkMatcherWithRegExp(EMAIL_REGEX, (text) => `mailto:${text}`)
      ]
    })
  ]
});

ClickableLinkExtension

Makes links clickable.
import { 
  LinkExtension, 
  ClickableLinkExtension 
} from '@lexical/link';

const editor = createEditor({
  extensions: [
    LinkExtension,
    ClickableLinkExtension.configure({
      newTab: true,
      onClick: (event, url) => {
        // Custom click handling
      }
    })
  ]
});

Types

LinkAttributes

type LinkAttributes = {
  target?: string;
  rel?: string;
  title?: string;
}

AutoLinkAttributes

type AutoLinkAttributes = LinkAttributes & {
  isUnlinked?: boolean;
}

SerializedLinkNode

type SerializedLinkNode = Spread<
  {
    url: string;
    target?: string;
    rel?: string;
    title?: string;
  },
  SerializedElementNode
>

SerializedAutoLinkNode

type SerializedAutoLinkNode = Spread<
  {
    isUnlinked: boolean;
  },
  SerializedLinkNode
>

Complete Example

import { createEditor } from 'lexical';
import { 
  LinkExtension,
  AutoLinkExtension,
  ClickableLinkExtension,
  $createLinkNode,
  TOGGLE_LINK_COMMAND,
  createLinkMatcherWithRegExp
} from '@lexical/link';

const URL_REGEX = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)/;

const editor = createEditor({
  extensions: [
    LinkExtension,
    AutoLinkExtension.configure({
      matchers: [
        createLinkMatcherWithRegExp(URL_REGEX)
      ]
    }),
    ClickableLinkExtension.configure({
      newTab: true
    })
  ]
});

editor.setRootElement(document.getElementById('editor'));

// Create a link programmatically
editor.update(() => {
  const paragraph = $createParagraphNode();
  const link = $createLinkNode('https://lexical.dev', {
    target: '_blank',
    rel: 'noopener noreferrer'
  });
  link.append($createTextNode('Lexical'));
  paragraph.append(
    $createTextNode('Visit '),
    link,
    $createTextNode(' for more info.')
  );
  $getRoot().append(paragraph);
});

// Toggle link on selection
editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
  url: 'https://example.com',
  target: '_blank'
});

Build docs developers (and LLMs) love