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