UNPKG

5.18 kBJavaScriptView Raw
1'use strict';
2
3var utils = module.exports;
4
5/**
6 * Module dependencies
7 */
8
9utils.define = require('define-property');
10utils.extend = require('extend-shallow');
11utils.flatten = require('arr-flatten');
12utils.isObject = require('isobject');
13utils.range = require('fill-range');
14utils.repeat = require('repeat-element');
15utils.unique = require('array-unique');
16
17/**
18 * Create the key to use for memoization. The unique key is generated
19 * by iterating over the options and concatenating key-value pairs
20 * to the pattern string.
21 */
22
23utils.createKey = function(pattern, options) {
24 var key = pattern;
25 if (typeof options === 'undefined') {
26 return key;
27 }
28 for (var prop in options) {
29 if (options.hasOwnProperty(prop)) {
30 key += ';' + prop + '=' + String(options[prop]);
31 }
32 }
33 return key;
34};
35
36/**
37 * Normalize options
38 */
39
40utils.createOptions = function(options) {
41 var opts = utils.extend.apply(null, arguments);
42 if (typeof opts.expand === 'boolean') {
43 opts.optimize = !opts.expand;
44 }
45 if (typeof opts.optimize === 'boolean') {
46 opts.expand = !opts.optimize;
47 }
48 if (opts.optimize === true) {
49 opts.makeRe = true;
50 }
51 return opts;
52};
53
54/**
55 * Join patterns in `a` to patterns in `b`
56 */
57
58utils.join = function(a, b, options) {
59 options = options || {};
60 a = utils.arrayify(a);
61 b = utils.arrayify(b);
62 if (!a.length) return b;
63 if (!b.length) return a;
64
65 var len = a.length;
66 var idx = -1;
67 var arr = [];
68
69 while (++idx < len) {
70 var str = a[idx];
71 if (Array.isArray(str)) {
72 str = str.map(function(ele) {
73 return utils.join(ele, b);
74 });
75 arr.push(str);
76 continue;
77 }
78
79 for (var i = 0; i < b.length; i++) {
80 if (Array.isArray(b[i])) {
81 arr.push(utils.join(str, b[i]));
82 } else {
83 arr.push(str + b[i]);
84 }
85 }
86 }
87 return arr;
88};
89
90/**
91 * Split the given string on `,` if not escaped.
92 */
93
94utils.split = function(str) {
95 var segs = str.split(',');
96 var tok = {rest: ''};
97 var res = [];
98
99 while (segs.length) {
100 var key = segs.shift();
101 var next = segs[segs.length - 1];
102 var quoted;
103
104 while (key.slice(-1) === '\\' || (quoted = isQuote(key, next))) {
105 if (quoted) tok.quoted = true;
106 tok.escaped = true;
107 var ch = segs.shift();
108 if (!ch) break;
109 key = key.slice(0, -1) + ',' + (quoted ? ch.slice(1) : ch);
110 }
111 res.push(key);
112 }
113
114 if (tok.quoted) {
115 tok.val = res[0];
116 }
117
118 tok.segs = res;
119 return tok;
120};
121
122function isDoubleQuote(key, next) {
123 return key.slice(-1) === '"' && next.charAt(0) === '"';
124}
125
126function isSingleQuote(key, next) {
127 return key.slice(-1) === "'" && next.charAt(0) === "'";
128}
129
130function isQuote(key, next) {
131 return isDoubleQuote(key, next) || isSingleQuote(key, next);
132}
133
134/**
135 * Expand ranges or sets in the given `pattern`.
136 *
137 * @param {String} `str`
138 * @param {Object} `options`
139 * @return {Object}
140 */
141
142utils.expand = function(str, options) {
143 var opts = utils.extend({rangeLimit: 250}, options);
144 var tok = utils.split(str);
145 var segs = tok.segs;
146
147 if (segs.length > 1) {
148 if (opts.optimize === false) {
149 tok.val = segs[0];
150 return tok;
151 }
152
153 tok.segs = utils.stringify(tok.segs);
154 } else if (segs.length === 1) {
155 var arr = str.split('..');
156
157 if (arr.length === 1) {
158 tok.val = tok.segs.pop() || tok.val || str;
159 tok.segs = [];
160 return tok;
161 }
162
163 if (arr.length === 2 && arr[0] === arr[1]) {
164 tok.escaped = true;
165 tok.val = arr[0];
166 tok.segs = [];
167 return tok;
168 }
169
170 if (arr.length > 1) {
171 if (opts.optimize !== false) {
172 opts.optimize = true;
173 delete opts.expand;
174 }
175
176 if (opts.optimize !== true) {
177 var min = Math.min(arr[0], arr[1]);
178 var max = Math.max(arr[0], arr[1]);
179 var step = arr[2] || 1;
180 if (((max - min) / step) >= opts.rangeLimit) {
181 opts.optimize = true;
182 tok.isOptimized = true;
183 delete opts.expand;
184 }
185 }
186
187 arr.push(opts);
188 tok.segs = utils.range.apply(null, arr);
189
190 if (!tok.segs.length) {
191 tok.escaped = true;
192 tok.val = str;
193 return tok;
194 }
195
196 if (opts.optimize === true) {
197 tok.segs = utils.stringify(tok.segs);
198 }
199
200 if (tok.segs === '') {
201 tok.val = str;
202 } else {
203 tok.val = tok.segs[0];
204 }
205 return tok;
206 }
207 } else {
208 tok.val = str;
209 }
210 return tok;
211};
212
213/**
214 * Cast `val` to an array.
215 * @param {*} `val`
216 */
217
218utils.stringify = function(arr) {
219 return [utils.arrayify(arr).join('|')];
220};
221
222/**
223 * Cast `val` to an array.
224 * @param {*} `val`
225 */
226
227utils.arrayify = function(arr) {
228 if (typeof arr === 'undefined') return [];
229 return Array.isArray(arr) ? arr : [arr];
230};
231
232/**
233 * Returns true if the given `str` is a non-empty string
234 * @return {Boolean}
235 */
236
237utils.isString = function(str) {
238 return str != null && typeof str === 'string';
239};
240
241/**
242 * Get the last element from `array`
243 * @param {Array} `array`
244 * @return {*}
245 */
246
247utils.last = function(arr) {
248 return arr[arr.length - 1];
249};
250
251utils.escapeRegex = function(str) {
252 return str.replace(/\\?([!$^*?()\[\]{}+?/])/g, '\\$1');
253};