Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
pattern.js219 linesDownload Raw Back to esm
1// this is just a very light wrapper around 2 arrays with an offset index
2import { GLOBSTAR } from 'minimatch';
3const isPatternList = (pl) => pl.length >= 1;
4const isGlobList = (gl) => gl.length >= 1;
5const customInspect = Symbol.for('nodejs.util.inspect.custom');
6/**
7 * An immutable-ish view on an array of glob parts and their parsed
8 * results
9 */
10export class Pattern {
11    #patternList;
12    #globList;
13    #index;
14    length;
15    #platform;
16    #rest;
17    #globString;
18    #isDrive;
19    #isUNC;
20    #isAbsolute;
21    #followGlobstar = true;
22    constructor(patternList, globList, index, platform) {
23        if (!isPatternList(patternList)) {
24            throw new TypeError('empty pattern list');
25        }
26        if (!isGlobList(globList)) {
27            throw new TypeError('empty glob list');
28        }
29        if (globList.length !== patternList.length) {
30            throw new TypeError('mismatched pattern list and glob list lengths');
31        }
32        this.length = patternList.length;
33        if (index < 0 || index >= this.length) {
34            throw new TypeError('index out of range');
35        }
36        this.#patternList = patternList;
37        this.#globList = globList;
38        this.#index = index;
39        this.#platform = platform;
40        // normalize root entries of absolute patterns on initial creation.
41        if (this.#index === 0) {
42            // c: => ['c:/']
43            // C:/ => ['C:/']
44            // C:/x => ['C:/', 'x']
45            // //host/share => ['//host/share/']
46            // //host/share/ => ['//host/share/']
47            // //host/share/x => ['//host/share/', 'x']
48            // /etc => ['/', 'etc']
49            // / => ['/']
50            if (this.isUNC()) {
51                // '' / '' / 'host' / 'share'
52                const [p0, p1, p2, p3, ...prest] = this.#patternList;
53                const [g0, g1, g2, g3, ...grest] = this.#globList;
54                if (prest[0] === '') {
55                    // ends in /
56                    prest.shift();
57                    grest.shift();
58                }
59                const p = [p0, p1, p2, p3, ''].join('/');
60                const g = [g0, g1, g2, g3, ''].join('/');
61                this.#patternList = [p, ...prest];
62                this.#globList = [g, ...grest];
63                this.length = this.#patternList.length;
64            }
65            else if (this.isDrive() || this.isAbsolute()) {
66                const [p1, ...prest] = this.#patternList;
67                const [g1, ...grest] = this.#globList;
68                if (prest[0] === '') {
69                    // ends in /
70                    prest.shift();
71                    grest.shift();
72                }
73                const p = p1 + '/';
74                const g = g1 + '/';
75                this.#patternList = [p, ...prest];
76                this.#globList = [g, ...grest];
77                this.length = this.#patternList.length;
78            }
79        }
80    }
81    [customInspect]() {
82        return 'Pattern <' + this.#globList.slice(this.#index).join('/') + '>';
83    }
84    /**
85     * The first entry in the parsed list of patterns
86     */
87    pattern() {
88        return this.#patternList[this.#index];
89    }
90    /**
91     * true of if pattern() returns a string
92     */
93    isString() {
94        return typeof this.#patternList[this.#index] === 'string';
95    }
96    /**
97     * true of if pattern() returns GLOBSTAR
98     */
99    isGlobstar() {
100        return this.#patternList[this.#index] === GLOBSTAR;
101    }
102    /**
103     * true if pattern() returns a regexp
104     */
105    isRegExp() {
106        return this.#patternList[this.#index] instanceof RegExp;
107    }
108    /**
109     * The /-joined set of glob parts that make up this pattern
110     */
111    globString() {
112        return (this.#globString =
113            this.#globString ||
114                (this.#index === 0 ?
115                    this.isAbsolute() ?
116                        this.#globList[0] + this.#globList.slice(1).join('/')
117                        : this.#globList.join('/')
118                    : this.#globList.slice(this.#index).join('/')));
119    }
120    /**
121     * true if there are more pattern parts after this one
122     */
123    hasMore() {
124        return this.length > this.#index + 1;
125    }
126    /**
127     * The rest of the pattern after this part, or null if this is the end
128     */
129    rest() {
130        if (this.#rest !== undefined)
131            return this.#rest;
132        if (!this.hasMore())
133            return (this.#rest = null);
134        this.#rest = new Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform);
135        this.#rest.#isAbsolute = this.#isAbsolute;
136        this.#rest.#isUNC = this.#isUNC;
137        this.#rest.#isDrive = this.#isDrive;
138        return this.#rest;
139    }
140    /**
141     * true if the pattern represents a //unc/path/ on windows
142     */
143    isUNC() {
144        const pl = this.#patternList;
145        return this.#isUNC !== undefined ?
146            this.#isUNC
147            : (this.#isUNC =
148                this.#platform === 'win32' &&
149                    this.#index === 0 &&
150                    pl[0] === '' &&
151                    pl[1] === '' &&
152                    typeof pl[2] === 'string' &&
153                    !!pl[2] &&
154                    typeof pl[3] === 'string' &&
155                    !!pl[3]);
156    }
157    // pattern like C:/...
158    // split = ['C:', ...]
159    // XXX: would be nice to handle patterns like `c:*` to test the cwd
160    // in c: for *, but I don't know of a way to even figure out what that
161    // cwd is without actually chdir'ing into it?
162    /**
163     * True if the pattern starts with a drive letter on Windows
164     */
165    isDrive() {
166        const pl = this.#patternList;
167        return this.#isDrive !== undefined ?
168            this.#isDrive
169            : (this.#isDrive =
170                this.#platform === 'win32' &&
171                    this.#index === 0 &&
172                    this.length > 1 &&
173                    typeof pl[0] === 'string' &&
174                    /^[a-z]:$/i.test(pl[0]));
175    }
176    // pattern = '/' or '/...' or '/x/...'
177    // split = ['', ''] or ['', ...] or ['', 'x', ...]
178    // Drive and UNC both considered absolute on windows
179    /**
180     * True if the pattern is rooted on an absolute path
181     */
182    isAbsolute() {
183        const pl = this.#patternList;
184        return this.#isAbsolute !== undefined ?
185            this.#isAbsolute
186            : (this.#isAbsolute =
187                (pl[0] === '' && pl.length > 1) ||
188                    this.isDrive() ||
189                    this.isUNC());
190    }
191    /**
192     * consume the root of the pattern, and return it
193     */
194    root() {
195        const p = this.#patternList[0];
196        return (typeof p === 'string' && this.isAbsolute() && this.#index === 0) ?
197            p
198            : '';
199    }
200    /**
201     * Check to see if the current globstar pattern is allowed to follow
202     * a symbolic link.
203     */
204    checkFollowGlobstar() {
205        return !(this.#index === 0 ||
206            !this.isGlobstar() ||
207            !this.#followGlobstar);
208    }
209    /**
210     * Mark that the current globstar pattern is following a symbolic link
211     */
212    markFollowGlobstar() {
213        if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)
214            return false;
215        this.#followGlobstar = false;
216        return true;
217    }
218}
219//# sourceMappingURL=pattern.js.map
codekingpro/portable-devtools · Team Ai