source: trip-planner-front/node_modules/postcss-value-parser/lib/parse.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 7.4 KB
Line 
1var openParentheses = "(".charCodeAt(0);
2var closeParentheses = ")".charCodeAt(0);
3var singleQuote = "'".charCodeAt(0);
4var doubleQuote = '"'.charCodeAt(0);
5var backslash = "\\".charCodeAt(0);
6var slash = "/".charCodeAt(0);
7var comma = ",".charCodeAt(0);
8var colon = ":".charCodeAt(0);
9var star = "*".charCodeAt(0);
10var uLower = "u".charCodeAt(0);
11var uUpper = "U".charCodeAt(0);
12var plus = "+".charCodeAt(0);
13var isUnicodeRange = /^[a-f0-9?-]+$/i;
14
15module.exports = function(input) {
16 var tokens = [];
17 var value = input;
18
19 var next,
20 quote,
21 prev,
22 token,
23 escape,
24 escapePos,
25 whitespacePos,
26 parenthesesOpenPos;
27 var pos = 0;
28 var code = value.charCodeAt(pos);
29 var max = value.length;
30 var stack = [{ nodes: tokens }];
31 var balanced = 0;
32 var parent;
33
34 var name = "";
35 var before = "";
36 var after = "";
37
38 while (pos < max) {
39 // Whitespaces
40 if (code <= 32) {
41 next = pos;
42 do {
43 next += 1;
44 code = value.charCodeAt(next);
45 } while (code <= 32);
46 token = value.slice(pos, next);
47
48 prev = tokens[tokens.length - 1];
49 if (code === closeParentheses && balanced) {
50 after = token;
51 } else if (prev && prev.type === "div") {
52 prev.after = token;
53 } else if (
54 code === comma ||
55 code === colon ||
56 (code === slash &&
57 value.charCodeAt(next + 1) !== star &&
58 (!parent ||
59 (parent && parent.type === "function" && parent.value !== "calc")))
60 ) {
61 before = token;
62 } else {
63 tokens.push({
64 type: "space",
65 sourceIndex: pos,
66 value: token
67 });
68 }
69
70 pos = next;
71
72 // Quotes
73 } else if (code === singleQuote || code === doubleQuote) {
74 next = pos;
75 quote = code === singleQuote ? "'" : '"';
76 token = {
77 type: "string",
78 sourceIndex: pos,
79 quote: quote
80 };
81 do {
82 escape = false;
83 next = value.indexOf(quote, next + 1);
84 if (~next) {
85 escapePos = next;
86 while (value.charCodeAt(escapePos - 1) === backslash) {
87 escapePos -= 1;
88 escape = !escape;
89 }
90 } else {
91 value += quote;
92 next = value.length - 1;
93 token.unclosed = true;
94 }
95 } while (escape);
96 token.value = value.slice(pos + 1, next);
97
98 tokens.push(token);
99 pos = next + 1;
100 code = value.charCodeAt(pos);
101
102 // Comments
103 } else if (code === slash && value.charCodeAt(pos + 1) === star) {
104 token = {
105 type: "comment",
106 sourceIndex: pos
107 };
108
109 next = value.indexOf("*/", pos);
110 if (next === -1) {
111 token.unclosed = true;
112 next = value.length;
113 }
114
115 token.value = value.slice(pos + 2, next);
116 tokens.push(token);
117
118 pos = next + 2;
119 code = value.charCodeAt(pos);
120
121 // Operation within calc
122 } else if (
123 (code === slash || code === star) &&
124 parent &&
125 parent.type === "function" &&
126 parent.value === "calc"
127 ) {
128 token = value[pos];
129 tokens.push({
130 type: "word",
131 sourceIndex: pos - before.length,
132 value: token
133 });
134 pos += 1;
135 code = value.charCodeAt(pos);
136
137 // Dividers
138 } else if (code === slash || code === comma || code === colon) {
139 token = value[pos];
140
141 tokens.push({
142 type: "div",
143 sourceIndex: pos - before.length,
144 value: token,
145 before: before,
146 after: ""
147 });
148 before = "";
149
150 pos += 1;
151 code = value.charCodeAt(pos);
152
153 // Open parentheses
154 } else if (openParentheses === code) {
155 // Whitespaces after open parentheses
156 next = pos;
157 do {
158 next += 1;
159 code = value.charCodeAt(next);
160 } while (code <= 32);
161 parenthesesOpenPos = pos;
162 token = {
163 type: "function",
164 sourceIndex: pos - name.length,
165 value: name,
166 before: value.slice(parenthesesOpenPos + 1, next)
167 };
168 pos = next;
169
170 if (name === "url" && code !== singleQuote && code !== doubleQuote) {
171 next -= 1;
172 do {
173 escape = false;
174 next = value.indexOf(")", next + 1);
175 if (~next) {
176 escapePos = next;
177 while (value.charCodeAt(escapePos - 1) === backslash) {
178 escapePos -= 1;
179 escape = !escape;
180 }
181 } else {
182 value += ")";
183 next = value.length - 1;
184 token.unclosed = true;
185 }
186 } while (escape);
187 // Whitespaces before closed
188 whitespacePos = next;
189 do {
190 whitespacePos -= 1;
191 code = value.charCodeAt(whitespacePos);
192 } while (code <= 32);
193 if (parenthesesOpenPos < whitespacePos) {
194 if (pos !== whitespacePos + 1) {
195 token.nodes = [
196 {
197 type: "word",
198 sourceIndex: pos,
199 value: value.slice(pos, whitespacePos + 1)
200 }
201 ];
202 } else {
203 token.nodes = [];
204 }
205 if (token.unclosed && whitespacePos + 1 !== next) {
206 token.after = "";
207 token.nodes.push({
208 type: "space",
209 sourceIndex: whitespacePos + 1,
210 value: value.slice(whitespacePos + 1, next)
211 });
212 } else {
213 token.after = value.slice(whitespacePos + 1, next);
214 }
215 } else {
216 token.after = "";
217 token.nodes = [];
218 }
219 pos = next + 1;
220 code = value.charCodeAt(pos);
221 tokens.push(token);
222 } else {
223 balanced += 1;
224 token.after = "";
225 tokens.push(token);
226 stack.push(token);
227 tokens = token.nodes = [];
228 parent = token;
229 }
230 name = "";
231
232 // Close parentheses
233 } else if (closeParentheses === code && balanced) {
234 pos += 1;
235 code = value.charCodeAt(pos);
236
237 parent.after = after;
238 after = "";
239 balanced -= 1;
240 stack.pop();
241 parent = stack[balanced];
242 tokens = parent.nodes;
243
244 // Words
245 } else {
246 next = pos;
247 do {
248 if (code === backslash) {
249 next += 1;
250 }
251 next += 1;
252 code = value.charCodeAt(next);
253 } while (
254 next < max &&
255 !(
256 code <= 32 ||
257 code === singleQuote ||
258 code === doubleQuote ||
259 code === comma ||
260 code === colon ||
261 code === slash ||
262 code === openParentheses ||
263 (code === star &&
264 parent &&
265 parent.type === "function" &&
266 parent.value === "calc") ||
267 (code === slash &&
268 parent.type === "function" &&
269 parent.value === "calc") ||
270 (code === closeParentheses && balanced)
271 )
272 );
273 token = value.slice(pos, next);
274
275 if (openParentheses === code) {
276 name = token;
277 } else if (
278 (uLower === token.charCodeAt(0) || uUpper === token.charCodeAt(0)) &&
279 plus === token.charCodeAt(1) &&
280 isUnicodeRange.test(token.slice(2))
281 ) {
282 tokens.push({
283 type: "unicode-range",
284 sourceIndex: pos,
285 value: token
286 });
287 } else {
288 tokens.push({
289 type: "word",
290 sourceIndex: pos,
291 value: token
292 });
293 }
294
295 pos = next;
296 }
297 }
298
299 for (pos = stack.length - 1; pos; pos -= 1) {
300 stack[pos].unclosed = true;
301 }
302
303 return stack[0].nodes;
304};
Note: See TracBrowser for help on using the repository browser.