243 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
| import { Minimatch } from 'minimatch';
 | |
| import { fileURLToPath } from 'node:url';
 | |
| import { PathScurry, PathScurryDarwin, PathScurryPosix, PathScurryWin32, } from 'path-scurry';
 | |
| import { Pattern } from './pattern.js';
 | |
| import { GlobStream, GlobWalker } from './walker.js';
 | |
| // if no process global, just call it linux.
 | |
| // so we default to case-sensitive, / separators
 | |
| const defaultPlatform = (typeof process === 'object' &&
 | |
|     process &&
 | |
|     typeof process.platform === 'string') ?
 | |
|     process.platform
 | |
|     : 'linux';
 | |
| /**
 | |
|  * An object that can perform glob pattern traversals.
 | |
|  */
 | |
| export class Glob {
 | |
|     absolute;
 | |
|     cwd;
 | |
|     root;
 | |
|     dot;
 | |
|     dotRelative;
 | |
|     follow;
 | |
|     ignore;
 | |
|     magicalBraces;
 | |
|     mark;
 | |
|     matchBase;
 | |
|     maxDepth;
 | |
|     nobrace;
 | |
|     nocase;
 | |
|     nodir;
 | |
|     noext;
 | |
|     noglobstar;
 | |
|     pattern;
 | |
|     platform;
 | |
|     realpath;
 | |
|     scurry;
 | |
|     stat;
 | |
|     signal;
 | |
|     windowsPathsNoEscape;
 | |
|     withFileTypes;
 | |
|     includeChildMatches;
 | |
|     /**
 | |
|      * The options provided to the constructor.
 | |
|      */
 | |
|     opts;
 | |
|     /**
 | |
|      * An array of parsed immutable {@link Pattern} objects.
 | |
|      */
 | |
|     patterns;
 | |
|     /**
 | |
|      * All options are stored as properties on the `Glob` object.
 | |
|      *
 | |
|      * See {@link GlobOptions} for full options descriptions.
 | |
|      *
 | |
|      * Note that a previous `Glob` object can be passed as the
 | |
|      * `GlobOptions` to another `Glob` instantiation to re-use settings
 | |
|      * and caches with a new pattern.
 | |
|      *
 | |
|      * Traversal functions can be called multiple times to run the walk
 | |
|      * again.
 | |
|      */
 | |
|     constructor(pattern, opts) {
 | |
|         /* c8 ignore start */
 | |
|         if (!opts)
 | |
|             throw new TypeError('glob options required');
 | |
|         /* c8 ignore stop */
 | |
|         this.withFileTypes = !!opts.withFileTypes;
 | |
|         this.signal = opts.signal;
 | |
|         this.follow = !!opts.follow;
 | |
|         this.dot = !!opts.dot;
 | |
|         this.dotRelative = !!opts.dotRelative;
 | |
|         this.nodir = !!opts.nodir;
 | |
|         this.mark = !!opts.mark;
 | |
|         if (!opts.cwd) {
 | |
|             this.cwd = '';
 | |
|         }
 | |
|         else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
 | |
|             opts.cwd = fileURLToPath(opts.cwd);
 | |
|         }
 | |
|         this.cwd = opts.cwd || '';
 | |
|         this.root = opts.root;
 | |
|         this.magicalBraces = !!opts.magicalBraces;
 | |
|         this.nobrace = !!opts.nobrace;
 | |
|         this.noext = !!opts.noext;
 | |
|         this.realpath = !!opts.realpath;
 | |
|         this.absolute = opts.absolute;
 | |
|         this.includeChildMatches = opts.includeChildMatches !== false;
 | |
|         this.noglobstar = !!opts.noglobstar;
 | |
|         this.matchBase = !!opts.matchBase;
 | |
|         this.maxDepth =
 | |
|             typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
 | |
|         this.stat = !!opts.stat;
 | |
|         this.ignore = opts.ignore;
 | |
|         if (this.withFileTypes && this.absolute !== undefined) {
 | |
|             throw new Error('cannot set absolute and withFileTypes:true');
 | |
|         }
 | |
|         if (typeof pattern === 'string') {
 | |
|             pattern = [pattern];
 | |
|         }
 | |
|         this.windowsPathsNoEscape =
 | |
|             !!opts.windowsPathsNoEscape ||
 | |
|                 opts.allowWindowsEscape ===
 | |
|                     false;
 | |
|         if (this.windowsPathsNoEscape) {
 | |
|             pattern = pattern.map(p => p.replace(/\\/g, '/'));
 | |
|         }
 | |
|         if (this.matchBase) {
 | |
|             if (opts.noglobstar) {
 | |
|                 throw new TypeError('base matching requires globstar');
 | |
|             }
 | |
|             pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
 | |
|         }
 | |
|         this.pattern = pattern;
 | |
|         this.platform = opts.platform || defaultPlatform;
 | |
|         this.opts = { ...opts, platform: this.platform };
 | |
|         if (opts.scurry) {
 | |
|             this.scurry = opts.scurry;
 | |
|             if (opts.nocase !== undefined &&
 | |
|                 opts.nocase !== opts.scurry.nocase) {
 | |
|                 throw new Error('nocase option contradicts provided scurry option');
 | |
|             }
 | |
|         }
 | |
|         else {
 | |
|             const Scurry = opts.platform === 'win32' ? PathScurryWin32
 | |
|                 : opts.platform === 'darwin' ? PathScurryDarwin
 | |
|                     : opts.platform ? PathScurryPosix
 | |
|                         : PathScurry;
 | |
|             this.scurry = new Scurry(this.cwd, {
 | |
|                 nocase: opts.nocase,
 | |
|                 fs: opts.fs,
 | |
|             });
 | |
|         }
 | |
|         this.nocase = this.scurry.nocase;
 | |
|         // If you do nocase:true on a case-sensitive file system, then
 | |
|         // we need to use regexps instead of strings for non-magic
 | |
|         // path portions, because statting `aBc` won't return results
 | |
|         // for the file `AbC` for example.
 | |
|         const nocaseMagicOnly = this.platform === 'darwin' || this.platform === 'win32';
 | |
|         const mmo = {
 | |
|             // default nocase based on platform
 | |
|             ...opts,
 | |
|             dot: this.dot,
 | |
|             matchBase: this.matchBase,
 | |
|             nobrace: this.nobrace,
 | |
|             nocase: this.nocase,
 | |
|             nocaseMagicOnly,
 | |
|             nocomment: true,
 | |
|             noext: this.noext,
 | |
|             nonegate: true,
 | |
|             optimizationLevel: 2,
 | |
|             platform: this.platform,
 | |
|             windowsPathsNoEscape: this.windowsPathsNoEscape,
 | |
|             debug: !!this.opts.debug,
 | |
|         };
 | |
|         const mms = this.pattern.map(p => new Minimatch(p, mmo));
 | |
|         const [matchSet, globParts] = mms.reduce((set, m) => {
 | |
|             set[0].push(...m.set);
 | |
|             set[1].push(...m.globParts);
 | |
|             return set;
 | |
|         }, [[], []]);
 | |
|         this.patterns = matchSet.map((set, i) => {
 | |
|             const g = globParts[i];
 | |
|             /* c8 ignore start */
 | |
|             if (!g)
 | |
|                 throw new Error('invalid pattern object');
 | |
|             /* c8 ignore stop */
 | |
|             return new Pattern(set, g, 0, this.platform);
 | |
|         });
 | |
|     }
 | |
|     async walk() {
 | |
|         // Walkers always return array of Path objects, so we just have to
 | |
|         // coerce them into the right shape.  It will have already called
 | |
|         // realpath() if the option was set to do so, so we know that's cached.
 | |
|         // start out knowing the cwd, at least
 | |
|         return [
 | |
|             ...(await new GlobWalker(this.patterns, this.scurry.cwd, {
 | |
|                 ...this.opts,
 | |
|                 maxDepth: this.maxDepth !== Infinity ?
 | |
|                     this.maxDepth + this.scurry.cwd.depth()
 | |
|                     : Infinity,
 | |
|                 platform: this.platform,
 | |
|                 nocase: this.nocase,
 | |
|                 includeChildMatches: this.includeChildMatches,
 | |
|             }).walk()),
 | |
|         ];
 | |
|     }
 | |
|     walkSync() {
 | |
|         return [
 | |
|             ...new GlobWalker(this.patterns, this.scurry.cwd, {
 | |
|                 ...this.opts,
 | |
|                 maxDepth: this.maxDepth !== Infinity ?
 | |
|                     this.maxDepth + this.scurry.cwd.depth()
 | |
|                     : Infinity,
 | |
|                 platform: this.platform,
 | |
|                 nocase: this.nocase,
 | |
|                 includeChildMatches: this.includeChildMatches,
 | |
|             }).walkSync(),
 | |
|         ];
 | |
|     }
 | |
|     stream() {
 | |
|         return new GlobStream(this.patterns, this.scurry.cwd, {
 | |
|             ...this.opts,
 | |
|             maxDepth: this.maxDepth !== Infinity ?
 | |
|                 this.maxDepth + this.scurry.cwd.depth()
 | |
|                 : Infinity,
 | |
|             platform: this.platform,
 | |
|             nocase: this.nocase,
 | |
|             includeChildMatches: this.includeChildMatches,
 | |
|         }).stream();
 | |
|     }
 | |
|     streamSync() {
 | |
|         return new GlobStream(this.patterns, this.scurry.cwd, {
 | |
|             ...this.opts,
 | |
|             maxDepth: this.maxDepth !== Infinity ?
 | |
|                 this.maxDepth + this.scurry.cwd.depth()
 | |
|                 : Infinity,
 | |
|             platform: this.platform,
 | |
|             nocase: this.nocase,
 | |
|             includeChildMatches: this.includeChildMatches,
 | |
|         }).streamSync();
 | |
|     }
 | |
|     /**
 | |
|      * Default sync iteration function. Returns a Generator that
 | |
|      * iterates over the results.
 | |
|      */
 | |
|     iterateSync() {
 | |
|         return this.streamSync()[Symbol.iterator]();
 | |
|     }
 | |
|     [Symbol.iterator]() {
 | |
|         return this.iterateSync();
 | |
|     }
 | |
|     /**
 | |
|      * Default async iteration function. Returns an AsyncGenerator that
 | |
|      * iterates over the results.
 | |
|      */
 | |
|     iterate() {
 | |
|         return this.stream()[Symbol.asyncIterator]();
 | |
|     }
 | |
|     [Symbol.asyncIterator]() {
 | |
|         return this.iterate();
 | |
|     }
 | |
| }
 | |
| //# sourceMappingURL=glob.js.map
 |