0
# URL Utilities
1
2
URL utility functions provide robust URL processing, validation, and encoding/decoding capabilities with error handling and security considerations.
3
4
## Capabilities
5
6
### URL Validation
7
8
#### validateUrl
9
10
Validates URLs according to plugin configuration, allowing internal links and configured schemes.
11
12
```typescript { .api }
13
/**
14
* Validate a URL according to plugin configuration
15
* @param editor - Slate editor instance for accessing configuration
16
* @param url - URL string to validate
17
* @returns Whether the URL is valid
18
*/
19
function validateUrl(editor: SlateEditor, url: string): boolean;
20
```
21
22
**Usage Examples:**
23
24
```typescript
25
import { validateUrl } from "@udecode/plate-link";
26
27
// Basic validation
28
const isValid = validateUrl(editor, "https://example.com");
29
console.log(isValid); // true
30
31
// Internal links are allowed
32
const isInternalValid = validateUrl(editor, "/internal/page");
33
console.log(isInternalValid); // true
34
35
// Fragment links are allowed
36
const isFragmentValid = validateUrl(editor, "#section");
37
console.log(isFragmentValid); // true
38
39
// Scheme validation based on plugin config
40
const isMailtoValid = validateUrl(editor, "mailto:user@example.com");
41
// true if 'mailto' in allowedSchemes
42
```
43
44
**Validation Rules:**
45
46
- Internal links starting with `/` are always valid
47
- Fragment links starting with `#` are always valid
48
- External URLs must match allowed schemes from plugin configuration
49
- Empty or null URLs are invalid
50
- Default allowed schemes: `['http', 'https', 'mailto', 'tel']`
51
52
### URL Encoding
53
54
#### encodeUrlIfNeeded
55
56
Conditionally encodes URLs that aren't already encoded, with graceful error handling.
57
58
```typescript { .api }
59
/**
60
* Encode URL if not already encoded, with error handling
61
* @param url - URL string to potentially encode
62
* @returns Encoded URL string
63
*/
64
function encodeUrlIfNeeded(url: string): string;
65
```
66
67
**Usage Examples:**
68
69
```typescript
70
import { encodeUrlIfNeeded } from "@udecode/plate-link";
71
72
// Encode spaces and special characters
73
const encoded = encodeUrlIfNeeded("https://example.com/path with spaces");
74
console.log(encoded); // "https://example.com/path%20with%20spaces"
75
76
// Already encoded URLs are left unchanged
77
const alreadyEncoded = encodeUrlIfNeeded("https://example.com/path%20encoded");
78
console.log(alreadyEncoded); // "https://example.com/path%20encoded"
79
80
// Handles malformed URLs gracefully
81
const malformed = encodeUrlIfNeeded("not-a-url");
82
console.log(malformed); // Returns original string if encoding fails
83
```
84
85
**Encoding Behavior:**
86
87
- Only encodes if the URL isn't already encoded
88
- Handles URI component encoding errors gracefully
89
- Returns original string if encoding fails
90
- Preserves scheme and domain structure
91
92
### URL Decoding
93
94
#### safeDecodeUrl
95
96
Safely decodes URLs with error handling, returning the original URL if decoding fails.
97
98
```typescript { .api }
99
/**
100
* Safely decode a URL with error handling
101
* @param url - URL string to decode
102
* @returns Decoded URL string, or original if decoding fails
103
*/
104
function safeDecodeUrl(url: string): string;
105
```
106
107
**Usage Examples:**
108
109
```typescript
110
import { safeDecodeUrl } from "@udecode/plate-link";
111
112
// Decode percent-encoded URLs
113
const decoded = safeDecodeUrl("https://example.com/path%20with%20spaces");
114
console.log(decoded); // "https://example.com/path with spaces"
115
116
// Handles malformed encoded URLs
117
const malformed = safeDecodeUrl("https://example.com/bad%encoding");
118
console.log(malformed); // Returns original string if decoding fails
119
120
// Already decoded URLs pass through
121
const plainUrl = safeDecodeUrl("https://example.com/plain-path");
122
console.log(plainUrl); // "https://example.com/plain-path"
123
```
124
125
**Decoding Safety:**
126
127
- Catches URI decoding errors gracefully
128
- Returns original URL if decoding fails
129
- Prevents crashes from malformed encoded URLs
130
- Handles edge cases in percent encoding
131
132
### Link Attributes
133
134
#### getLinkAttributes
135
136
Generates proper HTML attributes for link elements, including sanitization and default attributes.
137
138
```typescript { .api }
139
/**
140
* Generate HTML attributes for link elements with sanitization
141
* @param editor - Slate editor instance for configuration access
142
* @param link - Link element to generate attributes for
143
* @returns React anchor element attributes
144
*/
145
function getLinkAttributes(
146
editor: SlateEditor,
147
link: TLinkElement
148
): React.AnchorHTMLAttributes<HTMLAnchorElement>;
149
```
150
151
**Usage Examples:**
152
153
```typescript
154
import { getLinkAttributes } from "@udecode/plate-link";
155
156
// Basic attribute generation
157
const linkElement = {
158
type: 'a',
159
url: 'https://example.com',
160
children: [{ text: 'Example' }]
161
};
162
163
const attributes = getLinkAttributes(editor, linkElement);
164
console.log(attributes);
165
// { href: 'https://example.com', target: '_blank', rel: 'noopener' }
166
167
// With custom target
168
const linkWithTarget = {
169
type: 'a',
170
url: 'https://example.com',
171
target: '_self',
172
children: [{ text: 'Example' }]
173
};
174
175
const customAttributes = getLinkAttributes(editor, linkWithTarget);
176
console.log(customAttributes);
177
// { href: 'https://example.com', target: '_self' }
178
```
179
180
**Attribute Processing:**
181
182
- Applies URL encoding if needed
183
- Merges plugin default attributes
184
- Handles target attribute logic
185
- Applies security attributes for external links
186
- Respects `dangerouslySkipSanitization` option
187
188
### Node Creation
189
190
#### createLinkNode
191
192
Creates properly formatted link nodes with validation and attribute processing.
193
194
```typescript { .api }
195
/**
196
* Create a properly formatted link node
197
* @param editor - Slate editor instance
198
* @param options - Link creation options
199
* @returns Formatted link element
200
*/
201
function createLinkNode(
202
editor: SlateEditor,
203
options: CreateLinkNodeOptions
204
): TLinkElement;
205
206
interface CreateLinkNodeOptions {
207
/** The URL for the link */
208
url: string;
209
/** Child text nodes (defaults to URL as text) */
210
children?: TText[];
211
/** Link target attribute */
212
target?: string;
213
/** Text content (alternative to children) */
214
text?: string;
215
}
216
```
217
218
**Usage Examples:**
219
220
```typescript
221
import { createLinkNode } from "@udecode/plate-link";
222
223
// Create basic link node
224
const linkNode = createLinkNode(editor, {
225
url: "https://example.com",
226
text: "Example Link"
227
});
228
229
// Create with custom children
230
const customLink = createLinkNode(editor, {
231
url: "https://example.com",
232
children: [
233
{ text: "Visit ", bold: true },
234
{ text: "Example" }
235
]
236
});
237
238
// Create with target
239
const externalLink = createLinkNode(editor, {
240
url: "https://external.com",
241
text: "External Link",
242
target: "_blank"
243
});
244
```
245
246
### Advanced URL Processing
247
248
#### URL Scheme Detection
249
250
```typescript
251
import { validateUrl } from "@udecode/plate-link";
252
253
function getUrlScheme(url: string): string | null {
254
try {
255
const urlObj = new URL(url);
256
return urlObj.protocol.slice(0, -1); // Remove trailing colon
257
} catch {
258
return null;
259
}
260
}
261
262
function isExternalUrl(url: string): boolean {
263
return !url.startsWith('/') && !url.startsWith('#') && getUrlScheme(url) !== null;
264
}
265
```
266
267
#### URL Normalization
268
269
```typescript
270
import { encodeUrlIfNeeded, safeDecodeUrl } from "@udecode/plate-link";
271
272
function normalizeUrl(url: string): string {
273
// Decode first to handle double-encoding
274
const decoded = safeDecodeUrl(url);
275
276
// Re-encode to ensure proper encoding
277
return encodeUrlIfNeeded(decoded);
278
}
279
280
function addProtocolIfNeeded(url: string): string {
281
if (!url.includes('://') && !url.startsWith('/') && !url.startsWith('#')) {
282
return `https://${url}`;
283
}
284
return url;
285
}
286
```
287
288
#### Batch URL Processing
289
290
```typescript
291
import { validateUrl, encodeUrlIfNeeded } from "@udecode/plate-link";
292
293
function processUrls(editor: SlateEditor, urls: string[]): Array<{
294
original: string;
295
processed: string;
296
isValid: boolean;
297
}> {
298
return urls.map(url => {
299
const processed = encodeUrlIfNeeded(url);
300
const isValid = validateUrl(editor, processed);
301
302
return {
303
original: url,
304
processed,
305
isValid
306
};
307
});
308
}
309
```