CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nanomatch

Fast, minimal glob matcher for node.js with complete Bash 4.3 wildcard support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

regex-compilation.mddocs/

Regex and Compilation

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.

Capabilities

Regular Expression Generation

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']

Complete Pattern Processing

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 errors

Pattern Parsing

Parse 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 }

AST Compilation

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 options

Advanced Usage Patterns

Custom Pattern Analysis

const 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
//   }

Pattern Optimization

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 approaches

Debugging Pattern Compilation

const 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');

Error Handling and Edge Cases

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); //=> true

Performance and Memory Considerations

  • makeRe() results are cached - identical patterns return the same RegExp instance
  • create(), parse(), and compile() also benefit from caching
  • ASTs can be large for complex patterns - consider memory usage for many patterns
  • create() with sourcemap: true uses additional memory for source map data
  • For simple use cases, higher-level functions like isMatch() are more efficient
  • Direct regex compilation is fastest when you need to test the same pattern many times

docs

collection-operations.md

content-matching.md

core-matching.md

index.md

matcher-creation.md

regex-compilation.md

tile.json