source: frontend/node_modules/brace-expansion/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 4.9 KB
Line 
1var concatMap = require('concat-map');
2var balanced = require('balanced-match');
3
4module.exports = expandTop;
5
6var escSlash = '\0SLASH'+Math.random()+'\0';
7var escOpen = '\0OPEN'+Math.random()+'\0';
8var escClose = '\0CLOSE'+Math.random()+'\0';
9var escComma = '\0COMMA'+Math.random()+'\0';
10var escPeriod = '\0PERIOD'+Math.random()+'\0';
11
12function numeric(str) {
13 return parseInt(str, 10) == str
14 ? parseInt(str, 10)
15 : str.charCodeAt(0);
16}
17
18function escapeBraces(str) {
19 return str.split('\\\\').join(escSlash)
20 .split('\\{').join(escOpen)
21 .split('\\}').join(escClose)
22 .split('\\,').join(escComma)
23 .split('\\.').join(escPeriod);
24}
25
26function unescapeBraces(str) {
27 return str.split(escSlash).join('\\')
28 .split(escOpen).join('{')
29 .split(escClose).join('}')
30 .split(escComma).join(',')
31 .split(escPeriod).join('.');
32}
33
34
35// Basically just str.split(","), but handling cases
36// where we have nested braced sections, which should be
37// treated as individual members, like {a,{b,c},d}
38function parseCommaParts(str) {
39 if (!str)
40 return [''];
41
42 var parts = [];
43 var m = balanced('{', '}', str);
44
45 if (!m)
46 return str.split(',');
47
48 var pre = m.pre;
49 var body = m.body;
50 var post = m.post;
51 var p = pre.split(',');
52
53 p[p.length-1] += '{' + body + '}';
54 var postParts = parseCommaParts(post);
55 if (post.length) {
56 p[p.length-1] += postParts.shift();
57 p.push.apply(p, postParts);
58 }
59
60 parts.push.apply(parts, p);
61
62 return parts;
63}
64
65function expandTop(str, options) {
66 if (!str)
67 return [];
68
69 options = options || {};
70 var max = options.max == null ? Infinity : options.max;
71
72 // I don't know why Bash 4.3 does this, but it does.
73 // Anything starting with {} will have the first two bytes preserved
74 // but *only* at the top level, so {},a}b will not expand to anything,
75 // but a{},b}c will be expanded to [a}c,abc].
76 // One could argue that this is a bug in Bash, but since the goal of
77 // this module is to match Bash's rules, we escape a leading {}
78 if (str.substr(0, 2) === '{}') {
79 str = '\\{\\}' + str.substr(2);
80 }
81
82 return expand(escapeBraces(str), max, true).map(unescapeBraces);
83}
84
85function identity(e) {
86 return e;
87}
88
89function embrace(str) {
90 return '{' + str + '}';
91}
92function isPadded(el) {
93 return /^-?0\d/.test(el);
94}
95
96function lte(i, y) {
97 return i <= y;
98}
99function gte(i, y) {
100 return i >= y;
101}
102
103function expand(str, max, isTop) {
104 var expansions = [];
105
106 var m = balanced('{', '}', str);
107 if (!m || /\$$/.test(m.pre)) return [str];
108
109 var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
110 var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
111 var isSequence = isNumericSequence || isAlphaSequence;
112 var isOptions = m.body.indexOf(',') >= 0;
113 if (!isSequence && !isOptions) {
114 // {a},b}
115 if (m.post.match(/,(?!,).*\}/)) {
116 str = m.pre + '{' + m.body + escClose + m.post;
117 return expand(str, max, true);
118 }
119 return [str];
120 }
121
122 var n;
123 if (isSequence) {
124 n = m.body.split(/\.\./);
125 } else {
126 n = parseCommaParts(m.body);
127 if (n.length === 1) {
128 // x{{a,b}}y ==> x{a}y x{b}y
129 n = expand(n[0], max, false).map(embrace);
130 if (n.length === 1) {
131 var post = m.post.length
132 ? expand(m.post, max, false)
133 : [''];
134 return post.map(function(p) {
135 return m.pre + n[0] + p;
136 });
137 }
138 }
139 }
140
141 // at this point, n is the parts, and we know it's not a comma set
142 // with a single entry.
143
144 // no need to expand pre, since it is guaranteed to be free of brace-sets
145 var pre = m.pre;
146 var post = m.post.length
147 ? expand(m.post, max, false)
148 : [''];
149
150 var N;
151
152 if (isSequence) {
153 var x = numeric(n[0]);
154 var y = numeric(n[1]);
155 var width = Math.max(n[0].length, n[1].length)
156 var incr = n.length == 3
157 ? Math.max(Math.abs(numeric(n[2])), 1)
158 : 1;
159 var test = lte;
160 var reverse = y < x;
161 if (reverse) {
162 incr *= -1;
163 test = gte;
164 }
165 var pad = n.some(isPadded);
166
167 N = [];
168
169 for (var i = x; test(i, y); i += incr) {
170 var c;
171 if (isAlphaSequence) {
172 c = String.fromCharCode(i);
173 if (c === '\\')
174 c = '';
175 } else {
176 c = String(i);
177 if (pad) {
178 var need = width - c.length;
179 if (need > 0) {
180 var z = new Array(need + 1).join('0');
181 if (i < 0)
182 c = '-' + z + c.slice(1);
183 else
184 c = z + c;
185 }
186 }
187 }
188 N.push(c);
189 }
190 } else {
191 N = concatMap(n, function(el) { return expand(el, max, false) });
192 }
193
194 for (var j = 0; j < N.length; j++) {
195 for (var k = 0; k < post.length && expansions.length < max; k++) {
196 var expansion = pre + N[j] + post[k];
197 if (!isTop || isSequence || expansion)
198 expansions.push(expansion);
199 }
200 }
201
202 return expansions;
203}
Note: See TracBrowser for help on using the repository browser.