1 | 'use strict';
|
2 |
|
3 | var openParentheses = "(".charCodeAt(0);
|
4 | var closeParentheses = ")".charCodeAt(0);
|
5 | var singleQuote = "'".charCodeAt(0);
|
6 | var doubleQuote = '"'.charCodeAt(0);
|
7 | var backslash = "\\".charCodeAt(0);
|
8 | var slash = "/".charCodeAt(0);
|
9 | var comma = ",".charCodeAt(0);
|
10 | var colon = ":".charCodeAt(0);
|
11 | var star = "*".charCodeAt(0);
|
12 | var uLower = "u".charCodeAt(0);
|
13 | var uUpper = "U".charCodeAt(0);
|
14 | var plus$1 = "+".charCodeAt(0);
|
15 | var isUnicodeRange = /^[a-f0-9?-]+$/i;
|
16 |
|
17 | var parse$1 = function(input) {
|
18 | var tokens = [];
|
19 | var value = input;
|
20 |
|
21 | var next,
|
22 | quote,
|
23 | prev,
|
24 | token,
|
25 | escape,
|
26 | escapePos,
|
27 | whitespacePos,
|
28 | parenthesesOpenPos;
|
29 | var pos = 0;
|
30 | var code = value.charCodeAt(pos);
|
31 | var max = value.length;
|
32 | var stack = [{ nodes: tokens }];
|
33 | var balanced = 0;
|
34 | var parent;
|
35 |
|
36 | var name = "";
|
37 | var before = "";
|
38 | var after = "";
|
39 |
|
40 | while (pos < max) {
|
41 |
|
42 | if (code <= 32) {
|
43 | next = pos;
|
44 | do {
|
45 | next += 1;
|
46 | code = value.charCodeAt(next);
|
47 | } while (code <= 32);
|
48 | token = value.slice(pos, next);
|
49 |
|
50 | prev = tokens[tokens.length - 1];
|
51 | if (code === closeParentheses && balanced) {
|
52 | after = token;
|
53 | } else if (prev && prev.type === "div") {
|
54 | prev.after = token;
|
55 | } else if (
|
56 | code === comma ||
|
57 | code === colon ||
|
58 | (code === slash &&
|
59 | value.charCodeAt(next + 1) !== star &&
|
60 | (!parent ||
|
61 | (parent && parent.type === "function" && parent.value !== "calc")))
|
62 | ) {
|
63 | before = token;
|
64 | } else {
|
65 | tokens.push({
|
66 | type: "space",
|
67 | sourceIndex: pos,
|
68 | value: token
|
69 | });
|
70 | }
|
71 |
|
72 | pos = next;
|
73 |
|
74 |
|
75 | } else if (code === singleQuote || code === doubleQuote) {
|
76 | next = pos;
|
77 | quote = code === singleQuote ? "'" : '"';
|
78 | token = {
|
79 | type: "string",
|
80 | sourceIndex: pos,
|
81 | quote: quote
|
82 | };
|
83 | do {
|
84 | escape = false;
|
85 | next = value.indexOf(quote, next + 1);
|
86 | if (~next) {
|
87 | escapePos = next;
|
88 | while (value.charCodeAt(escapePos - 1) === backslash) {
|
89 | escapePos -= 1;
|
90 | escape = !escape;
|
91 | }
|
92 | } else {
|
93 | value += quote;
|
94 | next = value.length - 1;
|
95 | token.unclosed = true;
|
96 | }
|
97 | } while (escape);
|
98 | token.value = value.slice(pos + 1, next);
|
99 |
|
100 | tokens.push(token);
|
101 | pos = next + 1;
|
102 | code = value.charCodeAt(pos);
|
103 |
|
104 |
|
105 | } else if (code === slash && value.charCodeAt(pos + 1) === star) {
|
106 | token = {
|
107 | type: "comment",
|
108 | sourceIndex: pos
|
109 | };
|
110 |
|
111 | next = value.indexOf("*/", pos);
|
112 | if (next === -1) {
|
113 | token.unclosed = true;
|
114 | next = value.length;
|
115 | }
|
116 |
|
117 | token.value = value.slice(pos + 2, next);
|
118 | tokens.push(token);
|
119 |
|
120 | pos = next + 2;
|
121 | code = value.charCodeAt(pos);
|
122 |
|
123 |
|
124 | } else if (
|
125 | (code === slash || code === star) &&
|
126 | parent &&
|
127 | parent.type === "function" &&
|
128 | parent.value === "calc"
|
129 | ) {
|
130 | token = value[pos];
|
131 | tokens.push({
|
132 | type: "word",
|
133 | sourceIndex: pos - before.length,
|
134 | value: token
|
135 | });
|
136 | pos += 1;
|
137 | code = value.charCodeAt(pos);
|
138 |
|
139 |
|
140 | } else if (code === slash || code === comma || code === colon) {
|
141 | token = value[pos];
|
142 |
|
143 | tokens.push({
|
144 | type: "div",
|
145 | sourceIndex: pos - before.length,
|
146 | value: token,
|
147 | before: before,
|
148 | after: ""
|
149 | });
|
150 | before = "";
|
151 |
|
152 | pos += 1;
|
153 | code = value.charCodeAt(pos);
|
154 |
|
155 |
|
156 | } else if (openParentheses === code) {
|
157 |
|
158 | next = pos;
|
159 | do {
|
160 | next += 1;
|
161 | code = value.charCodeAt(next);
|
162 | } while (code <= 32);
|
163 | parenthesesOpenPos = pos;
|
164 | token = {
|
165 | type: "function",
|
166 | sourceIndex: pos - name.length,
|
167 | value: name,
|
168 | before: value.slice(parenthesesOpenPos + 1, next)
|
169 | };
|
170 | pos = next;
|
171 |
|
172 | if (name === "url" && code !== singleQuote && code !== doubleQuote) {
|
173 | next -= 1;
|
174 | do {
|
175 | escape = false;
|
176 | next = value.indexOf(")", next + 1);
|
177 | if (~next) {
|
178 | escapePos = next;
|
179 | while (value.charCodeAt(escapePos - 1) === backslash) {
|
180 | escapePos -= 1;
|
181 | escape = !escape;
|
182 | }
|
183 | } else {
|
184 | value += ")";
|
185 | next = value.length - 1;
|
186 | token.unclosed = true;
|
187 | }
|
188 | } while (escape);
|
189 |
|
190 | whitespacePos = next;
|
191 | do {
|
192 | whitespacePos -= 1;
|
193 | code = value.charCodeAt(whitespacePos);
|
194 | } while (code <= 32);
|
195 | if (parenthesesOpenPos < whitespacePos) {
|
196 | if (pos !== whitespacePos + 1) {
|
197 | token.nodes = [
|
198 | {
|
199 | type: "word",
|
200 | sourceIndex: pos,
|
201 | value: value.slice(pos, whitespacePos + 1)
|
202 | }
|
203 | ];
|
204 | } else {
|
205 | token.nodes = [];
|
206 | }
|
207 | if (token.unclosed && whitespacePos + 1 !== next) {
|
208 | token.after = "";
|
209 | token.nodes.push({
|
210 | type: "space",
|
211 | sourceIndex: whitespacePos + 1,
|
212 | value: value.slice(whitespacePos + 1, next)
|
213 | });
|
214 | } else {
|
215 | token.after = value.slice(whitespacePos + 1, next);
|
216 | }
|
217 | } else {
|
218 | token.after = "";
|
219 | token.nodes = [];
|
220 | }
|
221 | pos = next + 1;
|
222 | code = value.charCodeAt(pos);
|
223 | tokens.push(token);
|
224 | } else {
|
225 | balanced += 1;
|
226 | token.after = "";
|
227 | tokens.push(token);
|
228 | stack.push(token);
|
229 | tokens = token.nodes = [];
|
230 | parent = token;
|
231 | }
|
232 | name = "";
|
233 |
|
234 |
|
235 | } else if (closeParentheses === code && balanced) {
|
236 | pos += 1;
|
237 | code = value.charCodeAt(pos);
|
238 |
|
239 | parent.after = after;
|
240 | after = "";
|
241 | balanced -= 1;
|
242 | stack.pop();
|
243 | parent = stack[balanced];
|
244 | tokens = parent.nodes;
|
245 |
|
246 |
|
247 | } else {
|
248 | next = pos;
|
249 | do {
|
250 | if (code === backslash) {
|
251 | next += 1;
|
252 | }
|
253 | next += 1;
|
254 | code = value.charCodeAt(next);
|
255 | } while (
|
256 | next < max &&
|
257 | !(
|
258 | code <= 32 ||
|
259 | code === singleQuote ||
|
260 | code === doubleQuote ||
|
261 | code === comma ||
|
262 | code === colon ||
|
263 | code === slash ||
|
264 | code === openParentheses ||
|
265 | (code === star &&
|
266 | parent &&
|
267 | parent.type === "function" &&
|
268 | parent.value === "calc") ||
|
269 | (code === slash &&
|
270 | parent.type === "function" &&
|
271 | parent.value === "calc") ||
|
272 | (code === closeParentheses && balanced)
|
273 | )
|
274 | );
|
275 | token = value.slice(pos, next);
|
276 |
|
277 | if (openParentheses === code) {
|
278 | name = token;
|
279 | } else if (
|
280 | (uLower === token.charCodeAt(0) || uUpper === token.charCodeAt(0)) &&
|
281 | plus$1 === token.charCodeAt(1) &&
|
282 | isUnicodeRange.test(token.slice(2))
|
283 | ) {
|
284 | tokens.push({
|
285 | type: "unicode-range",
|
286 | sourceIndex: pos,
|
287 | value: token
|
288 | });
|
289 | } else {
|
290 | tokens.push({
|
291 | type: "word",
|
292 | sourceIndex: pos,
|
293 | value: token
|
294 | });
|
295 | }
|
296 |
|
297 | pos = next;
|
298 | }
|
299 | }
|
300 |
|
301 | for (pos = stack.length - 1; pos; pos -= 1) {
|
302 | stack[pos].unclosed = true;
|
303 | }
|
304 |
|
305 | return stack[0].nodes;
|
306 | };
|
307 |
|
308 | var walk$1 = function walk(nodes, cb, bubble) {
|
309 | var i, max, node, result;
|
310 |
|
311 | for (i = 0, max = nodes.length; i < max; i += 1) {
|
312 | node = nodes[i];
|
313 | if (!bubble) {
|
314 | result = cb(node, i, nodes);
|
315 | }
|
316 |
|
317 | if (
|
318 | result !== false &&
|
319 | node.type === "function" &&
|
320 | Array.isArray(node.nodes)
|
321 | ) {
|
322 | walk(node.nodes, cb, bubble);
|
323 | }
|
324 |
|
325 | if (bubble) {
|
326 | cb(node, i, nodes);
|
327 | }
|
328 | }
|
329 | };
|
330 |
|
331 | function stringifyNode(node, custom) {
|
332 | var type = node.type;
|
333 | var value = node.value;
|
334 | var buf;
|
335 | var customResult;
|
336 |
|
337 | if (custom && (customResult = custom(node)) !== undefined) {
|
338 | return customResult;
|
339 | } else if (type === "word" || type === "space") {
|
340 | return value;
|
341 | } else if (type === "string") {
|
342 | buf = node.quote || "";
|
343 | return buf + value + (node.unclosed ? "" : buf);
|
344 | } else if (type === "comment") {
|
345 | return "/*" + value + (node.unclosed ? "" : "*/");
|
346 | } else if (type === "div") {
|
347 | return (node.before || "") + value + (node.after || "");
|
348 | } else if (Array.isArray(node.nodes)) {
|
349 | buf = stringify$1(node.nodes, custom);
|
350 | if (type !== "function") {
|
351 | return buf;
|
352 | }
|
353 | return (
|
354 | value +
|
355 | "(" +
|
356 | (node.before || "") +
|
357 | buf +
|
358 | (node.after || "") +
|
359 | (node.unclosed ? "" : ")")
|
360 | );
|
361 | }
|
362 | return value;
|
363 | }
|
364 |
|
365 | function stringify$1(nodes, custom) {
|
366 | var result, i;
|
367 |
|
368 | if (Array.isArray(nodes)) {
|
369 | result = "";
|
370 | for (i = nodes.length - 1; ~i; i -= 1) {
|
371 | result = stringifyNode(nodes[i], custom) + result;
|
372 | }
|
373 | return result;
|
374 | }
|
375 | return stringifyNode(nodes, custom);
|
376 | }
|
377 |
|
378 | var stringify_1 = stringify$1;
|
379 |
|
380 | var minus = "-".charCodeAt(0);
|
381 | var plus = "+".charCodeAt(0);
|
382 | var dot = ".".charCodeAt(0);
|
383 | var exp = "e".charCodeAt(0);
|
384 | var EXP = "E".charCodeAt(0);
|
385 |
|
386 |
|
387 |
|
388 | function likeNumber(value) {
|
389 | var code = value.charCodeAt(0);
|
390 | var nextCode;
|
391 |
|
392 | if (code === plus || code === minus) {
|
393 | nextCode = value.charCodeAt(1);
|
394 |
|
395 | if (nextCode >= 48 && nextCode <= 57) {
|
396 | return true;
|
397 | }
|
398 |
|
399 | var nextNextCode = value.charCodeAt(2);
|
400 |
|
401 | if (nextCode === dot && nextNextCode >= 48 && nextNextCode <= 57) {
|
402 | return true;
|
403 | }
|
404 |
|
405 | return false;
|
406 | }
|
407 |
|
408 | if (code === dot) {
|
409 | nextCode = value.charCodeAt(1);
|
410 |
|
411 | if (nextCode >= 48 && nextCode <= 57) {
|
412 | return true;
|
413 | }
|
414 |
|
415 | return false;
|
416 | }
|
417 |
|
418 | if (code >= 48 && code <= 57) {
|
419 | return true;
|
420 | }
|
421 |
|
422 | return false;
|
423 | }
|
424 |
|
425 |
|
426 |
|
427 | var unit = function(value) {
|
428 | var pos = 0;
|
429 | var length = value.length;
|
430 | var code;
|
431 | var nextCode;
|
432 | var nextNextCode;
|
433 |
|
434 | if (length === 0 || !likeNumber(value)) {
|
435 | return false;
|
436 | }
|
437 |
|
438 | code = value.charCodeAt(pos);
|
439 |
|
440 | if (code === plus || code === minus) {
|
441 | pos++;
|
442 | }
|
443 |
|
444 | while (pos < length) {
|
445 | code = value.charCodeAt(pos);
|
446 |
|
447 | if (code < 48 || code > 57) {
|
448 | break;
|
449 | }
|
450 |
|
451 | pos += 1;
|
452 | }
|
453 |
|
454 | code = value.charCodeAt(pos);
|
455 | nextCode = value.charCodeAt(pos + 1);
|
456 |
|
457 | if (code === dot && nextCode >= 48 && nextCode <= 57) {
|
458 | pos += 2;
|
459 |
|
460 | while (pos < length) {
|
461 | code = value.charCodeAt(pos);
|
462 |
|
463 | if (code < 48 || code > 57) {
|
464 | break;
|
465 | }
|
466 |
|
467 | pos += 1;
|
468 | }
|
469 | }
|
470 |
|
471 | code = value.charCodeAt(pos);
|
472 | nextCode = value.charCodeAt(pos + 1);
|
473 | nextNextCode = value.charCodeAt(pos + 2);
|
474 |
|
475 | if (
|
476 | (code === exp || code === EXP) &&
|
477 | ((nextCode >= 48 && nextCode <= 57) ||
|
478 | ((nextCode === plus || nextCode === minus) &&
|
479 | nextNextCode >= 48 &&
|
480 | nextNextCode <= 57))
|
481 | ) {
|
482 | pos += nextCode === plus || nextCode === minus ? 3 : 2;
|
483 |
|
484 | while (pos < length) {
|
485 | code = value.charCodeAt(pos);
|
486 |
|
487 | if (code < 48 || code > 57) {
|
488 | break;
|
489 | }
|
490 |
|
491 | pos += 1;
|
492 | }
|
493 | }
|
494 |
|
495 | return {
|
496 | number: value.slice(0, pos),
|
497 | unit: value.slice(pos)
|
498 | };
|
499 | };
|
500 |
|
501 | var parse = parse$1;
|
502 | var walk = walk$1;
|
503 | var stringify = stringify_1;
|
504 |
|
505 | function ValueParser(value) {
|
506 | if (this instanceof ValueParser) {
|
507 | this.nodes = parse(value);
|
508 | return this;
|
509 | }
|
510 | return new ValueParser(value);
|
511 | }
|
512 |
|
513 | ValueParser.prototype.toString = function() {
|
514 | return Array.isArray(this.nodes) ? stringify(this.nodes) : "";
|
515 | };
|
516 |
|
517 | ValueParser.prototype.walk = function(cb, bubble) {
|
518 | walk(this.nodes, cb, bubble);
|
519 | return this;
|
520 | };
|
521 |
|
522 | ValueParser.unit = unit;
|
523 |
|
524 | ValueParser.walk = walk;
|
525 |
|
526 | ValueParser.stringify = stringify;
|
527 |
|
528 | var lib = ValueParser;
|
529 |
|
530 | exports.lib = lib;
|
531 |
|