@bigbinary/eslint-plugin-neeto 1.8.1 → 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.
Files changed (2) hide show
  1. package/dist/index.js +1130 -1029
  2. 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$2, global.ramda, global["@bigbinary/neeto-cist"], global.neetoCommonsConstants));
5
- })(this, (function (fs, path$2, ramda, neetoCist, neetoCommonsConstants) { 'use strict';
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$2.resolve(__dirname, "../../../..", jsPath);
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$2.resolve(__dirname, "../../../..", jsPath);
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$2.join(__dirname, "../../../../");
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$2.join(rootOfTheProject, jsPath));
266
+ return require(path$1.join(rootOfTheProject, jsPath));
267
267
  } catch {
268
268
  return {};
269
269
  }
@@ -285,114 +285,9 @@
285
285
  }
286
286
  });
287
287
 
288
- var name = "@bigbinary/eslint-plugin-neeto";
289
- var version = "1.8.0";
290
- var main = "dist/index.js";
291
- var license = "UNLICENSED";
292
- var scripts = {
293
- prepare: "husky install",
294
- test: "npm run build && jest dist/util-tests.spec.js && node dist/rule-tests.js",
295
- build: "rollup --bundleConfigAsCjs -c rollup.config.js",
296
- watch: "rollup --bundleConfigAsCjs -c rollup.config.js --watch"
297
- };
298
- var files = [
299
- "dist/index.js",
300
- "dist/resolveConfigWorker.js"
301
- ];
302
- var engines = {
303
- node: ">=22.13",
304
- npm: ">=9",
305
- yarn: ">=1.22"
306
- };
307
- var dependencies = {
308
- };
309
- var devDependencies = {
310
- "@babel/core": "^7.19.1",
311
- "@babel/eslint-parser": "^7.27.5",
312
- "@babel/plugin-transform-runtime": "^7.19.1",
313
- "@babel/preset-env": "7.17.10",
314
- "@babel/preset-react": "7.16.7",
315
- "@babel/preset-typescript": "^7.18.6",
316
- "@babel/runtime": "^7.19.0",
317
- "@bigbinary/babel-preset-neeto": "^1.0.3",
318
- "@bigbinary/eslint-plugin-neeto": "^1.7.2",
319
- "@bigbinary/neeto-cist": "^1.0.3",
320
- "@bigbinary/neeto-commons-frontend": "^4.13.42",
321
- "@rollup/plugin-alias": "^3.1.9",
322
- "@rollup/plugin-babel": "^6.0.4",
323
- "@rollup/plugin-commonjs": "^22.0.0",
324
- "@rollup/plugin-json": "^4.1.0",
325
- "@rollup/plugin-node-resolve": "^15.3.0",
326
- "babel-loader": "^8.2.5",
327
- "babel-plugin-dynamic-import-node": "^2.3.3",
328
- "babel-plugin-istanbul": "^6.1.1",
329
- "babel-plugin-js-logger": "1.0.17",
330
- "babel-plugin-macros": "3.1.0",
331
- "babel-plugin-module-resolver": "^5.0.0",
332
- "babel-plugin-preval": "^5.1.0",
333
- "babel-plugin-transform-imports": "^2.0.0",
334
- "babel-plugin-transform-react-remove-prop-types": "0.4.24",
335
- "babel-preset-react": "6.24.1",
336
- "babel-preset-typescript": "^7.0.0-alpha.19",
337
- cheerio: "^1.0.0-rc.12",
338
- "command-line-args": "^5.2.1",
339
- eslint: "^9.25.1",
340
- "eslint-config-prettier": "^10.1.2",
341
- "eslint-plugin-import": "^2.31.0",
342
- "eslint-plugin-jam3": "^0.2.3",
343
- "eslint-plugin-json": "^4.0.1",
344
- "eslint-plugin-prettier": "^5.2.6",
345
- "eslint-plugin-promise": "^7.2.1",
346
- "eslint-plugin-react": "^7.37.5",
347
- "eslint-plugin-react-hooks": "^5.2.0",
348
- "eslint-plugin-security": "^3.0.1",
349
- "eslint-plugin-sonarjs": "^3.0.2",
350
- "eslint-plugin-unused-imports": "^4.1.4",
351
- globals: "^16.0.0",
352
- husky: "7.0.4",
353
- i18next: "21.7.0",
354
- jest: "27.5.1",
355
- "lint-staged": "12.4.1",
356
- minimatch: "^5.1.0",
357
- "mock-fs": "^5.2.0",
358
- prettier: "2.6.2",
359
- ramda: "0.29.0",
360
- rollup: "^4.24.0",
361
- "rollup-plugin-analyzer": "^4.0.0",
362
- "rollup-plugin-cleaner": "^1.0.0",
363
- "rollup-plugin-copy": "^3.5.0",
364
- "rollup-plugin-peer-deps-external": "^2.2.4",
365
- synckit: "^0.9.0"
366
- };
367
- var peerDependencies = {
368
- "@bigbinary/neeto-cist": "^1.0.3",
369
- "@bigbinary/neeto-commons-frontend": "4.13.38",
370
- eslint: "^9.25.1",
371
- i18next: "21.7.0",
372
- ramda: "0.29.0"
373
- };
288
+ var version = "1.8.2";
374
289
  var packageJson = {
375
- name: name,
376
- version: version,
377
- main: main,
378
- license: license,
379
- scripts: scripts,
380
- "lint-staged": {
381
- "{package.json}": [
382
- "prettier --write",
383
- "eslint --fix --no-warn-ignored"
384
- ],
385
- "**/*.js": [
386
- "prettier --write",
387
- "eslint --fix --no-warn-ignored"
388
- ]
389
- },
390
- files: files,
391
- engines: engines,
392
- dependencies: dependencies,
393
- devDependencies: devDependencies,
394
- peerDependencies: peerDependencies
395
- };
290
+ version: version};
396
291
 
397
292
  const prefix = "export default ";
398
293
  var jsonProcessor = {
@@ -459,7 +354,6 @@
459
354
  PROPERTY: "Property",
460
355
  RETURN_STATEMENT: "ReturnStatement",
461
356
  SPREAD_ELEMENT: "SpreadElement",
462
- TEMPLATE_ELEMENT: "TemplateElement",
463
357
  TEMPLATE_LITERAL: "TemplateLiteral",
464
358
  UNARY_EXPRESSION: "UnaryExpression",
465
359
  VARIABLE_DECLARATION: "VariableDeclaration",
@@ -807,7 +701,7 @@
807
701
  */
808
702
  const isInsideApisDirectory = context => {
809
703
  const filename = context.getFilename();
810
- const apisDirectory = path$2.resolve(APIS_DIRECTORY);
704
+ const apisDirectory = path$1.resolve(APIS_DIRECTORY);
811
705
  return filename.startsWith(apisDirectory) && filename !== `${apisDirectory}/axios.js`;
812
706
  };
813
707
 
@@ -818,7 +712,7 @@
818
712
  */
819
713
  const isInsideComponentsDirectory = context => {
820
714
  const filename = context.getFilename();
821
- const componentsDirectory = path$2.resolve(COMPONENTS_DIRECTORY);
715
+ const componentsDirectory = path$1.resolve(COMPONENTS_DIRECTORY);
822
716
  return filename.startsWith(componentsDirectory);
823
717
  };
824
718
 
@@ -891,7 +785,7 @@
891
785
  optional: true
892
786
  }, node);
893
787
  const optionalChainingOptimizedName = (funcName, node) => isOptionalChainingPresent(node) ? `_${funcName}` : funcName;
894
- const isExcludedFile = (excludedFiles, filename) => excludedFiles.some(filePath => filePath.test(path$2.resolve(filename)));
788
+ const isExcludedFile = (excludedFiles, filename) => excludedFiles.some(filePath => filePath.test(path$1.resolve(filename)));
895
789
  const parseJsonData = filePath => {
896
790
  try {
897
791
  const jsonData = fs.readFileSync(filePath).toString();
@@ -1865,8 +1759,8 @@
1865
1759
 
1866
1760
  var semver$1 = {exports: {}};
1867
1761
 
1868
- (function (module, exports) {
1869
- exports = module.exports = SemVer;
1762
+ (function (module, exports$1) {
1763
+ exports$1 = module.exports = SemVer;
1870
1764
 
1871
1765
  var debug;
1872
1766
  /* istanbul ignore next */
@@ -1885,7 +1779,7 @@
1885
1779
 
1886
1780
  // Note: this is the semver.org version of the spec that it implements
1887
1781
  // Not necessarily the package version of this code.
1888
- exports.SEMVER_SPEC_VERSION = '2.0.0';
1782
+ exports$1.SEMVER_SPEC_VERSION = '2.0.0';
1889
1783
 
1890
1784
  var MAX_LENGTH = 256;
1891
1785
  var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
@@ -1897,10 +1791,10 @@
1897
1791
  var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6;
1898
1792
 
1899
1793
  // The actual regexps go on exports.re
1900
- var re = exports.re = [];
1901
- var safeRe = exports.safeRe = [];
1902
- var src = exports.src = [];
1903
- var t = exports.tokens = {};
1794
+ var re = exports$1.re = [];
1795
+ var safeRe = exports$1.safeRe = [];
1796
+ var src = exports$1.src = [];
1797
+ var t = exports$1.tokens = {};
1904
1798
  var R = 0;
1905
1799
 
1906
1800
  function tok (n) {
@@ -2158,7 +2052,7 @@
2158
2052
  }
2159
2053
  }
2160
2054
 
2161
- exports.parse = parse;
2055
+ exports$1.parse = parse;
2162
2056
  function parse (version, options) {
2163
2057
  if (!options || typeof options !== 'object') {
2164
2058
  options = {
@@ -2191,19 +2085,19 @@
2191
2085
  }
2192
2086
  }
2193
2087
 
2194
- exports.valid = valid;
2088
+ exports$1.valid = valid;
2195
2089
  function valid (version, options) {
2196
2090
  var v = parse(version, options);
2197
2091
  return v ? v.version : null
2198
2092
  }
2199
2093
 
2200
- exports.clean = clean;
2094
+ exports$1.clean = clean;
2201
2095
  function clean (version, options) {
2202
2096
  var s = parse(version.trim().replace(/^[=v]+/, ''), options);
2203
2097
  return s ? s.version : null
2204
2098
  }
2205
2099
 
2206
- exports.SemVer = SemVer;
2100
+ exports$1.SemVer = SemVer;
2207
2101
 
2208
2102
  function SemVer (version, options) {
2209
2103
  if (!options || typeof options !== 'object') {
@@ -2474,7 +2368,7 @@
2474
2368
  return this
2475
2369
  };
2476
2370
 
2477
- exports.inc = inc;
2371
+ exports$1.inc = inc;
2478
2372
  function inc (version, release, loose, identifier) {
2479
2373
  if (typeof (loose) === 'string') {
2480
2374
  identifier = loose;
@@ -2488,7 +2382,7 @@
2488
2382
  }
2489
2383
  }
2490
2384
 
2491
- exports.diff = diff;
2385
+ exports$1.diff = diff;
2492
2386
  function diff (version1, version2) {
2493
2387
  if (eq(version1, version2)) {
2494
2388
  return null
@@ -2511,7 +2405,7 @@
2511
2405
  }
2512
2406
  }
2513
2407
 
2514
- exports.compareIdentifiers = compareIdentifiers;
2408
+ exports$1.compareIdentifiers = compareIdentifiers;
2515
2409
 
2516
2410
  var numeric = /^[0-9]+$/;
2517
2411
  function compareIdentifiers (a, b) {
@@ -2530,93 +2424,93 @@
2530
2424
  : 1
2531
2425
  }
2532
2426
 
2533
- exports.rcompareIdentifiers = rcompareIdentifiers;
2427
+ exports$1.rcompareIdentifiers = rcompareIdentifiers;
2534
2428
  function rcompareIdentifiers (a, b) {
2535
2429
  return compareIdentifiers(b, a)
2536
2430
  }
2537
2431
 
2538
- exports.major = major;
2432
+ exports$1.major = major;
2539
2433
  function major (a, loose) {
2540
2434
  return new SemVer(a, loose).major
2541
2435
  }
2542
2436
 
2543
- exports.minor = minor;
2437
+ exports$1.minor = minor;
2544
2438
  function minor (a, loose) {
2545
2439
  return new SemVer(a, loose).minor
2546
2440
  }
2547
2441
 
2548
- exports.patch = patch;
2442
+ exports$1.patch = patch;
2549
2443
  function patch (a, loose) {
2550
2444
  return new SemVer(a, loose).patch
2551
2445
  }
2552
2446
 
2553
- exports.compare = compare;
2447
+ exports$1.compare = compare;
2554
2448
  function compare (a, b, loose) {
2555
2449
  return new SemVer(a, loose).compare(new SemVer(b, loose))
2556
2450
  }
2557
2451
 
2558
- exports.compareLoose = compareLoose;
2452
+ exports$1.compareLoose = compareLoose;
2559
2453
  function compareLoose (a, b) {
2560
2454
  return compare(a, b, true)
2561
2455
  }
2562
2456
 
2563
- exports.compareBuild = compareBuild;
2457
+ exports$1.compareBuild = compareBuild;
2564
2458
  function compareBuild (a, b, loose) {
2565
2459
  var versionA = new SemVer(a, loose);
2566
2460
  var versionB = new SemVer(b, loose);
2567
2461
  return versionA.compare(versionB) || versionA.compareBuild(versionB)
2568
2462
  }
2569
2463
 
2570
- exports.rcompare = rcompare;
2464
+ exports$1.rcompare = rcompare;
2571
2465
  function rcompare (a, b, loose) {
2572
2466
  return compare(b, a, loose)
2573
2467
  }
2574
2468
 
2575
- exports.sort = sort;
2469
+ exports$1.sort = sort;
2576
2470
  function sort (list, loose) {
2577
2471
  return list.sort(function (a, b) {
2578
- return exports.compareBuild(a, b, loose)
2472
+ return exports$1.compareBuild(a, b, loose)
2579
2473
  })
2580
2474
  }
2581
2475
 
2582
- exports.rsort = rsort;
2476
+ exports$1.rsort = rsort;
2583
2477
  function rsort (list, loose) {
2584
2478
  return list.sort(function (a, b) {
2585
- return exports.compareBuild(b, a, loose)
2479
+ return exports$1.compareBuild(b, a, loose)
2586
2480
  })
2587
2481
  }
2588
2482
 
2589
- exports.gt = gt;
2483
+ exports$1.gt = gt;
2590
2484
  function gt (a, b, loose) {
2591
2485
  return compare(a, b, loose) > 0
2592
2486
  }
2593
2487
 
2594
- exports.lt = lt;
2488
+ exports$1.lt = lt;
2595
2489
  function lt (a, b, loose) {
2596
2490
  return compare(a, b, loose) < 0
2597
2491
  }
2598
2492
 
2599
- exports.eq = eq;
2493
+ exports$1.eq = eq;
2600
2494
  function eq (a, b, loose) {
2601
2495
  return compare(a, b, loose) === 0
2602
2496
  }
2603
2497
 
2604
- exports.neq = neq;
2498
+ exports$1.neq = neq;
2605
2499
  function neq (a, b, loose) {
2606
2500
  return compare(a, b, loose) !== 0
2607
2501
  }
2608
2502
 
2609
- exports.gte = gte;
2503
+ exports$1.gte = gte;
2610
2504
  function gte (a, b, loose) {
2611
2505
  return compare(a, b, loose) >= 0
2612
2506
  }
2613
2507
 
2614
- exports.lte = lte;
2508
+ exports$1.lte = lte;
2615
2509
  function lte (a, b, loose) {
2616
2510
  return compare(a, b, loose) <= 0
2617
2511
  }
2618
2512
 
2619
- exports.cmp = cmp;
2513
+ exports$1.cmp = cmp;
2620
2514
  function cmp (a, op, b, loose) {
2621
2515
  switch (op) {
2622
2516
  case '===':
@@ -2658,7 +2552,7 @@
2658
2552
  }
2659
2553
  }
2660
2554
 
2661
- exports.Comparator = Comparator;
2555
+ exports$1.Comparator = Comparator;
2662
2556
  function Comparator (comp, options) {
2663
2557
  if (!options || typeof options !== 'object') {
2664
2558
  options = {
@@ -2790,7 +2684,7 @@
2790
2684
  oppositeDirectionsLessThan || oppositeDirectionsGreaterThan
2791
2685
  };
2792
2686
 
2793
- exports.Range = Range;
2687
+ exports$1.Range = Range;
2794
2688
  function Range (range, options) {
2795
2689
  if (!options || typeof options !== 'object') {
2796
2690
  options = {
@@ -2934,7 +2828,7 @@
2934
2828
  }
2935
2829
 
2936
2830
  // Mostly just for testing and legacy API reasons
2937
- exports.toComparators = toComparators;
2831
+ exports$1.toComparators = toComparators;
2938
2832
  function toComparators (range, options) {
2939
2833
  return new Range(range, options).set.map(function (comp) {
2940
2834
  return comp.map(function (c) {
@@ -3245,7 +3139,7 @@
3245
3139
  return true
3246
3140
  }
3247
3141
 
3248
- exports.satisfies = satisfies;
3142
+ exports$1.satisfies = satisfies;
3249
3143
  function satisfies (version, range, options) {
3250
3144
  try {
3251
3145
  range = new Range(range, options);
@@ -3255,7 +3149,7 @@
3255
3149
  return range.test(version)
3256
3150
  }
3257
3151
 
3258
- exports.maxSatisfying = maxSatisfying;
3152
+ exports$1.maxSatisfying = maxSatisfying;
3259
3153
  function maxSatisfying (versions, range, options) {
3260
3154
  var max = null;
3261
3155
  var maxSV = null;
@@ -3277,7 +3171,7 @@
3277
3171
  return max
3278
3172
  }
3279
3173
 
3280
- exports.minSatisfying = minSatisfying;
3174
+ exports$1.minSatisfying = minSatisfying;
3281
3175
  function minSatisfying (versions, range, options) {
3282
3176
  var min = null;
3283
3177
  var minSV = null;
@@ -3299,7 +3193,7 @@
3299
3193
  return min
3300
3194
  }
3301
3195
 
3302
- exports.minVersion = minVersion;
3196
+ exports$1.minVersion = minVersion;
3303
3197
  function minVersion (range, loose) {
3304
3198
  range = new Range(range, loose);
3305
3199
 
@@ -3353,7 +3247,7 @@
3353
3247
  return null
3354
3248
  }
3355
3249
 
3356
- exports.validRange = validRange;
3250
+ exports$1.validRange = validRange;
3357
3251
  function validRange (range, options) {
3358
3252
  try {
3359
3253
  // Return '*' instead of '' so that truthiness works.
@@ -3365,18 +3259,18 @@
3365
3259
  }
3366
3260
 
3367
3261
  // Determine if version is less than all the versions possible in the range
3368
- exports.ltr = ltr;
3262
+ exports$1.ltr = ltr;
3369
3263
  function ltr (version, range, options) {
3370
3264
  return outside(version, range, '<', options)
3371
3265
  }
3372
3266
 
3373
3267
  // Determine if version is greater than all the versions possible in the range.
3374
- exports.gtr = gtr;
3268
+ exports$1.gtr = gtr;
3375
3269
  function gtr (version, range, options) {
3376
3270
  return outside(version, range, '>', options)
3377
3271
  }
3378
3272
 
3379
- exports.outside = outside;
3273
+ exports$1.outside = outside;
3380
3274
  function outside (version, range, hilo, options) {
3381
3275
  version = new SemVer(version, options);
3382
3276
  range = new Range(range, options);
@@ -3446,20 +3340,20 @@
3446
3340
  return true
3447
3341
  }
3448
3342
 
3449
- exports.prerelease = prerelease;
3343
+ exports$1.prerelease = prerelease;
3450
3344
  function prerelease (version, options) {
3451
3345
  var parsed = parse(version, options);
3452
3346
  return (parsed && parsed.prerelease.length) ? parsed.prerelease : null
3453
3347
  }
3454
3348
 
3455
- exports.intersects = intersects;
3349
+ exports$1.intersects = intersects;
3456
3350
  function intersects (r1, r2, options) {
3457
3351
  r1 = new Range(r1, options);
3458
3352
  r2 = new Range(r2, options);
3459
3353
  return r1.intersects(r2)
3460
3354
  }
3461
3355
 
3462
- exports.coerce = coerce;
3356
+ exports$1.coerce = coerce;
3463
3357
  function coerce (version, options) {
3464
3358
  if (version instanceof SemVer) {
3465
3359
  return version
@@ -3637,11 +3531,6 @@
3637
3531
  })
3638
3532
  };
3639
3533
 
3640
- const isWindows = typeof process === 'object' &&
3641
- process &&
3642
- process.platform === 'win32';
3643
- var path$1 = isWindows ? { sep: '\\' } : { sep: '/' };
3644
-
3645
3534
  var balancedMatch = balanced$1;
3646
3535
  function balanced$1(a, b, str) {
3647
3536
  if (a instanceof RegExp) a = maybeMatch(a, str);
@@ -3781,7 +3670,7 @@
3781
3670
  str = '\\{\\}' + str.substr(2);
3782
3671
  }
3783
3672
 
3784
- return expand$1(escapeBraces(str), true).map(unescapeBraces);
3673
+ return expand(escapeBraces(str), true).map(unescapeBraces);
3785
3674
  }
3786
3675
 
3787
3676
  function embrace(str) {
@@ -3798,7 +3687,7 @@
3798
3687
  return i >= y;
3799
3688
  }
3800
3689
 
3801
- function expand$1(str, isTop) {
3690
+ function expand(str, isTop) {
3802
3691
  var expansions = [];
3803
3692
 
3804
3693
  var m = balanced('{', '}', str);
@@ -3807,7 +3696,7 @@
3807
3696
  // no need to expand pre, since it is guaranteed to be free of brace-sets
3808
3697
  var pre = m.pre;
3809
3698
  var post = m.post.length
3810
- ? expand$1(m.post, false)
3699
+ ? expand(m.post, false)
3811
3700
  : [''];
3812
3701
 
3813
3702
  if (/\$$/.test(m.pre)) {
@@ -3822,9 +3711,9 @@
3822
3711
  var isOptions = m.body.indexOf(',') >= 0;
3823
3712
  if (!isSequence && !isOptions) {
3824
3713
  // {a},b}
3825
- if (m.post.match(/,.*\}/)) {
3714
+ if (m.post.match(/,(?!,).*\}/)) {
3826
3715
  str = m.pre + '{' + m.body + escClose + m.post;
3827
- return expand$1(str);
3716
+ return expand(str);
3828
3717
  }
3829
3718
  return [str];
3830
3719
  }
@@ -3836,7 +3725,7 @@
3836
3725
  n = parseCommaParts(m.body);
3837
3726
  if (n.length === 1) {
3838
3727
  // x{{a,b}}y ==> x{a}y x{b}y
3839
- n = expand$1(n[0], false).map(embrace);
3728
+ n = expand(n[0], false).map(embrace);
3840
3729
  if (n.length === 1) {
3841
3730
  return post.map(function(p) {
3842
3731
  return m.pre + n[0] + p;
@@ -3891,7 +3780,7 @@
3891
3780
  N = [];
3892
3781
 
3893
3782
  for (var j = 0; j < n.length; j++) {
3894
- N.push.apply(N, expand$1(n[j], false));
3783
+ N.push.apply(N, expand(n[j], false));
3895
3784
  }
3896
3785
  }
3897
3786
 
@@ -3907,102 +3796,135 @@
3907
3796
  return expansions;
3908
3797
  }
3909
3798
 
3910
- const minimatch = minimatch_1 = (p, pattern, options = {}) => {
3911
- assertValidPattern(pattern);
3912
-
3913
- // shortcut: comments match nothing.
3914
- if (!options.nocomment && pattern.charAt(0) === '#') {
3915
- return false
3916
- }
3917
-
3918
- return new Minimatch(pattern, options).match(p)
3919
- };
3920
-
3921
- var minimatch_1 = minimatch;
3922
-
3923
- const path = path$1;
3924
- minimatch.sep = path.sep;
3925
-
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;
3926
3870
  const GLOBSTAR = Symbol('globstar **');
3927
3871
  minimatch.GLOBSTAR = GLOBSTAR;
3928
- const expand = braceExpansion;
3929
-
3930
3872
  const plTypes = {
3931
- '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
3932
- '?': { open: '(?:', close: ')?' },
3933
- '+': { open: '(?:', close: ')+' },
3934
- '*': { open: '(?:', close: ')*' },
3935
- '@': { open: '(?:', close: ')' }
3873
+ '!': { open: '(?:(?!(?:', close: '))[^/]*?)' },
3874
+ '?': { open: '(?:', close: ')?' },
3875
+ '+': { open: '(?:', close: ')+' },
3876
+ '*': { open: '(?:', close: ')*' },
3877
+ '@': { open: '(?:', close: ')' },
3936
3878
  };
3937
-
3938
3879
  // any single thing other than /
3939
3880
  // don't need to escape / when using new RegExp()
3940
3881
  const qmark = '[^/]';
3941
-
3942
3882
  // * => any number of characters
3943
3883
  const star = qmark + '*?';
3944
-
3945
3884
  // ** when dots are allowed. Anything goes, except .. and .
3946
3885
  // not (^ or / followed by one or two dots followed by $ or /),
3947
3886
  // followed by anything, any number of times.
3948
- const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?';
3949
-
3887
+ const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
3950
3888
  // not a ^ or / followed by a dot,
3951
3889
  // followed by anything, any number of times.
3952
- const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?';
3953
-
3890
+ const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
3954
3891
  // "abc" -> { a:true, b:true, c:true }
3955
- const charSet = s => s.split('').reduce((set, c) => {
3956
- set[c] = true;
3957
- return set
3892
+ const charSet = (s) => s.split('').reduce((set, c) => {
3893
+ set[c] = true;
3894
+ return set;
3958
3895
  }, {});
3959
-
3960
3896
  // characters that need to be escaped in RegExp.
3961
3897
  const reSpecials = charSet('().*{}+?[]^$\\!');
3962
-
3963
3898
  // characters that indicate we have to add the pattern start
3964
3899
  const addPatternStartSet = charSet('[.(');
3965
-
3966
- // normalizes slashes.
3967
- const slashSplit = /\/+/;
3968
-
3969
- minimatch.filter = (pattern, options = {}) =>
3970
- (p, i, list) => minimatch(p, pattern, options);
3971
-
3972
- const ext = (a, b = {}) => {
3973
- const t = {};
3974
- Object.keys(a).forEach(k => t[k] = a[k]);
3975
- Object.keys(b).forEach(k => t[k] = b[k]);
3976
- return t
3977
- };
3978
-
3979
- minimatch.defaults = def => {
3980
- if (!def || typeof def !== 'object' || !Object.keys(def).length) {
3981
- return minimatch
3982
- }
3983
-
3984
- const orig = minimatch;
3985
-
3986
- const m = (p, pattern, options) => orig(p, pattern, ext(def, options));
3987
- m.Minimatch = class Minimatch extends orig.Minimatch {
3988
- constructor (pattern, options) {
3989
- super(pattern, ext(def, options));
3990
- }
3991
- };
3992
- m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch;
3993
- m.filter = (pattern, options) => orig.filter(pattern, ext(def, options));
3994
- m.defaults = options => orig.defaults(ext(def, options));
3995
- m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options));
3996
- m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options));
3997
- m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options));
3998
-
3999
- 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
+ });
4000
3926
  };
4001
-
4002
-
4003
-
4004
-
4005
-
3927
+ minimatch.defaults = defaults;
4006
3928
  // Brace expansion:
4007
3929
  // a{b,c}d -> abd acd
4008
3930
  // a{b,}c -> abc ac
@@ -4013,32 +3935,26 @@
4013
3935
  // Invalid sets are not expanded.
4014
3936
  // a{2..}b -> a{2..}b
4015
3937
  // a{b}c -> a{b}c
4016
- minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options);
4017
-
4018
3938
  const braceExpand = (pattern, options = {}) => {
4019
- assertValidPattern(pattern);
4020
-
4021
- // Thanks to Yeting Li <https://github.com/yetingli> for
4022
- // improving this regexp to avoid a ReDOS vulnerability.
4023
- if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
4024
- // shortcut. no need to expand.
4025
- return [pattern]
4026
- }
4027
-
4028
- 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);
4029
3947
  };
4030
-
3948
+ minimatch.braceExpand = braceExpand;
4031
3949
  const MAX_PATTERN_LENGTH = 1024 * 64;
4032
- const assertValidPattern = pattern => {
4033
- if (typeof pattern !== 'string') {
4034
- throw new TypeError('invalid pattern')
4035
- }
4036
-
4037
- if (pattern.length > MAX_PATTERN_LENGTH) {
4038
- throw new TypeError('pattern is too long')
4039
- }
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
+ }
4040
3957
  };
4041
-
4042
3958
  // parse a component of the expanded set.
4043
3959
  // At this point, no pattern may contain "/" in it
4044
3960
  // so we're going to return a 2d array, where each entry is the full
@@ -4051,771 +3967,961 @@
4051
3967
  // of * is equivalent to a single *. Globstar behavior is enabled by
4052
3968
  // default, and can be disabled by setting options.noglobstar.
4053
3969
  const SUBPARSE = Symbol('subparse');
4054
-
4055
- minimatch.makeRe = (pattern, options) =>
4056
- new Minimatch(pattern, options || {}).makeRe();
4057
-
4058
- minimatch.match = (list, pattern, options = {}) => {
4059
- const mm = new Minimatch(pattern, options);
4060
- list = list.filter(f => mm.match(f));
4061
- if (mm.options.nonull && !list.length) {
4062
- list.push(pattern);
4063
- }
4064
- 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;
4065
3979
  };
4066
-
3980
+ minimatch.match = match;
4067
3981
  // replace stuff like \* with *
4068
- const globUnescape = s => s.replace(/\\(.)/g, '$1');
4069
- const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
4070
-
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, '\\$&');
4071
3986
  class Minimatch {
4072
- constructor (pattern, options) {
4073
- assertValidPattern(pattern);
4074
-
4075
- if (!options) options = {};
4076
-
4077
- this.options = options;
4078
- this.set = [];
4079
- this.pattern = pattern;
4080
- this.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
4081
- options.allowWindowsEscape === false;
4082
- if (this.windowsPathsNoEscape) {
4083
- this.pattern = this.pattern.replace(/\\/g, '/');
4084
- }
4085
- this.regexp = null;
4086
- this.negate = false;
4087
- this.comment = false;
4088
- this.empty = false;
4089
- this.partial = !!options.partial;
4090
-
4091
- // make the set of regexps etc.
4092
- this.make();
4093
- }
4094
-
4095
- debug () {}
4096
-
4097
- make () {
4098
- const pattern = this.pattern;
4099
- const options = this.options;
4100
-
4101
- // empty patterns and comments match nothing.
4102
- if (!options.nocomment && pattern.charAt(0) === '#') {
4103
- this.comment = true;
4104
- return
4105
- }
4106
- if (!pattern) {
4107
- this.empty = true;
4108
- return
4109
- }
4110
-
4111
- // step 1: figure out negation, etc.
4112
- this.parseNegate();
4113
-
4114
- // step 2: expand braces
4115
- let set = this.globSet = this.braceExpand();
4116
-
4117
- if (options.debug) this.debug = (...args) => console.error(...args);
4118
-
4119
- this.debug(this.pattern, set);
4120
-
4121
- // step 3: now we have a set, so turn each one into a series of path-portion
4122
- // matching patterns.
4123
- // These will be regexps, except in the case of "**", which is
4124
- // set to the GLOBSTAR object for globstar behavior,
4125
- // and will not contain any / characters
4126
- set = this.globParts = set.map(s => s.split(slashSplit));
4127
-
4128
- this.debug(this.pattern, set);
4129
-
4130
- // glob --> regexps
4131
- set = set.map((s, si, set) => s.map(this.parse, this));
4132
-
4133
- this.debug(this.pattern, set);
4134
-
4135
- // filter out everything that didn't compile properly.
4136
- set = set.filter(s => s.indexOf(false) === -1);
4137
-
4138
- this.debug(this.pattern, set);
4139
-
4140
- this.set = set;
4141
- }
4142
-
4143
- parseNegate () {
4144
- if (this.options.nonegate) return
4145
-
4146
- const pattern = this.pattern;
4147
- let negate = false;
4148
- let negateOffset = 0;
4149
-
4150
- for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
4151
- negate = !negate;
4152
- negateOffset++;
4153
- }
4154
-
4155
- if (negateOffset) this.pattern = pattern.substr(negateOffset);
4156
- this.negate = negate;
4157
- }
4158
-
4159
- // set partial to true to test if, for example,
4160
- // "/a/b" matches the start of "/*/b/*/d"
4161
- // Partial means, if you run out of file before you run
4162
- // out of pattern, then that's fine, as long as all
4163
- // the parts match.
4164
- matchOne (file, pattern, partial) {
4165
- var options = this.options;
4166
-
4167
- this.debug('matchOne',
4168
- { 'this': this, file: file, pattern: pattern });
4169
-
4170
- this.debug('matchOne', file.length, pattern.length);
4171
-
4172
- for (var fi = 0,
4173
- pi = 0,
4174
- fl = file.length,
4175
- pl = pattern.length
4176
- ; (fi < fl) && (pi < pl)
4177
- ; fi++, pi++) {
4178
- this.debug('matchOne loop');
4179
- var p = pattern[pi];
4180
- var f = file[fi];
4181
-
4182
- this.debug(pattern, p, f);
4183
-
4184
- // should be impossible.
4185
- // some invalid regexp stuff in the set.
4186
- /* istanbul ignore if */
4187
- if (p === false) return false
4188
-
4189
- if (p === GLOBSTAR) {
4190
- this.debug('GLOBSTAR', [pattern, p, f]);
4191
-
4192
- // "**"
4193
- // a/**/b/**/c would match the following:
4194
- // a/b/x/y/z/c
4195
- // a/x/y/z/b/c
4196
- // a/b/x/b/x/c
4197
- // a/b/c
4198
- // To do this, take the rest of the pattern after
4199
- // the **, and see if it would match the file remainder.
4200
- // If so, return success.
4201
- // If not, the ** "swallows" a segment, and try again.
4202
- // This is recursively awful.
4203
- //
4204
- // a/**/b/**/c matching a/b/x/y/z/c
4205
- // - a matches a
4206
- // - doublestar
4207
- // - matchOne(b/x/y/z/c, b/**/c)
4208
- // - b matches b
4209
- // - doublestar
4210
- // - matchOne(x/y/z/c, c) -> no
4211
- // - matchOne(y/z/c, c) -> no
4212
- // - matchOne(z/c, c) -> no
4213
- // - matchOne(c, c) yes, hit
4214
- var fr = fi;
4215
- var pr = pi + 1;
4216
- if (pr === pl) {
4217
- this.debug('** at the end');
4218
- // a ** at the end will just swallow the rest.
4219
- // We have found a match.
4220
- // however, it will not swallow /.x, unless
4221
- // options.dot is set.
4222
- // . and .. are *never* matched by **, for explosively
4223
- // exponential reasons.
4224
- for (; fi < fl; fi++) {
4225
- if (file[fi] === '.' || file[fi] === '..' ||
4226
- (!options.dot && file[fi].charAt(0) === '.')) return false
4227
- }
4228
- return true
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, '/');
4229
4010
  }
4230
-
4231
- // ok, let's see if we can swallow whatever we can.
4232
- while (fr < fl) {
4233
- var swallowee = file[fr];
4234
-
4235
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
4236
-
4237
- // XXX remove this slice. Just pass the start index.
4238
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
4239
- this.debug('globstar found match!', fr, fl, swallowee);
4240
- // found a match.
4241
- return true
4242
- } else {
4243
- // can't swallow "." or ".." ever.
4244
- // can only swallow ".foo" when explicitly asked.
4245
- if (swallowee === '.' || swallowee === '..' ||
4246
- (!options.dot && swallowee.charAt(0) === '.')) {
4247
- this.debug('dot detected!', file, fr, pattern, pr);
4248
- break
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;
4034
+ }
4035
+ if (!pattern) {
4036
+ this.empty = true;
4037
+ return;
4038
+ }
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);
4045
+ }
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;
4066
+ }
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);
4249
4082
  }
4250
-
4251
- // ** swallows a segment, and continue.
4252
- this.debug('globstar swallow a segment, and continue');
4253
- fr++;
4254
- }
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
+ });
4255
4100
  }
4256
-
4257
- // no match was found.
4258
- // However, in partial mode, we can't say this is necessarily over.
4259
- // If there's more *pattern* left, then
4260
- /* istanbul ignore if */
4261
- if (partial) {
4262
- // ran out of file
4263
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
4264
- if (fr === fl) return true
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
+ }
4265
4119
  }
4266
- return false
4267
- }
4268
-
4269
- // something other than **
4270
- // non-magic patterns just have to match exactly
4271
- // patterns with magic have been turned into regexps.
4272
- var hit;
4273
- if (typeof p === 'string') {
4274
- hit = f === p;
4275
- this.debug('string match', p, f, hit);
4276
- } else {
4277
- hit = f.match(p);
4278
- this.debug('pattern match', p, f, hit);
4279
- }
4280
-
4281
- if (!hit) return false
4282
- }
4283
-
4284
- // Note: ending in / means that we'll get a final ""
4285
- // at the end of the pattern. This can only match a
4286
- // corresponding "" at the end of the file.
4287
- // If the file ends in /, then it can only match a
4288
- // a pattern that ends in /, unless the pattern just
4289
- // doesn't have any more for it. But, a/b/ should *not*
4290
- // match "a/b/*", even though "" matches against the
4291
- // [^/]*? pattern, except in partial mode, where it might
4292
- // simply not be reached yet.
4293
- // However, a/b/ should still satisfy a/*
4294
-
4295
- // now either we fell off the end of the pattern, or we're done.
4296
- if (fi === fl && pi === pl) {
4297
- // ran out of pattern and filename at the same time.
4298
- // an exact hit!
4299
- return true
4300
- } else if (fi === fl) {
4301
- // ran out of file, but still had pattern left.
4302
- // this is ok if we're doing the match as part of
4303
- // a glob fs traversal.
4304
- return partial
4305
- } else /* istanbul ignore else */ if (pi === pl) {
4306
- // ran out of pattern, still have file left.
4307
- // this is only acceptable if we're on the very last
4308
- // empty segment of a file with a trailing slash.
4309
- // a/* should match a/b/
4310
- return (fi === fl - 1) && (file[fi] === '')
4311
- }
4312
-
4313
- // should be unreachable.
4314
- /* istanbul ignore next */
4315
- throw new Error('wtf?')
4316
- }
4317
-
4318
- braceExpand () {
4319
- return braceExpand(this.pattern, this.options)
4320
- }
4321
-
4322
- parse (pattern, isSub) {
4323
- assertValidPattern(pattern);
4324
-
4325
- const options = this.options;
4326
-
4327
- // shortcuts
4328
- if (pattern === '**') {
4329
- if (!options.noglobstar)
4330
- return GLOBSTAR
4331
- else
4332
- pattern = '*';
4333
- }
4334
- if (pattern === '') return ''
4335
-
4336
- let re = '';
4337
- let hasMagic = !!options.nocase;
4338
- let escaping = false;
4339
- // ? => one single character
4340
- const patternListStack = [];
4341
- const negativeLists = [];
4342
- let stateChar;
4343
- let inClass = false;
4344
- let reClassStart = -1;
4345
- let classStart = -1;
4346
- let cs;
4347
- let pl;
4348
- let sp;
4349
- // . and .. never match anything that doesn't start with .,
4350
- // even when options.dot is set.
4351
- const patternStart = pattern.charAt(0) === '.' ? '' // anything
4352
- // not (start or / followed by . or .. followed by / or end)
4353
- : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
4354
- : '(?!\\.)';
4355
-
4356
- const clearStateChar = () => {
4357
- if (stateChar) {
4358
- // we had some state-tracking character
4359
- // that wasn't consumed by this pass.
4360
- switch (stateChar) {
4361
- case '*':
4362
- re += star;
4363
- hasMagic = true;
4364
- break
4365
- case '?':
4366
- re += qmark;
4367
- hasMagic = true;
4368
- break
4369
- default:
4370
- re += '\\' + stateChar;
4371
- break
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++;
4372
4131
  }
4373
- this.debug('clearStateChar %j %j', stateChar, re);
4374
- stateChar = false;
4375
- }
4376
- };
4377
-
4378
- for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
4379
- this.debug('%s\t%s %s %j', pattern, i, re, c);
4380
-
4381
- // skip over any that are escaped.
4382
- if (escaping) {
4383
- /* istanbul ignore next - completely not allowed, even escaped. */
4384
- if (c === '/') {
4385
- return false
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
+ }
4386
4177
  }
4387
-
4388
- if (reSpecials[c]) {
4389
- re += '\\';
4178
+ if (pattern.indexOf(GLOBSTAR) !== -1) {
4179
+ return this._matchGlobstar(file, pattern, partial, 0, 0);
4390
4180
  }
4391
- re += c;
4392
- escaping = false;
4393
- continue
4394
- }
4395
-
4396
- switch (c) {
4397
- /* istanbul ignore next */
4398
- case '/': {
4399
- // Should already be path-split by now.
4400
- return false
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
+ }
4401
4191
  }
4402
-
4403
- case '\\':
4404
- clearStateChar();
4405
- escaping = true;
4406
- continue
4407
-
4408
- // the various stateChar values
4409
- // for the "extglob" stuff.
4410
- case '?':
4411
- case '*':
4412
- case '+':
4413
- case '@':
4414
- case '!':
4415
- this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
4416
-
4417
- // all of those are literals inside a class, except that
4418
- // the glob [!a] means [^a] in regexp
4419
- if (inClass) {
4420
- this.debug(' in class');
4421
- if (c === '!' && i === classStart + 1) c = '^';
4422
- re += c;
4423
- continue
4424
- }
4425
-
4426
- // if we already have a stateChar, then it means
4427
- // that there was something like ** or +? in there.
4428
- // Handle the stateChar, then proceed with this one.
4429
- this.debug('call clearStateChar %j', stateChar);
4430
- clearStateChar();
4431
- stateChar = c;
4432
- // if extglob is disabled, then +(asdf|foo) isn't a thing.
4433
- // just clear the statechar *now*, rather than even diving into
4434
- // the patternList stuff.
4435
- if (options.noext) clearStateChar();
4436
- continue
4437
-
4438
- case '(':
4439
- if (inClass) {
4440
- re += '(';
4441
- continue
4442
- }
4443
-
4444
- if (!stateChar) {
4445
- re += '\\(';
4446
- continue
4447
- }
4448
-
4449
- patternListStack.push({
4450
- type: stateChar,
4451
- start: i - 1,
4452
- reStart: re.length,
4453
- open: plTypes[stateChar].open,
4454
- close: plTypes[stateChar].close
4455
- });
4456
- // negation is (?:(?!js)[^/]*)
4457
- re += stateChar === '!' ? '(?:(?!(?:' : '(?:';
4458
- this.debug('plType %j %j', stateChar, re);
4459
- stateChar = false;
4460
- continue
4461
-
4462
- case ')':
4463
- if (inClass || !patternListStack.length) {
4464
- re += '\\)';
4465
- continue
4466
- }
4467
-
4468
- clearStateChar();
4469
- hasMagic = true;
4470
- pl = patternListStack.pop();
4471
- // negation is (?:(?!js)[^/]*)
4472
- // The others are (?:<pattern>)<type>
4473
- re += pl.close;
4474
- if (pl.type === '!') {
4475
- negativeLists.push(pl);
4476
- }
4477
- pl.reEnd = re.length;
4478
- continue
4479
-
4480
- case '|':
4481
- if (inClass || !patternListStack.length) {
4482
- re += '\\|';
4483
- continue
4484
- }
4485
-
4486
- clearStateChar();
4487
- re += '|';
4488
- continue
4489
-
4490
- // these are mostly the same in regexp and glob
4491
- case '[':
4492
- // swallow any state-tracking char before the [
4493
- clearStateChar();
4494
-
4495
- if (inClass) {
4496
- re += '\\' + c;
4497
- continue
4498
- }
4499
-
4500
- inClass = true;
4501
- classStart = i;
4502
- reClassStart = re.length;
4503
- re += c;
4504
- continue
4505
-
4506
- case ']':
4507
- // a right bracket shall lose its special
4508
- // meaning and represent itself in
4509
- // a bracket expression if it occurs
4510
- // first in the list. -- POSIX.2 2.8.3.2
4511
- if (i === classStart + 1 || !inClass) {
4512
- re += '\\' + c;
4513
- continue
4514
- }
4515
-
4516
- // handle the case where we left a class open.
4517
- // "[z-a]" is valid, equivalent to "\[z-a\]"
4518
- // split where the last [ was, make sure we don't have
4519
- // an invalid re. if so, re-walk the contents of the
4520
- // would-be class to re-translate any characters that
4521
- // were passed through as-is
4522
- // TODO: It would probably be faster to determine this
4523
- // without a try/catch and a new RegExp, but it's tricky
4524
- // to do safely. For now, this is safe and works.
4525
- cs = pattern.substring(classStart + 1, i);
4526
- try {
4527
- RegExp('[' + cs + ']');
4528
- } catch (er) {
4529
- // not a valid class!
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);
4530
4654
  sp = this.parse(cs, SUBPARSE);
4531
- re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]';
4655
+ re = re.substring(0, reClassStart) + '\\[' + sp[0];
4532
4656
  hasMagic = hasMagic || sp[1];
4533
- inClass = false;
4534
- continue
4535
- }
4536
-
4537
- // finish up the class.
4538
- hasMagic = true;
4539
- inClass = false;
4540
- re += c;
4541
- continue
4542
-
4543
- default:
4544
- // swallow any state char that wasn't consumed
4545
- clearStateChar();
4546
-
4547
- if (reSpecials[c] && !(c === '^' && inClass)) {
4548
- re += '\\';
4549
- }
4550
-
4551
- re += c;
4552
- break
4553
-
4554
- } // switch
4555
- } // for
4556
-
4557
- // handle the case where we left a class open.
4558
- // "[abc" is valid, equivalent to "\[abc"
4559
- if (inClass) {
4560
- // split where the last [ was, and escape it
4561
- // this is a huge pita. We now have to re-walk
4562
- // the contents of the would-be class to re-translate
4563
- // any characters that were passed through as-is
4564
- cs = pattern.substr(classStart + 1);
4565
- sp = this.parse(cs, SUBPARSE);
4566
- re = re.substr(0, reClassStart) + '\\[' + sp[0];
4567
- hasMagic = hasMagic || sp[1];
4568
- }
4569
-
4570
- // handle the case where we had a +( thing at the *end*
4571
- // of the pattern.
4572
- // each pattern list stack adds 3 chars, and we need to go through
4573
- // and escape any | chars that were passed through as-is for the regexp.
4574
- // Go through and escape them, taking care not to double-escape any
4575
- // | chars that were already escaped.
4576
- for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
4577
- let tail;
4578
- tail = re.slice(pl.reStart + pl.open.length);
4579
- this.debug('setting tail', re, pl);
4580
- // maybe some even number of \, then maybe 1 \, followed by a |
4581
- tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
4582
- /* istanbul ignore else - should already be done */
4583
- if (!$2) {
4584
- // the | isn't already escaped, so escape it.
4585
- $2 = '\\';
4586
4657
  }
4587
-
4588
- // need to escape all those slashes *again*, without escaping the
4589
- // one that we need for escaping the | character. As it works out,
4590
- // escaping an even number of slashes can be done by simply repeating
4591
- // it exactly after itself. That's why this trick works.
4592
- //
4593
- // I am sorry that you have to see this.
4594
- return $1 + $1 + $2 + '|'
4595
- });
4596
-
4597
- this.debug('tail=%j\n %s', tail, tail, pl, re);
4598
- const t = pl.type === '*' ? star
4599
- : pl.type === '?' ? qmark
4600
- : '\\' + pl.type;
4601
-
4602
- hasMagic = true;
4603
- re = re.slice(0, pl.reStart) + t + '\\(' + tail;
4604
- }
4605
-
4606
- // handle trailing things that only matter at the very end.
4607
- clearStateChar();
4608
- if (escaping) {
4609
- // trailing \\
4610
- re += '\\\\';
4611
- }
4612
-
4613
- // only need to apply the nodot start if the re starts with
4614
- // something that could conceivably capture a dot
4615
- const addPatternStart = addPatternStartSet[re.charAt(0)];
4616
-
4617
- // Hack to work around lack of negative lookbehind in JS
4618
- // A pattern like: *.!(x).!(y|z) needs to ensure that a name
4619
- // like 'a.xyz.yz' doesn't match. So, the first negative
4620
- // lookahead, has to look ALL the way ahead, to the end of
4621
- // the pattern.
4622
- for (let n = negativeLists.length - 1; n > -1; n--) {
4623
- const nl = negativeLists[n];
4624
-
4625
- const nlBefore = re.slice(0, nl.reStart);
4626
- const nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
4627
- let nlAfter = re.slice(nl.reEnd);
4628
- const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter;
4629
-
4630
- // Handle nested stuff like *(*.js|!(*.json)), where open parens
4631
- // mean that we should *not* include the ) in the bit that is considered
4632
- // "after" the negated section.
4633
- const openParensBefore = nlBefore.split('(').length - 1;
4634
- let cleanAfter = nlAfter;
4635
- for (let i = 0; i < openParensBefore; i++) {
4636
- cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
4637
- }
4638
- nlAfter = cleanAfter;
4639
-
4640
- const dollar = nlAfter === '' && isSub !== SUBPARSE ? '$' : '';
4641
- re = nlBefore + nlFirst + nlAfter + dollar + nlLast;
4642
- }
4643
-
4644
- // if the re is not "" at this point, then we need to make sure
4645
- // it doesn't match against an empty path part.
4646
- // Otherwise a/* will match a/, which it should not.
4647
- if (re !== '' && hasMagic) {
4648
- re = '(?=.)' + re;
4649
- }
4650
-
4651
- if (addPatternStart) {
4652
- re = patternStart + re;
4653
- }
4654
-
4655
- // parsing just a piece of a larger pattern.
4656
- if (isSub === SUBPARSE) {
4657
- return [re, hasMagic]
4658
- }
4659
-
4660
- // skip the regexp for non-magical patterns
4661
- // unescape anything in it, though, so that it'll be
4662
- // an exact match against a file etc.
4663
- if (!hasMagic) {
4664
- return globUnescape(pattern)
4665
- }
4666
-
4667
- const flags = options.nocase ? 'i' : '';
4668
- try {
4669
- return Object.assign(new RegExp('^' + re + '$', flags), {
4670
- _glob: pattern,
4671
- _src: re,
4672
- })
4673
- } catch (er) /* istanbul ignore next - should be impossible */ {
4674
- // If it was an invalid regular expression, then it can't match
4675
- // anything. This trick looks for a character after the end of
4676
- // the string, which is of course impossible, except in multi-line
4677
- // mode, but it's not a /m regex.
4678
- return new RegExp('$.')
4679
- }
4680
- }
4681
-
4682
- makeRe () {
4683
- if (this.regexp || this.regexp === false) return this.regexp
4684
-
4685
- // at this point, this.set is a 2d array of partial
4686
- // pattern strings, or "**".
4687
- //
4688
- // It's better to use .match(). This function shouldn't
4689
- // be used, really, but it's pretty convenient sometimes,
4690
- // when you just want to work with a regex.
4691
- const set = this.set;
4692
-
4693
- if (!set.length) {
4694
- this.regexp = false;
4695
- return this.regexp
4696
- }
4697
- const options = this.options;
4698
-
4699
- const twoStar = options.noglobstar ? star
4700
- : options.dot ? twoStarDot
4701
- : twoStarNoDot;
4702
- const flags = options.nocase ? 'i' : '';
4703
-
4704
- // coalesce globstars and regexpify non-globstar patterns
4705
- // if it's the only item, then we just do one twoStar
4706
- // if it's the first, and there are more, prepend (\/|twoStar\/)? to next
4707
- // if it's the last, append (\/twoStar|) to previous
4708
- // if it's in the middle, append (\/|\/twoStar\/) to previous
4709
- // then filter out GLOBSTAR symbols
4710
- let re = set.map(pattern => {
4711
- pattern = pattern.map(p =>
4712
- typeof p === 'string' ? regExpEscape(p)
4713
- : p === GLOBSTAR ? GLOBSTAR
4714
- : p._src
4715
- ).reduce((set, p) => {
4716
- if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) {
4717
- set.push(p);
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;
4687
+ hasMagic = true;
4688
+ re = re.slice(0, pl.reStart) + t + '\\(' + tail;
4718
4689
  }
4719
- return set
4720
- }, []);
4721
- pattern.forEach((p, i) => {
4722
- if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
4723
- return
4690
+ // handle trailing things that only matter at the very end.
4691
+ clearStateChar();
4692
+ if (escaping) {
4693
+ // trailing \\
4694
+ re += '\\\\';
4724
4695
  }
4725
- if (i === 0) {
4726
- if (pattern.length > 1) {
4727
- pattern[i+1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i+1];
4728
- } else {
4729
- pattern[i] = twoStar;
4730
- }
4731
- } else if (i === pattern.length - 1) {
4732
- pattern[i-1] += '(?:\\\/|' + twoStar + ')?';
4733
- } else {
4734
- pattern[i-1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i+1];
4735
- pattern[i+1] = GLOBSTAR;
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;
4736
4722
  }
4737
- });
4738
- return pattern.filter(p => p !== GLOBSTAR).join('/')
4739
- }).join('|');
4740
-
4741
- // must match entire pattern
4742
- // ending in a * or ** will make it less strict.
4743
- re = '^(?:' + re + ')$';
4744
-
4745
- // can match anything, as long as it's not this.
4746
- if (this.negate) re = '^(?!' + re + ').*$';
4747
-
4748
- try {
4749
- this.regexp = new RegExp(re, flags);
4750
- } catch (ex) /* istanbul ignore next - should be impossible */ {
4751
- this.regexp = 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;
4728
+ }
4729
+ if (addPatternStart) {
4730
+ re = patternStart() + re;
4731
+ }
4732
+ // parsing just a piece of a larger pattern.
4733
+ if (isSub === SUBPARSE) {
4734
+ return [re, hasMagic];
4735
+ }
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();
4739
+ }
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);
4745
+ }
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 */
4752
4771
  }
4753
- return this.regexp
4754
- }
4755
-
4756
- match (f, partial = this.partial) {
4757
- this.debug('match', f, this.pattern);
4758
- // short-circuit in the case of busted things.
4759
- // comments, etc.
4760
- if (this.comment) return false
4761
- if (this.empty) return f === ''
4762
-
4763
- if (f === '/' && partial) return true
4764
-
4765
- const options = this.options;
4766
-
4767
- // windows: need to use /, not \
4768
- if (path.sep !== '/') {
4769
- f = f.split(path.sep).join('/');
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 */
4840
+ }
4841
+ catch (ex) {
4842
+ // should be impossible
4843
+ this.regexp = false;
4844
+ }
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(/\/+/);
4862
+ }
4770
4863
  }
4771
-
4772
- // treat the test path as a set of pathparts.
4773
- f = f.split(slashSplit);
4774
- this.debug(this.pattern, 'split', f);
4775
-
4776
- // just ONE of the pattern sets in this.set needs to match
4777
- // in order for it to be valid. If negating, then just one
4778
- // match means that we have failed.
4779
- // Either way, return on the first hit.
4780
-
4781
- const set = this.set;
4782
- this.debug(this.pattern, 'set', set);
4783
-
4784
- // Find the basename of the path by looking for the last non-empty segment
4785
- let filename;
4786
- for (let i = f.length - 1; i >= 0; i--) {
4787
- filename = f[i];
4788
- if (filename) break
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;
4789
4918
  }
4790
-
4791
- for (let i = 0; i < set.length; i++) {
4792
- const pattern = set[i];
4793
- let file = f;
4794
- if (options.matchBase && pattern.length === 1) {
4795
- file = [filename];
4796
- }
4797
- const hit = this.matchOne(file, pattern, partial);
4798
- if (hit) {
4799
- if (options.flipNegate) return true
4800
- return !this.negate
4801
- }
4919
+ static defaults(def) {
4920
+ return minimatch.defaults(def).Minimatch;
4802
4921
  }
4803
-
4804
- // didn't get any hits. this is success if it's a negative
4805
- // pattern, failure otherwise.
4806
- if (options.flipNegate) return false
4807
- return this.negate
4808
- }
4809
-
4810
- static defaults (def) {
4811
- return minimatch.defaults(def).Minimatch
4812
- }
4813
4922
  }
4814
-
4815
4923
  minimatch.Minimatch = Minimatch;
4816
4924
 
4817
- var minimatch$1 = minimatch_1;
4818
-
4819
4925
  const EXPORT_PATTERN = {
4820
4926
  type: ramda.includes(ramda.__, [TYPES.EXPORT_DEFAULT_DECLARATION, TYPES.EXPORT_NAMED_DECLARATION])
4821
4927
  };
@@ -4846,9 +4952,9 @@
4846
4952
  const fullFilePath = context.getFilename();
4847
4953
  const basePath = context.options[0].basePath;
4848
4954
  return configs.find(config => {
4849
- const isIncluded = asArray(config.includes).some(pathPattern => minimatch$1(fullFilePath, basePath + pathPattern));
4955
+ const isIncluded = asArray(config.includes).some(pathPattern => minimatch(fullFilePath, basePath + pathPattern));
4850
4956
  if (config.includes && !isIncluded) return false;
4851
- const isExcluded = asArray(config.excludes).some(pathPattern => minimatch$1(fullFilePath, basePath + pathPattern));
4957
+ const isExcluded = asArray(config.excludes).some(pathPattern => minimatch(fullFilePath, basePath + pathPattern));
4852
4958
  return !(config.excludes && isExcluded);
4853
4959
  });
4854
4960
  };
@@ -5590,7 +5696,7 @@
5590
5696
  translationFiles = neetoCist.modifyBy({
5591
5697
  lng
5592
5698
  }, ramda.assoc("content", {
5593
- ...parseJsonData(path$2.join(translationsDirPath, changedFileName)),
5699
+ ...parseJsonData(path$1.join(translationsDirPath, changedFileName)),
5594
5700
  ...nanosContent[lng]
5595
5701
  }), translationFiles);
5596
5702
  });
@@ -5673,11 +5779,11 @@
5673
5779
  if (neetoCist.isNot(previousOptions, context.options[0])) {
5674
5780
  const nanosTranslationOption = context.options[0].nanosTranslationDir;
5675
5781
  translationFiles = context.options[0].languages.map(lng => {
5676
- nanosContent[lng] = nanosTranslationOption ? nanosTranslationOption.map(filePath => path$2.join(filePath, `${lng}.json`)).reduce((mergedObj, filePath) => ({
5782
+ nanosContent[lng] = nanosTranslationOption ? nanosTranslationOption.map(filePath => path$1.join(filePath, `${lng}.json`)).reduce((mergedObj, filePath) => ({
5677
5783
  ...mergedObj,
5678
5784
  ...parseJsonData(filePath)
5679
5785
  }), {}) : {};
5680
- const translationsFilePath = path$2.join(context.options[0].translationsDir, `${lng}.json`);
5786
+ const translationsFilePath = path$1.join(context.options[0].translationsDir, `${lng}.json`);
5681
5787
  const translationsContent = parseJsonData(translationsFilePath);
5682
5788
  const combinedContent = ramda.mergeDeepLeft(translationsContent, nanosContent[lng]);
5683
5789
  return {
@@ -7100,7 +7206,7 @@
7100
7206
 
7101
7207
  // Do not replace this with `isInsideApisDirectory` since this rule should include axios.js
7102
7208
  // `isInsideApisDirectory` returns false for apis/axios.js
7103
- const apisFolder = path$2.resolve(aliases?.apis || APIS_DIRECTORY);
7209
+ const apisFolder = path$1.resolve(aliases?.apis || APIS_DIRECTORY);
7104
7210
  if (context.getFilename().startsWith(apisFolder)) return;
7105
7211
  if (!isPackageImported(context, node, "axios")) return;
7106
7212
  context.report(node, NO_AXIOS_IMPORT_OUTSIDE_APIS_MESSAGE);
@@ -7293,7 +7399,6 @@
7293
7399
  };
7294
7400
 
7295
7401
  ({
7296
- type: TYPES.VARIABLE_DECLARATION,
7297
7402
  declarations: [{
7298
7403
  type: TYPES.VARIABLE_DECLARATOR,
7299
7404
  init: {
@@ -7306,11 +7411,8 @@
7306
7411
  }]
7307
7412
  });
7308
7413
  ({
7309
- type: TYPES.EXPRESSION_STATEMENT,
7310
7414
  expression: {
7311
- type: TYPES.CALL_EXPRESSION,
7312
7415
  callee: {
7313
- type: TYPES.IDENTIFIER,
7314
7416
  name: ramda.test(/use[a-zA-z0-9].+/)
7315
7417
  }
7316
7418
  }
@@ -9550,7 +9652,7 @@
9550
9652
  const WHITELISTED_FOLDER_NAMES = ["constants", "utils"];
9551
9653
  const WHITELISTED_FILE_NAMES = ["constants", "utils"];
9552
9654
 
9553
- const getFolderName = fileName => path$2.basename(path$2.dirname(fileName));
9655
+ const getFolderName = fileName => path$1.basename(path$1.dirname(fileName));
9554
9656
  var filesInsideReactQueryFolderShouldEndWithApi = {
9555
9657
  meta: {
9556
9658
  type: "problem",
@@ -9582,7 +9684,7 @@
9582
9684
  };
9583
9685
  const isInsideReactQueryDirectory = context => {
9584
9686
  const filename = context.getFilename();
9585
- const reactQueryDirectory = path$2.resolve(REACT_QUERY_DIRECTORY);
9687
+ const reactQueryDirectory = path$1.resolve(REACT_QUERY_DIRECTORY);
9586
9688
  return filename.startsWith(reactQueryDirectory);
9587
9689
  };
9588
9690
  var useReactQueryForManagingRemoteData = {
@@ -10669,7 +10771,7 @@
10669
10771
 
10670
10772
  const IMAGE_PATH = "images/";
10671
10773
 
10672
- const resolvePath = relativePath => path$2.resolve(__dirname, "../../../../", relativePath);
10774
+ const resolvePath = relativePath => path$1.resolve(__dirname, "../../../../", relativePath);
10673
10775
  const isImportFileSvg = importPath => fs.existsSync(resolvePath(`app/assets/${importPath}.svg`));
10674
10776
  const findSrcAttributeIndex = (attributes, svgs) => neetoCist.findIndexBy({
10675
10777
  name: {
@@ -11556,7 +11658,7 @@
11556
11658
  const aliases = context.options[0];
11557
11659
  if (ramda.isEmpty(aliases) || ramda.isNil(aliases)) return;
11558
11660
  const importPath = node.source.value;
11559
- const importFullPath = importPath.startsWith("../") ? path$2.resolve(context.getFilename(), "../", importPath) : importPath;
11661
+ const importFullPath = importPath.startsWith("../") ? path$1.resolve(context.getFilename(), "../", importPath) : importPath;
11560
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);
11561
11663
  if (matches.length === 0) return;
11562
11664
  const aliasMatch = matches[matches.length - 1];
@@ -11748,7 +11850,6 @@
11748
11850
  // useCurrentUserStore()
11749
11851
  ({
11750
11852
  callee: {
11751
- type: TYPES.IDENTIFIER,
11752
11853
  name: ramda.test(/use[a-zA-z0-9].+Store/)
11753
11854
  }
11754
11855
  });