0
# Utility Functions
1
2
Helper functions for content sanitization, slug generation, and other common markdown processing tasks.
3
4
## Capabilities
5
6
### Content Sanitization
7
8
Built-in sanitizer function for securing URLs and content against XSS and other security vulnerabilities.
9
10
```typescript { .api }
11
/**
12
* Default sanitizer function for URLs and attribute values
13
* @param input - The input string to sanitize
14
* @returns Sanitized string or null if blocked
15
*/
16
function sanitizer(input: string): string | null;
17
18
/**
19
* Custom sanitizer function type for advanced security controls
20
* @param value - The attribute value to sanitize
21
* @param tag - The HTML tag containing the attribute
22
* @param attribute - The attribute name being sanitized
23
* @returns Sanitized value or null to remove the attribute
24
*/
25
type SanitizerFunction = (
26
value: string,
27
tag: HTMLTags,
28
attribute: string
29
) => string | null;
30
```
31
32
**Usage Examples:**
33
34
```typescript
35
import { sanitizer } from "markdown-to-jsx";
36
37
// Basic sanitization
38
const safeUrl = sanitizer("https://example.com"); // "https://example.com"
39
const blockedJs = sanitizer("javascript:alert('xss')"); // null
40
const blockedVbs = sanitizer("vbscript:msgbox('xss')"); // null
41
const blockedData = sanitizer("data:text/html,<script>"); // null
42
43
// Safe data URLs are allowed
44
const safeImage = sanitizer("data:image/png;base64,iVBOR..."); // allowed
45
46
// Custom sanitizer implementation
47
const strictSanitizer = (value, tag, attribute) => {
48
// Block all external URLs
49
if (attribute === 'href' || attribute === 'src') {
50
if (value.startsWith('http://') || value.startsWith('https://')) {
51
return null; // Block external resources
52
}
53
}
54
55
// Use default sanitizer for other cases
56
return sanitizer(value);
57
};
58
59
// Apply custom sanitizer
60
const options = {
61
sanitizer: strictSanitizer
62
};
63
64
const result = compiler(markdownWithLinks, options);
65
```
66
67
### Slug Generation
68
69
Convert text strings to URL-safe slugs for heading IDs and anchor links.
70
71
```typescript { .api }
72
/**
73
* Convert string to URL-safe slug for heading IDs
74
* @param str - Input string to convert to slug
75
* @returns URL-safe slug string
76
*/
77
function slugify(str: string): string;
78
79
/**
80
* Custom slug generation function type
81
* @param input - Input string to convert
82
* @param defaultFn - Default slugify function to fall back to
83
* @returns Custom slug string
84
*/
85
type SlugifyFunction = (
86
input: string,
87
defaultFn: (input: string) => string
88
) => string;
89
```
90
91
**Usage Examples:**
92
93
```typescript
94
import { slugify } from "markdown-to-jsx";
95
96
// Basic slug generation
97
slugify("Hello World"); // "hello-world"
98
slugify("Special Characters!@#"); // "special-characters"
99
slugify("Àccented Tëxt"); // "accented-text"
100
slugify("Multiple Spaces"); // "multiple-spaces"
101
slugify("123 Numbers"); // "123-numbers"
102
103
// Custom slugify function
104
const customSlugify = (input, defaultFn) => {
105
// Add timestamp to make unique
106
const baseSlug = defaultFn(input);
107
return `${baseSlug}-${Date.now()}`;
108
};
109
110
// Custom slugify with prefix
111
const prefixedSlugify = (input, defaultFn) => {
112
const baseSlug = defaultFn(input);
113
return `section-${baseSlug}`;
114
};
115
116
// Apply custom slugify
117
const options = {
118
slugify: customSlugify
119
};
120
121
const markdownWithHeadings = `
122
# Main Title
123
## Sub Title
124
### Another Heading
125
`;
126
127
const result = compiler(markdownWithHeadings, options);
128
// Generates unique IDs: main-title-1634567890123, etc.
129
```
130
131
### Sanitizer Configuration in Options
132
133
Configure sanitization behavior through the options system for comprehensive security control.
134
135
**Usage Examples:**
136
137
```typescript
138
// Disable sanitization (not recommended for untrusted content)
139
const unsafeOptions = {
140
sanitizer: (value) => value // Pass through all values
141
};
142
143
// Strict sanitization
144
const strictOptions = {
145
sanitizer: (value, tag, attribute) => {
146
// Only allow specific domains
147
const allowedDomains = ['example.com', 'trusted-site.org'];
148
149
if (attribute === 'href' || attribute === 'src') {
150
try {
151
const url = new URL(value);
152
if (!allowedDomains.includes(url.hostname)) {
153
return null;
154
}
155
} catch {
156
// Invalid URL, allow relative links
157
if (!value.startsWith('/') && !value.startsWith('#')) {
158
return null;
159
}
160
}
161
}
162
163
// Use default sanitizer for validation
164
return sanitizer(value);
165
}
166
};
167
168
// Content-Security-Policy aware sanitizer
169
const cspSanitizer = (value, tag, attribute) => {
170
// Remove inline styles to comply with CSP
171
if (attribute === 'style') {
172
return null;
173
}
174
175
// Only allow relative URLs for images
176
if (tag === 'img' && attribute === 'src') {
177
if (!value.startsWith('/') && !value.startsWith('./')) {
178
return null;
179
}
180
}
181
182
return sanitizer(value);
183
};
184
```
185
186
### Advanced Utility Patterns
187
188
Complex utility function combinations for sophisticated markdown processing.
189
190
**Usage Examples:**
191
192
```typescript
193
// Utility function factory
194
const createSecureProcessor = (config) => {
195
const customSanitizer = (value, tag, attribute) => {
196
// Apply domain whitelist
197
if (config.allowedDomains && (attribute === 'href' || attribute === 'src')) {
198
try {
199
const url = new URL(value);
200
if (!config.allowedDomains.includes(url.hostname)) {
201
return config.blockExternal ? null : '#blocked';
202
}
203
} catch {
204
// Not a full URL, allow if relative
205
}
206
}
207
208
return sanitizer(value);
209
};
210
211
const customSlugify = (input, defaultFn) => {
212
const baseSlug = defaultFn(input);
213
return config.slugPrefix ? `${config.slugPrefix}-${baseSlug}` : baseSlug;
214
};
215
216
return {
217
sanitizer: customSanitizer,
218
slugify: customSlugify
219
};
220
};
221
222
// Usage
223
const secureConfig = createSecureProcessor({
224
allowedDomains: ['example.com', 'cdn.example.com'],
225
blockExternal: true,
226
slugPrefix: 'doc'
227
});
228
229
const options = {
230
...secureConfig,
231
enforceAtxHeadings: true,
232
disableAutoLink: false
233
};
234
235
// Debugging utilities
236
const debugSanitizer = (value, tag, attribute) => {
237
console.log('Sanitizing:', { value, tag, attribute });
238
const result = sanitizer(value);
239
console.log('Result:', result);
240
return result;
241
};
242
243
const debugSlugify = (input, defaultFn) => {
244
console.log('Slugifying:', input);
245
const result = defaultFn(input);
246
console.log('Slug result:', result);
247
return result;
248
};
249
250
// Performance monitoring utilities
251
const performanceSanitizer = (() => {
252
let callCount = 0;
253
let totalTime = 0;
254
255
return (value, tag, attribute) => {
256
const start = performance.now();
257
const result = sanitizer(value);
258
const end = performance.now();
259
260
callCount++;
261
totalTime += (end - start);
262
263
if (callCount % 100 === 0) {
264
console.log(`Sanitizer performance: ${callCount} calls, ${totalTime.toFixed(2)}ms total`);
265
}
266
267
return result;
268
};
269
})();
270
```
271
272
### Security Best Practices
273
274
Guidelines and patterns for secure markdown processing with the utility functions.
275
276
**Usage Examples:**
277
278
```typescript
279
// Secure configuration for user-generated content
280
const userContentOptions = {
281
// Use strict sanitization
282
sanitizer: (value, tag, attribute) => {
283
// Block all JavaScript
284
if (value.toLowerCase().includes('javascript:')) {
285
return null;
286
}
287
288
// Block data URLs except images
289
if (value.startsWith('data:') && !value.startsWith('data:image/')) {
290
return null;
291
}
292
293
// Use default sanitizer
294
return sanitizer(value);
295
},
296
297
// Disable HTML parsing for safety
298
disableParsingRawHTML: true,
299
300
// Use predictable slugs
301
slugify: (input, defaultFn) => {
302
// Remove potentially problematic characters
303
const cleaned = input.replace(/[<>]/g, '');
304
return defaultFn(cleaned);
305
}
306
};
307
308
// Configuration for trusted content
309
const trustedContentOptions = {
310
// Standard sanitization
311
sanitizer: sanitizer,
312
313
// Allow HTML parsing
314
disableParsingRawHTML: false,
315
316
// Enhanced slugs with metadata
317
slugify: (input, defaultFn) => {
318
const baseSlug = defaultFn(input);
319
// Add section prefix for navigation
320
return `section-${baseSlug}`;
321
}
322
};
323
324
// Apply based on content source
325
const processMarkdown = (content, isTrusted = false) => {
326
const options = isTrusted ? trustedContentOptions : userContentOptions;
327
return compiler(content, options);
328
};
329
```