.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / nanomatch / lib / utils.js
1 'use strict';
2
3 var utils = module.exports;
4 var path = require('path');
5
6 /**
7  * Module dependencies
8  */
9
10 var isWindows = require('is-windows')();
11 var Snapdragon = require('snapdragon');
12 utils.define = require('define-property');
13 utils.diff = require('arr-diff');
14 utils.extend = require('extend-shallow');
15 utils.pick = require('object.pick');
16 utils.typeOf = require('kind-of');
17 utils.unique = require('array-unique');
18
19 /**
20  * Returns true if the given value is effectively an empty string
21  */
22
23 utils.isEmptyString = function(val) {
24   return String(val) === '' || String(val) === './';
25 };
26
27 /**
28  * Returns true if the platform is windows, or `path.sep` is `\\`.
29  * This is defined as a function to allow `path.sep` to be set in unit tests,
30  * or by the user, if there is a reason to do so.
31  * @return {Boolean}
32  */
33
34 utils.isWindows = function() {
35   return path.sep === '\\' || isWindows === true;
36 };
37
38 /**
39  * Return the last element from an array
40  */
41
42 utils.last = function(arr, n) {
43   return arr[arr.length - (n || 1)];
44 };
45
46 /**
47  * Get the `Snapdragon` instance to use
48  */
49
50 utils.instantiate = function(ast, options) {
51   var snapdragon;
52   // if an instance was created by `.parse`, use that instance
53   if (utils.typeOf(ast) === 'object' && ast.snapdragon) {
54     snapdragon = ast.snapdragon;
55   // if the user supplies an instance on options, use that instance
56   } else if (utils.typeOf(options) === 'object' && options.snapdragon) {
57     snapdragon = options.snapdragon;
58   // create a new instance
59   } else {
60     snapdragon = new Snapdragon(options);
61   }
62
63   utils.define(snapdragon, 'parse', function(str, options) {
64     var parsed = Snapdragon.prototype.parse.call(this, str, options);
65     parsed.input = str;
66
67     // escape unmatched brace/bracket/parens
68     var last = this.parser.stack.pop();
69     if (last && this.options.strictErrors !== true) {
70       var open = last.nodes[0];
71       var inner = last.nodes[1];
72       if (last.type === 'bracket') {
73         if (inner.val.charAt(0) === '[') {
74           inner.val = '\\' + inner.val;
75         }
76
77       } else {
78         open.val = '\\' + open.val;
79         var sibling = open.parent.nodes[1];
80         if (sibling.type === 'star') {
81           sibling.loose = true;
82         }
83       }
84     }
85
86     // add non-enumerable parser reference
87     utils.define(parsed, 'parser', this.parser);
88     return parsed;
89   });
90
91   return snapdragon;
92 };
93
94 /**
95  * Create the key to use for memoization. The key is generated
96  * by iterating over the options and concatenating key-value pairs
97  * to the pattern string.
98  */
99
100 utils.createKey = function(pattern, options) {
101   if (typeof options === 'undefined') {
102     return pattern;
103   }
104   var key = pattern;
105   for (var prop in options) {
106     if (options.hasOwnProperty(prop)) {
107       key += ';' + prop + '=' + String(options[prop]);
108     }
109   }
110   return key;
111 };
112
113 /**
114  * Cast `val` to an array
115  * @return {Array}
116  */
117
118 utils.arrayify = function(val) {
119   if (typeof val === 'string') return [val];
120   return val ? (Array.isArray(val) ? val : [val]) : [];
121 };
122
123 /**
124  * Return true if `val` is a non-empty string
125  */
126
127 utils.isString = function(val) {
128   return typeof val === 'string';
129 };
130
131 /**
132  * Return true if `val` is a non-empty string
133  */
134
135 utils.isRegex = function(val) {
136   return utils.typeOf(val) === 'regexp';
137 };
138
139 /**
140  * Return true if `val` is a non-empty string
141  */
142
143 utils.isObject = function(val) {
144   return utils.typeOf(val) === 'object';
145 };
146
147 /**
148  * Escape regex characters in the given string
149  */
150
151 utils.escapeRegex = function(str) {
152   return str.replace(/[-[\]{}()^$|*+?.\\/\s]/g, '\\$&');
153 };
154
155 /**
156  * Combines duplicate characters in the provided `input` string.
157  * @param {String} `input`
158  * @returns {String}
159  */
160
161 utils.combineDupes = function(input, patterns) {
162   patterns = utils.arrayify(patterns).join('|').split('|');
163   patterns = patterns.map(function(s) {
164     return s.replace(/\\?([+*\\/])/g, '\\$1');
165   });
166   var substr = patterns.join('|');
167   var regex = new RegExp('(' + substr + ')(?=\\1)', 'g');
168   return input.replace(regex, '');
169 };
170
171 /**
172  * Returns true if the given `str` has special characters
173  */
174
175 utils.hasSpecialChars = function(str) {
176   return /(?:(?:(^|\/)[!.])|[*?+()|[\]{}]|[+@]\()/.test(str);
177 };
178
179 /**
180  * Normalize slashes in the given filepath.
181  *
182  * @param {String} `filepath`
183  * @return {String}
184  */
185
186 utils.toPosixPath = function(str) {
187   return str.replace(/\\+/g, '/');
188 };
189
190 /**
191  * Strip backslashes before special characters in a string.
192  *
193  * @param {String} `str`
194  * @return {String}
195  */
196
197 utils.unescape = function(str) {
198   return utils.toPosixPath(str.replace(/\\(?=[*+?!.])/g, ''));
199 };
200
201 /**
202  * Strip the drive letter from a windows filepath
203  * @param {String} `fp`
204  * @return {String}
205  */
206
207 utils.stripDrive = function(fp) {
208   return utils.isWindows() ? fp.replace(/^[a-z]:[\\/]+?/i, '/') : fp;
209 };
210
211 /**
212  * Strip the prefix from a filepath
213  * @param {String} `fp`
214  * @return {String}
215  */
216
217 utils.stripPrefix = function(str) {
218   if (str.charAt(0) === '.' && (str.charAt(1) === '/' || str.charAt(1) === '\\')) {
219     return str.slice(2);
220   }
221   return str;
222 };
223
224 /**
225  * Returns true if `str` is a common character that doesn't need
226  * to be processed to be used for matching.
227  * @param {String} `str`
228  * @return {Boolean}
229  */
230
231 utils.isSimpleChar = function(str) {
232   return str.trim() === '' || str === '.';
233 };
234
235 /**
236  * Returns true if the given str is an escaped or
237  * unescaped path character
238  */
239
240 utils.isSlash = function(str) {
241   return str === '/' || str === '\\/' || str === '\\' || str === '\\\\';
242 };
243
244 /**
245  * Returns a function that returns true if the given
246  * pattern matches or contains a `filepath`
247  *
248  * @param {String} `pattern`
249  * @return {Function}
250  */
251
252 utils.matchPath = function(pattern, options) {
253   return (options && options.contains)
254     ? utils.containsPattern(pattern, options)
255     : utils.equalsPattern(pattern, options);
256 };
257
258 /**
259  * Returns true if the given (original) filepath or unixified path are equal
260  * to the given pattern.
261  */
262
263 utils._equals = function(filepath, unixPath, pattern) {
264   return pattern === filepath || pattern === unixPath;
265 };
266
267 /**
268  * Returns true if the given (original) filepath or unixified path contain
269  * the given pattern.
270  */
271
272 utils._contains = function(filepath, unixPath, pattern) {
273   return filepath.indexOf(pattern) !== -1 || unixPath.indexOf(pattern) !== -1;
274 };
275
276 /**
277  * Returns a function that returns true if the given
278  * pattern is the same as a given `filepath`
279  *
280  * @param {String} `pattern`
281  * @return {Function}
282  */
283
284 utils.equalsPattern = function(pattern, options) {
285   var unixify = utils.unixify(options);
286   options = options || {};
287
288   return function fn(filepath) {
289     var equal = utils._equals(filepath, unixify(filepath), pattern);
290     if (equal === true || options.nocase !== true) {
291       return equal;
292     }
293     var lower = filepath.toLowerCase();
294     return utils._equals(lower, unixify(lower), pattern);
295   };
296 };
297
298 /**
299  * Returns a function that returns true if the given
300  * pattern contains a `filepath`
301  *
302  * @param {String} `pattern`
303  * @return {Function}
304  */
305
306 utils.containsPattern = function(pattern, options) {
307   var unixify = utils.unixify(options);
308   options = options || {};
309
310   return function(filepath) {
311     var contains = utils._contains(filepath, unixify(filepath), pattern);
312     if (contains === true || options.nocase !== true) {
313       return contains;
314     }
315     var lower = filepath.toLowerCase();
316     return utils._contains(lower, unixify(lower), pattern);
317   };
318 };
319
320 /**
321  * Returns a function that returns true if the given
322  * regex matches the `filename` of a file path.
323  *
324  * @param {RegExp} `re` Matching regex
325  * @return {Function}
326  */
327
328 utils.matchBasename = function(re) {
329   return function(filepath) {
330     return re.test(filepath) || re.test(path.basename(filepath));
331   };
332 };
333
334 /**
335  * Returns the given value unchanced.
336  * @return {any}
337  */
338
339 utils.identity = function(val) {
340   return val;
341 };
342
343 /**
344  * Determines the filepath to return based on the provided options.
345  * @return {any}
346  */
347
348 utils.value = function(str, unixify, options) {
349   if (options && options.unixify === false) {
350     return str;
351   }
352   if (options && typeof options.unixify === 'function') {
353     return options.unixify(str);
354   }
355   return unixify(str);
356 };
357
358 /**
359  * Returns a function that normalizes slashes in a string to forward
360  * slashes, strips `./` from beginning of paths, and optionally unescapes
361  * special characters.
362  * @return {Function}
363  */
364
365 utils.unixify = function(options) {
366   var opts = options || {};
367   return function(filepath) {
368     if (opts.stripPrefix !== false) {
369       filepath = utils.stripPrefix(filepath);
370     }
371     if (opts.unescape === true) {
372       filepath = utils.unescape(filepath);
373     }
374     if (opts.unixify === true || utils.isWindows()) {
375       filepath = utils.toPosixPath(filepath);
376     }
377     return filepath;
378   };
379 };