GithubHelp home page GithubHelp logo

matcher's Introduction

matcher

Simple wildcard matching

Useful when you want to accept loose string input and regexes/globs are too convoluted.

Install

npm install matcher

Usage

import {matcher, isMatch} from 'matcher';

matcher(['foo', 'bar', 'moo'], ['*oo', '!foo']);
//=> ['moo']

matcher(['foo', 'bar', 'moo'], ['!*oo']);
//=> ['bar']

matcher('moo', ['']);
//=> []

matcher('moo', []);
//=> []

matcher([''], ['']);
//=> ['']

isMatch('unicorn', 'uni*');
//=> true

isMatch('unicorn', '*corn');
//=> true

isMatch('unicorn', 'un*rn');
//=> true

isMatch('rainbow', '!unicorn');
//=> true

isMatch('foo bar baz', 'foo b* b*');
//=> true

isMatch('unicorn', 'uni\\*');
//=> false

isMatch(['foo', 'bar'], 'f*');
//=> true

isMatch(['foo', 'bar'], ['a*', 'b*']);
//=> true

isMatch('unicorn', ['']);
//=> false

isMatch('unicorn', []);
//=> false

isMatch([], 'bar');
//=> false

isMatch([], []);
//=> false

isMatch('', '');
//=> true

API

It matches even across newlines. For example, foo*r will match foo\nbar.

matcher(inputs, patterns, options?)

Accepts a string or an array of strings for both inputs and patterns.

Returns an array of inputs filtered based on the patterns.

isMatch(inputs, patterns, options?)

Accepts a string or an array of strings for both inputs and patterns.

Returns a boolean of whether any of given inputs matches all the patterns.

inputs

Type: string | string[]

The string or array of strings to match.

options

Type: object

caseSensitive

Type: boolean
Default: false

Treat uppercase and lowercase characters as being the same.

Ensure you use this correctly. For example, files and directories should be matched case-insensitively, while most often, object keys should be matched case-sensitively.

import {isMatch} from 'matcher';

isMatch('UNICORN', 'UNI*', {caseSensitive: true});
//=> true

isMatch('UNICORN', 'unicorn', {caseSensitive: true});
//=> false

isMatch('unicorn', ['tri*', 'UNI*'], {caseSensitive: true});
//=> false
allPatterns

Type: boolean
Default: false

Require all negated patterns to not match and any normal patterns to match at least once. Otherwise, it will be a no-match condition.

import {matcher} from 'matcher';

// Find text strings containing both "edge" and "tiger" in arbitrary order, but not "stunt".
const demo = (strings) => matcher(strings, ['*edge*', '*tiger*', '!*stunt*'], {allPatterns: true});

demo(['Hey, tiger!', 'tiger has edge over hyenas', 'pushing a tiger over the edge is a stunt']);
//=> ['tiger has edge over hyenas']
import {matcher} from 'matcher';

matcher(['foo', 'for', 'bar'], ['f*', 'b*', '!x*'], {allPatterns: true});
//=> ['foo', 'for', 'bar']

matcher(['foo', 'for', 'bar'], ['f*'], {allPatterns: true});
//=> []

patterns

Type: string | string[]

Use * to match zero or more characters.

A leading ! negates the pattern.

An input string will be omitted, if it does not match any non-negated patterns present, or if it matches a negated pattern, or if no pattern is present.

Benchmark

npm run bench

Related

  • matcher-cli - CLI for this module
  • multimatch - Extends minimatch.match() with support for multiple patterns

Get professional support for this package with a Tidelift subscription
Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies.

matcher's People

Contributors

aretecode avatar atjn avatar bendingbender avatar coreyfarrell avatar daveseco7 avatar delucis avatar haltcase avatar luftywiranda13 avatar ricardo-silva91 avatar richienb avatar sindresorhus avatar valango avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

matcher's Issues

Negated rule is position - sensitive

If the negated rule is the last that actually matches, then the result list will be empty, but otherwise not:

match(['ab'], ['a*', '!ab'])    //  --> []
match(['ab'], ['!ab', 'a*'])    //  --> ['ab']
match(['ab'], ['x', '!ab', 'a*'])    //  --> ['ab']

Because filtering is essentially a sets operation, one may expect that internal ordering of a set operand does not matter, but it does.

Not a big issue, but perhaps the readme should say something about this?

Does not match across newlines

> require('matcher').isMatch('test\nhaha', 'test*')
false

I think the wildcard should match newline characters as well.

Version 5.0.0 ERR_REQUIRE_ESM error

Version 5.0.0 appears to use an import statement which breaks node.js builds expecting CommonJS modules:

09:49:43  internal/modules/cjs/loader.js:1015
09:49:43        throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
09:49:43        ^
09:49:43  
09:49:43  Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: node_modules/matcher/index.js

ES5 support

Hi!

The template literals and arrow functions break our build for Internet Explorer 11. Could you please consider transpiling the library to ES5 – or simply use ES5 – in order to support more browser versions?

Takk :)

Line ending errors

After a fresh clone, I ran npm install, followed by npm test and got this:

C:\Users\james.monger\Desktop\js\m\matcher (master) ([email protected])
λ npm test

> [email protected] test C:\Users\james.monger\Desktop\js\m\matcher
> xo && ava


C:\Users\james.monger\Desktop\js\m\matcher\index.js
   1:14  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   2:58  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   3:18  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   4:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   5:41  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   6:40  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   7:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   8:26  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   9:28  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  10:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  11:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  12:22  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  13:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  14:27  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  15:18  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  16:30  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  17:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  18:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  19:63  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  20:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  21:32  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  22:35  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  23:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  24:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  25:48  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  26:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  27:23  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  28:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  29:25  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  30:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  31:12  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  32:2   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  33:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  34:47  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  35:60  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  36:92  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  37:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  38:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  39:30  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  40:17  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  41:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  42:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  43:44  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  44:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  45:40  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  46:27  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  47:5   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  48:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  49:15  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  50:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  51:43  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  52:44  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  53:42  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  54:30  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  55:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  56:46  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  57:38  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  58:36  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  59:5   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  60:4   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  61:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  62:17  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  63:24  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  64:4   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  65:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  66:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  67:13  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  68:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  69:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  70:53  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  71:43  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  72:3   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

C:\Users\james.monger\Desktop\js\m\matcher\test.js
   1:24  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   2:20  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   3:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   4:25  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   5:51  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   6:51  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   7:66  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   8:58  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
   9:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  10:31  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  11:4   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  12:1   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  13:33  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  14:42  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  15:39  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  16:40  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  17:40  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  18:52  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  19:36  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  20:36  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  21:44  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  22:41  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  23:31  error  Unnecessary escape character: \*                 no-useless-escape
  23:37  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  24:42  error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style
  25:4   error  Expected linebreaks to be 'LF' but found 'CRLF'  linebreak-style

✖ 98 problems (98 errors, 0 warnings)
npm ERR! Test failed.  See above for more details.
npm ERR! not ok code 0

Case sensitive option

hi all,

I saw it was discussed previously, but please consider adding case-sensitive option. I'm working on a project where I need to filter out an array of file names and use wildcards. Case does matter...

Code-wise, it's just a toggle on the regex flag and this feature would not break the existing apps, just implement default on "case insensitive = on" mode and let people turn it off.

What do you think?

Thanks for creating and maintaining this by the way.

Negative matching doesn't work for `isMatch`

I have come across an issue with the isMatch method in that it is returning false when I expect it to be true using a negative pattern.

Even the example in the README:

matcher.isMatch('rainbow', '!unicorn');
//=> true

returns false. Here's is the output from my REPL:

> const m = require('matcher')
> m.isMatch('rainbow', '!unicorn');
false
> |

This is either a bug or a mistake in the documentation. If I have time this week, I'll try to make a PR for this. Just thought it should be on your radar

Feedback

I could use some feedback on the API, docs, and code.

Are the docs clear enough? API nice enough? Anything missing? Any suggestions for better method name than matcher.isMatch()?

Currently the matching is case-insensitive? Is this a good default? Should there be an option to toggle this?

.isMatch support collection

Hello, what do you think add collection support to .isMatch?

It will be equivalent using matcher or .isMatch, just making different the output

matcher(['foo', 'bar', 'moo'], ['*oo', '!foo']); //=> ['moo']

Using .isMatch

matcher.isMatch(['foo', 'bar', 'moo'], ['*oo', '!foo']) // => true 

Issue or not.

Are you intentionally implemented a code to get a result as below?.

matcher

From the documentation,

matcher(['foo', 'bar', 'moo'], ['*oo', '!foo']);
//=> ['moo']

[First example]: if you change the order of the pattern elements, matcher is returning all the elements from the input. (Question: Is there any order preference in the pattern elements like, non-match (!) pattern element should come always last?)

matcher(['foo', 'bar', 'moo'], ['!foo', '*oo']);
//=> ['foo', 'bar', 'moo']

In my second example, I used three elements in the pattern match array ['*oo', '!foo', '*o']. The third match is overriding the first one and it doesn't care about the second match (!foo - non-match). Hence, matcher is returning both foo and moo.

matcher(['foo', 'bar', 'moo'], ['*oo', '!foo', '*o']);
//=> ['foo', 'moo']

Option to match any pattern in .isMatch

.isMatch currently matches when every (Array.prototype.every) pattern matches, but I have a case where I need to match any (Array.prototype.some) pattern. Would you accept adding a option for that?

Option to match any pattern in `isMatch`

I'm using this package to match CORS origin domains. I was going insane debugging why the origin was not being returned when I found the issue appears to happen when you have multiple allowed domains.

const matcher = require('matcher');
const allowedOrigins = [
    '*.example.com',
    '*.dev.example.com',
];

const origin = 'https://my.example.com';

const match = matcher.isMatch(
    origin,
    allowedOrigins,
);
// false but expected true

Note that when using matcher, I get back a proper result

const matcher = require('matcher');
const allowedOrigins = [
    '*.example.com',
    '*.dev.example.com',
];

const origin = 'https://my.example.com';

const match = matcher(
    origin,
    allowedOrigins,
);
// ['https://my.example.com']

I am working around this by checking to see if the array is empty or not

Feature request: the 'all' option

The matcher option all would work like this:

matcher(package.keywords, ['regex', 'missing']);
//=> ['regexp', 'regexpr']
matcher(package.keywords, ['regex', 'missing'], {all: true});
//=> []
matcher(package.keywords.concat(['missing']), ['regex', 'allting'], {all: true});
//=> ['regexp', 'regexpr', 'missing']

Or, perhaps 'every' would be better name for this option.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.