Skip to content

fix: apply prepend as a string on generated regexes (#110) - #209

Open
cpruijsen wants to merge 1 commit into
micromatch:masterfrom
cpruijsen:fix/issue-110
Open

cpruijsen wants to merge 1 commit into
micromatch:masterfrom
cpruijsen:fix/issue-110

Conversation

@cpruijsen

Copy link
Copy Markdown

Summary

  • Document options.prepend as a string (it was listed as boolean while the description, micromatch, and the parser all treated it as a string).
  • Copy that string into the generated regex for ordinary patterns, not only after the parser backtracks.
  • Skip tokenizer fast paths when prepend is set, because those paths never see the beginning-of-string token that holds it.
  • When the tokenizer recursively parses a suffix after a negated extglob (for example !(*.d).ts), do not pass prepend back into parse(), or the prefix is applied twice and excluded names start matching.

Provenance: issue #110 reported the type/description mismatch. micromatch already documents this option as string. This repo already stored it as opts.prepend || '' on the beginning-of-string token.

Decision

  • Chose: document it as string and honor that string on parse/makeRe output, including fast-path globs, by sending those globs through the tokenizer.
  • Alternative: change only the type column and leave prepend as a no-op except on backtracking patterns (POSIX classes, some brace ranges). A second alternative is to concatenate the string inside parse.fastpaths / wrapOutput so fast-path regexes stay byte-identical aside from the prefix.
  • Reasoning: the option was already a string on the bos token; the missing copy into state.output is what made the description false for most globs. Skipping fast paths keeps a single source of truth instead of assembling the prefix in three return sites. The cost is that prepended *.js / .* use full-parser semantics (the same as fastpaths: false), including no optional trailing slash on *.js.
  • Offer: I can drop the parser change and keep the docs-only type fix if you prefer. I can also thread the string through the fast paths instead of skipping them if you want those regexes unchanged aside from the prefix.

Test plan

  • npx mocha test/options.prepend.js, prepend appears on parse output, makeRe, fast-path globs like *.js, POSIX classes without doubling, and !(*.d).ts without doubling
  • parse('abc', { prepend: 'foo' }).output === 'fooabc'
  • makeRe('abc', { prepend: 'foo' }).source === '^(?:fooabc)$'
  • isMatch('foofile.d.ts', '!(*.d).ts', { prepend: 'foo' }) === false
  • Existing tests still pass (npx mocha)

The option was documented as a boolean but stored as a string on the
beginning-of-string token, and that string was only copied into the regex
after the parser backtracked. Initialize parser output from it, skip
fast paths that would drop it, and document the option as a string.

When the tokenizer recursively parses a suffix after a negated extglob
(for example `!(*.d).ts`), do not pass prepend back into parse() or the
prefix is applied twice and files that should be excluded start matching.

Closes micromatch#110
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant