Skip to content

Link

The Link mark applies hyperlink formatting to text. It renders as <a> with href, target, rel, title, and class attributes. Links are semantic data, not formatting - they survive unsetAllMarks() (clear formatting). Included in StarterKit by default.

Select text and apply a link with buttons, keyboard shortcut (Cmd+K / Ctrl+K), or type/paste a URL to see autolink in action.

With the default theme enabled. Click the link toolbar button or use Cmd+K / Ctrl+K to open the URL popover.

Click to try it out

Link is included in StarterKit, so it works out of the box. When using StarterKit, Mod-K opens the LinkPopover with a URL input. URLs are auto-detected when typing (autolink) and when pasting.

To use Link standalone:

With StarterKit, the link toolbar button and Mod-K shortcut open the built-in URL popover automatically:

import { Editor, StarterKit } from '@domternal/core';
import '@domternal/theme';
const editor = new Editor({
element: document.getElementById('editor')!,
extensions: [StarterKit],
content: '<p>Select text and press <code>Cmd+K</code> to add a link. Try typing a URL like example.com followed by a space.</p>',
});

Without StarterKit (standalone Link, no popover), handle the linkEdit event yourself:

import { Editor, Document, Paragraph, Text, Link } from '@domternal/core';
const editor = new Editor({
element: document.getElementById('editor')!,
extensions: [Document, Paragraph, Text, Link],
content: '<p>Visit <a href="https://example.com">Example</a> for more.</p>',
});
// Mod-K emits linkEdit - show your own UI
editor.on('linkEdit', () => {
const url = prompt('URL:');
if (url) editor.chain().focus().setLink({ href: url }).run();
});

To disable Link in StarterKit:

StarterKit.configure({ link: false })
PropertyValue
ProseMirror namelink
TypeMark
HTML tag<a>
Priority1000
isFormattingfalse

The inclusive property is dynamic: when autolink is enabled, the mark is inclusive so typing at the end of a link extends it. When autolink is off, links are not inclusive.

AttributeTypeDefaultDescription
hrefstringnullURL target
targetstring | nullnullLink target (e.g. _blank)
relstring | nullnullRelationship (e.g. noopener noreferrer)
titlestring | nullnullTooltip text
classstring | nullnullCSS classes
SourceCondition
<a>Must have href attribute with a valid URL (validated against protocols)

The parser extracts all 5 attributes (href, target, rel, title, class) from the <a> element. Invalid URLs are rejected.

OptionTypeDefaultDescription
HTMLAttributesRecord<string, unknown>{}Custom HTML attributes added to the rendered <a> element
protocolsstring[]['http:', 'https:', 'mailto:', 'tel:']Allowed URL protocols
openOnClickboolean | 'whenNotEditable'trueWhen to open links on click
addRelNoopenerbooleantrueAuto-add rel="noopener noreferrer" to target="_blank" links
autolinkbooleantrueAuto-convert typed URLs to links
linkOnPastebooleantrueConvert pasted URLs to links
defaultProtocolstring'https'Default protocol for bare URLs
shouldAutoLink(url: string) => booleanundefinedCustom validation for autolink
enableClickSelectionbooleanfalseSelect full link text on click
import { Link } from '@domternal/core';
const CustomLink = Link.configure({
protocols: ['http:', 'https:'],
openOnClick: 'whenNotEditable',
autolink: true,
linkOnPaste: true,
defaultProtocol: 'https',
});

Applies a link to the current selection. Validates the href against allowed protocols.

editor.commands.setLink({ href: 'https://example.com' });
// With target
editor.commands.setLink({
href: 'https://example.com',
target: '_blank',
});

Returns false if the URL is invalid.

Removes the link from the current selection. If the cursor is empty, removes the link from the entire link range around the cursor.

editor.commands.unsetLink();

Toggles a link on the current selection. If the cursor is in a link, removes it. If not, applies the link.

editor.commands.toggleLink({ href: 'https://example.com' });
// With chaining
editor.chain().focus().toggleLink({ href: 'https://example.com' }).run();
KeyAction
Mod-KOpen link popover (linkEdit event)

Mod is Cmd on macOS and Ctrl on Windows/Linux.

Link has no input rules. URLs are detected through the autolink plugin (type a URL followed by a space or punctuation) and the paste plugin (paste a URL to wrap the selection or insert as a link).

Link creates up to 5 ProseMirror plugins:

PluginConditionDescription
linkClickAlwaysOpens links on click (configurable via openOnClick)
linkPastelinkOnPaste: trueConverts pasted URLs to links
linkExitAlwaysPressing ArrowRight at link boundary exits the mark
linkKeepOnSplitAlwaysPressing Enter at link end does not carry the link to the new line
autolinkautolink: trueAuto-converts typed URLs to links on space/punctuation

Link registers a button in the toolbar with the name link in group format at priority 120.

ItemTypeCommandIconShortcutActive when
LinkbuttonunsetLinklinkMod-KLink mark is active on selection

The toolbar button also has emitEvent: 'linkEdit', which triggers the LinkPopover to open when clicked.

import { Link } from '@domternal/core';
import type { LinkOptions, LinkAttributes } from '@domternal/core';
ExportTypeDescription
LinkMark extensionThe link mark extension
LinkOptionsTypeScript typeOptions for Link.configure()
LinkAttributesTypeScript typeAttributes for setLink() / toggleLink()

Link also exports its plugin helpers:

import {
linkClickPlugin,
linkClickPluginKey,
linkPastePlugin,
linkPastePluginKey,
autolinkPlugin,
autolinkPluginKey,
linkExitPlugin,
linkExitPluginKey,
} from '@domternal/core';

Link uses two ProseMirror plugins internally:

  1. Autolink plugin - Watches for text that matches URL patterns as you type. When a valid URL is detected (ending with a space, Enter, or punctuation), it is automatically wrapped in a link mark. Autolink respects the autolink option and only triggers outside code blocks.

  2. Paste handler plugin - When you paste a URL over selected text, the text is converted into a link with that URL instead of replacing the text. When you paste a URL without selection, the URL is inserted as a clickable link. Both behaviors respect the protocols allowlist.

The LinkPopover extension (included in StarterKit) provides the floating UI for editing link URLs. When the cursor is inside a link, the popover shows the URL with edit and remove buttons. Pressing Mod-K opens the popover to create a new link or edit an existing one.

@domternal/core - Link.ts