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