Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
scan.js392 linesDownload Raw Back to lib
1'use strict';
2
3const utils = require('./utils');
4const {
5  CHAR_ASTERISK,             /* * */
6  CHAR_AT,                   /* @ */
7  CHAR_BACKWARD_SLASH,       /* \ */
8  CHAR_COMMA,                /* , */
9  CHAR_DOT,                  /* . */
10  CHAR_EXCLAMATION_MARK,     /* ! */
11  CHAR_FORWARD_SLASH,        /* / */
12  CHAR_LEFT_CURLY_BRACE,     /* { */
13  CHAR_LEFT_PARENTHESES,     /* ( */
14  CHAR_LEFT_SQUARE_BRACKET,  /* [ */
15  CHAR_PLUS,                 /* + */
16  CHAR_QUESTION_MARK,        /* ? */
17  CHAR_RIGHT_CURLY_BRACE,    /* } */
18  CHAR_RIGHT_PARENTHESES,    /* ) */
19  CHAR_RIGHT_SQUARE_BRACKET  /* ] */
20} = require('./constants');
21
22const isPathSeparator = code => {
23  return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
24};
25
26const depth = token => {
27  if (token.isPrefix !== true) {
28    token.depth = token.isGlobstar ? Infinity : 1;
29  }
30};
31
32/**
33 * Quickly scans a glob pattern and returns an object with a handful of
34 * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists),
35 * `glob` (the actual pattern), `negated` (true if the path starts with `!` but not
36 * with `!(`) and `negatedExtglob` (true if the path starts with `!(`).
37 *
38 * ```js
39 * const pm = require('picomatch');
40 * console.log(pm.scan('foo/bar/*.js'));
41 * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' }
42 * ```
43 * @param {String} `str`
44 * @param {Object} `options`
45 * @return {Object} Returns an object with tokens and regex source string.
46 * @api public
47 */
48
49const scan = (input, options) => {
50  const opts = options || {};
51
52  const length = input.length - 1;
53  const scanToEnd = opts.parts === true || opts.scanToEnd === true;
54  const slashes = [];
55  const tokens = [];
56  const parts = [];
57
58  let str = input;
59  let index = -1;
60  let start = 0;
61  let lastIndex = 0;
62  let isBrace = false;
63  let isBracket = false;
64  let isGlob = false;
65  let isExtglob = false;
66  let isGlobstar = false;
67  let braceEscaped = false;
68  let backslashes = false;
69  let negated = false;
70  let negatedExtglob = false;
71  let finished = false;
72  let braces = 0;
73  let prev;
74  let code;
75  let token = { value: '', depth: 0, isGlob: false };
76
77  const eos = () => index >= length;
78  const peek = () => str.charCodeAt(index + 1);
79  const advance = () => {
80    prev = code;
81    return str.charCodeAt(++index);
82  };
83
84  while (index < length) {
85    code = advance();
86    let next;
87
88    if (code === CHAR_BACKWARD_SLASH) {
89      backslashes = token.backslashes = true;
90      code = advance();
91
92      if (code === CHAR_LEFT_CURLY_BRACE) {
93        braceEscaped = true;
94      }
95      continue;
96    }
97
98    if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) {
99      braces++;
100
101      while (eos() !== true && (code = advance())) {
102        if (code === CHAR_BACKWARD_SLASH) {
103          backslashes = token.backslashes = true;
104          advance();
105          continue;
106        }
107
108        if (code === CHAR_LEFT_CURLY_BRACE) {
109          braces++;
110          continue;
111        }
112
113        if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) {
114          isBrace = token.isBrace = true;
115          isGlob = token.isGlob = true;
116          finished = true;
117
118          if (scanToEnd === true) {
119            continue;
120          }
121
122          break;
123        }
124
125        if (braceEscaped !== true && code === CHAR_COMMA) {
126          isBrace = token.isBrace = true;
127          isGlob = token.isGlob = true;
128          finished = true;
129
130          if (scanToEnd === true) {
131            continue;
132          }
133
134          break;
135        }
136
137        if (code === CHAR_RIGHT_CURLY_BRACE) {
138          braces--;
139
140          if (braces === 0) {
141            braceEscaped = false;
142            isBrace = token.isBrace = true;
143            finished = true;
144            break;
145          }
146        }
147      }
148
149      if (scanToEnd === true) {
150        continue;
151      }
152
153      break;
154    }
155
156    if (code === CHAR_FORWARD_SLASH) {
157      slashes.push(index);
158      tokens.push(token);
159      token = { value: '', depth: 0, isGlob: false };
160
161      if (finished === true) continue;
162      if (prev === CHAR_DOT && index === (start + 1)) {
163        start += 2;
164        continue;
165      }
166
167      lastIndex = index + 1;
168      continue;
169    }
170
171    if (opts.noext !== true) {
172      const isExtglobChar = code === CHAR_PLUS
173        || code === CHAR_AT
174        || code === CHAR_ASTERISK
175        || code === CHAR_QUESTION_MARK
176        || code === CHAR_EXCLAMATION_MARK;
177
178      if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) {
179        isGlob = token.isGlob = true;
180        isExtglob = token.isExtglob = true;
181        finished = true;
182        if (code === CHAR_EXCLAMATION_MARK && index === start) {
183          negatedExtglob = true;
184        }
185
186        if (scanToEnd === true) {
187          while (eos() !== true && (code = advance())) {
188            if (code === CHAR_BACKWARD_SLASH) {
189              backslashes = token.backslashes = true;
190              code = advance();
191              continue;
192            }
193
194            if (code === CHAR_RIGHT_PARENTHESES) {
195              isGlob = token.isGlob = true;
196              finished = true;
197              break;
198            }
199          }
200          continue;
201        }
202        break;
203      }
204    }
205
206    if (code === CHAR_ASTERISK) {
207      if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true;
208      isGlob = token.isGlob = true;
209      finished = true;
210
211      if (scanToEnd === true) {
212        continue;
213      }
214      break;
215    }
216
217    if (code === CHAR_QUESTION_MARK) {
218      isGlob = token.isGlob = true;
219      finished = true;
220
221      if (scanToEnd === true) {
222        continue;
223      }
224      break;
225    }
226
227    if (code === CHAR_LEFT_SQUARE_BRACKET) {
228      while (eos() !== true && (next = advance())) {
229        if (next === CHAR_BACKWARD_SLASH) {
230          backslashes = token.backslashes = true;
231          advance();
232          continue;
233        }
234
235        if (next === CHAR_RIGHT_SQUARE_BRACKET) {
236          isBracket = token.isBracket = true;
237          isGlob = token.isGlob = true;
238          finished = true;
239          break;
240        }
241      }
242
243      if (scanToEnd === true) {
244        continue;
245      }
246
247      break;
248    }
249
250    if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) {
251      negated = token.negated = true;
252      start++;
253      continue;
254    }
255
256    if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) {
257      isGlob = token.isGlob = true;
258
259      if (scanToEnd === true) {
260        while (eos() !== true && (code = advance())) {
261          if (code === CHAR_LEFT_PARENTHESES) {
262            backslashes = token.backslashes = true;
263            code = advance();
264            continue;
265          }
266
267          if (code === CHAR_RIGHT_PARENTHESES) {
268            finished = true;
269            break;
270          }
271        }
272        continue;
273      }
274      break;
275    }
276
277    if (isGlob === true) {
278      finished = true;
279
280      if (scanToEnd === true) {
281        continue;
282      }
283
284      break;
285    }
286  }
287
288  if (opts.noext === true) {
289    isExtglob = false;
290    isGlob = false;
291  }
292
293  let base = str;
294  let prefix = '';
295  let glob = '';
296
297  if (start > 0) {
298    prefix = str.slice(0, start);
299    str = str.slice(start);
300    lastIndex -= start;
301  }
302
303  if (base && isGlob === true && lastIndex > 0) {
304    base = str.slice(0, lastIndex);
305    glob = str.slice(lastIndex);
306  } else if (isGlob === true) {
307    base = '';
308    glob = str;
309  } else {
310    base = str;
311  }
312
313  if (base && base !== '' && base !== '/' && base !== str) {
314    if (isPathSeparator(base.charCodeAt(base.length - 1))) {
315      base = base.slice(0, -1);
316    }
317  }
318
319  if (opts.unescape === true) {
320    if (glob) glob = utils.removeBackslashes(glob);
321
322    if (base && backslashes === true) {
323      base = utils.removeBackslashes(base);
324    }
325  }
326
327  const state = {
328    prefix,
329    input,
330    start,
331    base,
332    glob,
333    isBrace,
334    isBracket,
335    isGlob,
336    isExtglob,
337    isGlobstar,
338    negated,
339    negatedExtglob
340  };
341
342  if (opts.tokens === true) {
343    state.maxDepth = 0;
344    if (!isPathSeparator(code)) {
345      tokens.push(token);
346    }
347    state.tokens = tokens;
348  }
349
350  if (opts.parts === true || opts.tokens === true) {
351    let prevIndex;
352
353    for (let idx = 0; idx < slashes.length; idx++) {
354      const n = prevIndex ? prevIndex + 1 : start;
355      const i = slashes[idx];
356      const value = input.slice(n, i);
357      if (opts.tokens) {
358        if (idx === 0 && start !== 0) {
359          tokens[idx].isPrefix = true;
360          tokens[idx].value = prefix;
361        } else {
362          tokens[idx].value = value;
363        }
364        depth(tokens[idx]);
365        state.maxDepth += tokens[idx].depth;
366      }
367      if (idx !== 0 || value !== '') {
368        parts.push(value);
369      }
370      prevIndex = i;
371    }
372
373    if (prevIndex && prevIndex + 1 < input.length) {
374      const value = input.slice(prevIndex + 1);
375      parts.push(value);
376
377      if (opts.tokens) {
378        tokens[tokens.length - 1].value = value;
379        depth(tokens[tokens.length - 1]);
380        state.maxDepth += tokens[tokens.length - 1].depth;
381      }
382    }
383
384    state.slashes = slashes;
385    state.parts = parts;
386  }
387
388  return state;
389};
390
391module.exports = scan;
392 
codekingpro/portable-devtools · Team Ai