Link extension for tiptap rich text editor providing automatic link detection, paste handling, click behavior, and XSS protection.
88
Editor commands for programmatic link manipulation with chainable API integration. These commands extend the Tiptap Commands interface to provide link-specific functionality.
Sets a link mark on the current selection with specified attributes.
/**
* Set a link mark on the current selection
* @param attributes - Link attributes including href and optional target, rel, class
* @returns Chainable command result
*/
setLink: (attributes: {
href: string;
target?: string | null;
rel?: string | null;
class?: string | null;
}) => ReturnType;Usage Examples:
import { Editor } from "@tiptap/core";
import { Link } from "@tiptap/extension-link";
const editor = new Editor({
extensions: [Link],
});
// Basic link setting
editor.commands.setLink({ href: 'https://tiptap.dev' });
// Link with custom attributes
editor.commands.setLink({
href: 'https://example.com',
target: '_blank',
rel: 'noopener noreferrer',
class: 'external-link',
});
// Chainable with other commands
editor
.chain()
.focus()
.selectAll()
.setLink({ href: 'https://tiptap.dev' })
.run();Toggles a link mark on the current selection. If a link exists, it removes it; if no link exists, it creates one with the provided attributes.
/**
* Toggle a link mark on the current selection
* @param attributes - Optional link attributes. If not provided and link exists, removes the link
* @returns Chainable command result
*/
toggleLink: (attributes?: {
href: string;
target?: string | null;
rel?: string | null;
class?: string | null;
}) => ReturnType;Usage Examples:
// Toggle link with URL
editor.commands.toggleLink({ href: 'https://tiptap.dev' });
// Toggle with custom attributes
editor.commands.toggleLink({
href: 'https://example.com',
target: '_blank',
class: 'toggled-link',
});
// Toggle without attributes (removes existing link)
editor.commands.toggleLink();
// Chainable toggle
editor
.chain()
.focus()
.toggleLink({ href: 'https://tiptap.dev' })
.run();Removes the link mark from the current selection, converting linked text back to plain text.
/**
* Remove link mark from current selection
* @returns Chainable command result
*/
unsetLink: () => ReturnType;Usage Examples:
// Remove link from selection
editor.commands.unsetLink();
// Chainable unset
editor
.chain()
.focus()
.selectAll()
.unsetLink()
.run();
// Conditional link removal
if (editor.isActive('link')) {
editor.commands.unsetLink();
}The Link extension extends the Tiptap Commands interface with link-specific methods.
declare module '@tiptap/core' {
interface Commands<ReturnType> {
link: {
/**
* Set a link mark
* @param attributes The link attributes
*/
setLink: (attributes: {
href: string;
target?: string | null;
rel?: string | null;
class?: string | null;
}) => ReturnType;
/**
* Toggle a link mark
* @param attributes The link attributes
*/
toggleLink: (attributes?: {
href: string;
target?: string | null;
rel?: string | null;
class?: string | null;
}) => ReturnType;
/**
* Unset a link mark
*/
unsetLink: () => ReturnType;
};
}
}All link commands include built-in URL validation to prevent XSS attacks and ensure only allowed URIs are processed.
Validation Behavior:
// Commands automatically validate URLs using the configured isAllowedUri function
editor.commands.setLink({ href: 'javascript:alert("xss")' }); // Returns false, link not set
editor.commands.setLink({ href: 'https://safe-url.com' }); // Returns true, link set
// Custom validation context is used
const isValid = editor.extensionManager.extensions
.find(ext => ext.name === 'link')
.options.isAllowedUri('https://example.com', {
defaultValidate: (url) => /* default validation */,
protocols: ['http', 'https', 'ftp'],
defaultProtocol: 'https'
});All link commands support Tiptap's chainable command API for complex operations.
Usage Examples:
// Complex command chain
editor
.chain()
.focus()
.selectAll()
.unsetLink() // Remove any existing links
.setTextSelection({ from: 10, to: 20 })
.setLink({ href: 'https://tiptap.dev' })
.setTextSelection({ from: 30, to: 40 })
.toggleLink({ href: 'https://example.com' })
.run();
// Conditional chaining
const chain = editor.chain().focus();
if (shouldAddLink) {
chain.setLink({ href: 'https://tiptap.dev' });
} else {
chain.unsetLink();
}
chain.run();Use Tiptap's state checking methods to determine link status before executing commands.
Usage Examples:
// Check if selection has a link
const hasLink = editor.isActive('link');
// Get current link attributes
const linkAttrs = editor.getAttributes('link');
console.log(linkAttrs.href); // Current link URL
// Conditional command execution
if (editor.isActive('link')) {
editor.commands.unsetLink();
} else {
editor.commands.setLink({ href: 'https://tiptap.dev' });
}/** Link command attribute interface */
interface LinkCommandAttributes {
/** Link URL (required) */
href: string;
/** Link target attribute */
target?: string | null;
/** Link relationship attribute */
rel?: string | null;
/** CSS class attribute */
class?: string | null;
}Install with Tessl CLI
npx tessl i tessl/npm-tiptap--extension-linkdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10