Fast, minimal glob matcher for node.js with complete Bash 4.3 wildcard support
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
Convert glob patterns directly to regular expressions for use outside nanomatch.
/**
* Create a regular expression from a glob pattern
* @param {String} pattern - Glob pattern to convert to regular expression
* @param {Object} options - Optional configuration for regex compilation
* @returns {RegExp} Compiled regular expression that matches the glob pattern
*/
nanomatch.makeRe(pattern, options);Usage Examples:
const nanomatch = require('nanomatch');
// Basic pattern to regex conversion
const jsRegex = nanomatch.makeRe('*.js');
console.log(jsRegex);
//=> /^(?:(?!\.)(?=.)[^\/]*?\.js)$/
console.log(jsRegex.test('app.js')); //=> true
console.log(jsRegex.test('styles.css')); //=> false
// Globstar patterns
const nestedRegex = nanomatch.makeRe('src/**/*.js');
console.log(nestedRegex.test('src/app.js')); //=> true
console.log(nestedRegex.test('src/components/ui.js')); //=> true
console.log(nestedRegex.test('lib/utils.js')); //=> false
// Question mark patterns
const singleCharRegex = nanomatch.makeRe('test?');
console.log(singleCharRegex.test('test1')); //=> true
console.log(singleCharRegex.test('test')); //=> false
console.log(singleCharRegex.test('test12')); //=> false
// Bracket patterns
const bracketRegex = nanomatch.makeRe('[abc]*.js');
console.log(bracketRegex.test('app.js')); //=> true
console.log(bracketRegex.test('data.js')); //=> false
// With options
const caseInsensitiveRegex = nanomatch.makeRe('*.JS', { nocase: true });
console.log(caseInsensitiveRegex.test('app.js')); //=> true
// Negation patterns
const negationRegex = nanomatch.makeRe('!test*');
console.log(negationRegex.test('app.js')); //=> true
console.log(negationRegex.test('test.js')); //=> false
// Using with native regex methods
const pattern = nanomatch.makeRe('**/*.{js,ts}');
const files = ['app.js', 'utils.ts', 'styles.css'];
const sourceFiles = files.filter(file => pattern.test(file));
console.log(sourceFiles); //=> ['app.js', 'utils.ts']Parse and compile patterns with full metadata, AST, and compilation details.
/**
* Parse and compile a glob pattern with complete metadata
* @param {String} pattern - Glob pattern to parse and compile
* @param {Object} options - Optional configuration for parsing and compilation
* @returns {Object} Complete compilation result with AST, output, and metadata
*/
nanomatch.create(pattern, options);
interface CompilationResult {
/** Compiled regex pattern string */
output: string;
/** Parsed abstract syntax tree */
ast: ParseResult;
/** Source map if sourcemap option enabled */
map?: SourceMap;
/** Parser options used during compilation */
options: Object;
/** Parser state information */
state: Object;
/** Available compiler functions */
compilers: Object;
}Usage Examples:
const nanomatch = require('nanomatch');
// Complete pattern compilation
const result = nanomatch.create('src/**/*.js');
console.log(result.output);
//=> Compiled regex pattern string
console.log(result.ast);
//=> { type: 'root', nodes: [...], input: 'src/**/*.js', ... }
console.log(result.options);
//=> { source: 'string', sourcemap: true, ... }
// With source map generation
const resultWithMap = nanomatch.create('**/*.{js,ts}', { sourcemap: true });
console.log(resultWithMap.map);
//=> { version: 3, sources: [...], mappings: '...', ... }
// Complex pattern analysis
const complexResult = nanomatch.create('!(**/node_modules|coverage)/**');
console.log(complexResult.ast.nodes.length); // Number of AST nodes
console.log(complexResult.state); // Parser state information
// Error analysis
const errorResult = nanomatch.create('[invalid');
console.log(errorResult.ast.errors); // Array of parsing errorsParse glob patterns into abstract syntax trees for analysis and manipulation.
/**
* Parse a glob pattern into an abstract syntax tree
* @param {String} pattern - Glob pattern string to parse
* @param {Object} options - Optional configuration for parsing behavior
* @returns {Object} Abstract syntax tree representation of the pattern
*/
nanomatch.parse(pattern, options);
interface ParseResult {
/** AST root node type */
type: string;
/** Original input pattern string */
input: string;
/** Array of child AST nodes */
nodes: ASTNode[];
/** Array of parsing errors if any */
errors: any[];
/** Parser instance reference */
parser?: Object;
}Usage Examples:
const nanomatch = require('nanomatch');
// Basic pattern parsing
const ast = nanomatch.parse('*.js');
console.log(ast);
//=> {
// type: 'root',
// input: '*.js',
// nodes: [
// { type: 'bos', val: '' },
// { type: 'star', val: '*' },
// { type: 'text', val: '.js' },
// { type: 'eos', val: '' }
// ],
// errors: []
// }
// Complex pattern parsing
const complexAst = nanomatch.parse('src/**/[abc]*.{js,ts}');
console.log(complexAst.nodes.map(n => n.type));
//=> ['bos', 'text', 'slash', 'globstar', 'slash', 'bracket', 'star', 'text', 'brace', 'eos']
// Error handling in parsing
const invalidAst = nanomatch.parse('[unclosed');
console.log(invalidAst.errors.length > 0); //=> true (has parsing errors)
// Analyze pattern structure
function analyzePattern(pattern) {
const ast = nanomatch.parse(pattern);
const nodeTypes = ast.nodes.map(n => n.type);
return {
hasGlobstar: nodeTypes.includes('globstar'),
hasWildcard: nodeTypes.includes('star'),
hasBrackets: nodeTypes.includes('bracket'),
hasBraces: nodeTypes.includes('brace'),
complexity: ast.nodes.length
};
}
console.log(analyzePattern('src/**/*.{js,ts}'));
//=> { hasGlobstar: true, hasWildcard: true, hasBrackets: false, hasBraces: true, complexity: 9 }Compile abstract syntax trees or pattern strings into regex output.
/**
* Compile an AST or pattern string into regex output
* @param {Object|String} ast - AST object from parse() or pattern string
* @param {Object} options - Optional configuration for compilation behavior
* @returns {Object} Compilation result with output pattern and metadata
*/
nanomatch.compile(ast, options);
interface CompileResult {
/** Compiled regex pattern string */
output: string;
/** Original or parsed AST */
ast: ParseResult;
/** Compiler options used */
options: Object;
/** Compiler state information */
state: Object;
/** Available compiler functions */
compilers: Object;
}Usage Examples:
const nanomatch = require('nanomatch');
// Compile from string
const compiled = nanomatch.compile('*.js');
console.log(compiled.output);
//=> Compiled regex pattern string
// Two-step parse and compile
const ast = nanomatch.parse('src/**/*.js');
const compiled2 = nanomatch.compile(ast);
console.log(compiled2.output === nanomatch.create('src/**/*.js').output);
//=> true (same output)
// Compile with custom options
const customCompiled = nanomatch.compile('*.JS', { nocase: true });
console.log(customCompiled.output); // Case-insensitive regex pattern
// Access compilation metadata
console.log(compiled.state); // Compiler state
console.log(compiled.compilers); // Available compiler functions
console.log(compiled.options); // Compilation options used
// Compile modified AST
const ast2 = nanomatch.parse('*.js');
// Modify AST here if needed
const modifiedCompiled = nanomatch.compile(ast2, { dot: true });
console.log(modifiedCompiled.output); // Different output due to optionsconst nanomatch = require('nanomatch');
// Pattern complexity analyzer
function analyzePatternComplexity(pattern) {
const result = nanomatch.create(pattern);
const ast = result.ast;
let complexity = 0;
let features = [];
ast.nodes.forEach(node => {
switch (node.type) {
case 'star':
complexity += 1;
features.push('wildcard');
break;
case 'globstar':
complexity += 3;
features.push('globstar');
break;
case 'bracket':
complexity += 2;
features.push('character-class');
break;
case 'brace':
complexity += 4;
features.push('alternation');
break;
case 'qmark':
complexity += 1;
features.push('single-char');
break;
}
});
return {
pattern,
complexity,
features: [...new Set(features)],
regexLength: result.output.length,
nodeCount: ast.nodes.length
};
}
console.log(analyzePatternComplexity('src/**/*.{js,ts,jsx,tsx}'));
//=> {
// pattern: 'src/**/*.{js,ts,jsx,tsx}',
// complexity: 8,
// features: ['globstar', 'wildcard', 'alternation'],
// regexLength: 89,
// nodeCount: 11
// }const nanomatch = require('nanomatch');
// Compare different pattern approaches
function comparePatterns(patterns, testStrings) {
const results = patterns.map(pattern => {
const startTime = process.hrtime.bigint();
const regex = nanomatch.makeRe(pattern);
const compileTime = process.hrtime.bigint() - startTime;
const matchStartTime = process.hrtime.bigint();
const matches = testStrings.filter(str => regex.test(str));
const matchTime = process.hrtime.bigint() - matchStartTime;
return {
pattern,
compileTime: Number(compileTime) / 1000000, // Convert to milliseconds
matchTime: Number(matchTime) / 1000000,
matches: matches.length,
regexLength: regex.source.length
};
});
return results;
}
const testFiles = [
'src/app.js', 'src/utils.ts', 'lib/helper.js',
'components/Button.jsx', 'components/List.tsx'
];
const patterns = [
'**/*.{js,ts,jsx,tsx}',
'**/*.js|**/*.ts|**/*.jsx|**/*.tsx', // Less efficient alternative
'{src,lib,components}/**/*.{js,ts,jsx,tsx}'
];
console.log(comparePatterns(patterns, testFiles));
// Shows performance comparison between different pattern approachesconst nanomatch = require('nanomatch');
// Debug pattern compilation step by step
function debugPattern(pattern) {
console.log(`\nDebugging pattern: ${pattern}`);
// Step 1: Parse
const ast = nanomatch.parse(pattern);
console.log('AST nodes:', ast.nodes.map(n => `${n.type}:${n.val || ''}`));
if (ast.errors.length > 0) {
console.log('Parse errors:', ast.errors);
}
// Step 2: Compile
const compiled = nanomatch.compile(ast);
console.log('Compiled output:', compiled.output);
// Step 3: Create regex
const regex = nanomatch.makeRe(pattern);
console.log('Final regex:', regex);
console.log('Regex source:', regex.source);
// Step 4: Test cases
const testCases = ['app.js', 'src/app.js', 'test.txt', '.hidden.js'];
console.log('Test results:');
testCases.forEach(test => {
console.log(` ${test}: ${regex.test(test)}`);
});
}
debugPattern('src/**/*.js');
debugPattern('*.{js,ts}');
debugPattern('[abc]*.js');const nanomatch = require('nanomatch');
// Pattern length limits
try {
const longPattern = '*'.repeat(70000); // Exceeds MAX_LENGTH
nanomatch.makeRe(longPattern);
} catch (error) {
console.log(error.message);
//=> 'expected pattern to be less than 65536 characters'
}
// Invalid pattern types
try {
nanomatch.makeRe(123);
} catch (error) {
console.log(error.message);
//=> 'expected pattern to be a string'
}
try {
nanomatch.parse(null);
} catch (error) {
console.log(error.message);
//=> 'expected a string'
}
// RegExp input handling
const existingRegex = /\.js$/;
const passThrough = nanomatch.makeRe(existingRegex);
console.log(passThrough === existingRegex); //=> true (returns as-is)
// Empty pattern handling
const emptyRegex = nanomatch.makeRe('');
console.log(emptyRegex.test('anything')); //=> false
// Malformed bracket patterns
const malformedResult = nanomatch.create('[unclosed');
console.log(malformedResult.ast.errors.length > 0); //=> truemakeRe() results are cached - identical patterns return the same RegExp instancecreate(), parse(), and compile() also benefit from cachingcreate() with sourcemap: true uses additional memory for source map dataisMatch() are more efficient