Link extension for tiptap rich text editor providing automatic link detection, paste handling, click behavior, and XSS protection.
88
Smart link detection system with tokenization and validation for creating links as users type. The autolink system uses linkifyjs tokenization to provide sophisticated URL detection with comprehensive validation.
Creates a ProseMirror plugin that automatically detects and creates links as users type.
/**
* Creates a ProseMirror plugin for automatic link detection
* @param options - Configuration options for autolink behavior
* @returns ProseMirror Plugin instance
*/
function autolink(options: AutolinkOptions): Plugin;Usage Examples:
import { Plugin } from "@tiptap/pm/state";
import { autolink } from "@tiptap/extension-link";
// Create autolink plugin
const autolinkPlugin = autolink({
type: linkMarkType,
defaultProtocol: 'https',
validate: (url) => url.startsWith('http'),
shouldAutoLink: (url) => !url.includes('localhost'),
});
// Plugin is automatically used by Link extension
const editor = new Editor({
extensions: [
Link.configure({
autolink: true, // Enables the autolink plugin
}),
],
});Configuration interface for autolink plugin behavior and validation.
interface AutolinkOptions {
/**
* The link mark type from ProseMirror schema
*/
type: MarkType;
/**
* Default protocol to use when none is specified
* @example 'https'
*/
defaultProtocol: string;
/**
* URL validation function - determines if URL is valid
* @param url - The URL to validate
* @returns True if URL is valid and should be processed
*/
validate: (url: string) => boolean;
/**
* Auto-link decision function - determines if valid URL should be auto-linked
* @param url - The validated URL
* @returns True if URL should be automatically converted to link
*/
shouldAutoLink: (url: string) => boolean;
}Advanced tokenization validation that ensures complete and valid text is hyperlinked.
/**
* Check if the provided tokens form a valid link structure
* Can be a single link token or a link token surrounded by parentheses or square brackets
* Prevents incomplete linking like 'example.com1' -> 'example.com' + '1'
* @param tokens - Array of linkifyjs token objects
* @returns True if tokens form a valid link structure
*/
function isValidLinkStructure(tokens: Array<ReturnType<MultiToken['toObject']>>): boolean;Token Structure Examples:
// Valid single token
[{ value: 'https://example.com', isLink: true }] // ✓ Valid
// Valid wrapped tokens
[
{ value: '(', isLink: false },
{ value: 'https://example.com', isLink: true },
{ value: ')', isLink: false }
] // ✓ Valid
[
{ value: '[', isLink: false },
{ value: 'https://example.com', isLink: true },
{ value: ']', isLink: false }
] // ✓ Valid
// Invalid structures
[
{ value: 'https://example.com', isLink: true },
{ value: '1', isLink: false }
] // ✗ Invalid - incomplete linkThe autolink system detects URLs when users type whitespace or create new paragraphs.
Detection Triggers:
// Autolink triggers on:
// 1. Whitespace after URL
"Visit https://tiptap.dev " // ← Space triggers autolink
// 2. Enter key (new paragraph)
"Check out https://example.com
" // ← Enter triggers autolink
// 3. Unicode whitespace characters
"Link: https://site.com\u00A0" // ← Non-breaking space triggers autolinkDetection Process:
// 1. Document change detection
// 2. Text extraction from changed ranges
// 3. Whitespace-based word splitting
// 4. Tokenization using linkifyjs
// 5. Link structure validation
// 6. URL validation (via validate function)
// 7. Auto-link decision (via shouldAutoLink function)
// 8. Link mark creationComplex autolink configurations for different use cases.
Content-Aware Autolink:
import { Editor } from "@tiptap/core";
import { Link } from "@tiptap/extension-link";
const editor = new Editor({
extensions: [
Link.configure({
autolink: true,
shouldAutoLink: (url) => {
// Don't auto-link in code blocks
const { state } = editor;
const { selection } = state;
const { $from } = selection;
// Check if we're in a code block or code mark
const codeBlock = $from.node().type.name === 'codeBlock';
const codeMark = state.doc.rangeHasMark(
selection.from,
selection.to,
state.schema.marks.code
);
return !codeBlock && !codeMark;
},
validate: (url) => {
// Validate URL format and domain
try {
const urlObj = new URL(url);
const allowedDomains = ['example.com', 'tiptap.dev'];
return allowedDomains.includes(urlObj.hostname);
} catch {
return false;
}
},
}),
],
});Conditional Autolink:
const editor = new Editor({
extensions: [
Link.configure({
autolink: true,
shouldAutoLink: (url) => {
// Context-aware auto-linking rules
// Don't auto-link localhost URLs in production
if (process.env.NODE_ENV === 'production' && url.includes('localhost')) {
return false;
}
// Don't auto-link very long URLs (UX consideration)
if (url.length > 100) {
return false;
}
// Don't auto-link URLs with certain query parameters
if (url.includes('utm_')) {
return false;
}
return true;
},
}),
],
});The autolink system is optimized for performance with several key features:
Efficient Processing:
// 1. Only processes document changes (not every keystroke)
// 2. Limits processing to changed text ranges
// 3. Uses efficient tokenization via linkifyjs
// 4. Avoids duplicate link creation
// 5. Respects code mark boundaries
// 6. Lazy evaluation patternChange Detection:
// The plugin only runs when:
// - Document actually changes (not just cursor movement)
// - Transaction is not marked with 'preventAutolink' meta
// - Changed ranges contain text blocks
// - Text ends with whitespace (triggers detection)The autolink plugin is automatically configured and managed by the Link extension.
Automatic Integration:
// When autolink is enabled in Link configuration:
const editor = new Editor({
extensions: [
Link.configure({
autolink: true, // Automatically adds autolink plugin
shouldAutoLink: (url) => /* custom logic */,
validate: (url) => /* custom validation */,
}),
],
});
// The Link extension automatically:
// 1. Creates autolink plugin with proper configuration
// 2. Passes validation functions to plugin
// 3. Provides mark type reference
// 4. Manages plugin lifecycleThe autolink system includes robust error handling for edge cases.
Error Prevention:
// 1. Graceful handling of invalid URLs
// 2. Prevention of autolink in code contexts
// 3. Validation of token structures
// 4. Whitespace handling for different Unicode ranges
// 5. Transaction safety with preventAutolink meta
// 6. Mark collision detection and prevention/** Configuration options for autolink plugin */
interface AutolinkOptions {
type: MarkType;
defaultProtocol: string;
validate: (url: string) => boolean;
shouldAutoLink: (url: string) => boolean;
}
/** Linkifyjs multi-token interface */
interface MultiToken {
toObject(defaultProtocol?: string): {
value: string;
isLink: boolean;
href?: string;
start: number;
end: number;
};
}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