Skip to content

Commit 02257b9

Browse files
committed
New version. More strict. Drop returnIndex and startIndex params for now.
1 parent c906c02 commit 02257b9

File tree

5 files changed

+132
-111
lines changed

5 files changed

+132
-111
lines changed

Diff for: .travis.yml

+2-7
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,5 @@ sudo: false
22
language: node_js
33
node_js:
44
- node
5-
- '8'
6-
- '7'
7-
- '6'
8-
- '5'
9-
- '4'
10-
- '0.12'
11-
- '0.10'
5+
- '10'
6+
- '8'

Diff for: index.d.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// type
2+
3+
import sep from 'path';
4+
5+
// * @param {Array|Function|String|RegExp} matchers
6+
// * @param {String=} testString
7+
// * @param {Boolean=} returnIndex
8+
9+
type AnymatchPattern = String|RegExp|{(string:String): Boolean};
10+
type AnymatchMatcher = AnymatchPattern|Array<AnymatchPattern>
11+
function anymatch(matchers: AnymatchMatcher, testString: String): Boolean;
12+
function anymatch(matchers: AnymatchMatcher, testString: String, returnIndex: Boolean): Number;
13+
function anymatch(matchers: AnymatchMatcher): (testString: String) => Boolean;
14+
function anymatch(matchers: AnymatchMatcher): (testString: String, returnIndex: Boolean) => Number;
15+
export = anymatch;

Diff for: index.js

+62-55
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,74 @@
11
'use strict';
22

3-
var micromatch = require('micromatch');
4-
var normalize = require('normalize-path');
5-
var path = require('path'); // required for tests.
6-
var arrify = function(a) { return a == null ? [] : (Array.isArray(a) ? a : [a]); };
3+
const micromatch = require('micromatch');
4+
const normalizePath = require('normalize-path');
5+
const {sep} = require('path'); // required for tests.
76

8-
var anymatch = function(criteria, value, returnIndex, startIndex, endIndex) {
9-
criteria = arrify(criteria);
10-
value = arrify(value);
11-
if (arguments.length === 1) {
12-
return anymatch.bind(null, criteria.map(function(criterion) {
13-
return typeof criterion === 'string' && criterion[0] !== '!' ?
14-
micromatch.matcher(criterion) : criterion;
15-
}));
7+
/**
8+
* @typedef {String|RegExp|{(string:String): Boolean}} AnymatchPattern
9+
* @typedef {AnymatchPattern|Array<AnymatchPattern>} AnymatchMatcher
10+
*/
11+
12+
const BANG = '!';
13+
const arrify = (item) => Array.isArray(item) ? item : [item];
14+
15+
const createPattern = (matcher) => (string) => {
16+
if (typeof matcher === 'function') {
17+
return matcher(string);
1618
}
17-
startIndex = startIndex || 0;
18-
var string = value[0];
19-
var altString, altValue;
20-
var matched = false;
21-
var matchIndex = -1;
22-
function testCriteria(criterion, index) {
23-
var result;
24-
switch (Object.prototype.toString.call(criterion)) {
25-
case '[object String]':
26-
result = string === criterion || altString && altString === criterion;
27-
result = result || micromatch.isMatch(string, criterion);
28-
break;
29-
case '[object RegExp]':
30-
result = criterion.test(string) || altString && criterion.test(altString);
31-
break;
32-
case '[object Function]':
33-
result = criterion.apply(null, value);
34-
result = result || altValue && criterion.apply(null, altValue);
35-
break;
36-
default:
37-
result = false;
38-
}
39-
if (result) {
40-
matchIndex = index + startIndex;
19+
if (typeof matcher === 'string') {
20+
return matcher === string || micromatch.isMatch(string, matcher);
21+
}
22+
if (matcher instanceof RegExp) {
23+
return matcher.test(string);
24+
}
25+
return false;
26+
};
27+
28+
/**
29+
* @param {AnymatchMatcher} matchers
30+
* @param {String} testString
31+
* @param {Boolean=} returnIndex
32+
* @returns {Boolean|Number|Function}
33+
*/
34+
const anymatch = (matchers, testString, returnIndex=false) => {
35+
if (matchers == null) {
36+
throw new TypeError('anymatch: specify first argument');
37+
}
38+
if (testString == null) {
39+
return (testString, ri=false) => {
40+
const returnIndex = typeof ri === 'boolean' ? ri : false;
41+
return anymatch(matchers, testString, returnIndex);
4142
}
42-
return result;
4343
}
44-
var crit = criteria;
45-
var negGlobs = crit.reduce(function(arr, criterion, index) {
46-
if (typeof criterion === 'string' && criterion[0] === '!') {
47-
if (crit === criteria) {
48-
// make a copy before modifying
49-
crit = crit.slice();
50-
}
51-
crit[index] = null;
52-
arr.push(criterion.substr(1));
44+
if (typeof testString !== 'string') {
45+
throw new TypeError('anymatch: second argument must be a string: got ' +
46+
Object.prototype.toString.call(testString))
47+
}
48+
49+
const unixified = normalizePath(testString);
50+
const arrified = arrify(matchers);
51+
const negatedGlobs = arrified
52+
.filter(item => typeof item === 'string' && item.charAt(0) === BANG)
53+
.map(item => item.slice(1));
54+
55+
// console.log('anymatch', {matchers, testString, containsNegatedGlob, negatedGlobs});
56+
57+
if (negatedGlobs.length > 0) {
58+
if (micromatch.some(unixified, negatedGlobs)) {
59+
return returnIndex ? -1 : false;
5360
}
54-
return arr;
55-
}, []);
56-
if (!negGlobs.length || !micromatch.any(string, negGlobs)) {
57-
if (path.sep === '\\' && typeof string === 'string') {
58-
altString = normalize(string);
59-
altString = altString === string ? null : altString;
60-
if (altString) altValue = [altString].concat(value.slice(1));
61+
}
62+
63+
const patterns = arrified.map(createPattern);
64+
for (let index=0; index < patterns.length; index++) {
65+
const pattern = patterns[index];
66+
if (pattern(unixified)) {
67+
return returnIndex ? index : true;
6168
}
62-
matched = crit.slice(startIndex, endIndex).some(testCriteria);
6369
}
64-
return returnIndex === true ? matchIndex : matched;
70+
71+
return returnIndex ? -1 : false;
6572
};
6673

6774
module.exports = anymatch;

Diff for: package.json

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
{
22
"name": "anymatch",
3-
"version": "2.0.0",
3+
"version": "3.0.0-pre",
44
"description": "Matches strings against configurable strings, globs, regular expressions, and/or functions",
55
"files": [
6-
"index.js"
6+
"index.js",
7+
"index.d.ts"
78
],
89
"author": {
910
"name": "Elan Shanker",
@@ -36,12 +37,12 @@
3637
"test": "istanbul cover _mocha && cat ./coverage/lcov.info | coveralls"
3738
},
3839
"dependencies": {
39-
"micromatch": "^3.1.4",
40-
"normalize-path": "^2.1.1"
40+
"micromatch": "micromatch/micromatch#dev",
41+
"normalize-path": "^3.0.0"
4142
},
4243
"devDependencies": {
4344
"coveralls": "^2.7.0",
4445
"istanbul": "^0.4.5",
45-
"mocha": "^3.0.0"
46+
"mocha": "^6.0.2"
4647
}
4748
}

Diff for: test.js

+47-44
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ describe('anymatch', function() {
1414
}
1515
];
1616
it('should resolve string matchers', function() {
17-
assert.equal(true, anymatch(matchers, 'path/to/file.js'));
18-
assert.equal(true, anymatch(matchers[0], 'path/to/file.js'));
19-
assert.equal(false, anymatch(matchers[0], 'bar.js'));
17+
assert(anymatch(matchers, 'path/to/file.js'));
18+
assert(anymatch(matchers[0], 'path/to/file.js'));
19+
assert(!anymatch(matchers[0], 'bar.js'));
2020
});
2121
it('should resolve glob matchers', function() {
2222
assert.equal(true, anymatch(matchers, 'path/anyjs/baz.js'));
@@ -38,8 +38,8 @@ describe('anymatch', function() {
3838
});
3939
it('should ignore improperly typed matchers', function() {
4040
var emptyObj = {};
41-
assert.equal(false, anymatch(emptyObj, emptyObj));
42-
assert.equal(false, anymatch(Infinity, Infinity));
41+
assert.equal(false, anymatch(emptyObj, ''));
42+
assert.equal(false, anymatch(Infinity, ''));
4343
});
4444

4545
describe('with returnIndex = true', function() {
@@ -58,7 +58,10 @@ describe('anymatch', function() {
5858
});
5959

6060
describe('curried matching function', function() {
61-
var matchFn = anymatch(matchers);
61+
var matchFn;
62+
before(() => {
63+
matchFn = anymatch(matchers);
64+
});
6265
it('should resolve matchers', function() {
6366
assert.equal(true, matchFn('path/to/file.js'));
6467
assert.equal(true, matchFn('path/anyjs/baz.js'));
@@ -91,46 +94,46 @@ describe('anymatch', function() {
9194
});
9295
});
9396

94-
describe('using matcher subsets', function() {
95-
it('should skip matchers before the startIndex', function() {
96-
assert(anymatch(matchers, 'path/to/file.js', false));
97-
assert(!anymatch(matchers, 'path/to/file.js', false, 1));
98-
});
99-
it('should skip matchers after and including the endIndex', function() {
100-
assert(anymatch(matchers, 'path/to/bars.js', false));
101-
assert(!anymatch(matchers, 'path/to/bars.js', false, 0, 3));
102-
assert(!anymatch(matchers, 'foo.js', false, 0, 1));
103-
});
104-
});
97+
// describe('using matcher subsets', function() {
98+
// it('should skip matchers before the startIndex', function() {
99+
// assert(anymatch(matchers, 'path/to/file.js', false));
100+
// assert(!anymatch(matchers, 'path/to/file.js', false, 1));
101+
// });
102+
// it('should skip matchers after and including the endIndex', function() {
103+
// assert(anymatch(matchers, 'path/to/bars.js', false));
104+
// assert(!anymatch(matchers, 'path/to/bars.js', false, 0, 3));
105+
// assert(!anymatch(matchers, 'foo.js', false, 0, 1));
106+
// });
107+
// });
105108

106109
describe('extra args', function() {
107-
it('should allow string to be passed as first member of an array', function() {
108-
assert(anymatch(matchers, ['path/to/bar.js']));
109-
});
110-
it('should pass extra args to function matchers', function() {
111-
matchers.push(function(string, arg1, arg2) { return arg1 || arg2; });
112-
assert(!anymatch(matchers, 'bar.js'), 1);
113-
assert(!anymatch(matchers, ['bar.js', 0]), 2);
114-
assert(anymatch(matchers, ['bar.js', true]), 3);
115-
assert(anymatch(matchers, ['bar.js', 0, true]), 4);
116-
// with returnIndex
117-
assert.equal(anymatch(matchers, ['bar.js', 1], true), 4, 5);
118-
// curried versions
119-
var matchFn1 = anymatch(matchers);
120-
var matchFn2 = anymatch(matchers[4]);
121-
assert(!matchFn1(['bar.js', 0]), 6);
122-
assert(!matchFn2(['bar.js', 0]), 7);
123-
assert(matchFn1(['bar.js', true]), 8);
124-
assert(matchFn2(['bar.js', true]), 9);
125-
assert(matchFn1(['bar.js', 0, true]), 10);
126-
assert(matchFn2(['bar.js', 0, true]), 11);
127-
// curried with returnIndex
128-
assert.equal(matchFn1(['bar.js', 1], true), 4, 12);
129-
assert.equal(matchFn2(['bar.js', 1], true), 0, 13);
130-
assert.equal(matchFn1(['bar.js', 0], true), -1, 14);
131-
assert.equal(matchFn2(['bar.js', 0], true), -1, 15);
132-
matchers.pop();
133-
});
110+
it('should not allow string to be passed as first member of an array', function() {
111+
assert.throws(() => anymatch(matchers, ['path/to/bar.js']));
112+
});
113+
// it('should pass extra args to function matchers', function() {
114+
// matchers.push(function(string, arg1, arg2) { return arg1 || arg2; });
115+
// assert(!anymatch(matchers, 'bar.js'), 1);
116+
// assert(!anymatch(matchers, ['bar.js', 0]), 2);
117+
// assert(anymatch(matchers, ['bar.js', true]), 3);
118+
// assert(anymatch(matchers, ['bar.js', 0, true]), 4);
119+
// // with returnIndex
120+
// assert.equal(anymatch(matchers, ['bar.js', 1], true), 4, 5);
121+
// // curried versions
122+
// var matchFn1 = anymatch(matchers);
123+
// var matchFn2 = anymatch(matchers[4]);
124+
// assert(!matchFn1(['bar.js', 0]), 6);
125+
// assert(!matchFn2(['bar.js', 0]), 7);
126+
// assert(matchFn1(['bar.js', true]), 8);
127+
// assert(matchFn2(['bar.js', true]), 9);
128+
// assert(matchFn1(['bar.js', 0, true]), 10);
129+
// assert(matchFn2(['bar.js', 0, true]), 11);
130+
// // curried with returnIndex
131+
// assert.equal(matchFn1(['bar.js', 1], true), 4, 12);
132+
// assert.equal(matchFn2(['bar.js', 1], true), 0, 13);
133+
// assert.equal(matchFn1(['bar.js', 0], true), -1, 14);
134+
// assert.equal(matchFn2(['bar.js', 0], true), -1, 15);
135+
// matchers.pop();
136+
// });
134137
});
135138

136139
describe('glob negation', function() {

0 commit comments

Comments
 (0)