1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | var Token = require('./token')
|
13 | , nodes = require('./nodes')
|
14 | , errors = require('./errors')
|
15 | , units = require('./units');
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | exports = module.exports = Lexer;
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | var alias = {
|
28 | 'and': '&&'
|
29 | , 'or': '||'
|
30 | , 'is': '=='
|
31 | , 'isnt': '!='
|
32 | , 'is not': '!='
|
33 | , ':=': '?='
|
34 | };
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | units = units.join('|');
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | var unit = new RegExp('^(-)?(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ')?[ \\t]*');
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | function Lexer(str, options) {
|
57 | options = options || {};
|
58 | this.stash = [];
|
59 | this.indentStack = [];
|
60 | this.indentRe = null;
|
61 | this.lineno = 1;
|
62 | this.column = 1;
|
63 |
|
64 |
|
65 | function comment(str, val, offset, s) {
|
66 | var inComment = s.lastIndexOf('/*', offset) > s.lastIndexOf('*/', offset)
|
67 | , commentIdx = s.lastIndexOf('//', offset)
|
68 | , i = s.lastIndexOf('\n', offset)
|
69 | , double = 0
|
70 | , single = 0;
|
71 |
|
72 | if (~commentIdx && commentIdx > i) {
|
73 | while (i != offset) {
|
74 | if ("'" == s[i]) single ? single-- : single++;
|
75 | if ('"' == s[i]) double ? double-- : double++;
|
76 |
|
77 | if ('/' == s[i] && '/' == s[i + 1]) {
|
78 | inComment = !single && !double;
|
79 | break;
|
80 | }
|
81 | ++i;
|
82 | }
|
83 | }
|
84 |
|
85 | return inComment
|
86 | ? str
|
87 | : val + '\r';
|
88 | };
|
89 |
|
90 |
|
91 | if ('\uFEFF' == str.charAt(0)) str = str.slice(1);
|
92 |
|
93 | this.str = str
|
94 | .replace(/\s+$/, '\n')
|
95 | .replace(/\r\n?/g, '\n')
|
96 | .replace(/\\ *\n/g, '\r')
|
97 | .replace(/([,(:](?!\/\/[^ ])) *(?:\/\/[^\n]*)?\n\s*/g, comment)
|
98 | .replace(/\s*\n[ \t]*([,)])/g, comment);
|
99 | };
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | Lexer.prototype = {
|
106 |
|
107 | |
108 |
|
109 |
|
110 |
|
111 | inspect: function(){
|
112 | var tok
|
113 | , tmp = this.str
|
114 | , buf = [];
|
115 | while ('eos' != (tok = this.next()).type) {
|
116 | buf.push(tok.inspect());
|
117 | }
|
118 | this.str = tmp;
|
119 | return buf.concat(tok.inspect()).join('\n');
|
120 | },
|
121 |
|
122 | |
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | lookahead: function(n){
|
131 | var fetch = n - this.stash.length;
|
132 | while (fetch-- > 0) this.stash.push(this.advance());
|
133 | return this.stash[--n];
|
134 | },
|
135 |
|
136 | |
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 | skip: function(len){
|
144 | var chunk = len[0];
|
145 | len = chunk ? chunk.length : len;
|
146 | this.str = this.str.substr(len);
|
147 | if (chunk) {
|
148 | this.move(chunk);
|
149 | } else {
|
150 | this.column += len;
|
151 | }
|
152 | },
|
153 |
|
154 | |
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 | move: function(str){
|
162 | var lines = str.match(/\n/g)
|
163 | , idx = str.lastIndexOf('\n');
|
164 |
|
165 | if (lines) this.lineno += lines.length;
|
166 | this.column = ~idx
|
167 | ? str.length - idx
|
168 | : this.column + str.length;
|
169 | },
|
170 |
|
171 | |
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 | next: function() {
|
179 | var tok = this.stashed() || this.advance();
|
180 | this.prev = tok;
|
181 | return tok;
|
182 | },
|
183 |
|
184 | |
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 | isPartOfSelector: function() {
|
192 | var tok = this.stash[this.stash.length - 1] || this.prev;
|
193 | switch (tok && tok.type) {
|
194 |
|
195 | case 'color':
|
196 | return 2 == tok.val.raw.length;
|
197 |
|
198 | case '.':
|
199 |
|
200 | case '[':
|
201 | return true;
|
202 | }
|
203 | return false;
|
204 | },
|
205 |
|
206 | |
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | advance: function() {
|
214 | var column = this.column
|
215 | , line = this.lineno
|
216 | , tok = this.eos()
|
217 | || this.null()
|
218 | || this.sep()
|
219 | || this.keyword()
|
220 | || this.urlchars()
|
221 | || this.comment()
|
222 | || this.newline()
|
223 | || this.escaped()
|
224 | || this.important()
|
225 | || this.literal()
|
226 | || this.anonFunc()
|
227 | || this.atrule()
|
228 | || this.function()
|
229 | || this.brace()
|
230 | || this.paren()
|
231 | || this.color()
|
232 | || this.string()
|
233 | || this.unit()
|
234 | || this.namedop()
|
235 | || this.boolean()
|
236 | || this.unicode()
|
237 | || this.ident()
|
238 | || this.op()
|
239 | || this.eol()
|
240 | || this.space()
|
241 | || this.selector();
|
242 | tok.lineno = line;
|
243 | tok.column = column;
|
244 | return tok;
|
245 | },
|
246 |
|
247 | |
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 | peek: function() {
|
255 | return this.lookahead(1);
|
256 | },
|
257 |
|
258 | |
259 |
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 | stashed: function() {
|
266 | return this.stash.shift();
|
267 | },
|
268 |
|
269 | |
270 |
|
271 |
|
272 |
|
273 | eos: function() {
|
274 | if (this.str.length) return;
|
275 | if (this.indentStack.length) {
|
276 | this.indentStack.shift();
|
277 | return new Token('outdent');
|
278 | } else {
|
279 | return new Token('eos');
|
280 | }
|
281 | },
|
282 |
|
283 | |
284 |
|
285 |
|
286 |
|
287 | urlchars: function() {
|
288 | var captures;
|
289 | if (!this.isURL) return;
|
290 | if (captures = /^[\/:@.;?&=*!,<>#%0-9]+/.exec(this.str)) {
|
291 | this.skip(captures);
|
292 | return new Token('literal', new nodes.Literal(captures[0]));
|
293 | }
|
294 | },
|
295 |
|
296 | |
297 |
|
298 |
|
299 |
|
300 | sep: function() {
|
301 | var captures;
|
302 | if (captures = /^;[ \t]*/.exec(this.str)) {
|
303 | this.skip(captures);
|
304 | return new Token(';');
|
305 | }
|
306 | },
|
307 |
|
308 | |
309 |
|
310 |
|
311 |
|
312 | eol: function() {
|
313 | if ('\r' == this.str[0]) {
|
314 | ++this.lineno;
|
315 | this.skip(1);
|
316 | return this.advance();
|
317 | }
|
318 | },
|
319 |
|
320 | |
321 |
|
322 |
|
323 |
|
324 | space: function() {
|
325 | var captures;
|
326 | if (captures = /^([ \t]+)/.exec(this.str)) {
|
327 | this.skip(captures);
|
328 | return new Token('space');
|
329 | }
|
330 | },
|
331 |
|
332 | |
333 |
|
334 |
|
335 |
|
336 | escaped: function() {
|
337 | var captures;
|
338 | if (captures = /^\\(.)[ \t]*/.exec(this.str)) {
|
339 | var c = captures[1];
|
340 | this.skip(captures);
|
341 | return new Token('ident', new nodes.Literal(c));
|
342 | }
|
343 | },
|
344 |
|
345 | |
346 |
|
347 |
|
348 |
|
349 | literal: function() {
|
350 |
|
351 | var captures;
|
352 | if (captures = /^@css[ \t]*\{/.exec(this.str)) {
|
353 | this.skip(captures);
|
354 | var c
|
355 | , braces = 1
|
356 | , css = ''
|
357 | , node;
|
358 | while (c = this.str[0]) {
|
359 | this.str = this.str.substr(1);
|
360 | switch (c) {
|
361 | case '{': ++braces; break;
|
362 | case '}': --braces; break;
|
363 | case '\n': ++this.lineno; break;
|
364 | }
|
365 | css += c;
|
366 | if (!braces) break;
|
367 | }
|
368 | css = css.replace(/\s*}$/, '');
|
369 | node = new nodes.Literal(css);
|
370 | node.css = true;
|
371 | return new Token('literal', node);
|
372 | }
|
373 | },
|
374 |
|
375 | |
376 |
|
377 |
|
378 |
|
379 | important: function() {
|
380 | var captures;
|
381 | if (captures = /^!important[ \t]*/.exec(this.str)) {
|
382 | this.skip(captures);
|
383 | return new Token('ident', new nodes.Literal('!important'));
|
384 | }
|
385 | },
|
386 |
|
387 | |
388 |
|
389 |
|
390 |
|
391 | brace: function() {
|
392 | var captures;
|
393 | if (captures = /^([{}])/.exec(this.str)) {
|
394 | this.skip(1);
|
395 | var brace = captures[1];
|
396 | return new Token(brace, brace);
|
397 | }
|
398 | },
|
399 |
|
400 | |
401 |
|
402 |
|
403 |
|
404 | paren: function() {
|
405 | var captures;
|
406 | if (captures = /^([()])([ \t]*)/.exec(this.str)) {
|
407 | var paren = captures[1];
|
408 | this.skip(captures);
|
409 | if (')' == paren) this.isURL = false;
|
410 | var tok = new Token(paren, paren);
|
411 | tok.space = captures[2];
|
412 | return tok;
|
413 | }
|
414 | },
|
415 |
|
416 | |
417 |
|
418 |
|
419 |
|
420 | null: function() {
|
421 | var captures
|
422 | , tok;
|
423 | if (captures = /^(null)\b[ \t]*/.exec(this.str)) {
|
424 | this.skip(captures);
|
425 | if (this.isPartOfSelector()) {
|
426 | tok = new Token('ident', new nodes.Ident(captures[0]));
|
427 | } else {
|
428 | tok = new Token('null', nodes.null);
|
429 | }
|
430 | return tok;
|
431 | }
|
432 | },
|
433 |
|
434 | |
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 | keyword: function() {
|
444 | var captures
|
445 | , tok;
|
446 | if (captures = /^(return|if|else|unless|for|in)\b[ \t]*/.exec(this.str)) {
|
447 | var keyword = captures[1];
|
448 | this.skip(captures);
|
449 | if (this.isPartOfSelector()) {
|
450 | tok = new Token('ident', new nodes.Ident(captures[0]));
|
451 | } else {
|
452 | tok = new Token(keyword, keyword);
|
453 | }
|
454 | return tok;
|
455 | }
|
456 | },
|
457 |
|
458 | |
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
|
465 |
|
466 |
|
467 |
|
468 |
|
469 | namedop: function() {
|
470 | var captures
|
471 | , tok;
|
472 | if (captures = /^(not|and|or|is a|is defined|isnt|is not|is)(?!-)\b([ \t]*)/.exec(this.str)) {
|
473 | var op = captures[1];
|
474 | this.skip(captures);
|
475 | if (this.isPartOfSelector()) {
|
476 | tok = new Token('ident', new nodes.Ident(captures[0]));
|
477 | } else {
|
478 | op = alias[op] || op;
|
479 | tok = new Token(op, op);
|
480 | }
|
481 | tok.space = captures[2];
|
482 | return tok;
|
483 | }
|
484 | },
|
485 |
|
486 | |
487 |
|
488 |
|
489 |
|
490 |
|
491 |
|
492 |
|
493 |
|
494 |
|
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 |
|
505 |
|
506 |
|
507 |
|
508 |
|
509 |
|
510 |
|
511 |
|
512 |
|
513 |
|
514 |
|
515 |
|
516 |
|
517 |
|
518 |
|
519 |
|
520 |
|
521 |
|
522 |
|
523 | op: function() {
|
524 | var captures;
|
525 | if (captures = /^([.]{1,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])([ \t]*)/.exec(this.str)) {
|
526 | var op = captures[1];
|
527 | this.skip(captures);
|
528 | op = alias[op] || op;
|
529 | var tok = new Token(op, op);
|
530 | tok.space = captures[2];
|
531 | this.isURL = false;
|
532 | return tok;
|
533 | }
|
534 | },
|
535 |
|
536 | |
537 |
|
538 |
|
539 |
|
540 | anonFunc: function() {
|
541 | var tok;
|
542 | if ('@' == this.str[0] && '(' == this.str[1]) {
|
543 | this.skip(2);
|
544 | tok = new Token('function', new nodes.Ident('anonymous'));
|
545 | tok.anonymous = true;
|
546 | return tok;
|
547 | }
|
548 | },
|
549 |
|
550 | |
551 |
|
552 |
|
553 |
|
554 | atrule: function() {
|
555 | var captures;
|
556 | if (captures = /^@(?:-(\w+)-)?([a-zA-Z0-9-_]+)[ \t]*/.exec(this.str)) {
|
557 | this.skip(captures);
|
558 | var vendor = captures[1]
|
559 | , type = captures[2]
|
560 | , tok;
|
561 | switch (type) {
|
562 | case 'require':
|
563 | case 'import':
|
564 | case 'charset':
|
565 | case 'namespace':
|
566 | case 'media':
|
567 | case 'scope':
|
568 | case 'supports':
|
569 | return new Token(type);
|
570 | case 'document':
|
571 | return new Token('-moz-document');
|
572 | case 'block':
|
573 | return new Token('atblock');
|
574 | case 'extend':
|
575 | case 'extends':
|
576 | return new Token('extend');
|
577 | case 'keyframes':
|
578 | return new Token(type, vendor);
|
579 | default:
|
580 | return new Token('atrule', (vendor ? '-' + vendor + '-' + type : type));
|
581 | }
|
582 | }
|
583 | },
|
584 |
|
585 | |
586 |
|
587 |
|
588 |
|
589 | comment: function() {
|
590 |
|
591 | if ('/' == this.str[0] && '/' == this.str[1]) {
|
592 | var end = this.str.indexOf('\n');
|
593 | if (-1 == end) end = this.str.length;
|
594 | this.skip(end);
|
595 | return this.advance();
|
596 | }
|
597 |
|
598 |
|
599 | if ('/' == this.str[0] && '*' == this.str[1]) {
|
600 | var end = this.str.indexOf('*/');
|
601 | if (-1 == end) end = this.str.length;
|
602 | var str = this.str.substr(0, end + 2)
|
603 | , lines = str.split('\n').length - 1
|
604 | , suppress = true
|
605 | , inline = false;
|
606 | this.lineno += lines;
|
607 | this.skip(end + 2);
|
608 |
|
609 | if ('!' == str[2]) {
|
610 | str = str.replace('*!', '*');
|
611 | suppress = false;
|
612 | }
|
613 | if (this.prev && ';' == this.prev.type) inline = true;
|
614 | return new Token('comment', new nodes.Comment(str, suppress, inline));
|
615 | }
|
616 | },
|
617 |
|
618 | |
619 |
|
620 |
|
621 |
|
622 | boolean: function() {
|
623 | var captures;
|
624 | if (captures = /^(true|false)\b([ \t]*)/.exec(this.str)) {
|
625 | var val = nodes.Boolean('true' == captures[1]);
|
626 | this.skip(captures);
|
627 | var tok = new Token('boolean', val);
|
628 | tok.space = captures[2];
|
629 | return tok;
|
630 | }
|
631 | },
|
632 |
|
633 | |
634 |
|
635 |
|
636 |
|
637 | unicode: function() {
|
638 | var captures;
|
639 | if (captures = /^u\+[0-9a-f?]{1,6}(?:-[0-9a-f]{1,6})?/i.exec(this.str)) {
|
640 | this.skip(captures);
|
641 | return new Token('literal', new nodes.Literal(captures[0]));
|
642 | }
|
643 | },
|
644 |
|
645 | |
646 |
|
647 |
|
648 |
|
649 | function: function() {
|
650 | var captures;
|
651 | if (captures = /^(-*[_a-zA-Z$][-\w\d$]*)\(([ \t]*)/.exec(this.str)) {
|
652 | var name = captures[1];
|
653 | this.skip(captures);
|
654 | this.isURL = 'url' == name;
|
655 | var tok = new Token('function', new nodes.Ident(name));
|
656 | tok.space = captures[2];
|
657 | return tok;
|
658 | }
|
659 | },
|
660 |
|
661 | |
662 |
|
663 |
|
664 |
|
665 | ident: function() {
|
666 | var captures;
|
667 | if (captures = /^-*[_a-zA-Z$][-\w\d$]*/.exec(this.str)) {
|
668 | this.skip(captures);
|
669 | return new Token('ident', new nodes.Ident(captures[0]));
|
670 | }
|
671 | },
|
672 |
|
673 | |
674 |
|
675 |
|
676 |
|
677 | newline: function() {
|
678 | var captures, re;
|
679 |
|
680 |
|
681 | if (this.indentRe){
|
682 | captures = this.indentRe.exec(this.str);
|
683 |
|
684 | } else {
|
685 |
|
686 | re = /^\n([\t]*)[ \t]*/;
|
687 | captures = re.exec(this.str);
|
688 |
|
689 |
|
690 | if (captures && !captures[1].length) {
|
691 | re = /^\n([ \t]*)/;
|
692 | captures = re.exec(this.str);
|
693 | }
|
694 |
|
695 |
|
696 | if (captures && captures[1].length) this.indentRe = re;
|
697 | }
|
698 |
|
699 |
|
700 | if (captures) {
|
701 | var tok
|
702 | , indents = captures[1].length;
|
703 |
|
704 | this.skip(captures);
|
705 | if (this.str[0] === ' ' || this.str[0] === '\t') {
|
706 | throw new errors.SyntaxError('Invalid indentation. You can use tabs or spaces to indent, but not both.');
|
707 | }
|
708 |
|
709 |
|
710 | if ('\n' == this.str[0]) return this.advance();
|
711 |
|
712 |
|
713 | if (this.indentStack.length && indents < this.indentStack[0]) {
|
714 | while (this.indentStack.length && this.indentStack[0] > indents) {
|
715 | this.stash.push(new Token('outdent'));
|
716 | this.indentStack.shift();
|
717 | }
|
718 | tok = this.stash.pop();
|
719 |
|
720 | } else if (indents && indents != this.indentStack[0]) {
|
721 | this.indentStack.unshift(indents);
|
722 | tok = new Token('indent');
|
723 |
|
724 | } else {
|
725 | tok = new Token('newline');
|
726 | }
|
727 |
|
728 | return tok;
|
729 | }
|
730 | },
|
731 |
|
732 | |
733 |
|
734 |
|
735 |
|
736 | unit: function() {
|
737 | var captures;
|
738 | if (captures = unit.exec(this.str)) {
|
739 | this.skip(captures);
|
740 | var n = parseFloat(captures[2]);
|
741 | if ('-' == captures[1]) n = -n;
|
742 | var node = new nodes.Unit(n, captures[3]);
|
743 | node.raw = captures[0];
|
744 | return new Token('unit', node);
|
745 | }
|
746 | },
|
747 |
|
748 | |
749 |
|
750 |
|
751 |
|
752 | string: function() {
|
753 | var captures;
|
754 | if (captures = /^("[^"]*"|'[^']*')[ \t]*/.exec(this.str)) {
|
755 | var str = captures[1]
|
756 | , quote = captures[0][0];
|
757 | this.skip(captures);
|
758 | str = str.slice(1,-1).replace(/\\n/g, '\n');
|
759 | return new Token('string', new nodes.String(str, quote));
|
760 | }
|
761 | },
|
762 |
|
763 | |
764 |
|
765 |
|
766 |
|
767 | color: function() {
|
768 | return this.rrggbbaa()
|
769 | || this.rrggbb()
|
770 | || this.rgba()
|
771 | || this.rgb()
|
772 | || this.nn()
|
773 | || this.n()
|
774 | },
|
775 |
|
776 | |
777 |
|
778 |
|
779 |
|
780 | n: function() {
|
781 | var captures;
|
782 | if (captures = /^#([a-fA-F0-9]{1})[ \t]*/.exec(this.str)) {
|
783 | this.skip(captures);
|
784 | var n = parseInt(captures[1] + captures[1], 16)
|
785 | , color = new nodes.RGBA(n, n, n, 1);
|
786 | color.raw = captures[0];
|
787 | return new Token('color', color);
|
788 | }
|
789 | },
|
790 |
|
791 | |
792 |
|
793 |
|
794 |
|
795 | nn: function() {
|
796 | var captures;
|
797 | if (captures = /^#([a-fA-F0-9]{2})[ \t]*/.exec(this.str)) {
|
798 | this.skip(captures);
|
799 | var n = parseInt(captures[1], 16)
|
800 | , color = new nodes.RGBA(n, n, n, 1);
|
801 | color.raw = captures[0];
|
802 | return new Token('color', color);
|
803 | }
|
804 | },
|
805 |
|
806 | |
807 |
|
808 |
|
809 |
|
810 | rgb: function() {
|
811 | var captures;
|
812 | if (captures = /^#([a-fA-F0-9]{3})[ \t]*/.exec(this.str)) {
|
813 | this.skip(captures);
|
814 | var rgb = captures[1]
|
815 | , r = parseInt(rgb[0] + rgb[0], 16)
|
816 | , g = parseInt(rgb[1] + rgb[1], 16)
|
817 | , b = parseInt(rgb[2] + rgb[2], 16)
|
818 | , color = new nodes.RGBA(r, g, b, 1);
|
819 | color.raw = captures[0];
|
820 | return new Token('color', color);
|
821 | }
|
822 | },
|
823 |
|
824 | |
825 |
|
826 |
|
827 |
|
828 | rgba: function() {
|
829 | var captures;
|
830 | if (captures = /^#([a-fA-F0-9]{4})[ \t]*/.exec(this.str)) {
|
831 | this.skip(captures);
|
832 | var rgb = captures[1]
|
833 | , r = parseInt(rgb[0] + rgb[0], 16)
|
834 | , g = parseInt(rgb[1] + rgb[1], 16)
|
835 | , b = parseInt(rgb[2] + rgb[2], 16)
|
836 | , a = parseInt(rgb[3] + rgb[3], 16)
|
837 | , color = new nodes.RGBA(r, g, b, a/255);
|
838 | color.raw = captures[0];
|
839 | return new Token('color', color);
|
840 | }
|
841 | },
|
842 |
|
843 | |
844 |
|
845 |
|
846 |
|
847 | rrggbb: function() {
|
848 | var captures;
|
849 | if (captures = /^#([a-fA-F0-9]{6})[ \t]*/.exec(this.str)) {
|
850 | this.skip(captures);
|
851 | var rgb = captures[1]
|
852 | , r = parseInt(rgb.substr(0, 2), 16)
|
853 | , g = parseInt(rgb.substr(2, 2), 16)
|
854 | , b = parseInt(rgb.substr(4, 2), 16)
|
855 | , color = new nodes.RGBA(r, g, b, 1);
|
856 | color.raw = captures[0];
|
857 | return new Token('color', color);
|
858 | }
|
859 | },
|
860 |
|
861 | |
862 |
|
863 |
|
864 |
|
865 | rrggbbaa: function() {
|
866 | var captures;
|
867 | if (captures = /^#([a-fA-F0-9]{8})[ \t]*/.exec(this.str)) {
|
868 | this.skip(captures);
|
869 | var rgb = captures[1]
|
870 | , r = parseInt(rgb.substr(0, 2), 16)
|
871 | , g = parseInt(rgb.substr(2, 2), 16)
|
872 | , b = parseInt(rgb.substr(4, 2), 16)
|
873 | , a = parseInt(rgb.substr(6, 2), 16)
|
874 | , color = new nodes.RGBA(r, g, b, a/255);
|
875 | color.raw = captures[0];
|
876 | return new Token('color', color);
|
877 | }
|
878 | },
|
879 |
|
880 | |
881 |
|
882 |
|
883 |
|
884 | selector: function() {
|
885 | var captures;
|
886 | if (captures = /^.*?(?=\/\/(?![^\[]*\])|[,\n{])/.exec(this.str)) {
|
887 | var selector = captures[0];
|
888 | this.skip(captures);
|
889 | return new Token('selector', selector);
|
890 | }
|
891 | }
|
892 | };
|