[Pkg-javascript-commits] [node-stylus] 04/12: Imported Upstream version 0.47.3

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Thu Jul 31 01:28:27 UTC 2014


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to branch master
in repository node-stylus.

commit 2895980a5183563fd94d1885b210afee7612f5ef
Author: Andrew Kelley <superjoe30 at gmail.com>
Date:   Thu Jul 31 00:22:31 2014 +0000

    Imported Upstream version 0.47.3
---
 History.md                          |  41 ++++
 bin/stylus                          |   6 +-
 docs/bifs.md                        | 118 ++++++++--
 docs/functions.md                   |  37 ++-
 docs/hashes.md                      |   2 +-
 docs/keyframes.md                   |   4 +-
 lib/functions/index.js              | 440 ++++++++++++++++++++++++++++++++++--
 lib/functions/index.styl            |  12 +-
 lib/functions/url.js                |   2 +-
 lib/lexer.js                        |  44 +++-
 lib/middleware.js                   |   5 +-
 lib/nodes/block.js                  |   5 +-
 lib/nodes/ident.js                  |   2 +
 lib/nodes/literal.js                |   5 +-
 lib/nodes/media.js                  |   5 +-
 lib/parser.js                       | 104 ++++-----
 lib/visitor/compiler.js             |   4 +-
 lib/visitor/evaluator.js            |   2 +-
 lib/visitor/normalizer.js           |  14 +-
 package.json                        |  19 +-
 test/cases/bifs.blend.css           |  15 ++
 test/cases/bifs.blend.styl          |  14 ++
 test/cases/bifs.components.css      | 123 +++++++++-
 test/cases/bifs.components.styl     | 138 ++++++++++-
 test/cases/bifs.contrast.css        |   9 +
 test/cases/bifs.contrast.styl       |   8 +
 test/cases/bifs.hsla.css            |   7 +
 test/cases/bifs.hsla.styl           |   6 +
 test/cases/bifs.invert.css          |   1 +
 test/cases/bifs.invert.styl         |   1 +
 test/cases/bifs.list-separator.css  |   5 +
 test/cases/bifs.list-separator.styl |   7 +
 test/cases/bifs.luminosity.css      |   7 +
 test/cases/bifs.luminosity.styl     |   6 +
 test/cases/bifs.transparentify.css  |  42 ++++
 test/cases/bifs.transparentify.styl |  41 ++++
 test/cases/bifs.url.css             |   3 +-
 test/cases/bifs.url.styl            |   3 +-
 test/cases/coercion.css             |   4 +-
 test/cases/coercion.styl            |   5 +-
 test/cases/functions.anonymous.css  |   3 +
 test/cases/functions.anonymous.styl |  11 +
 test/cases/keyframes.css            |   8 +
 test/cases/keyframes.styl           |  14 ++
 test/cases/literal.css              |  16 --
 test/cases/literal.styl             |  29 +--
 test/cases/media.complex.css        |   5 +
 test/cases/media.complex.styl       |   6 +
 test/cases/multiline.css            |   5 +-
 test/cases/multiline.styl           |  26 ++-
 test/cases/parse.css                |  37 +++
 test/cases/parse.styl               |  20 ++
 test/cases/regression.1584.css      |   7 +
 test/cases/regression.1584.styl     |  15 ++
 test/cases/regression.1623.css      |  15 ++
 test/cases/regression.1623.styl     |  47 ++++
 test/cases/selectors.css            |   6 +
 test/cases/selectors.styl           |   6 +
 58 files changed, 1388 insertions(+), 204 deletions(-)

diff --git a/History.md b/History.md
index 27074b3..ca52320 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,44 @@
+0.47.3 / 2014-07-22
+===================
+
+  * Fixed support for schema-less urls inside `url()`.
+
+0.47.2 / 2014-07-19
+===================
+
+  * Fixed comma-first multiline syntax, #1634.
+  * Fixed hsla arguments for different color functions, #1619.
+  * Fixed Bug with @media and placeholder selectors, #1625.
+  * Fixed bug with nested media queries, 1620.
+  * Fixed broken URL parsing for source and destination paths, #1613.
+
+0.47.1 / 2014-07-02
+===================
+
+  * Fixed treatment of unknown pseudo-elements, #1608.
+  * Fixed unit expression precedence error, #1611.
+
+0.47.0 / 2014-07-01
+===================
+
+  * Added support for anonymous functions, #1580.
+  * A lot of better color functions, #1526:
+      * Added support for two arguments for `hsla`.
+      * Added component setters (`red`, `hue`, `alpha` etc.).
+      * Added `luminosity` bif.
+      * Added `blend` bif.
+      * Added `contrast` bif.
+      * Added `transparentify` bif.
+  * Added `list-separator` bif, #1576.
+  * Added symlinks support to CLI, #1577.
+  * Added idents and units coercion, #1605.
+  * Fixed `@keyframes` parsing issue.
+  * Fixed parse error when `{` is on a new line in at-rules.
+  * Fixed an issue with multiline parsing.
+  * Fixed another issue with cached imports, #1587.
+  * Fixed illegal unary "%", missing left-hand operand, #1586.
+  * Reverted #1527.
+
 0.46.3 / 2014-06-09
 ===================
 
diff --git a/bin/stylus b/bin/stylus
index 9016ed9..344b6c3 100755
--- a/bin/stylus
+++ b/bin/stylus
@@ -504,7 +504,7 @@ function highlight(str) {
  */
 
 function compileCSSFile(file, fileOut) {
-  fs.lstat(file, function(err, stat){
+  fs.stat(file, function(err, stat){
     if (err) throw err;
     if (stat.isFile()) {
       fs.readFile(file, 'utf8', function(err, str){
@@ -561,7 +561,7 @@ function compileFiles(files) {
 function displayDeps() {
   files.forEach(function(file){
     // ensure file exists
-    fs.lstat(file, function(err, stat){
+    fs.stat(file, function(err, stat){
       if (err) throw err;
       fs.readFile(file, 'utf8', function(err, str){
         if (err) throw err;
@@ -583,7 +583,7 @@ function displayDeps() {
 
 function compileFile(file) {
   // ensure file exists
-  fs.lstat(file, function(err, stat){
+  fs.stat(file, function(err, stat){
     if (err) throw err;
     // file
     if (stat.isFile()) {
diff --git a/docs/bifs.md b/docs/bifs.md
index 21c492f..2df91cc 100644
--- a/docs/bifs.md
+++ b/docs/bifs.md
@@ -5,30 +5,39 @@ permalink: docs/bifs.html
 
 # Built-in Functions
 
-## red(color)
+## red(color[, value])
 
-Return the red component of the given `color`.
+Return the red component of the given `color`, or set the red component to the optional second `value` argument.
 
      red(#c00)
      // => 204
 
-## green(color)
+     red(#000, 255)
+     // => #f00
 
-Return the green component of the given `color`.
+## green(color[, value])
+
+Return the green component of the given `color`, or set the green component to the optional second `value` argument.
 
      green(#0c0)
      // => 204
 
-## blue(color)
+     green(#000, 255)
+     // => #0f0
+
+## blue(color[, value])
 
-Return the blue component of the given `color`.
+Return the blue component of the given `color`, or set the blue component to the optional second `value` argument.
 
      blue(#00c)
      // => 204
 
-## alpha(color)
+     blue(#000, 255)
+     // => #00f
+
+## alpha(color[, value])
 
-Return the alpha component of the given `color`.
+Return the alpha component of the given `color`, or set the alpha component to the optional second `value` argument.
 
       alpha(#fff)
       // => 1
@@ -36,6 +45,9 @@ Return the alpha component of the given `color`.
       alpha(rgba(0,0,0,0.3))
       // => 0.3
 
+      alpha(#fff, 0.5)
+      // => rgba(255,255,255,0.5)
+
 ## dark(color)
 
 Check if `color` is dark:
@@ -63,27 +75,36 @@ Check if `color` is light:
     light(#00FF40)
     // => true
 
-## hue(color)
+## hue(color[, value])
 
-Return the hue of the given `color`.
+Return the hue of the given `color`, or set the hue component to the optional second `value` argument.
 
     hue(hsla(50deg, 100%, 80%))
     // => 50deg
 
-## saturation(color)
+    hue(#00c, 90deg)
+    // => #6c0
+
+## saturation(color[, value])
 
-Return the saturation of the given `color`.
+Return the saturation of the given `color`, or set the saturation component to the optional second `value` argument.
 
     saturation(hsla(50deg, 100%, 80%))
     // => 100%
 
-## lightness(color)
+    saturation(#00c, 50%)
+    // => #339
 
-Return the lightness of the given `color`.
+## lightness(color[, value])
+
+Return the lightness of the given `color`, or set the lightness component to the optional second `value` argument.
 
     lightness(hsla(50deg, 100%, 80%))
     // => 80%
 
+    lightness(#00c, 80%)
+    // => #99f
+
 ## push(expr, args...)
 
  Push the given `args` to `expr`.
@@ -124,6 +145,18 @@ Return the lightness of the given `color`.
      values(pairs)
      // => 1 2 3
 
+## list-separator(list)
+
+  Return the separator of the given `list`.
+
+     list1 = a b c
+     list-separator(list1)
+     // => ' '
+
+     list2 = a, b, c
+     list-separator(list2)
+     // => ','
+
 ## typeof(node)
 
 Return type of `node` as a string.
@@ -354,6 +387,19 @@ Return a `RGBA` from the r,g,b channels or cast to an `RGBA` node.
     rgb(#fff)
     // => #fff
 
+## blend(top[, bottom])
+
+Blends the given `top` color over the `bottom` one using the normal blending. The `bottom` argument is optional and is defaulted to `#fff`.
+
+    blend(rgba(#FFF, 0.5), #000)
+    // => #808080
+
+    blend(rgba(#FFDE00,.42), #19C261)
+    // => #7ace38
+
+    blend(rgba(lime, 0.5), rgba(red, 0.25))
+    // => rgba(128,128,0,0.625)
+
 ## lighten(color, amount)
 
 Lighten the given `color` by `amount`. This function is
@@ -427,6 +473,50 @@ Mix the given color with black.
     shade(#fd0cc7,66%)
     // => #560443
 
+## luminosity(color)
+
+Returns the [relative luminance](http://www.w3.org/TR/WCAG20/#relativeluminancedef) of the given `color`.
+
+    luminosity(white)
+    // => 1
+
+    luminosity(#000)
+    // => 0
+
+    luminosity(red)
+    // => 0.2126
+
+## contrast(top[, bottom])
+
+Returns the [contrast ratio](http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef) object between `top` and `bottom` colors, based on [script](https://github.com/LeaVerou/contrast-ratio/blob/gh-pages/color.js#L108) underlying “[contrast ratio](http://leaverou.github.io/contrast-ratio/)” tool by Lea Verou.
+
+The second argument is optional and is defaulted to `#fff`.
+
+The main key in the returned object is `ratio`, it also have `min` and `max` values that are different from the `ratio` only when the `bottom` color is transparent. In that case the `error` also contains an error margin.
+
+    contrast(#000, #fff).ratio
+    => 21
+    contrast(#000, rgba(#FFF, 0.5))
+    => { "ratio": "13.15;", "error": "-7.85", "min": "5.3", "max": "21" }
+
+## transparentify(top[, bottom, alpha])
+
+Returns the transparent version of the given `top` color, as if it was blend over the given `bottom` color (or the closest to it, if it is possible).
+
+The second argument is optional and is defaulted to `#fff`.
+
+The third argument is optional and overrides the autodetected alpha.
+
+    transparentify(#808080)
+    => rgba(0,0,0,0.5)
+
+    transparentify(#414141, #000)
+    => rgba(255,255,255,0.25)
+
+    transparentify(#91974C, #F34949, 0.5)
+    => rgba(47,229,79,0.5)
+
+
 ## unquote(str | ident)
 
   Unquote the given `str` and returned as a `Literal` node.
diff --git a/docs/functions.md b/docs/functions.md
index 16d8214..b3086f4 100644
--- a/docs/functions.md
+++ b/docs/functions.md
@@ -159,12 +159,15 @@ Usage:
 
   In the same way that we can "alias" a function, we can pass a function as well. Here, our `invoke()` function accepts a function, so we can pass it `add()` or `sub()`.
 
-    invoke(a, b, fn)
-      fn(a, b)
-
     add(a, b)
       a + b
 
+    sub(a, b)
+      a - b
+
+    invoke(a, b, fn)
+      fn(a, b)
+
     body
       padding invoke(5, 10, add)
       padding invoke(5, 10, sub)
@@ -176,6 +179,34 @@ Yielding:
       padding: -5;
     }
 
+## Anonymous functions
+
+You can use anonymous functions where needed using `@(){}` syntax. Here is how you could use it to create a custom `sort()` function:
+
+    sort(list, fn = null)
+      // default sort function
+      if fn == null
+        fn = @(a, b) {
+          a > b
+        }
+
+      // bubble sort
+      for $i in 1..length(list) - 1
+        for $j in 0..$i - 1
+          if fn(list[$j], list[$i])
+            $temp = list[$i]
+            list[$i] = list[$j]
+            list[$j] = $temp
+      return list
+
+      sort('e' 'c' 'f' 'a' 'b' 'd')
+      // => 'a' 'b' 'c' 'd' 'e' 'f'
+
+      sort(5 3 6 1 2 4, @(a, b){
+        a < b
+      })
+      // => 6 5 4 3 2 1
+
 ## arguments
 
  The `arguments` local is available to all function bodies, and contains all the arguments passed. 
diff --git a/docs/hashes.md b/docs/hashes.md
index a8d37bd..75f9a1d 100644
--- a/docs/hashes.md
+++ b/docs/hashes.md
@@ -113,7 +113,7 @@ You can iterate through hashes with optional key param:
     // => width: 10px;
     //    height: 20px;
 
-You can check existance of a key in hash using `in`:
+You can check existence of a key in hash using `in`:
 
     foo = { bar: 10px}
 
diff --git a/docs/keyframes.md b/docs/keyframes.md
index a7358d0..fbb8c08 100644
--- a/docs/keyframes.md
+++ b/docs/keyframes.md
@@ -38,7 +38,7 @@ Yielding (expanded prefixes ommited):
 
 ## Expansion
 
-By using `@keyframes`, your rules are automatically expanded to the vendor prefixes defined by the `vendors` variable (default: `moz webkit o official`). This means we can alter it at any time for the expansion to take effect immediately. 
+By using `@keyframes`, your rules are automatically expanded to the vendor prefixes defined by the `vendors` variable (default: `moz webkit o ms official`). This means we can alter it at any time for the expansion to take effect immediately. 
 
 **Note that expansion of `@keyframes` to the prefixed at-rules would be removed from the Stylus 1.0 when we'd get to it**
  
@@ -53,7 +53,7 @@ For example, consider the following:
       }
     }
 
-This expands to our two default vendors, and the official syntax:
+This expands to our three default vendors, and the official syntax:
 
     @-moz-keyframes foo {
       from {
diff --git a/lib/functions/index.js b/lib/functions/index.js
index 21aad79..0889a4f 100644
--- a/lib/functions/index.js
+++ b/lib/functions/index.js
@@ -81,6 +81,17 @@ exports.hsla = function hsla(hue, saturation, lightness, alpha){
     case 1:
       utils.assertColor(hue);
       return hue.hsla;
+    case 2:
+      utils.assertColor(hue);
+      var color = hue.hsla;
+      utils.assertType(saturation, 'unit', 'alpha');
+      var alpha = saturation;
+      if ('%' == alpha.type) alpha.val /= 100;
+      return new nodes.HSLA(
+          color.h
+        , color.s
+        , color.l
+        , alpha.val);
     default:
       utils.assertType(hue, 'unit', 'hue');
       utils.assertType(saturation, 'unit', 'saturation');
@@ -233,54 +244,223 @@ exports.extname = function extname(p){
 }).raw = true;
 
 /**
- * Return the red component of the given `color`.
+ * Return the red component of the given `color`,
+ * or set the red component to the optional second `value` argument.
  *
  * Examples:
  *
  *    red(#c00)
  *    // => 204
  *
+ *    red(#000, 255)
+ *    // => #f00
+ *
  * @param {RGBA|HSLA} color
- * @return {Unit}
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
  * @api public
  */
 
-exports.red = function red(color){
-  return exports.component(color, new nodes.String('red'));
+exports.red = function red(color, value){
+  color = color.rgba;
+  if (value) {
+    return exports.rgba(
+      value,
+      new nodes.Unit(color.g),
+      new nodes.Unit(color.b),
+      new nodes.Unit(color.a)
+    );
+  }
+  return new nodes.Unit(color.r, '');
 };
 
 /**
- * Return the green component of the given `color`.
+ * Return the green component of the given `color`,
+ * or set the green component to the optional second `value` argument.
  *
  * Examples:
  *
  *    green(#0c0)
  *    // => 204
  *
+ *    green(#000, 255)
+ *    // => #0f0
+ *
  * @param {RGBA|HSLA} color
- * @return {Unit}
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
  * @api public
  */
 
-exports.green = function green(color){
-  return exports.component(color, new nodes.String('green'));
+exports.green = function green(color, value){
+  color = color.rgba;
+  if (value) {
+    return exports.rgba(
+      new nodes.Unit(color.r),
+      value,
+      new nodes.Unit(color.b),
+      new nodes.Unit(color.a)
+    );
+  }
+  return new nodes.Unit(color.g, '');
 };
 
 /**
- * Return the blue component of the given `color`.
+ * Return the blue component of the given `color`,
+ * or set the blue component to the optional second `value` argument.
  *
  * Examples:
  *
  *    blue(#00c)
  *    // => 204
  *
+ *    blue(#000, 255)
+ *    // => #00f
+ *
  * @param {RGBA|HSLA} color
- * @return {Unit}
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
+ * @api public
+ */
+
+exports.blue = function blue(color, value){
+  color = color.rgba;
+  if (value) {
+    return exports.rgba(
+      new nodes.Unit(color.r),
+      new nodes.Unit(color.g),
+      value,
+      new nodes.Unit(color.a)
+    );
+  }
+  return new nodes.Unit(color.b, '');
+};
+
+/**
+ * Return the alpha component of the given `color`,
+ * or set the alpha component to the optional second `value` argument.
+ *
+ * Examples:
+ *
+ *    alpha(#fff)
+ *    // => 1
+ *
+ *    alpha(rgba(0,0,0,0.3))
+ *    // => 0.3
+ *
+ *    alpha(#fff, 0.5)
+ *    // => rgba(255,255,255,0.5)
+ *
+ * @param {RGBA|HSLA} color
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
+ * @api public
+ */
+
+exports.alpha = function alpha(color, value){
+  color = color.rgba;
+  if (value) {
+    return exports.rgba(
+      new nodes.Unit(color.r),
+      new nodes.Unit(color.g),
+      new nodes.Unit(color.b),
+      value
+    );
+  }
+  return new nodes.Unit(color.a, '');
+};
+
+/**
+ * Return the hue component of the given `color`,
+ * or set the hue component to the optional second `value` argument.
+ *
+ * Examples:
+ *
+ *    hue(#00c)
+ *    // => 240deg
+ *
+ *    hue(#00c, 90deg)
+ *    // => #6c0
+ *
+ * @param {RGBA|HSLA} color
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
+ * @api public
+ */
+
+exports.hue = function hue(color, value){
+  if (value) {
+    var hslaColor = color.hsla;
+    return exports.hsla(
+      value,
+      new nodes.Unit(hslaColor.s),
+      new nodes.Unit(hslaColor.l),
+      new nodes.Unit(hslaColor.a)
+    )
+  }
+  return exports.component(color, new nodes.String('hue'));
+};
+
+/**
+ * Return the saturation component of the given `color`,
+ * or set the saturation component to the optional second `value` argument.
+ *
+ * Examples:
+ *
+ *    saturation(#00c)
+ *    // => 100%
+ *
+ *    saturation(#00c, 50%)
+ *    // => #339
+ *
+ * @param {RGBA|HSLA} color
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
+ * @api public
+ */
+
+exports.saturation = function saturation(color, value){
+  if (value) {
+    var hslaColor = color.hsla;
+    return exports.hsla(
+      new nodes.Unit(hslaColor.h),
+      value,
+      new nodes.Unit(hslaColor.l),
+      new nodes.Unit(hslaColor.a)
+    )
+  }
+  return exports.component(color, new nodes.String('saturation'));
+};
+
+/**
+ * Return the lightness component of the given `color`,
+ * or set the lightness component to the optional second `value` argument.
+ *
+ * Examples:
+ *
+ *    lightness(#00c)
+ *    // => 100%
+ *
+ *    lightness(#00c, 80%)
+ *    // => #99f
+ *
+ * @param {RGBA|HSLA} color
+ * @param {Unit} [value]
+ * @return {Unit|RGBA}
  * @api public
  */
 
-exports.blue = function blue(color){
-  return exports.component(color, new nodes.String('blue'));
+exports.lightness = function lightness(color, value){
+  if (value) {
+    var hslaColor = color.hsla;
+    return exports.hsla(
+      new nodes.Unit(hslaColor.h),
+      new nodes.Unit(hslaColor.s),
+      value,
+      new nodes.Unit(hslaColor.a)
+    )
+  }
+  return exports.component(color, new nodes.String('lightness'));
 };
 
 /**
@@ -309,12 +489,7 @@ exports.rgba = function rgba(red, green, blue, alpha){
   switch (arguments.length) {
     case 1:
       utils.assertColor(red);
-      var color = red.rgba;
-      return new nodes.RGBA(
-          color.r
-        , color.g
-        , color.b
-        , color.a);
+      return red.rgba;
     case 2:
       utils.assertColor(red);
       var color = red.rgba;
@@ -330,9 +505,9 @@ exports.rgba = function rgba(red, green, blue, alpha){
       utils.assertType(green, 'unit', 'green');
       utils.assertType(blue, 'unit', 'blue');
       utils.assertType(alpha, 'unit', 'alpha');
-      var r = '%' == red.type ? Math.round(red.val * 2.55) : red.val;
-      var g = '%' == green.type ? Math.round(green.val * 2.55) : green.val;
-      var b = '%' == blue.type ? Math.round(blue.val * 2.55) : blue.val;
+      var r = '%' == red.type ? Math.round(red.val * 2.55) : red.val
+        , g = '%' == green.type ? Math.round(green.val * 2.55) : green.val
+        , b = '%' == blue.type ? Math.round(blue.val * 2.55) : blue.val;
       if (alpha && '%' == alpha.type) alpha.val /= 100;
       return new nodes.RGBA(
           r
@@ -380,6 +555,206 @@ exports.rgb = function rgb(red, green, blue){
 };
 
 /**
+ * Blend the `top` color over the `bottom`
+ *
+ * Examples:
+ *
+ *     blend(rgba(#FFF, 0.5), #000)
+ *     // => #808080
+ * 
+ *     blend(rgba(#FFDE00,.42), #19C261)
+ *     // => #7ace38
+ * 
+ *     blend(rgba(lime, 0.5), rgba(red, 0.25))
+ *     // => rgba(128,128,0,0.625)
+ *
+ * @param {RGBA|HSLA} top
+ * @param {RGBA|HSLA} [bottom=#fff]
+ * @return {RGBA}
+ * @api public
+ */
+
+exports.blend = function blend(top, bottom){
+  // TODO: different blend modes like overlay etc.
+  utils.assertColor(top);
+  top = top.rgba;
+  bottom = bottom || new nodes.RGBA(255, 255, 255, 1);
+  utils.assertColor(bottom);
+  bottom = bottom.rgba;
+
+  return new nodes.RGBA(
+    top.r * top.a + bottom.r * (1 - top.a),
+    top.g * top.a + bottom.g * (1 - top.a),
+    top.b * top.a + bottom.b * (1 - top.a),
+    top.a + bottom.a - top.a * bottom.a);
+};
+
+/**
+ * Returns the relative luminance of the given `color`,
+ * see http://www.w3.org/TR/WCAG20/#relativeluminancedef
+ *
+ * Examples:
+ *
+ *     luminosity(white)
+ *     // => 1
+ * 
+ *     luminosity(#000)
+ *     // => 0
+ * 
+ *     luminosity(red)
+ *     // => 0.2126
+ *
+ * @param {RGBA|HSLA} color
+ * @return {Unit}
+ * @api public
+ */
+
+exports.luminosity = function luminosity(color){
+  utils.assertColor(color);
+  color = color.rgba;
+  function processChannel(channel) {
+    channel = channel / 255;
+    return (0.03928 > channel)
+      ? channel / 12.92
+      : Math.pow(((channel + 0.055) / 1.055), 2.4);
+  }
+  return new nodes.Unit(
+    0.2126 * processChannel(color.r)
+    + 0.7152 * processChannel(color.g)
+    + 0.0722 * processChannel(color.b)
+  );
+}
+
+/**
+ * Returns the contrast ratio object between `top` and `bottom` colors,
+ * based on http://leaverou.github.io/contrast-ratio/
+ * and https://github.com/LeaVerou/contrast-ratio/blob/gh-pages/color.js#L108
+ *
+ * Examples:
+ *
+ *     contrast(#000, #fff).ratio
+ *     => 21
+ *
+ *     contrast(#000, rgba(#FFF, 0.5))
+ *     => { "ratio": "13.15;", "error": "7.85", "min": "5.3", "max": "21" }
+ *
+ * @param {RGBA|HSLA} top
+ * @param {RGBA|HSLA} [bottom=#fff]
+ * @return {Object}
+ * @api public
+ */
+
+exports.contrast = function contrast(top, bottom){
+  var result = new nodes.Object();
+  utils.assertColor(top);
+  top = top.rgba;
+  bottom = bottom || new nodes.RGBA(255, 255, 255, 1);
+  utils.assertColor(bottom);
+  bottom = bottom.rgba;
+  function contrast(top, bottom) {
+    if (1 > top.a) {
+      top = exports.blend(top, bottom);
+    }
+    var l1 = exports.luminosity(bottom).val + 0.05
+      , l2 = exports.luminosity(top).val + 0.05
+      , ratio = l1 / l2;
+
+    if (l2 > l1) {
+      ratio = 1 / ratio;
+    }
+    return Math.round(ratio * 10) / 10;
+  }
+
+  if (1 <= bottom.a) {
+    var resultRatio = new nodes.Unit(contrast(top, bottom));
+    result.set('ratio', resultRatio);
+    result.set('error', new nodes.Unit(0));
+    result.set('min', resultRatio);
+    result.set('max', resultRatio);
+  } else {
+    var onBlack = contrast(top, exports.blend(bottom, new nodes.RGBA(0, 0, 0, 1)))
+      , onWhite = contrast(top, exports.blend(bottom, new nodes.RGBA(255, 255, 255, 1)))
+      , max = Math.max(onBlack, onWhite);
+    function processChannel(topChannel, bottomChannel) {
+      return Math.min(Math.max(0, (topChannel - bottomChannel * bottom.a) / (1 - bottom.a)), 255);
+    }
+    var closest = new nodes.RGBA(
+      processChannel(top.r, bottom.r),
+      processChannel(top.g, bottom.g),
+      processChannel(top.b, bottom.b),
+      1
+    );
+    var min = contrast(top, exports.blend(bottom, closest));
+
+    result.set('ratio', new nodes.Unit(Math.round((min + max) * 50) / 100));
+    result.set('error', new nodes.Unit(Math.round((max - min) * 50) / 100));
+    result.set('min', new nodes.Unit(min));
+    result.set('max', new nodes.Unit(max));
+  }
+  return result;
+}
+
+/**
+ * Returns the transparent version of the given `top` color,
+ * as if it was blend over the given `bottom` color.
+ *
+ * Examples:
+ *
+ *     transparentify(#808080)
+ *     => rgba(0,0,0,0.5)
+ *
+ *     transparentify(#414141, #000)
+ *     => rgba(255,255,255,0.25)
+ *
+ *     transparentify(#91974C, #F34949, 0.5)
+ *     => rgba(47,229,79,0.5)
+ *
+ * @param {RGBA|HSLA} top
+ * @param {RGBA|HSLA} [bottom=#fff]
+ * @param {Unit} [alpha]
+ * @return {RGBA}
+ * @api public
+ */
+exports.transparentify = function transparentify(top, bottom, alpha){
+  utils.assertColor(top);
+  top = top.rgba;
+  // Handle default arguments
+  bottom = bottom || new nodes.RGBA(255, 255, 255, 1);
+  if (!alpha && bottom && !bottom.rgba) {
+    alpha = bottom;
+    bottom = new nodes.RGBA(255, 255, 255, 1);
+  }
+  utils.assertColor(bottom);
+  bottom = bottom.rgba;
+  var bestAlpha = ['r', 'g', 'b'].map(function(channel){
+    return (top[channel] - bottom[channel]) / ((0 < (top[channel] - bottom[channel]) ? 255 : 0) - bottom[channel]);
+  }).sort(function(a, b){return a < b;})[0];
+  if (alpha) {
+    utils.assertType(alpha, 'unit', 'alpha');
+    if ('%' == alpha.type) {
+      bestAlpha = alpha.val / 100;
+    } else if (!alpha.type) {
+      bestAlpha = alpha = alpha.val;
+    }
+  }
+  bestAlpha = Math.max(Math.min(bestAlpha, 1), 0);
+  // Calculate the resulting color
+  function processChannel(channel) {
+    if (0 == bestAlpha) {
+      return bottom[channel]
+    } else {
+      return bottom[channel] + (top[channel] - bottom[channel]) / bestAlpha
+    }
+  }
+  return new nodes.RGBA(
+    processChannel('r'),
+    processChannel('g'),
+    processChannel('b'),
+    Math.round(bestAlpha * 100) / 100
+  );
+}
+
+/**
  * Convert a .json file into stylus variables or object.
  * Nested variable object keys are joined with a dash (-)
  *
@@ -1195,6 +1570,29 @@ exports['current-media'] = function currentMedia(){
 };
 
 /**
+ * Return the separator of the given `list`.
+ *
+ * Examples:
+ *
+ *    list1 = a b c
+ *    list-separator(list1)
+ *    // => ' '
+ *
+ *    list2 = a, b, c
+ *    list-separator(list2)
+ *    // => ','
+ *
+ * @param {Experssion} list
+ * @return {String}
+ * @api public
+ */
+
+(exports['list-separator'] = function listSeparator(list){
+  list = utils.unwrap(list);
+  return new nodes.String(list.isList ? ',' : ' ');
+}).raw = true;
+
+/**
  * Attempt to parse unit `str`.
  *
  * @param {String} str
diff --git a/lib/functions/index.styl b/lib/functions/index.styl
index 611796e..9e25525 100644
--- a/lib/functions/index.styl
+++ b/lib/functions/index.styl
@@ -89,13 +89,6 @@ percent-to-decimal(n)
   else
     n
 
-// color components
-
-alpha(color) { component(hsl(color), 'alpha') }
-hue(color) { component(hsl(color), 'hue') }
-saturation(color) { component(hsl(color), 'saturation') }
-lightness(color) { component(hsl(color), 'lightness') }
-
 // check if n is an odd number
 
 odd(n)
@@ -195,10 +188,7 @@ mix(color1, color2, weight = 50%)
 
 invert(color = '')
   if color is a 'color'
-    r = 255 - red(color)
-    g = 255 - green(color)
-    b = 255 - blue(color)
-    rgba(r,g,b,alpha(color))
+    rgba(#fff - color, alpha(color))
   else
     unquote( "invert(" + color + ")" )
 
diff --git a/lib/functions/url.js b/lib/functions/url.js
index bea63c4..fc8e450 100644
--- a/lib/functions/url.js
+++ b/lib/functions/url.js
@@ -98,7 +98,7 @@ module.exports = function(options) {
     // Read data
     buf = fs.readFileSync(found);
 
-    // To large
+    // Too large
     if (false !== sizeLimit && buf.length > sizeLimit) return literal;
 
     // Encode
diff --git a/lib/lexer.js b/lib/lexer.js
index 3d6dbbb..caf4511 100644
--- a/lib/lexer.js
+++ b/lib/lexer.js
@@ -60,13 +60,27 @@ function Lexer(str, options) {
   this.indentRe = null;
   this.lineno = 1;
 
+  // HACK!
+  function comment(str, val, offset, s) {
+    var commentIdx = s.lastIndexOf('//', offset)
+      , inComment = s.lastIndexOf('/*', offset) > s.lastIndexOf('*/', offset)
+        || (~commentIdx && commentIdx > s.lastIndexOf('\n', offset)
+        && commentIdx > s.lastIndexOf("'", offset)
+        && commentIdx > s.lastIndexOf('"', offset));
+    return inComment
+      ? str
+      : val + '\u0085';
+  };
+
   // Remove UTF-8 BOM.
   if ('\uFEFF' == str.charAt(0)) str = str.slice(1);
 
   this.str = str
     .replace(/\s+$/, '\n')
-    .replace(/\\ *\n/g, ' ')
-    .replace(/\r\n?/g, '\n');
+    .replace(/\\ *\n/g, '\u0085')
+    .replace(/\r\n?/g, '\n')
+    .replace(/((?:[,(]|:)(?!\/\/[^ ])) *(?:\/\/[^\n]*)?\n\s*/g, comment)
+    .replace(/\s*\n[ \t]*([,)])/g, comment);
 };
 
 /**
@@ -191,6 +205,7 @@ Lexer.prototype = {
       || this.boolean()
       || this.ident()
       || this.op()
+      || this.eol()
       || this.space()
       || this.selector();
   },
@@ -255,6 +270,18 @@ Lexer.prototype = {
       return new Token(';');
     }
   },
+
+  /**
+   * '\u0085'
+   */
+
+  eol: function() {
+    if ('\u0085' == this.str[0]) {
+      ++this.lineno;
+      this.skip(1);
+      return this.advance();
+    }
+  },
   
   /**
    * ' '+
@@ -470,15 +497,16 @@ Lexer.prototype = {
   },
 
   /**
-   * '@' (-(\w+)-)?[a-zA-Z0-9-_]+
+   * '@' (-(\w+)-)?[a-zA-Z0-9-_]*(?
    */
 
   atrule: function() {
     var captures;
-    if (captures = /^@(?:-(\w+)-)?([a-zA-Z0-9-_]+)[ \t]*/.exec(this.str)) {
+    if (captures = /^@(?:-(\w+)-)?([a-zA-Z0-9-_]*\(?)[ \t]*/.exec(this.str)) {
       this.skip(captures);
       var vendor = captures[1]
-        , type = captures[2];
+        , type = captures[2]
+        , tok;
       switch (type) {
         case 'require':
         case 'import':
@@ -491,6 +519,10 @@ Lexer.prototype = {
           return new Token('-moz-document');
         case 'block':
           return new Token('atblock');
+        case '(':
+          tok = new Token('function', new nodes.Ident('anonymous'));
+          tok.anonymous = true;
+          return tok;
         case 'extend':
         case 'extends':
           return new Token('extend');
@@ -575,7 +607,7 @@ Lexer.prototype = {
       return new Token('ident', new nodes.Ident(captures[0]));
     }
   },
-  
+
   /**
    * '\n' ' '+
    */
diff --git a/lib/middleware.js b/lib/middleware.js
index e19f40a..e231b88 100644
--- a/lib/middleware.js
+++ b/lib/middleware.js
@@ -112,8 +112,9 @@ module.exports = function(options){
 
       if (typeof dest == 'string' || typeof dest == 'function') {
         // check for dest-path overlap
-        var overlap = compare((typeof dest == 'function' ? dest(path) : dest), path);
-        path = path.slice(overlap.length);
+        var overlap = compare((typeof dest == 'function' ? dest(path) : dest), path).length;
+        if (sep == path.charAt(0)) overlap++;
+        path = path.slice(overlap);
       }
 
       var cssPath, stylusPath;
diff --git a/lib/nodes/block.js b/lib/nodes/block.js
index c758d99..05ec6bd 100644
--- a/lib/nodes/block.js
+++ b/lib/nodes/block.js
@@ -41,10 +41,7 @@ Block.prototype.__proto__ = Node.prototype;
 
 Block.prototype.__defineGetter__('hasProperties', function(){
   for (var i = 0, len = this.nodes.length; i < len; ++i) {
-    var node = this.nodes[i];
-    // real property or unquoted literal
-    if ('property' == node.nodeName
-      || (!node.css && 'literal' == node.nodeName)) {
+    if ('property' == this.nodes[i].nodeName) {
       return true;
     }
   }
diff --git a/lib/nodes/ident.js b/lib/nodes/ident.js
index 0a5420c..4ccb8db 100644
--- a/lib/nodes/ident.js
+++ b/lib/nodes/ident.js
@@ -119,6 +119,8 @@ Ident.prototype.coerce = function(other){
     case 'string':
     case 'literal':
       return new Ident(other.string);
+    case 'unit':
+      return new Ident(other.toString());
     default:
       return Node.prototype.coerce.call(this, other);
   }
diff --git a/lib/nodes/literal.js b/lib/nodes/literal.js
index e9858af..e1dd8fa 100644
--- a/lib/nodes/literal.js
+++ b/lib/nodes/literal.js
@@ -16,15 +16,13 @@ var Node = require('./node')
  * Initialize a new `Literal` with the given `str`.
  *
  * @param {String} str
- * @param {Boolean} [css]
  * @api public
  */
 
-var Literal = module.exports = function Literal(str, css){
+var Literal = module.exports = function Literal(str){
   Node.call(this);
   this.val = str;
   this.string = str;
-  this.css = css;
   this.prefixed = false;
 };
 
@@ -106,7 +104,6 @@ Literal.prototype.toJSON = function(){
     __type: 'Literal',
     val: this.val,
     string: this.string,
-    css: this.css,
     prefixed: this.prefixed,
     lineno: this.lineno,
     filename: this.filename
diff --git a/lib/nodes/media.js b/lib/nodes/media.js
index 4d134e6..3693a8b 100644
--- a/lib/nodes/media.js
+++ b/lib/nodes/media.js
@@ -86,8 +86,7 @@ Media.prototype.toString = function(){
 };
 
 function hasProperties(block) {
-  for (var i = 0, len = block.nodes.length; i < len; i++) {
-    var node = block.nodes[i];
+  return block.nodes.some(function(node) {
     switch (node.nodeName) {
       case 'property':
         return true;
@@ -98,5 +97,5 @@ function hasProperties(block) {
       default:
         if (node.block) return hasProperties(node.block);
     }
-  }
+  });
 }
diff --git a/lib/parser.js b/lib/parser.js
index aca76f4..b2668e4 100644
--- a/lib/parser.js
+++ b/lib/parser.js
@@ -1,4 +1,3 @@
-
 /*!
  * Stylus - Parser
  * Copyright(c) 2010 LearnBoost <dev at learnboost.com>
@@ -12,6 +11,7 @@
 var Lexer = require('./lexer')
   , nodes = require('./nodes')
   , Token = require('./token')
+  , units = require('./units')
   , errors = require('./errors')
   , cache = require('./cache');
 
@@ -225,6 +225,8 @@ Parser.prototype = {
     var block = this.parent = this.root;
     if (Parser.cache.has(this.hash)) {
       block = Parser.cache.get(this.hash);
+      // normalize cached imports
+      if ('block' == block.nodeName) block.constructor = nodes.Root;
     } else {
       while ('eos' != this.peek().type) {
         this.skipWhitespace();
@@ -471,12 +473,21 @@ Parser.prototype = {
   /**
    * Check if the following sequence of tokens
    * forms a selector.
+   *
+   * @param {Boolean} [fromProperty]
+   * @return {Boolean}
+   * @api private
    */
 
-  looksLikeSelector: function() {
+  looksLikeSelector: function(fromProperty) {
     var i = 1
       , brace;
 
+    // Real property
+    if (fromProperty && ':' == this.lookahead(i + 1).type
+      && (this.lookahead(i + 1).space || 'indent' == this.lookahead(i + 2).type))
+      return false;
+
     // Assume selector when an ident is
     // followed by a selector
     while ('ident' == this.lookahead(i).type
@@ -494,20 +505,19 @@ Parser.prototype = {
       if ('*' == this.lookahead(i).type && 'newline' == this.lookahead(i + 1).type)
         return true;
 
-      if (this.looksLikeAttributeSelector(i))
+      if (':' == this.lookahead(i).type
+        && ':' == this.lookahead(i + 1).type)
         return true;
 
-      if (':' == this.lookahead(i).type && !this.isPseudoSelector(i + 1)
-        && ('indent' == this.lookahead(i + 1).type
-        || 'function' == this.lookahead(i + 1).type))
-        return false;
+      if (this.looksLikeAttributeSelector(i))
+        return true;
 
       if (('=' == this.lookahead(i).type || 'function' == this.lookahead(i).type)
         && '{' == this.lookahead(i + 1).type)
         return false;
 
       if (':' == this.lookahead(i).type
-        && ':' != this.lookahead(i + 1).type && !this.isPseudoSelector(i + 1)
+        && !this.isPseudoSelector(i + 1)
         && this.lineContains('.'))
         return false;
 
@@ -591,7 +601,8 @@ Parser.prototype = {
    */
 
   looksLikeKeyframe: function() {
-    var i = 2;
+    var i = 2
+      , type;
     switch (this.lookahead(i).type) {
       case '{':
       case 'indent':
@@ -600,31 +611,12 @@ Parser.prototype = {
       case 'newline':
         while ('unit' == this.lookahead(++i).type
             || 'newline' == this.lookahead(i).type) ;
-        if ('indent' == this.lookahead(i).type) return true;
+        type = this.lookahead(i).type;
+        return 'indent' == type || '{' == type;
     }
   },
 
   /**
-   * Check if the current state allows object literal.
-   */
-
-  stateAllowsObject: function() {
-    switch (this.previousState()) {
-      case 'conditional':
-      case 'for':
-        return false;
-      // if a == 1 {
-      // if a = 1 {
-      // @media foo.bar {
-      case 'expression':
-      case 'assignment':
-      case 'media':
-        return !this.cond;
-    }
-    return true;
-  },
-
-  /**
    * Check if the current state supports selectors.
    */
 
@@ -808,6 +800,8 @@ Parser.prototype = {
 
     if (false === scope) block.scope = false;
 
+    this.accept('newline');
+
     // css-style
     if (this.accept('{')) {
       this.css++;
@@ -815,7 +809,7 @@ Parser.prototype = {
       this.skipWhitespace();
     } else {
       delim = 'outdent';
-      this.accept('indent');
+      this.expect('indent');
     }
 
     while (delim != this.peek().type) {
@@ -1065,7 +1059,6 @@ Parser.prototype = {
     }
 
     do {
-      this.accept('indent');
       query.push(this.queryExpr());
     } while (this.accept('&&'));
 
@@ -1357,7 +1350,7 @@ Parser.prototype = {
    */
 
   property: function() {
-    if (this.looksLikeSelector()) return this.selector();
+    if (this.looksLikeSelector(true)) return this.selector();
 
     // property
     var ident = this.interpolate()
@@ -1636,7 +1629,6 @@ Parser.prototype = {
       , keyword;
 
     do {
-      this.accept('newline') || this.accept('indent');
       // keyword
       if ('ident' == this.peek().type && ':' == this.lookahead(2).type) {
         keyword = this.next().val.string;
@@ -1647,7 +1639,6 @@ Parser.prototype = {
         args.push(this.expression());
       }
     } while (this.accept(','));
-    this.accept('outdent');
 
     return args;
   },
@@ -1657,19 +1648,9 @@ Parser.prototype = {
    */
 
   list: function() {
-    var node
-      , indent
-      , prev;
+    var node = this.expression();
 
-    if (this.inProperty) {
-      indent = this.accept('indent');
-    }
-    node = this.expression();
     while (this.accept(',')) {
-      prev = this.lexer.prev;
-      if (',' == prev.type) {
-        indent = this.accept('newline') || this.accept('indent');
-      }
       if (node.isList) {
         list.push(this.expression());
       } else {
@@ -1678,7 +1659,6 @@ Parser.prototype = {
         list.push(this.expression());
         node = list;
       }
-      if (indent) this.accept('outdent');
     }
     return node;
   },
@@ -1992,27 +1972,31 @@ Parser.prototype = {
    */
 
   primary: function() {
-    var op
-      , unit
-      , node;
-
+    var tok;
     this.skipSpacesAndComments();
 
     // Parenthesis
     if (this.accept('(')) {
       ++this.parens;
-      var expr = this.expression();
-      this.expect(')');
+      var expr = this.expression()
+        , paren = this.expect(')');
       --this.parens;
-      // (2 + 3)%, (2 + 3)px etc.
-      if (unit = this.accept('%') || this.accept('ident')) {
-        expr.push(new nodes.Ident(unit.val.string || '%'));
+      if (this.accept('%')) expr.push(new nodes.Ident('%'));
+      tok = this.peek();
+      // (1 + 2)px, (1 + 2)em, etc.
+      if (!paren.space
+        && 'ident' == tok.type
+        && ~units.indexOf(tok.val.string)) {
+        expr.push(new nodes.Ident(tok.val.string));
+        this.next();
       }
       return expr;
     }
 
+    tok = this.peek();
+
     // Primitive
-    switch (this.peek().type) {
+    switch (tok.type) {
       case 'null':
       case 'unit':
       case 'color':
@@ -2020,7 +2004,7 @@ Parser.prototype = {
       case 'literal':
       case 'boolean':
         return this.next().val;
-      case this.stateAllowsObject() && '{':
+      case !this.cond && '{':
         return this.object();
       case 'atblock':
         return this.atblock();
@@ -2032,7 +2016,9 @@ Parser.prototype = {
       case 'ident':
         return this.ident();
       case 'function':
-        return this.functionCall();
+        return tok.anonymous
+          ? this.functionDefinition()
+          : this.functionCall();
     }
   }
 };
diff --git a/lib/visitor/compiler.js b/lib/visitor/compiler.js
index 30bbb43..92f4ac4 100644
--- a/lib/visitor/compiler.js
+++ b/lib/visitor/compiler.js
@@ -158,9 +158,7 @@ Compiler.prototype.visitBlock = function(block){
         }
         break;
       case 'literal':
-        if (node.css) {
-          this.buf += this.visit(node) + '\n';
-        }
+        this.buf += this.visit(node) + '\n';
         break;
     }
   }
diff --git a/lib/visitor/evaluator.js b/lib/visitor/evaluator.js
index 4b12815..3de51da 100644
--- a/lib/visitor/evaluator.js
+++ b/lib/visitor/evaluator.js
@@ -59,7 +59,7 @@ function importFile(node, file, literal, index) {
   nodes.filename = file;
 
   var str = fs.readFileSync(file, 'utf8');
-  if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n'), true);
+  if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n'));
 
   // parse
   var block = new nodes.Block
diff --git a/lib/visitor/normalizer.js b/lib/visitor/normalizer.js
index 31aa35e..e67f156 100644
--- a/lib/visitor/normalizer.js
+++ b/lib/visitor/normalizer.js
@@ -31,7 +31,6 @@ var Normalizer = module.exports = function Normalizer(root, options) {
   options = options || {};
   Visitor.call(this, root);
   this.stack = [];
-  this.extends = {};
   this.map = {};
 };
 
@@ -49,8 +48,6 @@ Normalizer.prototype.__proto__ = Visitor.prototype;
  */
 
 Normalizer.prototype.normalize = function(){
-  // normalize cached imports
-  if ('block' == this.root.nodeName) this.root.constructor = nodes.Root;
   return this.visit(this.root);
 };
 
@@ -152,7 +149,6 @@ Normalizer.prototype.visitBlock = function(block){
 
   if (block.hasProperties) {
     for (var i = 0, len = block.nodes.length; i < len; ++i) {
-      this.last = len - 1 == i;
       node = block.nodes[i];
       switch (node.nodeName) {
         case 'null':
@@ -256,13 +252,11 @@ Normalizer.prototype.visitMedia = function(media){
     var block = new nodes.Block(media.block);
     block.push(media);
     medias.forEach(function(node){
-      if (node.bubbled) {
-        if (!media.block.parent.node) {
-          node.group.block = node.block.nodes[0].block;
-          node.block.nodes[0] = node.group;
-        }
-        media.block.parent.push(node);
+      if (node.bubbled && !media.block.parent.node) {
+        node.group.block = node.block.nodes[0].block;
+        node.block.nodes[0] = node.group;
       }
+      media.block.parent.push(node);
       block.push(node);
     });
     return block;
diff --git a/package.json b/package.json
index e7f96c9..b6f8ccd 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "stylus",
   "description": "Robust, expressive, and feature-rich CSS superset",
-  "version": "0.46.3",
+  "version": "0.47.3",
   "author": "TJ Holowaychuk <tj at vision-media.ca>",
   "keywords": [
     "css",
@@ -11,7 +11,10 @@
     "jade",
     "language"
   ],
-  "repository": "git://github.com/LearnBoost/stylus",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/LearnBoost/stylus"
+  },
   "main": "./index.js",
   "browserify": "./lib/browserify.js",
   "engines": {
@@ -36,5 +39,15 @@
     "should": "2.x",
     "mocha": "*",
     "jscoverage": "0.3.8"
-  }
+  },
+  "bugs": {
+    "url": "https://github.com/LearnBoost/stylus/issues"
+  },
+  "homepage": "https://github.com/LearnBoost/stylus",
+  "directories": {
+    "doc": "docs",
+    "example": "examples",
+    "test": "test"
+  },
+  "license": "MIT"
 }
diff --git a/test/cases/bifs.blend.css b/test/cases/bifs.blend.css
new file mode 100644
index 0000000..d233e1c
--- /dev/null
+++ b/test/cases/bifs.blend.css
@@ -0,0 +1,15 @@
+.test {
+  color: #808080;
+  background: #808080;
+  border-color: #fff;
+  border-bottom-color: #7ace38;
+}
+.test_simples {
+  color: #0f0;
+  color: #0f0;
+  color: rgba(128,128,0,0.625);
+}
+.test_hsla {
+  color: #004d00;
+  color: #356020;
+}
diff --git a/test/cases/bifs.blend.styl b/test/cases/bifs.blend.styl
new file mode 100644
index 0000000..739a80c
--- /dev/null
+++ b/test/cases/bifs.blend.styl
@@ -0,0 +1,14 @@
+.test
+  color: blend(rgba(0,0,0,0.5))
+  background: blend(rgba(255,255,255,0.5), #000)
+  border-color: blend(rgba(#FFF,0.7))
+  border-bottom-color: blend(rgba(#FFDE00,.42), #19C261)
+
+.test_simples
+  color: blend(rgba(red, 0), lime)
+  color: blend(lime, red)
+  color: blend(rgba(lime, 0.5), rgba(red, 0.25))
+
+.test_hsla
+  color: blend(rgba(lime,.3), hsl(200,0%,0%))
+  color: blend(hsla(100,50%,50%,0.5), hsla(200,0%,0%,1))
diff --git a/test/cases/bifs.components.css b/test/cases/bifs.components.css
index dc77fa4..6b1559d 100644
--- a/test/cases/bifs.components.css
+++ b/test/cases/bifs.components.css
@@ -3,7 +3,128 @@ body {
   background: 204;
   background: 0;
   background: 0.4;
+}
+.setters {
+  background: #0c0;
+  background: #f00;
+  background: #fc0;
+  background: rgba(255,255,255,0.5);
+  background: #3c0;
+  background: #f30;
+  background: #fc3;
+  background: rgba(255,255,255,0.5);
+}
+body {
+  background: 255;
+  background: 204;
+  background: 0;
+  background: 0.4;
+}
+.setters {
+  background: #0c0;
+  background: #f00;
+  background: #fc0;
+  background: rgba(255,255,255,0.5);
+  background: #3c0;
+  background: #f30;
+  background: #fc3;
+  background: rgba(255,255,255,0.5);
+}
+body {
+  background: 255;
+  background: 204;
+  background: 0;
+  background: 0.4;
+}
+.setters {
+  background: rgba(0,204,0,0.5);
+  background: rgba(255,0,0,0.5);
+  background: rgba(255,204,0,0.5);
+  background: rgba(255,255,255,0.5);
+  background: rgba(51,204,0,0.5);
+  background: rgba(255,51,0,0.5);
+  background: rgba(255,204,51,0.5);
+  background: rgba(255,255,255,0.5);
+}
+body {
+  background: 255;
+  background: 204;
+  background: 0;
+  background: 0.4;
+}
+.setters {
+  background: #0c0;
+  background: #f00;
+  background: #fc0;
+  background: rgba(255,255,255,0.5);
+  background: #3c0;
+  background: #f30;
+  background: #fc3;
+  background: rgba(255,255,255,0.5);
+}
+body {
+  background: 255;
+  background: 204;
+  background: 0;
+  background: 0.4;
+}
+.setters {
+  background: rgba(0,204,0,0.5);
+  background: rgba(255,0,0,0.5);
+  background: rgba(255,204,0,0.5);
+  background: rgba(255,255,255,0.5);
+  background: rgba(51,204,0,0.5);
+  background: rgba(255,51,0,0.5);
+  background: rgba(255,204,51,0.5);
+  background: rgba(255,255,255,0.5);
+}
+body {
+  background: 15deg;
+  background: 100%;
+  background: 60%;
+}
+.setters {
+  background: #6c0;
+  background: #339;
+  background: #ccf;
+}
+body {
+  background: 15deg;
+  background: 100%;
+  background: 60%;
+}
+.setters {
+  background: #6c0;
+  background: #339;
+  background: #ccf;
+}
+body {
+  background: 15deg;
+  background: 100%;
+  background: 60%;
+}
+.setters {
+  background: rgba(102,204,0,0.5);
+  background: rgba(51,51,153,0.5);
+  background: rgba(204,204,255,0.5);
+}
+body {
+  background: 15deg;
+  background: 100%;
+  background: 60%;
+}
+.setters {
+  background: #6c0;
+  background: #339;
+  background: #ccf;
+}
+body {
   background: 15deg;
   background: 100%;
   background: 60%;
-}
\ No newline at end of file
+}
+.setters {
+  background: rgba(102,204,0,0.5);
+  background: rgba(51,51,153,0.5);
+  background: rgba(204,204,255,0.5);
+}
diff --git a/test/cases/bifs.components.styl b/test/cases/bifs.components.styl
index dc8b9a6..8ec88cf 100644
--- a/test/cases/bifs.components.styl
+++ b/test/cases/bifs.components.styl
@@ -1,9 +1,143 @@
+// red, green, blue & alpha components
+
+// --- hex
 body
   background red(#fc0)
   background green(#fc0)
   background blue(#fc0)
   background alpha(#fff - rgba(0,0,0,.6))
-  
+
+.setters
+  background red(#fc0, 0)
+  background green(#fc0, 0)
+  background blue(#fc0, 0)
+  background alpha(#fff, 0.5)
+  background red(#fc0, 20%)
+  background green(#fc0, 20%)
+  background blue(#fc0, 20%)
+  background alpha(#fff, 50%)
+
+// --- rgb
+body
+  background red(rgb(255,204,0))
+  background green(rgb(255,204,0))
+  background blue(rgb(255,204,0))
+  background alpha(rgb(255,255,255) - rgba(0,0,0,.6))
+
+.setters
+  background red(rgb(255,204,0), 0)
+  background green(rgb(255,204,0), 0)
+  background blue(rgb(255,204,0), 0)
+  background alpha(rgb(255,255,255), 0.5)
+  background red(rgb(255,204,0), 20%)
+  background green(rgb(255,204,0), 20%)
+  background blue(rgb(255,204,0), 20%)
+  background alpha(rgb(255,255,255), 50%)
+
+// --- rgba
+body
+  background red(rgba(255,204,0,0.5))
+  background green(rgba(255,204,0,0.5))
+  background blue(rgba(255,204,0,0.5))
+  background alpha(rgba(255,255,255,1) - rgba(0,0,0,.6))
+
+.setters
+  background red(rgba(255,204,0,0.5), 0)
+  background green(rgba(255,204,0,0.5), 0)
+  background blue(rgba(255,204,0,0.5), 0)
+  background alpha(rgba(255,255,255,1), 0.5)
+  background red(rgba(255,204,0,0.5), 20%)
+  background green(rgba(255,204,0,0.5), 20%)
+  background blue(rgba(255,204,0,0.5), 20%)
+  background alpha(rgba(255,255,255,1), 50%)
+
+// --- hsl
+body
+  background red(hsl(48,100,50))
+  background green(hsl(48,100,50))
+  background blue(hsl(48,100,50))
+  background alpha(hsl(0,0,100) - rgba(0,0,0,.6))
+
+.setters
+  background red(hsl(48,100,50), 0)
+  background green(hsl(48,100,50), 0)
+  background blue(hsl(48,100,50), 0)
+  background alpha(hsl(0,0,100), 0.5)
+  background red(hsl(48,100,50), 20%)
+  background green(hsl(48,100,50), 20%)
+  background blue(hsl(48,100,50), 20%)
+  background alpha(hsl(0,0,100), 50%)
+
+// --- hsla
+body
+  background red(hsla(48,100,50,0.5))
+  background green(hsla(48,100,50,0.5))
+  background blue(hsla(48,100,50,0.5))
+  background alpha(hsla(0,0,100,1) - rgba(0,0,0,.6))
+
+.setters
+  background red(hsla(48,100,50,0.5), 0)
+  background green(hsla(48,100,50,0.5), 0)
+  background blue(hsla(48,100,50,0.5), 0)
+  background alpha(hsla(0,0,100,1), 0.5)
+  background red(hsla(48,100,50,0.5), 20%)
+  background green(hsla(48,100,50,0.5), 20%)
+  background blue(hsla(48,100,50,0.5), 20%)
+  background alpha(hsla(0,0,100,1), 50%)
+
+// hue, saturation, lightness components
+
+// --- hex
+body
+  background hue(#f63)
+  background saturation(#f63)
+  background lightness(#f63)
+
+.setters
+  background hue(#00c, 90deg)
+  background saturation(#00c, 50%)
+  background lightness(#00c, 90%)
+
+// --- rgb
+body
+  background hue(rgb(255,102,51))
+  background saturation(rgb(255,102,51))
+  background lightness(rgb(255,102,51))
+
+.setters
+  background hue(rgb(0,0,204), 90deg)
+  background saturation(rgb(0,0,204), 50%)
+  background lightness(rgb(0,0,204), 90%)
+
+// --- rgba
+body
+  background hue(rgba(255,102,51,0.5))
+  background saturation(rgba(255,102,51,0.5))
+  background lightness(rgba(255,102,51,0.5))
+
+.setters
+  background hue(rgba(0,0,204,0.5), 90deg)
+  background saturation(rgba(0,0,204,0.5), 50%)
+  background lightness(rgba(0,0,204,0.5), 90%)
+
+// --- hsl
+body
   background hue(hsl(15deg,100%,60%))
   background saturation(hsl(15deg,100%,60%))
-  background lightness(hsl(15deg,100%,60%))
\ No newline at end of file
+  background lightness(hsl(15deg,100%,60%))
+
+.setters
+  background hue(hsl(240,100,40), 90deg)
+  background saturation(hsl(240,100,40), 50%)
+  background lightness(hsl(240,100,40), 90%)
+
+// --- hsla
+body
+  background hue(hsla(15deg,100%,60%,0.5))
+  background saturation(hsla(15deg,100%,60%,0.5))
+  background lightness(hsla(15deg,100%,60%,0.5))
+
+.setters
+  background hue(hsla(240,100,40,0.5), 90deg)
+  background saturation(hsla(240,100,40,0.5), 50%)
+  background lightness(hsla(240,100,40,0.5), 90%)
diff --git a/test/cases/bifs.contrast.css b/test/cases/bifs.contrast.css
new file mode 100644
index 0000000..4249d13
--- /dev/null
+++ b/test/cases/bifs.contrast.css
@@ -0,0 +1,9 @@
+.test {
+  test1: 21;
+  test2: 1;
+  test3: 2.9;
+  test4: 13.15;
+  test4_min: 5.3;
+  test4_max: 21;
+  test5: 6.3;
+}
\ No newline at end of file
diff --git a/test/cases/bifs.contrast.styl b/test/cases/bifs.contrast.styl
new file mode 100644
index 0000000..0cb0ab0
--- /dev/null
+++ b/test/cases/bifs.contrast.styl
@@ -0,0 +1,8 @@
+.test
+  test1: contrast(#000).ratio
+  test2: contrast(#fff, white).ratio
+  test3: contrast(red, lime).ratio
+  test4: contrast(#000, rgba(#FFF, 0.5)).ratio
+  test4_min: contrast(#000, rgba(#FFF, 0.5)).min
+  test4_max: contrast(#000, rgba(#FFF, 0.5)).max
+  test5: contrast(hsla(200,50%,50%,1), hsla(200,0%,00%,1)).ratio
\ No newline at end of file
diff --git a/test/cases/bifs.hsla.css b/test/cases/bifs.hsla.css
new file mode 100644
index 0000000..c62be57
--- /dev/null
+++ b/test/cases/bifs.hsla.css
@@ -0,0 +1,7 @@
+body {
+  background: #39ac99;
+  background: rgba(57,172,153,0.5);
+  background: rgba(57,172,153,0.1);
+  background: #39ac99;
+  background: rgba(57,172,153,0.5);
+}
diff --git a/test/cases/bifs.hsla.styl b/test/cases/bifs.hsla.styl
new file mode 100644
index 0000000..65454e4
--- /dev/null
+++ b/test/cases/bifs.hsla.styl
@@ -0,0 +1,6 @@
+body
+  background hsla(170, 50%, 45%, 1)
+  background hsla(170, 50%, 45%, 0.5)
+  background hsla(170,50%,45%,0.1)
+  background hsla(#39AC99)
+  background hsla(#39AC99, 0.5)
diff --git a/test/cases/bifs.invert.css b/test/cases/bifs.invert.css
index fc7645f..4806b58 100644
--- a/test/cases/bifs.invert.css
+++ b/test/cases/bifs.invert.css
@@ -5,6 +5,7 @@ body {
 }
 body {
   foo: rgba(220,131,209,0.5);
+  foo: rgba(220,131,209,0.25);
 }
 body {
   foo: invert();
diff --git a/test/cases/bifs.invert.styl b/test/cases/bifs.invert.styl
index fcee847..88bfacb 100644
--- a/test/cases/bifs.invert.styl
+++ b/test/cases/bifs.invert.styl
@@ -5,6 +5,7 @@ body
 
 body
   foo invert(rgba(35,124,46,0.5))
+  foo invert(rgba(35,124,46,0.25))
 
 body
   foo invert()
diff --git a/test/cases/bifs.list-separator.css b/test/cases/bifs.list-separator.css
new file mode 100644
index 0000000..d7b0233
--- /dev/null
+++ b/test/cases/bifs.list-separator.css
@@ -0,0 +1,5 @@
+body {
+  test: true;
+  test: true;
+  test: true;
+}
diff --git a/test/cases/bifs.list-separator.styl b/test/cases/bifs.list-separator.styl
new file mode 100644
index 0000000..0fda449
--- /dev/null
+++ b/test/cases/bifs.list-separator.styl
@@ -0,0 +1,7 @@
+list1 = 1 2 3
+list2 = 4, 5, 6
+
+body
+  test: list-separator(list1) == ' '
+  test: list-separator(list2) == ','
+  test: list-separator(1px) == ' '
diff --git a/test/cases/bifs.luminosity.css b/test/cases/bifs.luminosity.css
new file mode 100644
index 0000000..ffb2dda
--- /dev/null
+++ b/test/cases/bifs.luminosity.css
@@ -0,0 +1,7 @@
+.test {
+  test1: 1;
+  test2: 0;
+  test3: 0.2126;
+  test4: 0;
+  test5: 0.215860500113899;
+}
diff --git a/test/cases/bifs.luminosity.styl b/test/cases/bifs.luminosity.styl
new file mode 100644
index 0000000..1f8f488
--- /dev/null
+++ b/test/cases/bifs.luminosity.styl
@@ -0,0 +1,6 @@
+.test
+  test1: luminosity(white)
+  test2: luminosity(#000)
+  test3: luminosity(red)
+  test4: luminosity(hsla(200,0%,0%,1))
+  test5: luminosity(hsl(200,0%,50%))
diff --git a/test/cases/bifs.transparentify.css b/test/cases/bifs.transparentify.css
new file mode 100644
index 0000000..717b805
--- /dev/null
+++ b/test/cases/bifs.transparentify.css
@@ -0,0 +1,42 @@
+.test1 {
+  color: rgba(255,255,255,0);
+}
+.test2 {
+  color: #000;
+}
+.test3 {
+  color: rgba(0,0,0,0.5);
+}
+.test4 {
+  color: rgba(255,255,255,0.5);
+}
+.test5 {
+  color: rgba(255,255,255,0.25);
+}
+.test6 {
+  color: rgba(255,0,0,0.5);
+}
+.test7 {
+  color: rgba(0,124,104,0.26);
+}
+.test8 {
+  color: rgba(87,0,55,0.77);
+}
+.test9 {
+  color: rgba(14,255,80,0.43);
+}
+.test10 {
+  color: rgba(47,229,79,0.5);
+}
+.test11 {
+  color: rgba(74,74,74,0.7);
+}
+.test12 {
+  color: rgba(183,183,183,0.7);
+}
+.test13 {
+  color: rgba(145,0,129,0.67);
+}
+.test14 {
+  color: rgba(0,72,108,0.76);
+}
diff --git a/test/cases/bifs.transparentify.styl b/test/cases/bifs.transparentify.styl
new file mode 100644
index 0000000..b1de93f
--- /dev/null
+++ b/test/cases/bifs.transparentify.styl
@@ -0,0 +1,41 @@
+.test1
+  color: transparentify(#FFF)
+
+.test2
+  color: transparentify(#000)
+
+.test3
+  color: transparentify(#808080)
+
+.test4
+  color: transparentify(#808080, #000)
+
+.test5
+  color: transparentify(#414141, #000)
+
+.test6
+  color: transparentify(#FF7F7F)
+
+.test7
+  color: transparentify(#BDDDD8)
+
+.test8
+  color: transparentify(#7E3B65)
+
+.test9
+  color: transparentify(#91974C, #F34949)
+
+.test10
+  color: transparentify(#91974C, #F34949, 0.5)
+
+.test11
+  color: transparentify(#808080, 0.7)
+
+.test12
+  color: transparentify(#808080, #000, 0.7)
+
+.test13
+  color: transparentify(#AE1268, #E93636)
+
+.test14
+  color: transparentify(hsla(200,40%,40%,.3), hsla(200,0%,100%,1))
diff --git a/test/cases/bifs.url.css b/test/cases/bifs.url.css
index 98189d4..4daac42 100644
--- a/test/cases/bifs.url.css
+++ b/test/cases/bifs.url.css
@@ -9,4 +9,5 @@ body {
   background: url("/images/foo.png");
   background: url("/images/foo.png");
   background: url("http://foo.com/images/bar.png");
-}
\ No newline at end of file
+  background: url("//foo.com/images/bar.png");
+}
diff --git a/test/cases/bifs.url.styl b/test/cases/bifs.url.styl
index 23092c0..532927c 100644
--- a/test/cases/bifs.url.styl
+++ b/test/cases/bifs.url.styl
@@ -15,4 +15,5 @@ body
   list = foo bar
   background url('/images/' + list[0] + '.png')
 
-  background url(http://foo.com/images/bar.png)
\ No newline at end of file
+  background url(http://foo.com/images/bar.png)
+  background url(//foo.com/images/bar.png)
diff --git a/test/cases/coercion.css b/test/cases/coercion.css
index 1bdb2cd..0bd552a 100644
--- a/test/cases/coercion.css
+++ b/test/cases/coercion.css
@@ -11,5 +11,7 @@ body {
   foo: 2in;
   foo: 50cm;
   foo: 12.834645669291339pt;
+  foo: bar10px;
+  foo: bar10em;
+  foo: bar10;
 }
-
diff --git a/test/cases/coercion.styl b/test/cases/coercion.styl
index e634555..beae6ae 100644
--- a/test/cases/coercion.styl
+++ b/test/cases/coercion.styl
@@ -10,4 +10,7 @@ body
   foo 1in + 25.4mm
   foo 1in + 2.54cm
   foo (100cm / 2cm)
-  foo 10pt + 1mm
\ No newline at end of file
+  foo 10pt + 1mm
+  foo bar + 10px
+  foo bar + 10em
+  foo bar + 10
diff --git a/test/cases/functions.anonymous.css b/test/cases/functions.anonymous.css
new file mode 100644
index 0000000..0becd82
--- /dev/null
+++ b/test/cases/functions.anonymous.css
@@ -0,0 +1,3 @@
+body {
+  width: 25;
+}
diff --git a/test/cases/functions.anonymous.styl b/test/cases/functions.anonymous.styl
new file mode 100644
index 0000000..152a174
--- /dev/null
+++ b/test/cases/functions.anonymous.styl
@@ -0,0 +1,11 @@
+mixin(add) {
+  mul = @(c, d) {
+    c * d
+  }
+  width: add(2, 3) + mul(4, 5)
+}
+
+body
+  mixin(@(a, b) {
+    return a + b;
+  })
diff --git a/test/cases/keyframes.css b/test/cases/keyframes.css
index 6de6a37..ef12fba 100644
--- a/test/cases/keyframes.css
+++ b/test/cases/keyframes.css
@@ -224,3 +224,11 @@
     color: #ff0;
   }
 }
+ at keyframes foo {
+  0% {
+    color: #f00;
+  }
+  100% {
+    color: #00f;
+  }
+}
diff --git a/test/cases/keyframes.styl b/test/cases/keyframes.styl
index a2f8126..950aac2 100644
--- a/test/cases/keyframes.styl
+++ b/test/cases/keyframes.styl
@@ -57,3 +57,17 @@ for i in 1..3
       color: blue
     100%
       color: green
+
+vendors = official
+ at keyframes foo
+{
+  0%
+  {
+    color: red;
+  }
+
+  100%
+  {
+    color: blue;
+  }
+}
diff --git a/test/cases/literal.css b/test/cases/literal.css
index 03b9e6c..b905bc0 100644
--- a/test/cases/literal.css
+++ b/test/cases/literal.css
@@ -3,19 +3,3 @@ body {
 }
 
 a { text-decoration: none; }
-#login {
-  border-radius: /;
-  border-radius: true;
-  border-radius: true;
-}
-#login {
-  color: #f00;
-background: url("test.png");
-}
-#test,
-#logon {
-width: 100%
-}
-#logon {
-  color: #f00;
-}
diff --git a/test/cases/literal.styl b/test/cases/literal.styl
index 500e4a6..f92c83b 100644
--- a/test/cases/literal.styl
+++ b/test/cases/literal.styl
@@ -2,33 +2,6 @@
   body {
     font: 14px;
   }
-  
-  a { text-decoration: none; }
-}
-
-
-border-radius() {
-  border-radius: arguments[2];
-  border-radius: arguments[2] == '/';
-  border-radius: '/' == arguments[2];
-}
-
-#login {
-  border-radius: 1px 2px / 3px 4px;
-}
 
-#login {
-  color: red;
-  @css {
-    background: url("test.png");
-  }
-}
-
-#test {
-  @css { width: 100% }
-}
-
-#logon {
-  @extend #test
-  color: red
+  a { text-decoration: none; }
 }
diff --git a/test/cases/media.complex.css b/test/cases/media.complex.css
index 683a157..3806222 100644
--- a/test/cases/media.complex.css
+++ b/test/cases/media.complex.css
@@ -129,3 +129,8 @@
     width: 650px;
   }
 }
+ at media only screen and (min-width: 800px) and (-webkit-min-device-pixel-ratio: 1.3), only screen and (min-width: 800px) and (-o-min-device-pixel-ratio: 13/10), only screen and (min-width: 800px) and (min-resolution: 120dpi), only screen and (min-width: 800px) and (min-resolution: 1.3dppx) {
+  body {
+    color: #f00;
+  }
+}
diff --git a/test/cases/media.complex.styl b/test/cases/media.complex.styl
index ce94d51..65a96df 100644
--- a/test/cases/media.complex.styl
+++ b/test/cases/media.complex.styl
@@ -147,3 +147,9 @@ body
   .sidebar, .header, .footer
     @media (orientation: landscape)
       width: 650px;
+
+ at media only screen
+  @media (min-width: 800px)
+    @media (-webkit-min-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 13/10), (min-resolution: 120dpi), (min-resolution: 1.3dppx)
+      body
+        color: red
diff --git a/test/cases/multiline.css b/test/cases/multiline.css
index 3533759..4f4eb34 100644
--- a/test/cases/multiline.css
+++ b/test/cases/multiline.css
@@ -1,7 +1,10 @@
 .popup {
-  box-shadow: 0 -2px 2px #525f7a, 0 -10px 10px #29303d, 0 0 15px #000, inset 0 5px 1px rgba(5,19,46,0.4), inset 0 0 5px rgba(5,19,46,0.1), inset 0 20px 15px #fff, inset 0 1px 0 #000, inset 0 -50px 50px -40px rgba(5,19,46,0.3), inset 0 -1px 0px #29303d, inset 0 -2px 0px #525f7a, inset 0 -2px 1px #94a0b8, inset 0 -3px 0px #679, inset 0 -4px 0px #679, inset 0 -5px 0px #a3adc2, inset 0 -5px 1px #679, inset 0 -6px 0px #8592ad, inset 0 -7px 0px #8592ad, inset 0 -8px 0px #c2c9d6, inset 0 -8px 1 [...]
+  box-shadow: 0 -2px 2px #525f7a, 0 -10px 10px #29303d, 0 0 15px #000, inset 0 5px 1px rgba(5,19,46,0.4), inset 0 0 5px rgba(5,19,46,0.1), inset 0 20px 15px #fff, inset 0 1px 0 #000, inset 0 1px 0 #000, inset 0 -50px 50px -40px rgba(5,19,46,0.3), inset 0 -1px 0px #29303d, inset 0 -2px 0px #525f7a, inset 0 -2px 1px #94a0b8, inset 0 -3px 0px #679, inset 0 -4px 0px #679, inset 0 -5px 0px #a3adc2, inset 0 -5px 1px #679, inset 0 -6px 0px #8592ad, inset 0 -7px 0px #8592ad, inset 0 -8px 0px #c2 [...]
   foo: 'bar';
 }
 body {
   font-families: Helvetica, Arial, sans-serif;
 }
+body {
+  foo: 'bar';
+}
diff --git a/test/cases/multiline.styl b/test/cases/multiline.styl
index 191fecb..b4e9660 100644
--- a/test/cases/multiline.styl
+++ b/test/cases/multiline.styl
@@ -14,6 +14,12 @@
                             0%
                           ), 
 
+    inset 0 1px 0         hsl(
+                            219
+                          , 20%
+                          , 0%
+                          ),
+
     inset 0 -50px 50px -40px hsla(220, 80%, 10%, .3),
 
     inset 0 -1px 0px      hsl(220, 20%, 20%),
@@ -40,4 +46,22 @@ families = Helvetica,
   sans-serif
 
 body
-  font-families: families
\ No newline at end of file
+  font-families: families
+
+a = {}
+
+bar(obj, bool)
+  obj.params = { foo: 'bar' }
+
+baz(params)
+  body
+    foo: params.foo
+
+foo()
+  if true
+    bar(a,
+      true)
+
+  baz(a.params)
+
+foo()
diff --git a/test/cases/parse.css b/test/cases/parse.css
index 1c9580c..3122e5c 100644
--- a/test/cases/parse.css
+++ b/test/cases/parse.css
@@ -30,3 +30,40 @@ h1 {
 a:hover {
   color: #000;
 }
+ at media screen {
+  body {
+    color: #f00;
+  }
+}
+ at -moz-keyframes foo {
+  from {
+    color: #f00;
+  }
+  to {
+    color: #00f;
+  }
+}
+ at -webkit-keyframes foo {
+  from {
+    color: #f00;
+  }
+  to {
+    color: #00f;
+  }
+}
+ at -o-keyframes foo {
+  from {
+    color: #f00;
+  }
+  to {
+    color: #00f;
+  }
+}
+ at keyframes foo {
+  from {
+    color: #f00;
+  }
+  to {
+    color: #00f;
+  }
+}
diff --git a/test/cases/parse.styl b/test/cases/parse.styl
index f85dee4..6295a16 100644
--- a/test/cases/parse.styl
+++ b/test/cases/parse.styl
@@ -43,3 +43,23 @@ h1
 
 a:hover
   color black
+
+ at media screen
+{
+  body
+  {
+    color: red;
+  }
+}
+
+ at keyframes foo
+{
+  from
+  {
+    color: red;
+  }
+  to
+  {
+    color: blue;
+  }
+}
diff --git a/test/cases/regression.1584.css b/test/cases/regression.1584.css
new file mode 100644
index 0000000..ad8a17c
--- /dev/null
+++ b/test/cases/regression.1584.css
@@ -0,0 +1,7 @@
+ at font-face {
+  font-family: "foo";
+  font-weight: normal;
+  font-style: normal;
+  src: url("foo.eot");
+  src: local("foo"), url("foo.eot?#iefix") format('embedded-opentype'), url("foo.woff") format('woff'), url("foo.ttf") format('truetype'), url("foo.svg#foo") format('svg');
+}
diff --git a/test/cases/regression.1584.styl b/test/cases/regression.1584.styl
new file mode 100644
index 0000000..b8f25c9
--- /dev/null
+++ b/test/cases/regression.1584.styl
@@ -0,0 +1,15 @@
+font-face(font-family, file-path, weight = normal, style = normal) {
+  @font-face {
+    font-family: '"%s"' % (unquote(font-family));
+    font-weight: unquote(weight);
+    font-style: unquote(style);
+    src: 'url("%s.eot")' % (unquote(file-path));
+    src: 'local("%s")' % (unquote(font-family)),
+         'url("%s.eot?#iefix")' % (unquote(file-path)) format('embedded-opentype'),
+         'url("%s.woff")' % (unquote(file-path)) format('woff'),
+         'url("%s.ttf")' % (unquote(file-path)) format('truetype'),
+         'url("%s.svg#%s")' % (unquote(file-path) unquote(font-family)) format('svg');
+  }
+}
+
+font-face('foo', 'foo')
diff --git a/test/cases/regression.1623.css b/test/cases/regression.1623.css
new file mode 100644
index 0000000..0fb1cf6
--- /dev/null
+++ b/test/cases/regression.1623.css
@@ -0,0 +1,15 @@
+.column,
+.sidebar,
+.wrapper {
+  test: test;
+}
+ at media screen and (min-width: 35.5em) {
+  .sidebar {
+    width: 41.6666%;
+    *width: 41.6356%;
+  }
+  .wrapper {
+    width: 58.3333%;
+    *width: 58.3023%;
+  }
+}
diff --git a/test/cases/regression.1623.styl b/test/cases/regression.1623.styl
new file mode 100644
index 0000000..15c2696
--- /dev/null
+++ b/test/cases/regression.1623.styl
@@ -0,0 +1,47 @@
+grid-use-placeholders   =   true
+grid-old-ie-delta       =   -0.00031
+grid-decimals           =   4
+grid-columns            =   12
+grid-wrapper            =   950px
+grid-gutter             =   24px
+grid-push               =   true
+grid-pull               =   true
+grid-breakpoints        =   {
+  small: '(min-width: 35.5em)'
+  medium: '(min-width: 48em)'
+  large: '(min-width: 64em)'
+}
+ 
+beginning = grid-use-placeholders ? '$' : '.'
+ 
+calcColumnWidth(i, adjust = 0)
+    return unit(floor((i / grid-columns + adjust) * 100, grid-decimals), '%')
+ 
+convertNumberToWord(num)
+    for word, i in zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour
+        if num is i
+            return word
+ 
+ 
+.column,
+$column
+  test: test
+ 
+ 
+for key, i in keys(grid-breakpoints)
+    value = values(grid-breakpoints)[i]
+    media = 'screen and ' + value
+ 
+    @media media
+        for i in 1..grid-columns
+            $lol,
+            {beginning + key + '-' + convertNumberToWord(i)}
+                @extends {beginning}column
+                width: calcColumnWidth(i)
+                *width: calcColumnWidth(i, grid-old-ie-delta)
+ 
+.sidebar
+    @extends {beginning + 'small-five'}
+ 
+.wrapper
+    @extends {beginning + 'small-seven'}
diff --git a/test/cases/selectors.css b/test/cases/selectors.css
index 8fd0ba9..e187bd5 100644
--- a/test/cases/selectors.css
+++ b/test/cases/selectors.css
@@ -126,3 +126,9 @@ input,
 a {
   color: #f00;
 }
+paper {
+  background: #008000;
+}
+paper paper-input::shadow .color {
+  background: #f00;
+}
diff --git a/test/cases/selectors.styl b/test/cases/selectors.styl
index d4db891..60e9083 100644
--- a/test/cases/selectors.styl
+++ b/test/cases/selectors.styl
@@ -119,3 +119,9 @@ input[type="submit"]
 
 button, input, /* foo */ a
   color red
+
+paper
+  background green
+
+  paper-input::shadow .color
+    background red

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-stylus.git



More information about the Pkg-javascript-commits mailing list