Initial commit
[yaffs-website] / node_modules / braces / index.js
1 /*!
2  * braces <https://github.com/jonschlinkert/braces>
3  *
4  * Copyright (c) 2014-2015, Jon Schlinkert.
5  * Licensed under the MIT license.
6  */
7
8 'use strict';
9
10 /**
11  * Module dependencies
12  */
13
14 var expand = require('expand-range');
15 var repeat = require('repeat-element');
16 var tokens = require('preserve');
17
18 /**
19  * Expose `braces`
20  */
21
22 module.exports = function(str, options) {
23   if (typeof str !== 'string') {
24     throw new Error('braces expects a string');
25   }
26   return braces(str, options);
27 };
28
29 /**
30  * Expand `{foo,bar}` or `{1..5}` braces in the
31  * given `string`.
32  *
33  * @param  {String} `str`
34  * @param  {Array} `arr`
35  * @param  {Object} `options`
36  * @return {Array}
37  */
38
39 function braces(str, arr, options) {
40   if (str === '') {
41     return [];
42   }
43
44   if (!Array.isArray(arr)) {
45     options = arr;
46     arr = [];
47   }
48
49   var opts = options || {};
50   arr = arr || [];
51
52   if (typeof opts.nodupes === 'undefined') {
53     opts.nodupes = true;
54   }
55
56   var fn = opts.fn;
57   var es6;
58
59   if (typeof opts === 'function') {
60     fn = opts;
61     opts = {};
62   }
63
64   if (!(patternRe instanceof RegExp)) {
65     patternRe = patternRegex();
66   }
67
68   var matches = str.match(patternRe) || [];
69   var m = matches[0];
70
71   switch(m) {
72     case '\\,':
73       return escapeCommas(str, arr, opts);
74     case '\\.':
75       return escapeDots(str, arr, opts);
76     case '\/.':
77       return escapePaths(str, arr, opts);
78     case ' ':
79       return splitWhitespace(str);
80     case '{,}':
81       return exponential(str, opts, braces);
82     case '{}':
83       return emptyBraces(str, arr, opts);
84     case '\\{':
85     case '\\}':
86       return escapeBraces(str, arr, opts);
87     case '${':
88       if (!/\{[^{]+\{/.test(str)) {
89         return arr.concat(str);
90       } else {
91         es6 = true;
92         str = tokens.before(str, es6Regex());
93       }
94   }
95
96   if (!(braceRe instanceof RegExp)) {
97     braceRe = braceRegex();
98   }
99
100   var match = braceRe.exec(str);
101   if (match == null) {
102     return [str];
103   }
104
105   var outter = match[1];
106   var inner = match[2];
107   if (inner === '') { return [str]; }
108
109   var segs, segsLength;
110
111   if (inner.indexOf('..') !== -1) {
112     segs = expand(inner, opts, fn) || inner.split(',');
113     segsLength = segs.length;
114
115   } else if (inner[0] === '"' || inner[0] === '\'') {
116     return arr.concat(str.split(/['"]/).join(''));
117
118   } else {
119     segs = inner.split(',');
120     if (opts.makeRe) {
121       return braces(str.replace(outter, wrap(segs, '|')), opts);
122     }
123
124     segsLength = segs.length;
125     if (segsLength === 1 && opts.bash) {
126       segs[0] = wrap(segs[0], '\\');
127     }
128   }
129
130   var len = segs.length;
131   var i = 0, val;
132
133   while (len--) {
134     var path = segs[i++];
135
136     if (/(\.[^.\/])/.test(path)) {
137       if (segsLength > 1) {
138         return segs;
139       } else {
140         return [str];
141       }
142     }
143
144     val = splice(str, outter, path);
145
146     if (/\{[^{}]+?\}/.test(val)) {
147       arr = braces(val, arr, opts);
148     } else if (val !== '') {
149       if (opts.nodupes && arr.indexOf(val) !== -1) { continue; }
150       arr.push(es6 ? tokens.after(val) : val);
151     }
152   }
153
154   if (opts.strict) { return filter(arr, filterEmpty); }
155   return arr;
156 }
157
158 /**
159  * Expand exponential ranges
160  *
161  *   `a{,}{,}` => ['a', 'a', 'a', 'a']
162  */
163
164 function exponential(str, options, fn) {
165   if (typeof options === 'function') {
166     fn = options;
167     options = null;
168   }
169
170   var opts = options || {};
171   var esc = '__ESC_EXP__';
172   var exp = 0;
173   var res;
174
175   var parts = str.split('{,}');
176   if (opts.nodupes) {
177     return fn(parts.join(''), opts);
178   }
179
180   exp = parts.length - 1;
181   res = fn(parts.join(esc), opts);
182   var len = res.length;
183   var arr = [];
184   var i = 0;
185
186   while (len--) {
187     var ele = res[i++];
188     var idx = ele.indexOf(esc);
189
190     if (idx === -1) {
191       arr.push(ele);
192
193     } else {
194       ele = ele.split('__ESC_EXP__').join('');
195       if (!!ele && opts.nodupes !== false) {
196         arr.push(ele);
197
198       } else {
199         var num = Math.pow(2, exp);
200         arr.push.apply(arr, repeat(ele, num));
201       }
202     }
203   }
204   return arr;
205 }
206
207 /**
208  * Wrap a value with parens, brackets or braces,
209  * based on the given character/separator.
210  *
211  * @param  {String|Array} `val`
212  * @param  {String} `ch`
213  * @return {String}
214  */
215
216 function wrap(val, ch) {
217   if (ch === '|') {
218     return '(' + val.join(ch) + ')';
219   }
220   if (ch === ',') {
221     return '{' + val.join(ch) + '}';
222   }
223   if (ch === '-') {
224     return '[' + val.join(ch) + ']';
225   }
226   if (ch === '\\') {
227     return '\\{' + val + '\\}';
228   }
229 }
230
231 /**
232  * Handle empty braces: `{}`
233  */
234
235 function emptyBraces(str, arr, opts) {
236   return braces(str.split('{}').join('\\{\\}'), arr, opts);
237 }
238
239 /**
240  * Filter out empty-ish values
241  */
242
243 function filterEmpty(ele) {
244   return !!ele && ele !== '\\';
245 }
246
247 /**
248  * Handle patterns with whitespace
249  */
250
251 function splitWhitespace(str) {
252   var segs = str.split(' ');
253   var len = segs.length;
254   var res = [];
255   var i = 0;
256
257   while (len--) {
258     res.push.apply(res, braces(segs[i++]));
259   }
260   return res;
261 }
262
263 /**
264  * Handle escaped braces: `\\{foo,bar}`
265  */
266
267 function escapeBraces(str, arr, opts) {
268   if (!/\{[^{]+\{/.test(str)) {
269     return arr.concat(str.split('\\').join(''));
270   } else {
271     str = str.split('\\{').join('__LT_BRACE__');
272     str = str.split('\\}').join('__RT_BRACE__');
273     return map(braces(str, arr, opts), function(ele) {
274       ele = ele.split('__LT_BRACE__').join('{');
275       return ele.split('__RT_BRACE__').join('}');
276     });
277   }
278 }
279
280 /**
281  * Handle escaped dots: `{1\\.2}`
282  */
283
284 function escapeDots(str, arr, opts) {
285   if (!/[^\\]\..+\\\./.test(str)) {
286     return arr.concat(str.split('\\').join(''));
287   } else {
288     str = str.split('\\.').join('__ESC_DOT__');
289     return map(braces(str, arr, opts), function(ele) {
290       return ele.split('__ESC_DOT__').join('.');
291     });
292   }
293 }
294
295 /**
296  * Handle escaped dots: `{1\\.2}`
297  */
298
299 function escapePaths(str, arr, opts) {
300   str = str.split('\/.').join('__ESC_PATH__');
301   return map(braces(str, arr, opts), function(ele) {
302     return ele.split('__ESC_PATH__').join('\/.');
303   });
304 }
305
306 /**
307  * Handle escaped commas: `{a\\,b}`
308  */
309
310 function escapeCommas(str, arr, opts) {
311   if (!/\w,/.test(str)) {
312     return arr.concat(str.split('\\').join(''));
313   } else {
314     str = str.split('\\,').join('__ESC_COMMA__');
315     return map(braces(str, arr, opts), function(ele) {
316       return ele.split('__ESC_COMMA__').join(',');
317     });
318   }
319 }
320
321 /**
322  * Regex for common patterns
323  */
324
325 function patternRegex() {
326   return /\${|( (?=[{,}])|(?=[{,}]) )|{}|{,}|\\,(?=.*[{}])|\/\.(?=.*[{}])|\\\.(?={)|\\{|\\}/;
327 }
328
329 /**
330  * Braces regex.
331  */
332
333 function braceRegex() {
334   return /.*(\\?\{([^}]+)\})/;
335 }
336
337 /**
338  * es6 delimiter regex.
339  */
340
341 function es6Regex() {
342   return /\$\{([^}]+)\}/;
343 }
344
345 var braceRe;
346 var patternRe;
347
348 /**
349  * Faster alternative to `String.replace()` when the
350  * index of the token to be replaces can't be supplied
351  */
352
353 function splice(str, token, replacement) {
354   var i = str.indexOf(token);
355   return str.substr(0, i) + replacement
356     + str.substr(i + token.length);
357 }
358
359 /**
360  * Fast array map
361  */
362
363 function map(arr, fn) {
364   if (arr == null) {
365     return [];
366   }
367
368   var len = arr.length;
369   var res = new Array(len);
370   var i = -1;
371
372   while (++i < len) {
373     res[i] = fn(arr[i], i, arr);
374   }
375
376   return res;
377 }
378
379 /**
380  * Fast array filter
381  */
382
383 function filter(arr, cb) {
384   if (arr == null) return [];
385   if (typeof cb !== 'function') {
386     throw new TypeError('braces: filter expects a callback function.');
387   }
388
389   var len = arr.length;
390   var res = arr.slice();
391   var i = 0;
392
393   while (len--) {
394     if (!cb(arr[len], i++)) {
395       res.splice(len, 1);
396     }
397   }
398   return res;
399 }