CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-braces

Bash-like brace expansion library for JavaScript with complete Bash 4.3 specification 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

Braces

Braces is a JavaScript library that provides Bash-like brace expansion functionality. It can expand brace patterns into arrays of strings or compile them into optimized regex-compatible strings for pattern matching. The library supports the complete Bash 4.3 braces specification with enhanced safety features to prevent malicious regex attacks.

Package Information

  • Package Name: braces
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install braces

Core Imports

const braces = require('braces');

ESM import:

import braces from 'braces';

Basic Usage

const braces = require('braces');

// Compile to regex-compatible strings (default behavior)
console.log(braces('{a,b,c}'));
//=> ['(a|b|c)']

console.log(braces('a/{x,y,z}/b'));
//=> ['a/(x|y|z)/b']

// Expand to full arrays
console.log(braces('{a,b,c}', { expand: true }));  
//=> ['a', 'b', 'c']

console.log(braces('a/{x,y,z}/b', { expand: true }));
//=> ['a/x/b', 'a/y/b', 'a/z/b']

// Sequences and ranges
console.log(braces('{1..5}', { expand: true }));
//=> ['1', '2', '3', '4', '5']

console.log(braces('{01..05}', { expand: true }));
//=> ['01', '02', '03', '04', '05']

Architecture

Braces is built around several key components that work together to provide flexible brace expansion:

  • Parser: Converts brace patterns into Abstract Syntax Trees (AST) for manipulation
  • Compiler: Transforms AST into optimized regex-compatible strings for pattern matching
  • Expander: Generates complete arrays of all possible string combinations from patterns
  • Stringify: Reconstructs brace patterns from AST nodes for round-trip processing
  • Safety Layer: Prevents malicious patterns through length limits and range restrictions

The library uses a two-phase approach: parsing creates a structured representation, then compilation or expansion produces the final output based on the requested mode.

Capabilities

Main Function

The primary interface for brace expansion and compilation.

/**
 * Expand the given pattern or create a regex-compatible string
 * @param {string|string[]} input - Brace pattern(s) to process
 * @param {BraceOptions} options - Configuration options
 * @returns {string[]} Array of expanded or compiled strings
 */
function braces(input, options = {});

Parse

Parse brace patterns into an Abstract Syntax Tree for advanced manipulation.

/**
 * Parse brace pattern into AST
 * @param {string} input - Brace pattern to parse
 * @param {BraceOptions} options - Configuration options  
 * @returns {BraceAST} Abstract syntax tree representation
 */
braces.parse(input, options = {});

Stringify

Convert an AST back into a brace pattern string.

/**
 * Creates a braces string from an AST or AST node
 * @param {string|BraceAST} input - Brace pattern or AST
 * @param {BraceOptions} options - Configuration options
 * @returns {string} Reconstructed brace pattern string
 */
braces.stringify(input, options = {});

Compile

Compile brace patterns into regex-compatible, optimized strings.

/**
 * Compiles a brace pattern into a regex-compatible, optimized string
 * @param {string|BraceAST} input - Brace pattern or AST
 * @param {BraceOptions} options - Configuration options  
 * @returns {string[]} Array of regex-compatible strings
 */
braces.compile(input, options = {});

Expand

Expand brace patterns into arrays of all possible string combinations.

/**
 * Expands a brace pattern into an array of strings
 * @param {string|BraceAST} input - Brace pattern or AST
 * @param {BraceOptions} options - Configuration options
 * @returns {string[]} Array of expanded strings
 */
braces.expand(input, options = {});

Create

Lower-level function that processes patterns based on options.

/**
 * Processes a brace pattern and returns either expanded array or optimized regex string
 * @param {string} input - Brace pattern  
 * @param {BraceOptions} options - Configuration options
 * @returns {string[]} Array of processed strings
 */
braces.create(input, options = {});

Types

/**
 * Configuration options for brace processing
 */
interface BraceOptions {
  /** Generate expanded array instead of compiled regex (default: undefined) */
  expand?: boolean;
  /** Maximum input string length (default: 10000) */ 
  maxLength?: number;
  /** Remove duplicates from results (default: undefined) */
  nodupes?: boolean;
  /** Maximum range expansion size (default: 1000) */
  rangeLimit?: number;
  /** Filter out empty strings from results (default: undefined) */
  noempty?: boolean;
  /** Custom transformation function for range values. For non-numeric ranges, 'value' is a character code. For numeric ranges, 'value' is the number. */
  transform?: (value: any, index: number) => any;
  /** Treat patterns as regex quantifiers instead of lists (default: undefined) */
  quantifiers?: boolean;
  /** Preserve escape characters in output (default: undefined) */
  keepEscaping?: boolean;
  /** Preserve quotes in parsed output (default: undefined) */
  keepQuotes?: boolean;
  /** Escape invalid brace patterns (default: undefined) */
  escapeInvalid?: boolean;
  /** Step/increment for ranges */
  step?: number;
  /** Wrap ranges in parentheses (passed to fill-range) */
  wrap?: boolean;
  /** Convert ranges to regex (passed to fill-range) */
  toRegex?: boolean;
  /** Preserve leading zeros in ranges (passed to fill-range) */
  strictZeros?: boolean;
}

/**
 * Abstract Syntax Tree node structure
 */
interface BraceAST {
  /** Node type identifier */
  type: 'root' | 'brace' | 'text' | 'comma' | 'open' | 'close' | 'range';
  /** Original input string (root nodes only) */
  input?: string;
  /** Node value/content */
  value?: string;
  /** Child nodes */
  nodes?: BraceAST[];
  /** Whether node is invalid */
  invalid?: boolean;
  /** Whether node is escaped */
  escaped?: boolean;
}

Pattern Support

Braces supports all standard Bash 4.3 brace expansion patterns:

Lists (Sets): Comma-separated alternatives

braces('{a,b,c}');           // => ['(a|b|c)']
braces('{foo,bar,baz}');     // => ['(foo|bar|baz)']

Sequences (Ranges): Numeric or alphabetic ranges

braces('{1..5}');            // => ['([1-5])']
braces('{a..e}');            // => ['([a-e])']
braces('{01..05}');          // => ['(0[1-5])'] (zero-padded)

Stepped Ranges: Ranges with increments

braces('{2..10..2}');        // => ['(2|4|6|8|10)']
braces('{a..z..3}');         // => ['(a|d|g|j|m|p|s|v|y)']

Nested Patterns: Complex nested brace expressions

braces('a/{x,{1..3},y}/b');  // => ['a/(x|([1-3])|y)/b']

Escaping: Prevent evaluation of special characters

braces('a\\{b,c\\}d');       // => ['a{b,c}d'] (not expanded)

Invalid Patterns: Patterns that don't follow proper brace syntax

braces('{a}');               // => ['{a}'] (single item, not expanded)
braces('{a,b');              // => ['{a,b'] (unclosed brace)
braces('a,b}');              // => ['a,b}'] (unopened brace)

Brace patterns are considered invalid when they:

  • Contain unmatched opening or closing braces
  • Have only a single item within braces
  • Contain syntax errors that prevent proper parsing

Error Handling

  • TypeError: Thrown when input to parse() is not a string
  • SyntaxError: Thrown when input length exceeds maxLength limit
  • RangeError: Thrown when expanded array exceeds rangeLimit during expansion

Usage Examples

File path generation:

const paths = braces('./src/{components,utils,types}/**/*.js', { expand: true });
// => ['./src/components/**/*.js', './src/utils/**/*.js', './src/types/**/*.js']

Regex pattern creation:

const pattern = braces('user-{200..300}/project-{a,b,c}')[0];
// => 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)'
const regex = new RegExp(pattern);

Transform range values:

// For numeric ranges, 'value' is the number
const customRange = braces('{1..5}', {
  expand: true,
  transform: (value) => `item${value}`
});
// => ['item1', 'item2', 'item3', 'item4', 'item5']

// For alpha ranges, 'value' is a character code
const alphaRange = braces('{a..e}', {
  expand: true,
  transform: (code, index) => `${String.fromCharCode(code)}-${index}`
});
// => ['a-0', 'b-1', 'c-2', 'd-3', 'e-4']

Safe processing with limits:

try {
  const result = braces('{1..10000}', { 
    expand: true,
    rangeLimit: 100 
  });
} catch (error) {
  console.log('Range too large:', error.message);
  // Use compile mode instead for large ranges
  const compiled = braces('{1..10000}');
  // => ['([1-9]|[1-9][0-9]{1,3}|10000)']
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/braces@3.0.x
Publish Source
CLI
Badge
tessl/npm-braces badge