256
return regEx;
257
}
259
>
// regexes to check for trivial glob patterns that just check for String#endsWith
260
>
const T1 = /^\*\*\/\*\.[\w\.-]+$/; // **/*.something
261
>
const T2 = /^\*\*\/([\w\.-]+)\/?$/; // **/something
262
>
const T3 = /^{\*\*\/\*?[\w\.-]+\/?(,\*\*\/\*?[\w\.-]+\/?)*}$/; // {**/*.something,**/*.else} or {**/package.json,**/project.json}
263
>
const T3_2 = /^{\*\*\/\*?[\w\.-]+(\/(\*\*)?)?(,\*\*\/\*?[\w\.-]+(\/(\*\*)?)?)*}$/; // Like T3, with optional trailing /**
264
>
const T4 = /^\*\*((\/[\w\.-]+)+)\/?$/; // **/something/else
265
>
const T5 = /^([\w\.-]+(\/[\w\.-]+)*)\/?$/; // something/else
266
>
267
>
export type ParsedPattern = (path: string, basename?: string) => boolean;
268
>
269
>
// The `ParsedExpression` returns a `Promise`
270
>
// iff `hasSibling` returns a `Promise`.
271
>
export type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise<boolean>) => string | null | Promise<string | null> /* the matching pattern */;
272
>
273
>
export interface IGlobOptions {
274
>
275
>
/**
276
>
* Simplify patterns for use as exclusion filters during
277
>
* tree traversal to skip entire subtrees. Cannot be used
278
>
* outside of a tree traversal.
279
>
*/
280
>
trimForExclusions?: boolean;
281
>
282
>
/**
283
>
* Whether glob pattern matching should be case insensitive.
284
>
*/
285
>
ignoreCase?: boolean;
286
>
}
287
>
288
>
interface IGlobOptionsInternal extends IGlobOptions {
289
>
equals: (a: string, b: string) => boolean;
290
>
endsWith: (str: string, candidate: string) => boolean;
291
>
isEqualOrParent: (base: string, candidate: string) => boolean;
292
>
}
293
>
294
>
interface ParsedStringPattern {
295
>
(path: string, basename?: string): string | null | Promise<string | null> /* the matching pattern */;
296
>
basenames?: string[];
297
>
patterns?: string[];
298
>
allBasenames?: string[];
299
>
allPaths?: string[];
300
>
}
301
>
302
>
interface ParsedExpressionPattern {
303
>
(path: string, basename?: string, name?: string, hasSibling?: (name: string) => boolean | Promise<boolean>): string | null | Promise<string | null> /* the matching pattern */;
304
>
requiresSiblings?: boolean;
305
>
allBasenames?: string[];
306
>
allPaths?: string[];
307
>
}
308
>
309
>
const CACHE = new LRUCache<string, ParsedStringPattern>(10000); // bounded to 10000 elements
310
>
311
>
const FALSE = function () {
312
return false;
313
};
315
>
const NULL = function (): string | null {
316
return null;
317
};
319
>
/**
320
>
* Check if a provided parsed pattern or expression
321
>
* is empty - hence it won't ever match anything.
322
>
*
323
>
* See {@link FALSE} and {@link NULL}.
324
>
*/
325
>
export function isEmptyPattern(pattern: ParsedPattern | ParsedExpression): pattern is (typeof FALSE | typeof NULL) {
326
if (pattern === FALSE) {
327
return true;