Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrectly matches trailing negation (e.g. to match .ts but not .d.ts with **/!(*.d).ts) #83

Closed
duniul opened this issue May 21, 2021 · 4 comments

Comments

@duniul
Copy link

duniul commented May 21, 2021

Thanks for a great library and apologies in advance if this has been adressed somewhere else! 🙏

Issue

I'm trying to match a pattern that matches all *.ts files except *.d.ts, and while it works most of the time it does not seem to work if whatever pattern you're negating is used anywhere else in the path.

The glob **/!(*.d).ts should work for this case, but with picomatch and micromatch it excludes any file name that contains .d at all, not just at the end. With minimatch and other globbing tools it works as expected.

Example

import minimatch from 'minimatch';
import picomatch from 'micromatch';
import micromatch from 'micromatch';

const glob = '**/!(*.d).ts';

const mini = (path) => minimatch(path, glob);
mini('/file.d.ts')            // false (correct)
mini('/file.ts')              // true  (correct)
mini('/file.d.something.ts')  // true  (correct)
mini('/file.dhello.ts')       // true  (correct)

const pico = (path) => picomatch.isMatch(path, glob);
pico('/file.d.ts')            // false (correct)
pico('/file.ts')              // true  (correct)
pico('/file.d.something.ts')  // false (incorrect)
pico('/file.dhello.ts')       // false (incorrect)

const micro = (path) => micromatch.isMatch(path, glob);
micro('/file.d.ts')            // false (correct)
micro('/file.ts')              // true  (correct)
micro('/file.d.something.ts')  // false (incorrect)
micro('/file.dhello.ts')       // false (incorrect)

I also created a CodeSandbox with an example for testing any glob (see the console output).

@jonschlinkert
Copy link
Member

jonschlinkert commented May 21, 2021

I think I know what's causing it, but I'll double check with the sandbox, thanks for doing that!

edit: in your code snippet here, you are using micromatch in the mini (minimatch) example. Do you want to update that first so we can see what the behavior is for minimatch?

The pattern !(*.d).ts should should not match (or negate) file.d.something.ts since there is a segment between d and .js. There needs to be another *. there somewhere, probably as a second condition in the parens. I'll play around with it and see what works.

@jonschlinkert
Copy link
Member

fwiw I'm still playing around with the sandbox, I think that there might be a bug here. I'll report back when I'm finished looking into it.

@duniul
Copy link
Author

duniul commented May 21, 2021

in your code snippet here, you are using micromatch in the mini (minimatch) example. Do you want to update that first so we can see what the behavior is for minimatch?

@jonschlinkert Oops, incorrectly edited the example to make it more readable. I've cleaned it up now, the results are the same though (minimatch shows one result, picomatch and micromatch another).

Incredibly fast response, thanks a lot 🙌

@duniul
Copy link
Author

duniul commented May 21, 2021

The pattern !(*.d).ts should should not match (or negate) file.d.something.ts since there is a segment between d and .js. There needs to be another *. there somewhere, probably as a second condition in the parens.

Exactly, out of the paths in the example only file.d.ts should be excluded.

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

No branches or pull requests

2 participants