stylus-source 0.15.4

Sign up to get free protection for your applications and to get access to all the features.
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,53 @@
1
+
2
+ /*!
3
+ * Stylus - Token
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var inspect = require('sys').inspect;
13
+
14
+ /**
15
+ * Initialize a new `Token` with the given `type` and `val`.
16
+ *
17
+ * @param {String} type
18
+ * @param {Mixed} val
19
+ * @api private
20
+ */
21
+
22
+ var Token = exports = module.exports = function Token(type, val) {
23
+ this.type = type;
24
+ this.val = val;
25
+ };
26
+
27
+ /**
28
+ * Custom inspect.
29
+ *
30
+ * @return {String}
31
+ * @api public
32
+ */
33
+
34
+ Token.prototype.inspect = function(){
35
+ var val = ' ' + inspect(this.val);
36
+ return '[Token:' + this.lineno + ' '
37
+ + '\x1b[32m' + this.type + '\x1b[0m'
38
+ + '\x1b[33m' + (this.val ? val : '') + '\x1b[0m'
39
+ + ']';
40
+ };
41
+
42
+ /**
43
+ * Return type or val.
44
+ *
45
+ * @return {String}
46
+ * @api public
47
+ */
48
+
49
+ Token.prototype.toString = function(){
50
+ return (undefined === this.val
51
+ ? this.type
52
+ : this.val).toString();
53
+ };
@@ -0,0 +1,237 @@
1
+
2
+ /*!
3
+ * Stylus - utils
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var nodes = require('./nodes')
13
+ , join = require('path').join
14
+ , fs = require('fs');
15
+
16
+ /**
17
+ * Check if `path` looks absolute.
18
+ *
19
+ * @param {String} path
20
+ * @return {Boolean}
21
+ * @api private
22
+ */
23
+
24
+ exports.absolute = function(path){
25
+ return /^([a-z]:\\)|\//i.test(path);
26
+ };
27
+
28
+ /**
29
+ * Attempt to lookup `path` within `paths` from tail to head.
30
+ * Optionally a path to `ignore` may be passed.
31
+ *
32
+ * @param {String} path
33
+ * @param {String} paths
34
+ * @param {String} ignore
35
+ * @return {String}
36
+ * @api private
37
+ */
38
+
39
+ exports.lookup = function(path, paths, ignore){
40
+ var lookup
41
+ , i = paths.length;
42
+
43
+ // Absolute
44
+ if (exports.absolute(path)) {
45
+ try {
46
+ fs.statSync(path);
47
+ return path;
48
+ } catch (err) {
49
+ // Ignore, continue on
50
+ // to trying relative lookup.
51
+ // Needed for url(/images/foo.png)
52
+ // for example
53
+ }
54
+ }
55
+
56
+ // Relative
57
+ while (i--) {
58
+ try {
59
+ lookup = join(paths[i], path);
60
+ if (ignore == lookup) continue;
61
+ fs.statSync(lookup);
62
+ return lookup;
63
+ } catch (err) {
64
+ // Ignore
65
+ }
66
+ }
67
+ };
68
+
69
+ /**
70
+ * Format the given `err` with the given `options`.
71
+ *
72
+ * Options:
73
+ *
74
+ * - `filename` context filename
75
+ * - `context` context line count [8]
76
+ * - `lineno` context line number
77
+ * - `input` input string
78
+ *
79
+ * @param {Error} err
80
+ * @param {Object} options
81
+ * @return {Error}
82
+ * @api private
83
+ */
84
+
85
+ exports.formatException = function(err, options){
86
+ var lineno = options.lineno
87
+ , filename = options.filename
88
+ , str = options.input
89
+ , context = options.context || 8
90
+ , context = context / 2
91
+ , lines = ('\n' + str).split('\n')
92
+ , start = Math.max(lineno - context, 1)
93
+ , end = Math.min(lines.length, lineno + context)
94
+ , pad = end.toString().length;
95
+
96
+ var context = lines.slice(start, end).map(function(line, i){
97
+ var curr = i + start;
98
+ return (curr == lineno ? ' > ' : ' ')
99
+ + Array(pad - curr.toString().length + 1).join(' ')
100
+ + curr
101
+ + '| '
102
+ + line;
103
+ }).join('\n');
104
+
105
+ err.message = filename
106
+ + ':' + lineno
107
+ + '\n' + context
108
+ + '\n\n' + err.message + '\n'
109
+ + (err.stylusStack ? err.stylusStack + '\n' : '');
110
+
111
+ return err;
112
+ };
113
+
114
+ /**
115
+ * Assert that `node` is of the given `type`, or throw.
116
+ *
117
+ * @param {Node} node
118
+ * @param {Function} type
119
+ * @param {String} param
120
+ * @api public
121
+ */
122
+
123
+ exports.assertType = function(node, type, param){
124
+ exports.assertPresent(node, param);
125
+ if (node.nodeName == type) return;
126
+ var actual = node.nodeName
127
+ , msg = 'expected "'
128
+ + param + '" to be a '
129
+ + type + ', but got '
130
+ + actual + ':' + node;
131
+ throw new Error('TypeError: ' + msg);
132
+ };
133
+
134
+ /**
135
+ * Assert that `node` is a `String` or `Ident`.
136
+ *
137
+ * @param {Node} node
138
+ * @param {String} param
139
+ * @api public
140
+ */
141
+
142
+ exports.assertString = function(node, param){
143
+ exports.assertPresent(node, param);
144
+ switch (node.nodeName) {
145
+ case 'string':
146
+ case 'ident':
147
+ case 'literal':
148
+ return;
149
+ default:
150
+ var actual = node.nodeName
151
+ , msg = 'expected string, ident or literal, but got ' + actual + ':' + node;
152
+ throw new Error('TypeError: ' + msg);
153
+ }
154
+ };
155
+
156
+ /**
157
+ * Assert that `node` is a `RGBA` or `HSLA`.
158
+ *
159
+ * @param {Node} node
160
+ * @param {String} param
161
+ * @api public
162
+ */
163
+
164
+ exports.assertColor = function(node, param){
165
+ exports.assertPresent(node, param);
166
+ switch (node.nodeName) {
167
+ case 'rgba':
168
+ case 'hsla':
169
+ return;
170
+ default:
171
+ var actual = node.nodeName
172
+ , msg = 'expected rgba or hsla, but got ' + actual + ':' + node;
173
+ throw new Error('TypeError: ' + msg);
174
+ }
175
+ };
176
+
177
+ /**
178
+ * Assert that param `name` is given, aka the `node` is passed.
179
+ *
180
+ * @param {Node} node
181
+ * @param {String} name
182
+ * @api public
183
+ */
184
+
185
+ exports.assertPresent = function(node, name){
186
+ if (node) return;
187
+ if (name) throw new Error('"' + name + '" argument required');
188
+ throw new Error('argument missing');
189
+ };
190
+
191
+ /**
192
+ * Unwrap `expr`.
193
+ *
194
+ * Takes an expressions with length of 1
195
+ * such as `((1 2 3))` and unwraps it to `(1 2 3)`.
196
+ *
197
+ * @param {Expression} expr
198
+ * @return {Node}
199
+ * @api public
200
+ */
201
+
202
+ exports.unwrap = function(expr){
203
+ // explicitly preserve the expression
204
+ if (expr.preserve) return expr;
205
+ if ('arguments' != expr.nodeName && 'expression' != expr.nodeName) return expr;
206
+ if (1 != expr.nodes.length) return expr;
207
+ if ('arguments' != expr.nodes[0].nodeName && 'expression' != expr.nodes[0].nodeName) return expr;
208
+ return exports.unwrap(expr.nodes[0]);
209
+ };
210
+
211
+ /**
212
+ * Return param names for `fn`.
213
+ *
214
+ * @param {Function} fn
215
+ * @return {Array}
216
+ * @api private
217
+ */
218
+
219
+ exports.params = function(fn){
220
+ return fn
221
+ .toString()
222
+ .match(/\(([^)]*)\)/)[1].split(/ *, */);
223
+ };
224
+
225
+ /**
226
+ * Merge object `b` with `a`.
227
+ *
228
+ * @param {Object} a
229
+ * @param {Object} b
230
+ * @return {Object} a
231
+ * @api private
232
+ */
233
+
234
+ exports.merge = function(a, b){
235
+ for (var k in b) a[k] = b[k];
236
+ return a;
237
+ }
@@ -0,0 +1,472 @@
1
+
2
+ /*!
3
+ * Stylus - Compiler
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var Visitor = require('./')
13
+ , nodes = require('../nodes')
14
+ , fs = require('fs');
15
+
16
+ /**
17
+ * Initialize a new `Compiler` with the given `root` Node
18
+ * and the following `options`.
19
+ *
20
+ * Options:
21
+ *
22
+ * - `compress` Compress the css output, defaults to false
23
+ *
24
+ * @param {Node} root
25
+ * @api public
26
+ */
27
+
28
+ var Compiler = module.exports = function Compiler(root, options) {
29
+ options = options || {};
30
+ this.compress = options.compress;
31
+ this.firebug = options.firebug;
32
+ this.linenos = options.linenos;
33
+ this.indents = 1;
34
+ Visitor.call(this, root);
35
+ this.tree = [];
36
+ this.js = '';
37
+ };
38
+
39
+ /**
40
+ * Inherit from `Visitor.prototype`.
41
+ */
42
+
43
+ Compiler.prototype.__proto__ = Visitor.prototype;
44
+
45
+ /**
46
+ * Compile to css, and return a string of CSS.
47
+ *
48
+ * @return {String}
49
+ * @api private
50
+ */
51
+
52
+ Compiler.prototype.compile = function(){
53
+ return this.visit(this.root);
54
+ };
55
+
56
+ /**
57
+ * Return indentation string.
58
+ *
59
+ * @return {String}
60
+ * @api private
61
+ */
62
+
63
+ Compiler.prototype.__defineGetter__('indent', function(){
64
+ return this.compress
65
+ ? ''
66
+ : new Array(this.indents).join(' ');
67
+ });
68
+
69
+ /**
70
+ * Visit Root.
71
+ */
72
+
73
+ Compiler.prototype.visitRoot = function(block){
74
+ this.buf = '';
75
+ for (var i = 0, len = block.nodes.length; i < len; ++i) {
76
+ var node = block.nodes[i];
77
+ switch (node.nodeName) {
78
+ case 'null':
79
+ case 'expression':
80
+ case 'function':
81
+ case 'jsliteral':
82
+ case 'unit':
83
+ continue;
84
+ default:
85
+ if (this.linenos || this.firebug) this.debugInfo(node);
86
+ var ret = this.visit(node);
87
+ if (ret) this.buf += ret + '\n';
88
+ }
89
+ }
90
+ return this.buf;
91
+ };
92
+
93
+ /**
94
+ * Visit Block.
95
+ */
96
+
97
+ Compiler.prototype.visitBlock = function(block){
98
+ var node;
99
+
100
+ if (block.hasProperties) {
101
+ var arr = [this.compress ? '{' : ' {'];
102
+ ++this.indents;
103
+ for (var i = 0, len = block.nodes.length; i < len; ++i) {
104
+ this.last = len - 1 == i;
105
+ node = block.nodes[i];
106
+ switch (node.nodeName) {
107
+ case 'null':
108
+ case 'expression':
109
+ case 'function':
110
+ case 'jsliteral':
111
+ case 'group':
112
+ case 'unit':
113
+ continue;
114
+ default:
115
+ arr.push(this.visit(node));
116
+ }
117
+ }
118
+ --this.indents;
119
+ arr.push(this.indent + '}');
120
+ this.buf += arr.join(this.compress ? '' : '\n');
121
+ this.buf += '\n';
122
+ }
123
+
124
+ // Nesting
125
+ for (var i = 0, len = block.nodes.length; i < len; ++i) {
126
+ node = block.nodes[i];
127
+ switch (node.nodeName) {
128
+ case 'group':
129
+ case 'print':
130
+ case 'page':
131
+ case 'block':
132
+ case 'keyframes':
133
+ if (this.linenos || this.firebug) this.debugInfo(node);
134
+ this.visit(node);
135
+ break;
136
+ case 'media':
137
+ case 'import':
138
+ this.visit(node);
139
+ break;
140
+ }
141
+ }
142
+ };
143
+
144
+ /**
145
+ * Visit Keyframes.
146
+ */
147
+
148
+ Compiler.prototype.visitKeyframes = function(node){
149
+ var prefix = 'official' == node.prefix
150
+ ? ''
151
+ : '-' + node.prefix + '-';
152
+
153
+ this.buf += '@' + prefix + 'keyframes '
154
+ + this.visit(node.name)
155
+ + (this.compress ? '{' : ' {');
156
+ ++this.indents;
157
+ node.frames.forEach(function(frame){
158
+ if (!this.compress) this.buf += '\n ';
159
+ this.buf += this.visit(frame.pos);
160
+ this.visit(frame.block);
161
+ }, this);
162
+ --this.indents;
163
+ this.buf += '}' + (this.compress ? '' : '\n');
164
+ };
165
+
166
+ /**
167
+ * Visit Media.
168
+ */
169
+
170
+ Compiler.prototype.visitMedia = function(media){
171
+ this.buf += '@media ' + media.val;
172
+ this.buf += this.compress ? '{' : ' {\n';
173
+ ++this.indents;
174
+ this.visit(media.block);
175
+ --this.indents;
176
+ this.buf += '}' + (this.compress ? '' : '\n');
177
+ };
178
+
179
+ /**
180
+ * Visit Page.
181
+ */
182
+
183
+ Compiler.prototype.visitPage = function(page){
184
+ this.buf += this.indent + '@page';
185
+ this.buf += page.selector ? ' ' + page.selector : '';
186
+ this.visit(page.block);
187
+ };
188
+
189
+ /**
190
+ * Visit Import.
191
+ */
192
+
193
+ Compiler.prototype.visitImport = function(imported){
194
+ this.buf += '@import ' + this.visit(imported.path) + ';\n';
195
+ };
196
+
197
+ /**
198
+ * Visit FontFace.
199
+ */
200
+
201
+ Compiler.prototype.visitFontFace = function(face){
202
+ this.buf += this.indent + '@font-face';
203
+ this.visit(face.block);
204
+ };
205
+
206
+ /**
207
+ * Visit JSLiteral.
208
+ */
209
+
210
+ Compiler.prototype.visitJSLiteral = function(js){
211
+ this.js += '\n' + js.val.replace(/@selector/g, '"' + this.selector + '"');
212
+ return '';
213
+ };
214
+
215
+ /**
216
+ * Visit Comment.
217
+ */
218
+
219
+ Compiler.prototype.visitComment = function(comment){
220
+ return this.compress
221
+ ? comment.suppress
222
+ ? ''
223
+ : comment.str
224
+ : comment.str;
225
+ };
226
+
227
+ /**
228
+ * Visit Function.
229
+ */
230
+
231
+ Compiler.prototype.visitFunction = function(fn){
232
+ return fn.name;
233
+ };
234
+
235
+ /**
236
+ * Visit Variable.
237
+ */
238
+
239
+ Compiler.prototype.visitVariable = function(variable){
240
+ return '';
241
+ };
242
+
243
+ /**
244
+ * Visit Charset.
245
+ */
246
+
247
+ Compiler.prototype.visitCharset = function(charset){
248
+ return '@charset ' + this.visit(charset.val) + ';';
249
+ };
250
+
251
+ /**
252
+ * Visit Literal.
253
+ */
254
+
255
+ Compiler.prototype.visitLiteral = function(lit){
256
+ return lit.val.trim().replace(/^ /gm, '');
257
+ };
258
+
259
+ /**
260
+ * Visit Boolean.
261
+ */
262
+
263
+ Compiler.prototype.visitBoolean = function(bool){
264
+ return bool.toString();
265
+ };
266
+
267
+ /**
268
+ * Visit RGBA.
269
+ */
270
+
271
+ Compiler.prototype.visitRGBA = function(rgba){
272
+ return rgba.toString();
273
+ };
274
+
275
+ /**
276
+ * Visit HSLA.
277
+ */
278
+
279
+ Compiler.prototype.visitHSLA = function(hsla){
280
+ return hsla.rgba.toString();
281
+ };
282
+
283
+ /**
284
+ * Visit Unit.
285
+ */
286
+
287
+ Compiler.prototype.visitUnit = function(unit){
288
+ var type = unit.type || ''
289
+ , n = unit.val
290
+ , float = n != (n | 0);
291
+
292
+ // Compress
293
+ if (this.compress) {
294
+ // Zero is always '0', unless when
295
+ // a percentage, this is required by keyframes
296
+ if ('%' != type && 0 == n) return '0';
297
+ // Omit leading '0' on floats
298
+ if (float && n < 1 && n > -1) {
299
+ return n.toString().replace('0.', '.') + type;
300
+ }
301
+ }
302
+
303
+ return n.toString() + type;
304
+ };
305
+
306
+ /**
307
+ * Visit Group.
308
+ */
309
+
310
+ Compiler.prototype.visitGroup = function(group){
311
+ var self = this
312
+ , tree = this.tree
313
+ , prev = tree[tree.length - 1]
314
+ , curr = [];
315
+
316
+ // Construct an array of arrays
317
+ // representing the selector hierarchy
318
+ group.nodes.forEach(function(node){
319
+ curr.push(node.parent
320
+ ? node
321
+ : node.val);
322
+ });
323
+
324
+ tree.push(curr);
325
+
326
+ // Reverse recurse the
327
+ // hierarchy array to build
328
+ // up the selector combinations.
329
+ // When we reach root, we have our
330
+ // selector string built
331
+ var selectors = []
332
+ , buf = [];
333
+ function join(arr, i) {
334
+ if (i) {
335
+ arr[i].forEach(function(str){
336
+ buf.unshift(str);
337
+ join(arr, i - 1);
338
+ buf.shift();
339
+ });
340
+ } else {
341
+ arr[0].forEach(function(selector){
342
+ var str = selector.trim();
343
+ if (buf.length) {
344
+ for (var i = 0, len = buf.length; i < len; ++i) {
345
+ if (~buf[i].indexOf('&')) {
346
+ str = buf[i].replace(/&/g, str).trim();
347
+ } else {
348
+ str += ' ' + buf[i].trim();
349
+ }
350
+ }
351
+ }
352
+ selectors.push(self.indent + str.trimRight());
353
+ });
354
+ }
355
+ }
356
+
357
+ // Join selectors
358
+ if (group.block.hasProperties) {
359
+ join(tree, tree.length - 1);
360
+ this.buf += (this.selector = selectors.join(this.compress ? ',' : ',\n'));
361
+ }
362
+
363
+ // Output blocks
364
+ this.visit(group.block);
365
+ tree.pop();
366
+ };
367
+
368
+ /**
369
+ * Visit Ident.
370
+ */
371
+
372
+ Compiler.prototype.visitIdent = function(ident){
373
+ return ident.name;
374
+ };
375
+
376
+ /**
377
+ * Visit String.
378
+ */
379
+
380
+ Compiler.prototype.visitString = function(string){
381
+ return this.isURL
382
+ ? string.val
383
+ : string.toString();
384
+ };
385
+
386
+ /**
387
+ * Visit Null.
388
+ */
389
+
390
+ Compiler.prototype.visitNull = function(node){
391
+ return '';
392
+ };
393
+
394
+ /**
395
+ * Visit Call.
396
+ */
397
+
398
+ Compiler.prototype.visitCall = function(call){
399
+ this.isURL = 'url' == call.name;
400
+ var args = call.args.nodes.map(function(arg){
401
+ return this.visit(arg);
402
+ }, this).join(this.compress ? ',' : ', ');
403
+ if (this.isURL) args = '"' + args + '"';
404
+ delete this.isURL;
405
+ return call.name + '(' + args + ')';
406
+ };
407
+
408
+ /**
409
+ * Visit Expression.
410
+ */
411
+
412
+ Compiler.prototype.visitExpression = function(expr){
413
+ var buf = []
414
+ , self = this
415
+ , len = expr.nodes.length
416
+ , nodes = expr.nodes.map(function(node){ return self.visit(node); });
417
+
418
+ nodes.forEach(function(node, i){
419
+ var last = i == len - 1;
420
+ buf.push(node);
421
+ if ('/' == nodes[i + 1] || '/' == node) return;
422
+ if (last) return;
423
+ buf.push(expr.isList
424
+ ? (self.compress ? ',' : ', ')
425
+ : (self.isURL ? '' : ' '));
426
+ });
427
+
428
+ return buf.join('');
429
+ };
430
+
431
+ /**
432
+ * Visit Arguments.
433
+ */
434
+
435
+ Compiler.prototype.visitArguments = Compiler.prototype.visitExpression;
436
+
437
+ /**
438
+ * Visit Property.
439
+ */
440
+
441
+ Compiler.prototype.visitProperty = function(prop){
442
+ var self = this
443
+ , val = this.visit(prop.expr);
444
+ return this.indent + (prop.name || prop.segments.join(''))
445
+ + (this.compress ? ':' + val : ': ' + val)
446
+ + (this.compress
447
+ ? (this.last ? '' : ';')
448
+ : ';');
449
+ };
450
+
451
+ /**
452
+ * Debug info.
453
+ */
454
+
455
+ Compiler.prototype.debugInfo = function(node){
456
+
457
+ var path = fs.realpathSync(node.filename)
458
+ , line = node.nodes ? node.nodes[0].lineno : node.lineno;
459
+
460
+ if (this.linenos){
461
+ this.buf += '\n/* ' + 'line ' + line + ' : ' + path + ' */\n';
462
+ }
463
+
464
+ if (this.firebug){
465
+ // debug info for firebug, the crazy formatting is needed
466
+ path = 'file\\\:\\\/\\\/' + path.replace(/(\/|\.)/g, '\\$1');
467
+ line = '\\00003' + line;
468
+ this.buf += '\n@media -stylus-debug-info'
469
+ + '{filename{font-family:' + path
470
+ + '}line{font-family:' + line + '}}\n';
471
+ }
472
+ }