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,58 @@
1
+
2
+ /*!
3
+ * Stylus - errors
4
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Expose constructors.
10
+ */
11
+
12
+ exports.ParseError = ParseError;
13
+ exports.SyntaxError = SyntaxError;
14
+
15
+ /**
16
+ * Inherit from `Error.prototype`.
17
+ */
18
+
19
+ SyntaxError.prototype.__proto__ = Error.prototype;
20
+
21
+ /**
22
+ * Initialize a new `ParseError` with the given `msg`.
23
+ *
24
+ * @param {String} msg
25
+ * @api private
26
+ */
27
+
28
+ function ParseError(msg) {
29
+ this.name = 'ParseError';
30
+ this.message = msg;
31
+ Error.captureStackTrace(this, ParseError);
32
+ }
33
+
34
+ /**
35
+ * Inherit from `Error.prototype`.
36
+ */
37
+
38
+ ParseError.prototype.__proto__ = Error.prototype;
39
+
40
+ /**
41
+ * Initialize a new `SyntaxError` with the given `msg`.
42
+ *
43
+ * @param {String} msg
44
+ * @api private
45
+ */
46
+
47
+ function SyntaxError(msg) {
48
+ this.name = 'SyntaxError';
49
+ this.message = msg;
50
+ Error.captureStackTrace(this, ParseError);
51
+ }
52
+
53
+ /**
54
+ * Inherit from `Error.prototype`.
55
+ */
56
+
57
+ SyntaxError.prototype.__proto__ = Error.prototype;
58
+
@@ -0,0 +1,120 @@
1
+
2
+
3
+ /*!
4
+ * Stylus - plugin - url
5
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ /**
10
+ * Module dependencies.
11
+ */
12
+
13
+ var utils = require('../utils')
14
+ , nodes = require('../nodes')
15
+ , fs = require('fs');
16
+
17
+ /**
18
+ * Initialize a new `Image` with the given `ctx` and `path.
19
+ *
20
+ * @param {Evaluator} ctx
21
+ * @param {String} path
22
+ * @api private
23
+ */
24
+
25
+ var Image = module.exports = function Image(ctx, path) {
26
+ this.ctx = ctx;
27
+ this.path = utils.lookup(path, ctx.paths);
28
+ if (!this.path) throw new Error('failed to locate file ' + path);
29
+ };
30
+
31
+ /**
32
+ * Open the image for reading.
33
+ *
34
+ * @api private
35
+ */
36
+
37
+ Image.prototype.open = function(){
38
+ this.fd = fs.openSync(this.path, 'r');
39
+ };
40
+
41
+ /**
42
+ * Close the file.
43
+ *
44
+ * @api private
45
+ */
46
+
47
+ Image.prototype.close = function(){
48
+ if (this.fd) fs.closeSync(this.fd);
49
+ };
50
+
51
+ /**
52
+ * Return the type of image, supports:
53
+ *
54
+ * - gif
55
+ * - png
56
+ * - jpeg
57
+ *
58
+ * @return {String}
59
+ * @api private
60
+ */
61
+
62
+ Image.prototype.type = function(){
63
+ var type
64
+ , buf = new Buffer(4);
65
+
66
+ fs.readSync(this.fd, buf, 0, 4, 0);
67
+
68
+ // GIF
69
+ if (0x47 == buf[0] && 0x49 == buf[1] && 0x46 == buf[2]) type = 'gif';
70
+
71
+ // PNG
72
+ else if (0x50 == buf[1] && 0x4E == buf[2] && 0x47 == buf[3]) type = 'png';
73
+
74
+ // JPEG
75
+ else if (0xff == buf[0] && 0xd8 == buf[1]) type = 'jpeg';
76
+
77
+ return type;
78
+ };
79
+
80
+ /**
81
+ * Return image dimensions `[width, height]`.
82
+ *
83
+ * @return {Array}
84
+ * @api private
85
+ */
86
+
87
+ Image.prototype.size = function(){
88
+ var width
89
+ , height
90
+ , type = this.type();
91
+
92
+ function uint16(b) { return b[1] << 8 | b[0]; }
93
+ function uint32(b) { return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; }
94
+
95
+ // Determine dimensions
96
+ switch (type) {
97
+ case 'jpeg':
98
+ throw new Error('image-size() jpeg support not yet implemented');
99
+ break;
100
+ case 'png':
101
+ var buf = new Buffer(8);
102
+ // IHDR chunk width / height uint32_t big-endian
103
+ fs.readSync(this.fd, buf, 0, 8, 16);
104
+ width = uint32(buf);
105
+ height = uint32(buf.slice(4, 8));
106
+ break;
107
+ case 'gif':
108
+ var buf = new Buffer(4);
109
+ // width / height uint16_t little-endian
110
+ fs.readSync(this.fd, buf, 0, 4, 6);
111
+ width = uint16(buf);
112
+ height = uint16(buf.slice(2, 4));
113
+ break;
114
+ }
115
+
116
+ if ('number' != typeof width) throw new Error('failed to find width of "' + this.path + '"');
117
+ if ('number' != typeof height) throw new Error('failed to find height of "' + this.path + '"');
118
+
119
+ return [width, height];
120
+ };
@@ -0,0 +1,722 @@
1
+
2
+ /*!
3
+ * Stylus - Evaluator - built-in functions
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
+ , utils = require('../utils')
15
+ , Image = require('./image');
16
+
17
+ /**
18
+ * Color component name map.
19
+ */
20
+
21
+ var componentMap = {
22
+ red: 'r'
23
+ , green: 'g'
24
+ , blue: 'b'
25
+ , alpha: 'a'
26
+ , hue: 'h'
27
+ , saturation: 's'
28
+ , lightness: 'l'
29
+ };
30
+
31
+ /**
32
+ * Color component unit type map.
33
+ */
34
+
35
+ var unitMap = {
36
+ hue: 'deg'
37
+ , saturation: '%'
38
+ , lightness: '%'
39
+ };
40
+
41
+ /**
42
+ * Color type map.
43
+ */
44
+
45
+ var typeMap = {
46
+ red: 'rgba'
47
+ , blue: 'rgba'
48
+ , green: 'rgba'
49
+ , alpha: 'rgba'
50
+ , hue: 'hsla'
51
+ , saturation: 'hsla'
52
+ , lightness: 'hsla'
53
+ };
54
+
55
+ /**
56
+ * Convert the given `color` to an `HSLA` node,
57
+ * or h,s,l,a component values.
58
+ *
59
+ * Examples:
60
+ *
61
+ * hsla(10deg, 50%, 30%, 0.5)
62
+ * // => HSLA
63
+ *
64
+ * hsla(#ffcc00)
65
+ * // => HSLA
66
+ *
67
+ * @param {RGBA|HSLA|Unit} hue
68
+ * @param {Unit} saturation
69
+ * @param {Unit} lightness
70
+ * @param {Unit} alpha
71
+ * @return {HSLA}
72
+ * @api public
73
+ */
74
+
75
+ exports.hsla = function hsla(hue, saturation, lightness, alpha){
76
+ switch (arguments.length) {
77
+ case 1:
78
+ utils.assertColor(hue);
79
+ return hue.hsla;
80
+ default:
81
+ utils.assertType(hue, 'unit', 'hue');
82
+ utils.assertType(saturation, 'unit', 'saturation');
83
+ utils.assertType(lightness, 'unit', 'lightness');
84
+ utils.assertType(alpha, 'unit', 'alpha');
85
+ return new nodes.HSLA(
86
+ hue.val
87
+ , saturation.val
88
+ , lightness.val
89
+ , alpha.val);
90
+ }
91
+ };
92
+
93
+ /**
94
+ * Convert the given `color` to an `HSLA` node,
95
+ * or h,s,l component values.
96
+ *
97
+ * Examples:
98
+ *
99
+ * hsl(10, 50, 30)
100
+ * // => HSLA
101
+ *
102
+ * hsl(#ffcc00)
103
+ * // => HSLA
104
+ *
105
+ * @param {Unit|HSLA|RGBA} hue
106
+ * @param {Unit} saturation
107
+ * @param {Unit} lightness
108
+ * @return {HSLA}
109
+ * @api public
110
+ */
111
+
112
+ exports.hsl = function hsl(hue, saturation, lightness){
113
+ if (1 == arguments.length) {
114
+ utils.assertColor(hue, 'color');
115
+ return hue.hsla;
116
+ } else {
117
+ return exports.hsla(
118
+ hue
119
+ , saturation
120
+ , lightness
121
+ , new nodes.Unit(1));
122
+ }
123
+ };
124
+
125
+ /**
126
+ * Return type of `node`.
127
+ *
128
+ * Examples:
129
+ *
130
+ * type(12)
131
+ * // => 'unit'
132
+ *
133
+ * type(#fff)
134
+ * // => 'color'
135
+ *
136
+ * type(type)
137
+ * // => 'function'
138
+ *
139
+ * type(unbound)
140
+ * typeof(unbound)
141
+ * type-of(unbound)
142
+ * // => 'ident'
143
+ *
144
+ * @param {Node} node
145
+ * @return {String}
146
+ * @api public
147
+ */
148
+
149
+ exports.type =
150
+ exports.typeof =
151
+ exports['type-of'] = function type(node){
152
+ utils.assertPresent(node, 'expression');
153
+ var type = node.nodeName;
154
+ return new nodes.String(type);
155
+ };
156
+
157
+ /**
158
+ * Return component `name` for the given `color`.
159
+ *
160
+ * @param {RGBA|HSLA} color
161
+ * @param {String} na,e
162
+ * @return {Unit}
163
+ * @api public
164
+ */
165
+
166
+ exports.component = function component(color, name) {
167
+ utils.assertColor(color, 'color');
168
+ utils.assertString(name, 'name');
169
+ var name = name.string
170
+ , unit = unitMap[name]
171
+ , type = typeMap[name]
172
+ , name = componentMap[name];
173
+ if (!name) throw new Error('invalid color component "' + name + '"');
174
+ return new nodes.Unit(color[type][name], unit);
175
+ };
176
+
177
+ /**
178
+ * Return the red component of the given `color`.
179
+ *
180
+ * Examples:
181
+ *
182
+ * red(#c00)
183
+ * // => 204
184
+ *
185
+ * @param {RGBA|HSLA} color
186
+ * @return {Unit}
187
+ * @api public
188
+ */
189
+
190
+ exports.red = function red(color){
191
+ return exports.component(color, new nodes.String('red'));
192
+ };
193
+
194
+ /**
195
+ * Return the green component of the given `color`.
196
+ *
197
+ * Examples:
198
+ *
199
+ * green(#0c0)
200
+ * // => 204
201
+ *
202
+ * @param {RGBA|HSLA} color
203
+ * @return {Unit}
204
+ * @api public
205
+ */
206
+
207
+ exports.green = function green(color){
208
+ return exports.component(color, new nodes.String('green'));
209
+ };
210
+
211
+ /**
212
+ * Return the blue component of the given `color`.
213
+ *
214
+ * Examples:
215
+ *
216
+ * blue(#00c)
217
+ * // => 204
218
+ *
219
+ * @param {RGBA|HSLA} color
220
+ * @return {Unit}
221
+ * @api public
222
+ */
223
+
224
+ exports.blue = function blue(color){
225
+ return exports.component(color, new nodes.String('blue'));
226
+ };
227
+
228
+ /**
229
+ * Return a `RGBA` from the r,g,b,a channels.
230
+ *
231
+ * Examples:
232
+ *
233
+ * rgba(255,0,0,0.5)
234
+ * // => rgba(255,0,0,0.5)
235
+ *
236
+ * rgba(255,0,0,1)
237
+ * // => #ff0000
238
+ *
239
+ * rgba(#ffcc00, 0.5)
240
+ * // rgba(255,204,0,0.5)
241
+ *
242
+ * @param {Unit|RGBA|HSLA} red
243
+ * @param {Unit} green
244
+ * @param {Unit} blue
245
+ * @param {Unit} alpha
246
+ * @return {RGBA}
247
+ * @api public
248
+ */
249
+
250
+ exports.rgba = function rgba(red, green, blue, alpha){
251
+ switch (arguments.length) {
252
+ case 1:
253
+ utils.assertColor(red);
254
+ var color = red.rgba;
255
+ return new nodes.RGBA(
256
+ color.r
257
+ , color.g
258
+ , color.b
259
+ , color.a);
260
+ case 2:
261
+ utils.assertColor(red);
262
+ var color = red.rgba;
263
+ utils.assertType(green, 'unit', 'alpha');
264
+ return new nodes.RGBA(
265
+ color.r
266
+ , color.g
267
+ , color.b
268
+ , green.val);
269
+ default:
270
+ utils.assertType(red, 'unit', 'red');
271
+ utils.assertType(green, 'unit', 'green');
272
+ utils.assertType(blue, 'unit', 'blue');
273
+ utils.assertType(alpha, 'unit', 'alpha');
274
+ return new nodes.RGBA(
275
+ red.val
276
+ , green.val
277
+ , blue.val
278
+ , alpha.val);
279
+ }
280
+ };
281
+
282
+ /**
283
+ * Return a `RGBA` from the r,g,b channels.
284
+ *
285
+ * Examples:
286
+ *
287
+ * rgb(255,204,0)
288
+ * // => #ffcc00
289
+ *
290
+ * rgb(#fff)
291
+ * // => #fff
292
+ *
293
+ * @param {Unit|RGBA|HSLA} red
294
+ * @param {Unit} green
295
+ * @param {Unit} blue
296
+ * @return {RGBA}
297
+ * @api public
298
+ */
299
+
300
+ exports.rgb = function rgb(red, green, blue){
301
+ switch (arguments.length) {
302
+ case 1:
303
+ utils.assertColor(red);
304
+ var color = red.rgba;
305
+ return new nodes.RGBA(
306
+ color.r
307
+ , color.g
308
+ , color.b
309
+ , 1);
310
+ default:
311
+ return exports.rgba(
312
+ red
313
+ , green
314
+ , blue
315
+ , new nodes.Unit(1));
316
+ }
317
+ };
318
+
319
+ /**
320
+ * Unquote the given `str`.
321
+ *
322
+ * Examples:
323
+ *
324
+ * unquote("sans-serif")
325
+ * // => sans-serif
326
+ *
327
+ * unquote(sans-serif)
328
+ * // => sans-serif
329
+ *
330
+ * @param {String|Ident} string
331
+ * @return {Literal}
332
+ * @api public
333
+ */
334
+
335
+ exports.unquote = function unquote(string){
336
+ utils.assertString(string, 'string');
337
+ return new nodes.Literal(string.string);
338
+ };
339
+
340
+ /**
341
+ * Assign `type` to the given `unit` or return `unit`'s type.
342
+ *
343
+ * @param {Unit} unit
344
+ * @param {String|Ident} type
345
+ * @return {Unit}
346
+ * @api public
347
+ */
348
+
349
+ exports.unit = function unit(unit, type){
350
+ utils.assertType(unit, 'unit', 'unit');
351
+
352
+ // Assign
353
+ if (type) {
354
+ utils.assertString(type, 'type');
355
+ return new nodes.Unit(unit.val, type.string);
356
+ } else {
357
+ return new nodes.String(unit.type || '');
358
+ }
359
+ };
360
+
361
+ /**
362
+ * Lookup variable `name` or return Null.
363
+ *
364
+ * @param {String} name
365
+ * @return {Mixed}
366
+ * @api public
367
+ */
368
+
369
+ exports.lookup = function lookup(name){
370
+ utils.assertType(name, 'string', 'name');
371
+ var node = this.lookup(name.val);
372
+ if (!node) return nodes.null;
373
+ return this.visit(node);
374
+ };
375
+
376
+ /**
377
+ * Perform `op` on the `left` and `right` operands.
378
+ *
379
+ * @param {String} op
380
+ * @param {Node} left
381
+ * @param {Node} right
382
+ * @return {Node}
383
+ * @api public
384
+ */
385
+
386
+ exports.operate = function operate(op, left, right){
387
+ utils.assertType(op, 'string', 'op');
388
+ utils.assertPresent(left, 'left');
389
+ utils.assertPresent(right, 'right');
390
+ return left.operate(op.val, right);
391
+ };
392
+
393
+ /**
394
+ * Test if `val` matches the given `pattern`.
395
+ *
396
+ * Examples:
397
+ *
398
+ * match('^foo(bar)?', foo)
399
+ * match('^foo(bar)?', foobar)
400
+ * match('^foo(bar)?', 'foo')
401
+ * match('^foo(bar)?', 'foobar')
402
+ * // => true
403
+ *
404
+ * match('^foo(bar)?', 'bar')
405
+ * // => false
406
+ *
407
+ * @param {String} pattern
408
+ * @param {String|Ident} val
409
+ * @return {Boolean}
410
+ * @api public
411
+ */
412
+
413
+ exports.match = function match(pattern, val){
414
+ utils.assertType(pattern, 'string', 'pattern');
415
+ utils.assertString(val, 'val');
416
+ var re = new RegExp(pattern.val);
417
+ return nodes.Boolean(re.test(val.string));
418
+ };
419
+
420
+ /**
421
+ * Return length of the given `expr`.
422
+ *
423
+ * @param {Expression} expr
424
+ * @return {Unit}
425
+ * @api public
426
+ */
427
+
428
+ (exports.length = function length(expr){
429
+ if (expr) {
430
+ if (expr.nodes) {
431
+ return new nodes.Unit(utils.unwrap(expr).nodes.length);
432
+ } else {
433
+ return new nodes.Unit(1);
434
+ }
435
+ }
436
+ return new nodes.Unit(0);
437
+ }).raw = true;
438
+
439
+ /**
440
+ * Inspect the given `expr`.
441
+ *
442
+ * @param {Expression} expr
443
+ * @api public
444
+ */
445
+
446
+ (exports.p = function p(expr){
447
+ expr = utils.unwrap(expr);
448
+ console.log('\033[90minspect:\033[0m %s'
449
+ , expr.toString().replace(/^\(|\)$/g, ''));
450
+ return nodes.null;
451
+ }).raw = true;
452
+
453
+ /**
454
+ * Throw an error with the given `msg`.
455
+ *
456
+ * @param {String} msg
457
+ * @api public
458
+ */
459
+
460
+ exports.error = function error(msg){
461
+ utils.assertType(msg, 'string', 'msg');
462
+ throw new Error(msg.val);
463
+ };
464
+
465
+ /**
466
+ * Warn with the given `msg` prefixed by "Warning: ".
467
+ *
468
+ * @param {String} msg
469
+ * @api public
470
+ */
471
+
472
+ exports.warn = function warn(msg){
473
+ utils.assertType(msg, 'string', 'msg');
474
+ console.warn('Warning: %s', msg.val);
475
+ return nodes.null;
476
+ };
477
+
478
+ /**
479
+ * Output stack trace.
480
+ *
481
+ * @api public
482
+ */
483
+
484
+ exports.trace = function trace(){
485
+ console.log(this.stack);
486
+ return nodes.null;
487
+ };
488
+
489
+ /**
490
+ * Push the given args to `expr`.
491
+ *
492
+ * @param {Expression} expr
493
+ * @param {Node} ...
494
+ * @return {Unit}
495
+ * @api public
496
+ */
497
+
498
+ (exports.push = exports.append = function(expr){
499
+ expr = utils.unwrap(expr);
500
+ for (var i = 1, len = arguments.length; i < len; ++i) {
501
+ expr.nodes.push(utils.unwrap(arguments[i]));
502
+ }
503
+ return new nodes.Unit(expr.nodes.length);
504
+ }).raw = true;
505
+
506
+ /**
507
+ * Unshift the given args to `expr`.
508
+ *
509
+ * @param {Expression} expr
510
+ * @param {Node} ...
511
+ * @return {Unit}
512
+ * @api public
513
+ */
514
+
515
+ (exports.unshift = exports.prepend = function(expr){
516
+ expr = utils.unwrap(expr);
517
+ for (var i = 1, len = arguments.length; i < len; ++i) {
518
+ expr.nodes.unshift(utils.unwrap(arguments[i]));
519
+ }
520
+ return new nodes.Unit(expr.nodes.length);
521
+ }).raw = true;
522
+
523
+ /**
524
+ * Return a `Literal` with the given `fmt`, and
525
+ * variable number of arguments.
526
+ *
527
+ * @param {String} fmt
528
+ * @param {Node} ...
529
+ * @return {Literal}
530
+ * @api public
531
+ */
532
+
533
+ (exports.s = function s(fmt){
534
+ fmt = utils.unwrap(fmt).nodes[0];
535
+ utils.assertString(fmt);
536
+ var self = this
537
+ , str = fmt.string
538
+ , args = arguments
539
+ , i = 1;
540
+
541
+ // format
542
+ str = str.replace(/%(s|d)/g, function(_, specifier){
543
+ var arg = args[i++] || nodes.null;
544
+ switch (specifier) {
545
+ case 's':
546
+ return new Compiler(arg, self.options).compile();
547
+ case 'd':
548
+ arg = utils.unwrap(arg).first;
549
+ if ('unit' != arg.nodeName) throw new Error('%d requires a unit');
550
+ return arg.val;
551
+ }
552
+ });
553
+
554
+ return new nodes.Literal(str);
555
+ }).raw = true;
556
+
557
+ /**
558
+ * Return the opposites of the given `positions`.
559
+ *
560
+ * Examples:
561
+ *
562
+ * opposite-position(top left)
563
+ * // => bottom right
564
+ *
565
+ * @param {Expression} positions
566
+ * @return {Expression}
567
+ * @api public
568
+ */
569
+
570
+ (exports['opposite-position'] = function oppositePosition(positions){
571
+ var expr = new nodes.Expression;
572
+ utils.unwrap(positions).nodes.forEach(function(pos, i){
573
+ utils.assertString(pos, 'position ' + i);
574
+ pos = (function(){ switch (pos.string) {
575
+ case 'top': return 'bottom';
576
+ case 'bottom': return 'top';
577
+ case 'left': return 'right';
578
+ case 'right': return 'left';
579
+ default: throw new Error('invalid position ' + pos);
580
+ }})();
581
+ expr.push(new nodes.Literal(pos));
582
+ });
583
+ return expr;
584
+ }).raw = true;
585
+
586
+ /**
587
+ * Return the width and height of the given `img` path.
588
+ *
589
+ * Examples:
590
+ *
591
+ * image-size('foo.png')
592
+ * // => 200px 100px
593
+ *
594
+ * image-size('foo.png')[0]
595
+ * // => 200px
596
+ *
597
+ * image-size('foo.png')[1]
598
+ * // => 100px
599
+ *
600
+ * @param {String} img
601
+ * @return {Expression}
602
+ * @api public
603
+ */
604
+
605
+ exports['image-size'] = function imageSize(img) {
606
+ utils.assertType(img, 'string', 'img');
607
+ var img = new Image(this, img.string);
608
+
609
+ // Read size
610
+ img.open();
611
+ var size = img.size();
612
+ img.close();
613
+
614
+ // Return (w h)
615
+ var expr = new nodes.Expression;
616
+ expr.push(new nodes.Unit(size[0], 'px'));
617
+ expr.push(new nodes.Unit(size[1], 'px'));
618
+
619
+ return expr;
620
+ };
621
+
622
+ /**
623
+ * Apply Math `fn` to `n`.
624
+ *
625
+ * @param {Unit} n
626
+ * @param {String} fn
627
+ * @return {Unit}
628
+ * @api private
629
+ */
630
+
631
+ exports['-math'] = function math(n, fn){
632
+ return new nodes.Unit(Math[fn.string](n.val), n.type);
633
+ };
634
+
635
+ /**
636
+ * Get Math `prop`.
637
+ *
638
+ * @param {String} prop
639
+ * @return {Unit}
640
+ * @api private
641
+ */
642
+
643
+ exports['-math-prop'] = function math(prop){
644
+ return new nodes.Unit(Math[prop.string]);
645
+ };
646
+
647
+ /**
648
+ * Buffer the given js `str`.
649
+ *
650
+ * @param {String} str
651
+ * @return {JSLiteral}
652
+ * @api private
653
+ */
654
+
655
+ exports.js = function js(str){
656
+ utils.assertString(str, 'str');
657
+ return new nodes.JSLiteral(str.val);
658
+ };
659
+
660
+ /**
661
+ * Adjust HSL `color` `prop` by `amount`.
662
+ *
663
+ * @param {RGBA|HSLA} color
664
+ * @param {String} prop
665
+ * @param {Unit} amount
666
+ * @return {RGBA}
667
+ * @api private
668
+ */
669
+
670
+ exports['-adjust'] = function adjust(color, prop, amount){
671
+ var hsl = color.hsla.clone();
672
+ prop = { hue: 'h', saturation: 's', lightness: 'l' }[prop.string];
673
+ if (!prop) throw new Error('invalid adjustment property');
674
+ var val = amount.val;
675
+ if ('%' == amount.type){
676
+ val = 'l' == prop && val > 0
677
+ ? (100 - hsl[prop]) * val / 100
678
+ : hsl[prop] * (val / 100);
679
+ }
680
+ hsl[prop] += val;
681
+ return hsl.rgba;
682
+ };
683
+
684
+ /**
685
+ * Return a clone of the given `expr`.
686
+ *
687
+ * @param {Expression} expr
688
+ * @return {Node}
689
+ * @api public
690
+ */
691
+
692
+ (exports.clone = function clone(expr){
693
+ utils.assertPresent(expr, 'expr');
694
+ return expr.clone();
695
+ }).raw = true;
696
+
697
+ /**
698
+ * Add property `name` with the given `expr`
699
+ * to the mixin-able block.
700
+ *
701
+ * @param {String|Ident|Literal} name
702
+ * @param {Expression} expr
703
+ * @return {Property}
704
+ * @api public
705
+ */
706
+
707
+ (exports['add-property'] = function addProperty(name, expr){
708
+ utils.assertType(name, 'expression', 'name');
709
+ name = utils.unwrap(name).first;
710
+ utils.assertString(name, 'name');
711
+ utils.assertType(expr, 'expression', 'expr');
712
+ var prop = new nodes.Property([name], expr);
713
+ var block = this.closestBlock;
714
+
715
+ var len = block.nodes.length
716
+ , head = block.nodes.slice(0, block.index)
717
+ , tail = block.nodes.slice(block.index++, len);
718
+ head.push(prop);
719
+ block.nodes = head.concat(tail);
720
+
721
+ return prop;
722
+ }).raw = true;