mirror of
				https://scm.univ-tours.fr/22107988t/rappaurio-sae501_502.git
				synced 2025-10-31 14:55:23 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			215 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // this is just a very light wrapper around 2 arrays with an offset index
 | |
| import { GLOBSTAR } from 'minimatch';
 | |
| const isPatternList = (pl) => pl.length >= 1;
 | |
| const isGlobList = (gl) => gl.length >= 1;
 | |
| /**
 | |
|  * An immutable-ish view on an array of glob parts and their parsed
 | |
|  * results
 | |
|  */
 | |
| export class Pattern {
 | |
|     #patternList;
 | |
|     #globList;
 | |
|     #index;
 | |
|     length;
 | |
|     #platform;
 | |
|     #rest;
 | |
|     #globString;
 | |
|     #isDrive;
 | |
|     #isUNC;
 | |
|     #isAbsolute;
 | |
|     #followGlobstar = true;
 | |
|     constructor(patternList, globList, index, platform) {
 | |
|         if (!isPatternList(patternList)) {
 | |
|             throw new TypeError('empty pattern list');
 | |
|         }
 | |
|         if (!isGlobList(globList)) {
 | |
|             throw new TypeError('empty glob list');
 | |
|         }
 | |
|         if (globList.length !== patternList.length) {
 | |
|             throw new TypeError('mismatched pattern list and glob list lengths');
 | |
|         }
 | |
|         this.length = patternList.length;
 | |
|         if (index < 0 || index >= this.length) {
 | |
|             throw new TypeError('index out of range');
 | |
|         }
 | |
|         this.#patternList = patternList;
 | |
|         this.#globList = globList;
 | |
|         this.#index = index;
 | |
|         this.#platform = platform;
 | |
|         // normalize root entries of absolute patterns on initial creation.
 | |
|         if (this.#index === 0) {
 | |
|             // c: => ['c:/']
 | |
|             // C:/ => ['C:/']
 | |
|             // C:/x => ['C:/', 'x']
 | |
|             // //host/share => ['//host/share/']
 | |
|             // //host/share/ => ['//host/share/']
 | |
|             // //host/share/x => ['//host/share/', 'x']
 | |
|             // /etc => ['/', 'etc']
 | |
|             // / => ['/']
 | |
|             if (this.isUNC()) {
 | |
|                 // '' / '' / 'host' / 'share'
 | |
|                 const [p0, p1, p2, p3, ...prest] = this.#patternList;
 | |
|                 const [g0, g1, g2, g3, ...grest] = this.#globList;
 | |
|                 if (prest[0] === '') {
 | |
|                     // ends in /
 | |
|                     prest.shift();
 | |
|                     grest.shift();
 | |
|                 }
 | |
|                 const p = [p0, p1, p2, p3, ''].join('/');
 | |
|                 const g = [g0, g1, g2, g3, ''].join('/');
 | |
|                 this.#patternList = [p, ...prest];
 | |
|                 this.#globList = [g, ...grest];
 | |
|                 this.length = this.#patternList.length;
 | |
|             }
 | |
|             else if (this.isDrive() || this.isAbsolute()) {
 | |
|                 const [p1, ...prest] = this.#patternList;
 | |
|                 const [g1, ...grest] = this.#globList;
 | |
|                 if (prest[0] === '') {
 | |
|                     // ends in /
 | |
|                     prest.shift();
 | |
|                     grest.shift();
 | |
|                 }
 | |
|                 const p = p1 + '/';
 | |
|                 const g = g1 + '/';
 | |
|                 this.#patternList = [p, ...prest];
 | |
|                 this.#globList = [g, ...grest];
 | |
|                 this.length = this.#patternList.length;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     /**
 | |
|      * The first entry in the parsed list of patterns
 | |
|      */
 | |
|     pattern() {
 | |
|         return this.#patternList[this.#index];
 | |
|     }
 | |
|     /**
 | |
|      * true of if pattern() returns a string
 | |
|      */
 | |
|     isString() {
 | |
|         return typeof this.#patternList[this.#index] === 'string';
 | |
|     }
 | |
|     /**
 | |
|      * true of if pattern() returns GLOBSTAR
 | |
|      */
 | |
|     isGlobstar() {
 | |
|         return this.#patternList[this.#index] === GLOBSTAR;
 | |
|     }
 | |
|     /**
 | |
|      * true if pattern() returns a regexp
 | |
|      */
 | |
|     isRegExp() {
 | |
|         return this.#patternList[this.#index] instanceof RegExp;
 | |
|     }
 | |
|     /**
 | |
|      * The /-joined set of glob parts that make up this pattern
 | |
|      */
 | |
|     globString() {
 | |
|         return (this.#globString =
 | |
|             this.#globString ||
 | |
|                 (this.#index === 0
 | |
|                     ? this.isAbsolute()
 | |
|                         ? this.#globList[0] + this.#globList.slice(1).join('/')
 | |
|                         : this.#globList.join('/')
 | |
|                     : this.#globList.slice(this.#index).join('/')));
 | |
|     }
 | |
|     /**
 | |
|      * true if there are more pattern parts after this one
 | |
|      */
 | |
|     hasMore() {
 | |
|         return this.length > this.#index + 1;
 | |
|     }
 | |
|     /**
 | |
|      * The rest of the pattern after this part, or null if this is the end
 | |
|      */
 | |
|     rest() {
 | |
|         if (this.#rest !== undefined)
 | |
|             return this.#rest;
 | |
|         if (!this.hasMore())
 | |
|             return (this.#rest = null);
 | |
|         this.#rest = new Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform);
 | |
|         this.#rest.#isAbsolute = this.#isAbsolute;
 | |
|         this.#rest.#isUNC = this.#isUNC;
 | |
|         this.#rest.#isDrive = this.#isDrive;
 | |
|         return this.#rest;
 | |
|     }
 | |
|     /**
 | |
|      * true if the pattern represents a //unc/path/ on windows
 | |
|      */
 | |
|     isUNC() {
 | |
|         const pl = this.#patternList;
 | |
|         return this.#isUNC !== undefined
 | |
|             ? this.#isUNC
 | |
|             : (this.#isUNC =
 | |
|                 this.#platform === 'win32' &&
 | |
|                     this.#index === 0 &&
 | |
|                     pl[0] === '' &&
 | |
|                     pl[1] === '' &&
 | |
|                     typeof pl[2] === 'string' &&
 | |
|                     !!pl[2] &&
 | |
|                     typeof pl[3] === 'string' &&
 | |
|                     !!pl[3]);
 | |
|     }
 | |
|     // pattern like C:/...
 | |
|     // split = ['C:', ...]
 | |
|     // XXX: would be nice to handle patterns like `c:*` to test the cwd
 | |
|     // in c: for *, but I don't know of a way to even figure out what that
 | |
|     // cwd is without actually chdir'ing into it?
 | |
|     /**
 | |
|      * True if the pattern starts with a drive letter on Windows
 | |
|      */
 | |
|     isDrive() {
 | |
|         const pl = this.#patternList;
 | |
|         return this.#isDrive !== undefined
 | |
|             ? this.#isDrive
 | |
|             : (this.#isDrive =
 | |
|                 this.#platform === 'win32' &&
 | |
|                     this.#index === 0 &&
 | |
|                     this.length > 1 &&
 | |
|                     typeof pl[0] === 'string' &&
 | |
|                     /^[a-z]:$/i.test(pl[0]));
 | |
|     }
 | |
|     // pattern = '/' or '/...' or '/x/...'
 | |
|     // split = ['', ''] or ['', ...] or ['', 'x', ...]
 | |
|     // Drive and UNC both considered absolute on windows
 | |
|     /**
 | |
|      * True if the pattern is rooted on an absolute path
 | |
|      */
 | |
|     isAbsolute() {
 | |
|         const pl = this.#patternList;
 | |
|         return this.#isAbsolute !== undefined
 | |
|             ? this.#isAbsolute
 | |
|             : (this.#isAbsolute =
 | |
|                 (pl[0] === '' && pl.length > 1) ||
 | |
|                     this.isDrive() ||
 | |
|                     this.isUNC());
 | |
|     }
 | |
|     /**
 | |
|      * consume the root of the pattern, and return it
 | |
|      */
 | |
|     root() {
 | |
|         const p = this.#patternList[0];
 | |
|         return typeof p === 'string' && this.isAbsolute() && this.#index === 0
 | |
|             ? p
 | |
|             : '';
 | |
|     }
 | |
|     /**
 | |
|      * Check to see if the current globstar pattern is allowed to follow
 | |
|      * a symbolic link.
 | |
|      */
 | |
|     checkFollowGlobstar() {
 | |
|         return !(this.#index === 0 ||
 | |
|             !this.isGlobstar() ||
 | |
|             !this.#followGlobstar);
 | |
|     }
 | |
|     /**
 | |
|      * Mark that the current globstar pattern is following a symbolic link
 | |
|      */
 | |
|     markFollowGlobstar() {
 | |
|         if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)
 | |
|             return false;
 | |
|         this.#followGlobstar = false;
 | |
|         return true;
 | |
|     }
 | |
| }
 | |
| //# sourceMappingURL=pattern.js.map
 |