1 var openParentheses = "(".charCodeAt(0);
2 var closeParentheses = ")".charCodeAt(0);
3 var singleQuote = "'".charCodeAt(0);
4 var doubleQuote = '"'.charCodeAt(0);
5 var backslash = "\\".charCodeAt(0);
6 var slash = "/".charCodeAt(0);
7 var comma = ",".charCodeAt(0);
8 var colon = ":".charCodeAt(0);
9 var star = "*".charCodeAt(0);
11 module.exports = function(input) {
15 var next, quote, prev, token, escape, escapePos, whitespacePos;
17 var code = value.charCodeAt(pos);
18 var max = value.length;
19 var stack = [{ nodes: tokens }];
33 code = value.charCodeAt(next);
35 token = value.slice(pos, next);
37 prev = tokens[tokens.length - 1];
38 if (code === closeParentheses && balanced) {
40 } else if (prev && prev.type === "div") {
45 (code === slash && value.charCodeAt(next + 1) !== star)
59 } else if (code === singleQuote || code === doubleQuote) {
61 quote = code === singleQuote ? "'" : '"';
69 next = value.indexOf(quote, next + 1);
72 while (value.charCodeAt(escapePos - 1) === backslash) {
78 next = value.length - 1;
79 token.unclosed = true;
82 token.value = value.slice(pos + 1, next);
86 code = value.charCodeAt(pos);
89 } else if (code === slash && value.charCodeAt(pos + 1) === star) {
95 next = value.indexOf("*/", pos);
97 token.unclosed = true;
101 token.value = value.slice(pos + 2, next);
105 code = value.charCodeAt(pos);
108 } else if (code === slash || code === comma || code === colon) {
113 sourceIndex: pos - before.length,
121 code = value.charCodeAt(pos);
124 } else if (openParentheses === code) {
125 // Whitespaces after open parentheses
129 code = value.charCodeAt(next);
130 } while (code <= 32);
133 sourceIndex: pos - name.length,
135 before: value.slice(pos + 1, next)
139 if (name === "url" && code !== singleQuote && code !== doubleQuote) {
143 next = value.indexOf(")", next + 1);
146 while (value.charCodeAt(escapePos - 1) === backslash) {
152 next = value.length - 1;
153 token.unclosed = true;
156 // Whitespaces before closed
157 whitespacePos = next;
160 code = value.charCodeAt(whitespacePos);
161 } while (code <= 32);
162 if (pos !== whitespacePos + 1) {
167 value: value.slice(pos, whitespacePos + 1)
173 if (token.unclosed && whitespacePos + 1 !== next) {
177 sourceIndex: whitespacePos + 1,
178 value: value.slice(whitespacePos + 1, next)
181 token.after = value.slice(whitespacePos + 1, next);
184 code = value.charCodeAt(pos);
191 tokens = token.nodes = [];
197 } else if (closeParentheses === code && balanced) {
199 code = value.charCodeAt(pos);
201 parent.after = after;
205 parent = stack[balanced];
206 tokens = parent.nodes;
212 if (code === backslash) {
216 code = value.charCodeAt(next);
221 code === singleQuote ||
222 code === doubleQuote ||
226 code === openParentheses ||
227 (code === closeParentheses && balanced)
230 token = value.slice(pos, next);
232 if (openParentheses === code) {
246 for (pos = stack.length - 1; pos; pos -= 1) {
247 stack[pos].unclosed = true;
250 return stack[0].nodes;