0
# Utilities
1
2
The utils module provides helper functions for custom rule development, text processing, and HTML manipulation. These utilities are exposed to enable consistent behavior in custom rendering rules and plugins.
3
4
## Capabilities
5
6
### Type Checking Utilities
7
8
Functions for runtime type checking and validation.
9
10
```javascript { .api }
11
/**
12
* Check if value is a string
13
* @param obj - Value to check
14
* @returns True if value is a string
15
*/
16
function isString(obj: any): boolean;
17
```
18
19
**Usage Examples:**
20
21
```javascript
22
import { utils } from "remarkable";
23
24
// Type checking in custom rules
25
function customRule(state, start, end, silent) {
26
const line = state.getLines(start, start + 1, 0, false);
27
28
if (!utils.isString(line)) {
29
return false;
30
}
31
32
// Process string content
33
return processLine(line);
34
}
35
36
// Validating plugin options
37
function myPlugin(md, options) {
38
if (options.template && !utils.isString(options.template)) {
39
throw new Error('Template option must be a string');
40
}
41
}
42
```
43
44
### Object Utilities
45
46
Functions for object property checking and manipulation.
47
48
```javascript { .api }
49
/**
50
* Check if object has own property
51
* @param object - Object to check
52
* @param key - Property key to look for
53
* @returns True if object has the property
54
*/
55
function has(object: object, key: string): boolean;
56
57
/**
58
* Merge multiple objects into target object (Object.assign polyfill)
59
* @param target - Target object to merge into
60
* @param sources - Source objects to merge from
61
* @returns Modified target object
62
*/
63
function assign(target: object, ...sources: object[]): object;
64
```
65
66
**Usage Examples:**
67
68
```javascript
69
import { utils } from "remarkable";
70
71
// Property checking in custom rules
72
function processToken(token, options) {
73
if (utils.has(token, 'attrs') && token.attrs) {
74
// Process attributes
75
token.attrs.forEach(([name, value]) => {
76
console.log(`${name}: ${value}`);
77
});
78
}
79
80
if (utils.has(options, 'customClass')) {
81
token.attrSet('class', options.customClass);
82
}
83
}
84
85
// Object merging for plugin options
86
function configurePlugin(defaultOptions, userOptions) {
87
return utils.assign({}, defaultOptions, userOptions);
88
}
89
90
// Example usage
91
const defaultOpts = { theme: 'default', showNumbers: false };
92
const userOpts = { showNumbers: true, highlighter: 'prism' };
93
const finalOpts = utils.assign({}, defaultOpts, userOpts);
94
// Result: { theme: 'default', showNumbers: true, highlighter: 'prism' }
95
```
96
97
### String Processing Utilities
98
99
Functions for processing and escaping text content.
100
101
```javascript { .api }
102
/**
103
* Unescape markdown escape sequences
104
* @param str - String with markdown escapes
105
* @returns String with escapes resolved
106
*/
107
function unescapeMd(str: string): string;
108
109
/**
110
* Replace HTML entities with their character equivalents
111
* @param str - String containing HTML entities
112
* @returns String with entities replaced
113
*/
114
function replaceEntities(str: string): string;
115
116
/**
117
* Escape HTML special characters
118
* @param str - String to escape
119
* @returns HTML-safe string
120
*/
121
function escapeHtml(str: string): string;
122
```
123
124
**Usage Examples:**
125
126
```javascript
127
import { utils } from "remarkable";
128
129
// Unescaping markdown in custom rules
130
function processMarkdown(content) {
131
// Handle escaped characters like \* \_ \#
132
const unescaped = utils.unescapeMd(content);
133
return unescaped;
134
}
135
136
// Entity replacement in text processing
137
function processEntities(text) {
138
// Convert & < > " ' etc. to actual characters
139
const withEntities = utils.replaceEntities(text);
140
return withEntities;
141
}
142
143
// HTML escaping for safe output
144
function customTextRule(tokens, idx, options, env, renderer) {
145
const token = tokens[idx];
146
const safeContent = utils.escapeHtml(token.content);
147
return safeContent;
148
}
149
150
// Example transformations
151
console.log(utils.unescapeMd('\\*not italic\\*')); // β *not italic*
152
console.log(utils.replaceEntities('<p>')); // β <p>
153
console.log(utils.escapeHtml('<script>alert(1)</script>')); // β <script>alert(1)</script>
154
```
155
156
### Entity Processing Utilities
157
158
Advanced utilities for Unicode and HTML entity processing.
159
160
```javascript { .api }
161
/**
162
* Check if Unicode code point is valid
163
* @param code - Unicode code point to validate
164
* @returns True if code point is valid
165
*/
166
function isValidEntityCode(code: number): boolean;
167
168
/**
169
* Convert Unicode code point to string character
170
* @param code - Unicode code point
171
* @returns String character for the code point
172
*/
173
function fromCodePoint(code: number): string;
174
```
175
176
**Usage Examples:**
177
178
```javascript
179
import { utils } from "remarkable";
180
181
// Unicode validation
182
const validCode = 0x1F600; // π emoji
183
console.log(utils.isValidEntityCode(validCode)); // β true
184
185
const invalidCode = 0xD800; // Surrogate pair range
186
console.log(utils.isValidEntityCode(invalidCode)); // β false
187
188
// Code point conversion
189
console.log(utils.fromCodePoint(0x1F600)); // β π
190
console.log(utils.fromCodePoint(0x41)); // β A
191
console.log(utils.fromCodePoint(0x20AC)); // β β¬
192
193
// Custom entity processing
194
function processCustomEntities(text) {
195
return text.replace(/&#(\d+);/g, (match, code) => {
196
const codeNum = parseInt(code, 10);
197
return utils.isValidEntityCode(codeNum)
198
? utils.fromCodePoint(codeNum)
199
: match; // Keep original if invalid
200
});
201
}
202
```
203
204
### Practical Usage Patterns
205
206
Common patterns for using utilities in custom rules and plugins.
207
208
**Custom Renderer Rules:**
209
210
```javascript
211
import { Remarkable, utils } from "remarkable";
212
213
const md = new Remarkable();
214
215
// Safe text rendering with escaping
216
md.renderer.rules.text = function(tokens, idx, options, env, renderer) {
217
const token = tokens[idx];
218
return utils.escapeHtml(token.content);
219
};
220
221
// Custom code block with entity handling
222
md.renderer.rules.code = function(tokens, idx, options, env, renderer) {
223
const token = tokens[idx];
224
const content = utils.replaceEntities(token.content);
225
const escaped = utils.escapeHtml(content);
226
227
if (token.block) {
228
return `<pre><code>${escaped}</code></pre>\n`;
229
}
230
return `<code>${escaped}</code>`;
231
};
232
233
// Link processing with validation
234
md.renderer.rules.link_open = function(tokens, idx, options, env, renderer) {
235
const token = tokens[idx];
236
const href = token.attrGet('href');
237
238
if (utils.isString(href)) {
239
const safeHref = utils.escapeHtml(href);
240
token.attrSet('href', safeHref);
241
}
242
243
return '<a' + renderer.renderAttrs(token) + '>';
244
};
245
```
246
247
**Plugin Development:**
248
249
```javascript
250
function safeContentPlugin(md, options) {
251
const defaultOptions = {
252
escapeLevel: 'basic',
253
preserveEntities: false
254
};
255
256
// Merge options safely
257
const opts = utils.assign({}, defaultOptions, options);
258
259
// Custom rule for safe content processing
260
md.core.ruler.push('safe_content', function(state) {
261
state.tokens.forEach(token => {
262
if (token.type === 'inline' && token.children) {
263
token.children.forEach(child => {
264
if (child.type === 'text' && utils.isString(child.content)) {
265
// Process text content safely
266
if (!opts.preserveEntities) {
267
child.content = utils.replaceEntities(child.content);
268
}
269
if (opts.escapeLevel === 'full') {
270
child.content = utils.escapeHtml(child.content);
271
}
272
}
273
});
274
}
275
});
276
});
277
}
278
279
// Usage
280
const md = new Remarkable().use(safeContentPlugin, {
281
escapeLevel: 'full',
282
preserveEntities: true
283
});
284
```
285
286
**Token Processing:**
287
288
```javascript
289
function processTokens(tokens) {
290
return tokens.map(token => {
291
// Check for required properties
292
if (!utils.has(token, 'type')) {
293
throw new Error('Token missing required type property');
294
}
295
296
// Process text tokens
297
if (token.type === 'text' && utils.isString(token.content)) {
298
const processed = utils.assign({}, token);
299
processed.content = utils.unescapeMd(token.content);
300
return processed;
301
}
302
303
// Process container tokens
304
if (utils.has(token, 'children') && Array.isArray(token.children)) {
305
const processed = utils.assign({}, token);
306
processed.children = processTokens(token.children);
307
return processed;
308
}
309
310
return token;
311
});
312
}
313
```
314
315
### Utility Function Reference
316
317
Complete reference of all available utility functions with their signatures.
318
319
```javascript { .api }
320
interface Utils {
321
/** Type checking */
322
isString(obj: any): boolean;
323
324
/** Object utilities */
325
has(object: object, key: string): boolean;
326
assign(target: object, ...sources: object[]): object;
327
328
/** String processing */
329
unescapeMd(str: string): string;
330
replaceEntities(str: string): string;
331
escapeHtml(str: string): string;
332
333
/** Entity processing (advanced utilities) */
334
isValidEntityCode(code: number): boolean;
335
fromCodePoint(code: number): string;
336
}
337
338
// Import patterns
339
import { utils } from "remarkable";
340
const { utils } = require("remarkable");
341
342
// Individual function imports (not available - import from utils object)
343
// import { escapeHtml } from "remarkable"; // β Not available
344
// const { escapeHtml } = utils; // β Correct way
345
```