0
# Automatic Link Detection
1
2
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.
3
4
## Capabilities
5
6
### Autolink Plugin Function
7
8
Creates a ProseMirror plugin that automatically detects and creates links as users type.
9
10
```typescript { .api }
11
/**
12
* Creates a ProseMirror plugin for automatic link detection
13
* @param options - Configuration options for autolink behavior
14
* @returns ProseMirror Plugin instance
15
*/
16
function autolink(options: AutolinkOptions): Plugin;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import { Plugin } from "@tiptap/pm/state";
23
import { autolink } from "@tiptap/extension-link";
24
25
// Create autolink plugin
26
const autolinkPlugin = autolink({
27
type: linkMarkType,
28
defaultProtocol: 'https',
29
validate: (url) => url.startsWith('http'),
30
shouldAutoLink: (url) => !url.includes('localhost'),
31
});
32
33
// Plugin is automatically used by Link extension
34
const editor = new Editor({
35
extensions: [
36
Link.configure({
37
autolink: true, // Enables the autolink plugin
38
}),
39
],
40
});
41
```
42
43
### Autolink Options Interface
44
45
Configuration interface for autolink plugin behavior and validation.
46
47
```typescript { .api }
48
interface AutolinkOptions {
49
/**
50
* The link mark type from ProseMirror schema
51
*/
52
type: MarkType;
53
54
/**
55
* Default protocol to use when none is specified
56
* @example 'https'
57
*/
58
defaultProtocol: string;
59
60
/**
61
* URL validation function - determines if URL is valid
62
* @param url - The URL to validate
63
* @returns True if URL is valid and should be processed
64
*/
65
validate: (url: string) => boolean;
66
67
/**
68
* Auto-link decision function - determines if valid URL should be auto-linked
69
* @param url - The validated URL
70
* @returns True if URL should be automatically converted to link
71
*/
72
shouldAutoLink: (url: string) => boolean;
73
}
74
```
75
76
### Link Structure Validation
77
78
Advanced tokenization validation that ensures complete and valid text is hyperlinked.
79
80
```typescript { .api }
81
/**
82
* Check if the provided tokens form a valid link structure
83
* Can be a single link token or a link token surrounded by parentheses or square brackets
84
* Prevents incomplete linking like 'example.com1' -> 'example.com' + '1'
85
* @param tokens - Array of linkifyjs token objects
86
* @returns True if tokens form a valid link structure
87
*/
88
function isValidLinkStructure(tokens: Array<ReturnType<MultiToken['toObject']>>): boolean;
89
```
90
91
**Token Structure Examples:**
92
93
```typescript
94
// Valid single token
95
[{ value: 'https://example.com', isLink: true }] // ✓ Valid
96
97
// Valid wrapped tokens
98
[
99
{ value: '(', isLink: false },
100
{ value: 'https://example.com', isLink: true },
101
{ value: ')', isLink: false }
102
] // ✓ Valid
103
104
[
105
{ value: '[', isLink: false },
106
{ value: 'https://example.com', isLink: true },
107
{ value: ']', isLink: false }
108
] // ✓ Valid
109
110
// Invalid structures
111
[
112
{ value: 'https://example.com', isLink: true },
113
{ value: '1', isLink: false }
114
] // ✗ Invalid - incomplete link
115
```
116
117
### Autolink Detection Behavior
118
119
The autolink system detects URLs when users type whitespace or create new paragraphs.
120
121
**Detection Triggers:**
122
123
```typescript
124
// Autolink triggers on:
125
// 1. Whitespace after URL
126
"Visit https://tiptap.dev " // ← Space triggers autolink
127
128
// 2. Enter key (new paragraph)
129
"Check out https://example.com
130
" // ← Enter triggers autolink
131
132
// 3. Unicode whitespace characters
133
"Link: https://site.com\u00A0" // ← Non-breaking space triggers autolink
134
```
135
136
**Detection Process:**
137
138
```typescript
139
// 1. Document change detection
140
// 2. Text extraction from changed ranges
141
// 3. Whitespace-based word splitting
142
// 4. Tokenization using linkifyjs
143
// 5. Link structure validation
144
// 6. URL validation (via validate function)
145
// 7. Auto-link decision (via shouldAutoLink function)
146
// 8. Link mark creation
147
```
148
149
### Advanced Autolink Configuration
150
151
Complex autolink configurations for different use cases.
152
153
**Content-Aware Autolink:**
154
155
```typescript
156
import { Editor } from "@tiptap/core";
157
import { Link } from "@tiptap/extension-link";
158
159
const editor = new Editor({
160
extensions: [
161
Link.configure({
162
autolink: true,
163
shouldAutoLink: (url) => {
164
// Don't auto-link in code blocks
165
const { state } = editor;
166
const { selection } = state;
167
const { $from } = selection;
168
169
// Check if we're in a code block or code mark
170
const codeBlock = $from.node().type.name === 'codeBlock';
171
const codeMark = state.doc.rangeHasMark(
172
selection.from,
173
selection.to,
174
state.schema.marks.code
175
);
176
177
return !codeBlock && !codeMark;
178
},
179
validate: (url) => {
180
// Validate URL format and domain
181
try {
182
const urlObj = new URL(url);
183
const allowedDomains = ['example.com', 'tiptap.dev'];
184
return allowedDomains.includes(urlObj.hostname);
185
} catch {
186
return false;
187
}
188
},
189
}),
190
],
191
});
192
```
193
194
**Conditional Autolink:**
195
196
```typescript
197
const editor = new Editor({
198
extensions: [
199
Link.configure({
200
autolink: true,
201
shouldAutoLink: (url) => {
202
// Context-aware auto-linking rules
203
204
// Don't auto-link localhost URLs in production
205
if (process.env.NODE_ENV === 'production' && url.includes('localhost')) {
206
return false;
207
}
208
209
// Don't auto-link very long URLs (UX consideration)
210
if (url.length > 100) {
211
return false;
212
}
213
214
// Don't auto-link URLs with certain query parameters
215
if (url.includes('utm_')) {
216
return false;
217
}
218
219
return true;
220
},
221
}),
222
],
223
});
224
```
225
226
### Performance Considerations
227
228
The autolink system is optimized for performance with several key features:
229
230
**Efficient Processing:**
231
232
```typescript
233
// 1. Only processes document changes (not every keystroke)
234
// 2. Limits processing to changed text ranges
235
// 3. Uses efficient tokenization via linkifyjs
236
// 4. Avoids duplicate link creation
237
// 5. Respects code mark boundaries
238
// 6. Lazy evaluation pattern
239
```
240
241
**Change Detection:**
242
243
```typescript
244
// The plugin only runs when:
245
// - Document actually changes (not just cursor movement)
246
// - Transaction is not marked with 'preventAutolink' meta
247
// - Changed ranges contain text blocks
248
// - Text ends with whitespace (triggers detection)
249
```
250
251
### Integration with Link Extension
252
253
The autolink plugin is automatically configured and managed by the Link extension.
254
255
**Automatic Integration:**
256
257
```typescript
258
// When autolink is enabled in Link configuration:
259
const editor = new Editor({
260
extensions: [
261
Link.configure({
262
autolink: true, // Automatically adds autolink plugin
263
shouldAutoLink: (url) => /* custom logic */,
264
validate: (url) => /* custom validation */,
265
}),
266
],
267
});
268
269
// The Link extension automatically:
270
// 1. Creates autolink plugin with proper configuration
271
// 2. Passes validation functions to plugin
272
// 3. Provides mark type reference
273
// 4. Manages plugin lifecycle
274
```
275
276
### Error Handling
277
278
The autolink system includes robust error handling for edge cases.
279
280
**Error Prevention:**
281
282
```typescript
283
// 1. Graceful handling of invalid URLs
284
// 2. Prevention of autolink in code contexts
285
// 3. Validation of token structures
286
// 4. Whitespace handling for different Unicode ranges
287
// 5. Transaction safety with preventAutolink meta
288
// 6. Mark collision detection and prevention
289
```
290
291
## Types
292
293
```typescript { .api }
294
/** Configuration options for autolink plugin */
295
interface AutolinkOptions {
296
type: MarkType;
297
defaultProtocol: string;
298
validate: (url: string) => boolean;
299
shouldAutoLink: (url: string) => boolean;
300
}
301
302
/** Linkifyjs multi-token interface */
303
interface MultiToken {
304
toObject(defaultProtocol?: string): {
305
value: string;
306
isLink: boolean;
307
href?: string;
308
start: number;
309
end: number;
310
};
311
}
312
```