source: trip-planner-front/node_modules/postcss-values-parser/old-lib/tokenize.js

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

initial commit

  • Property mode set to 100644
File size: 10.1 KB
Line 
1const openBracket = '{'.charCodeAt(0);
2const closeBracket = '}'.charCodeAt(0);
3const openParen = '('.charCodeAt(0);
4const closeParen = ')'.charCodeAt(0);
5const singleQuote = "'".charCodeAt(0);
6const doubleQuote = '"'.charCodeAt(0);
7const backslash = '\\'.charCodeAt(0);
8const slash = '/'.charCodeAt(0);
9const period = '.'.charCodeAt(0);
10const comma = ','.charCodeAt(0);
11const colon = ':'.charCodeAt(0);
12const asterisk = '*'.charCodeAt(0);
13const minus = '-'.charCodeAt(0);
14const plus = '+'.charCodeAt(0);
15const pound = '#'.charCodeAt(0);
16const newline = '\n'.charCodeAt(0);
17const space = ' '.charCodeAt(0);
18const feed = '\f'.charCodeAt(0);
19const tab = '\t'.charCodeAt(0);
20const cr = '\r'.charCodeAt(0);
21const at = '@'.charCodeAt(0);
22const lowerE = 'e'.charCodeAt(0);
23const upperE = 'E'.charCodeAt(0);
24const digit0 = '0'.charCodeAt(0);
25const digit9 = '9'.charCodeAt(0);
26const lowerU = 'u'.charCodeAt(0);
27const upperU = 'U'.charCodeAt(0);
28const atEnd = /[ \n\t\r\{\(\)'"\\;,/]/g;
29const wordEnd = /[ \n\t\r\(\)\{\}\*:;@!&'"\+\|~>,\[\]\\]|\/(?=\*)/g;
30const wordEndNum = /[ \n\t\r\(\)\{\}\*:;@!&'"\-\+\|~>,\[\]\\]|\//g;
31const alphaNum = /^[a-z0-9]/i;
32const unicodeRange = /^[a-f0-9?\-]/i;
33
34const util = require('util');
35
36const TokenizeError = require('./errors/TokenizeError');
37
38module.exports = function tokenize(input, options) {
39 options = options || {};
40
41 const tokens = [];
42
43 const css = input.valueOf();
44
45 const length = css.length;
46
47 let offset = -1;
48
49 let line = 1;
50
51 let pos = 0;
52
53 let parentCount = 0;
54
55 let isURLArg = null;
56
57 let code;
58 let next;
59 let quote;
60 let lines;
61 let last;
62 let content;
63 let escape;
64 let nextLine;
65 let nextOffset;
66
67 let escaped;
68 let escapePos;
69 let nextChar;
70
71 function unclosed(what) {
72 const message = util.format(
73 'Unclosed %s at line: %d, column: %d, token: %d',
74 what,
75 line,
76 pos - offset,
77 pos
78 );
79 throw new TokenizeError(message);
80 }
81
82 function tokenizeError() {
83 const message = util.format(
84 'Syntax error at line: %d, column: %d, token: %d',
85 line,
86 pos - offset,
87 pos
88 );
89 throw new TokenizeError(message);
90 }
91
92 while (pos < length) {
93 code = css.charCodeAt(pos);
94
95 if (code === newline) {
96 offset = pos;
97 line += 1;
98 }
99
100 switch (code) {
101 case newline:
102 case space:
103 case tab:
104 case cr:
105 case feed:
106 next = pos;
107 do {
108 next += 1;
109 code = css.charCodeAt(next);
110 if (code === newline) {
111 offset = next;
112 line += 1;
113 }
114 } while (
115 code === space ||
116 code === newline ||
117 code === tab ||
118 code === cr ||
119 code === feed
120 );
121
122 tokens.push(['space', css.slice(pos, next), line, pos - offset, line, next - offset, pos]);
123
124 pos = next - 1;
125 break;
126
127 case colon:
128 next = pos + 1;
129 tokens.push(['colon', css.slice(pos, next), line, pos - offset, line, next - offset, pos]);
130
131 pos = next - 1;
132 break;
133
134 case comma:
135 next = pos + 1;
136 tokens.push(['comma', css.slice(pos, next), line, pos - offset, line, next - offset, pos]);
137
138 pos = next - 1;
139 break;
140
141 case openBracket:
142 tokens.push(['{', '{', line, pos - offset, line, next - offset, pos]);
143 break;
144
145 case closeBracket:
146 tokens.push(['}', '}', line, pos - offset, line, next - offset, pos]);
147 break;
148
149 case openParen:
150 parentCount++;
151 isURLArg =
152 !isURLArg &&
153 parentCount === 1 &&
154 tokens.length > 0 &&
155 tokens[tokens.length - 1][0] === 'word' &&
156 tokens[tokens.length - 1][1] === 'url';
157 tokens.push(['(', '(', line, pos - offset, line, next - offset, pos]);
158 break;
159
160 case closeParen:
161 parentCount--;
162 isURLArg = !isURLArg && parentCount === 1;
163 tokens.push([')', ')', line, pos - offset, line, next - offset, pos]);
164 break;
165
166 case singleQuote:
167 case doubleQuote:
168 quote = code === singleQuote ? "'" : '"';
169 next = pos;
170 do {
171 escaped = false;
172 next = css.indexOf(quote, next + 1);
173 if (next === -1) {
174 unclosed('quote', quote);
175 }
176 escapePos = next;
177 while (css.charCodeAt(escapePos - 1) === backslash) {
178 escapePos -= 1;
179 escaped = !escaped;
180 }
181 } while (escaped);
182
183 tokens.push([
184 'string',
185 css.slice(pos, next + 1),
186 line,
187 pos - offset,
188 line,
189 next - offset,
190 pos
191 ]);
192 pos = next;
193 break;
194
195 case at:
196 atEnd.lastIndex = pos + 1;
197 atEnd.test(css);
198
199 if (atEnd.lastIndex === 0) {
200 next = css.length - 1;
201 } else {
202 next = atEnd.lastIndex - 2;
203 }
204
205 tokens.push([
206 'atword',
207 css.slice(pos, next + 1),
208 line,
209 pos - offset,
210 line,
211 next - offset,
212 pos
213 ]);
214 pos = next;
215 break;
216
217 case backslash:
218 next = pos;
219 code = css.charCodeAt(next + 1);
220
221 if (
222 escape &&
223 (code !== slash &&
224 code !== space &&
225 code !== newline &&
226 code !== tab &&
227 code !== cr &&
228 code !== feed)
229 ) {
230 next += 1;
231 }
232
233 tokens.push([
234 'word',
235 css.slice(pos, next + 1),
236 line,
237 pos - offset,
238 line,
239 next - offset,
240 pos
241 ]);
242
243 pos = next;
244 break;
245
246 case plus:
247 case minus:
248 case asterisk:
249 next = pos + 1;
250 nextChar = css.slice(pos + 1, next + 1);
251
252 const prevChar = css.slice(pos - 1, pos);
253
254 // if the operator is immediately followed by a word character, then we
255 // have a prefix of some kind, and should fall-through. eg. -webkit
256
257 // look for --* for custom variables
258 if (code === minus && nextChar.charCodeAt(0) === minus) {
259 next++;
260
261 tokens.push(['word', css.slice(pos, next), line, pos - offset, line, next - offset, pos]);
262
263 pos = next - 1;
264 break;
265 }
266
267 tokens.push([
268 'operator',
269 css.slice(pos, next),
270 line,
271 pos - offset,
272 line,
273 next - offset,
274 pos
275 ]);
276
277 pos = next - 1;
278 break;
279
280 default:
281 if (
282 code === slash &&
283 (css.charCodeAt(pos + 1) === asterisk ||
284 (options.loose && !isURLArg && css.charCodeAt(pos + 1) === slash))
285 ) {
286 const isStandardComment = css.charCodeAt(pos + 1) === asterisk;
287
288 if (isStandardComment) {
289 next = css.indexOf('*/', pos + 2) + 1;
290 if (next === 0) {
291 unclosed('comment', '*/');
292 }
293 } else {
294 const newlinePos = css.indexOf('\n', pos + 2);
295
296 next = newlinePos !== -1 ? newlinePos - 1 : length;
297 }
298
299 content = css.slice(pos, next + 1);
300 lines = content.split('\n');
301 last = lines.length - 1;
302
303 if (last > 0) {
304 nextLine = line + last;
305 nextOffset = next - lines[last].length;
306 } else {
307 nextLine = line;
308 nextOffset = offset;
309 }
310
311 tokens.push(['comment', content, line, pos - offset, nextLine, next - nextOffset, pos]);
312
313 offset = nextOffset;
314 line = nextLine;
315 pos = next;
316 } else if (code === pound && !alphaNum.test(css.slice(pos + 1, pos + 2))) {
317 next = pos + 1;
318
319 tokens.push(['#', css.slice(pos, next), line, pos - offset, line, next - offset, pos]);
320
321 pos = next - 1;
322 } else if ((code === lowerU || code === upperU) && css.charCodeAt(pos + 1) === plus) {
323 next = pos + 2;
324
325 do {
326 next += 1;
327 code = css.charCodeAt(next);
328 } while (next < length && unicodeRange.test(css.slice(next, next + 1)));
329
330 tokens.push([
331 'unicoderange',
332 css.slice(pos, next),
333 line,
334 pos - offset,
335 line,
336 next - offset,
337 pos
338 ]);
339 pos = next - 1;
340 }
341 // catch a regular slash, that isn't a comment
342 else if (code === slash) {
343 next = pos + 1;
344
345 tokens.push([
346 'operator',
347 css.slice(pos, next),
348 line,
349 pos - offset,
350 line,
351 next - offset,
352 pos
353 ]);
354
355 pos = next - 1;
356 } else {
357 let regex = wordEnd;
358
359 // we're dealing with a word that starts with a number
360 // those get treated differently
361 if (code >= digit0 && code <= digit9) {
362 regex = wordEndNum;
363 }
364
365 regex.lastIndex = pos + 1;
366 regex.test(css);
367
368 if (regex.lastIndex === 0) {
369 next = css.length - 1;
370 } else {
371 next = regex.lastIndex - 2;
372 }
373
374 // Exponential number notation with minus or plus: 1e-10, 1e+10
375 if (regex === wordEndNum || code === period) {
376 const ncode = css.charCodeAt(next);
377
378 const ncode1 = css.charCodeAt(next + 1);
379
380 const ncode2 = css.charCodeAt(next + 2);
381
382 if (
383 (ncode === lowerE || ncode === upperE) &&
384 (ncode1 === minus || ncode1 === plus) &&
385 (ncode2 >= digit0 && ncode2 <= digit9)
386 ) {
387 wordEndNum.lastIndex = next + 2;
388 wordEndNum.test(css);
389
390 if (wordEndNum.lastIndex === 0) {
391 next = css.length - 1;
392 } else {
393 next = wordEndNum.lastIndex - 2;
394 }
395 }
396 }
397
398 tokens.push([
399 'word',
400 css.slice(pos, next + 1),
401 line,
402 pos - offset,
403 line,
404 next - offset,
405 pos
406 ]);
407 pos = next;
408 }
409 break;
410 }
411
412 pos++;
413 }
414
415 return tokens;
416};
Note: See TracBrowser for help on using the repository browser.