source: imaps-frontend/node_modules/clean-css/lib/tokenizer/tokenize.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 29.7 KB
Line 
1var Marker = require('./marker');
2var Token = require('./token');
3
4var formatPosition = require('../utils/format-position');
5
6var Level = {
7 BLOCK: 'block',
8 COMMENT: 'comment',
9 DOUBLE_QUOTE: 'double-quote',
10 RULE: 'rule',
11 SINGLE_QUOTE: 'single-quote'
12};
13
14var AT_RULES = [
15 '@charset',
16 '@import'
17];
18
19var BLOCK_RULES = [
20 '@-moz-document',
21 '@document',
22 '@-moz-keyframes',
23 '@-ms-keyframes',
24 '@-o-keyframes',
25 '@-webkit-keyframes',
26 '@keyframes',
27 '@media',
28 '@supports',
29 '@container',
30 '@layer'
31];
32
33var IGNORE_END_COMMENT_PATTERN = /\/\* clean-css ignore:end \*\/$/;
34var IGNORE_START_COMMENT_PATTERN = /^\/\* clean-css ignore:start \*\//;
35
36var PAGE_MARGIN_BOXES = [
37 '@bottom-center',
38 '@bottom-left',
39 '@bottom-left-corner',
40 '@bottom-right',
41 '@bottom-right-corner',
42 '@left-bottom',
43 '@left-middle',
44 '@left-top',
45 '@right-bottom',
46 '@right-middle',
47 '@right-top',
48 '@top-center',
49 '@top-left',
50 '@top-left-corner',
51 '@top-right',
52 '@top-right-corner'
53];
54
55var EXTRA_PAGE_BOXES = [
56 '@footnote',
57 '@footnotes',
58 '@left',
59 '@page-float-bottom',
60 '@page-float-top',
61 '@right'
62];
63
64var REPEAT_PATTERN = /^\[\s{0,31}\d+\s{0,31}\]$/;
65var TAIL_BROKEN_VALUE_PATTERN = /([^}])\}*$/;
66var RULE_WORD_SEPARATOR_PATTERN = /[\s(]/;
67
68function tokenize(source, externalContext) {
69 var internalContext = {
70 level: Level.BLOCK,
71 position: {
72 source: externalContext.source || undefined,
73 line: 1,
74 column: 0,
75 index: 0
76 }
77 };
78
79 return intoTokens(source, externalContext, internalContext, false);
80}
81
82function intoTokens(source, externalContext, internalContext, isNested) {
83 var allTokens = [];
84 var newTokens = allTokens;
85 var lastToken;
86 var ruleToken;
87 var ruleTokens = [];
88 var propertyToken;
89 var metadata;
90 var metadatas = [];
91 var level = internalContext.level;
92 var levels = [];
93 var buffer = [];
94 var buffers = [];
95 var isBufferEmpty = true;
96 var serializedBuffer;
97 var serializedBufferPart;
98 var roundBracketLevel = 0;
99 var isQuoted;
100 var isSpace;
101 var isNewLineNix;
102 var isNewLineWin;
103 var isCarriageReturn;
104 var isCommentStart;
105 var wasCommentStart = false;
106 var isCommentEnd;
107 var wasCommentEnd = false;
108 var isCommentEndMarker;
109 var isEscaped;
110 var wasEscaped = false;
111 var characterWithNoSpecialMeaning;
112 var isPreviousDash = false;
113 var isVariable = false;
114 var isRaw = false;
115 var seekingValue = false;
116 var seekingPropertyBlockClosing = false;
117 var position = internalContext.position;
118 var lastCommentStartAt;
119
120 for (; position.index < source.length; position.index++) {
121 var character = source[position.index];
122
123 isQuoted = level == Level.SINGLE_QUOTE || level == Level.DOUBLE_QUOTE;
124 isSpace = character == Marker.SPACE || character == Marker.TAB;
125 isNewLineNix = character == Marker.NEW_LINE_NIX;
126 isNewLineWin = character == Marker.NEW_LINE_NIX
127 && source[position.index - 1] == Marker.CARRIAGE_RETURN;
128 isCarriageReturn = character == Marker.CARRIAGE_RETURN
129 && source[position.index + 1] && source[position.index + 1] != Marker.NEW_LINE_NIX;
130 isCommentStart = !wasCommentEnd
131 && level != Level.COMMENT && !isQuoted
132 && character == Marker.ASTERISK && source[position.index - 1] == Marker.FORWARD_SLASH;
133 isCommentEndMarker = !wasCommentStart
134 && !isQuoted && character == Marker.FORWARD_SLASH
135 && source[position.index - 1] == Marker.ASTERISK;
136 isCommentEnd = level == Level.COMMENT && isCommentEndMarker;
137 characterWithNoSpecialMeaning = !isSpace && !isCarriageReturn && (character >= 'A' && character <= 'Z' || character >= 'a' && character <= 'z' || character >= '0' && character <= '9' || character == '-');
138 isVariable = isVariable || (level != Level.COMMENT && !seekingValue && isPreviousDash && character === '-' && buffer.length === 1);
139 isPreviousDash = character === '-';
140 roundBracketLevel = Math.max(roundBracketLevel, 0);
141
142 metadata = isBufferEmpty
143 ? [position.line, position.column, position.source]
144 : metadata;
145
146 if (isEscaped) {
147 // previous character was a backslash
148 buffer.push(character);
149 isBufferEmpty = false;
150 } else if (characterWithNoSpecialMeaning) {
151 // it's just an alphanumeric character or a hyphen (part of any rule or property name) so let's end it quickly
152 buffer.push(character);
153 isBufferEmpty = false;
154 } else if ((isSpace || isNewLineNix && !isNewLineWin) && (isQuoted || level == Level.COMMENT)) {
155 buffer.push(character);
156 isBufferEmpty = false;
157 } else if ((isSpace || isNewLineNix && !isNewLineWin) && isBufferEmpty) {
158 // noop
159 } else if (!isCommentEnd && level == Level.COMMENT) {
160 buffer.push(character);
161 isBufferEmpty = false;
162 } else if (!isCommentStart && !isCommentEnd && isRaw) {
163 buffer.push(character);
164 isBufferEmpty = false;
165 } else if (isCommentStart
166 && isVariable
167 && (level == Level.BLOCK || level == Level.RULE) && buffer.length > 1) {
168 // comment start within a variable, e.g. var(/*<--
169 buffer.push(character);
170 isBufferEmpty = false;
171
172 levels.push(level);
173 level = Level.COMMENT;
174 } else if (isCommentStart && (level == Level.BLOCK || level == Level.RULE) && buffer.length > 1) {
175 // comment start within block preceded by some content, e.g. div/*<--
176 metadatas.push(metadata);
177 buffer.push(character);
178 buffers.push(buffer.slice(0, -2));
179 isBufferEmpty = false;
180
181 buffer = buffer.slice(-2);
182 metadata = [position.line, position.column - 1, position.source];
183
184 levels.push(level);
185 level = Level.COMMENT;
186 } else if (isCommentStart) {
187 // comment start, e.g. /*<--
188 levels.push(level);
189 level = Level.COMMENT;
190 buffer.push(character);
191 isBufferEmpty = false;
192 } else if (isCommentEnd && isVariable) {
193 // comment end within a variable, e.g. var(/*!*/<--
194 buffer.push(character);
195 level = levels.pop();
196 } else if (isCommentEnd && isIgnoreStartComment(buffer)) {
197 // ignore:start comment end, e.g. /* clean-css ignore:start */<--
198 serializedBuffer = buffer.join('').trim() + character;
199 lastToken = [
200 Token.COMMENT,
201 serializedBuffer,
202 [originalMetadata(metadata, serializedBuffer, externalContext)]
203 ];
204 newTokens.push(lastToken);
205
206 isRaw = true;
207 metadata = metadatas.pop() || null;
208 buffer = buffers.pop() || [];
209 isBufferEmpty = buffer.length === 0;
210 } else if (isCommentEnd && isIgnoreEndComment(buffer)) {
211 // ignore:start comment end, e.g. /* clean-css ignore:end */<--
212 serializedBuffer = buffer.join('') + character;
213 lastCommentStartAt = serializedBuffer.lastIndexOf(Marker.FORWARD_SLASH + Marker.ASTERISK);
214
215 serializedBufferPart = serializedBuffer.substring(0, lastCommentStartAt);
216 lastToken = [
217 Token.RAW,
218 serializedBufferPart,
219 [originalMetadata(metadata, serializedBufferPart, externalContext)]
220 ];
221 newTokens.push(lastToken);
222
223 serializedBufferPart = serializedBuffer.substring(lastCommentStartAt);
224 metadata = [position.line, position.column - serializedBufferPart.length + 1, position.source];
225 lastToken = [
226 Token.COMMENT,
227 serializedBufferPart,
228 [originalMetadata(metadata, serializedBufferPart, externalContext)]
229 ];
230 newTokens.push(lastToken);
231
232 isRaw = false;
233 level = levels.pop();
234 metadata = metadatas.pop() || null;
235 buffer = buffers.pop() || [];
236 isBufferEmpty = buffer.length === 0;
237 } else if (isCommentEnd) {
238 // comment end, e.g. /* comment */<--
239 serializedBuffer = buffer.join('').trim() + character;
240 lastToken = [
241 Token.COMMENT,
242 serializedBuffer,
243 [originalMetadata(metadata, serializedBuffer, externalContext)]
244 ];
245 newTokens.push(lastToken);
246
247 level = levels.pop();
248 metadata = metadatas.pop() || null;
249 buffer = buffers.pop() || [];
250 isBufferEmpty = buffer.length === 0;
251 } else if (isCommentEndMarker && source[position.index + 1] != Marker.ASTERISK) {
252 externalContext.warnings.push('Unexpected \'*/\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
253 buffer = [];
254 isBufferEmpty = true;
255 } else if (character == Marker.SINGLE_QUOTE && !isQuoted) {
256 // single quotation start, e.g. a[href^='https<--
257 levels.push(level);
258 level = Level.SINGLE_QUOTE;
259 buffer.push(character);
260 isBufferEmpty = false;
261 } else if (character == Marker.SINGLE_QUOTE && level == Level.SINGLE_QUOTE) {
262 // single quotation end, e.g. a[href^='https'<--
263 level = levels.pop();
264 buffer.push(character);
265 isBufferEmpty = false;
266 } else if (character == Marker.DOUBLE_QUOTE && !isQuoted) {
267 // double quotation start, e.g. a[href^="<--
268 levels.push(level);
269 level = Level.DOUBLE_QUOTE;
270 buffer.push(character);
271 isBufferEmpty = false;
272 } else if (character == Marker.DOUBLE_QUOTE && level == Level.DOUBLE_QUOTE) {
273 // double quotation end, e.g. a[href^="https"<--
274 level = levels.pop();
275 buffer.push(character);
276 isBufferEmpty = false;
277 } else if (character != Marker.CLOSE_ROUND_BRACKET
278 && character != Marker.OPEN_ROUND_BRACKET
279 && level != Level.COMMENT && !isQuoted && roundBracketLevel > 0) {
280 // character inside any function, e.g. hsla(.<--
281 buffer.push(character);
282 isBufferEmpty = false;
283 } else if (character == Marker.OPEN_ROUND_BRACKET
284 && !isQuoted && level != Level.COMMENT
285 && !seekingValue) {
286 // round open bracket, e.g. @import url(<--
287 buffer.push(character);
288 isBufferEmpty = false;
289
290 roundBracketLevel++;
291 } else if (character == Marker.CLOSE_ROUND_BRACKET
292 && !isQuoted
293 && level != Level.COMMENT
294 && !seekingValue) {
295 // round open bracket, e.g. @import url(test.css)<--
296 buffer.push(character);
297 isBufferEmpty = false;
298
299 roundBracketLevel--;
300 } else if (character == Marker.SEMICOLON && level == Level.BLOCK && buffer[0] == Marker.AT) {
301 // semicolon ending rule at block level, e.g. @import '...';<--
302 serializedBuffer = buffer.join('').trim();
303 allTokens.push([
304 Token.AT_RULE,
305 serializedBuffer,
306 [originalMetadata(metadata, serializedBuffer, externalContext)]
307 ]);
308
309 buffer = [];
310 isBufferEmpty = true;
311 } else if (character == Marker.COMMA && level == Level.BLOCK && ruleToken) {
312 // comma separator at block level, e.g. a,div,<--
313 serializedBuffer = buffer.join('').trim();
314 ruleToken[1].push([
315 tokenScopeFrom(ruleToken[0]),
316 serializedBuffer,
317 [originalMetadata(metadata, serializedBuffer, externalContext, ruleToken[1].length)]
318 ]);
319
320 buffer = [];
321 isBufferEmpty = true;
322 } else if (character == Marker.COMMA && level == Level.BLOCK && tokenTypeFrom(buffer) == Token.AT_RULE) {
323 // comma separator at block level, e.g. @import url(...) screen,<--
324 // keep iterating as end semicolon will create the token
325 buffer.push(character);
326 isBufferEmpty = false;
327 } else if (character == Marker.COMMA && level == Level.BLOCK) {
328 // comma separator at block level, e.g. a,<--
329 ruleToken = [tokenTypeFrom(buffer), [], []];
330 serializedBuffer = buffer.join('').trim();
331 ruleToken[1].push([
332 tokenScopeFrom(ruleToken[0]),
333 serializedBuffer,
334 [originalMetadata(metadata, serializedBuffer, externalContext, 0)]
335 ]);
336
337 buffer = [];
338 isBufferEmpty = true;
339 } else if (character == Marker.OPEN_CURLY_BRACKET
340 && level == Level.BLOCK
341 && ruleToken
342 && ruleToken[0] == Token.NESTED_BLOCK) {
343 // open brace opening at-rule at block level, e.g. @media{<--
344 serializedBuffer = buffer.join('').trim();
345 ruleToken[1].push([
346 Token.NESTED_BLOCK_SCOPE,
347 serializedBuffer,
348 [originalMetadata(metadata, serializedBuffer, externalContext)]
349 ]);
350 allTokens.push(ruleToken);
351
352 levels.push(level);
353 position.column++;
354 position.index++;
355 buffer = [];
356 isBufferEmpty = true;
357
358 ruleToken[2] = intoTokens(source, externalContext, internalContext, true);
359 ruleToken = null;
360 } else if (character == Marker.OPEN_CURLY_BRACKET
361 && level == Level.BLOCK
362 && tokenTypeFrom(buffer) == Token.NESTED_BLOCK) {
363 // open brace opening at-rule at block level, e.g. @media{<--
364 serializedBuffer = buffer.join('').trim();
365 ruleToken = ruleToken || [Token.NESTED_BLOCK, [], []];
366 ruleToken[1].push([
367 Token.NESTED_BLOCK_SCOPE,
368 serializedBuffer,
369 [originalMetadata(metadata, serializedBuffer, externalContext)]
370 ]);
371 allTokens.push(ruleToken);
372
373 levels.push(level);
374 position.column++;
375 position.index++;
376 buffer = [];
377 isBufferEmpty = true;
378 isVariable = false;
379
380 ruleToken[2] = intoTokens(source, externalContext, internalContext, true);
381 ruleToken = null;
382 } else if (character == Marker.OPEN_CURLY_BRACKET && level == Level.BLOCK) {
383 // open brace opening rule at block level, e.g. div{<--
384 serializedBuffer = buffer.join('').trim();
385 ruleToken = ruleToken || [tokenTypeFrom(buffer), [], []];
386 ruleToken[1].push([
387 tokenScopeFrom(ruleToken[0]),
388 serializedBuffer,
389 [originalMetadata(metadata, serializedBuffer, externalContext, ruleToken[1].length)]
390 ]);
391 newTokens = ruleToken[2];
392 allTokens.push(ruleToken);
393
394 levels.push(level);
395 level = Level.RULE;
396 buffer = [];
397 isBufferEmpty = true;
398 } else if (character == Marker.OPEN_CURLY_BRACKET && level == Level.RULE && seekingValue) {
399 // open brace opening rule at rule level, e.g. div{--variable:{<--
400 ruleTokens.push(ruleToken);
401 ruleToken = [Token.PROPERTY_BLOCK, []];
402 propertyToken.push(ruleToken);
403 newTokens = ruleToken[1];
404
405 levels.push(level);
406 level = Level.RULE;
407 seekingValue = false;
408 } else if (character == Marker.OPEN_CURLY_BRACKET && level == Level.RULE && isPageMarginBox(buffer)) {
409 // open brace opening page-margin box at rule level, e.g. @page{@top-center{<--
410 serializedBuffer = buffer.join('').trim();
411 ruleTokens.push(ruleToken);
412 ruleToken = [Token.AT_RULE_BLOCK, [], []];
413 ruleToken[1].push([
414 Token.AT_RULE_BLOCK_SCOPE,
415 serializedBuffer,
416 [originalMetadata(metadata, serializedBuffer, externalContext)]
417 ]);
418 newTokens.push(ruleToken);
419 newTokens = ruleToken[2];
420
421 levels.push(level);
422 level = Level.RULE;
423 buffer = [];
424 isBufferEmpty = true;
425 } else if (character == Marker.COLON && level == Level.RULE && !seekingValue) {
426 // colon at rule level, e.g. a{color:<--
427 serializedBuffer = buffer.join('').trim();
428 propertyToken = [
429 Token.PROPERTY,
430 [
431 Token.PROPERTY_NAME,
432 serializedBuffer,
433 [originalMetadata(metadata, serializedBuffer, externalContext)]
434 ]
435 ];
436 newTokens.push(propertyToken);
437
438 seekingValue = true;
439 buffer = [];
440 isBufferEmpty = true;
441 } else if (character == Marker.SEMICOLON
442 && level == Level.RULE
443 && propertyToken
444 && ruleTokens.length > 0
445 && !isBufferEmpty
446 && buffer[0] == Marker.AT) {
447 // semicolon at rule level for at-rule, e.g. a{--color:{@apply(--other-color);<--
448 serializedBuffer = buffer.join('').trim();
449 ruleToken[1].push([
450 Token.AT_RULE,
451 serializedBuffer,
452 [originalMetadata(metadata, serializedBuffer, externalContext)]
453 ]);
454
455 buffer = [];
456 isBufferEmpty = true;
457 } else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && !isBufferEmpty) {
458 // semicolon at rule level, e.g. a{color:red;<--
459 serializedBuffer = buffer.join('').trim();
460 propertyToken.push([
461 Token.PROPERTY_VALUE,
462 serializedBuffer,
463 [originalMetadata(metadata, serializedBuffer, externalContext)]
464 ]);
465
466 propertyToken = null;
467 seekingValue = false;
468 buffer = [];
469 isBufferEmpty = true;
470 isVariable = false;
471 } else if (character == Marker.SEMICOLON
472 && level == Level.RULE
473 && propertyToken
474 && isBufferEmpty
475 && isVariable
476 && !propertyToken[2]) {
477 // semicolon after empty variable value at rule level, e.g. a{--color: ;<--
478 propertyToken.push([Token.PROPERTY_VALUE, ' ', [originalMetadata(metadata, ' ', externalContext)]]);
479 isVariable = false;
480 propertyToken = null;
481 seekingValue = false;
482 } else if (character == Marker.SEMICOLON && level == Level.RULE && propertyToken && isBufferEmpty) {
483 // semicolon after bracketed value at rule level, e.g. a{color:rgb(...);<--
484 propertyToken = null;
485 seekingValue = false;
486 } else if (character == Marker.SEMICOLON
487 && level == Level.RULE
488 && !isBufferEmpty
489 && buffer[0] == Marker.AT) {
490 // semicolon for at-rule at rule level, e.g. a{@apply(--variable);<--
491 serializedBuffer = buffer.join('');
492 newTokens.push([
493 Token.AT_RULE,
494 serializedBuffer,
495 [originalMetadata(metadata, serializedBuffer, externalContext)]
496 ]);
497
498 seekingValue = false;
499 buffer = [];
500 isBufferEmpty = true;
501 } else if (character == Marker.SEMICOLON && level == Level.RULE && seekingPropertyBlockClosing) {
502 // close brace after a property block at rule level, e.g. a{--custom:{color:red;};<--
503 seekingPropertyBlockClosing = false;
504 buffer = [];
505 isBufferEmpty = true;
506 } else if (character == Marker.SEMICOLON && level == Level.RULE && isBufferEmpty) {
507 // stray semicolon at rule level, e.g. a{;<--
508 // noop
509 } else if (character == Marker.CLOSE_CURLY_BRACKET
510 && level == Level.RULE
511 && propertyToken
512 && seekingValue
513 && !isBufferEmpty && ruleTokens.length > 0) {
514 // close brace at rule level, e.g. a{--color:{color:red}<--
515 serializedBuffer = buffer.join('');
516 propertyToken.push([
517 Token.PROPERTY_VALUE,
518 serializedBuffer,
519 [originalMetadata(metadata, serializedBuffer, externalContext)]
520 ]);
521 propertyToken = null;
522 ruleToken = ruleTokens.pop();
523 newTokens = ruleToken[2];
524
525 level = levels.pop();
526 seekingValue = false;
527 buffer = [];
528 isBufferEmpty = true;
529 } else if (character == Marker.CLOSE_CURLY_BRACKET
530 && level == Level.RULE
531 && propertyToken
532 && !isBufferEmpty
533 && buffer[0] == Marker.AT
534 && ruleTokens.length > 0) {
535 // close brace at rule level for at-rule, e.g. a{--color:{@apply(--other-color)}<--
536 serializedBuffer = buffer.join('');
537 ruleToken[1].push([
538 Token.AT_RULE,
539 serializedBuffer,
540 [originalMetadata(metadata, serializedBuffer, externalContext)]
541 ]);
542 propertyToken = null;
543 ruleToken = ruleTokens.pop();
544 newTokens = ruleToken[2];
545
546 level = levels.pop();
547 seekingValue = false;
548 buffer = [];
549 isBufferEmpty = true;
550 } else if (character == Marker.CLOSE_CURLY_BRACKET
551 && level == Level.RULE
552 && propertyToken
553 && ruleTokens.length > 0) {
554 // close brace at rule level after space, e.g. a{--color:{color:red }<--
555 propertyToken = null;
556 ruleToken = ruleTokens.pop();
557 newTokens = ruleToken[2];
558
559 level = levels.pop();
560 seekingValue = false;
561 } else if (character == Marker.CLOSE_CURLY_BRACKET
562 && level == Level.RULE
563 && propertyToken
564 && !isBufferEmpty) {
565 // close brace at rule level, e.g. a{color:red}<--
566 serializedBuffer = buffer.join('');
567 propertyToken.push([
568 Token.PROPERTY_VALUE,
569 serializedBuffer,
570 [originalMetadata(metadata, serializedBuffer, externalContext)]
571 ]);
572 propertyToken = null;
573 ruleToken = ruleTokens.pop();
574 newTokens = allTokens;
575
576 level = levels.pop();
577 seekingValue = false;
578 buffer = [];
579 isBufferEmpty = true;
580 } else if (character == Marker.CLOSE_CURLY_BRACKET
581 && level == Level.RULE
582 && !isBufferEmpty
583 && buffer[0] == Marker.AT) {
584 // close brace after at-rule at rule level, e.g. a{@apply(--variable)}<--
585 propertyToken = null;
586 ruleToken = null;
587 serializedBuffer = buffer.join('').trim();
588 newTokens.push([
589 Token.AT_RULE,
590 serializedBuffer,
591 [originalMetadata(metadata, serializedBuffer, externalContext)]
592 ]);
593 newTokens = allTokens;
594
595 level = levels.pop();
596 seekingValue = false;
597 buffer = [];
598 isBufferEmpty = true;
599 } else if (character == Marker.CLOSE_CURLY_BRACKET
600 && level == Level.RULE
601 && levels[levels.length - 1] == Level.RULE) {
602 // close brace after a property block at rule level, e.g. a{--custom:{color:red;}<--
603 propertyToken = null;
604 ruleToken = ruleTokens.pop();
605 newTokens = ruleToken[2];
606
607 level = levels.pop();
608 seekingValue = false;
609 seekingPropertyBlockClosing = true;
610 buffer = [];
611 isBufferEmpty = true;
612 } else if (character == Marker.CLOSE_CURLY_BRACKET
613 && level == Level.RULE
614 && isVariable
615 && propertyToken
616 && !propertyToken[2]) {
617 // close brace after an empty variable declaration inside a rule, e.g. a{--color: }<--
618 propertyToken.push([Token.PROPERTY_VALUE, ' ', [originalMetadata(metadata, ' ', externalContext)]]);
619 isVariable = false;
620 propertyToken = null;
621 ruleToken = null;
622 newTokens = allTokens;
623
624 level = levels.pop();
625 seekingValue = false;
626 isVariable = false;
627 } else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.RULE) {
628 // close brace after a rule, e.g. a{color:red;}<--
629 propertyToken = null;
630 ruleToken = null;
631 newTokens = allTokens;
632
633 level = levels.pop();
634 seekingValue = false;
635 isVariable = false;
636 } else if (character == Marker.CLOSE_CURLY_BRACKET
637 && level == Level.BLOCK
638 && !isNested
639 && position.index <= source.length - 1) {
640 // stray close brace at block level, e.g. a{color:red}color:blue}<--
641 externalContext.warnings.push('Unexpected \'}\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
642 buffer.push(character);
643 isBufferEmpty = false;
644 } else if (character == Marker.CLOSE_CURLY_BRACKET && level == Level.BLOCK) {
645 // close brace at block level, e.g. @media screen {...}<--
646 break;
647 } else if (character == Marker.OPEN_ROUND_BRACKET && level == Level.RULE && seekingValue) {
648 // round open bracket, e.g. a{color:hsla(<--
649 buffer.push(character);
650 isBufferEmpty = false;
651 roundBracketLevel++;
652 } else if (character == Marker.CLOSE_ROUND_BRACKET
653 && level == Level.RULE
654 && seekingValue
655 && roundBracketLevel == 1) {
656 // round close bracket, e.g. a{color:hsla(0,0%,0%)<--
657 buffer.push(character);
658 isBufferEmpty = false;
659 serializedBuffer = buffer.join('').trim();
660 propertyToken.push([
661 Token.PROPERTY_VALUE,
662 serializedBuffer,
663 [originalMetadata(metadata, serializedBuffer, externalContext)]
664 ]);
665
666 roundBracketLevel--;
667 buffer = [];
668 isBufferEmpty = true;
669 isVariable = false;
670 } else if (character == Marker.CLOSE_ROUND_BRACKET && level == Level.RULE && seekingValue) {
671 // round close bracket within other brackets, e.g. a{width:calc((10rem / 2)<--
672 buffer.push(character);
673 isBufferEmpty = false;
674 isVariable = false;
675 roundBracketLevel--;
676 } else if (character == Marker.FORWARD_SLASH
677 && source[position.index + 1] != Marker.ASTERISK
678 && level == Level.RULE
679 && seekingValue
680 && !isBufferEmpty) {
681 // forward slash within a property, e.g. a{background:url(image.png) 0 0/<--
682 serializedBuffer = buffer.join('').trim();
683 propertyToken.push([
684 Token.PROPERTY_VALUE,
685 serializedBuffer,
686 [originalMetadata(metadata, serializedBuffer, externalContext)]
687 ]);
688 propertyToken.push([
689 Token.PROPERTY_VALUE,
690 character,
691 [[position.line, position.column, position.source]]
692 ]);
693
694 buffer = [];
695 isBufferEmpty = true;
696 } else if (character == Marker.FORWARD_SLASH
697 && source[position.index + 1] != Marker.ASTERISK
698 && level == Level.RULE
699 && seekingValue) {
700 // forward slash within a property after space, e.g. a{background:url(image.png) 0 0 /<--
701 propertyToken.push([
702 Token.PROPERTY_VALUE,
703 character,
704 [[position.line, position.column, position.source]]
705 ]);
706
707 buffer = [];
708 isBufferEmpty = true;
709 } else if (character == Marker.COMMA && level == Level.RULE && seekingValue && !isBufferEmpty) {
710 // comma within a property, e.g. a{background:url(image.png),<--
711 serializedBuffer = buffer.join('').trim();
712 propertyToken.push([
713 Token.PROPERTY_VALUE,
714 serializedBuffer,
715 [originalMetadata(metadata, serializedBuffer, externalContext)]
716 ]);
717 propertyToken.push([
718 Token.PROPERTY_VALUE,
719 character,
720 [[position.line, position.column, position.source]]
721 ]);
722
723 buffer = [];
724 isBufferEmpty = true;
725 } else if (character == Marker.COMMA && level == Level.RULE && seekingValue) {
726 // comma within a property after space, e.g. a{background:url(image.png) ,<--
727 propertyToken.push([
728 Token.PROPERTY_VALUE,
729 character,
730 [[position.line, position.column, position.source]]
731 ]);
732
733 buffer = [];
734 isBufferEmpty = true;
735 } else if (character == Marker.CLOSE_SQUARE_BRACKET
736 && propertyToken
737 && propertyToken.length > 1
738 && !isBufferEmpty
739 && isRepeatToken(buffer)) {
740 buffer.push(character);
741 serializedBuffer = buffer.join('').trim();
742 propertyToken[propertyToken.length - 1][1] += serializedBuffer;
743
744 buffer = [];
745 isBufferEmpty = true;
746 } else if ((isSpace || (isNewLineNix && !isNewLineWin))
747 && level == Level.RULE
748 && seekingValue
749 && propertyToken
750 && !isBufferEmpty) {
751 // space or *nix newline within property, e.g. a{margin:0 <--
752 serializedBuffer = buffer.join('').trim();
753 propertyToken.push([
754 Token.PROPERTY_VALUE,
755 serializedBuffer,
756 [originalMetadata(metadata, serializedBuffer, externalContext)]
757 ]);
758
759 buffer = [];
760 isBufferEmpty = true;
761 } else if (isNewLineWin && level == Level.RULE && seekingValue && propertyToken && buffer.length > 1) {
762 // win newline within property, e.g. a{margin:0\r\n<--
763 serializedBuffer = buffer.join('').trim();
764 propertyToken.push([
765 Token.PROPERTY_VALUE,
766 serializedBuffer,
767 [originalMetadata(metadata, serializedBuffer, externalContext)]
768 ]);
769
770 buffer = [];
771 isBufferEmpty = true;
772 } else if (isNewLineWin && level == Level.RULE && seekingValue) {
773 // win newline
774 buffer = [];
775 isBufferEmpty = true;
776 } else if (isNewLineWin && buffer.length == 1) {
777 // ignore windows newline which is composed of two characters
778 buffer.pop();
779 isBufferEmpty = buffer.length === 0;
780 } else if (!isBufferEmpty || !isSpace && !isNewLineNix && !isNewLineWin && !isCarriageReturn) {
781 // any character
782 buffer.push(character);
783 isBufferEmpty = false;
784 }
785
786 wasEscaped = isEscaped;
787 isEscaped = !wasEscaped && character == Marker.BACK_SLASH;
788 wasCommentStart = isCommentStart;
789 wasCommentEnd = isCommentEnd;
790
791 position.line = (isNewLineWin || isNewLineNix || isCarriageReturn) ? position.line + 1 : position.line;
792 position.column = (isNewLineWin || isNewLineNix || isCarriageReturn) ? 0 : position.column + 1;
793 }
794
795 if (seekingValue) {
796 externalContext.warnings.push('Missing \'}\' at ' + formatPosition([position.line, position.column, position.source]) + '.');
797 }
798
799 if (seekingValue && buffer.length > 0) {
800 serializedBuffer = buffer.join('').trimRight().replace(TAIL_BROKEN_VALUE_PATTERN, '$1').trimRight();
801 propertyToken.push([
802 Token.PROPERTY_VALUE,
803 serializedBuffer,
804 [originalMetadata(metadata, serializedBuffer, externalContext)]
805 ]);
806
807 buffer = [];
808 }
809
810 if (buffer.length > 0) {
811 externalContext.warnings.push('Invalid character(s) \'' + buffer.join('') + '\' at ' + formatPosition(metadata) + '. Ignoring.');
812 }
813
814 return allTokens;
815}
816
817function isIgnoreStartComment(buffer) {
818 return IGNORE_START_COMMENT_PATTERN.test(buffer.join('') + Marker.FORWARD_SLASH);
819}
820
821function isIgnoreEndComment(buffer) {
822 return IGNORE_END_COMMENT_PATTERN.test(buffer.join('') + Marker.FORWARD_SLASH);
823}
824
825function originalMetadata(metadata, value, externalContext, selectorFallbacks) {
826 var source = metadata[2];
827
828 return externalContext.inputSourceMapTracker.isTracking(source)
829 ? externalContext.inputSourceMapTracker.originalPositionFor(metadata, value.length, selectorFallbacks)
830 : metadata;
831}
832
833function tokenTypeFrom(buffer) {
834 var isAtRule = buffer[0] == Marker.AT || buffer[0] == Marker.UNDERSCORE;
835 var ruleWord = buffer.join('').split(RULE_WORD_SEPARATOR_PATTERN)[0];
836
837 if (isAtRule && BLOCK_RULES.indexOf(ruleWord) > -1) {
838 return Token.NESTED_BLOCK;
839 } if (isAtRule && AT_RULES.indexOf(ruleWord) > -1) {
840 return Token.AT_RULE;
841 } if (isAtRule) {
842 return Token.AT_RULE_BLOCK;
843 }
844 return Token.RULE;
845}
846
847function tokenScopeFrom(tokenType) {
848 if (tokenType == Token.RULE) {
849 return Token.RULE_SCOPE;
850 } if (tokenType == Token.NESTED_BLOCK) {
851 return Token.NESTED_BLOCK_SCOPE;
852 } if (tokenType == Token.AT_RULE_BLOCK) {
853 return Token.AT_RULE_BLOCK_SCOPE;
854 }
855}
856
857function isPageMarginBox(buffer) {
858 var serializedBuffer = buffer.join('').trim();
859
860 return PAGE_MARGIN_BOXES.indexOf(serializedBuffer) > -1 || EXTRA_PAGE_BOXES.indexOf(serializedBuffer) > -1;
861}
862
863function isRepeatToken(buffer) {
864 return REPEAT_PATTERN.test(buffer.join('') + Marker.CLOSE_SQUARE_BRACKET);
865}
866
867module.exports = tokenize;
Note: See TracBrowser for help on using the repository browser.