@bigbinary/eslint-plugin-neeto 1.8.2 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1078 -956
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
2
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('fs'), require('path'), require('ramda'), require('@bigbinary/neeto-cist'), require('@bigbinary/neeto-commons-frontend/constants')) :
|
|
3
3
|
typeof define === 'function' && define.amd ? define(['fs', 'path', 'ramda', '@bigbinary/neeto-cist', '@bigbinary/neeto-commons-frontend/constants'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["@bigbinary/eslint-plugin-neeto"] = factory(global.fs, global.path$
|
|
5
|
-
})(this, (function (fs, path$
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["@bigbinary/eslint-plugin-neeto"] = factory(global.fs, global.path$1, global.ramda, global["@bigbinary/neeto-cist"], global.neetoCommonsConstants));
|
|
5
|
+
})(this, (function (fs, path$1, ramda, neetoCist, neetoCommonsConstants) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopNamespaceDefault(e) {
|
|
8
8
|
var n = Object.create(null);
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
var neetoCommonsConstants__namespace = /*#__PURE__*/_interopNamespaceDefault(neetoCommonsConstants);
|
|
25
25
|
|
|
26
26
|
/* eslint-disable @bigbinary/neeto/use-title-case-neeto-in-strings */
|
|
27
|
-
const absolutePath$1 = jsPath => path$
|
|
27
|
+
const absolutePath$1 = jsPath => path$1.resolve(__dirname, "../../../..", jsPath);
|
|
28
28
|
const loadJS$2 = jsPath => {
|
|
29
29
|
try {
|
|
30
30
|
return require(absolutePath$1(jsPath));
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
rules
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
-
const absolutePath = jsPath => path$
|
|
188
|
+
const absolutePath = jsPath => path$1.resolve(__dirname, "../../../..", jsPath);
|
|
189
189
|
const srcPath = fs.existsSync(absolutePath("src")) ? absolutePath("src") : absolutePath("app/javascript/src");
|
|
190
190
|
const pathToTranslationsDir = `${srcPath}/translations`;
|
|
191
191
|
const pathToResolveFile$1 = "resolve.js";
|
|
@@ -259,11 +259,11 @@
|
|
|
259
259
|
}
|
|
260
260
|
});
|
|
261
261
|
|
|
262
|
-
const rootOfTheProject = path$
|
|
262
|
+
const rootOfTheProject = path$1.join(__dirname, "../../../../");
|
|
263
263
|
const pathToResolveFile = "resolve.js";
|
|
264
264
|
const loadJS = jsPath => {
|
|
265
265
|
try {
|
|
266
|
-
return require(path$
|
|
266
|
+
return require(path$1.join(rootOfTheProject, jsPath));
|
|
267
267
|
} catch {
|
|
268
268
|
return {};
|
|
269
269
|
}
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
}
|
|
286
286
|
});
|
|
287
287
|
|
|
288
|
-
var version = "1.8.
|
|
288
|
+
var version = "1.8.2";
|
|
289
289
|
var packageJson = {
|
|
290
290
|
version: version};
|
|
291
291
|
|
|
@@ -701,7 +701,7 @@
|
|
|
701
701
|
*/
|
|
702
702
|
const isInsideApisDirectory = context => {
|
|
703
703
|
const filename = context.getFilename();
|
|
704
|
-
const apisDirectory = path$
|
|
704
|
+
const apisDirectory = path$1.resolve(APIS_DIRECTORY);
|
|
705
705
|
return filename.startsWith(apisDirectory) && filename !== `${apisDirectory}/axios.js`;
|
|
706
706
|
};
|
|
707
707
|
|
|
@@ -712,7 +712,7 @@
|
|
|
712
712
|
*/
|
|
713
713
|
const isInsideComponentsDirectory = context => {
|
|
714
714
|
const filename = context.getFilename();
|
|
715
|
-
const componentsDirectory = path$
|
|
715
|
+
const componentsDirectory = path$1.resolve(COMPONENTS_DIRECTORY);
|
|
716
716
|
return filename.startsWith(componentsDirectory);
|
|
717
717
|
};
|
|
718
718
|
|
|
@@ -785,7 +785,7 @@
|
|
|
785
785
|
optional: true
|
|
786
786
|
}, node);
|
|
787
787
|
const optionalChainingOptimizedName = (funcName, node) => isOptionalChainingPresent(node) ? `_${funcName}` : funcName;
|
|
788
|
-
const isExcludedFile = (excludedFiles, filename) => excludedFiles.some(filePath => filePath.test(path$
|
|
788
|
+
const isExcludedFile = (excludedFiles, filename) => excludedFiles.some(filePath => filePath.test(path$1.resolve(filename)));
|
|
789
789
|
const parseJsonData = filePath => {
|
|
790
790
|
try {
|
|
791
791
|
const jsonData = fs.readFileSync(filePath).toString();
|
|
@@ -3531,11 +3531,6 @@
|
|
|
3531
3531
|
})
|
|
3532
3532
|
};
|
|
3533
3533
|
|
|
3534
|
-
const isWindows = typeof process === 'object' &&
|
|
3535
|
-
process &&
|
|
3536
|
-
process.platform === 'win32';
|
|
3537
|
-
var path$1 = isWindows ? { sep: '\\' } : { sep: '/' };
|
|
3538
|
-
|
|
3539
3534
|
var balancedMatch = balanced$1;
|
|
3540
3535
|
function balanced$1(a, b, str) {
|
|
3541
3536
|
if (a instanceof RegExp) a = maybeMatch(a, str);
|
|
@@ -3675,7 +3670,7 @@
|
|
|
3675
3670
|
str = '\\{\\}' + str.substr(2);
|
|
3676
3671
|
}
|
|
3677
3672
|
|
|
3678
|
-
return expand
|
|
3673
|
+
return expand(escapeBraces(str), true).map(unescapeBraces);
|
|
3679
3674
|
}
|
|
3680
3675
|
|
|
3681
3676
|
function embrace(str) {
|
|
@@ -3692,7 +3687,7 @@
|
|
|
3692
3687
|
return i >= y;
|
|
3693
3688
|
}
|
|
3694
3689
|
|
|
3695
|
-
function expand
|
|
3690
|
+
function expand(str, isTop) {
|
|
3696
3691
|
var expansions = [];
|
|
3697
3692
|
|
|
3698
3693
|
var m = balanced('{', '}', str);
|
|
@@ -3701,7 +3696,7 @@
|
|
|
3701
3696
|
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
|
3702
3697
|
var pre = m.pre;
|
|
3703
3698
|
var post = m.post.length
|
|
3704
|
-
? expand
|
|
3699
|
+
? expand(m.post, false)
|
|
3705
3700
|
: [''];
|
|
3706
3701
|
|
|
3707
3702
|
if (/\$$/.test(m.pre)) {
|
|
@@ -3718,7 +3713,7 @@
|
|
|
3718
3713
|
// {a},b}
|
|
3719
3714
|
if (m.post.match(/,(?!,).*\}/)) {
|
|
3720
3715
|
str = m.pre + '{' + m.body + escClose + m.post;
|
|
3721
|
-
return expand
|
|
3716
|
+
return expand(str);
|
|
3722
3717
|
}
|
|
3723
3718
|
return [str];
|
|
3724
3719
|
}
|
|
@@ -3730,7 +3725,7 @@
|
|
|
3730
3725
|
n = parseCommaParts(m.body);
|
|
3731
3726
|
if (n.length === 1) {
|
|
3732
3727
|
// x{{a,b}}y ==> x{a}y x{b}y
|
|
3733
|
-
n = expand
|
|
3728
|
+
n = expand(n[0], false).map(embrace);
|
|
3734
3729
|
if (n.length === 1) {
|
|
3735
3730
|
return post.map(function(p) {
|
|
3736
3731
|
return m.pre + n[0] + p;
|
|
@@ -3785,7 +3780,7 @@
|
|
|
3785
3780
|
N = [];
|
|
3786
3781
|
|
|
3787
3782
|
for (var j = 0; j < n.length; j++) {
|
|
3788
|
-
N.push.apply(N, expand
|
|
3783
|
+
N.push.apply(N, expand(n[j], false));
|
|
3789
3784
|
}
|
|
3790
3785
|
}
|
|
3791
3786
|
|
|
@@ -3801,102 +3796,135 @@
|
|
|
3801
3796
|
return expansions;
|
|
3802
3797
|
}
|
|
3803
3798
|
|
|
3804
|
-
const minimatch =
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3799
|
+
const minimatch = (p, pattern, options = {}) => {
|
|
3800
|
+
assertValidPattern(pattern);
|
|
3801
|
+
// shortcut: comments match nothing.
|
|
3802
|
+
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
3803
|
+
return false;
|
|
3804
|
+
}
|
|
3805
|
+
return new Minimatch(pattern, options).match(p);
|
|
3806
|
+
};
|
|
3807
|
+
// Optimized checking for the most common glob patterns.
|
|
3808
|
+
const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
|
|
3809
|
+
const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
|
|
3810
|
+
const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
|
|
3811
|
+
const starDotExtTestNocase = (ext) => {
|
|
3812
|
+
ext = ext.toLowerCase();
|
|
3813
|
+
return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
|
|
3814
|
+
};
|
|
3815
|
+
const starDotExtTestNocaseDot = (ext) => {
|
|
3816
|
+
ext = ext.toLowerCase();
|
|
3817
|
+
return (f) => f.toLowerCase().endsWith(ext);
|
|
3818
|
+
};
|
|
3819
|
+
const starDotStarRE = /^\*+\.\*+$/;
|
|
3820
|
+
const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
|
|
3821
|
+
const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
|
|
3822
|
+
const dotStarRE = /^\.\*+$/;
|
|
3823
|
+
const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
|
|
3824
|
+
const starRE = /^\*+$/;
|
|
3825
|
+
const starTest = (f) => f.length !== 0 && !f.startsWith('.');
|
|
3826
|
+
const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
|
|
3827
|
+
const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
|
|
3828
|
+
const qmarksTestNocase = ([$0, ext = '']) => {
|
|
3829
|
+
const noext = qmarksTestNoExt([$0]);
|
|
3830
|
+
if (!ext)
|
|
3831
|
+
return noext;
|
|
3832
|
+
ext = ext.toLowerCase();
|
|
3833
|
+
return (f) => noext(f) && f.toLowerCase().endsWith(ext);
|
|
3834
|
+
};
|
|
3835
|
+
const qmarksTestNocaseDot = ([$0, ext = '']) => {
|
|
3836
|
+
const noext = qmarksTestNoExtDot([$0]);
|
|
3837
|
+
if (!ext)
|
|
3838
|
+
return noext;
|
|
3839
|
+
ext = ext.toLowerCase();
|
|
3840
|
+
return (f) => noext(f) && f.toLowerCase().endsWith(ext);
|
|
3841
|
+
};
|
|
3842
|
+
const qmarksTestDot = ([$0, ext = '']) => {
|
|
3843
|
+
const noext = qmarksTestNoExtDot([$0]);
|
|
3844
|
+
return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
|
|
3845
|
+
};
|
|
3846
|
+
const qmarksTest = ([$0, ext = '']) => {
|
|
3847
|
+
const noext = qmarksTestNoExt([$0]);
|
|
3848
|
+
return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
|
|
3849
|
+
};
|
|
3850
|
+
const qmarksTestNoExt = ([$0]) => {
|
|
3851
|
+
const len = $0.length;
|
|
3852
|
+
return (f) => f.length === len && !f.startsWith('.');
|
|
3853
|
+
};
|
|
3854
|
+
const qmarksTestNoExtDot = ([$0]) => {
|
|
3855
|
+
const len = $0.length;
|
|
3856
|
+
return (f) => f.length === len && f !== '.' && f !== '..';
|
|
3857
|
+
};
|
|
3858
|
+
/* c8 ignore start */
|
|
3859
|
+
const platform = typeof process === 'object' && process
|
|
3860
|
+
? (typeof process.env === 'object' &&
|
|
3861
|
+
process.env &&
|
|
3862
|
+
process.env.__MINIMATCH_TESTING_PLATFORM__) ||
|
|
3863
|
+
process.platform
|
|
3864
|
+
: 'posix';
|
|
3865
|
+
const isWindows = platform === 'win32';
|
|
3866
|
+
const path = isWindows ? { sep: '\\' } : { sep: '/' };
|
|
3867
|
+
/* c8 ignore stop */
|
|
3868
|
+
const sep = path.sep;
|
|
3869
|
+
minimatch.sep = sep;
|
|
3820
3870
|
const GLOBSTAR = Symbol('globstar **');
|
|
3821
3871
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
3822
|
-
const expand = braceExpansion;
|
|
3823
|
-
|
|
3824
3872
|
const plTypes = {
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3873
|
+
'!': { open: '(?:(?!(?:', close: '))[^/]*?)' },
|
|
3874
|
+
'?': { open: '(?:', close: ')?' },
|
|
3875
|
+
'+': { open: '(?:', close: ')+' },
|
|
3876
|
+
'*': { open: '(?:', close: ')*' },
|
|
3877
|
+
'@': { open: '(?:', close: ')' },
|
|
3830
3878
|
};
|
|
3831
|
-
|
|
3832
3879
|
// any single thing other than /
|
|
3833
3880
|
// don't need to escape / when using new RegExp()
|
|
3834
3881
|
const qmark = '[^/]';
|
|
3835
|
-
|
|
3836
3882
|
// * => any number of characters
|
|
3837
3883
|
const star = qmark + '*?';
|
|
3838
|
-
|
|
3839
3884
|
// ** when dots are allowed. Anything goes, except .. and .
|
|
3840
3885
|
// not (^ or / followed by one or two dots followed by $ or /),
|
|
3841
3886
|
// followed by anything, any number of times.
|
|
3842
|
-
const twoStarDot = '(?:(?!(
|
|
3843
|
-
|
|
3887
|
+
const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
|
|
3844
3888
|
// not a ^ or / followed by a dot,
|
|
3845
3889
|
// followed by anything, any number of times.
|
|
3846
|
-
const twoStarNoDot = '(?:(?!(
|
|
3847
|
-
|
|
3890
|
+
const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
|
|
3848
3891
|
// "abc" -> { a:true, b:true, c:true }
|
|
3849
|
-
const charSet = s => s.split('').reduce((set, c) => {
|
|
3850
|
-
|
|
3851
|
-
|
|
3892
|
+
const charSet = (s) => s.split('').reduce((set, c) => {
|
|
3893
|
+
set[c] = true;
|
|
3894
|
+
return set;
|
|
3852
3895
|
}, {});
|
|
3853
|
-
|
|
3854
3896
|
// characters that need to be escaped in RegExp.
|
|
3855
3897
|
const reSpecials = charSet('().*{}+?[]^$\\!');
|
|
3856
|
-
|
|
3857
3898
|
// characters that indicate we have to add the pattern start
|
|
3858
3899
|
const addPatternStartSet = charSet('[.(');
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
const
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
}
|
|
3885
|
-
};
|
|
3886
|
-
m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch;
|
|
3887
|
-
m.filter = (pattern, options) => orig.filter(pattern, ext(def, options));
|
|
3888
|
-
m.defaults = options => orig.defaults(ext(def, options));
|
|
3889
|
-
m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options));
|
|
3890
|
-
m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options));
|
|
3891
|
-
m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options));
|
|
3892
|
-
|
|
3893
|
-
return m
|
|
3900
|
+
const filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options);
|
|
3901
|
+
minimatch.filter = filter;
|
|
3902
|
+
const ext = (a, b = {}) => Object.assign({}, a, b);
|
|
3903
|
+
const defaults = (def) => {
|
|
3904
|
+
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
|
|
3905
|
+
return minimatch;
|
|
3906
|
+
}
|
|
3907
|
+
const orig = minimatch;
|
|
3908
|
+
const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
|
|
3909
|
+
return Object.assign(m, {
|
|
3910
|
+
Minimatch: class Minimatch extends orig.Minimatch {
|
|
3911
|
+
constructor(pattern, options = {}) {
|
|
3912
|
+
super(pattern, ext(def, options));
|
|
3913
|
+
}
|
|
3914
|
+
static defaults(options) {
|
|
3915
|
+
return orig.defaults(ext(def, options)).Minimatch;
|
|
3916
|
+
}
|
|
3917
|
+
},
|
|
3918
|
+
filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
|
|
3919
|
+
defaults: (options) => orig.defaults(ext(def, options)),
|
|
3920
|
+
makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
|
|
3921
|
+
braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
|
|
3922
|
+
match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
|
|
3923
|
+
sep: orig.sep,
|
|
3924
|
+
GLOBSTAR: GLOBSTAR,
|
|
3925
|
+
});
|
|
3894
3926
|
};
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3927
|
+
minimatch.defaults = defaults;
|
|
3900
3928
|
// Brace expansion:
|
|
3901
3929
|
// a{b,c}d -> abd acd
|
|
3902
3930
|
// a{b,}c -> abc ac
|
|
@@ -3907,32 +3935,26 @@
|
|
|
3907
3935
|
// Invalid sets are not expanded.
|
|
3908
3936
|
// a{2..}b -> a{2..}b
|
|
3909
3937
|
// a{b}c -> a{b}c
|
|
3910
|
-
minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options);
|
|
3911
|
-
|
|
3912
3938
|
const braceExpand = (pattern, options = {}) => {
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
return expand(pattern)
|
|
3939
|
+
assertValidPattern(pattern);
|
|
3940
|
+
// Thanks to Yeting Li <https://github.com/yetingli> for
|
|
3941
|
+
// improving this regexp to avoid a ReDOS vulnerability.
|
|
3942
|
+
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
|
|
3943
|
+
// shortcut. no need to expand.
|
|
3944
|
+
return [pattern];
|
|
3945
|
+
}
|
|
3946
|
+
return braceExpansion(pattern);
|
|
3923
3947
|
};
|
|
3924
|
-
|
|
3948
|
+
minimatch.braceExpand = braceExpand;
|
|
3925
3949
|
const MAX_PATTERN_LENGTH = 1024 * 64;
|
|
3926
|
-
const assertValidPattern = pattern => {
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
}
|
|
3950
|
+
const assertValidPattern = (pattern) => {
|
|
3951
|
+
if (typeof pattern !== 'string') {
|
|
3952
|
+
throw new TypeError('invalid pattern');
|
|
3953
|
+
}
|
|
3954
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
3955
|
+
throw new TypeError('pattern is too long');
|
|
3956
|
+
}
|
|
3934
3957
|
};
|
|
3935
|
-
|
|
3936
3958
|
// parse a component of the expanded set.
|
|
3937
3959
|
// At this point, no pattern may contain "/" in it
|
|
3938
3960
|
// so we're going to return a 2d array, where each entry is the full
|
|
@@ -3945,861 +3967,961 @@
|
|
|
3945
3967
|
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|
3946
3968
|
// default, and can be disabled by setting options.noglobstar.
|
|
3947
3969
|
const SUBPARSE = Symbol('subparse');
|
|
3948
|
-
|
|
3949
|
-
minimatch.makeRe =
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
list
|
|
3957
|
-
}
|
|
3958
|
-
return list
|
|
3970
|
+
const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
|
|
3971
|
+
minimatch.makeRe = makeRe;
|
|
3972
|
+
const match = (list, pattern, options = {}) => {
|
|
3973
|
+
const mm = new Minimatch(pattern, options);
|
|
3974
|
+
list = list.filter(f => mm.match(f));
|
|
3975
|
+
if (mm.options.nonull && !list.length) {
|
|
3976
|
+
list.push(pattern);
|
|
3977
|
+
}
|
|
3978
|
+
return list;
|
|
3959
3979
|
};
|
|
3960
|
-
|
|
3980
|
+
minimatch.match = match;
|
|
3961
3981
|
// replace stuff like \* with *
|
|
3962
|
-
const globUnescape = s => s.replace(/\\(.)/g, '$1');
|
|
3963
|
-
const charUnescape = s => s.replace(/\\([^-\]])/g, '$1');
|
|
3964
|
-
const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
3965
|
-
const braExpEscape = s => s.replace(/[[\]\\]/g, '\\$&');
|
|
3966
|
-
|
|
3982
|
+
const globUnescape = (s) => s.replace(/\\(.)/g, '$1');
|
|
3983
|
+
const charUnescape = (s) => s.replace(/\\([^-\]])/g, '$1');
|
|
3984
|
+
const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
3985
|
+
const braExpEscape = (s) => s.replace(/[[\]\\]/g, '\\$&');
|
|
3967
3986
|
class Minimatch {
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
}
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
}
|
|
3992
|
-
|
|
3993
|
-
debug () {}
|
|
3994
|
-
|
|
3995
|
-
make () {
|
|
3996
|
-
const pattern = this.pattern;
|
|
3997
|
-
const options = this.options;
|
|
3998
|
-
|
|
3999
|
-
// empty patterns and comments match nothing.
|
|
4000
|
-
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
4001
|
-
this.comment = true;
|
|
4002
|
-
return
|
|
4003
|
-
}
|
|
4004
|
-
if (!pattern) {
|
|
4005
|
-
this.empty = true;
|
|
4006
|
-
return
|
|
4007
|
-
}
|
|
4008
|
-
|
|
4009
|
-
// step 1: figure out negation, etc.
|
|
4010
|
-
this.parseNegate();
|
|
4011
|
-
|
|
4012
|
-
// step 2: expand braces
|
|
4013
|
-
let set = this.globSet = this.braceExpand();
|
|
4014
|
-
|
|
4015
|
-
if (options.debug) this.debug = (...args) => console.error(...args);
|
|
4016
|
-
|
|
4017
|
-
this.debug(this.pattern, set);
|
|
4018
|
-
|
|
4019
|
-
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
4020
|
-
// matching patterns.
|
|
4021
|
-
// These will be regexps, except in the case of "**", which is
|
|
4022
|
-
// set to the GLOBSTAR object for globstar behavior,
|
|
4023
|
-
// and will not contain any / characters
|
|
4024
|
-
set = this.globParts = set.map(s => s.split(slashSplit));
|
|
4025
|
-
|
|
4026
|
-
this.debug(this.pattern, set);
|
|
4027
|
-
|
|
4028
|
-
// glob --> regexps
|
|
4029
|
-
set = set.map((s, si, set) => s.map(this.parse, this));
|
|
4030
|
-
|
|
4031
|
-
this.debug(this.pattern, set);
|
|
4032
|
-
|
|
4033
|
-
// filter out everything that didn't compile properly.
|
|
4034
|
-
set = set.filter(s => s.indexOf(false) === -1);
|
|
4035
|
-
|
|
4036
|
-
this.debug(this.pattern, set);
|
|
4037
|
-
|
|
4038
|
-
this.set = set;
|
|
4039
|
-
}
|
|
4040
|
-
|
|
4041
|
-
parseNegate () {
|
|
4042
|
-
if (this.options.nonegate) return
|
|
4043
|
-
|
|
4044
|
-
const pattern = this.pattern;
|
|
4045
|
-
let negate = false;
|
|
4046
|
-
let negateOffset = 0;
|
|
4047
|
-
|
|
4048
|
-
for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
|
|
4049
|
-
negate = !negate;
|
|
4050
|
-
negateOffset++;
|
|
4051
|
-
}
|
|
4052
|
-
|
|
4053
|
-
if (negateOffset) this.pattern = pattern.slice(negateOffset);
|
|
4054
|
-
this.negate = negate;
|
|
4055
|
-
}
|
|
4056
|
-
|
|
4057
|
-
// set partial to true to test if, for example,
|
|
4058
|
-
// "/a/b" matches the start of "/*/b/*/d"
|
|
4059
|
-
// Partial means, if you run out of file before you run
|
|
4060
|
-
// out of pattern, then that's fine, as long as all
|
|
4061
|
-
// the parts match.
|
|
4062
|
-
matchOne (file, pattern, partial) {
|
|
4063
|
-
if (pattern.indexOf(GLOBSTAR) !== -1) {
|
|
4064
|
-
return this._matchGlobstar(file, pattern, partial, 0, 0)
|
|
4065
|
-
}
|
|
4066
|
-
return this._matchOne(file, pattern, partial, 0, 0)
|
|
4067
|
-
}
|
|
4068
|
-
|
|
4069
|
-
_matchGlobstar (file, pattern, partial, fileIndex, patternIndex) {
|
|
4070
|
-
// find first globstar from patternIndex
|
|
4071
|
-
let firstgs = -1;
|
|
4072
|
-
for (let i = patternIndex; i < pattern.length; i++) {
|
|
4073
|
-
if (pattern[i] === GLOBSTAR) { firstgs = i; break }
|
|
4074
|
-
}
|
|
4075
|
-
|
|
4076
|
-
// find last globstar
|
|
4077
|
-
let lastgs = -1;
|
|
4078
|
-
for (let i = pattern.length - 1; i >= 0; i--) {
|
|
4079
|
-
if (pattern[i] === GLOBSTAR) { lastgs = i; break }
|
|
4080
|
-
}
|
|
4081
|
-
|
|
4082
|
-
const head = pattern.slice(patternIndex, firstgs);
|
|
4083
|
-
const body = partial ? pattern.slice(firstgs + 1) : pattern.slice(firstgs + 1, lastgs);
|
|
4084
|
-
const tail = partial ? [] : pattern.slice(lastgs + 1);
|
|
4085
|
-
|
|
4086
|
-
// check the head
|
|
4087
|
-
if (head.length) {
|
|
4088
|
-
const fileHead = file.slice(fileIndex, fileIndex + head.length);
|
|
4089
|
-
if (!this._matchOne(fileHead, head, partial, 0, 0)) {
|
|
4090
|
-
return false
|
|
4091
|
-
}
|
|
4092
|
-
fileIndex += head.length;
|
|
4093
|
-
}
|
|
4094
|
-
|
|
4095
|
-
// check the tail
|
|
4096
|
-
let fileTailMatch = 0;
|
|
4097
|
-
if (tail.length) {
|
|
4098
|
-
if (tail.length + fileIndex > file.length) return false
|
|
4099
|
-
|
|
4100
|
-
const tailStart = file.length - tail.length;
|
|
4101
|
-
if (this._matchOne(file, tail, partial, tailStart, 0)) {
|
|
4102
|
-
fileTailMatch = tail.length;
|
|
4103
|
-
} else {
|
|
4104
|
-
// affordance for stuff like a/**/* matching a/b/
|
|
4105
|
-
if (file[file.length - 1] !== '' ||
|
|
4106
|
-
fileIndex + tail.length === file.length) {
|
|
4107
|
-
return false
|
|
3987
|
+
options;
|
|
3988
|
+
set;
|
|
3989
|
+
pattern;
|
|
3990
|
+
windowsPathsNoEscape;
|
|
3991
|
+
nonegate;
|
|
3992
|
+
negate;
|
|
3993
|
+
comment;
|
|
3994
|
+
empty;
|
|
3995
|
+
preserveMultipleSlashes;
|
|
3996
|
+
partial;
|
|
3997
|
+
globSet;
|
|
3998
|
+
globParts;
|
|
3999
|
+
regexp;
|
|
4000
|
+
maxGlobstarRecursion;
|
|
4001
|
+
constructor(pattern, options = {}) {
|
|
4002
|
+
assertValidPattern(pattern);
|
|
4003
|
+
options = options || {};
|
|
4004
|
+
this.options = options;
|
|
4005
|
+
this.pattern = pattern;
|
|
4006
|
+
this.windowsPathsNoEscape =
|
|
4007
|
+
!!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
|
|
4008
|
+
if (this.windowsPathsNoEscape) {
|
|
4009
|
+
this.pattern = this.pattern.replace(/\\/g, '/');
|
|
4108
4010
|
}
|
|
4109
|
-
|
|
4110
|
-
|
|
4011
|
+
this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
|
|
4012
|
+
this.regexp = null;
|
|
4013
|
+
this.negate = false;
|
|
4014
|
+
this.nonegate = !!options.nonegate;
|
|
4015
|
+
this.comment = false;
|
|
4016
|
+
this.empty = false;
|
|
4017
|
+
this.partial = !!options.partial;
|
|
4018
|
+
this.maxGlobstarRecursion = options.maxGlobstarRecursion !== undefined
|
|
4019
|
+
? options.maxGlobstarRecursion : 200;
|
|
4020
|
+
this.globSet = [];
|
|
4021
|
+
this.globParts = [];
|
|
4022
|
+
this.set = [];
|
|
4023
|
+
// make the set of regexps etc.
|
|
4024
|
+
this.make();
|
|
4025
|
+
}
|
|
4026
|
+
debug(..._) { }
|
|
4027
|
+
make() {
|
|
4028
|
+
const pattern = this.pattern;
|
|
4029
|
+
const options = this.options;
|
|
4030
|
+
// empty patterns and comments match nothing.
|
|
4031
|
+
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
4032
|
+
this.comment = true;
|
|
4033
|
+
return;
|
|
4111
4034
|
}
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
// if body is empty (single ** between head and tail)
|
|
4117
|
-
if (!body.length) {
|
|
4118
|
-
let sawSome = !!fileTailMatch;
|
|
4119
|
-
for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
|
|
4120
|
-
const f = String(file[i]);
|
|
4121
|
-
sawSome = true;
|
|
4122
|
-
if (f === '.' || f === '..' ||
|
|
4123
|
-
(!this.options.dot && f.charAt(0) === '.')) {
|
|
4124
|
-
return false
|
|
4035
|
+
if (!pattern) {
|
|
4036
|
+
this.empty = true;
|
|
4037
|
+
return;
|
|
4125
4038
|
}
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
let currentBody = bodySegments[0];
|
|
4133
|
-
let nonGsParts = 0;
|
|
4134
|
-
const nonGsPartsSums = [0];
|
|
4135
|
-
for (const b of body) {
|
|
4136
|
-
if (b === GLOBSTAR) {
|
|
4137
|
-
nonGsPartsSums.push(nonGsParts);
|
|
4138
|
-
currentBody = [[], 0];
|
|
4139
|
-
bodySegments.push(currentBody);
|
|
4140
|
-
} else {
|
|
4141
|
-
currentBody[0].push(b);
|
|
4142
|
-
nonGsParts++;
|
|
4143
|
-
}
|
|
4144
|
-
}
|
|
4145
|
-
|
|
4146
|
-
let idx = bodySegments.length - 1;
|
|
4147
|
-
const fileLength = file.length - fileTailMatch;
|
|
4148
|
-
for (const b of bodySegments) {
|
|
4149
|
-
b[1] = fileLength - (nonGsPartsSums[idx--] + b[0].length);
|
|
4150
|
-
}
|
|
4151
|
-
|
|
4152
|
-
return !!this._matchGlobStarBodySections(
|
|
4153
|
-
file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch
|
|
4154
|
-
)
|
|
4155
|
-
}
|
|
4156
|
-
|
|
4157
|
-
// return false for "nope, not matching"
|
|
4158
|
-
// return null for "not matching, cannot keep trying"
|
|
4159
|
-
_matchGlobStarBodySections (
|
|
4160
|
-
file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail
|
|
4161
|
-
) {
|
|
4162
|
-
const bs = bodySegments[bodyIndex];
|
|
4163
|
-
if (!bs) {
|
|
4164
|
-
// just make sure there are no bad dots
|
|
4165
|
-
for (let i = fileIndex; i < file.length; i++) {
|
|
4166
|
-
sawTail = true;
|
|
4167
|
-
const f = file[i];
|
|
4168
|
-
if (f === '.' || f === '..' ||
|
|
4169
|
-
(!this.options.dot && f.charAt(0) === '.')) {
|
|
4170
|
-
return false
|
|
4039
|
+
// step 1: figure out negation, etc.
|
|
4040
|
+
this.parseNegate();
|
|
4041
|
+
// step 2: expand braces
|
|
4042
|
+
this.globSet = this.braceExpand();
|
|
4043
|
+
if (options.debug) {
|
|
4044
|
+
this.debug = (...args) => console.error(...args);
|
|
4171
4045
|
}
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
);
|
|
4193
|
-
if (sub !== false) {
|
|
4194
|
-
return sub
|
|
4046
|
+
this.debug(this.pattern, this.globSet);
|
|
4047
|
+
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
4048
|
+
// matching patterns.
|
|
4049
|
+
// These will be regexps, except in the case of "**", which is
|
|
4050
|
+
// set to the GLOBSTAR object for globstar behavior,
|
|
4051
|
+
// and will not contain any / characters
|
|
4052
|
+
const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
|
|
4053
|
+
// consecutive globstars are an unncessary perf killer
|
|
4054
|
+
// also, **/*/... is equivalent to */**/..., so swap all of those
|
|
4055
|
+
// this turns a pattern like **/*/**/*/x into */*/**/x
|
|
4056
|
+
// and a pattern like **/x/**/*/y becomes **/x/*/**/y
|
|
4057
|
+
// the *later* we can push the **, the more efficient it is,
|
|
4058
|
+
// because we can avoid having to do a recursive walk until
|
|
4059
|
+
// the walked tree is as shallow as possible.
|
|
4060
|
+
// Note that this is only true up to the last pattern, though, because
|
|
4061
|
+
// a/*/** will only match a/b if b is a dir, but a/**/* will match a/b
|
|
4062
|
+
// regardless, since it's "0 or more path segments" if it's not final.
|
|
4063
|
+
if (this.options.noglobstar) {
|
|
4064
|
+
// ** is * anyway
|
|
4065
|
+
this.globParts = rawGlobParts;
|
|
4195
4066
|
}
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
}
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4067
|
+
else {
|
|
4068
|
+
// do this swap BEFORE the reduce, so that we can turn a string
|
|
4069
|
+
// of **/*/**/* into */*/**/** and then reduce the **'s into one
|
|
4070
|
+
for (const parts of rawGlobParts) {
|
|
4071
|
+
let swapped;
|
|
4072
|
+
do {
|
|
4073
|
+
swapped = false;
|
|
4074
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
4075
|
+
if (parts[i] === '*' && parts[i - 1] === '**') {
|
|
4076
|
+
parts[i] = '**';
|
|
4077
|
+
parts[i - 1] = '*';
|
|
4078
|
+
swapped = true;
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
} while (swapped);
|
|
4082
|
+
}
|
|
4083
|
+
this.globParts = rawGlobParts.map(parts => {
|
|
4084
|
+
parts = parts.reduce((set, part) => {
|
|
4085
|
+
const prev = set[set.length - 1];
|
|
4086
|
+
if (part === '**' && prev === '**') {
|
|
4087
|
+
return set;
|
|
4088
|
+
}
|
|
4089
|
+
if (part === '..') {
|
|
4090
|
+
if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
|
|
4091
|
+
set.pop();
|
|
4092
|
+
return set;
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
set.push(part);
|
|
4096
|
+
return set;
|
|
4097
|
+
}, []);
|
|
4098
|
+
return parts.length === 0 ? [''] : parts;
|
|
4099
|
+
});
|
|
4100
|
+
}
|
|
4101
|
+
this.debug(this.pattern, this.globParts);
|
|
4102
|
+
// glob --> regexps
|
|
4103
|
+
let set = this.globParts.map((s, _, __) => s.map(ss => this.parse(ss)));
|
|
4104
|
+
this.debug(this.pattern, set);
|
|
4105
|
+
// filter out everything that didn't compile properly.
|
|
4106
|
+
this.set = set.filter(s => s.indexOf(false) === -1);
|
|
4107
|
+
// do not treat the ? in UNC paths as magic
|
|
4108
|
+
if (isWindows) {
|
|
4109
|
+
for (let i = 0; i < this.set.length; i++) {
|
|
4110
|
+
const p = this.set[i];
|
|
4111
|
+
if (p[0] === '' &&
|
|
4112
|
+
p[1] === '' &&
|
|
4113
|
+
this.globParts[i][2] === '?' &&
|
|
4114
|
+
typeof p[3] === 'string' &&
|
|
4115
|
+
/^[a-z]:$/i.test(p[3])) {
|
|
4116
|
+
p[2] = '?';
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
this.debug(this.pattern, this.set);
|
|
4121
|
+
}
|
|
4122
|
+
parseNegate() {
|
|
4123
|
+
if (this.nonegate)
|
|
4124
|
+
return;
|
|
4125
|
+
const pattern = this.pattern;
|
|
4126
|
+
let negate = false;
|
|
4127
|
+
let negateOffset = 0;
|
|
4128
|
+
for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
|
|
4129
|
+
negate = !negate;
|
|
4130
|
+
negateOffset++;
|
|
4131
|
+
}
|
|
4132
|
+
if (negateOffset)
|
|
4133
|
+
this.pattern = pattern.slice(negateOffset);
|
|
4134
|
+
this.negate = negate;
|
|
4135
|
+
}
|
|
4136
|
+
// set partial to true to test if, for example,
|
|
4137
|
+
// "/a/b" matches the start of "/*/b/*/d"
|
|
4138
|
+
// Partial means, if you run out of file before you run
|
|
4139
|
+
// out of pattern, then that's fine, as long as all
|
|
4140
|
+
// the parts match.
|
|
4141
|
+
matchOne(file, pattern, partial = false) {
|
|
4142
|
+
// a UNC pattern like //?/c:/* can match a path like c:/x
|
|
4143
|
+
// and vice versa
|
|
4144
|
+
if (isWindows) {
|
|
4145
|
+
const fileUNC = file[0] === '' &&
|
|
4146
|
+
file[1] === '' &&
|
|
4147
|
+
file[2] === '?' &&
|
|
4148
|
+
typeof file[3] === 'string' &&
|
|
4149
|
+
/^[a-z]:$/i.test(file[3]);
|
|
4150
|
+
const patternUNC = pattern[0] === '' &&
|
|
4151
|
+
pattern[1] === '' &&
|
|
4152
|
+
pattern[2] === '?' &&
|
|
4153
|
+
typeof pattern[3] === 'string' &&
|
|
4154
|
+
/^[a-z]:$/i.test(pattern[3]);
|
|
4155
|
+
if (fileUNC && patternUNC) {
|
|
4156
|
+
const fd = file[3];
|
|
4157
|
+
const pd = pattern[3];
|
|
4158
|
+
if (fd.toLowerCase() === pd.toLowerCase()) {
|
|
4159
|
+
file[3] = pd;
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
else if (patternUNC && typeof file[0] === 'string') {
|
|
4163
|
+
const pd = pattern[3];
|
|
4164
|
+
const fd = file[0];
|
|
4165
|
+
if (pd.toLowerCase() === fd.toLowerCase()) {
|
|
4166
|
+
pattern[3] = fd;
|
|
4167
|
+
pattern = pattern.slice(3);
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
else if (fileUNC && typeof pattern[0] === 'string') {
|
|
4171
|
+
const fd = file[3];
|
|
4172
|
+
if (fd.toLowerCase() === pattern[0].toLowerCase()) {
|
|
4173
|
+
pattern[0] = fd;
|
|
4174
|
+
file = file.slice(3);
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
if (pattern.indexOf(GLOBSTAR) !== -1) {
|
|
4179
|
+
return this._matchGlobstar(file, pattern, partial, 0, 0);
|
|
4180
|
+
}
|
|
4181
|
+
return this._matchOne(file, pattern, partial, 0, 0);
|
|
4182
|
+
}
|
|
4183
|
+
_matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
|
|
4184
|
+
// find first globstar from patternIndex
|
|
4185
|
+
let firstgs = -1;
|
|
4186
|
+
for (let i = patternIndex; i < pattern.length; i++) {
|
|
4187
|
+
if (pattern[i] === GLOBSTAR) {
|
|
4188
|
+
firstgs = i;
|
|
4189
|
+
break;
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
// find last globstar
|
|
4193
|
+
let lastgs = -1;
|
|
4194
|
+
for (let i = pattern.length - 1; i >= 0; i--) {
|
|
4195
|
+
if (pattern[i] === GLOBSTAR) {
|
|
4196
|
+
lastgs = i;
|
|
4197
|
+
break;
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
const head = pattern.slice(patternIndex, firstgs);
|
|
4201
|
+
const body = pattern.slice(firstgs + 1, lastgs);
|
|
4202
|
+
const tail = pattern.slice(lastgs + 1);
|
|
4203
|
+
// check the head
|
|
4204
|
+
if (head.length) {
|
|
4205
|
+
const fileHead = file.slice(fileIndex, fileIndex + head.length);
|
|
4206
|
+
if (!this._matchOne(fileHead, head, partial, 0, 0)) {
|
|
4207
|
+
return false;
|
|
4208
|
+
}
|
|
4209
|
+
fileIndex += head.length;
|
|
4210
|
+
}
|
|
4211
|
+
// check the tail
|
|
4212
|
+
let fileTailMatch = 0;
|
|
4213
|
+
if (tail.length) {
|
|
4214
|
+
if (tail.length + fileIndex > file.length)
|
|
4215
|
+
return false;
|
|
4216
|
+
const tailStart = file.length - tail.length;
|
|
4217
|
+
if (this._matchOne(file, tail, partial, tailStart, 0)) {
|
|
4218
|
+
fileTailMatch = tail.length;
|
|
4219
|
+
}
|
|
4220
|
+
else {
|
|
4221
|
+
// affordance for stuff like a/**/* matching a/b/
|
|
4222
|
+
if (file[file.length - 1] !== '' ||
|
|
4223
|
+
fileIndex + tail.length === file.length) {
|
|
4224
|
+
return false;
|
|
4225
|
+
}
|
|
4226
|
+
if (!this._matchOne(file, tail, partial, tailStart - 1, 0)) {
|
|
4227
|
+
return false;
|
|
4228
|
+
}
|
|
4229
|
+
fileTailMatch = tail.length + 1;
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
// if body is empty (single ** between head and tail)
|
|
4233
|
+
if (!body.length) {
|
|
4234
|
+
let sawSome = !!fileTailMatch;
|
|
4235
|
+
for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
|
|
4236
|
+
const f = String(file[i]);
|
|
4237
|
+
sawSome = true;
|
|
4238
|
+
if (f === '.' ||
|
|
4239
|
+
f === '..' ||
|
|
4240
|
+
(!this.options.dot && f.startsWith('.'))) {
|
|
4241
|
+
return false;
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
return sawSome;
|
|
4245
|
+
}
|
|
4246
|
+
// split body into segments at each GLOBSTAR
|
|
4247
|
+
const bodySegments = [[[], 0]];
|
|
4248
|
+
let currentBody = bodySegments[0];
|
|
4249
|
+
let nonGsParts = 0;
|
|
4250
|
+
const nonGsPartsSums = [0];
|
|
4251
|
+
for (const b of body) {
|
|
4252
|
+
if (b === GLOBSTAR) {
|
|
4253
|
+
nonGsPartsSums.push(nonGsParts);
|
|
4254
|
+
currentBody = [[], 0];
|
|
4255
|
+
bodySegments.push(currentBody);
|
|
4256
|
+
}
|
|
4257
|
+
else {
|
|
4258
|
+
currentBody[0].push(b);
|
|
4259
|
+
nonGsParts++;
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
let idx = bodySegments.length - 1;
|
|
4263
|
+
const fileLength = file.length - fileTailMatch;
|
|
4264
|
+
for (const b of bodySegments) {
|
|
4265
|
+
b[1] = fileLength - (nonGsPartsSums[idx--] + b[0].length);
|
|
4266
|
+
}
|
|
4267
|
+
return !!this._matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
|
|
4268
|
+
}
|
|
4269
|
+
// return false for "nope, not matching"
|
|
4270
|
+
// return null for "not matching, cannot keep trying"
|
|
4271
|
+
_matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
|
|
4272
|
+
const bs = bodySegments[bodyIndex];
|
|
4273
|
+
if (!bs) {
|
|
4274
|
+
// just make sure there are no bad dots
|
|
4275
|
+
for (let i = fileIndex; i < file.length; i++) {
|
|
4276
|
+
sawTail = true;
|
|
4277
|
+
const f = file[i];
|
|
4278
|
+
if (f === '.' ||
|
|
4279
|
+
f === '..' ||
|
|
4280
|
+
(!this.options.dot && f.startsWith('.'))) {
|
|
4281
|
+
return false;
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
return sawTail;
|
|
4285
|
+
}
|
|
4286
|
+
const [body, after] = bs;
|
|
4287
|
+
while (fileIndex <= after) {
|
|
4288
|
+
const m = this._matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
|
|
4289
|
+
// if limit exceeded, no match. intentional false negative,
|
|
4290
|
+
// acceptable break in correctness for security.
|
|
4291
|
+
if (m && globStarDepth < this.maxGlobstarRecursion) {
|
|
4292
|
+
const sub = this._matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
|
|
4293
|
+
if (sub !== false) {
|
|
4294
|
+
return sub;
|
|
4295
|
+
}
|
|
4296
|
+
}
|
|
4297
|
+
const f = file[fileIndex];
|
|
4298
|
+
if (f === '.' ||
|
|
4299
|
+
f === '..' ||
|
|
4300
|
+
(!this.options.dot && f.startsWith('.'))) {
|
|
4301
|
+
return false;
|
|
4302
|
+
}
|
|
4303
|
+
fileIndex++;
|
|
4304
|
+
}
|
|
4305
|
+
return null;
|
|
4306
|
+
}
|
|
4307
|
+
_matchOne(file, pattern, partial, fileIndex, patternIndex) {
|
|
4308
|
+
let fi;
|
|
4309
|
+
let pi;
|
|
4310
|
+
let fl;
|
|
4311
|
+
let pl;
|
|
4312
|
+
for (fi = fileIndex,
|
|
4313
|
+
pi = patternIndex,
|
|
4314
|
+
fl = file.length,
|
|
4315
|
+
pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
|
|
4316
|
+
this.debug('matchOne loop');
|
|
4317
|
+
const p = pattern[pi];
|
|
4318
|
+
const f = file[fi];
|
|
4319
|
+
this.debug(pattern, p, f);
|
|
4320
|
+
// should be impossible.
|
|
4321
|
+
// some invalid regexp stuff in the set.
|
|
4322
|
+
/* c8 ignore start */
|
|
4323
|
+
if (p === false || p === GLOBSTAR) {
|
|
4324
|
+
return false;
|
|
4325
|
+
}
|
|
4326
|
+
/* c8 ignore stop */
|
|
4327
|
+
// something other than **
|
|
4328
|
+
// non-magic patterns just have to match exactly
|
|
4329
|
+
// patterns with magic have been turned into regexps.
|
|
4330
|
+
let hit;
|
|
4331
|
+
if (typeof p === 'string') {
|
|
4332
|
+
hit = f === p;
|
|
4333
|
+
this.debug('string match', p, f, hit);
|
|
4334
|
+
}
|
|
4335
|
+
else {
|
|
4336
|
+
hit = p.test(f);
|
|
4337
|
+
this.debug('pattern match', p, f, hit);
|
|
4338
|
+
}
|
|
4339
|
+
if (!hit)
|
|
4340
|
+
return false;
|
|
4341
|
+
}
|
|
4342
|
+
// now either we fell off the end of the pattern, or we're done.
|
|
4343
|
+
if (fi === fl && pi === pl) {
|
|
4344
|
+
// ran out of pattern and filename at the same time.
|
|
4345
|
+
// an exact hit!
|
|
4346
|
+
return true;
|
|
4347
|
+
}
|
|
4348
|
+
else if (fi === fl) {
|
|
4349
|
+
// ran out of file, but still had pattern left.
|
|
4350
|
+
// this is ok if we're doing the match as part of
|
|
4351
|
+
// a glob fs traversal.
|
|
4352
|
+
return partial;
|
|
4353
|
+
}
|
|
4354
|
+
else if (pi === pl) {
|
|
4355
|
+
// ran out of pattern, still have file left.
|
|
4356
|
+
// this is only acceptable if we're on the very last
|
|
4357
|
+
// empty segment of a file with a trailing slash.
|
|
4358
|
+
// a/* should match a/b/
|
|
4359
|
+
return fi === fl - 1 && file[fi] === '';
|
|
4360
|
+
/* c8 ignore start */
|
|
4361
|
+
}
|
|
4362
|
+
else {
|
|
4363
|
+
// should be unreachable.
|
|
4364
|
+
throw new Error('wtf?');
|
|
4365
|
+
}
|
|
4366
|
+
/* c8 ignore stop */
|
|
4367
|
+
}
|
|
4368
|
+
braceExpand() {
|
|
4369
|
+
return braceExpand(this.pattern, this.options);
|
|
4370
|
+
}
|
|
4371
|
+
parse(pattern, isSub) {
|
|
4372
|
+
assertValidPattern(pattern);
|
|
4373
|
+
const options = this.options;
|
|
4374
|
+
// shortcuts
|
|
4375
|
+
if (pattern === '**') {
|
|
4376
|
+
if (!options.noglobstar)
|
|
4377
|
+
return GLOBSTAR;
|
|
4378
|
+
else
|
|
4379
|
+
pattern = '*';
|
|
4380
|
+
}
|
|
4381
|
+
if (pattern === '')
|
|
4382
|
+
return '';
|
|
4383
|
+
// far and away, the most common glob pattern parts are
|
|
4384
|
+
// *, *.*, and *.<ext> Add a fast check method for those.
|
|
4385
|
+
let m;
|
|
4386
|
+
let fastTest = null;
|
|
4387
|
+
if (isSub !== SUBPARSE) {
|
|
4388
|
+
if ((m = pattern.match(starRE))) {
|
|
4389
|
+
fastTest = options.dot ? starTestDot : starTest;
|
|
4390
|
+
}
|
|
4391
|
+
else if ((m = pattern.match(starDotExtRE))) {
|
|
4392
|
+
fastTest = (options.nocase
|
|
4393
|
+
? options.dot
|
|
4394
|
+
? starDotExtTestNocaseDot
|
|
4395
|
+
: starDotExtTestNocase
|
|
4396
|
+
: options.dot
|
|
4397
|
+
? starDotExtTestDot
|
|
4398
|
+
: starDotExtTest)(m[1]);
|
|
4399
|
+
}
|
|
4400
|
+
else if ((m = pattern.match(qmarksRE))) {
|
|
4401
|
+
fastTest = (options.nocase
|
|
4402
|
+
? options.dot
|
|
4403
|
+
? qmarksTestNocaseDot
|
|
4404
|
+
: qmarksTestNocase
|
|
4405
|
+
: options.dot
|
|
4406
|
+
? qmarksTestDot
|
|
4407
|
+
: qmarksTest)(m);
|
|
4408
|
+
}
|
|
4409
|
+
else if ((m = pattern.match(starDotStarRE))) {
|
|
4410
|
+
fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
|
|
4411
|
+
}
|
|
4412
|
+
else if ((m = pattern.match(dotStarRE))) {
|
|
4413
|
+
fastTest = dotStarTest;
|
|
4414
|
+
}
|
|
4415
|
+
}
|
|
4416
|
+
let re = '';
|
|
4417
|
+
let hasMagic = false;
|
|
4418
|
+
let escaping = false;
|
|
4419
|
+
// ? => one single character
|
|
4420
|
+
const patternListStack = [];
|
|
4421
|
+
const negativeLists = [];
|
|
4422
|
+
let stateChar = false;
|
|
4423
|
+
let inClass = false;
|
|
4424
|
+
let reClassStart = -1;
|
|
4425
|
+
let classStart = -1;
|
|
4426
|
+
let cs;
|
|
4427
|
+
let pl;
|
|
4428
|
+
let sp;
|
|
4429
|
+
// . and .. never match anything that doesn't start with .,
|
|
4430
|
+
// even when options.dot is set. However, if the pattern
|
|
4431
|
+
// starts with ., then traversal patterns can match.
|
|
4432
|
+
let dotTravAllowed = pattern.charAt(0) === '.';
|
|
4433
|
+
let dotFileAllowed = options.dot || dotTravAllowed;
|
|
4434
|
+
const patternStart = () => dotTravAllowed
|
|
4435
|
+
? ''
|
|
4436
|
+
: dotFileAllowed
|
|
4437
|
+
? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
|
|
4438
|
+
: '(?!\\.)';
|
|
4439
|
+
const subPatternStart = (p) => p.charAt(0) === '.'
|
|
4440
|
+
? ''
|
|
4441
|
+
: options.dot
|
|
4442
|
+
? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
|
|
4443
|
+
: '(?!\\.)';
|
|
4444
|
+
const clearStateChar = () => {
|
|
4445
|
+
if (stateChar) {
|
|
4446
|
+
// we had some state-tracking character
|
|
4447
|
+
// that wasn't consumed by this pass.
|
|
4448
|
+
switch (stateChar) {
|
|
4449
|
+
case '*':
|
|
4450
|
+
re += star;
|
|
4451
|
+
hasMagic = true;
|
|
4452
|
+
break;
|
|
4453
|
+
case '?':
|
|
4454
|
+
re += qmark;
|
|
4455
|
+
hasMagic = true;
|
|
4456
|
+
break;
|
|
4457
|
+
default:
|
|
4458
|
+
re += '\\' + stateChar;
|
|
4459
|
+
break;
|
|
4460
|
+
}
|
|
4461
|
+
this.debug('clearStateChar %j %j', stateChar, re);
|
|
4462
|
+
stateChar = false;
|
|
4463
|
+
}
|
|
4464
|
+
};
|
|
4465
|
+
for (let i = 0, c; i < pattern.length && (c = pattern.charAt(i)); i++) {
|
|
4466
|
+
this.debug('%s\t%s %s %j', pattern, i, re, c);
|
|
4467
|
+
// skip over any that are escaped.
|
|
4468
|
+
if (escaping) {
|
|
4469
|
+
// completely not allowed, even escaped.
|
|
4470
|
+
// should be impossible.
|
|
4471
|
+
/* c8 ignore start */
|
|
4472
|
+
if (c === '/') {
|
|
4473
|
+
return false;
|
|
4474
|
+
}
|
|
4475
|
+
/* c8 ignore stop */
|
|
4476
|
+
if (reSpecials[c]) {
|
|
4477
|
+
re += '\\';
|
|
4478
|
+
}
|
|
4479
|
+
re += c;
|
|
4480
|
+
escaping = false;
|
|
4481
|
+
continue;
|
|
4482
|
+
}
|
|
4483
|
+
switch (c) {
|
|
4484
|
+
// Should already be path-split by now.
|
|
4485
|
+
/* c8 ignore start */
|
|
4486
|
+
case '/': {
|
|
4487
|
+
return false;
|
|
4488
|
+
}
|
|
4489
|
+
/* c8 ignore stop */
|
|
4490
|
+
case '\\':
|
|
4491
|
+
if (inClass && pattern.charAt(i + 1) === '-') {
|
|
4492
|
+
re += c;
|
|
4493
|
+
continue;
|
|
4494
|
+
}
|
|
4495
|
+
clearStateChar();
|
|
4496
|
+
escaping = true;
|
|
4497
|
+
continue;
|
|
4498
|
+
// the various stateChar values
|
|
4499
|
+
// for the "extglob" stuff.
|
|
4500
|
+
case '?':
|
|
4501
|
+
case '*':
|
|
4502
|
+
case '+':
|
|
4503
|
+
case '@':
|
|
4504
|
+
case '!':
|
|
4505
|
+
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
|
|
4506
|
+
// all of those are literals inside a class, except that
|
|
4507
|
+
// the glob [!a] means [^a] in regexp
|
|
4508
|
+
if (inClass) {
|
|
4509
|
+
this.debug(' in class');
|
|
4510
|
+
if (c === '!' && i === classStart + 1)
|
|
4511
|
+
c = '^';
|
|
4512
|
+
re += c;
|
|
4513
|
+
continue;
|
|
4514
|
+
}
|
|
4515
|
+
// coalesce consecutive non-globstar * characters
|
|
4516
|
+
if (c === '*' && stateChar === '*')
|
|
4517
|
+
continue;
|
|
4518
|
+
// if we already have a stateChar, then it means
|
|
4519
|
+
// that there was something like ** or +? in there.
|
|
4520
|
+
// Handle the stateChar, then proceed with this one.
|
|
4521
|
+
this.debug('call clearStateChar %j', stateChar);
|
|
4522
|
+
clearStateChar();
|
|
4523
|
+
stateChar = c;
|
|
4524
|
+
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
4525
|
+
// just clear the statechar *now*, rather than even diving into
|
|
4526
|
+
// the patternList stuff.
|
|
4527
|
+
if (options.noext)
|
|
4528
|
+
clearStateChar();
|
|
4529
|
+
continue;
|
|
4530
|
+
case '(': {
|
|
4531
|
+
if (inClass) {
|
|
4532
|
+
re += '(';
|
|
4533
|
+
continue;
|
|
4534
|
+
}
|
|
4535
|
+
if (!stateChar) {
|
|
4536
|
+
re += '\\(';
|
|
4537
|
+
continue;
|
|
4538
|
+
}
|
|
4539
|
+
const plEntry = {
|
|
4540
|
+
type: stateChar,
|
|
4541
|
+
start: i - 1,
|
|
4542
|
+
reStart: re.length,
|
|
4543
|
+
open: plTypes[stateChar].open,
|
|
4544
|
+
close: plTypes[stateChar].close,
|
|
4545
|
+
};
|
|
4546
|
+
this.debug(this.pattern, '\t', plEntry);
|
|
4547
|
+
patternListStack.push(plEntry);
|
|
4548
|
+
// negation is (?:(?!(?:js)(?:<rest>))[^/]*)
|
|
4549
|
+
re += plEntry.open;
|
|
4550
|
+
// next entry starts with a dot maybe?
|
|
4551
|
+
if (plEntry.start === 0 && plEntry.type !== '!') {
|
|
4552
|
+
dotTravAllowed = true;
|
|
4553
|
+
re += subPatternStart(pattern.slice(i + 1));
|
|
4554
|
+
}
|
|
4555
|
+
this.debug('plType %j %j', stateChar, re);
|
|
4556
|
+
stateChar = false;
|
|
4557
|
+
continue;
|
|
4558
|
+
}
|
|
4559
|
+
case ')': {
|
|
4560
|
+
const plEntry = patternListStack[patternListStack.length - 1];
|
|
4561
|
+
if (inClass || !plEntry) {
|
|
4562
|
+
re += '\\)';
|
|
4563
|
+
continue;
|
|
4564
|
+
}
|
|
4565
|
+
patternListStack.pop();
|
|
4566
|
+
// closing an extglob
|
|
4567
|
+
clearStateChar();
|
|
4568
|
+
hasMagic = true;
|
|
4569
|
+
pl = plEntry;
|
|
4570
|
+
// negation is (?:(?!js)[^/]*)
|
|
4571
|
+
// The others are (?:<pattern>)<type>
|
|
4572
|
+
re += pl.close;
|
|
4573
|
+
if (pl.type === '!') {
|
|
4574
|
+
negativeLists.push(Object.assign(pl, { reEnd: re.length }));
|
|
4575
|
+
}
|
|
4576
|
+
continue;
|
|
4577
|
+
}
|
|
4578
|
+
case '|': {
|
|
4579
|
+
const plEntry = patternListStack[patternListStack.length - 1];
|
|
4580
|
+
if (inClass || !plEntry) {
|
|
4581
|
+
re += '\\|';
|
|
4582
|
+
continue;
|
|
4583
|
+
}
|
|
4584
|
+
clearStateChar();
|
|
4585
|
+
re += '|';
|
|
4586
|
+
// next subpattern can start with a dot?
|
|
4587
|
+
if (plEntry.start === 0 && plEntry.type !== '!') {
|
|
4588
|
+
dotTravAllowed = true;
|
|
4589
|
+
re += subPatternStart(pattern.slice(i + 1));
|
|
4590
|
+
}
|
|
4591
|
+
continue;
|
|
4592
|
+
}
|
|
4593
|
+
// these are mostly the same in regexp and glob
|
|
4594
|
+
case '[':
|
|
4595
|
+
// swallow any state-tracking char before the [
|
|
4596
|
+
clearStateChar();
|
|
4597
|
+
if (inClass) {
|
|
4598
|
+
re += '\\' + c;
|
|
4599
|
+
continue;
|
|
4600
|
+
}
|
|
4601
|
+
inClass = true;
|
|
4602
|
+
classStart = i;
|
|
4603
|
+
reClassStart = re.length;
|
|
4604
|
+
re += c;
|
|
4605
|
+
continue;
|
|
4606
|
+
case ']':
|
|
4607
|
+
// a right bracket shall lose its special
|
|
4608
|
+
// meaning and represent itself in
|
|
4609
|
+
// a bracket expression if it occurs
|
|
4610
|
+
// first in the list. -- POSIX.2 2.8.3.2
|
|
4611
|
+
if (i === classStart + 1 || !inClass) {
|
|
4612
|
+
re += '\\' + c;
|
|
4613
|
+
continue;
|
|
4614
|
+
}
|
|
4615
|
+
// split where the last [ was, make sure we don't have
|
|
4616
|
+
// an invalid re. if so, re-walk the contents of the
|
|
4617
|
+
// would-be class to re-translate any characters that
|
|
4618
|
+
// were passed through as-is
|
|
4619
|
+
// TODO: It would probably be faster to determine this
|
|
4620
|
+
// without a try/catch and a new RegExp, but it's tricky
|
|
4621
|
+
// to do safely. For now, this is safe and works.
|
|
4622
|
+
cs = pattern.substring(classStart + 1, i);
|
|
4623
|
+
try {
|
|
4624
|
+
RegExp('[' + braExpEscape(charUnescape(cs)) + ']');
|
|
4625
|
+
// looks good, finish up the class.
|
|
4626
|
+
re += c;
|
|
4627
|
+
}
|
|
4628
|
+
catch (er) {
|
|
4629
|
+
// out of order ranges in JS are errors, but in glob syntax,
|
|
4630
|
+
// they're just a range that matches nothing.
|
|
4631
|
+
re = re.substring(0, reClassStart) + '(?:$.)'; // match nothing ever
|
|
4632
|
+
}
|
|
4633
|
+
hasMagic = true;
|
|
4634
|
+
inClass = false;
|
|
4635
|
+
continue;
|
|
4636
|
+
default:
|
|
4637
|
+
// swallow any state char that wasn't consumed
|
|
4638
|
+
clearStateChar();
|
|
4639
|
+
if (reSpecials[c] && !(c === '^' && inClass)) {
|
|
4640
|
+
re += '\\';
|
|
4641
|
+
}
|
|
4642
|
+
re += c;
|
|
4643
|
+
break;
|
|
4644
|
+
} // switch
|
|
4645
|
+
} // for
|
|
4646
|
+
// handle the case where we left a class open.
|
|
4647
|
+
// "[abc" is valid, equivalent to "\[abc"
|
|
4648
|
+
if (inClass) {
|
|
4649
|
+
// split where the last [ was, and escape it
|
|
4650
|
+
// this is a huge pita. We now have to re-walk
|
|
4651
|
+
// the contents of the would-be class to re-translate
|
|
4652
|
+
// any characters that were passed through as-is
|
|
4653
|
+
cs = pattern.slice(classStart + 1);
|
|
4654
|
+
sp = this.parse(cs, SUBPARSE);
|
|
4655
|
+
re = re.substring(0, reClassStart) + '\\[' + sp[0];
|
|
4656
|
+
hasMagic = hasMagic || sp[1];
|
|
4657
|
+
}
|
|
4658
|
+
// handle the case where we had a +( thing at the *end*
|
|
4659
|
+
// of the pattern.
|
|
4660
|
+
// each pattern list stack adds 3 chars, and we need to go through
|
|
4661
|
+
// and escape any | chars that were passed through as-is for the regexp.
|
|
4662
|
+
// Go through and escape them, taking care not to double-escape any
|
|
4663
|
+
// | chars that were already escaped.
|
|
4664
|
+
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|
4665
|
+
let tail;
|
|
4666
|
+
tail = re.slice(pl.reStart + pl.open.length);
|
|
4667
|
+
this.debug(this.pattern, 'setting tail', re, pl);
|
|
4668
|
+
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
4669
|
+
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
|
|
4670
|
+
if (!$2) {
|
|
4671
|
+
// the | isn't already escaped, so escape it.
|
|
4672
|
+
$2 = '\\';
|
|
4673
|
+
// should already be done
|
|
4674
|
+
/* c8 ignore start */
|
|
4675
|
+
}
|
|
4676
|
+
/* c8 ignore stop */
|
|
4677
|
+
// need to escape all those slashes *again*, without escaping the
|
|
4678
|
+
// one that we need for escaping the | character. As it works out,
|
|
4679
|
+
// escaping an even number of slashes can be done by simply repeating
|
|
4680
|
+
// it exactly after itself. That's why this trick works.
|
|
4681
|
+
//
|
|
4682
|
+
// I am sorry that you have to see this.
|
|
4683
|
+
return $1 + $1 + $2 + '|';
|
|
4684
|
+
});
|
|
4685
|
+
this.debug('tail=%j\n %s', tail, tail, pl, re);
|
|
4686
|
+
const t = pl.type === '*' ? star : pl.type === '?' ? qmark : '\\' + pl.type;
|
|
4324
4687
|
hasMagic = true;
|
|
4325
|
-
|
|
4326
|
-
default:
|
|
4327
|
-
re += '\\' + stateChar;
|
|
4328
|
-
break
|
|
4688
|
+
re = re.slice(0, pl.reStart) + t + '\\(' + tail;
|
|
4329
4689
|
}
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
|
|
4336
|
-
this.debug('%s\t%s %s %j', pattern, i, re, c);
|
|
4337
|
-
|
|
4338
|
-
// skip over any that are escaped.
|
|
4339
|
-
if (escaping) {
|
|
4340
|
-
/* istanbul ignore next - completely not allowed, even escaped. */
|
|
4341
|
-
if (c === '/') {
|
|
4342
|
-
return false
|
|
4690
|
+
// handle trailing things that only matter at the very end.
|
|
4691
|
+
clearStateChar();
|
|
4692
|
+
if (escaping) {
|
|
4693
|
+
// trailing \\
|
|
4694
|
+
re += '\\\\';
|
|
4343
4695
|
}
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4696
|
+
// only need to apply the nodot start if the re starts with
|
|
4697
|
+
// something that could conceivably capture a dot
|
|
4698
|
+
const addPatternStart = addPatternStartSet[re.charAt(0)];
|
|
4699
|
+
// Hack to work around lack of negative lookbehind in JS
|
|
4700
|
+
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
|
4701
|
+
// like 'a.xyz.yz' doesn't match. So, the first negative
|
|
4702
|
+
// lookahead, has to look ALL the way ahead, to the end of
|
|
4703
|
+
// the pattern.
|
|
4704
|
+
for (let n = negativeLists.length - 1; n > -1; n--) {
|
|
4705
|
+
const nl = negativeLists[n];
|
|
4706
|
+
const nlBefore = re.slice(0, nl.reStart);
|
|
4707
|
+
const nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
|
|
4708
|
+
let nlAfter = re.slice(nl.reEnd);
|
|
4709
|
+
const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter;
|
|
4710
|
+
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
|
4711
|
+
// mean that we should *not* include the ) in the bit that is considered
|
|
4712
|
+
// "after" the negated section.
|
|
4713
|
+
const closeParensBefore = nlBefore.split(')').length;
|
|
4714
|
+
const openParensBefore = nlBefore.split('(').length - closeParensBefore;
|
|
4715
|
+
let cleanAfter = nlAfter;
|
|
4716
|
+
for (let i = 0; i < openParensBefore; i++) {
|
|
4717
|
+
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
|
|
4718
|
+
}
|
|
4719
|
+
nlAfter = cleanAfter;
|
|
4720
|
+
const dollar = nlAfter === '' && isSub !== SUBPARSE ? '(?:$|\\/)' : '';
|
|
4721
|
+
re = nlBefore + nlFirst + nlAfter + dollar + nlLast;
|
|
4347
4722
|
}
|
|
4348
|
-
re
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
switch (c) {
|
|
4354
|
-
/* istanbul ignore next */
|
|
4355
|
-
case '/': {
|
|
4356
|
-
// Should already be path-split by now.
|
|
4357
|
-
return false
|
|
4723
|
+
// if the re is not "" at this point, then we need to make sure
|
|
4724
|
+
// it doesn't match against an empty path part.
|
|
4725
|
+
// Otherwise a/* will match a/, which it should not.
|
|
4726
|
+
if (re !== '' && hasMagic) {
|
|
4727
|
+
re = '(?=.)' + re;
|
|
4358
4728
|
}
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
if (inClass && pattern.charAt(i + 1) === '-') {
|
|
4362
|
-
re += c;
|
|
4363
|
-
continue
|
|
4364
|
-
}
|
|
4365
|
-
|
|
4366
|
-
clearStateChar();
|
|
4367
|
-
escaping = true;
|
|
4368
|
-
continue
|
|
4369
|
-
|
|
4370
|
-
// the various stateChar values
|
|
4371
|
-
// for the "extglob" stuff.
|
|
4372
|
-
case '?':
|
|
4373
|
-
case '*':
|
|
4374
|
-
case '+':
|
|
4375
|
-
case '@':
|
|
4376
|
-
case '!':
|
|
4377
|
-
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
|
|
4378
|
-
|
|
4379
|
-
// all of those are literals inside a class, except that
|
|
4380
|
-
// the glob [!a] means [^a] in regexp
|
|
4381
|
-
if (inClass) {
|
|
4382
|
-
this.debug(' in class');
|
|
4383
|
-
if (c === '!' && i === classStart + 1) c = '^';
|
|
4384
|
-
re += c;
|
|
4385
|
-
continue
|
|
4386
|
-
}
|
|
4387
|
-
|
|
4388
|
-
// coalesce consecutive non-globstar * characters
|
|
4389
|
-
if (c === '*' && stateChar === '*') continue
|
|
4390
|
-
|
|
4391
|
-
// if we already have a stateChar, then it means
|
|
4392
|
-
// that there was something like ** or +? in there.
|
|
4393
|
-
// Handle the stateChar, then proceed with this one.
|
|
4394
|
-
this.debug('call clearStateChar %j', stateChar);
|
|
4395
|
-
clearStateChar();
|
|
4396
|
-
stateChar = c;
|
|
4397
|
-
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
4398
|
-
// just clear the statechar *now*, rather than even diving into
|
|
4399
|
-
// the patternList stuff.
|
|
4400
|
-
if (options.noext) clearStateChar();
|
|
4401
|
-
continue
|
|
4402
|
-
|
|
4403
|
-
case '(': {
|
|
4404
|
-
if (inClass) {
|
|
4405
|
-
re += '(';
|
|
4406
|
-
continue
|
|
4407
|
-
}
|
|
4408
|
-
|
|
4409
|
-
if (!stateChar) {
|
|
4410
|
-
re += '\\(';
|
|
4411
|
-
continue
|
|
4412
|
-
}
|
|
4413
|
-
|
|
4414
|
-
const plEntry = {
|
|
4415
|
-
type: stateChar,
|
|
4416
|
-
start: i - 1,
|
|
4417
|
-
reStart: re.length,
|
|
4418
|
-
open: plTypes[stateChar].open,
|
|
4419
|
-
close: plTypes[stateChar].close,
|
|
4420
|
-
};
|
|
4421
|
-
this.debug(this.pattern, '\t', plEntry);
|
|
4422
|
-
patternListStack.push(plEntry);
|
|
4423
|
-
// negation is (?:(?!(?:js)(?:<rest>))[^/]*)
|
|
4424
|
-
re += plEntry.open;
|
|
4425
|
-
// next entry starts with a dot maybe?
|
|
4426
|
-
if (plEntry.start === 0 && plEntry.type !== '!') {
|
|
4427
|
-
dotTravAllowed = true;
|
|
4428
|
-
re += subPatternStart(pattern.slice(i + 1));
|
|
4429
|
-
}
|
|
4430
|
-
this.debug('plType %j %j', stateChar, re);
|
|
4431
|
-
stateChar = false;
|
|
4432
|
-
continue
|
|
4729
|
+
if (addPatternStart) {
|
|
4730
|
+
re = patternStart() + re;
|
|
4433
4731
|
}
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
if (inClass || !plEntry) {
|
|
4438
|
-
re += '\\)';
|
|
4439
|
-
continue
|
|
4440
|
-
}
|
|
4441
|
-
patternListStack.pop();
|
|
4442
|
-
|
|
4443
|
-
// closing an extglob
|
|
4444
|
-
clearStateChar();
|
|
4445
|
-
hasMagic = true;
|
|
4446
|
-
pl = plEntry;
|
|
4447
|
-
// negation is (?:(?!js)[^/]*)
|
|
4448
|
-
// The others are (?:<pattern>)<type>
|
|
4449
|
-
re += pl.close;
|
|
4450
|
-
if (pl.type === '!') {
|
|
4451
|
-
negativeLists.push(Object.assign(pl, { reEnd: re.length }));
|
|
4452
|
-
}
|
|
4453
|
-
continue
|
|
4732
|
+
// parsing just a piece of a larger pattern.
|
|
4733
|
+
if (isSub === SUBPARSE) {
|
|
4734
|
+
return [re, hasMagic];
|
|
4454
4735
|
}
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
if (inClass || !plEntry) {
|
|
4459
|
-
re += '\\|';
|
|
4460
|
-
continue
|
|
4461
|
-
}
|
|
4462
|
-
|
|
4463
|
-
clearStateChar();
|
|
4464
|
-
re += '|';
|
|
4465
|
-
// next subpattern can start with a dot?
|
|
4466
|
-
if (plEntry.start === 0 && plEntry.type !== '!') {
|
|
4467
|
-
dotTravAllowed = true;
|
|
4468
|
-
re += subPatternStart(pattern.slice(i + 1));
|
|
4469
|
-
}
|
|
4470
|
-
continue
|
|
4736
|
+
// if it's nocase, and the lcase/uppercase don't match, it's magic
|
|
4737
|
+
if (options.nocase && !hasMagic && !options.nocaseMagicOnly) {
|
|
4738
|
+
hasMagic = pattern.toUpperCase() !== pattern.toLowerCase();
|
|
4471
4739
|
}
|
|
4472
|
-
|
|
4473
|
-
//
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
if (inClass) {
|
|
4479
|
-
re += '\\' + c;
|
|
4480
|
-
continue
|
|
4481
|
-
}
|
|
4482
|
-
|
|
4483
|
-
inClass = true;
|
|
4484
|
-
classStart = i;
|
|
4485
|
-
reClassStart = re.length;
|
|
4486
|
-
re += c;
|
|
4487
|
-
continue
|
|
4488
|
-
|
|
4489
|
-
case ']':
|
|
4490
|
-
// a right bracket shall lose its special
|
|
4491
|
-
// meaning and represent itself in
|
|
4492
|
-
// a bracket expression if it occurs
|
|
4493
|
-
// first in the list. -- POSIX.2 2.8.3.2
|
|
4494
|
-
if (i === classStart + 1 || !inClass) {
|
|
4495
|
-
re += '\\' + c;
|
|
4496
|
-
continue
|
|
4497
|
-
}
|
|
4498
|
-
|
|
4499
|
-
// split where the last [ was, make sure we don't have
|
|
4500
|
-
// an invalid re. if so, re-walk the contents of the
|
|
4501
|
-
// would-be class to re-translate any characters that
|
|
4502
|
-
// were passed through as-is
|
|
4503
|
-
// TODO: It would probably be faster to determine this
|
|
4504
|
-
// without a try/catch and a new RegExp, but it's tricky
|
|
4505
|
-
// to do safely. For now, this is safe and works.
|
|
4506
|
-
cs = pattern.substring(classStart + 1, i);
|
|
4507
|
-
try {
|
|
4508
|
-
RegExp('[' + braExpEscape(charUnescape(cs)) + ']');
|
|
4509
|
-
// looks good, finish up the class.
|
|
4510
|
-
re += c;
|
|
4511
|
-
} catch (er) {
|
|
4512
|
-
// out of order ranges in JS are errors, but in glob syntax,
|
|
4513
|
-
// they're just a range that matches nothing.
|
|
4514
|
-
re = re.substring(0, reClassStart) + '(?:$.)'; // match nothing ever
|
|
4515
|
-
}
|
|
4516
|
-
hasMagic = true;
|
|
4517
|
-
inClass = false;
|
|
4518
|
-
continue
|
|
4519
|
-
|
|
4520
|
-
default:
|
|
4521
|
-
// swallow any state char that wasn't consumed
|
|
4522
|
-
clearStateChar();
|
|
4523
|
-
|
|
4524
|
-
if (reSpecials[c] && !(c === '^' && inClass)) {
|
|
4525
|
-
re += '\\';
|
|
4526
|
-
}
|
|
4527
|
-
|
|
4528
|
-
re += c;
|
|
4529
|
-
break
|
|
4530
|
-
|
|
4531
|
-
} // switch
|
|
4532
|
-
} // for
|
|
4533
|
-
|
|
4534
|
-
// handle the case where we left a class open.
|
|
4535
|
-
// "[abc" is valid, equivalent to "\[abc"
|
|
4536
|
-
if (inClass) {
|
|
4537
|
-
// split where the last [ was, and escape it
|
|
4538
|
-
// this is a huge pita. We now have to re-walk
|
|
4539
|
-
// the contents of the would-be class to re-translate
|
|
4540
|
-
// any characters that were passed through as-is
|
|
4541
|
-
cs = pattern.slice(classStart + 1);
|
|
4542
|
-
sp = this.parse(cs, SUBPARSE);
|
|
4543
|
-
re = re.substring(0, reClassStart) + '\\[' + sp[0];
|
|
4544
|
-
hasMagic = hasMagic || sp[1];
|
|
4545
|
-
}
|
|
4546
|
-
|
|
4547
|
-
// handle the case where we had a +( thing at the *end*
|
|
4548
|
-
// of the pattern.
|
|
4549
|
-
// each pattern list stack adds 3 chars, and we need to go through
|
|
4550
|
-
// and escape any | chars that were passed through as-is for the regexp.
|
|
4551
|
-
// Go through and escape them, taking care not to double-escape any
|
|
4552
|
-
// | chars that were already escaped.
|
|
4553
|
-
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|
4554
|
-
let tail;
|
|
4555
|
-
tail = re.slice(pl.reStart + pl.open.length);
|
|
4556
|
-
this.debug('setting tail', re, pl);
|
|
4557
|
-
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
4558
|
-
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
|
|
4559
|
-
/* istanbul ignore else - should already be done */
|
|
4560
|
-
if (!$2) {
|
|
4561
|
-
// the | isn't already escaped, so escape it.
|
|
4562
|
-
$2 = '\\';
|
|
4740
|
+
// skip the regexp for non-magical patterns
|
|
4741
|
+
// unescape anything in it, though, so that it'll be
|
|
4742
|
+
// an exact match against a file etc.
|
|
4743
|
+
if (!hasMagic) {
|
|
4744
|
+
return globUnescape(pattern);
|
|
4563
4745
|
}
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
// only need to apply the nodot start if the re starts with
|
|
4591
|
-
// something that could conceivably capture a dot
|
|
4592
|
-
const addPatternStart = addPatternStartSet[re.charAt(0)];
|
|
4593
|
-
|
|
4594
|
-
// Hack to work around lack of negative lookbehind in JS
|
|
4595
|
-
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
|
4596
|
-
// like 'a.xyz.yz' doesn't match. So, the first negative
|
|
4597
|
-
// lookahead, has to look ALL the way ahead, to the end of
|
|
4598
|
-
// the pattern.
|
|
4599
|
-
for (let n = negativeLists.length - 1; n > -1; n--) {
|
|
4600
|
-
const nl = negativeLists[n];
|
|
4601
|
-
|
|
4602
|
-
const nlBefore = re.slice(0, nl.reStart);
|
|
4603
|
-
const nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
|
|
4604
|
-
let nlAfter = re.slice(nl.reEnd);
|
|
4605
|
-
const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter;
|
|
4606
|
-
|
|
4607
|
-
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
|
4608
|
-
// mean that we should *not* include the ) in the bit that is considered
|
|
4609
|
-
// "after" the negated section.
|
|
4610
|
-
const closeParensBefore = nlBefore.split(')').length;
|
|
4611
|
-
const openParensBefore = nlBefore.split('(').length - closeParensBefore;
|
|
4612
|
-
let cleanAfter = nlAfter;
|
|
4613
|
-
for (let i = 0; i < openParensBefore; i++) {
|
|
4614
|
-
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
|
|
4615
|
-
}
|
|
4616
|
-
nlAfter = cleanAfter;
|
|
4617
|
-
|
|
4618
|
-
const dollar = nlAfter === '' && isSub !== SUBPARSE ? '(?:$|\\/)' : '';
|
|
4619
|
-
|
|
4620
|
-
re = nlBefore + nlFirst + nlAfter + dollar + nlLast;
|
|
4621
|
-
}
|
|
4622
|
-
|
|
4623
|
-
// if the re is not "" at this point, then we need to make sure
|
|
4624
|
-
// it doesn't match against an empty path part.
|
|
4625
|
-
// Otherwise a/* will match a/, which it should not.
|
|
4626
|
-
if (re !== '' && hasMagic) {
|
|
4627
|
-
re = '(?=.)' + re;
|
|
4628
|
-
}
|
|
4629
|
-
|
|
4630
|
-
if (addPatternStart) {
|
|
4631
|
-
re = patternStart() + re;
|
|
4632
|
-
}
|
|
4633
|
-
|
|
4634
|
-
// parsing just a piece of a larger pattern.
|
|
4635
|
-
if (isSub === SUBPARSE) {
|
|
4636
|
-
return [re, hasMagic]
|
|
4637
|
-
}
|
|
4638
|
-
|
|
4639
|
-
// if it's nocase, and the lcase/uppercase don't match, it's magic
|
|
4640
|
-
if (options.nocase && !hasMagic) {
|
|
4641
|
-
hasMagic = pattern.toUpperCase() !== pattern.toLowerCase();
|
|
4642
|
-
}
|
|
4643
|
-
|
|
4644
|
-
// skip the regexp for non-magical patterns
|
|
4645
|
-
// unescape anything in it, though, so that it'll be
|
|
4646
|
-
// an exact match against a file etc.
|
|
4647
|
-
if (!hasMagic) {
|
|
4648
|
-
return globUnescape(pattern)
|
|
4746
|
+
const flags = options.nocase ? 'i' : '';
|
|
4747
|
+
try {
|
|
4748
|
+
const ext = fastTest
|
|
4749
|
+
? {
|
|
4750
|
+
_glob: pattern,
|
|
4751
|
+
_src: re,
|
|
4752
|
+
test: fastTest,
|
|
4753
|
+
}
|
|
4754
|
+
: {
|
|
4755
|
+
_glob: pattern,
|
|
4756
|
+
_src: re,
|
|
4757
|
+
};
|
|
4758
|
+
return Object.assign(new RegExp('^' + re + '$', flags), ext);
|
|
4759
|
+
/* c8 ignore start */
|
|
4760
|
+
}
|
|
4761
|
+
catch (er) {
|
|
4762
|
+
// should be impossible
|
|
4763
|
+
// If it was an invalid regular expression, then it can't match
|
|
4764
|
+
// anything. This trick looks for a character after the end of
|
|
4765
|
+
// the string, which is of course impossible, except in multi-line
|
|
4766
|
+
// mode, but it's not a /m regex.
|
|
4767
|
+
this.debug('invalid regexp', er);
|
|
4768
|
+
return new RegExp('$.');
|
|
4769
|
+
}
|
|
4770
|
+
/* c8 ignore stop */
|
|
4649
4771
|
}
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4772
|
+
makeRe() {
|
|
4773
|
+
if (this.regexp || this.regexp === false)
|
|
4774
|
+
return this.regexp;
|
|
4775
|
+
// at this point, this.set is a 2d array of partial
|
|
4776
|
+
// pattern strings, or "**".
|
|
4777
|
+
//
|
|
4778
|
+
// It's better to use .match(). This function shouldn't
|
|
4779
|
+
// be used, really, but it's pretty convenient sometimes,
|
|
4780
|
+
// when you just want to work with a regex.
|
|
4781
|
+
const set = this.set;
|
|
4782
|
+
if (!set.length) {
|
|
4783
|
+
this.regexp = false;
|
|
4784
|
+
return this.regexp;
|
|
4785
|
+
}
|
|
4786
|
+
const options = this.options;
|
|
4787
|
+
const twoStar = options.noglobstar
|
|
4788
|
+
? star
|
|
4789
|
+
: options.dot
|
|
4790
|
+
? twoStarDot
|
|
4791
|
+
: twoStarNoDot;
|
|
4792
|
+
const flags = options.nocase ? 'i' : '';
|
|
4793
|
+
// regexpify non-globstar patterns
|
|
4794
|
+
// if ** is only item, then we just do one twoStar
|
|
4795
|
+
// if ** is first, and there are more, prepend (\/|twoStar\/)? to next
|
|
4796
|
+
// if ** is last, append (\/twoStar|) to previous
|
|
4797
|
+
// if ** is in the middle, append (\/|\/twoStar\/) to previous
|
|
4798
|
+
// then filter out GLOBSTAR symbols
|
|
4799
|
+
let re = set
|
|
4800
|
+
.map(pattern => {
|
|
4801
|
+
const pp = pattern.map(p => typeof p === 'string'
|
|
4802
|
+
? regExpEscape(p)
|
|
4803
|
+
: p === GLOBSTAR
|
|
4804
|
+
? GLOBSTAR
|
|
4805
|
+
: p._src);
|
|
4806
|
+
pp.forEach((p, i) => {
|
|
4807
|
+
const next = pp[i + 1];
|
|
4808
|
+
const prev = pp[i - 1];
|
|
4809
|
+
if (p !== GLOBSTAR || prev === GLOBSTAR) {
|
|
4810
|
+
return;
|
|
4811
|
+
}
|
|
4812
|
+
if (prev === undefined) {
|
|
4813
|
+
if (next !== undefined && next !== GLOBSTAR) {
|
|
4814
|
+
pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
|
|
4815
|
+
}
|
|
4816
|
+
else {
|
|
4817
|
+
pp[i] = twoStar;
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
else if (next === undefined) {
|
|
4821
|
+
pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
|
|
4822
|
+
}
|
|
4823
|
+
else if (next !== GLOBSTAR) {
|
|
4824
|
+
pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
|
|
4825
|
+
pp[i + 1] = GLOBSTAR;
|
|
4826
|
+
}
|
|
4827
|
+
});
|
|
4828
|
+
return pp.filter(p => p !== GLOBSTAR).join('/');
|
|
4829
|
+
})
|
|
4830
|
+
.join('|');
|
|
4831
|
+
// must match entire pattern
|
|
4832
|
+
// ending in a * or ** will make it less strict.
|
|
4833
|
+
re = '^(?:' + re + ')$';
|
|
4834
|
+
// can match anything, as long as it's not this.
|
|
4835
|
+
if (this.negate)
|
|
4836
|
+
re = '^(?!' + re + ').*$';
|
|
4837
|
+
try {
|
|
4838
|
+
this.regexp = new RegExp(re, flags);
|
|
4839
|
+
/* c8 ignore start */
|
|
4702
4840
|
}
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
|
|
4707
|
-
return
|
|
4841
|
+
catch (ex) {
|
|
4842
|
+
// should be impossible
|
|
4843
|
+
this.regexp = false;
|
|
4708
4844
|
}
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4845
|
+
/* c8 ignore stop */
|
|
4846
|
+
return this.regexp;
|
|
4847
|
+
}
|
|
4848
|
+
slashSplit(p) {
|
|
4849
|
+
// if p starts with // on windows, we preserve that
|
|
4850
|
+
// so that UNC paths aren't broken. Otherwise, any number of
|
|
4851
|
+
// / characters are coalesced into one, unless
|
|
4852
|
+
// preserveMultipleSlashes is set to true.
|
|
4853
|
+
if (this.preserveMultipleSlashes) {
|
|
4854
|
+
return p.split('/');
|
|
4855
|
+
}
|
|
4856
|
+
else if (isWindows && /^\/\/[^\/]+/.test(p)) {
|
|
4857
|
+
// add an extra '' for the one we lose
|
|
4858
|
+
return ['', ...p.split(/\/+/)];
|
|
4859
|
+
}
|
|
4860
|
+
else {
|
|
4861
|
+
return p.split(/\/+/);
|
|
4720
4862
|
}
|
|
4721
|
-
});
|
|
4722
|
-
return pattern.filter(p => p !== GLOBSTAR).join('/')
|
|
4723
|
-
}).join('|');
|
|
4724
|
-
|
|
4725
|
-
// must match entire pattern
|
|
4726
|
-
// ending in a * or ** will make it less strict.
|
|
4727
|
-
re = '^(?:' + re + ')$';
|
|
4728
|
-
|
|
4729
|
-
// can match anything, as long as it's not this.
|
|
4730
|
-
if (this.negate) re = '^(?!' + re + ').*$';
|
|
4731
|
-
|
|
4732
|
-
try {
|
|
4733
|
-
this.regexp = new RegExp(re, flags);
|
|
4734
|
-
} catch (ex) /* istanbul ignore next - should be impossible */ {
|
|
4735
|
-
this.regexp = false;
|
|
4736
|
-
}
|
|
4737
|
-
return this.regexp
|
|
4738
|
-
}
|
|
4739
|
-
|
|
4740
|
-
match (f, partial = this.partial) {
|
|
4741
|
-
this.debug('match', f, this.pattern);
|
|
4742
|
-
// short-circuit in the case of busted things.
|
|
4743
|
-
// comments, etc.
|
|
4744
|
-
if (this.comment) return false
|
|
4745
|
-
if (this.empty) return f === ''
|
|
4746
|
-
|
|
4747
|
-
if (f === '/' && partial) return true
|
|
4748
|
-
|
|
4749
|
-
const options = this.options;
|
|
4750
|
-
|
|
4751
|
-
// windows: need to use /, not \
|
|
4752
|
-
if (path.sep !== '/') {
|
|
4753
|
-
f = f.split(path.sep).join('/');
|
|
4754
4863
|
}
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4864
|
+
match(f, partial = this.partial) {
|
|
4865
|
+
this.debug('match', f, this.pattern);
|
|
4866
|
+
// short-circuit in the case of busted things.
|
|
4867
|
+
// comments, etc.
|
|
4868
|
+
if (this.comment) {
|
|
4869
|
+
return false;
|
|
4870
|
+
}
|
|
4871
|
+
if (this.empty) {
|
|
4872
|
+
return f === '';
|
|
4873
|
+
}
|
|
4874
|
+
if (f === '/' && partial) {
|
|
4875
|
+
return true;
|
|
4876
|
+
}
|
|
4877
|
+
const options = this.options;
|
|
4878
|
+
// windows: need to use /, not \
|
|
4879
|
+
if (path.sep !== '/') {
|
|
4880
|
+
f = f.split(path.sep).join('/');
|
|
4881
|
+
}
|
|
4882
|
+
// treat the test path as a set of pathparts.
|
|
4883
|
+
const ff = this.slashSplit(f);
|
|
4884
|
+
this.debug(this.pattern, 'split', ff);
|
|
4885
|
+
// just ONE of the pattern sets in this.set needs to match
|
|
4886
|
+
// in order for it to be valid. If negating, then just one
|
|
4887
|
+
// match means that we have failed.
|
|
4888
|
+
// Either way, return on the first hit.
|
|
4889
|
+
const set = this.set;
|
|
4890
|
+
this.debug(this.pattern, 'set', set);
|
|
4891
|
+
// Find the basename of the path by looking for the last non-empty segment
|
|
4892
|
+
let filename = ff[ff.length - 1];
|
|
4893
|
+
if (!filename) {
|
|
4894
|
+
for (let i = ff.length - 2; !filename && i >= 0; i--) {
|
|
4895
|
+
filename = ff[i];
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
for (let i = 0; i < set.length; i++) {
|
|
4899
|
+
const pattern = set[i];
|
|
4900
|
+
let file = ff;
|
|
4901
|
+
if (options.matchBase && pattern.length === 1) {
|
|
4902
|
+
file = [filename];
|
|
4903
|
+
}
|
|
4904
|
+
const hit = this.matchOne(file, pattern, partial);
|
|
4905
|
+
if (hit) {
|
|
4906
|
+
if (options.flipNegate) {
|
|
4907
|
+
return true;
|
|
4908
|
+
}
|
|
4909
|
+
return !this.negate;
|
|
4910
|
+
}
|
|
4911
|
+
}
|
|
4912
|
+
// didn't get any hits. this is success if it's a negative
|
|
4913
|
+
// pattern, failure otherwise.
|
|
4914
|
+
if (options.flipNegate) {
|
|
4915
|
+
return false;
|
|
4916
|
+
}
|
|
4917
|
+
return this.negate;
|
|
4773
4918
|
}
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
const pattern = set[i];
|
|
4777
|
-
let file = f;
|
|
4778
|
-
if (options.matchBase && pattern.length === 1) {
|
|
4779
|
-
file = [filename];
|
|
4780
|
-
}
|
|
4781
|
-
const hit = this.matchOne(file, pattern, partial);
|
|
4782
|
-
if (hit) {
|
|
4783
|
-
if (options.flipNegate) return true
|
|
4784
|
-
return !this.negate
|
|
4785
|
-
}
|
|
4919
|
+
static defaults(def) {
|
|
4920
|
+
return minimatch.defaults(def).Minimatch;
|
|
4786
4921
|
}
|
|
4787
|
-
|
|
4788
|
-
// didn't get any hits. this is success if it's a negative
|
|
4789
|
-
// pattern, failure otherwise.
|
|
4790
|
-
if (options.flipNegate) return false
|
|
4791
|
-
return this.negate
|
|
4792
|
-
}
|
|
4793
|
-
|
|
4794
|
-
static defaults (def) {
|
|
4795
|
-
return minimatch.defaults(def).Minimatch
|
|
4796
|
-
}
|
|
4797
4922
|
}
|
|
4798
|
-
|
|
4799
4923
|
minimatch.Minimatch = Minimatch;
|
|
4800
4924
|
|
|
4801
|
-
var minimatch$1 = minimatch_1;
|
|
4802
|
-
|
|
4803
4925
|
const EXPORT_PATTERN = {
|
|
4804
4926
|
type: ramda.includes(ramda.__, [TYPES.EXPORT_DEFAULT_DECLARATION, TYPES.EXPORT_NAMED_DECLARATION])
|
|
4805
4927
|
};
|
|
@@ -4830,9 +4952,9 @@
|
|
|
4830
4952
|
const fullFilePath = context.getFilename();
|
|
4831
4953
|
const basePath = context.options[0].basePath;
|
|
4832
4954
|
return configs.find(config => {
|
|
4833
|
-
const isIncluded = asArray(config.includes).some(pathPattern => minimatch
|
|
4955
|
+
const isIncluded = asArray(config.includes).some(pathPattern => minimatch(fullFilePath, basePath + pathPattern));
|
|
4834
4956
|
if (config.includes && !isIncluded) return false;
|
|
4835
|
-
const isExcluded = asArray(config.excludes).some(pathPattern => minimatch
|
|
4957
|
+
const isExcluded = asArray(config.excludes).some(pathPattern => minimatch(fullFilePath, basePath + pathPattern));
|
|
4836
4958
|
return !(config.excludes && isExcluded);
|
|
4837
4959
|
});
|
|
4838
4960
|
};
|
|
@@ -5574,7 +5696,7 @@
|
|
|
5574
5696
|
translationFiles = neetoCist.modifyBy({
|
|
5575
5697
|
lng
|
|
5576
5698
|
}, ramda.assoc("content", {
|
|
5577
|
-
...parseJsonData(path$
|
|
5699
|
+
...parseJsonData(path$1.join(translationsDirPath, changedFileName)),
|
|
5578
5700
|
...nanosContent[lng]
|
|
5579
5701
|
}), translationFiles);
|
|
5580
5702
|
});
|
|
@@ -5657,11 +5779,11 @@
|
|
|
5657
5779
|
if (neetoCist.isNot(previousOptions, context.options[0])) {
|
|
5658
5780
|
const nanosTranslationOption = context.options[0].nanosTranslationDir;
|
|
5659
5781
|
translationFiles = context.options[0].languages.map(lng => {
|
|
5660
|
-
nanosContent[lng] = nanosTranslationOption ? nanosTranslationOption.map(filePath => path$
|
|
5782
|
+
nanosContent[lng] = nanosTranslationOption ? nanosTranslationOption.map(filePath => path$1.join(filePath, `${lng}.json`)).reduce((mergedObj, filePath) => ({
|
|
5661
5783
|
...mergedObj,
|
|
5662
5784
|
...parseJsonData(filePath)
|
|
5663
5785
|
}), {}) : {};
|
|
5664
|
-
const translationsFilePath = path$
|
|
5786
|
+
const translationsFilePath = path$1.join(context.options[0].translationsDir, `${lng}.json`);
|
|
5665
5787
|
const translationsContent = parseJsonData(translationsFilePath);
|
|
5666
5788
|
const combinedContent = ramda.mergeDeepLeft(translationsContent, nanosContent[lng]);
|
|
5667
5789
|
return {
|
|
@@ -7084,7 +7206,7 @@
|
|
|
7084
7206
|
|
|
7085
7207
|
// Do not replace this with `isInsideApisDirectory` since this rule should include axios.js
|
|
7086
7208
|
// `isInsideApisDirectory` returns false for apis/axios.js
|
|
7087
|
-
const apisFolder = path$
|
|
7209
|
+
const apisFolder = path$1.resolve(aliases?.apis || APIS_DIRECTORY);
|
|
7088
7210
|
if (context.getFilename().startsWith(apisFolder)) return;
|
|
7089
7211
|
if (!isPackageImported(context, node, "axios")) return;
|
|
7090
7212
|
context.report(node, NO_AXIOS_IMPORT_OUTSIDE_APIS_MESSAGE);
|
|
@@ -9530,7 +9652,7 @@
|
|
|
9530
9652
|
const WHITELISTED_FOLDER_NAMES = ["constants", "utils"];
|
|
9531
9653
|
const WHITELISTED_FILE_NAMES = ["constants", "utils"];
|
|
9532
9654
|
|
|
9533
|
-
const getFolderName = fileName => path$
|
|
9655
|
+
const getFolderName = fileName => path$1.basename(path$1.dirname(fileName));
|
|
9534
9656
|
var filesInsideReactQueryFolderShouldEndWithApi = {
|
|
9535
9657
|
meta: {
|
|
9536
9658
|
type: "problem",
|
|
@@ -9562,7 +9684,7 @@
|
|
|
9562
9684
|
};
|
|
9563
9685
|
const isInsideReactQueryDirectory = context => {
|
|
9564
9686
|
const filename = context.getFilename();
|
|
9565
|
-
const reactQueryDirectory = path$
|
|
9687
|
+
const reactQueryDirectory = path$1.resolve(REACT_QUERY_DIRECTORY);
|
|
9566
9688
|
return filename.startsWith(reactQueryDirectory);
|
|
9567
9689
|
};
|
|
9568
9690
|
var useReactQueryForManagingRemoteData = {
|
|
@@ -10649,7 +10771,7 @@
|
|
|
10649
10771
|
|
|
10650
10772
|
const IMAGE_PATH = "images/";
|
|
10651
10773
|
|
|
10652
|
-
const resolvePath = relativePath => path$
|
|
10774
|
+
const resolvePath = relativePath => path$1.resolve(__dirname, "../../../../", relativePath);
|
|
10653
10775
|
const isImportFileSvg = importPath => fs.existsSync(resolvePath(`app/assets/${importPath}.svg`));
|
|
10654
10776
|
const findSrcAttributeIndex = (attributes, svgs) => neetoCist.findIndexBy({
|
|
10655
10777
|
name: {
|
|
@@ -11536,7 +11658,7 @@
|
|
|
11536
11658
|
const aliases = context.options[0];
|
|
11537
11659
|
if (ramda.isEmpty(aliases) || ramda.isNil(aliases)) return;
|
|
11538
11660
|
const importPath = node.source.value;
|
|
11539
|
-
const importFullPath = importPath.startsWith("../") ? path$
|
|
11661
|
+
const importFullPath = importPath.startsWith("../") ? path$1.resolve(context.getFilename(), "../", importPath) : importPath;
|
|
11540
11662
|
const matches = Object.entries(aliases).filter(([, path]) => importFullPath.startsWith(path) && ["/", undefined].includes(importFullPath.split(path)[1][0])).sort((first, second) => first.length - second.length);
|
|
11541
11663
|
if (matches.length === 0) return;
|
|
11542
11664
|
const aliasMatch = matches[matches.length - 1];
|