corrade-nucleus-nucleons – Blame information for rev 24
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
20 | office | 1 | // Based on minimatch.js by isaacs <https://npmjs.org/package/minimatch> |
2 | |||
3 | ;(function (require, exports, module, platform) { |
||
4 | |||
5 | if (module) module.exports = minimatch |
||
6 | else exports.minimatch = minimatch |
||
7 | |||
8 | if (!require) { |
||
9 | require = function (id) { |
||
10 | switch (id) { |
||
11 | case "sigmund": return function sigmund (obj) { |
||
12 | return JSON.stringify(obj) |
||
13 | } |
||
14 | case "path": return { basename: function (f) { |
||
15 | f = f.split(/[\/\\]/) |
||
16 | var e = f.pop() |
||
17 | if (!e) e = f.pop() |
||
18 | return e |
||
19 | }} |
||
20 | case "lru-cache": return function LRUCache () { |
||
21 | // not quite an LRU, but still space-limited. |
||
22 | var cache = {} |
||
23 | var cnt = 0 |
||
24 | this.set = function (k, v) { |
||
25 | cnt ++ |
||
26 | if (cnt >= 100) cache = {} |
||
27 | cache[k] = v |
||
28 | } |
||
29 | this.get = function (k) { return cache[k] } |
||
30 | } |
||
31 | } |
||
32 | } |
||
33 | } |
||
34 | |||
35 | minimatch.Minimatch = Minimatch |
||
36 | |||
37 | var LRU = require("lru-cache") |
||
38 | , cache = minimatch.cache = new LRU({max: 100}) |
||
39 | , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} |
||
40 | , sigmund = require("sigmund") |
||
41 | |||
42 | var path = require("path") |
||
43 | // any single thing other than / |
||
44 | // don't need to escape / when using new RegExp() |
||
45 | , qmark = "[^/]" |
||
46 | |||
47 | // * => any number of characters |
||
48 | , star = qmark + "*?" |
||
49 | |||
50 | // ** when dots are allowed. Anything goes, except .. and . |
||
51 | // not (^ or / followed by one or two dots followed by $ or /), |
||
52 | // followed by anything, any number of times. |
||
53 | , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" |
||
54 | |||
55 | // not a ^ or / followed by a dot, |
||
56 | // followed by anything, any number of times. |
||
57 | , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" |
||
58 | |||
59 | // characters that need to be escaped in RegExp. |
||
60 | , reSpecials = charSet("().*{}+?[]^$\\!") |
||
61 | |||
62 | // "abc" -> { a:true, b:true, c:true } |
||
63 | function charSet (s) { |
||
64 | return s.split("").reduce(function (set, c) { |
||
65 | set[c] = true |
||
66 | return set |
||
67 | }, {}) |
||
68 | } |
||
69 | |||
70 | // normalizes slashes. |
||
71 | var slashSplit = /\/+/ |
||
72 | |||
73 | minimatch.monkeyPatch = monkeyPatch |
||
74 | function monkeyPatch () { |
||
75 | var desc = Object.getOwnPropertyDescriptor(String.prototype, "match") |
||
76 | var orig = desc.value |
||
77 | desc.value = function (p) { |
||
78 | if (p instanceof Minimatch) return p.match(this) |
||
79 | return orig.call(this, p) |
||
80 | } |
||
81 | Object.defineProperty(String.prototype, desc) |
||
82 | } |
||
83 | |||
84 | minimatch.filter = filter |
||
85 | function filter (pattern, options) { |
||
86 | options = options || {} |
||
87 | return function (p, i, list) { |
||
88 | return minimatch(p, pattern, options) |
||
89 | } |
||
90 | } |
||
91 | |||
92 | function ext (a, b) { |
||
93 | a = a || {} |
||
94 | b = b || {} |
||
95 | var t = {} |
||
96 | Object.keys(b).forEach(function (k) { |
||
97 | t[k] = b[k] |
||
98 | }) |
||
99 | Object.keys(a).forEach(function (k) { |
||
100 | t[k] = a[k] |
||
101 | }) |
||
102 | return t |
||
103 | } |
||
104 | |||
105 | minimatch.defaults = function (def) { |
||
106 | if (!def || !Object.keys(def).length) return minimatch |
||
107 | |||
108 | var orig = minimatch |
||
109 | |||
110 | var m = function minimatch (p, pattern, options) { |
||
111 | return orig.minimatch(p, pattern, ext(def, options)) |
||
112 | } |
||
113 | |||
114 | m.Minimatch = function Minimatch (pattern, options) { |
||
115 | return new orig.Minimatch(pattern, ext(def, options)) |
||
116 | } |
||
117 | |||
118 | return m |
||
119 | } |
||
120 | |||
121 | Minimatch.defaults = function (def) { |
||
122 | if (!def || !Object.keys(def).length) return Minimatch |
||
123 | return minimatch.defaults(def).Minimatch |
||
124 | } |
||
125 | |||
126 | |||
127 | function minimatch (p, pattern, options) { |
||
128 | if (typeof pattern !== "string") { |
||
129 | throw new TypeError("glob pattern string required") |
||
130 | } |
||
131 | |||
132 | if (!options) options = {} |
||
133 | |||
134 | // shortcut: comments match nothing. |
||
135 | if (!options.nocomment && pattern.charAt(0) === "#") { |
||
136 | return false |
||
137 | } |
||
138 | |||
139 | // "" only matches "" |
||
140 | if (pattern.trim() === "") return p === "" |
||
141 | |||
142 | return new Minimatch(pattern, options).match(p) |
||
143 | } |
||
144 | |||
145 | function Minimatch (pattern, options) { |
||
146 | if (!(this instanceof Minimatch)) { |
||
147 | return new Minimatch(pattern, options, cache) |
||
148 | } |
||
149 | |||
150 | if (typeof pattern !== "string") { |
||
151 | throw new TypeError("glob pattern string required") |
||
152 | } |
||
153 | |||
154 | if (!options) options = {} |
||
155 | |||
156 | // windows: need to use /, not \ |
||
157 | // On other platforms, \ is a valid (albeit bad) filename char. |
||
158 | if (platform === "win32") { |
||
159 | pattern = pattern.split("\\").join("/") |
||
160 | } |
||
161 | |||
162 | // lru storage. |
||
163 | // these things aren't particularly big, but walking down the string |
||
164 | // and turning it into a regexp can get pretty costly. |
||
165 | var cacheKey = pattern + "\n" + sigmund(options) |
||
166 | var cached = minimatch.cache.get(cacheKey) |
||
167 | if (cached) return cached |
||
168 | minimatch.cache.set(cacheKey, this) |
||
169 | |||
170 | this.options = options |
||
171 | this.set = [] |
||
172 | this.pattern = pattern |
||
173 | this.regexp = null |
||
174 | this.negate = false |
||
175 | this.comment = false |
||
176 | this.empty = false |
||
177 | |||
178 | // make the set of regexps etc. |
||
179 | this.make() |
||
180 | } |
||
181 | |||
182 | Minimatch.prototype.make = make |
||
183 | function make () { |
||
184 | // don't do it more than once. |
||
185 | if (this._made) return |
||
186 | |||
187 | var pattern = this.pattern |
||
188 | var options = this.options |
||
189 | |||
190 | // empty patterns and comments match nothing. |
||
191 | if (!options.nocomment && pattern.charAt(0) === "#") { |
||
192 | this.comment = true |
||
193 | return |
||
194 | } |
||
195 | if (!pattern) { |
||
196 | this.empty = true |
||
197 | return |
||
198 | } |
||
199 | |||
200 | // step 1: figure out negation, etc. |
||
201 | this.parseNegate() |
||
202 | |||
203 | // step 2: expand braces |
||
204 | var set = this.globSet = this.braceExpand() |
||
205 | |||
206 | if (options.debug) console.error(this.pattern, set) |
||
207 | |||
208 | // step 3: now we have a set, so turn each one into a series of path-portion |
||
209 | // matching patterns. |
||
210 | // These will be regexps, except in the case of "**", which is |
||
211 | // set to the GLOBSTAR object for globstar behavior, |
||
212 | // and will not contain any / characters |
||
213 | set = this.globParts = set.map(function (s) { |
||
214 | return s.split(slashSplit) |
||
215 | }) |
||
216 | |||
217 | if (options.debug) console.error(this.pattern, set) |
||
218 | |||
219 | // glob --> regexps |
||
220 | set = set.map(function (s, si, set) { |
||
221 | return s.map(this.parse, this) |
||
222 | }, this) |
||
223 | |||
224 | if (options.debug) console.error(this.pattern, set) |
||
225 | |||
226 | // filter out everything that didn't compile properly. |
||
227 | set = set.filter(function (s) { |
||
228 | return -1 === s.indexOf(false) |
||
229 | }) |
||
230 | |||
231 | if (options.debug) console.error(this.pattern, set) |
||
232 | |||
233 | this.set = set |
||
234 | } |
||
235 | |||
236 | Minimatch.prototype.parseNegate = parseNegate |
||
237 | function parseNegate () { |
||
238 | var pattern = this.pattern |
||
239 | , negate = false |
||
240 | , options = this.options |
||
241 | , negateOffset = 0 |
||
242 | |||
243 | if (options.nonegate) return |
||
244 | |||
245 | for ( var i = 0, l = pattern.length |
||
246 | ; i < l && pattern.charAt(i) === "!" |
||
247 | ; i ++) { |
||
248 | negate = !negate |
||
249 | negateOffset ++ |
||
250 | } |
||
251 | |||
252 | if (negateOffset) this.pattern = pattern.substr(negateOffset) |
||
253 | this.negate = negate |
||
254 | } |
||
255 | |||
256 | // Brace expansion: |
||
257 | // a{b,c}d -> abd acd |
||
258 | // a{b,}c -> abc ac |
||
259 | // a{0..3}d -> a0d a1d a2d a3d |
||
260 | // a{b,c{d,e}f}g -> abg acdfg acefg |
||
261 | // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg |
||
262 | // |
||
263 | // Invalid sets are not expanded. |
||
264 | // a{2..}b -> a{2..}b |
||
265 | // a{b}c -> a{b}c |
||
266 | minimatch.braceExpand = function (pattern, options) { |
||
267 | return new Minimatch(pattern, options).braceExpand() |
||
268 | } |
||
269 | |||
270 | Minimatch.prototype.braceExpand = braceExpand |
||
271 | function braceExpand (pattern, options) { |
||
272 | options = options || this.options |
||
273 | pattern = typeof pattern === "undefined" |
||
274 | ? this.pattern : pattern |
||
275 | |||
276 | if (typeof pattern === "undefined") { |
||
277 | throw new Error("undefined pattern") |
||
278 | } |
||
279 | |||
280 | if (options.nobrace || |
||
281 | !pattern.match(/\{.*\}/)) { |
||
282 | // shortcut. no need to expand. |
||
283 | return [pattern] |
||
284 | } |
||
285 | |||
286 | var escaping = false |
||
287 | |||
288 | // examples and comments refer to this crazy pattern: |
||
289 | // a{b,c{d,e},{f,g}h}x{y,z} |
||
290 | // expected: |
||
291 | // abxy |
||
292 | // abxz |
||
293 | // acdxy |
||
294 | // acdxz |
||
295 | // acexy |
||
296 | // acexz |
||
297 | // afhxy |
||
298 | // afhxz |
||
299 | // aghxy |
||
300 | // aghxz |
||
301 | |||
302 | // everything before the first \{ is just a prefix. |
||
303 | // So, we pluck that off, and work with the rest, |
||
304 | // and then prepend it to everything we find. |
||
305 | if (pattern.charAt(0) !== "{") { |
||
306 | // console.error(pattern) |
||
307 | var prefix = null |
||
308 | for (var i = 0, l = pattern.length; i < l; i ++) { |
||
309 | var c = pattern.charAt(i) |
||
310 | // console.error(i, c) |
||
311 | if (c === "\\") { |
||
312 | escaping = !escaping |
||
313 | } else if (c === "{" && !escaping) { |
||
314 | prefix = pattern.substr(0, i) |
||
315 | break |
||
316 | } |
||
317 | } |
||
318 | |||
319 | // actually no sets, all { were escaped. |
||
320 | if (prefix === null) { |
||
321 | // console.error("no sets") |
||
322 | return [pattern] |
||
323 | } |
||
324 | |||
325 | var tail = braceExpand(pattern.substr(i), options) |
||
326 | return tail.map(function (t) { |
||
327 | return prefix + t |
||
328 | }) |
||
329 | } |
||
330 | |||
331 | // now we have something like: |
||
332 | // {b,c{d,e},{f,g}h}x{y,z} |
||
333 | // walk through the set, expanding each part, until |
||
334 | // the set ends. then, we'll expand the suffix. |
||
335 | // If the set only has a single member, then'll put the {} back |
||
336 | |||
337 | // first, handle numeric sets, since they're easier |
||
338 | var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) |
||
339 | if (numset) { |
||
340 | // console.error("numset", numset[1], numset[2]) |
||
341 | var suf = braceExpand(pattern.substr(numset[0].length), options) |
||
342 | , start = +numset[1] |
||
343 | , end = +numset[2] |
||
344 | , inc = start > end ? -1 : 1 |
||
345 | , set = [] |
||
346 | for (var i = start; i != (end + inc); i += inc) { |
||
347 | // append all the suffixes |
||
348 | for (var ii = 0, ll = suf.length; ii < ll; ii ++) { |
||
349 | set.push(i + suf[ii]) |
||
350 | } |
||
351 | } |
||
352 | return set |
||
353 | } |
||
354 | |||
355 | // ok, walk through the set |
||
356 | // We hope, somewhat optimistically, that there |
||
357 | // will be a } at the end. |
||
358 | // If the closing brace isn't found, then the pattern is |
||
359 | // interpreted as braceExpand("\\" + pattern) so that |
||
360 | // the leading \{ will be interpreted literally. |
||
361 | var i = 1 // skip the \{ |
||
362 | , depth = 1 |
||
363 | , set = [] |
||
364 | , member = "" |
||
365 | , sawEnd = false |
||
366 | , escaping = false |
||
367 | |||
368 | function addMember () { |
||
369 | set.push(member) |
||
370 | member = "" |
||
371 | } |
||
372 | |||
373 | // console.error("Entering for") |
||
374 | FOR: for (i = 1, l = pattern.length; i < l; i ++) { |
||
375 | var c = pattern.charAt(i) |
||
376 | // console.error("", i, c) |
||
377 | |||
378 | if (escaping) { |
||
379 | escaping = false |
||
380 | member += "\\" + c |
||
381 | } else { |
||
382 | switch (c) { |
||
383 | case "\\": |
||
384 | escaping = true |
||
385 | continue |
||
386 | |||
387 | case "{": |
||
388 | depth ++ |
||
389 | member += "{" |
||
390 | continue |
||
391 | |||
392 | case "}": |
||
393 | depth -- |
||
394 | // if this closes the actual set, then we're done |
||
395 | if (depth === 0) { |
||
396 | addMember() |
||
397 | // pluck off the close-brace |
||
398 | i ++ |
||
399 | break FOR |
||
400 | } else { |
||
401 | member += c |
||
402 | continue |
||
403 | } |
||
404 | |||
405 | case ",": |
||
406 | if (depth === 1) { |
||
407 | addMember() |
||
408 | } else { |
||
409 | member += c |
||
410 | } |
||
411 | continue |
||
412 | |||
413 | default: |
||
414 | member += c |
||
415 | continue |
||
416 | } // switch |
||
417 | } // else |
||
418 | } // for |
||
419 | |||
420 | // now we've either finished the set, and the suffix is |
||
421 | // pattern.substr(i), or we have *not* closed the set, |
||
422 | // and need to escape the leading brace |
||
423 | if (depth !== 0) { |
||
424 | // console.error("didn't close", pattern) |
||
425 | return braceExpand("\\" + pattern, options) |
||
426 | } |
||
427 | |||
428 | // x{y,z} -> ["xy", "xz"] |
||
429 | // console.error("set", set) |
||
430 | // console.error("suffix", pattern.substr(i)) |
||
431 | var suf = braceExpand(pattern.substr(i), options) |
||
432 | // ["b", "c{d,e}","{f,g}h"] -> |
||
433 | // [["b"], ["cd", "ce"], ["fh", "gh"]] |
||
434 | var addBraces = set.length === 1 |
||
435 | // console.error("set pre-expanded", set) |
||
436 | set = set.map(function (p) { |
||
437 | return braceExpand(p, options) |
||
438 | }) |
||
439 | // console.error("set expanded", set) |
||
440 | |||
441 | |||
442 | // [["b"], ["cd", "ce"], ["fh", "gh"]] -> |
||
443 | // ["b", "cd", "ce", "fh", "gh"] |
||
444 | set = set.reduce(function (l, r) { |
||
445 | return l.concat(r) |
||
446 | }) |
||
447 | |||
448 | if (addBraces) { |
||
449 | set = set.map(function (s) { |
||
450 | return "{" + s + "}" |
||
451 | }) |
||
452 | } |
||
453 | |||
454 | // now attach the suffixes. |
||
455 | var ret = [] |
||
456 | for (var i = 0, l = set.length; i < l; i ++) { |
||
457 | for (var ii = 0, ll = suf.length; ii < ll; ii ++) { |
||
458 | ret.push(set[i] + suf[ii]) |
||
459 | } |
||
460 | } |
||
461 | return ret |
||
462 | } |
||
463 | |||
464 | // parse a component of the expanded set. |
||
465 | // At this point, no pattern may contain "/" in it |
||
466 | // so we're going to return a 2d array, where each entry is the full |
||
467 | // pattern, split on '/', and then turned into a regular expression. |
||
468 | // A regexp is made at the end which joins each array with an |
||
469 | // escaped /, and another full one which joins each regexp with |. |
||
470 | // |
||
471 | // Following the lead of Bash 4.1, note that "**" only has special meaning |
||
472 | // when it is the *only* thing in a path portion. Otherwise, any series |
||
473 | // of * is equivalent to a single *. Globstar behavior is enabled by |
||
474 | // default, and can be disabled by setting options.noglobstar. |
||
475 | Minimatch.prototype.parse = parse |
||
476 | var SUBPARSE = {} |
||
477 | function parse (pattern, isSub) { |
||
478 | var options = this.options |
||
479 | |||
480 | // shortcuts |
||
481 | if (!options.noglobstar && pattern === "**") return GLOBSTAR |
||
482 | if (pattern === "") return "" |
||
483 | |||
484 | var re = "" |
||
485 | , hasMagic = !!options.nocase |
||
486 | , escaping = false |
||
487 | // ? => one single character |
||
488 | , patternListStack = [] |
||
489 | , plType |
||
490 | , stateChar |
||
491 | , inClass = false |
||
492 | , reClassStart = -1 |
||
493 | , classStart = -1 |
||
494 | // . and .. never match anything that doesn't start with ., |
||
495 | // even when options.dot is set. |
||
496 | , patternStart = pattern.charAt(0) === "." ? "" // anything |
||
497 | // not (start or / followed by . or .. followed by / or end) |
||
498 | : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" |
||
499 | : "(?!\\.)" |
||
500 | |||
501 | function clearStateChar () { |
||
502 | if (stateChar) { |
||
503 | // we had some state-tracking character |
||
504 | // that wasn't consumed by this pass. |
||
505 | switch (stateChar) { |
||
506 | case "*": |
||
507 | re += star |
||
508 | hasMagic = true |
||
509 | break |
||
510 | case "?": |
||
511 | re += qmark |
||
512 | hasMagic = true |
||
513 | break |
||
514 | default: |
||
515 | re += "\\"+stateChar |
||
516 | break |
||
517 | } |
||
518 | stateChar = false |
||
519 | } |
||
520 | } |
||
521 | |||
522 | for ( var i = 0, len = pattern.length, c |
||
523 | ; (i < len) && (c = pattern.charAt(i)) |
||
524 | ; i ++ ) { |
||
525 | |||
526 | if (options.debug) { |
||
527 | console.error("%s\t%s %s %j", pattern, i, re, c) |
||
528 | } |
||
529 | |||
530 | // skip over any that are escaped. |
||
531 | if (escaping && reSpecials[c]) { |
||
532 | re += "\\" + c |
||
533 | escaping = false |
||
534 | continue |
||
535 | } |
||
536 | |||
537 | SWITCH: switch (c) { |
||
538 | case "/": |
||
539 | // completely not allowed, even escaped. |
||
540 | // Should already be path-split by now. |
||
541 | return false |
||
542 | |||
543 | case "\\": |
||
544 | clearStateChar() |
||
545 | escaping = true |
||
546 | continue |
||
547 | |||
548 | // the various stateChar values |
||
549 | // for the "extglob" stuff. |
||
550 | case "?": |
||
551 | case "*": |
||
552 | case "+": |
||
553 | case "@": |
||
554 | case "!": |
||
555 | if (options.debug) { |
||
556 | console.error("%s\t%s %s %j <-- stateChar", pattern, i, re, c) |
||
557 | } |
||
558 | |||
559 | // all of those are literals inside a class, except that |
||
560 | // the glob [!a] means [^a] in regexp |
||
561 | if (inClass) { |
||
562 | if (c === "!" && i === classStart + 1) c = "^" |
||
563 | re += c |
||
564 | continue |
||
565 | } |
||
566 | |||
567 | // if we already have a stateChar, then it means |
||
568 | // that there was something like ** or +? in there. |
||
569 | // Handle the stateChar, then proceed with this one. |
||
570 | clearStateChar() |
||
571 | stateChar = c |
||
572 | // if extglob is disabled, then +(asdf|foo) isn't a thing. |
||
573 | // just clear the statechar *now*, rather than even diving into |
||
574 | // the patternList stuff. |
||
575 | if (options.noext) clearStateChar() |
||
576 | continue |
||
577 | |||
578 | case "(": |
||
579 | if (inClass) { |
||
580 | re += "(" |
||
581 | continue |
||
582 | } |
||
583 | |||
584 | if (!stateChar) { |
||
585 | re += "\\(" |
||
586 | continue |
||
587 | } |
||
588 | |||
589 | plType = stateChar |
||
590 | patternListStack.push({ type: plType |
||
591 | , start: i - 1 |
||
592 | , reStart: re.length }) |
||
593 | // negation is (?:(?!js)[^/]*) |
||
594 | re += stateChar === "!" ? "(?:(?!" : "(?:" |
||
595 | stateChar = false |
||
596 | continue |
||
597 | |||
598 | case ")": |
||
599 | if (inClass || !patternListStack.length) { |
||
600 | re += "\\)" |
||
601 | continue |
||
602 | } |
||
603 | |||
604 | hasMagic = true |
||
605 | re += ")" |
||
606 | plType = patternListStack.pop().type |
||
607 | // negation is (?:(?!js)[^/]*) |
||
608 | // The others are (?:<pattern>)<type> |
||
609 | switch (plType) { |
||
610 | case "!": |
||
611 | re += "[^/]*?)" |
||
612 | break |
||
613 | case "?": |
||
614 | case "+": |
||
615 | case "*": re += plType |
||
616 | case "@": break // the default anyway |
||
617 | } |
||
618 | continue |
||
619 | |||
620 | case "|": |
||
621 | if (inClass || !patternListStack.length || escaping) { |
||
622 | re += "\\|" |
||
623 | escaping = false |
||
624 | continue |
||
625 | } |
||
626 | |||
627 | re += "|" |
||
628 | continue |
||
629 | |||
630 | // these are mostly the same in regexp and glob |
||
631 | case "[": |
||
632 | // swallow any state-tracking char before the [ |
||
633 | clearStateChar() |
||
634 | |||
635 | if (inClass) { |
||
636 | re += "\\" + c |
||
637 | continue |
||
638 | } |
||
639 | |||
640 | inClass = true |
||
641 | classStart = i |
||
642 | reClassStart = re.length |
||
643 | re += c |
||
644 | continue |
||
645 | |||
646 | case "]": |
||
647 | // a right bracket shall lose its special |
||
648 | // meaning and represent itself in |
||
649 | // a bracket expression if it occurs |
||
650 | // first in the list. -- POSIX.2 2.8.3.2 |
||
651 | if (i === classStart + 1 || !inClass) { |
||
652 | re += "\\" + c |
||
653 | escaping = false |
||
654 | continue |
||
655 | } |
||
656 | |||
657 | // finish up the class. |
||
658 | hasMagic = true |
||
659 | inClass = false |
||
660 | re += c |
||
661 | continue |
||
662 | |||
663 | default: |
||
664 | // swallow any state char that wasn't consumed |
||
665 | clearStateChar() |
||
666 | |||
667 | if (escaping) { |
||
668 | // no need |
||
669 | escaping = false |
||
670 | } else if (reSpecials[c] |
||
671 | && !(c === "^" && inClass)) { |
||
672 | re += "\\" |
||
673 | } |
||
674 | |||
675 | re += c |
||
676 | |||
677 | } // switch |
||
678 | } // for |
||
679 | |||
680 | |||
681 | // handle the case where we left a class open. |
||
682 | // "[abc" is valid, equivalent to "\[abc" |
||
683 | if (inClass) { |
||
684 | // split where the last [ was, and escape it |
||
685 | // this is a huge pita. We now have to re-walk |
||
686 | // the contents of the would-be class to re-translate |
||
687 | // any characters that were passed through as-is |
||
688 | var cs = pattern.substr(classStart + 1) |
||
689 | , sp = this.parse(cs, SUBPARSE) |
||
690 | re = re.substr(0, reClassStart) + "\\[" + sp[0] |
||
691 | hasMagic = hasMagic || sp[1] |
||
692 | } |
||
693 | |||
694 | // handle the case where we had a +( thing at the *end* |
||
695 | // of the pattern. |
||
696 | // each pattern list stack adds 3 chars, and we need to go through |
||
697 | // and escape any | chars that were passed through as-is for the regexp. |
||
698 | // Go through and escape them, taking care not to double-escape any |
||
699 | // | chars that were already escaped. |
||
700 | var pl |
||
701 | while (pl = patternListStack.pop()) { |
||
702 | var tail = re.slice(pl.reStart + 3) |
||
703 | // maybe some even number of \, then maybe 1 \, followed by a | |
||
704 | tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { |
||
705 | if (!$2) { |
||
706 | // the | isn't already escaped, so escape it. |
||
707 | $2 = "\\" |
||
708 | } |
||
709 | |||
710 | // need to escape all those slashes *again*, without escaping the |
||
711 | // one that we need for escaping the | character. As it works out, |
||
712 | // escaping an even number of slashes can be done by simply repeating |
||
713 | // it exactly after itself. That's why this trick works. |
||
714 | // |
||
715 | // I am sorry that you have to see this. |
||
716 | return $1 + $1 + $2 + "|" |
||
717 | }) |
||
718 | |||
719 | // console.error("tail=%j\n %s", tail, tail) |
||
720 | var t = pl.type === "*" ? star |
||
721 | : pl.type === "?" ? qmark |
||
722 | : "\\" + pl.type |
||
723 | |||
724 | hasMagic = true |
||
725 | re = re.slice(0, pl.reStart) |
||
726 | + t + "\\(" |
||
727 | + tail |
||
728 | } |
||
729 | |||
730 | // handle trailing things that only matter at the very end. |
||
731 | clearStateChar() |
||
732 | if (escaping) { |
||
733 | // trailing \\ |
||
734 | re += "\\\\" |
||
735 | } |
||
736 | |||
737 | // only need to apply the nodot start if the re starts with |
||
738 | // something that could conceivably capture a dot |
||
739 | var addPatternStart = false |
||
740 | switch (re.charAt(0)) { |
||
741 | case ".": |
||
742 | case "[": |
||
743 | case "(": addPatternStart = true |
||
744 | } |
||
745 | |||
746 | // if the re is not "" at this point, then we need to make sure |
||
747 | // it doesn't match against an empty path part. |
||
748 | // Otherwise a/* will match a/, which it should not. |
||
749 | if (re !== "" && hasMagic) re = "(?=.)" + re |
||
750 | |||
751 | if (addPatternStart) re = patternStart + re |
||
752 | |||
753 | // parsing just a piece of a larger pattern. |
||
754 | if (isSub === SUBPARSE) { |
||
755 | return [ re, hasMagic ] |
||
756 | } |
||
757 | |||
758 | // skip the regexp for non-magical patterns |
||
759 | // unescape anything in it, though, so that it'll be |
||
760 | // an exact match against a file etc. |
||
761 | if (!hasMagic) { |
||
762 | return globUnescape(pattern) |
||
763 | } |
||
764 | |||
765 | var flags = options.nocase ? "i" : "" |
||
766 | , regExp = new RegExp("^" + re + "$", flags) |
||
767 | |||
768 | regExp._glob = pattern |
||
769 | regExp._src = re |
||
770 | |||
771 | return regExp |
||
772 | } |
||
773 | |||
774 | minimatch.makeRe = function (pattern, options) { |
||
775 | return new Minimatch(pattern, options || {}).makeRe() |
||
776 | } |
||
777 | |||
778 | Minimatch.prototype.makeRe = makeRe |
||
779 | function makeRe () { |
||
780 | if (this.regexp || this.regexp === false) return this.regexp |
||
781 | |||
782 | // at this point, this.set is a 2d array of partial |
||
783 | // pattern strings, or "**". |
||
784 | // |
||
785 | // It's better to use .match(). This function shouldn't |
||
786 | // be used, really, but it's pretty convenient sometimes, |
||
787 | // when you just want to work with a regex. |
||
788 | var set = this.set |
||
789 | |||
790 | if (!set.length) return this.regexp = false |
||
791 | var options = this.options |
||
792 | |||
793 | var twoStar = options.noglobstar ? star |
||
794 | : options.dot ? twoStarDot |
||
795 | : twoStarNoDot |
||
796 | , flags = options.nocase ? "i" : "" |
||
797 | |||
798 | var re = set.map(function (pattern) { |
||
799 | return pattern.map(function (p) { |
||
800 | return (p === GLOBSTAR) ? twoStar |
||
801 | : (typeof p === "string") ? regExpEscape(p) |
||
802 | : p._src |
||
803 | }).join("\\\/") |
||
804 | }).join("|") |
||
805 | |||
806 | // must match entire pattern |
||
807 | // ending in a * or ** will make it less strict. |
||
808 | re = "^(?:" + re + ")$" |
||
809 | |||
810 | // can match anything, as long as it's not this. |
||
811 | if (this.negate) re = "^(?!" + re + ").*$" |
||
812 | |||
813 | try { |
||
814 | return this.regexp = new RegExp(re, flags) |
||
815 | } catch (ex) { |
||
816 | return this.regexp = false |
||
817 | } |
||
818 | } |
||
819 | |||
820 | minimatch.match = function (list, pattern, options) { |
||
821 | var mm = new Minimatch(pattern, options) |
||
822 | list = list.filter(function (f) { |
||
823 | return mm.match(f) |
||
824 | }) |
||
825 | if (options.nonull && !list.length) { |
||
826 | list.push(pattern) |
||
827 | } |
||
828 | return list |
||
829 | } |
||
830 | |||
831 | Minimatch.prototype.match = match |
||
832 | function match (f, partial) { |
||
833 | // console.error("match", f, this.pattern) |
||
834 | // short-circuit in the case of busted things. |
||
835 | // comments, etc. |
||
836 | if (this.comment) return false |
||
837 | if (this.empty) return f === "" |
||
838 | |||
839 | if (f === "/" && partial) return true |
||
840 | |||
841 | var options = this.options |
||
842 | |||
843 | // windows: need to use /, not \ |
||
844 | // On other platforms, \ is a valid (albeit bad) filename char. |
||
845 | if (platform === "win32") { |
||
846 | f = f.split("\\").join("/") |
||
847 | } |
||
848 | |||
849 | // treat the test path as a set of pathparts. |
||
850 | f = f.split(slashSplit) |
||
851 | if (options.debug) { |
||
852 | console.error(this.pattern, "split", f) |
||
853 | } |
||
854 | |||
855 | // just ONE of the pattern sets in this.set needs to match |
||
856 | // in order for it to be valid. If negating, then just one |
||
857 | // match means that we have failed. |
||
858 | // Either way, return on the first hit. |
||
859 | |||
860 | var set = this.set |
||
861 | // console.error(this.pattern, "set", set) |
||
862 | |||
863 | for (var i = 0, l = set.length; i < l; i ++) { |
||
864 | var pattern = set[i] |
||
865 | var hit = this.matchOne(f, pattern, partial) |
||
866 | if (hit) { |
||
867 | if (options.flipNegate) return true |
||
868 | return !this.negate |
||
869 | } |
||
870 | } |
||
871 | |||
872 | // didn't get any hits. this is success if it's a negative |
||
873 | // pattern, failure otherwise. |
||
874 | if (options.flipNegate) return false |
||
875 | return this.negate |
||
876 | } |
||
877 | |||
878 | // set partial to true to test if, for example, |
||
879 | // "/a/b" matches the start of "/*/b/*/d" |
||
880 | // Partial means, if you run out of file before you run |
||
881 | // out of pattern, then that's fine, as long as all |
||
882 | // the parts match. |
||
883 | Minimatch.prototype.matchOne = function (file, pattern, partial) { |
||
884 | var options = this.options |
||
885 | |||
886 | if (options.debug) { |
||
887 | console.error("matchOne", |
||
888 | { "this": this |
||
889 | , file: file |
||
890 | , pattern: pattern }) |
||
891 | } |
||
892 | |||
893 | if (options.matchBase && pattern.length === 1) { |
||
894 | file = path.basename(file.join("/")).split("/") |
||
895 | } |
||
896 | |||
897 | if (options.debug) { |
||
898 | console.error("matchOne", file.length, pattern.length) |
||
899 | } |
||
900 | |||
901 | for ( var fi = 0 |
||
902 | , pi = 0 |
||
903 | , fl = file.length |
||
904 | , pl = pattern.length |
||
905 | ; (fi < fl) && (pi < pl) |
||
906 | ; fi ++, pi ++ ) { |
||
907 | |||
908 | if (options.debug) { |
||
909 | console.error("matchOne loop") |
||
910 | } |
||
911 | var p = pattern[pi] |
||
912 | , f = file[fi] |
||
913 | |||
914 | if (options.debug) { |
||
915 | console.error(pattern, p, f) |
||
916 | } |
||
917 | |||
918 | // should be impossible. |
||
919 | // some invalid regexp stuff in the set. |
||
920 | if (p === false) return false |
||
921 | |||
922 | if (p === GLOBSTAR) { |
||
923 | if (options.debug) |
||
924 | console.error('GLOBSTAR', [pattern, p, f]) |
||
925 | |||
926 | // "**" |
||
927 | // a/**/b/**/c would match the following: |
||
928 | // a/b/x/y/z/c |
||
929 | // a/x/y/z/b/c |
||
930 | // a/b/x/b/x/c |
||
931 | // a/b/c |
||
932 | // To do this, take the rest of the pattern after |
||
933 | // the **, and see if it would match the file remainder. |
||
934 | // If so, return success. |
||
935 | // If not, the ** "swallows" a segment, and try again. |
||
936 | // This is recursively awful. |
||
937 | // |
||
938 | // a/**/b/**/c matching a/b/x/y/z/c |
||
939 | // - a matches a |
||
940 | // - doublestar |
||
941 | // - matchOne(b/x/y/z/c, b/**/c) |
||
942 | // - b matches b |
||
943 | // - doublestar |
||
944 | // - matchOne(x/y/z/c, c) -> no |
||
945 | // - matchOne(y/z/c, c) -> no |
||
946 | // - matchOne(z/c, c) -> no |
||
947 | // - matchOne(c, c) yes, hit |
||
948 | var fr = fi |
||
949 | , pr = pi + 1 |
||
950 | if (pr === pl) { |
||
951 | if (options.debug) |
||
952 | console.error('** at the end') |
||
953 | // a ** at the end will just swallow the rest. |
||
954 | // We have found a match. |
||
955 | // however, it will not swallow /.x, unless |
||
956 | // options.dot is set. |
||
957 | // . and .. are *never* matched by **, for explosively |
||
958 | // exponential reasons. |
||
959 | for ( ; fi < fl; fi ++) { |
||
960 | if (file[fi] === "." || file[fi] === ".." || |
||
961 | (!options.dot && file[fi].charAt(0) === ".")) return false |
||
962 | } |
||
963 | return true |
||
964 | } |
||
965 | |||
966 | // ok, let's see if we can swallow whatever we can. |
||
967 | WHILE: while (fr < fl) { |
||
968 | var swallowee = file[fr] |
||
969 | |||
970 | if (options.debug) { |
||
971 | console.error('\nglobstar while', |
||
972 | file, fr, pattern, pr, swallowee) |
||
973 | } |
||
974 | |||
975 | // XXX remove this slice. Just pass the start index. |
||
976 | if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { |
||
977 | if (options.debug) |
||
978 | console.error('globstar found match!', fr, fl, swallowee) |
||
979 | // found a match. |
||
980 | return true |
||
981 | } else { |
||
982 | // can't swallow "." or ".." ever. |
||
983 | // can only swallow ".foo" when explicitly asked. |
||
984 | if (swallowee === "." || swallowee === ".." || |
||
985 | (!options.dot && swallowee.charAt(0) === ".")) { |
||
986 | if (options.debug) |
||
987 | console.error("dot detected!", file, fr, pattern, pr) |
||
988 | break WHILE |
||
989 | } |
||
990 | |||
991 | // ** swallows a segment, and continue. |
||
992 | if (options.debug) |
||
993 | console.error('globstar swallow a segment, and continue') |
||
994 | fr ++ |
||
995 | } |
||
996 | } |
||
997 | // no match was found. |
||
998 | // However, in partial mode, we can't say this is necessarily over. |
||
999 | // If there's more *pattern* left, then |
||
1000 | if (partial) { |
||
1001 | // ran out of file |
||
1002 | // console.error("\n>>> no match, partial?", file, fr, pattern, pr) |
||
1003 | if (fr === fl) return true |
||
1004 | } |
||
1005 | return false |
||
1006 | } |
||
1007 | |||
1008 | // something other than ** |
||
1009 | // non-magic patterns just have to match exactly |
||
1010 | // patterns with magic have been turned into regexps. |
||
1011 | var hit |
||
1012 | if (typeof p === "string") { |
||
1013 | if (options.nocase) { |
||
1014 | hit = f.toLowerCase() === p.toLowerCase() |
||
1015 | } else { |
||
1016 | hit = f === p |
||
1017 | } |
||
1018 | if (options.debug) { |
||
1019 | console.error("string match", p, f, hit) |
||
1020 | } |
||
1021 | } else { |
||
1022 | hit = f.match(p) |
||
1023 | if (options.debug) { |
||
1024 | console.error("pattern match", p, f, hit) |
||
1025 | } |
||
1026 | } |
||
1027 | |||
1028 | if (!hit) return false |
||
1029 | } |
||
1030 | |||
1031 | // Note: ending in / means that we'll get a final "" |
||
1032 | // at the end of the pattern. This can only match a |
||
1033 | // corresponding "" at the end of the file. |
||
1034 | // If the file ends in /, then it can only match a |
||
1035 | // a pattern that ends in /, unless the pattern just |
||
1036 | // doesn't have any more for it. But, a/b/ should *not* |
||
1037 | // match "a/b/*", even though "" matches against the |
||
1038 | // [^/]*? pattern, except in partial mode, where it might |
||
1039 | // simply not be reached yet. |
||
1040 | // However, a/b/ should still satisfy a/* |
||
1041 | |||
1042 | // now either we fell off the end of the pattern, or we're done. |
||
1043 | if (fi === fl && pi === pl) { |
||
1044 | // ran out of pattern and filename at the same time. |
||
1045 | // an exact hit! |
||
1046 | return true |
||
1047 | } else if (fi === fl) { |
||
1048 | // ran out of file, but still had pattern left. |
||
1049 | // this is ok if we're doing the match as part of |
||
1050 | // a glob fs traversal. |
||
1051 | return partial |
||
1052 | } else if (pi === pl) { |
||
1053 | // ran out of pattern, still have file left. |
||
1054 | // this is only acceptable if we're on the very last |
||
1055 | // empty segment of a file with a trailing slash. |
||
1056 | // a/* should match a/b/ |
||
1057 | var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") |
||
1058 | return emptyFileEnd |
||
1059 | } |
||
1060 | |||
1061 | // should be unreachable. |
||
1062 | throw new Error("wtf?") |
||
1063 | } |
||
1064 | |||
1065 | |||
1066 | // replace stuff like \* with * |
||
1067 | function globUnescape (s) { |
||
1068 | return s.replace(/\\(.)/g, "$1") |
||
1069 | } |
||
1070 | |||
1071 | |||
1072 | function regExpEscape (s) { |
||
1073 | return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") |
||
1074 | } |
||
1075 | |||
1076 | })( typeof require === "function" ? require : null, |
||
1077 | this, |
||
1078 | typeof module === "object" ? module : null, |
||
1079 | typeof process === "object" ? process.platform : "win32" |
||
1080 | ) |