demo · v136

Path & Glob Builder

Take a user-supplied path prefix or glob pattern and combine literal segments (escaped) with glob wildcards (left alive). RegExp.escape() handles the dots, plus, brackets, and dollar signs that paths love to carry.

Probing RegExp.escape support…
live results ↓

why this is a real problem

Build tools, search bars, and routers all need to convert a friendly glob like src/**/*.tsx into a regex. The literal slashes, dots, and parens are regex metacharacters — if you don’t escape them, src/(group)/Card.tsx becomes a capture group, and $weird.tsx becomes an end anchor. RegExp.escape() escapes only the segments between wildcards, so the wildcards survive while everything else becomes literal.

the code

function globToRegex(glob, { caseInsensitive = false, anchorEnd = true } = {}) {
  // Split on glob tokens, keep them as separators.
  const TOKEN = /(\*\*|\*|\?)/g;
  const parts = glob.split(TOKEN);
  const out = parts.map((p, i) => {
    // Odd positions in the split are the matched tokens.
    if (i % 2 === 1) {
      if (p === '**') return '.*';
      if (p === '*')  return '[^/]*';
      if (p === '?')  return '[^/]';
    }
    // Even positions are literal — escape them.
    return RegExp.escape(p);
  });
  const body = out.join('');
  const flags = caseInsensitive ? 'i' : '';
  return new RegExp('^' + body + (anchorEnd ? '$' : ''), flags);
}

see also