stylus-source 0.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. data/.DS_Store +0 -0
  2. data/README.md +3 -0
  3. data/lib/.DS_Store +0 -0
  4. data/lib/node_modules/cssom/.idea/CSSOM.iml +9 -0
  5. data/lib/node_modules/cssom/.idea/dictionaries/nv.xml +3 -0
  6. data/lib/node_modules/cssom/.idea/encodings.xml +5 -0
  7. data/lib/node_modules/cssom/.idea/misc.xml +17 -0
  8. data/lib/node_modules/cssom/.idea/modules.xml +9 -0
  9. data/lib/node_modules/cssom/.idea/projectCodeStyle.xml +82 -0
  10. data/lib/node_modules/cssom/.idea/vcs.xml +8 -0
  11. data/lib/node_modules/cssom/.idea/workspace.xml +467 -0
  12. data/lib/node_modules/cssom/.livereload +19 -0
  13. data/lib/node_modules/cssom/Jakefile +37 -0
  14. data/lib/node_modules/cssom/README.mdown +33 -0
  15. data/lib/node_modules/cssom/Rakefile +23 -0
  16. data/lib/node_modules/cssom/docs/.livereload +19 -0
  17. data/lib/node_modules/cssom/docs/bar.css +3 -0
  18. data/lib/node_modules/cssom/docs/demo.css +0 -0
  19. data/lib/node_modules/cssom/docs/foo.css +4 -0
  20. data/lib/node_modules/cssom/docs/parse.html +170 -0
  21. data/lib/node_modules/cssom/docs/parse2.html +431 -0
  22. data/lib/node_modules/cssom/index.html +100 -0
  23. data/lib/node_modules/cssom/lib/CSSImportRule.js +34 -0
  24. data/lib/node_modules/cssom/lib/CSSMediaRule.js +38 -0
  25. data/lib/node_modules/cssom/lib/CSSOM.js +3 -0
  26. data/lib/node_modules/cssom/lib/CSSRule.js +38 -0
  27. data/lib/node_modules/cssom/lib/CSSStyleDeclaration.js +130 -0
  28. data/lib/node_modules/cssom/lib/CSSStyleRule.js +187 -0
  29. data/lib/node_modules/cssom/lib/CSSStyleSheet.js +85 -0
  30. data/lib/node_modules/cssom/lib/MediaList.js +61 -0
  31. data/lib/node_modules/cssom/lib/StyleSheet.js +15 -0
  32. data/lib/node_modules/cssom/lib/clone.js +69 -0
  33. data/lib/node_modules/cssom/lib/index.js +10 -0
  34. data/lib/node_modules/cssom/lib/parse.js +195 -0
  35. data/lib/node_modules/cssom/media.html +17 -0
  36. data/lib/node_modules/cssom/package.json +30 -0
  37. data/lib/node_modules/cssom/plugins/toHTML.js +32 -0
  38. data/lib/node_modules/cssom/server/index.html +22 -0
  39. data/lib/node_modules/cssom/server/index.js +21 -0
  40. data/lib/node_modules/cssom/shorthands.html +21 -0
  41. data/lib/node_modules/cssom/test/CSSStyleDeclaration.test.js +35 -0
  42. data/lib/node_modules/cssom/test/CSSStyleRule.test.js +12 -0
  43. data/lib/node_modules/cssom/test/CSSStyleSheet.test.js +16 -0
  44. data/lib/node_modules/cssom/test/MediaList.test.js +21 -0
  45. data/lib/node_modules/cssom/test/clone.test.js +38 -0
  46. data/lib/node_modules/cssom/test/fixtures/dummy.css +3 -0
  47. data/lib/node_modules/cssom/test/helper.js +97 -0
  48. data/lib/node_modules/cssom/test/index.html +42 -0
  49. data/lib/node_modules/cssom/test/parse.test.js +346 -0
  50. data/lib/node_modules/cssom/test/vendor/qunit.css +189 -0
  51. data/lib/node_modules/cssom/test/vendor/qunit.js +1341 -0
  52. data/lib/node_modules/growl/History.md +16 -0
  53. data/lib/node_modules/growl/Readme.md +74 -0
  54. data/lib/node_modules/growl/lib/growl.js +82 -0
  55. data/lib/node_modules/growl/package.json +6 -0
  56. data/lib/node_modules/growl/test.js +17 -0
  57. data/lib/stylus/colors.js +156 -0
  58. data/lib/stylus/convert/css.js +130 -0
  59. data/lib/stylus/errors.js +58 -0
  60. data/lib/stylus/functions/image.js +120 -0
  61. data/lib/stylus/functions/index.js +722 -0
  62. data/lib/stylus/functions/index.styl +123 -0
  63. data/lib/stylus/functions/url.js +98 -0
  64. data/lib/stylus/lexer.js +728 -0
  65. data/lib/stylus/middleware.js +223 -0
  66. data/lib/stylus/nodes/arguments.js +65 -0
  67. data/lib/stylus/nodes/binop.js +54 -0
  68. data/lib/stylus/nodes/block.js +99 -0
  69. data/lib/stylus/nodes/boolean.js +103 -0
  70. data/lib/stylus/nodes/call.js +57 -0
  71. data/lib/stylus/nodes/charset.js +42 -0
  72. data/lib/stylus/nodes/comment.js +32 -0
  73. data/lib/stylus/nodes/each.js +56 -0
  74. data/lib/stylus/nodes/expression.js +168 -0
  75. data/lib/stylus/nodes/fontface.js +55 -0
  76. data/lib/stylus/nodes/function.js +104 -0
  77. data/lib/stylus/nodes/group.js +79 -0
  78. data/lib/stylus/nodes/hsla.js +256 -0
  79. data/lib/stylus/nodes/ident.js +127 -0
  80. data/lib/stylus/nodes/if.js +55 -0
  81. data/lib/stylus/nodes/import.js +30 -0
  82. data/lib/stylus/nodes/index.js +52 -0
  83. data/lib/stylus/nodes/jsliteral.js +32 -0
  84. data/lib/stylus/nodes/keyframes.js +78 -0
  85. data/lib/stylus/nodes/literal.js +92 -0
  86. data/lib/stylus/nodes/media.js +42 -0
  87. data/lib/stylus/nodes/node.js +209 -0
  88. data/lib/stylus/nodes/null.js +72 -0
  89. data/lib/stylus/nodes/page.js +43 -0
  90. data/lib/stylus/nodes/params.js +72 -0
  91. data/lib/stylus/nodes/property.js +72 -0
  92. data/lib/stylus/nodes/return.js +44 -0
  93. data/lib/stylus/nodes/rgba.js +335 -0
  94. data/lib/stylus/nodes/root.js +50 -0
  95. data/lib/stylus/nodes/selector.js +57 -0
  96. data/lib/stylus/nodes/string.js +120 -0
  97. data/lib/stylus/nodes/ternary.js +51 -0
  98. data/lib/stylus/nodes/unaryop.js +46 -0
  99. data/lib/stylus/nodes/unit.js +207 -0
  100. data/lib/stylus/parser.js +1514 -0
  101. data/lib/stylus/renderer.js +157 -0
  102. data/lib/stylus/source.rb +7 -0
  103. data/lib/stylus/stack/frame.js +66 -0
  104. data/lib/stylus/stack/index.js +146 -0
  105. data/lib/stylus/stack/scope.js +53 -0
  106. data/lib/stylus/stylus.js +102 -0
  107. data/lib/stylus/token.js +53 -0
  108. data/lib/stylus/utils.js +237 -0
  109. data/lib/stylus/visitor/compiler.js +472 -0
  110. data/lib/stylus/visitor/evaluator.js +1070 -0
  111. data/lib/stylus/visitor/index.js +31 -0
  112. data/stylus-source.gemspec +15 -0
  113. metadata +158 -0
@@ -0,0 +1,123 @@
1
+
2
+ vendors = moz webkit official
3
+
4
+ // stringify the given arg
5
+
6
+ -string(arg)
7
+ type(arg) + ' ' + arg
8
+
9
+ // require a color
10
+
11
+ require-color(color)
12
+ unless color is a 'color'
13
+ error('RGB or HSL value expected, got a ' + -string(color))
14
+
15
+ // require a unit
16
+
17
+ require-unit(n)
18
+ unless n is a 'unit'
19
+ error('unit expected, got a ' + -string(n))
20
+
21
+ // require a string
22
+
23
+ require-string(str)
24
+ unless str is a 'string' or str is a 'ident'
25
+ error('string expected, got a ' + -string(str))
26
+
27
+ // apply js Math function
28
+
29
+ math(n, fn)
30
+ require-unit(n)
31
+ require-string(fn)
32
+ -math(n, fn)
33
+
34
+ // adjust the given color's property by amount
35
+
36
+ adjust(color, prop, amount)
37
+ require-color(color)
38
+ require-string(prop)
39
+ require-unit(amount)
40
+ -adjust(color, prop, amount)
41
+
42
+ // Math functions
43
+
44
+ abs(n) { math(n, 'abs') }
45
+ ceil(n) { math(n, 'ceil') }
46
+ floor(n) { math(n, 'floor') }
47
+ round(n) { math(n, 'round') }
48
+ sin(n) { math(n, 'sin') }
49
+ cos(n) { math(n, 'cos') }
50
+ min(a, b) { a < b ? a : b }
51
+ max(a, b) { a > b ? a : b }
52
+ PI = -math-prop('PI')
53
+
54
+ // return the sum of the given numbers
55
+
56
+ sum(nums)
57
+ sum = 0
58
+ sum += n for n in nums
59
+
60
+ // return the average of the given numbers
61
+
62
+ avg(nums)
63
+ sum(nums) / length(nums)
64
+
65
+ // color components
66
+
67
+ alpha(color) { component(hsl(color), 'alpha') }
68
+ hue(color) { component(hsl(color), 'hue') }
69
+ saturation(color) { component(hsl(color), 'saturation') }
70
+ lightness(color) { component(hsl(color), 'lightness') }
71
+
72
+ // check if n is an odd number
73
+
74
+ odd(n)
75
+ 1 == n % 2
76
+
77
+ // check if n is an even number
78
+
79
+ even(n)
80
+ 0 == n % 2
81
+
82
+ // check if color is light
83
+
84
+ light(color)
85
+ lightness(color) >= 50%
86
+
87
+ // check if color is dark
88
+
89
+ dark(color)
90
+ lightness(color) < 50%
91
+
92
+ // desaturate color by amount
93
+
94
+ desaturate(color, amount)
95
+ adjust(color, 'saturation', - amount)
96
+
97
+ // saturate color by amount
98
+
99
+ saturate(color, amount)
100
+ adjust(color, 'saturation', amount)
101
+
102
+ // darken by the given amount
103
+
104
+ darken(color, amount)
105
+ adjust(color, 'lightness', - amount)
106
+
107
+ // lighten by the given amount
108
+
109
+ lighten(color, amount)
110
+ adjust(color, 'lightness', amount)
111
+
112
+ // return the last value in the given expr
113
+
114
+ last(expr)
115
+ expr[length(expr) - 1]
116
+
117
+ // join values with the given delimiter
118
+
119
+ join(delim, vals...)
120
+ buf = ''
121
+ vals = vals[0] if length(vals) == 1
122
+ for val, i in vals
123
+ buf += i ? delim + val : val
@@ -0,0 +1,98 @@
1
+
2
+ /*!
3
+ * Stylus - plugin - url
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var Compiler = require('../visitor/compiler')
13
+ , nodes = require('../nodes')
14
+ , parse = require('url').parse
15
+ , extname = require('path').extname
16
+ , utils = require('../utils')
17
+ , fs = require('fs');
18
+
19
+ /**
20
+ * Mime table.
21
+ */
22
+
23
+ var mimes = {
24
+ '.gif': 'image/gif'
25
+ , '.png': 'image/png'
26
+ , '.jpg': 'image/jpeg'
27
+ , '.jpeg': 'image/jpeg'
28
+ , '.svg': 'image/svg+xml'
29
+ };
30
+
31
+ /**
32
+ * Return a url() function with the given `options`.
33
+ *
34
+ * Options:
35
+ *
36
+ * - `limit` bytesize limit defaulting to 30Kb
37
+ * - `paths` image resolution path(s), merged with general lookup paths
38
+ *
39
+ * Examples:
40
+ *
41
+ * stylus(str)
42
+ * .set('filename', __dirname + '/css/test.styl')
43
+ * .define('url', stylus.url({ paths: [__dirname + '/public'] }))
44
+ * .render(function(err, css){ ... })
45
+ *
46
+ * @param {Object} options
47
+ * @return {Function}
48
+ * @api public
49
+ */
50
+
51
+ module.exports = function(options) {
52
+ options = options || {};
53
+
54
+ var sizeLimit = options.limit || 30000
55
+ , _paths = options.paths || [];
56
+
57
+ function url(url){
58
+ // Compile the url
59
+ var compiler = new Compiler(url);
60
+ compiler.isURL = true;
61
+ var url = url.nodes.map(function(node){
62
+ return compiler.visit(node);
63
+ }).join('');
64
+
65
+ // Parse literal
66
+ var url = parse(url)
67
+ , ext = extname(url.pathname)
68
+ , mime = mimes[ext]
69
+ , literal = new nodes.Literal('url("' + url.href + '")')
70
+ , paths = _paths.concat(this.paths)
71
+ , founds
72
+ , buf;
73
+
74
+ // Not supported
75
+ if (!mime) return literal;
76
+
77
+ // Absolute
78
+ if (url.protocol) return literal;
79
+
80
+ // Lookup
81
+ found = utils.lookup(url.pathname, paths);
82
+
83
+ // Failed to lookup
84
+ if (!found) return literal;
85
+
86
+ // Read data
87
+ buf = fs.readFileSync(found);
88
+
89
+ // To large
90
+ if (buf.length > sizeLimit) return literal;
91
+
92
+ // Encode
93
+ return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + '")');
94
+ };
95
+
96
+ url.raw = true;
97
+ return url;
98
+ };
@@ -0,0 +1,728 @@
1
+
2
+ /*!
3
+ * Stylus - Lexer
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var Token = require('./token')
13
+ , nodes = require('./nodes')
14
+ , errors = require('./errors');
15
+
16
+ /**
17
+ * Operator aliases.
18
+ */
19
+
20
+ var alias = {
21
+ 'and': '&&'
22
+ , 'or': '||'
23
+ , 'is': '=='
24
+ , 'isnt': '!='
25
+ , 'is not': '!='
26
+ , ':=': '?='
27
+ };
28
+
29
+ /**
30
+ * Units.
31
+ */
32
+
33
+ var units = [
34
+ 'em'
35
+ , 'ex'
36
+ , 'px'
37
+ , 'mm'
38
+ , 'cm'
39
+ , 'in'
40
+ , 'pt'
41
+ , 'pc'
42
+ , 'deg'
43
+ , 'rad'
44
+ , 'grad'
45
+ , 'ms'
46
+ , 's'
47
+ , 'Hz'
48
+ , 'kHz'
49
+ , 'rem'
50
+ , '%'].join('|');
51
+
52
+ /**
53
+ * Unit RegExp.
54
+ */
55
+
56
+ var unit = new RegExp('^(-)?(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ')? *');
57
+
58
+ /**
59
+ * Initialize a new `Lexer` with the given `str` and `options`.
60
+ *
61
+ * @param {String} str
62
+ * @param {Object} options
63
+ * @api private
64
+ */
65
+
66
+ var Lexer = module.exports = function Lexer(str, options) {
67
+ options = options || {};
68
+ this.str = str.replace(/\r\n?/g, '\n');
69
+ this.stash = [];
70
+ this.indentStack = [];
71
+ this.indentRe = null;
72
+ this.lineno = 1;
73
+ };
74
+
75
+ /**
76
+ * Lexer prototype.
77
+ */
78
+
79
+ Lexer.prototype = {
80
+
81
+ /**
82
+ * Custom inspect.
83
+ */
84
+
85
+ inspect: function(){
86
+ var tok
87
+ , tmp = this.str
88
+ , buf = [];
89
+ while ('eos' != (tok = this.next()).type) {
90
+ buf.push(tok.inspect());
91
+ }
92
+ this.str = tmp;
93
+ this.prevIndents = 0;
94
+ return buf.concat(tok.inspect()).join('\n');
95
+ },
96
+
97
+ /**
98
+ * Lookahead `n` tokens.
99
+ *
100
+ * @param {Number} n
101
+ * @return {Object}
102
+ * @api private
103
+ */
104
+
105
+ lookahead: function(n){
106
+ var fetch = n - this.stash.length;
107
+ while (fetch-- > 0) this.stash.push(this.advance());
108
+ return this.stash[--n];
109
+ },
110
+
111
+ /**
112
+ * Consume the given `len`.
113
+ *
114
+ * @param {Number|Array} len
115
+ * @api private
116
+ */
117
+
118
+ skip: function(len){
119
+ this.str = this.str.substr(Array.isArray(len)
120
+ ? len[0].length
121
+ : len);
122
+ },
123
+
124
+ /**
125
+ * Fetch next token including those stashed by peek.
126
+ *
127
+ * @return {Token}
128
+ * @api private
129
+ */
130
+
131
+ next: function() {
132
+ var tok = this.stashed() || this.advance();
133
+ switch (tok.type) {
134
+ case 'newline':
135
+ case 'indent':
136
+ ++this.lineno;
137
+ break;
138
+ case 'outdent':
139
+ if ('outdent' != this.prev.type) ++this.lineno;
140
+ }
141
+ this.prev = tok;
142
+ tok.lineno = this.lineno;
143
+ return tok;
144
+ },
145
+
146
+ /**
147
+ * Fetch next token.
148
+ *
149
+ * @return {Token}
150
+ * @api private
151
+ */
152
+
153
+ advance: function() {
154
+ return this.eos()
155
+ || this.null()
156
+ || this.sep()
157
+ || this.keyword()
158
+ || this.urlchars()
159
+ || this.atrule()
160
+ || this.media()
161
+ || this.comment()
162
+ || this.newline()
163
+ || this.escaped()
164
+ || this.important()
165
+ || this.literal()
166
+ || this.function()
167
+ || this.brace()
168
+ || this.paren()
169
+ || this.color()
170
+ || this.string()
171
+ || this.unit()
172
+ || this.namedop()
173
+ || this.boolean()
174
+ || this.ident()
175
+ || this.op()
176
+ || this.space()
177
+ || this.selector();
178
+ },
179
+
180
+ /**
181
+ * Lookahead a single token.
182
+ *
183
+ * @return {Token}
184
+ * @api private
185
+ */
186
+
187
+ peek: function() {
188
+ return this.lookahead(1);
189
+ },
190
+
191
+ /**
192
+ * Return the next possibly stashed token.
193
+ *
194
+ * @return {Token}
195
+ * @api private
196
+ */
197
+
198
+ stashed: function() {
199
+ return this.stash.shift();
200
+ },
201
+
202
+ /**
203
+ * EOS | trailing outdents.
204
+ */
205
+
206
+ eos: function() {
207
+ if (this.str.length) return;
208
+ if (this.indentStack.length) {
209
+ this.indentStack.shift();
210
+ return new Token('outdent');
211
+ } else {
212
+ return new Token('eos');
213
+ }
214
+ },
215
+
216
+ /**
217
+ * url char
218
+ */
219
+
220
+ urlchars: function() {
221
+ var captures;
222
+ if (!this.isURL) return;
223
+ if (captures = /^[\/:@.;?&=*!,<>#%0-9]+/.exec(this.str)) {
224
+ this.skip(captures);
225
+ return new Token('literal', new nodes.Literal(captures[0]));
226
+ }
227
+ },
228
+
229
+ /**
230
+ * ';' ' '*
231
+ */
232
+
233
+ sep: function() {
234
+ var captures;
235
+ if (captures = /^; */.exec(this.str)) {
236
+ this.skip(captures);
237
+ return new Token(';');
238
+ }
239
+ },
240
+
241
+ /**
242
+ * ' '+
243
+ */
244
+
245
+ space: function() {
246
+ var captures;
247
+ if (captures = /^( +)/.exec(this.str)) {
248
+ this.skip(captures);
249
+ return new Token('space');
250
+ }
251
+ },
252
+
253
+ /**
254
+ * '\\' . ' '*
255
+ */
256
+
257
+ escaped: function() {
258
+ var captures;
259
+ if (captures = /^\\(.) */.exec(this.str)) {
260
+ var c = captures[1];
261
+ this.skip(captures);
262
+ return new Token('ident', new nodes.Literal(c));
263
+ }
264
+ },
265
+
266
+ /**
267
+ * '@css' ' '* '{' .* '}' ' '*
268
+ */
269
+
270
+ literal: function() {
271
+ // HACK attack !!!
272
+ var captures;
273
+ if (captures = /^@css *\{/.exec(this.str)) {
274
+ this.skip(captures);
275
+ var c
276
+ , braces = 1
277
+ , css = '';
278
+ while (c = this.str[0]) {
279
+ this.str = this.str.substr(1);
280
+ switch (c) {
281
+ case '{': ++braces; break;
282
+ case '}': --braces; break;
283
+ }
284
+ css += c;
285
+ if (!braces) break;
286
+ }
287
+ css = css.replace(/\s*}$/, '');
288
+ return new Token('literal', new nodes.Literal(css));
289
+ }
290
+ },
291
+
292
+ /**
293
+ * '!important' ' '*
294
+ */
295
+
296
+ important: function() {
297
+ var captures;
298
+ if (captures = /^!important */.exec(this.str)) {
299
+ this.skip(captures);
300
+ return new Token('ident', new nodes.Literal('!important'));
301
+ }
302
+ },
303
+
304
+ /**
305
+ * '{' | '}'
306
+ */
307
+
308
+ brace: function() {
309
+ var captures;
310
+ if (captures = /^([{}])/.exec(this.str)) {
311
+ this.skip(1);
312
+ var brace = captures[1];
313
+ return new Token(brace, brace);
314
+ }
315
+ },
316
+
317
+ /**
318
+ * '(' | ')' ' '*
319
+ */
320
+
321
+ paren: function() {
322
+ var captures;
323
+ if (captures = /^([()]) */.exec(this.str)) {
324
+ var paren = captures[1];
325
+ this.skip(captures);
326
+ if (')' == paren) this.isURL = false;
327
+ return new Token(paren, paren);
328
+ }
329
+ },
330
+
331
+ /**
332
+ * 'null'
333
+ */
334
+
335
+ null: function() {
336
+ var captures;
337
+ if (captures = /^(null)\b */.exec(this.str)) {
338
+ this.skip(captures);
339
+ return new Token('null', nodes.null);
340
+ }
341
+ },
342
+
343
+ /**
344
+ * 'if'
345
+ * | 'else'
346
+ * | 'unless'
347
+ * | 'return'
348
+ * | 'for'
349
+ * | 'in'
350
+ */
351
+
352
+ keyword: function() {
353
+ var captures;
354
+ if (captures = /^(return|if|else|unless|for|in)\b */.exec(this.str)) {
355
+ var keyword = captures[1];
356
+ this.skip(captures);
357
+ return new Token(keyword, keyword);
358
+ }
359
+ },
360
+
361
+ /**
362
+ * 'not'
363
+ * | 'and'
364
+ * | 'or'
365
+ * | 'is'
366
+ * | 'is not'
367
+ * | 'isnt'
368
+ * | 'is a'
369
+ * | 'is defined'
370
+ */
371
+
372
+ namedop: function() {
373
+ var captures;
374
+ if (captures = /^(not|and|or|is a|is defined|isnt|is not|is)\b( *)/.exec(this.str)) {
375
+ var op = captures[1];
376
+ this.skip(captures);
377
+ op = alias[op] || op;
378
+ var tok = new Token(op, op);
379
+ tok.space = captures[2];
380
+ return tok;
381
+ }
382
+ },
383
+
384
+ /**
385
+ * ','
386
+ * | '+'
387
+ * | '+='
388
+ * | '-'
389
+ * | '-='
390
+ * | '*'
391
+ * | '*='
392
+ * | '/'
393
+ * | '/='
394
+ * | '%'
395
+ * | '%='
396
+ * | '**'
397
+ * | '!'
398
+ * | '&'
399
+ * | '&&'
400
+ * | '||'
401
+ * | '>'
402
+ * | '>='
403
+ * | '<'
404
+ * | '<='
405
+ * | '='
406
+ * | '=='
407
+ * | '!='
408
+ * | '!'
409
+ * | '~'
410
+ * | '?='
411
+ * | ':='
412
+ * | '?'
413
+ * | ':'
414
+ * | '['
415
+ * | ']'
416
+ * | '..'
417
+ * | '...'
418
+ */
419
+
420
+ op: function() {
421
+ var captures;
422
+ if (captures = /^([.]{2,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])( *)/.exec(this.str)) {
423
+ var op = captures[1];
424
+ this.skip(captures);
425
+ op = alias[op] || op;
426
+ var tok = new Token(op, op);
427
+ tok.space = captures[2];
428
+ return tok;
429
+ }
430
+ },
431
+
432
+ /**
433
+ * '@media' ([^{\n]+)
434
+ */
435
+
436
+ media: function() {
437
+ var captures;
438
+ if (captures = /^@media *([^{\n]+)/.exec(this.str)) {
439
+ this.skip(captures);
440
+ return new Token('media', captures[1].trim());
441
+ }
442
+ },
443
+
444
+ /**
445
+ * '@' ('import' | 'keyframes' | 'charset' | 'page' | 'font-face')
446
+ */
447
+
448
+ atrule: function() {
449
+ var captures;
450
+ if (captures = /^@(import|(?:-(\w+)-)?keyframes|charset|font-face|page) */.exec(this.str)) {
451
+ this.skip(captures);
452
+ var vendor = captures[2]
453
+ , type = captures[1];
454
+ if (vendor) type = 'keyframes';
455
+ return new Token(type, vendor);
456
+ }
457
+ },
458
+
459
+ /**
460
+ * '//' *
461
+ */
462
+
463
+ comment: function() {
464
+ // Single line
465
+ if ('/' == this.str[0] && '/' == this.str[1]) {
466
+ var end = this.str.indexOf('\n');
467
+ if (-1 == end) end = this.str.length;
468
+ this.skip(end);
469
+ return this.advance();
470
+ }
471
+
472
+ // Multi-line
473
+ if ('/' == this.str[0] && '*' == this.str[1]) {
474
+ var end = this.str.indexOf('*/');
475
+ if (-1 == end) end = this.str.length;
476
+ var str = this.str.substr(0, end + 2)
477
+ , lines = str.split('\n').length - 1
478
+ , suppress = true;
479
+ this.lineno += lines;
480
+ this.skip(end + 2);
481
+ // output
482
+ if ('!' == str[2]) {
483
+ str = str.replace('*!', '*');
484
+ suppress = false;
485
+ }
486
+ return new Token('comment', new nodes.Comment(str, suppress));
487
+ }
488
+ },
489
+
490
+ /**
491
+ * 'true' | 'false'
492
+ */
493
+
494
+ boolean: function() {
495
+ var captures;
496
+ if (captures = /^(true|false)\b( *)/.exec(this.str)) {
497
+ var val = nodes.Boolean('true' == captures[1]);
498
+ this.skip(captures);
499
+ var tok = new Token('boolean', val);
500
+ tok.space = captures[2];
501
+ return tok;
502
+ }
503
+ },
504
+
505
+ /**
506
+ * -?[a-zA-Z$] [-\w\d$]* '('
507
+ */
508
+
509
+ function: function() {
510
+ var captures;
511
+ if (captures = /^(-?[a-zA-Z$][-\w\d$]*)\(( *)/.exec(this.str)) {
512
+ var name = captures[1];
513
+ this.skip(captures);
514
+ this.isURL = 'url' == name;
515
+ var tok = new Token('function', new nodes.Ident(name));
516
+ tok.space = captures[2];
517
+ return tok;
518
+ }
519
+ },
520
+
521
+ /**
522
+ * -?[_a-zA-Z$] [-\w\d$]*
523
+ */
524
+
525
+ ident: function() {
526
+ var captures;
527
+ if (captures = /^(@)?(-?[_a-zA-Z$][-\w\d$]*)/.exec(this.str)) {
528
+ var at = captures[1]
529
+ , name = captures[2]
530
+ , id = new nodes.Ident(name);
531
+ this.skip(captures);
532
+ id.property = !! at;
533
+ return new Token('ident', id);
534
+ }
535
+ },
536
+
537
+ /**
538
+ * '\n' ' '+
539
+ */
540
+
541
+ newline: function() {
542
+ var captures, re;
543
+
544
+ // we have established the indentation regexp
545
+ if (this.indentRe){
546
+ captures = this.indentRe.exec(this.str);
547
+ // figure out if we are using tabs or spaces
548
+ } else {
549
+ // try tabs
550
+ re = /^\n([\t]*) */;
551
+ captures = re.exec(this.str);
552
+
553
+ // nope, try spaces
554
+ if (captures && !captures[1].length) {
555
+ re = /^\n( *)/;
556
+ captures = re.exec(this.str);
557
+ }
558
+
559
+ // established
560
+ if (captures && captures[1].length) this.indentRe = re;
561
+ }
562
+
563
+
564
+ if (captures) {
565
+ var tok
566
+ , indents = captures[1].length;
567
+
568
+ this.skip(captures);
569
+ if (this.str[0] === ' ' || this.str[0] === '\t') {
570
+ throw new errors.SyntaxError('Invalid indentation. You can use tabs or spaces to indent, but not both.');
571
+ }
572
+
573
+ // Reset state
574
+ this.isVariable = false;
575
+
576
+ // Blank line
577
+ if ('\n' == this.str[0]) {
578
+ ++this.lineno;
579
+ return this.advance();
580
+ }
581
+
582
+ // Outdent
583
+ if (this.indentStack.length && indents < this.indentStack[0]) {
584
+ while (this.indentStack.length && this.indentStack[0] > indents) {
585
+ this.stash.push(new Token('outdent'));
586
+ this.indentStack.shift();
587
+ }
588
+ tok = this.stash.pop();
589
+ // Indent
590
+ } else if (indents && indents != this.indentStack[0]) {
591
+ this.indentStack.unshift(indents);
592
+ tok = new Token('indent');
593
+ // Newline
594
+ } else {
595
+ tok = new Token('newline');
596
+ }
597
+
598
+ return tok;
599
+ }
600
+ },
601
+
602
+ /**
603
+ * '-'? (digit+ | digit* '.' digit+) unit
604
+ */
605
+
606
+ unit: function() {
607
+ var captures;
608
+ if (captures = unit.exec(this.str)) {
609
+ this.skip(captures);
610
+ var n = parseFloat(captures[2]);
611
+ if ('-' == captures[1]) n = -n;
612
+ var node = new nodes.Unit(n, captures[3]);
613
+ return new Token('unit', node);
614
+ }
615
+ },
616
+
617
+ /**
618
+ * '"' [^"]+ '"' | "'"" [^']+ "'"
619
+ */
620
+
621
+ string: function() {
622
+ var captures;
623
+ if (captures = /^("[^"]*"|'[^']*') */.exec(this.str)) {
624
+ var str = captures[1];
625
+ this.skip(captures);
626
+ str = str.slice(1,-1).replace(/\\n/g, '\n');
627
+ return new Token('string', new nodes.String(str));
628
+ }
629
+ },
630
+
631
+ /**
632
+ * #rrggbbaa | #rrggbb | #rgba | #rgb
633
+ */
634
+
635
+ color: function() {
636
+ return this.rrggbbaa()
637
+ || this.rrggbb()
638
+ || this.rgba()
639
+ || this.rgb()
640
+ },
641
+
642
+ /**
643
+ * #rgb
644
+ */
645
+
646
+ rgb: function() {
647
+ var captures;
648
+ if (captures = /^#([a-fA-F0-9]{3}) */.exec(this.str)) {
649
+ this.skip(captures);
650
+ var rgb = captures[1]
651
+ , r = parseInt(rgb[0] + rgb[0], 16)
652
+ , g = parseInt(rgb[1] + rgb[1], 16)
653
+ , b = parseInt(rgb[2] + rgb[2], 16)
654
+ , color = new nodes.RGBA(r, g, b, 1);
655
+ color.raw = captures[0];
656
+ return new Token('color', color);
657
+ }
658
+ },
659
+
660
+ /**
661
+ * #rgba
662
+ */
663
+
664
+ rgba: function() {
665
+ var captures;
666
+ if (captures = /^#([a-fA-F0-9]{4}) */.exec(this.str)) {
667
+ this.skip(captures);
668
+ var rgb = captures[1]
669
+ , r = parseInt(rgb[0] + rgb[0], 16)
670
+ , g = parseInt(rgb[1] + rgb[1], 16)
671
+ , b = parseInt(rgb[2] + rgb[2], 16)
672
+ , a = parseInt(rgb[3] + rgb[3], 16)
673
+ , color = new nodes.RGBA(r, g, b, a/255);
674
+ color.raw = captures[0];
675
+ return new Token('color', color);
676
+ }
677
+ },
678
+
679
+ /**
680
+ * #rrggbb
681
+ */
682
+
683
+ rrggbb: function() {
684
+ var captures;
685
+ if (captures = /^#([a-fA-F0-9]{6}) */.exec(this.str)) {
686
+ this.skip(captures);
687
+ var rgb = captures[1]
688
+ , r = parseInt(rgb.substr(0, 2), 16)
689
+ , g = parseInt(rgb.substr(2, 2), 16)
690
+ , b = parseInt(rgb.substr(4, 2), 16)
691
+ , color = new nodes.RGBA(r, g, b, 1);
692
+ color.raw = captures[0];
693
+ return new Token('color', color);
694
+ }
695
+ },
696
+
697
+ /**
698
+ * #rrggbbaa
699
+ */
700
+
701
+ rrggbbaa: function() {
702
+ var captures;
703
+ if (captures = /^#([a-fA-F0-9]{8}) */.exec(this.str)) {
704
+ this.skip(captures);
705
+ var rgb = captures[1]
706
+ , r = parseInt(rgb.substr(0, 2), 16)
707
+ , g = parseInt(rgb.substr(2, 2), 16)
708
+ , b = parseInt(rgb.substr(4, 2), 16)
709
+ , a = parseInt(rgb.substr(6, 2), 16)
710
+ , color = new nodes.RGBA(r, g, b, a/255);
711
+ color.raw = captures[0];
712
+ return new Token('color', color);
713
+ }
714
+ },
715
+
716
+ /**
717
+ * [^\n,;]+
718
+ */
719
+
720
+ selector: function() {
721
+ var captures;
722
+ if (captures = /^[^{\n,]+/.exec(this.str)) {
723
+ var selector = captures[0];
724
+ this.skip(captures);
725
+ return new Token('selector', selector);
726
+ }
727
+ }
728
+ };