0
# Regex and Compilation
1
2
Low-level pattern parsing, compilation, and regex generation for advanced use cases. These functions provide direct access to nanomatch's internal pattern processing pipeline for custom applications and debugging.
3
4
## Capabilities
5
6
### Regular Expression Generation
7
8
Convert glob patterns directly to regular expressions for use outside nanomatch.
9
10
```javascript { .api }
11
/**
12
* Create a regular expression from a glob pattern
13
* @param {String} pattern - Glob pattern to convert to regular expression
14
* @param {Object} options - Optional configuration for regex compilation
15
* @returns {RegExp} Compiled regular expression that matches the glob pattern
16
*/
17
nanomatch.makeRe(pattern, options);
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
const nanomatch = require('nanomatch');
24
25
// Basic pattern to regex conversion
26
const jsRegex = nanomatch.makeRe('*.js');
27
console.log(jsRegex);
28
//=> /^(?:(?!\.)(?=.)[^\/]*?\.js)$/
29
30
console.log(jsRegex.test('app.js')); //=> true
31
console.log(jsRegex.test('styles.css')); //=> false
32
33
// Globstar patterns
34
const nestedRegex = nanomatch.makeRe('src/**/*.js');
35
console.log(nestedRegex.test('src/app.js')); //=> true
36
console.log(nestedRegex.test('src/components/ui.js')); //=> true
37
console.log(nestedRegex.test('lib/utils.js')); //=> false
38
39
// Question mark patterns
40
const singleCharRegex = nanomatch.makeRe('test?');
41
console.log(singleCharRegex.test('test1')); //=> true
42
console.log(singleCharRegex.test('test')); //=> false
43
console.log(singleCharRegex.test('test12')); //=> false
44
45
// Bracket patterns
46
const bracketRegex = nanomatch.makeRe('[abc]*.js');
47
console.log(bracketRegex.test('app.js')); //=> true
48
console.log(bracketRegex.test('data.js')); //=> false
49
50
// With options
51
const caseInsensitiveRegex = nanomatch.makeRe('*.JS', { nocase: true });
52
console.log(caseInsensitiveRegex.test('app.js')); //=> true
53
54
// Negation patterns
55
const negationRegex = nanomatch.makeRe('!test*');
56
console.log(negationRegex.test('app.js')); //=> true
57
console.log(negationRegex.test('test.js')); //=> false
58
59
// Using with native regex methods
60
const pattern = nanomatch.makeRe('**/*.{js,ts}');
61
const files = ['app.js', 'utils.ts', 'styles.css'];
62
const sourceFiles = files.filter(file => pattern.test(file));
63
console.log(sourceFiles); //=> ['app.js', 'utils.ts']
64
```
65
66
### Complete Pattern Processing
67
68
Parse and compile patterns with full metadata, AST, and compilation details.
69
70
```javascript { .api }
71
/**
72
* Parse and compile a glob pattern with complete metadata
73
* @param {String} pattern - Glob pattern to parse and compile
74
* @param {Object} options - Optional configuration for parsing and compilation
75
* @returns {Object} Complete compilation result with AST, output, and metadata
76
*/
77
nanomatch.create(pattern, options);
78
79
interface CompilationResult {
80
/** Compiled regex pattern string */
81
output: string;
82
/** Parsed abstract syntax tree */
83
ast: ParseResult;
84
/** Source map if sourcemap option enabled */
85
map?: SourceMap;
86
/** Parser options used during compilation */
87
options: Object;
88
/** Parser state information */
89
state: Object;
90
/** Available compiler functions */
91
compilers: Object;
92
}
93
```
94
95
**Usage Examples:**
96
97
```javascript
98
const nanomatch = require('nanomatch');
99
100
// Complete pattern compilation
101
const result = nanomatch.create('src/**/*.js');
102
console.log(result.output);
103
//=> Compiled regex pattern string
104
105
console.log(result.ast);
106
//=> { type: 'root', nodes: [...], input: 'src/**/*.js', ... }
107
108
console.log(result.options);
109
//=> { source: 'string', sourcemap: true, ... }
110
111
// With source map generation
112
const resultWithMap = nanomatch.create('**/*.{js,ts}', { sourcemap: true });
113
console.log(resultWithMap.map);
114
//=> { version: 3, sources: [...], mappings: '...', ... }
115
116
// Complex pattern analysis
117
const complexResult = nanomatch.create('!(**/node_modules|coverage)/**');
118
console.log(complexResult.ast.nodes.length); // Number of AST nodes
119
console.log(complexResult.state); // Parser state information
120
121
// Error analysis
122
const errorResult = nanomatch.create('[invalid');
123
console.log(errorResult.ast.errors); // Array of parsing errors
124
```
125
126
### Pattern Parsing
127
128
Parse glob patterns into abstract syntax trees for analysis and manipulation.
129
130
```javascript { .api }
131
/**
132
* Parse a glob pattern into an abstract syntax tree
133
* @param {String} pattern - Glob pattern string to parse
134
* @param {Object} options - Optional configuration for parsing behavior
135
* @returns {Object} Abstract syntax tree representation of the pattern
136
*/
137
nanomatch.parse(pattern, options);
138
139
interface ParseResult {
140
/** AST root node type */
141
type: string;
142
/** Original input pattern string */
143
input: string;
144
/** Array of child AST nodes */
145
nodes: ASTNode[];
146
/** Array of parsing errors if any */
147
errors: any[];
148
/** Parser instance reference */
149
parser?: Object;
150
}
151
```
152
153
**Usage Examples:**
154
155
```javascript
156
const nanomatch = require('nanomatch');
157
158
// Basic pattern parsing
159
const ast = nanomatch.parse('*.js');
160
console.log(ast);
161
//=> {
162
// type: 'root',
163
// input: '*.js',
164
// nodes: [
165
// { type: 'bos', val: '' },
166
// { type: 'star', val: '*' },
167
// { type: 'text', val: '.js' },
168
// { type: 'eos', val: '' }
169
// ],
170
// errors: []
171
// }
172
173
// Complex pattern parsing
174
const complexAst = nanomatch.parse('src/**/[abc]*.{js,ts}');
175
console.log(complexAst.nodes.map(n => n.type));
176
//=> ['bos', 'text', 'slash', 'globstar', 'slash', 'bracket', 'star', 'text', 'brace', 'eos']
177
178
// Error handling in parsing
179
const invalidAst = nanomatch.parse('[unclosed');
180
console.log(invalidAst.errors.length > 0); //=> true (has parsing errors)
181
182
// Analyze pattern structure
183
function analyzePattern(pattern) {
184
const ast = nanomatch.parse(pattern);
185
const nodeTypes = ast.nodes.map(n => n.type);
186
187
return {
188
hasGlobstar: nodeTypes.includes('globstar'),
189
hasWildcard: nodeTypes.includes('star'),
190
hasBrackets: nodeTypes.includes('bracket'),
191
hasBraces: nodeTypes.includes('brace'),
192
complexity: ast.nodes.length
193
};
194
}
195
196
console.log(analyzePattern('src/**/*.{js,ts}'));
197
//=> { hasGlobstar: true, hasWildcard: true, hasBrackets: false, hasBraces: true, complexity: 9 }
198
```
199
200
### AST Compilation
201
202
Compile abstract syntax trees or pattern strings into regex output.
203
204
```javascript { .api }
205
/**
206
* Compile an AST or pattern string into regex output
207
* @param {Object|String} ast - AST object from parse() or pattern string
208
* @param {Object} options - Optional configuration for compilation behavior
209
* @returns {Object} Compilation result with output pattern and metadata
210
*/
211
nanomatch.compile(ast, options);
212
213
interface CompileResult {
214
/** Compiled regex pattern string */
215
output: string;
216
/** Original or parsed AST */
217
ast: ParseResult;
218
/** Compiler options used */
219
options: Object;
220
/** Compiler state information */
221
state: Object;
222
/** Available compiler functions */
223
compilers: Object;
224
}
225
```
226
227
**Usage Examples:**
228
229
```javascript
230
const nanomatch = require('nanomatch');
231
232
// Compile from string
233
const compiled = nanomatch.compile('*.js');
234
console.log(compiled.output);
235
//=> Compiled regex pattern string
236
237
// Two-step parse and compile
238
const ast = nanomatch.parse('src/**/*.js');
239
const compiled2 = nanomatch.compile(ast);
240
console.log(compiled2.output === nanomatch.create('src/**/*.js').output);
241
//=> true (same output)
242
243
// Compile with custom options
244
const customCompiled = nanomatch.compile('*.JS', { nocase: true });
245
console.log(customCompiled.output); // Case-insensitive regex pattern
246
247
// Access compilation metadata
248
console.log(compiled.state); // Compiler state
249
console.log(compiled.compilers); // Available compiler functions
250
console.log(compiled.options); // Compilation options used
251
252
// Compile modified AST
253
const ast2 = nanomatch.parse('*.js');
254
// Modify AST here if needed
255
const modifiedCompiled = nanomatch.compile(ast2, { dot: true });
256
console.log(modifiedCompiled.output); // Different output due to options
257
```
258
259
## Advanced Usage Patterns
260
261
### Custom Pattern Analysis
262
263
```javascript
264
const nanomatch = require('nanomatch');
265
266
// Pattern complexity analyzer
267
function analyzePatternComplexity(pattern) {
268
const result = nanomatch.create(pattern);
269
const ast = result.ast;
270
271
let complexity = 0;
272
let features = [];
273
274
ast.nodes.forEach(node => {
275
switch (node.type) {
276
case 'star':
277
complexity += 1;
278
features.push('wildcard');
279
break;
280
case 'globstar':
281
complexity += 3;
282
features.push('globstar');
283
break;
284
case 'bracket':
285
complexity += 2;
286
features.push('character-class');
287
break;
288
case 'brace':
289
complexity += 4;
290
features.push('alternation');
291
break;
292
case 'qmark':
293
complexity += 1;
294
features.push('single-char');
295
break;
296
}
297
});
298
299
return {
300
pattern,
301
complexity,
302
features: [...new Set(features)],
303
regexLength: result.output.length,
304
nodeCount: ast.nodes.length
305
};
306
}
307
308
console.log(analyzePatternComplexity('src/**/*.{js,ts,jsx,tsx}'));
309
//=> {
310
// pattern: 'src/**/*.{js,ts,jsx,tsx}',
311
// complexity: 8,
312
// features: ['globstar', 'wildcard', 'alternation'],
313
// regexLength: 89,
314
// nodeCount: 11
315
// }
316
```
317
318
### Pattern Optimization
319
320
```javascript
321
const nanomatch = require('nanomatch');
322
323
// Compare different pattern approaches
324
function comparePatterns(patterns, testStrings) {
325
const results = patterns.map(pattern => {
326
const startTime = process.hrtime.bigint();
327
const regex = nanomatch.makeRe(pattern);
328
const compileTime = process.hrtime.bigint() - startTime;
329
330
const matchStartTime = process.hrtime.bigint();
331
const matches = testStrings.filter(str => regex.test(str));
332
const matchTime = process.hrtime.bigint() - matchStartTime;
333
334
return {
335
pattern,
336
compileTime: Number(compileTime) / 1000000, // Convert to milliseconds
337
matchTime: Number(matchTime) / 1000000,
338
matches: matches.length,
339
regexLength: regex.source.length
340
};
341
});
342
343
return results;
344
}
345
346
const testFiles = [
347
'src/app.js', 'src/utils.ts', 'lib/helper.js',
348
'components/Button.jsx', 'components/List.tsx'
349
];
350
351
const patterns = [
352
'**/*.{js,ts,jsx,tsx}',
353
'**/*.js|**/*.ts|**/*.jsx|**/*.tsx', // Less efficient alternative
354
'{src,lib,components}/**/*.{js,ts,jsx,tsx}'
355
];
356
357
console.log(comparePatterns(patterns, testFiles));
358
// Shows performance comparison between different pattern approaches
359
```
360
361
### Debugging Pattern Compilation
362
363
```javascript
364
const nanomatch = require('nanomatch');
365
366
// Debug pattern compilation step by step
367
function debugPattern(pattern) {
368
console.log(`\nDebugging pattern: ${pattern}`);
369
370
// Step 1: Parse
371
const ast = nanomatch.parse(pattern);
372
console.log('AST nodes:', ast.nodes.map(n => `${n.type}:${n.val || ''}`));
373
374
if (ast.errors.length > 0) {
375
console.log('Parse errors:', ast.errors);
376
}
377
378
// Step 2: Compile
379
const compiled = nanomatch.compile(ast);
380
console.log('Compiled output:', compiled.output);
381
382
// Step 3: Create regex
383
const regex = nanomatch.makeRe(pattern);
384
console.log('Final regex:', regex);
385
console.log('Regex source:', regex.source);
386
387
// Step 4: Test cases
388
const testCases = ['app.js', 'src/app.js', 'test.txt', '.hidden.js'];
389
console.log('Test results:');
390
testCases.forEach(test => {
391
console.log(` ${test}: ${regex.test(test)}`);
392
});
393
}
394
395
debugPattern('src/**/*.js');
396
debugPattern('*.{js,ts}');
397
debugPattern('[abc]*.js');
398
```
399
400
## Error Handling and Edge Cases
401
402
```javascript
403
const nanomatch = require('nanomatch');
404
405
// Pattern length limits
406
try {
407
const longPattern = '*'.repeat(70000); // Exceeds MAX_LENGTH
408
nanomatch.makeRe(longPattern);
409
} catch (error) {
410
console.log(error.message);
411
//=> 'expected pattern to be less than 65536 characters'
412
}
413
414
// Invalid pattern types
415
try {
416
nanomatch.makeRe(123);
417
} catch (error) {
418
console.log(error.message);
419
//=> 'expected pattern to be a string'
420
}
421
422
try {
423
nanomatch.parse(null);
424
} catch (error) {
425
console.log(error.message);
426
//=> 'expected a string'
427
}
428
429
// RegExp input handling
430
const existingRegex = /\.js$/;
431
const passThrough = nanomatch.makeRe(existingRegex);
432
console.log(passThrough === existingRegex); //=> true (returns as-is)
433
434
// Empty pattern handling
435
const emptyRegex = nanomatch.makeRe('');
436
console.log(emptyRegex.test('anything')); //=> false
437
438
// Malformed bracket patterns
439
const malformedResult = nanomatch.create('[unclosed');
440
console.log(malformedResult.ast.errors.length > 0); //=> true
441
```
442
443
## Performance and Memory Considerations
444
445
- `makeRe()` results are cached - identical patterns return the same RegExp instance
446
- `create()`, `parse()`, and `compile()` also benefit from caching
447
- ASTs can be large for complex patterns - consider memory usage for many patterns
448
- `create()` with `sourcemap: true` uses additional memory for source map data
449
- For simple use cases, higher-level functions like `isMatch()` are more efficient
450
- Direct regex compilation is fastest when you need to test the same pattern many times