diff --git a/Makefile b/Makefile index a200fb560..40a5dc832 100644 --- a/Makefile +++ b/Makefile @@ -8,17 +8,6 @@ test: test-integration test-integration: @node test/run.js -docs: docs/index.html - -docs/index.html: $(SRC) - @mkdir -p docs - dox \ - --title "Stylus" \ - --desc "Expressive, dynamic, robust CSS for nodejs" \ - --ribbon http://github.com/learnboost/stylus \ - --private \ - $^ > $@ - install-bundle: cp -fr $(TM_BUNDLE) $(TM_BUNDLE_DEST) @@ -28,4 +17,4 @@ update-bundle: benchmark: @node bm.js -.PHONY: test test-integration install-bundle docs update-bundle benchmark \ No newline at end of file +.PHONY: test test-integration install-bundle update-bundle benchmark \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 83aa03c59..000000000 --- a/docs/index.html +++ /dev/null @@ -1,8744 +0,0 @@ -Fork me on GitHub - - Stylus - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Stylus

Expressive, dynamic, robust CSS for nodejs

image

lib/functions/image.js
-

Module dependencies. -

-
-
var utils = require('../utils')
-  , nodes = require('../nodes')
-  , fs = require('fs');
-
-

Initialize a new Image with the given ctx and `path.

- -

- -
  • param: Evaluator ctx

  • param: String path

  • api: private

-
-
var Image = module.exports = function Image(ctx, path) {
-  this.ctx = ctx;
-  this.path = utils.lookup(path, ctx.paths);
-  if (!this.path) throw new Error('failed to locate file ' + path);
-};
-
-

Open the image for reading.

- -
  • api: private

-
-
Image.prototype.open = function(){
-  this.fd = fs.openSync(this.path, 'r');
-};
-
-

Close the file.

- -
  • api: private

-
-
Image.prototype.close = function(){
-  if (this.fd) fs.closeSync(this.fd);
-};
-
-

Return the type of image, supports:

- -
  • gif
  • png
  • jpeg
- -

- -
  • return: String

  • api: private

-
-
Image.prototype.type = function(){
-  var type
-    , buf = new Buffer(4);
-  
-  fs.readSync(this.fd, buf, 0, 4, 0);
-
-  // GIF
-  if (x47 == buf[0] && x49 == buf[1] && x46 == buf[2]) type = 'gif';
-
-  // PNG
-  else if (x50 == buf[1] && x4E == buf[2] && x47 == buf[3]) type = 'png';
-
-  // JPEG
-  else if (xff == buf[0] && xd8 == buf[1]) type = 'jpeg';
-
-  return type;
-};
-
-

Return image dimensions [width, height].

- -

- -
  • return: Array

  • api: private

-
-
Image.prototype.size = function(){
-  var width
-    , height
-    , type = this.type();
-
-  function uint16(b) { return b[1] << 8 | b[0]; }
-  function uint32(b) { return b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; } 
-
-  // Determine dimensions
-  switch (type) {
-    case 'jpeg':
-      throw new Error('image-size() jpeg support not yet implemented');
-      break;
-    case 'png':
-      var buf = new Buffer(8);
-      // IHDR chunk width / height uint32_t big-endian
-      fs.readSync(this.fd, buf, 0, 8, 16);
-      width = uint32(buf);
-      height = uint32(buf.slice(4, 8));
-      break;
-    case 'gif':
-      var buf = new Buffer(4);
-      // width / height uint16_t little-endian
-      fs.readSync(this.fd, buf, 0, 4, 6);
-      width = uint16(buf);
-      height = uint16(buf.slice(2, 4));
-      break;
-  }
-
-  if ('number' != typeof width) throw new Error('failed to find width of "' + this.path + '"');
-  if ('number' != typeof height) throw new Error('failed to find height of "' + this.path + '"');
-
-  return [width, height];
-};
-

colors

lib/colors.js
-

module.exports = { - aliceblue: [240, 248, 255] - , antiquewhite: [250, 235, 215] - , aqua: [0, 255, 255] - , aquamarine: [127, 255, 212] - , azure: [240, 255, 255] - , beige: [245, 245, 220] - , bisque: [255, 228, 196] - , black: [0, 0, 0] - , blanchedalmond: [255, 235, 205] - , blue: [0, 0, 255] - , blueviolet: [138, 43, 226] - , brown: [165, 42, 42] - , burlywood: [222, 184, 135] - , cadetblue: [95, 158, 160] - , chartreuse: [127, 255, 0] - , chocolate: [210, 105, 30] - , coral: [255, 127, 80] - , cornflowerblue: [100, 149, 237] - , cornsilk: [255, 248, 220] - , crimson: [220, 20, 60] - , cyan: [0, 255, 255] - , darkblue: [0, 0, 139] - , darkcyan: [0, 139, 139] - , darkgoldenrod: [184, 132, 11] - , darkgray: [169, 169, 169] - , darkgreen: [0, 100, 0] - , darkgrey: [169, 169, 169] - , darkkhaki: [189, 183, 107] - , darkmagenta: [139, 0, 139] - , darkolivegreen: [85, 107, 47] - , darkorange: [255, 140, 0] - , darkorchid: [153, 50, 204] - , darkred: [139, 0, 0] - , darksalmon: [233, 150, 122] - , darkseagreen: [143, 188, 143] - , darkslateblue: [72, 61, 139] - , darkslategray: [47, 79, 79] - , darkslategrey: [47, 79, 79] - , darkturquoise: [0, 206, 209] - , darkviolet: [148, 0, 211] - , deeppink: [255, 20, 147] - , deepskyblue: [0, 191, 255] - , dimgray: [105, 105, 105] - , dimgrey: [105, 105, 105] - , dodgerblue: [30, 144, 255] - , firebrick: [178, 34, 34] - , floralwhite: [255, 255, 240] - , forestgreen: [34, 139, 34] - , fuchsia: [255, 0, 255] - , gainsboro: [220, 220, 220] - , ghostwhite: [248, 248, 255] - , gold: [255, 215, 0] - , goldenrod: [218, 165, 32] - , gray: [128, 128, 128] - , green: [0, 128, 0] - , greenyellow: [173, 255, 47] - , grey: [128, 128, 128] - , honeydew: [240, 255, 240] - , hotpink: [255, 105, 180] - , indianred: [205, 92, 92] - , indigo: [75, 0, 130] - , ivory: [255, 255, 240] - , khaki: [240, 230, 140] - , lavender: [230, 230, 250] - , lavenderblush: [255, 240, 245] - , lawngreen: [124, 252, 0] - , lemonchiffon: [255, 250, 205] - , lightblue: [173, 216, 230] - , lightcoral: [240, 128, 128] - , lightcyan: [224, 255, 255] - , lightgoldenrodyellow: [250, 250, 210] - , lightgray: [211, 211, 211] - , lightgreen: [144, 238, 144] - , lightgrey: [211, 211, 211] - , lightpink: [255, 182, 193] - , lightsalmon: [255, 160, 122] - , lightseagreen: [32, 178, 170] - , lightskyblue: [135, 206, 250] - , lightslategray: [119, 136, 153] - , lightslategrey: [119, 136, 153] - , lightsteelblue: [176, 196, 222] - , lightyellow: [255, 255, 224] - , lime: [0, 255, 0] - , limegreen: [50, 205, 50] - , linen: [250, 240, 230] - , magenta: [255, 0, 255] - , maroon: [128, 0, 0] - , mediumaquamarine: [102, 205, 170] - , mediumblue: [0, 0, 205] - , mediumorchid: [186, 85, 211] - , mediumpurple: [147, 112, 219] - , mediumseagreen: [60, 179, 113] - , mediumslateblue: [123, 104, 238] - , mediumspringgreen: [0, 250, 154] - , mediumturquoise: [72, 209, 204] - , mediumvioletred: [199, 21, 133] - , midnightblue: [25, 25, 112] - , mintcream: [245, 255, 250] - , mistyrose: [255, 228, 225] - , moccasin: [255, 228, 181] - , navajowhite: [255, 222, 173] - , navy: [0, 0, 128] - , oldlace: [253, 245, 230] - , olive: [128, 128, 0] - , olivedrab: [107, 142, 35] - , orange: [255, 165, 0] - , orangered: [255, 69, 0] - , orchid: [218, 112, 214] - , palegoldenrod: [238, 232, 170] - , palegreen: [152, 251, 152] - , paleturquoise: [175, 238, 238] - , palevioletred: [219, 112, 147] - , papayawhip: [255, 239, 213] - , peachpuff: [255, 218, 185] - , peru: [205, 133, 63] - , pink: [255, 192, 203] - , plum: [221, 160, 203] - , powderblue: [176, 224, 230] - , purple: [128, 0, 128] - , red: [255, 0, 0] - , rosybrown: [188, 143, 143] - , royalblue: [65, 105, 225] - , saddlebrown: [139, 69, 19] - , salmon: [250, 128, 114] - , sandybrown: [244, 164, 96] - , seagreen: [46, 139, 87] - , seashell: [255, 245, 238] - , sienna: [160, 82, 45] - , silver: [192, 192, 192] - , skyblue: [135, 206, 235] - , slateblue: [106, 90, 205] - , slategray: [119, 128, 144] - , slategrey: [119, 128, 144] - , snow: [255, 255, 250] - , springgreen: [0, 255, 127] - , steelblue: [70, 130, 180] - , tan: [210, 180, 140] - , teal: [0, 128, 128] - , thistle: [216, 191, 216] - , tomato: [255, 99, 71] - , turquoise: [64, 224, 208] - , violet: [238, 130, 238] - , wheat: [245, 222, 179] - , white: [255, 255, 255] - , whitesmoke: [245, 245, 245] - , yellow: [255, 255, 0] - , yellowgreen: [154, 205, 5] -};

-
- -

css

lib/convert/css.js
-

Convert the given css to stylus source.

- -

- -
  • param: String css

  • return: String

  • api: public

-
-
module.exports = function(css){
-  return new Converter(css).stylus();
-};
-
-

Initialize a new Converter with the given css.

- -

- -
  • param: String css

  • api: private

-
-
function Converter(css) {
-  var cssom = require('cssom');
-  this.css = css;
-  this.types = cssom.CSSRule;
-  this.root = cssom.parse(css);
-  this.indents = 0;
-}
-
-

Convert to stylus.

- -

- -
  • return: String

  • api: private

-
-
Converter.prototype.stylus = function(){
-  return this.visitRules(this.root.cssRules);
-};
-
-

Return indent string.

- -

- -
  • return: String

  • api: private

-
-
Converter.prototype.__defineGetter__('indent', function(){
-  return Array(this.indents + 1).join('  ');
-});
-
-

Visit node.

- -

- -
  • param: CSSRule node

  • return: String

  • api: private

-
-
Converter.prototype.visit = function(node){
-  switch (node.type) {
-    case this.types.STYLE_RULE:
-      return this.visitStyle(node);
-    case this.types.MEDIA_RULE:
-      return this.visitMedia(node);
-  }
-};
-
-

Visit the rules on node.

- -

- -
  • param: CSSRule node

  • return: String

  • api: private

-
-
Converter.prototype.visitRules = function(node){
-  var buf = '';
-  for (var i = 0, len = node.length; i < len; ++i) {
-    buf += this.visit(node[i]);
-  }
-  return buf;
-};
-
-

Visit CSSMediaRule node.

- -

- -
  • param: CSSMediaRule node

  • return: String

  • api: private

-
-
Converter.prototype.visitMedia = function(node){
-  var buf = this.indent + '@media ';
-  for (var i = 0, len = node.media.length; i < len; ++i) {
-    buf += node.media[i];
-  }
-  buf += '\n';
-  ++this.indents;
-  buf += this.visitRules(node.cssRules);
-  --this.indents;
-  return buf;
-};
-
-

Visit CSSStyleRule node.`

- -

- -
  • param: CSSStyleRule node

  • return: String

  • api: private

-
-
Converter.prototype.visitStyle = function(node){
-  var buf = this.indent + node.selectorText + '\n';
-  ++this.indents;
-  for (var i = 0, len = node.style.length; i < len; ++i) {
-    var prop = node.style[i]
-      , val = node.style[prop];
-    if (prop) {
-      buf += this.indent + prop + ' ' + val + '\n';
-    }
-  }
-  --this.indents;
-  return buf + '\n';
-};
-

index

lib/functions/index.js
-

Module dependencies. -

-
-
var nodes = require('../nodes')
-  , utils = require('../utils')
-  , Image = require('./image');
-
-

Color component name map. -

-
-
var componentMap = {
-    red: 'r'
-  , green: 'g'
-  , blue: 'b'
-  , alpha: 'a'
-  , hue: 'h'
-  , saturation: 's'
-  , lightness: 'l'
-};
-
-

Color component type map. -

-
-
var typeMap = {
-    hue: 'deg'
-  , saturation: '%'
-  , lightness: '%'
-};
-
-

Convert the given color to an HSLA node, -or h,s,l,a component values.

- -

Examples

- -

hsla(10deg, 50%, 30%, 0.5) - // => HSLA

- -

hsla(#ffcc00) - // => HSLA

- -

- -
  • param: RGBA | HSLA | Unit h

  • param: Unit s

  • param: Unit l

  • param: Unit a

  • return: HSLA

  • api: public

-
-
exports.hsla = function(h,s,l,a){
-  switch (arguments.length) {
-    case 1:
-      utils.assertColor(h);
-      return h.hsla;
-    default:
-      utils.assertType(h, nodes.Unit, 'hue');
-      utils.assertType(s, nodes.Unit, 'saturation');
-      utils.assertType(l, nodes.Unit, 'lightness');
-      utils.assertType(a, nodes.Unit, 'alpha');
-      return new nodes.HSLA(h.val,s.val,l.val,a.val);
-  }
-};
-
-

Convert the given color to an HSLA node, -or h,s,l component values.

- -

Examples

- -

hsl(10, 50, 30) - // => HSLA

- -

hsl(#ffcc00) - // => HSLA

- -

- -
  • param: Unit | HSLA | RGBA h

  • param: Unit s

  • param: Unit l

  • return: HSLA

  • api: public

-
-
exports.hsl = function(h,s,l){
-  if (arguments.length > 1) {
-    return exports.hsla(h,s,l,new nodes.Unit(1));
-  }
-  utils.assertColor(h, 'color');
-  return h.hsla;
-};
-
-

Return type of node.

- -

Examples

- -

type(12) - // => 'unit'

- -

type(#fff) - // => 'color'

- -

type(type) - // => 'function'

- -

type(unbound) - typeof(unbound) - type-of(unbound) - // => 'ident'

- -

- -
  • param: Node node

  • return: String

  • api: public

-
-
exports.type =
-exports.typeof =
-exports['type-of'] = function(node){
-  utils.assertPresent(node, 'expression');
-  var type = node.nodeName;
-  return new nodes.String(type);
-};
-
-

Return component name for the given color.

- -

- -
  • param: RGBA | HSLA color

  • param: String na,e

  • return: Unit

  • api: public

-
-
exports.component = function(color, name) {
-  utils.assertColor(color, 'color');
-  utils.assertString(name, 'name');
-  var name = name.string
-    , type = typeMap[name]
-    , name = componentMap[name];
-  if (!name) throw new Error('invalid color component "' + name + '"');
-  return new nodes.Unit(color[name], type);
-};
-
-

Return the red component of the given color.

- -

Examples

- -

red(#c00) - // => 204

- -

- -
  • param: RGBA | HSLA color

  • return: Unit

  • api: public

-
-
exports.red = function(color){
-  return exports.component(color, new nodes.String('red'));
-};
-
-

Return the green component of the given color.

- -

Examples

- -

green(#0c0) - // => 204

- -

- -
  • param: RGBA | HSLA color

  • return: Unit

  • api: public

-
-
exports.green = function(color){
-  return exports.component(color, new nodes.String('green'));
-};
-
-

Return the blue component of the given color.

- -

Examples

- -

blue(#00c) - // => 204

- -

- -
  • param: RGBA | HSLA color

  • return: Unit

  • api: public

-
-
exports.blue = function(color){
-  return exports.component(color, new nodes.String('blue'));
-};
-
-

Return a RGBA from the r,g,b,a channels.

- -

Examples

- -

rgba(255,0,0,0.5) - // => rgba(255,0,0,0.5)

- -

rgba(255,0,0,1) - // => #ff0000

- -

rgba(#ffcc00, 0.5) - // rgba(255,204,0,0.5)

- -

- -
  • param: Unit | RGBA | HSLA r

  • param: Unit g

  • param: Unit b

  • param: Unit a

  • return: RGBA

  • api: public

-
-
exports.rgba = function(r,g,b,a){
-  switch (arguments.length) {
-    case 1:
-      utils.assertColor(r);
-      var color = r.rgba;
-      return new nodes.RGBA(
-          color.r
-        , color.g
-        , color.b
-        , color.a);
-    case 2:
-      utils.assertColor(r);
-      var color = r.rgba;
-      utils.assertType(g, nodes.Unit);
-      return new nodes.RGBA(
-          color.r
-        , color.g
-        , color.b
-        , g.val);
-    default:
-      utils.assertType(r, nodes.Unit, 'red');
-      utils.assertType(g, nodes.Unit, 'green');
-      utils.assertType(b, nodes.Unit, 'blue');
-      utils.assertType(a, nodes.Unit, 'alpha');
-      return new nodes.RGBA(
-          r.val
-        , g.val
-        , b.val
-        , a.val);
-  }
-};
-
-

Return a RGBA from the r,g,b channels.

- -

Examples

- -

rgb(255,204,0) - // => #ffcc00

- -

rgb(#fff) - // => #fff

- -

- -
  • param: Unit | RGBA | HSLA r

  • param: Unit g

  • param: Unit b

  • return: RGBA

  • api: public

-
-
exports.rgb = function(r,g,b){
-  switch (arguments.length) {
-    case 1:
-      utils.assertColor(r);
-      var color = r.rgba;
-      return new nodes.RGBA(
-          color.r
-        , color.g
-        , color.b
-        , 1);
-    default:
-      return exports.rgba(r,g,b,new nodes.Unit(1));
-  }
-};
-
-

Unquote the given str.

- -

Examples

- -

unquote("sans-serif") - // => sans-serif

- -

unquote(sans-serif) - // => sans-serif

- -

- -
  • param: String | Ident val

  • return: Literal

  • api: public

-
-
exports.unquote = function(val){
-  utils.assertString(val, 'string');
-  return new nodes.Literal(val.string);
-};
-
-

Assign type to the given unit or return unit's type.

- -

- -
  • param: Unit unit

  • param: String | Ident type

  • return: Unit

  • api: public

-
-
exports.unit = function(unit, type){
-  utils.assertType(unit, nodes.Unit, 'unit');
-
-  // Assign
-  if (type) {
-    utils.assertString(type, 'type');
-    return new nodes.Unit(unit.val, type.string);
-  } else {
-    return new nodes.String(unit.type || '');
-  }
-};
-
-

Lookup variable name or return Null.

- -

- -
  • param: String name

  • return: Mixed

  • api: public

-
-
exports.lookup = function(name){
-  utils.assertType(name, nodes.String, 'name');
-  var node = this.lookup(name.val);
-  if (!node) return nodes.null;
-  return this.visit(node);
-};
-
-

Perform op on the left and right operands.

- -

- -
  • param: String op

  • param: Node left

  • param: Node right

  • return: Node

  • api: public

-
-
exports.operate = function(op, left, right){
-  utils.assertType(op, nodes.String, 'op');
-  utils.assertPresent(left, 'left');
-  utils.assertPresent(right, 'right');
-  return left.operate(op.val, right);
-};
-
-

Test if val matches the given pattern.

- -

Examples

- -
match('^foo(bar)?', foo)
-match('^foo(bar)?', foobar)
-match('^foo(bar)?', 'foo')
-match('^foo(bar)?', 'foobar')
-// => true
-
-match('^foo(bar)?', 'bar')
-// => false
- -

- -
  • param: String pattern

  • param: String | Ident val

  • return: Boolean

  • api: public

-
-
exports.match = function(pattern, val){
-  utils.assertType(pattern, nodes.String, 'pattern');
-  utils.assertString(val, 'val');
-  var re = new RegExp(pattern.val);
-  return nodes.Boolean(re.test(val.string));
-};
-
-

Return length of the given expr.

- -

- -
  • param: Expression expr

  • return: Unit

  • api: public

-
-
(exports.length = function(expr){
-  if (expr) {
-    if (expr.nodes) {
-      return new nodes.Unit(utils.unwrap(expr).nodes.length);
-    } else {
-      return new nodes.Unit(1);
-    }
-  }
-  return new nodes.Unit(0);
-}).raw = true;
-
-

Inspect the given node.

- -

- -
  • param: Node node

  • api: public

-
-
(exports.p = function(node){
-  console.log('\033[90minspect:\033[0m %s', node);
-  return nodes.null;
-}).raw = true;
-
-

Throw an error with the given msg.

- -

- -
  • param: String msg

  • api: public

-
-
exports.error = function(msg){
-  utils.assertType(msg, nodes.String, 'msg');
-  throw new Error(msg.val);
-};
-
-

Warn with the given msg prefixed by "Warning: ".

- -

- -
  • param: String msg

  • api: public

-
-
exports.warn = function(msg){
-  utils.assertType(msg, nodes.String, 'msg');
-  console.warn('Warning: %s', msg.val);
-  return nodes.null;
-};
-
-

Output stack trace.

- -
  • api: public

-
-
exports.trace = function(){
-  console.log(this.stack);
-  return nodes.null;
-};
-
-

Return the opposites of the given positions.

- -

Examples

- -

opposite-position(top left) - // => bottom right

- -

- -
  • param: Expression positions

  • return: Expression

  • api: public

-
-
(exports['opposite-position'] = function(positions){
-  var expr = new nodes.Expression;
-  utils.unwrap(positions).nodes.forEach(function(pos, i){
-    utils.assertString(pos, 'position ' + i);
-    pos = (function(){ switch (pos.string) {
-      case 'top': return 'bottom';
-      case 'bottom': return 'top';
-      case 'left': return 'right';
-      case 'right': return 'left';
-      default: throw new Error('invalid position ' + pos);
-    }})();
-    expr.push(new nodes.Literal(pos));
-  });
-  return expr;
-}).raw = true;
-
-

Return the width and height of the given img path.

- -

Examples

- -

image-size('foo.png') - // => 200px 100px

- -

image-size('foo.png')[0] - // => 200px

- -

image-size('foo.png')[1] - // => 100px

- -

- -
  • param: String img

  • return: Expression

  • api: public

-
-
exports['image-size'] = function(img) {
-  utils.assertType(img, nodes.String, 'img');
-  var img = new Image(this, img.string);
-
-  // Read size
-  img.open();
-  var size = img.size();
-  img.close();
-
-  // Return (w h)
-  var expr = new nodes.Expression;
-  expr.push(new nodes.Unit(size[0], 'px'));
-  expr.push(new nodes.Unit(size[1], 'px'));
-
-  return expr;
-};
-
-

Apply Math fn to n

- -

- -
  • param: Unit n

  • param: String fn

  • return: Unit

  • api: private

-
-
exports['-math'] = function(n, fn){
-  return new nodes.Unit(Math[fn.string](n.val), n.type);
-};
-
-

Adjust HSL color prop by amount.

- -

- -
  • param: RGBA | HSLA color

  • param: String prop

  • param: Unit amount

  • return: HSLA

  • api: private

-
-
exports['-adjust'] = function(color, prop, amount){
-  var hsl = color.hsla;
-  prop = { hue: 'h', saturation: 's', lightness: 'l' }[prop.string];
-  if (!prop) throw new Error('invalid adjustment property');
-  hsl[prop] = hsl[prop] + amount.val;
-  return hsl.clone();
-};
-

lexer

lib/lexer.js
-

Module dependencies. -

-
-
var Token = require('./token')
-  , nodes = require('./nodes');
-
-

Operator aliases. -

-
-
var alias = {
-    'and': '&&'
-  , 'or': '||'
-  , 'is': '=='
-  , 'isnt': '!='
-  , 'is not': '!='
-};
-
-

Units. -

-
-
var units = [
-    'em'
-  , 'ex'
-  , 'px'
-  , 'mm'
-  , 'cm'
-  , 'in'
-  , 'pt'
-  , 'pc'
-  , 'deg'
-  , 'rad'
-  , 'grad'
-  , 'ms'
-  , 's'
-  , 'Hz'
-  , 'kHz'
-  , '%'].join('|');
-
-

Unit RegExp. -

-
-
var unit = new RegExp('^(-)?(\\d+\\.\\d+|\\d+|\\.\\d+)(' + units + ')? *');
-
-

Initialize a new Lexer with the given str and options.

- -

- -
  • param: String str

  • param: Object options

  • api: private

-
-
var Lexer = module.exports = function Lexer(str, options) {
-  options = options || {};
-  this.str = str.replace(/\r\n?/g, '\n');
-  this.stash = [];
-  this.indentStack = [];
-  this.indentRe = null;
-  this.lineno = 0;
-};
-
-

Lexer prototype. -

-
-
Lexer.prototype = {
-
-

Custom inspect. -

-
-
inspect: function(){
-    var tok
-      , tmp = this.str
-      , buf = [];
-    while ('eos' != (tok = this.next()).type) {
-      buf.push(tok.inspect());
-    }
-    this.str = tmp;
-    this.prevIndents = 0;
-    return buf.concat(tok.inspect()).join('\n');
-  },
-
-

Lookahead n tokens.

- -

- -
  • param: Number n

  • return: Object

  • api: private

-
-
lookahead: function(n){
-    var fetch = n - this.stash.length;
-    while (fetch-- > 0) this.stash.push(this.advance());
-    return this.stash[--n];
-  },
-
-

Consume the given len.

- -

- -
  • param: Number | Array len

  • api: private

-
-
skip: function(len){
-    this.str = this.str.substr(Array.isArray(len)
-      ? len[0].length
-      : len);
-  },
-
-

Fetch next token including those stashed by peek.

- -

- -
  • return: Token

  • api: private

-
-
next: function() {
-    var tok = this.stashed() || this.advance();
-    switch (tok.type) {
-      case 'newline':
-      case 'selector':
-      case 'indent':
-        ++this.lineno;
-    }
-    tok.lineno = this.lineno;
-    return tok;
-  },
-
-

Fetch next token.

- -

- -
  • return: Token

  • api: private

-
-
advance: function() {
-    return this.eos()
-      || this.null()
-      || this.sep()
-      || this.keyword()
-      || this.urlchars()
-      || this.atrule()
-      || this.media()
-      || this.comment()
-      || this.newline()
-      || this.escaped()
-      || this.important()
-      || this.literal()
-      || this.function()
-      || this.brace()
-      || this.paren()
-      || this.color()
-      || this.string()
-      || this.unit()
-      || this.namedop()
-      || this.boolean()
-      || this.ident()
-      || this.op()
-      || this.space()
-      || this.selector();
-  },
-
-

Lookahead a single token.

- -

- -
  • return: Token

  • api: private

-
-
peek: function() {
-    return this.lookahead(1);
-  },
-
-

Return the next possibly stashed token.

- -

- -
  • return: Token

  • api: private

-
-
stashed: function() {
-    return this.stash.shift();
-  },
-
-

EOS | trailing outdents. -

-
-
eos: function() {
-    if (this.str.length) return;
-    if (this.indentStack.length) {
-      this.indentStack.shift();
-      return new Token('outdent');
-    } else {
-      return new Token('eos');
-    }
-  },
-
-

url char -

-
-
urlchars: function() {
-    var captures;
-    if (!this.isURL) return;
-    if (captures = /^[\/:@.;?&=*!,<>#%0-9]+/.exec(this.str)) {
-      this.skip(captures);
-      return new Token('literal', new nodes.Literal(captures[0]));
-    }
-  },
-
-

';' ' '* -

-
-
sep: function() {
-    var captures;
-    if (captures = /^; */.exec(this.str)) {
-      this.skip(captures);
-      return new Token(';');
-    }
-  },
-
-

' '+ -

-
-
space: function() {
-    var captures;
-    if (captures = /^( +)/.exec(this.str)) {
-      this.skip(captures);
-      return new Token('space');
-    }
-  },
-
-

'\' . ' '* -

-
-
escaped: function() {
-    var captures;
-    if (captures = /^\\(.) */.exec(this.str)) {
-      var c = captures[1];
-      this.skip(captures);
-      return new Token('ident', new nodes.Literal(c));
-    }
-  },
-
-

'@css' ' ' '{' . '}' ' '* -

-
-
literal: function() {
-    // HACK attack !!!
-    var captures;
-    if (captures = /^@css *\{/.exec(this.str)) {
-      this.skip(captures);
-      var c
-        , braces = 1
-        , css = '';
-      while (c = this.str[0]) {
-        this.str = this.str.substr(1);
-        switch (c) {
-          case '{': ++braces; break;
-          case '}': --braces; break;
-        }
-        css += c;
-        if (!braces) break;
-      }
-      css = css.replace(/\s*}$/, '');
-      return new Token('literal', new nodes.Literal(css));
-    }
-  },
-
-

'!important' ' '* -

-
-
important: function() {
-    var captures;
-    if (captures = /^!important */.exec(this.str)) {
-      this.skip(captures);
-      return new Token('ident', new nodes.Literal('!important'));
-    }
-  },
-
-

'{' | '}' -

-
-
brace: function() {
-    var captures;
-    if (captures = /^([{}])/.exec(this.str)) {
-      this.skip(1);
-      var brace = captures[1];
-      return new Token(brace, brace);
-    }
-  },
-
-

'(' | ')' ' '* -

-
-
paren: function() {
-    var captures;
-    if (captures = /^([()]) */.exec(this.str)) {
-      var paren = captures[1];
-      this.skip(captures);
-      if (')' == paren) this.isURL = false;
-      return new Token(paren, paren);
-    }
-  },
-
-

'null' -

-
-
null: function() {
-    var captures;
-    if (captures = /^(null)\b */.exec(this.str)) {
-      this.skip(captures);
-      return new Token('null', nodes.null);
-    }
-  },
-
-

'if' -| 'else' -| 'unless' -| 'return' -| 'for' -| 'in' -

-
-
keyword: function() {
-    var captures;
-    if (captures = /^(return|if|else|unless|for|in)\b */.exec(this.str)) {
-      var keyword = captures[1];
-      this.skip(captures);
-      return new Token(keyword, keyword);
-    }
-  },
-
-

'not' -| 'and' -| 'or' -| 'is' -| 'is not' -| 'isnt' -| 'is a' -| 'is defined' -

-
-
namedop: function() {
-    var captures;
-    if (captures = /^(not|and|or|is a|is defined|isnt|is not|is)\b( *)/.exec(this.str)) {
-      var op = captures[1];
-      this.skip(captures);
-      op = alias[op] || op;
-      var tok = new Token(op, op);
-      tok.space = captures[2];
-      return tok;
-    }
-  },
-
-

',' -| '+' -| '+=' -| '-' -| '-=' -| '' -| '=' -| '/' -| '/=' -| '%' -| '%=' -| '**' -| '!' -| '&' -| '&&' -| '||' -| '>' -| '>=' -| '<' -| '<=' -| '=' -| '==' -| '!=' -| '!' -| '~' -| '?=' -| '?' -| ':' -| '[' -| ']' -| '..' -| '...' -

-
-
op: function() {
-    var captures;
-    if (captures = /^([.]{2,3}|&&|\|\||[!<>=?]=|\*\*|[-+*\/%]=?|[,=?:!~&lt;&gt;&amp;\[\]])( *)/.exec(this.str)) {
-      var op = captures[1];
-      this.skip(captures);
-      op = alias[op] || op;
-      var tok = new Token(op, op);
-      tok.space = captures[2];
-      return tok;
-    }
-  },
-
-

'@media' ([^{\n]+) -

-
-
media: function() {
-    var captures;
-    if (captures = /^@media *([^{\n]+)/.exec(this.str)) {
-      this.skip(captures);
-      return new Token('media', captures[1].trim());
-    }
-  },
-
-

'@' ('import' | 'keyframes' | 'charset' | 'page') -

-
-
atrule: function() {
-    var captures;
-    if (captures = /^@(import|keyframes|charset|page) */.exec(this.str)) {
-      this.skip(captures);
-      return new Token(captures[1]);
-    }
-  },
-
-

'//' * -

-
-
comment: function() {
-    // Single line
-    if ('/' == this.str[0] &amp;&amp; '/' == this.str[1]) {
-      var end = this.str.indexOf('\n');
-      if (-1 == end) end = this.str.length;
-      this.skip(end);
-      return this.advance();
-    }
-
-    // Multi-line
-    if ('/' == this.str[0] &amp;&amp; '*' == this.str[1]) {
-      var end = this.str.indexOf('*/');
-      if (-1 == end) end = this.str.length;
-      var str = this.str.substr(0, end + 2)
-        , lines = str.split('\n').length - 1;
-      this.lineno += lines;
-      this.skip(end + 2);
-      return this.allowComments
-        ? new Token('comment', str)
-        : this.advance();
-    }
-  },
-
-

'true' | 'false' -

-
-
boolean: function() {
-    var captures;
-    if (captures = /^(true|false)\b( *)/.exec(this.str)) {
-      var val = 'true' == captures[1]
-        ? nodes.true
-        : nodes.false;
-      this.skip(captures);
-      var tok = new Token('boolean', val);
-      tok.space = captures[2];
-      return tok;
-    }
-  },
-
-

-?[a-zA-Z$] [-\w\d$]* '(' -

-
-
function: function() {
-    var captures;
-    if (captures = /^(-?[a-zA-Z$][-\w\d$]*)\(( *)/.exec(this.str)) {
-      var name = captures[1];
-      this.skip(captures);
-      this.isURL = 'url' == name;
-      var tok = new Token('function', new nodes.Ident(name));
-      tok.space = captures[2];
-      return tok;
-    } 
-  },
-
-

-?[a-zA-Z$] [-\w\d$]* -

-
-
ident: function() {
-    var captures;
-    if (captures = /^(-?[a-zA-Z$][-\w\d$]*)/.exec(this.str)) {
-      var name = captures[1];
-      this.skip(captures);
-      return new Token('ident', new nodes.Ident(name));
-    }
-  },
-
-

'\n' ' '+ -

-
-
newline: function() {
-    var captures, re;
-
-    // we have established the indentation regexp
-    if (this.indentRe){
-      captures = this.indentRe.exec(this.str);
-    // figure out if we are using tabs or spaces
-    } else {
-      // try tabs
-      re = /^\n([\t]*) */;
-      captures = re.exec(this.str);
-
-      // nope, try spaces
-      if (captures &amp;&amp; !captures[1].length) {
-        re = /^\n( *)/;
-        captures = re.exec(this.str);
-      }
-
-      // established
-      if (captures &amp;&amp; captures[1].length) this.indentRe = re;
-    }
-
-
-    if (captures) {
-      var tok
-        , indents = captures[1].length;
-
-      this.skip(captures);
-      if (this.str[0] === ' ' || this.str[0] === '\t') {
-        throw new Error('Invalid indentation, you can use tabs or spaces to indent but not both');
-      }
-
-      // Reset state
-      this.isVariable = false;
-
-      // Blank line
-      if ('\n' == this.str[0]) {
-        ++this.lineno;
-        return this.advance();
-      }
-
-      // Outdent
-      if (this.indentStack.length &amp;&amp; indents &lt; this.indentStack[0]) {
-        while (this.indentStack.length &amp;&amp; this.indentStack[0] &gt; indents) {
-          this.stash.push(new Token('outdent'));
-          this.indentStack.shift();
-        }
-        tok = this.stash.pop();
-      // Indent
-      } else if (indents &amp;&amp; indents != this.indentStack[0]) {
-        this.indentStack.unshift(indents);
-        tok = new Token('indent');
-      // Newline
-      } else {
-        tok = new Token('newline');
-      }
-
-      return tok;
-    }
-  },
-
-

'-'? (digit+ | digit* '.' digit+) unit -

-
-
unit: function() {
-    var captures;
-    if (captures = unit.exec(this.str)) {
-      this.skip(captures);
-      var n = parseFloat(captures[2]);
-      if ('-' == captures[1]) n = -n;
-      var node = new nodes.Unit(n, captures[3]);
-      return new Token('unit', node);
-    }
-  },
-
-

'"' [^"]+ '"' | "'"" [^']+ "'" -

-
-
string: function() {
-    var captures;
-    if (captures = /^("[^"]*"|'[^']*') */.exec(this.str)) {
-      var str = captures[1];
-      this.skip(captures);
-      return new Token('string', new nodes.String(str.slice(1,-1)));
-    }
-  },
-
-

nnnnnn | #nnn

-
-
color: function() {
-    return this.hex6()
-      || this.hex3();
-  },
-
-

nnn

-
-
hex3: function() {
-    var captures;
-    if (captures = /^#([a-fA-F0-9]{3}) */.exec(this.str)) {
-      this.skip(captures);
-      var rgb = captures[1]
-        , r = parseInt(rgb[0] + rgb[0], 16)
-        , g = parseInt(rgb[1] + rgb[1], 16)
-        , b = parseInt(rgb[2] + rgb[2], 16)
-        , color = new nodes.RGBA(r, g, b, 1);
-      color.raw = captures[0];
-      return new Token('color', color); 
-    }
-  },
-
-

nnnnnn

-
-
hex6: function() {
-    var captures;
-    if (captures = /^#([a-fA-F0-9]{6}) */.exec(this.str)) {
-      this.skip(captures);
-      var rgb = captures[1]
-        , r = parseInt(rgb.substr(0, 2), 16)
-        , g = parseInt(rgb.substr(2, 2), 16)
-        , b = parseInt(rgb.substr(4, 2), 16)
-        , color = new nodes.RGBA(r, g, b, 1);
-      color.raw = captures[0];
-      return new Token('color', color); 
-    }
-  },
-
-

[^\n,;]+ -

-
-
selector: function() {
-    var captures;
-    if (captures = /^[^{\n,]+/.exec(this.str)) {
-      var selector = captures[0];
-      this.skip(captures);
-      return new Token('selector', selector);
-    }
-  }
-};
-
-

middleware

lib/middleware.js
-

Module dependencies. -

-
-
var stylus = require('./stylus')
-  , fs = require('fs')
-  , url = require('url')
-  , basename = require('path').basename
-  , join = require('path').join
-  , ENOENT;
-
-// COMPAT:
-
-try {
-  ENOENT = require('constants').ENOENT;
-} catch (err) {
-  ENOENT = process.ENOENT;
-}
-
-

Return Connect middleware with the given options.

- -

Options

- -

force Always re-compile - src Source directory used to find .styl files - dest Destination directory used to output .css files - when undefined defaults to src. - compile Custom compile function, accepting the arguments - (str, path, callback). - compress Whether the output .css files should be compressed

- -

Examples

- -

Here we set up the custom compile function so that we may -set the compress option, or define additional functions.

- -

By default the compile function simply sets the filename -and renders the CSS.

- -
 function compile(str, path, fn) {
-   stylus(str)
-     .set('filename', path)
-     .set('compress', true)
-     .render(fn);
- }
- -

Pass the middleware to Connect, grabbing .styl files from this directory -and saving .css files to ./public. Also supplying our custom compile function.

- -

Following that we have a staticProvider layer setup to serve the .css -files generated by Stylus.

- -
 var server = connect.createServer(
-     stylus.middleware({
-         src: __dirname
-       , dest: __dirname + '/public'
-       , compile: compile
-     })
-   , connect.staticProvider(__dirname + '/public')
- );
- -

- -
  • param: Object options

  • return: Function

  • api: public

-
-
module.exports = function(options){
-  options = options || {};
-
-  // Accept src/dest dir
-  if ('string' == typeof options) {
-    options = { src: options };
-  }
-
-  // Force compilation
-  var force = options.force;
-
-  // Source dir required
-  var src = options.src;
-  if (!src) throw new Error('stylus.middleware() requires "src" directory');
-
-  // Default dest dir to source
-  var dest = options.dest
-    ? options.dest
-    : src;
-
-  // Default compile callback
-  options.compile = options.compile || function(str, path, fn){
-    stylus(str)
-      .set('filename', path)
-      .set('compress', options.compress)
-      .render(fn);
-  };
-
-  // Middleware
-  return function(req, res, next){
-    if ('GET' != req.method &amp;&amp; 'HEAD' != req.method) return next();
-    var path = url.parse(req.url).pathname;
-    if (/\.css$/.test(path)) {
-      var cssPath = join(dest, path)
-        , stylusPath = join(src, path.replace('.css', '.styl'));
-
-      // Ignore ENOENT to fall through as 404
-      function error(err) {
-        next(ENOENT == err.errno
-            ? null
-            : err);
-      }
-
-      // Force
-      if (force) return compile();
-
-      // Compile to cssPath
-      function compile() {
-        fs.readFile(stylusPath, 'utf8', function(err, str){
-          if (err) return error(err);
-          options.compile(str, stylusPath, function(err, css){
-            if (err) return next(err);
-            fs.writeFile(cssPath, css, 'utf8', function(err){
-              next(err);
-            });
-          });
-        });
-      }
-
-      // Compare mtimes
-      fs.stat(stylusPath, function(err, stylusStats){
-        if (err) return error(err);
-        fs.stat(cssPath, function(err, cssStats){
-          // CSS has not been compiled, compile it!
-          if (err) {
-            if (ENOENT == err.errno) {
-              compile();
-            } else {
-              next(err);
-            }
-          } else {
-            // Source has changed, compile it
-            if (stylusStats.mtime &gt; cssStats.mtime) {
-              compile();
-            // Already compiled, defer serving
-            } else {
-              next();
-            }
-          }
-        });
-      });
-    } else {
-      next();
-    }
-  }
-};
-

url

lib/functions/url.js
-

Module dependencies. -

-
-
var Compiler = require('../visitor/compiler')
-  , nodes = require('../nodes')
-  , parse = require('url').parse
-  , extname = require('path').extname
-  , utils = require('../utils')
-  , fs = require('fs');
-
-

Mime table. -

-
-
var mimes = {
-    '.gif': 'image/gif'
-  , '.png': 'image/png'
-  , '.jpg': 'image/jpeg'
-  , '.jpeg': 'image/jpeg'
-};
-
-

Return a url() function with the given options.

- -

Options

- -
  • limit bytesize limit defaulting to 30Kb
  • paths image resolution path(s), merged with general lookup paths
- -

Examples

- -

stylus(str) - .set('filename', __dirname + '/css/test.styl') - .define('url', stylus.url({ paths: [__dirname + '/public'] })) - .render(function(err, css){ ... })

- -

- -
  • param: Object options

  • return: Function

  • api: public

-
-
module.exports = function(options) {
-  options = options || {};
-
-  var sizeLimit = options.limit || 30000
-    , _paths = options.paths || [];
-
-  function url(url){
-    // Compile the url
-    var compiler = new Compiler(url);
-    compiler.isURL = true;
-    var url = url.nodes.map(function(node){
-      return compiler.visit(node);
-    }).join('');
-
-    // Parse literal 
-    var url = parse(url)
-      , ext = extname(url.pathname)
-      , mime = mimes[ext]
-      , literal = new nodes.Literal('url("' + url.href + '")')
-      , paths = _paths.concat(this.paths)
-      , founds
-      , buf;
-
-    // Not supported
-    if (!mime) return literal;
-
-    // Absolute
-    if (url.protocol) return literal;
-
-    // Lookup
-    found = utils.lookup(url.pathname, paths);
-
-    // Failed to lookup
-    if (!found) return literal;
-
-    // Read data
-    buf = fs.readFileSync(found);
-
-    // To large
-    if (buf.length &gt; sizeLimit) return literal;
-
-    // Encode
-    return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + '")');
-  };
-
-  url.raw = true;
-  return url;
-};
-

binop

lib/nodes/binop.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new BinOp with op, left and right.

- -

- -
  • param: String op

  • param: Node left

  • param: Node right

  • api: public

-
-
var BinOp = module.exports = function BinOp(op, left, right){
-  Node.call(this);
-  this.op = op;
-  this.left = left;
-  this.right = right;
-};
-
-

Inherit from Node.prototype. -

-
-
BinOp.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
BinOp.prototype.clone = function(){
-  var clone = new BinOp(
-      this.op
-    , this.left.clone()
-    , this.right ?
-      this.right.clone()
-      : null);
-  clone.lineno = this.lineno;
-  return clone;
-};
-

boolean

lib/nodes/boolean.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Boolean node with the given val.

- -

- -
  • param: Boolean val

  • api: public

-
-
var Boolean = module.exports = function Boolean(val){
-  Node.call(this);
-  if (this instanceof Boolean) {
-    this.val = !!val;
-  } else {
-    return val ? nodes.true : nodes.false;
-  }
-};
-
-

Inherit from Node.prototype. -

-
-
Boolean.prototype.__proto__ = Node.prototype;
-
-

Return this node.

- -

- -
  • return: Boolean

  • api: public

-
-
Boolean.prototype.toBoolean = function(){
-  return this;
-};
-
-

Negate the value.

- -

- -
  • return: Boolean

  • api: public

-
-
Boolean.prototype.negate = function(){
-  return this.val
-    ? nodes.false
-    : nodes.true;
-};
-
-

Return 'Boolean'.

- -

- -
  • return: String

  • api: public

-
-
Boolean.prototype.inspect = function(){
-  return '[Boolean ' + this.val + ']';
-};
-
-

Return 'true' or 'false'.

- -

- -
  • return: String

  • api: public

-
-
Boolean.prototype.toString = function(){
-  return this.val
-    ? 'true'
-    : 'false';
-};
-

block

lib/nodes/block.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Block node with parent Block.

- -

- -
  • param: Block parent

  • api: public

-
-
var Block = module.exports = function Block(parent, node){
-  Node.call(this);
-  this.nodes = [];
-  this.parent = parent;
-  this.node = node;
-  this.scope = true;
-};
-
-

Inherit from Node.prototype. -

-
-
Block.prototype.__proto__ = Node.prototype;
-
-

Check if this block has properties..

- -

- -
  • return: Boolean

  • api: public

-
-
Block.prototype.__defineGetter__('hasProperties', function(){
-  for (var i = 0, len = this.nodes.length; i &lt; len; ++i) {
-    if ('property' == this.nodes[i].nodeName) {
-      return true;
-    }
-  }
-});
-
-

Check if this block is empty.

- -

- -
  • return: Boolean

  • api: public

-
-
Block.prototype.__defineGetter__('isEmpty', function(){
-  return !this.nodes.length;
-});
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Block.prototype.clone = function(){
-  var clone = new Block(this.parent, this.node);
-  clone.lineno = this.lineno;
-  clone.scope = this.scope;
-  this.nodes.forEach(function(node){
-    node = node.clone();
-    switch (node.nodeName) {
-      case 'each':
-      case 'group':
-        node.block.parent = clone;
-        break;
-      case 'ident':
-        if ('function' == node.val.nodeName) {
-          node.val.block.parent = clone;
-        }
-    }
-    clone.push(node);
-  });
-  return clone;
-};
-
-

Push a node to this block.

- -

- -
  • param: Node node

  • api: public

-
-
Block.prototype.push = function(node){
-  this.nodes.push(node);
-};
-
-

charset

lib/nodes/charset.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Charset with the given val

- -

- -
  • param: String val

  • api: public

-
-
var Charset = module.exports = function Charset(val){
-  Node.call(this);
-  this.val = val;
-};
-
-

Inherit from Node.prototype. -

-
-
Charset.prototype.__proto__ = Node.prototype;
-
-

Return @charset "val".

- -

- -
  • return: String

  • api: public

-
-
Charset.prototype.toString = function(){
-  return '@charset ' + this.val;
-};
-
-

expression

lib/nodes/expression.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('../nodes')
-  , utils = require('../utils');
-
-

Initialize a new Expression.

- -

- -
  • param: Boolean isList

  • api: public

-
-
var Expression = module.exports = function Expression(isList){
-  Node.call(this);
-  this.nodes = [];
-  this.isList = isList;
-};
-
-

Check if the variable has a value.

- -

- -
  • return: Boolean

  • api: public

-
-
Expression.prototype.__defineGetter__('isEmpty', function(){
-  return !this.nodes.length;
-});
-
-

Return the first node in this expression.

- -

- -
  • return: Node

  • api: public

-
-
Expression.prototype.__defineGetter__('first', function(){
-  return this.nodes[0]
-    ? this.nodes[0].first
-    : nodes.null;
-});
-
-

Hash all the nodes in order.

- -

- -
  • return: String

  • api: public

-
-
Expression.prototype.__defineGetter__('hash', function(){
-  return this.nodes.map(function(node){
-    return node.hash;
-  }).join('::');
-});
-
-

Inherit from Node.prototype. -

-
-
Expression.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Expression.prototype.clone = function(){
-  var clone = new Expression(this.isList);
-  clone.lineno = this.lineno;
-  for (var i = 0; i &lt; this.nodes.length; ++i) {
-    clone.push(this.nodes[i].clone());
-  }
-  return clone;
-};
-
-

Push the given node.

- -

- -
  • param: Node node

  • api: public

-
-
Expression.prototype.push = function(node){
-  this.nodes.push(node);
-};
-
-

Operate on right with the given op.

- -

- -
  • param: String op

  • param: Node right

  • return: Node

  • api: public

-
-
Expression.prototype.operate = function(op, right){
-  switch (op) {
-    case '[]':
-      var expr = new nodes.Expression
-        , vals = utils.unwrap(this).nodes
-        , range = utils.unwrap(right).nodes;
-      range.forEach(function(unit){
-        if ('unit' == unit.nodeName) {
-          var node = vals[unit.val];
-          if (node) expr.push(node);
-        }
-      });
-      return expr.isEmpty
-        ? nodes.null
-        : expr;
-    default:
-      return Node.prototype.operate.call(this, op, right);
-  }
-};
-
-

Return "<a> <b> <c>" or "<a>, <b>, <c>" if -the expression represents a list.

- -

- -
  • return: String

  • api: public

-
-
Expression.prototype.toString = function(){
-  return this.nodes.map(function(node){
-    return node.toString();
-  }).join(this.isList ? ', ' : ' ');
-};
-
-
-
-

each

lib/nodes/each.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Each node with the given val name, -key name, expr, and block.

- -

- -
  • param: String val

  • param: String key

  • param: Expression expr

  • param: Block block

  • api: public

-
-
var Each = module.exports = function Each(val, key, expr, block){
-  Node.call(this);
-  this.val = val;
-  this.key = key;
-  this.expr = expr;
-  this.block = block;
-};
-
-

Inherit from Node.prototype. -

-
-
Each.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Each.prototype.clone = function(){
-  var clone = new Each(
-      this.val
-    , this.key
-    , this.expr.clone()
-    , this.block.clone());
-  clone.lineno = this.lineno;
-  return clone;
-};
-

call

lib/nodes/call.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Call with name and args.

- -

- -
  • param: String name

  • param: Expression args

  • api: public

-
-
var Call = module.exports = function Call(name, args){
-  Node.call(this);
-  this.name = name;
-  this.args = args;
-};
-
-

Inherit from Node.prototype. -

-
-
Call.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Call.prototype.clone = function(){
-  var clone = new Call(this.name, this.args.clone());
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Return <name>().

- -

- -
  • return: String

  • api: public

-
-
Call.prototype.toString = function(){
-  return this.name + '()';
-};
-
-

function

lib/nodes/function.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Function with name, params, and body.

- -

- -
  • param: String name

  • param: Params | Function params

  • param: Block body

  • api: public

-
-
var Function = module.exports = function Function(name, params, body){
-  Node.call(this);
-  this.name = name;
-  this.params = params;
-  this.block = body;
-  if ('function' == typeof params) this.fn = params;
-};
-
-

Check function arity.

- -

- -
  • return: Boolean

  • api: public

-
-
Function.prototype.__defineGetter__('arity', function(){
-  return this.params.length;
-});
-
-

Inherit from Node.prototype. -

-
-
Function.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Function.prototype.clone = function(){
-  if (this.fn) {
-    var clone = new Function(
-        this.name
-      , this.fn);
-  } else {
-    var clone = new Function(
-        this.name
-      , this.params.clone()
-      , this.block.clone());
-  }
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Return <name>(param1, param2, ...).

- -

- -
  • return: String

  • api: public

-
-
Function.prototype.toString = function(){
-  if (this.fn) {
-    return this.name
-      + '('
-      + this.fn.toString()
-        .match(/^function *\((.*?)\)/)
-        .slice(1)
-        .join(', ')
-      + ')';
-  } else {
-    return this.name
-      + '('
-      + this.params.nodes.join(', ')
-      + ')';
-  }
-};
-
-

group

lib/nodes/group.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Group.

- -
  • api: public

-
-
var Group = module.exports = function Group(){
-  Node.call(this);
-  this.nodes = [];
-};
-
-

Inherit from Node.prototype. -

-
-
Group.prototype.__proto__ = Node.prototype;
-
-

Push the given selector node.

- -

- -
  • param: Selector selector

  • api: public

-
-
Group.prototype.push = function(selector){
-  this.nodes.push(selector);
-};
-
-

Return this set's Block. -

-
-
Group.prototype.__defineGetter__('block', function(){
-  return this.nodes[0].block;
-});
-
-

Assign block to each selector in this set.

- -

- -
  • param: Block block

  • api: public

-
-
Group.prototype.__defineSetter__('block', function(block){
-  for (var i = 0, len = this.nodes.length; i &lt; len; ++i) {
-    this.nodes[i].block = block;
-  }
-});
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Group.prototype.clone = function(){
-  var clone = new Group;
-  clone.lineno = this.lineno;
-  this.nodes.forEach(function(node){
-    clone.push(node.clone());
-  });
-  clone.block = this.block.clone();
-  return clone;
-};
-
-

hsla

lib/nodes/hsla.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new HSLA with the given h,s,l,a component values.

- -

- -
  • param: Number h

  • param: Number s

  • param: Number l

  • param: Number a

  • api: public

-
-
var HSLA = exports = module.exports = function HSLA(h,s,l,a){
-  Node.call(this);
-  this.h = clampDegrees(h);
-  this.s = clampPercentage(s);
-  this.l = clampPercentage(l);
-  this.a = clampAlpha(a);
-  this.hsla = this;
-};
-
-

Inherit from Node.prototype. -

-
-
HSLA.prototype.__proto__ = Node.prototype;
-
-

Return hsla(n,n,n,n).

- -

- -
  • return: String

  • api: public

-
-
HSLA.prototype.toString = function(){
-  return 'hsla('
-    + this.h + ','
-    + this.s + ','
-    + this.l + ','
-    + this.a + ')';
-};
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
HSLA.prototype.clone = function(){
-  var clone = new HSLA(
-      this.h
-    , this.s
-    , this.l
-    , this.a);
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Return rgba RGBA representation.

- -

- -
  • return: RGBA

  • api: public

-
-
HSLA.prototype.__defineGetter__('rgba', function(){
-  return nodes.RGBA.fromHSLA(this);
-});
-
-

Return hash.

- -

- -
  • return: String

  • api: public

-
-
HSLA.prototype.__defineGetter__('hash', function(){
-  return this.rgba.toString();
-});
-
-

Coerce RGBA to HSLA.

- -

- -
  • param: Node other

  • return: Node

  • api: public

-
-
HSLA.prototype.coerce = function(other){
-  if (other instanceof nodes.RGBA) {
-    return other.hsla;
-  } else {
-    return Node.prototype.coerce.call(this, other);
-  }
-};
-
-

Operate on right with the given op.

- -

- -
  • param: String op

  • param: Node right

  • return: Node

  • api: public

-
-
HSLA.prototype.operate = function(op, right){
-  switch (op) {
-    case '+':
-      return new HSLA(
-          this.h + right.h
-        , this.s + right.s
-        , this.l + right.l
-        , 1 == right.a ? this.a : (this.a + right.a)
-        );
-    case '-':
-      return new HSLA(
-          this.h - right.h
-        , this.s - right.s
-        , this.l - right.l
-        , 1 == right.a ? this.a : (this.a - right.a)
-        );
-    case '*':
-      return new HSLA(
-          this.h * right.h
-        , this.s * right.s
-        , this.l * right.l
-        , this.a * right.a
-        );
-    case '/':
-      return new HSLA(
-          this.h / right.h
-        , this.s / right.s
-        , this.l / right.l
-        , this.a / right.a
-        );
-    default:
-      return Node.prototype.operate.call(this, op, right);
-  }
-};
-
-

Return HSLA representation of the given color.

- -

- -
  • param: RGBA color

  • return: HSLA

  • api: public

-
-
exports.fromRGBA = function(rgba){
-  var r = rgba.r / 255
-    , g = rgba.g / 255
-    , b = rgba.b / 255
-    , a = rgba.a;
-
-  var min = Math.min(r,g,b)
-    , max = Math.max(r,g,b)
-    , l = (max + min) / 2
-    , d = max - min
-    , h, s;
-
-  switch (max) {
-    case min: h = 0; break;
-    case r: h = 60 * (g-b) / d; break;
-    case g: h = 60 * (b-r) / d + 120; break;
-    case b: h = 60 * (r-g) / d + 240; break;
-  }
-
-  if (max == min) {
-    s = 0;
-  } else if (l &lt; .5) {
-    s = d / (2 * l);
-  } else {
-    s = d / (2 - 2 * l);
-  }
-
-  h %= 360;
-  s *= 100;
-  l *= 100;
-
-  return new HSLA(h,s,l,a);
-};
-
-

Clamp degree n >= 0 and <= 360.

- -

- -
  • param: Number n

  • return: Number

  • api: private

-
-
function clampDegrees(n) {
-  return Math.max(0, Math.min(n, 360));
-}
-
-

Clamp percentage n >= 0 and <= 100.

- -

- -
  • param: Number n

  • return: Number

  • api: private

-
-
function clampPercentage(n) {
-  return Math.max(0, Math.min(n, 100));
-}
-
-

Clamp alpha n >= 0 and <= 1.

- -

- -
  • param: Number n

  • return: Number

  • api: private

-
-
function clampAlpha(n) {
-  return Math.max(0, Math.min(n, 1));
-}
-
-

if

lib/nodes/if.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new If with the given cond.

- -

- -
  • param: Expression cond

  • param: Boolean | Block negate, block

  • api: public

-
-
var If = module.exports = function If(cond, negate){
-  Node.call(this);
-  this.cond = cond;
-  this.elses = [];
-  if (negate instanceof Node) {
-    this.block = negate;
-  } else {
-    this.negate = negate;
-  }
-};
-
-

Inherit from Node.prototype. -

-
-
If.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
If.prototype.clone = function(){
-  var cond = this.cond.clone()
-    , block = this.block.clone();
-  var clone = new If(cond, block);
-  clone.elses = this.elses.map(function(node){ return node.clone(); });
-  clone.negate = this.negate;
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

ident

lib/nodes/ident.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Ident by name with the given val node.

- -

- -
  • param: String name

  • param: Node val

  • api: public

-
-
var Ident = module.exports = function Ident(name, val){
-  Node.call(this);
-  this.name = name;
-  this.string = name;
-  this.val = val || nodes.null;
-};
-
-

Check if the variable has a value.

- -

- -
  • return: Boolean

  • api: public

-
-
Ident.prototype.__defineGetter__('isEmpty', function(){
-  return undefined == this.val;
-});
-
-

Return hash.

- -

- -
  • return: String

  • api: public

-
-
Ident.prototype.__defineGetter__('hash', function(){
-  return this.name;
-});
-
-

Inherit from Node.prototype. -

-
-
Ident.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Ident.prototype.clone = function(){
-  var clone = new Ident(this.name, this.val.clone());
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Return <name>.

- -

- -
  • return: String

  • api: public

-
-
Ident.prototype.toString = function(){
-  return this.name;
-};
-
-

Coerce other to an ident.

- -

- -
  • param: Node other

  • return: String

  • api: public

-
-
Ident.prototype.coerce = function(other){
-  if (other instanceof nodes.Literal ||
-      other instanceof Ident) {
-    return other;
-  } else {
-    return Node.prototype.coerce.call(this, other);
-  }
-};
-
-

import

lib/nodes/import.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Import with the given expr.

- -

- -
  • param: Expression expr

  • api: public

-
-
var Import = module.exports = function Import(expr){
-  Node.call(this);
-  this.path = expr;
-};
-
-

Inherit from Node.prototype. -

-
-
Import.prototype.__proto__ = Node.prototype;
-
-

index

lib/nodes/index.js
-

Constructors -

-
-
exports.Node = require('./node');
-exports.Root = require('./root');
-exports.Null = require('./null');
-exports.Each = require('./each');
-exports.If = require('./if');
-exports.Call = require('./call');
-exports.Page = require('./page');
-exports.UnaryOp = require('./unaryop');
-exports.BinOp = require('./binop');
-exports.Ternary = require('./ternary');
-exports.Block = require('./block');
-exports.Unit = require('./unit');
-exports.String = require('./string');
-exports.HSLA = require('./hsla');
-exports.RGBA = require('./rgba');
-exports.Ident = require('./ident');
-exports.Group = require('./group');
-exports.Literal = require('./literal');
-exports.Boolean = require('./boolean');
-exports.Return = require('./return');
-exports.Media = require('./media');
-exports.Params = require('./params');
-exports.Keyframes = require('./keyframes');
-exports.Charset = require('./charset');
-exports.Import = require('./import');
-exports.Function = require('./function');
-exports.Property = require('./property');
-exports.Selector = require('./selector');
-exports.Expression = require('./expression');
-
-

Singletons. -

-
-
exports.true = new exports.Boolean(true);
-exports.false = new exports.Boolean(false);
-exports.null = new exports.Null;
-

keyframes

lib/nodes/keyframes.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Keyframes with the given name.

- -

- -
  • param: String name

  • api: public

-
-
var Keyframes = module.exports = function Keyframes(name){
-  Node.call(this);
-  this.name = name;
-  this.frames = [];
-};
-
-

Inherit from Node.prototype. -

-
-
Keyframes.prototype.__proto__ = Node.prototype;
-
-

Push the given block at pos.

- -

- -
  • param: Unit pos

  • param: Block block

  • api: public

-
-
Keyframes.prototype.push = function(pos, block){
-  this.frames.push({
-      pos: pos
-    , block: block
-  });
-};
-
-

Return @keyframes name.

- -

- -
  • return: String

  • api: public

-
-
Keyframes.prototype.toString = function(){
-  return '@keyframes ' + this.name;
-};
-
-

literal

lib/nodes/literal.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Literal with the given str.

- -

- -
  • param: String str

  • api: public

-
-
var Literal = module.exports = function Literal(str){
-  Node.call(this);
-  this.val = str;
-};
-
-

Inherit from Node.prototype. -

-
-
Literal.prototype.__proto__ = Node.prototype;
-
-

Return hash.

- -

- -
  • return: String

  • api: public

-
-
Literal.prototype.__defineGetter__('hash', function(){
-  return this.val;
-});
-
-

Return literal value.

- -

- -
  • return: String

  • api: public

-
-
Literal.prototype.toString = function(){
-  return this.val;
-};
-
-

Coerce other to a literal.

- -

- -
  • param: Node other

  • return: String

  • api: public

-
-
Literal.prototype.coerce = function(other){
-  if (other instanceof Literal ||
-      other instanceof nodes.Ident) {
-    return other;
-  } else {
-    return Node.prototype.coerce.call(this, other);
-  }
-};
-
-

media

lib/nodes/media.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Media with the given val

- -

- -
  • param: String val

  • api: public

-
-
var Media = module.exports = function Media(val){
-  Node.call(this);
-  this.val = val;
-};
-
-

Inherit from Node.prototype. -

-
-
Media.prototype.__proto__ = Node.prototype;
-
-

Return @media "val".

- -

- -
  • return: String

  • api: public

-
-
Media.prototype.toString = function(){
-  return '@media ' + this.val;
-};
-
-

node

lib/nodes/node.js
-

Module dependencies. -

-
-
var Evaluator = require('../visitor/evaluator')
-  , utils = require('../utils')
-  , nodes = require('./');
-
-

Node constructor.

- -
  • api: public

-
-
var Node = module.exports = function Node(){
-  this.lineno = nodes.lineno;
-  Object.defineProperty(this, 'filename', { value: nodes.filename });
-  Object.defineProperty(this, 'source', { value: nodes.source });
-};
-
-

Return this node.

- -

- -
  • return: Node

  • api: public

-
-
Node.prototype.__defineGetter__('first', function(){
-  return this;
-});
-
-

Return hash.

- -

- -
  • return: String

  • api: public

-
-
Node.prototype.__defineGetter__('hash', function(){
-  return this.val;
-});
-
-

Return node name.

- -

- -
  • return: String

  • api: public

-
-
Node.prototype.__defineGetter__('nodeName', function(){
-  return this.constructor.name.toLowerCase();
-});
-
-

Return this node.

- -

- -
  • return: Node

  • api: public

-
-
Node.prototype.clone = function(){
-  return this;
-};
-
-

Nodes by default evaluate to themselves.

- -

- -
  • return: Node

  • api: public

-
-
Node.prototype.eval = function(){
-  return new Evaluator(this).evaluate();
-};
-
-

Return true.

- -

- -
  • return: Boolean

  • api: public

-
-
Node.prototype.toBoolean = function(){
-  return nodes.true;
-};
-
-

Operate on right with the given op.

- -

- -
  • param: String op

  • param: Node right

  • return: Node

  • api: public

-
-
Node.prototype.operate = function(op, right){
-  switch (op) {
-    case 'is a':
-      if ('string' == right.nodeName) {
-        if ('color' == right.string) {
-          return nodes.Boolean('rgba' == this.nodeName || 'hsla' == this.nodeName);
-        } else {
-          return nodes.Boolean(this.nodeName == right.val);
-        }
-      } else {
-        throw new Error('"is a" expects a string, got ' + right.nodeName);
-      }
-    case '==':
-      return nodes.Boolean(this.hash == right.hash);
-    case '!=':
-      return nodes.Boolean(this.hash != right.hash);
-    case '>=':
-      return nodes.Boolean(this.hash &gt;= right.hash);
-    case '<=':
-      return nodes.Boolean(this.hash &lt;= right.hash);
-    case '>':
-      return nodes.Boolean(this.hash &gt; right.hash);
-    case '<':
-      return nodes.Boolean(this.hash &lt; right.hash);
-    case '||':
-      return nodes.true == this.toBoolean()
-        ? this
-        : right;
-    case 'in':
-      var vals = utils.unwrap(right).nodes
-        , hash = this.hash;
-      if (!vals) throw new Error('"in" given invalid right-hand operand, expecting an expression');
-      for (var i = 0, len = vals.length; i &lt; len; ++i) {
-        if (hash == vals[i].hash) {
-          return nodes.true;
-        }
-      }
-      return nodes.false;
-    case '&&':
-      var a = this.toBoolean()
-        , b = right.toBoolean();
-      return nodes.true == a &amp;&amp; nodes.true == b
-        ? right
-        : nodes.false == a
-          ? this
-          : right;
-    default:
-      if ('[]' == op) {
-        var msg = 'cannot perform '
-          + this
-          + '[' + right + ']';
-      } else {
-        var msg = 'cannot perform'
-          + ' ' + this
-          + ' ' + op
-          + ' ' + right;
-      }
-      throw new Error(msg);
-  }
-};
-
-

Default coercion throws.

- -

- -
  • param: Node other

  • return: Node

  • api: public

-
-
Node.prototype.coerce = function(other){
-  if (other.nodeName == this.nodeName) return other;
-  throw new Error('cannot coerce ' + other + ' to ' + this.nodeName);
-};
-
-

null

lib/nodes/null.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Null node.

- -
  • api: public

-
-
var Null = module.exports = function Null(){};
-
-

Inherit from Node.prototype. -

-
-
Null.prototype.__proto__ = Node.prototype;
-
-

Return 'Null'.

- -

- -
  • return: String

  • api: public

-
-
Null.prototype.inspect = 
-Null.prototype.toString = function(){
-  return '[Null]';
-};
-
-

Return false.

- -

- -
  • return: Boolean

  • api: public

-
-
Null.prototype.toBoolean = function(){
-  return nodes.false;
-};
-
-

Return hash.

- -

- -
  • return: String

  • api: public

-
-
Null.prototype.__defineGetter__('hash', function(){
-  return null;
-});
-

params

lib/nodes/params.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Params with name, params, and body.

- -

- -
  • param: String name

  • param: Params params

  • param: Expression body

  • api: public

-
-
var Params = module.exports = function Params(){
-  Node.call(this);
-  this.nodes = [];
-};
-
-

Check function arity.

- -

- -
  • return: Boolean

  • api: public

-
-
Params.prototype.__defineGetter__('length', function(){
-  return this.nodes.length;
-});
-
-

Inherit from Node.prototype. -

-
-
Params.prototype.__proto__ = Node.prototype;
-
-

Push the given node.

- -

- -
  • param: Node node

  • api: public

-
-
Params.prototype.push = function(node){
-  this.nodes.push(node);
-};
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Params.prototype.clone = function(){
-  var clone = new Params;
-  clone.lineno = this.lineno;
-  this.nodes.forEach(function(node){
-    clone.push(node.clone());
-  });
-  return clone;
-};
-
-
-

page

lib/nodes/page.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Page with the given selector and block.

- -

- -
  • param: Selector selector

  • param: Block block

  • api: public

-
-
var Page = module.exports = function Page(selector, block){
-  Node.call(this);
-  this.selector = selector;
-  this.block = block;
-};
-
-

Inherit from Node.prototype. -

-
-
Page.prototype.__proto__ = Node.prototype;
-
-

Return @oage name.

- -

- -
  • return: String

  • api: public

-
-
Page.prototype.toString = function(){
-  return '@page ' + this.selector;
-};
-
-

property

lib/nodes/property.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Property with the given segs and optional expr.

- -

- -
  • param: Array segs

  • param: Expression expr

  • api: public

-
-
var Property = module.exports = function Property(segs, expr){
-  Node.call(this);
-  this.segments = segs;
-  this.expr = expr;
-};
-
-

Inherit from Node.prototype. -

-
-
Property.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Property.prototype.clone = function(){
-  var clone = new Property(this.segments);
-  clone.lineno = this.lineno;
-  this.segments = this.segments.map(function(node){ return node.clone(); });
-  if (this.expr) clone.expr = this.expr.clone();
-  return clone;
-};
-
-

return

lib/nodes/return.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Return node with the given expr.

- -

- -
  • param: Expression expr

  • api: public

-
-
var Return = module.exports = function Return(expr){
-  this.expr = expr || nodes.null;
-};
-
-

Inherit from Node.prototype. -

-
-
Return.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Return.prototype.clone = function(){
-  var clone = new Return(this.expr.clone());
-  clone.lineno = this.lineno;
-  return clone;
-};
-

rgba

lib/nodes/rgba.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , HSLA = require('./hsla')
-  , nodes = require('./');
-
-

Initialize a new RGBA with the given r,g,b,a component values.

- -

- -
  • param: Number r

  • param: Number g

  • param: Number b

  • param: Number a

  • api: public

-
-
var RGBA = exports = module.exports = function RGBA(r,g,b,a){
-  Node.call(this);
-  this.r = clamp(r);
-  this.g = clamp(g);
-  this.b = clamp(b);
-  this.a = clampAlpha(a);
-  this.rgba = this;
-};
-
-

Inherit from Node.prototype. -

-
-
RGBA.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
RGBA.prototype.clone = function(){
-  var clone = new RGBA(
-      this.r
-    , this.g
-    , this.b
-    , this.a);
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Return true.

- -

- -
  • return: Boolean

  • api: public

-
-
RGBA.prototype.toBoolean = function(){
-  return nodes.true;
-};
-
-

Return HSLA representation.

- -

- -
  • return: HSLA

  • api: public

-
-
RGBA.prototype.__defineGetter__('hsla', function(){
-  return HSLA.fromRGBA(this);
-});
-
-

Return hash.

- -

- -
  • return: String

  • api: public

-
-
RGBA.prototype.__defineGetter__('hash', function(){
-  return this.toString();
-});
-
-

Coerce HSLA and Unit to RGBA.

- -

- -
  • param: Node other

  • return: Node

  • api: public

-
-
RGBA.prototype.coerce = function(other){
-  if (other instanceof nodes.HSLA) {
-    return other.rgba;
-  } else if (other instanceof nodes.Unit) {
-    var n = other.val;
-    return new RGBA(n,n,n,1);
-  } else {
-    return Node.prototype.coerce.call(this, other);
-  }
-};
-
-

Operate on right with the given op.

- -

- -
  • param: String op

  • param: Node right

  • return: Node

  • api: public

-
-
RGBA.prototype.operate = function(op, right){
-  switch (op) {
-    case '+':
-      return new RGBA(
-          this.r + right.r
-        , this.g + right.g
-        , this.b + right.b
-        , 1 == right.a ? this.a : (this.a + right.a)
-        );
-    case '-':
-      return new RGBA(
-          this.r - right.r
-        , this.g - right.g
-        , this.b - right.b
-        , 1 == right.a ? this.a : (this.a - right.a)
-        );
-    case '*':
-      return new RGBA(
-          this.r * right.r
-        , this.g * right.g
-        , this.b * right.b
-        , this.a * right.a
-        );
-    case '/':
-      return new RGBA(
-          this.r / right.r
-        , this.g / right.g
-        , this.b / right.b
-        , this.a / right.a
-        );
-    default:
-      return Node.prototype.operate.call(this, op, right);
-  }
-};
-
-

Return #nnnnnn, #nnn, or rgba(n,n,n,n) string representation of the color.

- -

- -
  • return: String

  • api: public

-
-
RGBA.prototype.toString = function(){
-  function pad(n) {
-    return n &lt; 16
-      ? '0' + n.toString(16)
-      : n.toString(16);
-  }
-
-  if (1 == this.a) {
-    var r = pad(this.r)
-      , g = pad(this.g)
-      , b = pad(this.b);
-
-    // Compress
-    if (r[0] == r[1] &amp;&amp; g[0] == g[1] &amp;&amp; b[0] == b[1]) {
-      return '#' + r[0] + g[0] + b[0];
-    } else {
-      return '#' + r + g + b;
-    }
-  } else {
-    return 'rgba('
-      + this.r + ','
-      + this.g + ','
-      + this.b + ','
-      + this.a + ')';
-  }
-};
-
-

Return a RGBA from the given hsla.

- -

- -
  • param: HSLA hsla

  • return: RGBA

  • api: public

-
-
exports.fromHSLA = function(hsla){
-  var h = hsla.h / 360
-    , s = hsla.s / 100
-    , l = hsla.l / 100
-    , a = hsla.a;
-
-  var m2 = l &lt;= .5 ? l * (s + 1) : l + s - l * s
-    , m1 = l * 2 - m2;
-
-  var r = hue(h + 1/3) * xff
-    , g = hue(h) * xff
-    , b = hue(h - 1/3) * xff;
-
-  function hue(h) {
-    if (h &lt; 0) ++h;
-    if (h &gt; 1) --h;
-    if (h * 6 &lt; 1) return m1 + (m2 - m1) * h * 6;
-    if (h * 2 &lt; 1) return m2;
-    if (h * 3 &lt; 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
-    return m1;
-  }
-  
-  return new RGBA(r,g,b,a);
-};
-
-

Clamp n >= 0 and <= 255.

- -

- -
  • param: Number n

  • return: Number

  • api: private

-
-
function clamp(n) {
-  return Math.max(0, Math.min(n.toFixed(0), 255));
-}
-
-

Clamp alpha n >= 0 and <= 1.

- -

- -
  • param: Number n

  • return: Number

  • api: private

-
-
function clampAlpha(n) {
-  return Math.max(0, Math.min(n, 1));
-}
-
-

root

lib/nodes/root.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Root node.

- -
  • api: public

-
-
var Root = module.exports = function Root(){
-  this.nodes = [];
-};
-
-

Inherit from Node.prototype. -

-
-
Root.prototype.__proto__ = Node.prototype;
-
-

Push a node to this block.

- -

- -
  • param: Node node

  • api: public

-
-
Root.prototype.push = function(node){
-  this.nodes.push(node);
-};
-
-

Return "root".

- -

- -
  • return: String

  • api: public

-
-
Root.prototype.toString = function(){
-  return '[Root]';
-};
-
-

selector

lib/nodes/selector.js
-

Module dependencies. -

-
-
var Block = require('./block')
-  , Node = require('./node');
-
-

Initialize a new Selector with the given val.

- -

- -
  • param: String val

  • api: public

-
-
var Selector = module.exports = function Selector(val){
-  Node.call(this);
-  this.val = val.replace(/ +$/, '');
-};
-
-

Inherit from Node.prototype. -

-
-
Selector.prototype.__proto__ = Node.prototype;
-
-

Return the selector string.

- -

- -
  • return: String

  • api: public

-
-
Selector.prototype.toString = function(){
-  return this.val;
-};
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Selector.prototype.clone = function(){
-  var clone = new Selector(this.val);
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

string

lib/nodes/string.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new String with the given val.

- -

- -
  • param: String val

  • api: public

-
-
var String = module.exports = function String(val){
-  Node.call(this);
-  this.val = val;
-  this.string = val;
-};
-
-

Inherit from Node.prototype. -

-
-
String.prototype.__proto__ = Node.prototype;
-
-

Return quoted string.

- -

- -
  • return: String

  • api: public

-
-
String.prototype.toString = function(){
-  return '"' + this.val + '"';
-};
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
String.prototype.clone = function(){
-  var clone = new String(this.val);
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Return Boolean based on the length of this string.

- -

- -
  • return: Boolean

  • api: public

-
-
String.prototype.toBoolean = function(){
-  return nodes.Boolean(this.val.length);
-};
-
-

Coerce other to a string.

- -

- -
  • param: Node other

  • return: String

  • api: public

-
-
String.prototype.coerce = function(other){
-  if (other instanceof String) {
-    return other;
-  } else {
-    return new String(other.toString());
-  }
-};
-
-

Operate on right with the given op.

- -

- -
  • param: String op

  • param: Node right

  • return: Node

  • api: public

-
-
String.prototype.operate = function(op, right){
-  switch (op) {
-    case '+':
-      return new String(this.val + right.val);
-    default:
-      return Node.prototype.operate.call(this, op, right);
-  }
-};
-
-

ternary

lib/nodes/ternary.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new Ternary with cond, trueExpr and falseExpr.

- -

- -
  • param: Expression cond

  • param: Expression trueExpr

  • param: Expression falseExpr

  • api: public

-
-
var Ternary = module.exports = function Ternary(cond, trueExpr, falseExpr){
-  Node.call(this);
-  this.cond = cond;
-  this.trueExpr = trueExpr;
-  this.falseExpr = falseExpr;
-};
-
-

Inherit from Node.prototype. -

-
-
Ternary.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Ternary.prototype.clone = function(){
-  var clone = new Ternary(
-      this.cond.clone()
-    , this.trueExpr.clone()
-    , this.falseExpr.clone());
-  clone.lineno = this.lineno;
-  return clone;
-};
-

unaryop

lib/nodes/unaryop.js
-

Module dependencies. -

-
-
var Node = require('./node');
-
-

Initialize a new UnaryOp with op, and expr.

- -

- -
  • param: String op

  • param: Node expr

  • api: public

-
-
var UnaryOp = module.exports = function UnaryOp(op, expr){
-  Node.call(this);
-  this.op = op;
-  this.expr = expr;
-};
-
-

Inherit from Node.prototype. -

-
-
UnaryOp.prototype.__proto__ = Node.prototype;
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
UnaryOp.prototype.clone = function(){
-  var clone = new UnaryOp(this.op, this.expr.clone());
-  clone.lineno = this.lineno;
-  return clone;
-};
-

unit

lib/nodes/unit.js
-

Module dependencies. -

-
-
var Node = require('./node')
-  , nodes = require('./');
-
-

Initialize a new Unit with the given val and unit type -such as "px", "pt", "in", etc.

- -

- -
  • param: String val

  • param: String type

  • api: public

-
-
var Unit = module.exports = function Unit(val, type){
-  Node.call(this);
-  this.val = val;
-  this.type = type;
-};
-
-

Inherit from Node.prototype. -

-
-
Unit.prototype.__proto__ = Node.prototype;
-
-

Return Boolean based on the unit value.

- -

- -
  • return: Boolean

  • api: public

-
-
Unit.prototype.toBoolean = function(){
-  return nodes.Boolean(this.type
-      ? true
-      : this.val);
-};
-
-

Return unit string.

- -

- -
  • return: String

  • api: public

-
-
Unit.prototype.toString = function(){
-  var n = this.val;
-  if ('px' == this.type) n = n.toFixed(0);
-  return n + (this.type || '');
-};
-
-

Return a clone of this node.

- -

- -
  • return: Node

  • api: public

-
-
Unit.prototype.clone = function(){
-  var clone = new Unit(this.val, this.type);
-  clone.lineno = this.lineno;
-  return clone;
-};
-
-

Operate on right with the given op.

- -

- -
  • param: String op

  • param: Node right

  • return: Node

  • api: public

-
-
Unit.prototype.operate = function(op, right){
-  switch (op) {
-    case '-':
-      return new Unit(this.val - right.val, this.type);
-    case '+':
-      return new Unit(this.val + right.val, this.type);
-    case '/':
-      return new Unit(this.val / right.val, this.type);
-    case '*':
-      return new Unit(this.val * right.val, this.type);
-    case '%':
-      return new Unit(this.val % right.val, this.type);
-    case '**':
-      return new Unit(Math.pow(this.val, right.val), this.type);
-    case '..':
-    case '...':
-      var start = this.val
-        , end = right.val
-        , expr = new nodes.Expression
-        , inclusive = '..' == op;
-      do {
-        expr.push(new nodes.Unit(start));
-      } while (inclusive ? ++start &lt;= end : ++start &lt; end);
-      return expr;
-    default:
-      return Node.prototype.operate.call(this, op, right);
-  }
-};
-
-

Coerce other unit to the same type as this unit.

- -

Supports

- -

mm -> cm | in - cm -> mm | in - in -> mm | cm

- -

ms -> s - s -> ms

- -

Hz -> kHz - kHz -> Hz

- -

- -
  • param: Unit other

  • return: Unit

  • api: public

-
-
Unit.prototype.coerce = function(other){
-  if (other instanceof Unit) {
-    var a = this
-      , b = other;
-    switch (a.type) {
-      case 'mm':
-        switch (b.type) {
-          case 'cm':
-            return new nodes.Unit(b.val * 2.54, 'mm');
-          case 'in':
-            return new nodes.Unit(b.val * 25.4, 'mm');
-        }
-      case 'cm':
-        switch (b.type) {
-          case 'mm':
-            return new nodes.Unit(b.val / 10, 'cm');
-          case 'in':
-            return new nodes.Unit(b.val * 2.54, 'cm');
-        }
-      case 'in':
-        switch (b.type) {
-          case 'mm':
-            return new nodes.Unit(b.val / 25.4, 'in');
-          case 'cm':
-            return new nodes.Unit(b.val / 2.54, 'in');
-        }
-      case 'ms':
-        switch (b.type) {
-          case 's':
-            return new nodes.Unit(b.val * 1000, 'ms');
-        }
-      case 's':
-        switch (b.type) {
-          case 'ms':
-            return new nodes.Unit(b.val / 1000, 's');
-        }
-      case 'Hz':
-        switch (b.type) {
-          case 'kHz':
-            return new nodes.Unit(b.val * 1000, 'Hz');
-        }
-      case 'kHz':
-        switch (b.type) {
-          case 'Hz':
-            return new nodes.Unit(b.val / 1000, 'kHz');
-        }
-    }
-    return new nodes.Unit(b.val, a.type);
-  } else if (other instanceof nodes.String) {
-    var val = parseInt(other.val, 10);
-    if (isNaN(val)) Node.prototype.coerce.call(this, other);
-    return new nodes.Unit(val);
-  } else {
-    return Node.prototype.coerce.call(this, other);
-  }
-};
-
-

parser

lib/parser.js
-

Module dependencies. -

-
-
var Lexer = require('./lexer')
-  , nodes = require('./nodes')
-  , inspect = require('sys').inspect;
-
-

Selector composite tokens. -

-
-
var selectorTokens = [
-    'ident'
-  , 'string'
-  , 'selector'
-  , 'function'
-  , 'comment'
-  , 'space'
-  , 'color'
-  , 'unit'
-  , 'for'
-  , '['
-  , ']'
-  , '('
-  , ')'
-  , '+'
-  , '-'
-  , '*'
-  , '<'
-  , '>'
-  , '='
-  , ':'
-  , '&'
-  , '~'
-];
-
-

CSS3 pseudo-selectors. -

-
-
var pseudoSelectors = [
-    'root'
-  , 'nth-child'
-  , 'nth-last-child'
-  , 'nth-of-type'
-  , 'nth-last-of-type'
-  , 'first-child'
-  , 'last-child'
-  , 'first-of-type'
-  , 'last-of-type'
-  , 'only-child'
-  , 'only-of-type'
-  , 'empty'
-  , 'link'
-  , 'visited'
-  , 'active'
-  , 'hover'
-  , 'focus'
-  , 'target'
-  , 'lang'
-  , 'enabled'
-  , 'disabled'
-  , 'checked'
-  , 'not'
-];
-
-

Initialize a new Parser with the given str and options.

- -

- -
  • param: String str

  • param: Object options

  • api: private

-
-
var Parser = module.exports = function Parser(str, options) {
-  var self = this;
-  options = options || {};
-  this.str = nodes.source = str;
-  this.lexer = new Lexer(str, options);
-  this.root = options.root || new nodes.Root;
-  this.state = ['root'];
-  this.state.pop = function(){
-    self.prevState = [].pop.call(this);
-  };
-};
-
-

Parser prototype. -

-
-
Parser.prototype = {
-
-

Constructor. -

-
-
constructor: Parser,
-
-

Return current state.

- -

- -
  • return: String

  • api: private

-
-
currentState: function() {
-    return this.state[this.state.length - 1];
-  },
-
-

Parse the input, then return the root node.

- -

- -
  • return: Node

  • api: private

-
-
parse: function(){
-    var block = this.parent = this.root;
-    while ('eos' != this.peek().type) {
-      if (this.accept('newline')) continue;
-      var stmt = this.statement();
-      this.accept(';');
-      if (!stmt) this.error('unexpected token {peek}, not allowed at the root level');
-      block.push(stmt);
-    }
-    return block;
-  },
-
-

Throw an Error with the given msg.

- -

- -
  • param: String msg

  • api: private

-
-
error: function(msg){
-    var type = this.peek().type
-      , val = undefined == this.peek().val
-        ? ''
-        : ' ' + this.peek().toString();
-    if (val.trim() == type.trim()) val = '';
-    throw new Error(msg.replace('{peek}', type + val));
-  },
-
-

Accept the given token type, and return it, -otherwise return undefined.

- -

- -
  • param: String type

  • return: Token

  • api: private

-
-
accept: function(type){
-    if (type == this.peek().type) {
-      return this.next();
-    }
-  },
-
-

Expect token type and return it, throw otherwise.

- -

- -
  • param: String type

  • return: Token

  • api: private

-
-
expect: function(type){
-    if (type != this.peek().type) {
-      throw new Error('expected ' + type + ', got ' + this.peek());
-    }
-    return this.next();
-  },
-
-

Get the next token.

- -

- -
  • return: Token

  • api: private

-
-
next: function() {
-    var tok = this.lexer.next();
-    nodes.lineno = tok.lineno;
-    return tok;
-  },
-
-

Peek with lookahead(1).

- -

- -
  • return: Token

  • api: private

-
-
peek: function() {
-    return this.lexer.peek();
-  },
-
-

Lookahead n tokens.

- -

- -
  • param: Number n

  • return: Token

  • api: private

-
-
lookahead: function(n){
-    return this.lexer.lookahead(n);
-  },
-
-

Check if the token at n is a valid selector token.

- -

- -
  • param: Number n

  • return: Boolean

  • api: private

-
-
isSelectorToken: function(n) {
-    var la = this.lookahead(n).type;
-    switch (la) {
-      case 'for':
-        return this.bracketed;
-      case '[':
-        this.bracketed = true;
-        return true;
-      case ']':
-        this.bracketed = false;
-        return true;
-      default:
-        return ~selectorTokens.indexOf(la);
-    }
-  },
-
-

Check if the token at n is a pseudo selector.

- -

- -
  • param: Number n

  • return: Boolean

  • api: private

-
-
isPseudoSelector: function(n){
-    return ~pseudoSelectors.indexOf(this.lookahead(n).val.name);
-  },
-
-

Valid selector tokens. -

-
-
selectorToken: function() {
-    if (this.isSelectorToken(1)) return this.next();
-  },
-
-

Consume whitespace. -

-
-
skipWhitespace: function() {
-    while (~['space', 'indent', 'outdent', 'newline'].indexOf(this.peek().type))
-      this.next();
-  },
-
-

Consume spaces. -

-
-
skipSpaces: function() {
-    while ('space' == this.peek().type)
-      this.next();
-  },
-
-

Check if the following sequence of tokens -forms a function definition, ie trailing -{ or indentation. -

-
-
looksLikeFunctionDefinition: function(i) {
-    return 'indent' == this.lookahead(i).type
-      || '{' == this.lookahead(i).type;
-  },
-
-

Check if the following sequence of tokens -forms a selector. -

-
-
looksLikeSelector: function() {
-    var i = 1;
-
-    // Assume selector when an ident is
-    // followed by a selector
-    while ('ident' == this.lookahead(i).type
-      &amp;&amp; 'newline' == this.lookahead(i + 1).type) i += 2;
-
-    // Assume pseudo selectors are NOT properties
-    // as 'td:th-child(1)' may look like a property
-    // and function call to the parser otherwise
-    while (this.isSelectorToken(i)) {
-      if (':' == this.lookahead(i++).type
-        &amp;&amp; this.isPseudoSelector(i))
-        return true;
-    }
-
-    // Trailing comma
-    if (',' == this.lookahead(i).type
-      &amp;&amp; 'newline' == this.lookahead(i + 1).type)
-      return true;
-
-    // Trailing brace
-    if ('{' == this.lookahead(i).type
-      &amp;&amp; 'newline' == this.lookahead(i + 1).type)
-      return true;
-
-    // css-style mode, false on ; }
-    if (this.css) {
-      if (';' == this.lookahead(i) ||
-          '}' == this.lookahead(i))
-        return false;
-    }
-
-    // Trailing separators
-    while (!~[
-        'newline'
-      , 'indent'
-      , 'outdent'
-      , 'for'
-      , 'if'
-      , ';'
-      , '}'].indexOf(this.lookahead(i).type))
-      ++i;
-
-    if ('indent' == this.lookahead(i).type)
-      return true;
-  },
-
-

statement -| statement 'if' expression -| statement 'unless' expression -

-
-
statement: function() {
-    var stmt = this.stmt()
-      , state = this.prevState
-      , block
-      , op;
-
-    // special-case statements since it
-    // is not an expression. We could
-    // implement postfix conditionals at
-    // the expression level, however they
-    // would then fail to enclose properties
-    if (this.allowPostfix) {
-      delete this.allowPostfix;
-      state = 'expression';
-    }
-
-    switch (state) {
-      case 'assignment':
-      case 'expression':
-      case 'function arguments':
-        while (op =
-             this.accept('if')
-          || this.accept('unless')
-          || this.accept('for')) {
-          switch (op.type) {
-            case 'if':
-            case 'unless':
-              stmt = new nodes.If(this.expression(), stmt);
-              stmt.postfix = true;
-              stmt.negate = 'unless' == op.type;
-              this.accept(';');
-              break;
-            case 'for':
-              var key
-                , val = this.id().name;
-              if (this.accept(',')) key = this.id().name;
-              this.expect('in');
-              var each = new nodes.Each(val, key, this.expression());
-              block = new nodes.Block;
-              block.push(stmt);
-              each.block = block;
-              stmt = each;
-          }
-        }
-    }
-
-    return stmt;
-  },
-
-

ident - | selector - | literal - | charset - | import - | media - | keyframes - | page - | for - | if - | unless - | expression - | 'return' expression -

-
-
stmt: function() {
-    var type = this.peek().type;
-    switch (type) {
-      case 'selector':
-      case 'literal':
-      case 'keyframes':
-      case 'charset':
-      case 'import':
-      case 'media':
-      case 'page':
-      case 'ident':
-      case 'unless':
-      case 'function':
-      case 'for':
-      case 'if':
-        return this[type]();
-      case 'return':
-        return this.return();
-      case '{':
-        return this.property();
-      default:
-        // Contextual selectors
-        switch (this.currentState()) {
-          case 'root':
-          case 'selector':
-          case 'conditional':
-          case 'keyframe':
-          case 'function':
-          case 'media':
-          case 'for':
-            switch (type) {
-              case 'color':
-              case '~':
-              case '+':
-              case '>':
-              case '<':
-              case '*':
-              case ':':
-              case '&':
-              case '[':
-                return this.selector();
-            }
-        }
-
-        // Expression fallback
-        var expr = this.expression();
-        if (expr.isEmpty) this.error('unexpected {peek}');
-        return expr;
-    }
-  },
-
-

indent (!outdent)+ outdent -

-
-
block: function(node, scope) {
-    var delim
-      , stmt
-      , _ = this.css
-      , block = this.parent = new nodes.Block(this.parent, node);
-
-    if (false === scope) block.scope = false;
-
-    // css-style
-    if (this.css = this.accept('{')) {
-      delim = '}';
-      this.skipWhitespace();
-    } else {
-      delim = 'outdent';
-      this.expect('indent');
-    }
-
-    while (delim != this.peek().type) {
-      // css-style
-      if (this.css) {
-        if (this.accept('newline')) continue;
-        stmt = this.statement();
-        this.accept(';');
-        this.skipWhitespace();
-      } else {
-        if (this.accept('newline')) continue;
-        stmt = this.statement();
-        this.accept(';');
-      }
-      if (!stmt) this.error('unexpected token {peek} in block');
-      block.push(stmt);
-    }
-
-    // css-style
-    if (this.css) {
-      this.skipWhitespace();
-      this.expect('}');
-      this.skipSpaces();
-      this.css = _;
-    } else {
-      this.expect('outdent');
-    }
-
-    this.parent = block.parent;
-    return block;
-  },
-
-

for val (',' key) in expr -

-
-
for: function() {
-    this.expect('for');
-    var key
-      , val = this.id().name;
-    if (this.accept(',')) key = this.id().name;
-    this.expect('in');
-    var each = new nodes.Each(val, key, this.expression());
-    this.state.push('for');
-    each.block = this.block(each, false);
-    this.state.pop();
-    return each;
-  },
-
-

return expression -

-
-
return: function() {
-    this.expect('return');
-    var expr = this.expression();
-    return expr.isEmpty
-      ? new nodes.Return
-      : new nodes.Return(expr);
-  },
-
-

unless expression block -

-
-
unless: function() {
-    this.expect('unless');
-    var node = new nodes.If(this.expression(), true);
-    this.state.push('conditional');
-    node.block = this.block(node, false);
-    this.state.pop();
-    return node;
-  },
-
-

if expression block (else block)? -

-
-
if: function() {
-    this.expect('if');
-    var node = new nodes.If(this.expression());
-    this.state.push('conditional');
-    node.block = this.block(node, false);
-    while (this.accept('else')) {
-      if (this.accept('if')) {
-        var cond = this.expression()
-          , block = this.block(node, false);
-        node.elses.push(new nodes.If(cond, block));
-      } else {
-        node.elses.push(this.block(node, false));
-        break;
-      }
-    }
-    this.state.pop();
-    return node;
-  },
-
-

media -

-
-
media: function() {
-    var val = this.expect('media').val
-      , media = new nodes.Media(val);
-    this.state.push('media');
-    media.block = this.block(media);
-    this.state.pop();
-    return media;
-  },
-
-

import expression -

-
-
import: function() {
-    this.expect('import');
-    this.allowPostfix = true;
-    return new nodes.Import(this.expression());
-  },
-
-

charset string -

-
-
charset: function() {
-    this.expect('charset');
-    var str = this.expect('string').val;
-    this.allowPostfix = true;
-    return new nodes.Charset(str);
-  },
-
-

page selector? block -

-
-
page: function() {
-    var selector;
-    this.expect('page');
-    if (this.accept(':')) {
-      var str = this.expect('ident').val.name;
-      selector = new nodes.Literal(':' + str);
-    }
-    var page = new nodes.Page(selector);
-    this.state.push('page');
-    page.block = this.block(page);
-    this.state.pop();
-    return page;
-  },
-
-

keyframes name ((unit | from | to) block)+ -

-
-
keyframes: function() {
-    this.expect('keyframes');
-    var pos
-      , _ = this.css
-      , keyframes = new nodes.Keyframes(this.id());
-
-    // css-sty;e
-    if (this.css = this.accept('{')) {
-      this.skipWhitespace();
-    } else {
-      this.expect('indent');
-    }
-
-    while (pos = this.accept('unit') || this.accept('ident')) {
-      // from | to
-      if ('ident' == pos.type) {
-        this.accept('space');
-        switch (pos.val.name) {
-          case 'from':
-            pos = new nodes.Unit(0, '%');
-            break;
-          case 'to':
-            pos = new nodes.Unit(100, '%');
-            break;
-          default:
-            throw new Error('invalid ident "' + pos.val.name + '" in selector');
-        }
-      } else {
-        pos = pos.val;
-      }
-
-      // block
-      this.state.push('keyframe');
-      var block = this.block(keyframes);
-      keyframes.push(pos, block);
-      this.state.pop();
-      if (this.css) this.skipWhitespace();
-    }
-
-    // css-style
-    if (this.css) {
-      this.skipWhitespace();
-      this.expect('}');
-      this.css = _;
-    } else {
-      this.expect('outdent');
-    }
-
-    return keyframes;
-  },
-
-

literal -

-
-
literal: function() {
-    return this.expect('literal').val;
-  },
-
-

ident space? -

-
-
id: function() {
-    var tok = this.expect('ident');
-    this.accept('space');
-    return tok.val;
-  },
-
-

ident -| assignment -| property -| selector -

-
-
ident: function() {
-    var i = 2
-      , la = this.lookahead(i).type;
-
-    while ('space' == la) la = this.lookahead(++i).type;
-
-    switch (la) {
-      // Assignment
-      case '=':
-      case '?=':
-      case '-=':
-      case '+=':
-      case '*=':
-      case '/=':
-      case '%=':
-        return this.assignment();
-      // Operation
-      case '-':
-      case '+':
-      case '/':
-      case '*':
-      case '%':
-      case '**':
-      case 'and':
-      case 'or':
-      case '&&':
-      case '||':
-      case '>':
-      case '<':
-      case '>=':
-      case '<=':
-      case '!=':
-      case '==':
-      case '[':
-      case '?':
-      case 'in':
-      case 'is a':
-      case 'is defined':
-        // Prevent cyclic .ident, return literal
-        if (this._ident == this.peek()) {
-          return this.id();
-        } else {
-          this._ident = this.peek();
-          switch (this.currentState()) {
-            // unary op or selector in property / for
-            case 'for':
-            case 'selector':
-              return this.property();
-            // Part of a selector
-            case 'root':
-              return this.selector();
-            // Do not disrupt the ident when an operand
-            default:
-              return this.operand
-                ? this.id()
-                : this.expression();
-          }
-        }
-      // Selector or property
-      default:
-        switch (this.currentState()) {
-          case 'root':
-            return this.selector();
-          case 'for':
-          case 'page':
-          case 'media':
-          case 'selector':
-          case 'function':
-          case 'keyframe':
-          case 'conditional':
-            return this.property();
-          default:
-            return this.id();
-        }
-    }
-  },
-
-

(ident | '{' expression '}')+ -

-
-
interpolate: function() {
-    var node
-      , segs = [];
-    while (true) {
-      if (this.accept('{')) {
-        this.state.push('interpolation');
-        segs.push(this.expression());
-        this.expect('}');
-        this.state.pop();
-      } else if (node = this.accept('ident')){
-        segs.push(node.val);
-      } else {
-        break;
-      }
-    }
-    if (!segs.length) this.expect('ident');
-    return segs;
-  },
-
-

property ':'? expression -| ident -

-
-
property: function() {
-    if (this.looksLikeSelector()) return this.selector();
-
-    // property
-    var ident = this.interpolate()
-      , ret = prop = new nodes.Property(ident);
-
-    // optional ':'
-    this.accept('space');
-    if (this.accept(':')) this.accept('space');
-
-    this.state.push('property');
-    this.inProperty = true;
-    prop.expr = this.list();
-    if (prop.expr.isEmpty) ret = ident[0];
-    this.inProperty = false;
-    this.allowPostfix = true;
-    this.state.pop();
-
-    // optional ';'
-    this.accept(';');
-
-    return ret;
-  },
-
-

selector ',' selector -| selector newline selector -| selector block -

-
-
selector: function() {
-    var tok
-      , arr
-      , val
-      , prev
-      , parent
-      , group = new nodes.Group;
-
-    // Allow comments in selectors
-    // for hacks
-    this.lexer.allowComments = true;
-
-    do {
-      val = prev = null;
-      arr = [];
-
-      // Clobber newline after ,
-      this.accept('newline');
-
-      // Selector candidates,
-      // stitched together to
-      // form a selector.
-      while (tok = this.selectorToken()) {
-        // Selector component
-        switch (tok.type) {
-          case 'unit': val = tok.val.val; break;
-          case 'ident': val = tok.val.name; break;
-          case 'function': val = tok.val.name + '('; break;
-          case 'string': val = tok.val.toString(); break;
-          case 'color': val = tok.val.raw; break;
-          case 'space': val = ' '; break;
-          default: val = tok.val;
-        }
-
-        // Whitespace support
-        if (!prev || prev.space) {
-          arr.push(val);
-        } else {
-          arr[arr.length-1] += val;
-        }
-        prev = tok;
-      }
-
-      // Push the selector
-      group.push(new nodes.Selector(arr.join(' '), parent));
-    } while (this.accept(',') || this.accept('newline'));
-
-    this.lexer.allowComments = false;
-    this.state.push('selector');
-    group.block = this.block(group);
-    this.state.pop();
-
-
-    return group;
-  },
-
-

ident ('=' | '?=') expression -

-
-
assignment: function() {
-    var op
-      , node
-      , name = this.id().name;
-
-    if (op =
-         this.accept('=')
-      || this.accept('?=')
-      || this.accept('+=')
-      || this.accept('-=')
-      || this.accept('*=')
-      || this.accept('/=')
-      || this.accept('%=')) {
-      this.state.push('assignment');
-      var expr = this.list();
-      if (expr.isEmpty) this.error('invalid right-hand side operand in assignment, got {peek}')
-      node = new nodes.Ident(name, expr);
-      this.state.pop();
-
-      switch (op.type) {
-        case '?=':
-          var defined = new nodes.BinOp('is defined', node)
-            , lookup = new nodes.Ident(name);
-          node = new nodes.Ternary(defined, lookup, node);
-          break;
-        case '+=':
-        case '-=':
-        case '*=':
-        case '/=':
-        case '%=':
-          node.val = new nodes.BinOp(op.type[0], new nodes.Ident(name), expr);
-          break;
-      }
-    }
-
-    return node;
-  },
-
-

definition -| call -

-
-
function: function() {
-    var parens = 1
-      , i = 2
-      , tok;
-
-    // Lookahead and determine if we are dealing
-    // with a function call or definition. Here
-    // we pair parens to prevent false negatives
-    out:
-    while (tok = this.lookahead(i++)) {
-      switch (tok.type) {
-        case 'function': case '(': ++parens; break;
-        case ')': if (!--parens) break out;
-      }
-    }
-    
-    // Definition or call
-    switch (this.currentState()) {
-      case 'expression':
-        return this.functionCall();
-      default:
-        return this.looksLikeFunctionDefinition(i)
-          ? this.functionDefinition()
-          : this.expression();
-    }
-  },
-
-

url '(' (expression | urlchars)+ ')' -

-
-
url: function() {
-    this.expect('function');
-    this.state.push('function arguments');
-    var args = this.args();
-    this.expect(')');
-    this.state.pop();
-    return new nodes.Call('url', args);
-  },
-
-

ident '(' expression ')' -

-
-
functionCall: function() {
-    if ('url' == this.peek().val.name) return this.url();
-    var name = this.expect('function').val.name;
-    this.state.push('function arguments');
-    var args = this.args();
-    this.expect(')');
-    this.state.pop();
-    return new nodes.Call(name, args);
-  },
-
-

ident '(' params ')' block -

-
-
functionDefinition: function() {
-    var name = this.expect('function').val.name;
-
-    // params
-    this.state.push('function params');
-    this.skipWhitespace();
-    var params = this.params();
-    this.skipWhitespace();
-    this.expect(')');
-    this.state.pop();
-
-    // Body
-    this.state.push('function');
-    var fn = new nodes.Function(name, params);
-    fn.block = this.block(fn);
-    this.state.pop();
-    return new nodes.Ident(name, fn);
-  },
-
-

ident -| ident '...' -| ident '=' expression -| ident ',' ident -

-
-
params: function() {
-    var tok
-      , node
-      , params = new nodes.Params;
-    while (tok = this.accept('ident')) {
-      this.accept('space');
-      params.push(node = tok.val);
-      if (this.accept('...')) {
-        node.rest = true;
-      } else if (this.accept('=')) {
-        node.val = this.expression();
-      }
-      this.skipWhitespace();
-      this.accept(',');
-      this.skipWhitespace();
-    }
-    return params;
-  },
-
-

expression (',' expression)* -

-
-
args: function() {
-    var args = new nodes.Expression;
-    do {
-      args.push(this.expression());
-    } while (this.accept(','));
-    return args;
-  },
-
-

expression (',' expression)* -

-
-
list: function() {
-    var node = this.expression();
-    while (this.accept(',')) {
-      if (node.isList) {
-        list.push(this.expression());
-      } else {
-        var list = new nodes.Expression(true);
-        list.push(node);
-        list.push(this.expression());
-        node = list;
-      }
-    }
-    return node;
-  },
-
-

negation+ -

-
-
expression: function() {
-    var node
-      , expr = new nodes.Expression;
-    this.state.push('expression');
-    while (node = this.negation()) {
-      if (!node) this.error('unexpected token {peek} in expression');
-      expr.push(node);
-    }
-    this.state.pop();
-    return expr;
-  },
-
-

'not' ternary -| ternary -

-
-
negation: function() {
-    if (this.accept('not')) {
-      return new nodes.UnaryOp('!', this.negation());
-    }
-    return this.ternary();
-  },
-
-

logical ('?' expression ':' expression)? -

-
-
ternary: function() {
-    var node = this.logical();
-    if (this.accept('?')) {
-      var trueExpr = this.expression();
-      this.expect(':');
-      var falseExpr = this.expression();
-      node = new nodes.Ternary(node, trueExpr, falseExpr);
-    }
-    return node;
-  },
-
-

typecheck (('&&' | '||') typecheck)* -

-
-
logical: function() {
-    var op
-      , node = this.typecheck();
-    while (op = this.accept('&&') || this.accept('||')) {
-      node = new nodes.BinOp(op.type, node, this.typecheck());
-    }
-    return node;
-  },
-
-

equality ('is a' equality)* -

-
-
typecheck: function() {
-    var op
-      , node = this.equality();
-    while (op = this.accept('is a')) {
-      this.operand = true;
-      if (!node) throw new Error('illegal unary ' + op);
-      node = new nodes.BinOp(op.type, node, this.equality());
-      this.operand = false;
-    }
-    return node;
-  },
-
-

in (('==' | '!=') in)* -

-
-
equality: function() {
-    var op
-      , node = this.in();
-    while (op = this.accept('==') || this.accept('!=')) {
-      this.operand = true;
-      if (!node) throw new Error('illegal unary ' + op);
-      node = new nodes.BinOp(op.type, node, this.in());
-      this.operand = false;
-    }
-    return node;
-  },
-
-

relational ('in' relational)* -

-
-
in: function() {
-    var node = this.relational();
-    while (this.accept('in')) {
-      this.operand = true;
-      if (!node) throw new Error('illegal unary in');
-      node = new nodes.BinOp('in', node, this.relational());
-      this.operand = false;
-    }
-    return node;
-  },
-
-

range (('>=' | '<=' | '>' | '<') range)* -

-
-
relational: function() {
-    var op
-      , node = this.range();
-    while (op = 
-         this.accept('>=')
-      || this.accept('<=')
-      || this.accept('<')
-      || this.accept('>')
-      ) {
-      this.operand = true;
-      if (!node) throw new Error('illegal unary ' + op);
-      node = new nodes.BinOp(op.type, node, this.range());
-      this.operand = false;
-    }
-    return node;
-  },
-
-

additive (('..' | '...') additive)* -

-
-
range: function() {
-    var op
-      , node = this.additive();
-    if (op = this.accept('...') || this.accept('..')) {
-      this.operand = true;
-      if (!node) throw new Error('illegal unary ' + op);
-      node = new nodes.BinOp(op.val, node, this.additive());
-      this.operand = false;
-    }
-    return node;
-  },
-
-

multiplicative (('+' | '-') multiplicative)* -

-
-
additive: function() {
-    var op
-      , node = this.multiplicative();
-    while (op = this.accept('+') || this.accept('-')) {
-      this.operand = true;
-      node = new nodes.BinOp(op.type, node, this.multiplicative());
-      this.operand = false;
-    }
-    return node;
-  },
-
-

defined (('**' | '' | '/' | '%') defined) -

-
-
multiplicative: function() {
-    var op
-      , node = this.defined();
-    while (op =
-         this.accept('**')
-      || this.accept('*')
-      || this.accept('/')
-      || this.accept('%')) {
-      this.operand = true;
-      if ('/' == op &amp;&amp; this.inProperty &amp;&amp; !this.parens) {
-        var expr = new nodes.Expression;
-        expr.push(node);
-        expr.push(new nodes.Literal('/'));
-        return expr;
-      } else {
-        if (!node) throw new Error('illegal unary ' + op);
-        node = new nodes.BinOp(op.type, node, this.defined());
-        this.operand = false;
-      }
-    }
-    return node;
-  },
-
-

unary 'is defined' - | unary -

-
-
defined: function() {
-    var node = this.unary();
-    if (this.accept('is defined')) {
-      if (!node) throw new Error('illegal use of "is defined"');
-      node = new nodes.BinOp('is defined', node);
-    }
-    return node;
-  },
-
-

('!' | '~' | '+' | '-') unary -| subscript -

-
-
unary: function() {
-    var op
-      , node;
-    if (op =
-         this.accept('!')
-      || this.accept('~')
-      || this.accept('+')
-      || this.accept('-')) {
-      this.operand = true;
-      node = new nodes.UnaryOp(op.type, this.unary());
-      this.operand = false;
-      return node;
-    }
-    return this.subscript();
-  },
-
-

primary ('[' expression ']')+ -| primary -

-
-
subscript: function() {
-    var node = this.primary();
-    while (this.accept('[')) {
-      node = new nodes.BinOp('[]', node, this.expression());
-      this.expect(']');
-    }
-    return node;
-  },
-
-

unit -| null -| color -| string -| ident -| boolean -| literal -| '(' expression ')' -

-
-
primary: function() {
-    var op
-      , node;
-
-    // Parenthesis
-    if (this.accept('(')) {
-      this.parens = true;
-      var expr = this.expression();
-      this.expect(')');
-      this.parens = false;
-      return expr;
-    }
-
-    // Primitive
-    switch (this.peek().type) {
-      case 'null':
-      case 'unit':
-      case 'color':
-      case 'string':
-      case 'literal':
-      case 'boolean':
-        return this.next().val;
-      case 'ident':
-        return this.ident();
-      case 'function':
-        return this.functionCall();
-    }
-  }
-};
-
-

renderer

lib/renderer.js
-

Module dependencies. -

-
-
var Parser = require('./parser')
-  , Compiler = require('./visitor/compiler')
-  , Evaluator = require('./visitor/evaluator')
-  , utils = require('./utils')
-  , nodes = require('./nodes');
-
-

Initialize a new Renderer with the given str and options.

- -

- -
  • param: String str

  • param: Object options

  • api: public

-
-
var Renderer = module.exports = function Renderer(str, options) {
-  options = options || {};
-  options.functions = {};
-  options.imports = [__dirname + '/functions'];
-  options.filename = options.filename || 'stylus';
-  this.str = str;
-  this.options = options;
-  this.parser = new Parser(str, options);
-};
-
-

Parse and evaluate AST, then callback fn(err, css).

- -

- -
  • param: Function fn

  • api: public

-
-
Renderer.prototype.render = function(fn){
-  try {
-    var ast = this.parser.parse();
-    this.evaluator = new Evaluator(ast, this.options);
-    ast = this.evaluator.evaluate();
-    new Compiler(ast, this.options).compile(fn);
-  } catch (err) {
-    fn(utils.formatException(
-        this
-      , err
-      , this.options));
-  }
-  nodes.source = null;
-};
-
-

Set option key to val.

- -

- -
  • param: String key

  • param: Mixed val

  • return: Renderer for chaining

  • api: public

-
-
Renderer.prototype.set = function(key, val){
-  this.options[key] = val;
-  return this;
-};
-
-

Define function with the given name. Optionally -the function may accept full expressions, by setting raw -to true.

- -

- -
  • param: String name

  • param: Function fn

  • return: Renderer for chaining

  • api: public

-
-
Renderer.prototype.define = function(name, fn, raw){
-  this.options.functions[name] = fn;
-  if (undefined != raw) fn.raw = raw;
-  return this;
-};
-
-

Import the given file.

- -

- -
  • param: String file

  • return: Renderer for chaining

  • api: public

-
-
Renderer.prototype.import = function(file){
-  this.options.imports.push(file);
-  return this;
-};
-
-
-
-

index

lib/stack/index.js
-

Module dependencies. -

-
-
var Frame = require('./frame');
-
-

Initialize a new Stack.

- -
  • api: private

-
-
var Stack = module.exports = function Stack() {
-  Array.apply(this, arguments);
-};
-
-

Inherit from Array.prototype. -

-
-
Stack.prototype.__proto__ = Array.prototype;
-
-

Push the given frame.

- -

- -
  • param: Frame frame

  • api: public

-
-
Stack.prototype.push = function(frame){
-  frame.stack = this;
-  frame.parent = this.currentFrame;
-  return [].push.apply(this, arguments);
-};
-
-

Return the current stack Frame.

- -

- -
  • return: Frame

  • api: private

-
-
Stack.prototype.__defineGetter__('currentFrame', function(){
-  return this[this.length - 1];
-});
-
-

Lookup stack frame for the given block.

- -

- -
  • param: Block block

  • return: Frame

  • api: private

-
-
Stack.prototype.getBlockFrame = function(block){
-  for (var i = 0; i &lt; this.length; ++i) {
-    if (block == this[i].block) {
-      return this[i];
-    }
-  }
-};
-
-

Lookup the given local variable name, relative -to the lexical scope of the current frame's Block.

- -

When the result of a lookup is an identifier -a recursive lookup is performed, defaulting to -returning the identifier itself.

- -

- -
  • param: String name

  • return: Node

  • api: private

-
-
Stack.prototype.lookup = function(name){
-  var block = this.currentFrame.block
-    , val
-    , ret;
-
-  do {
-    var frame = this.getBlockFrame(block);
-    if (frame &amp;&amp; (val = frame.lookup(name))) {
-      switch (val.first.nodeName) {
-        case 'ident':
-          return this.lookup(val.first.name) || val;
-        default:
-          return val;
-      }
-    }
-  } while (block = block.parent);
-};
-
-

Custom inspect.

- -

- -
  • return: String

  • api: private

-
-
Stack.prototype.inspect = function(){
-  return this.reverse().map(function(frame){
-    return frame.inspect();
-  }).join('\n');
-};
-
-

Return stack string formatted as:

- -

at <context> (<filename>:<lineno>)

- -

- -
  • return: String

  • api: private

-
-
Stack.prototype.toString = function(){
-  var block
-    , node
-    , buf = []
-    , location
-    , len = this.length;
-
-  while (len--) {
-    block = this[len].block;
-    if (node = block.node) {
-      location = '(' + node.filename + ':' + node.lineno + ')';
-      switch (node.nodeName) {
-        case 'function':
-          buf.push('    at ' + node.name + '() ' + location);
-          break;
-        case 'group':
-          buf.push('    at "' + node.nodes[0].val + '" ' + location);
-          break;
-      }
-    }
-  }
-
-  return buf.join('\n');
-};
-

frame

lib/stack/frame.js
-

Module dependencies. -

-
-
var Scope = require('./scope')
-  , blocks = require('../nodes');
-
-

Initialize a new Frame with the given block.

- -

- -
  • param: Block block

  • api: private

-
-
var Frame = module.exports = function Frame(block) {
-  this._scope = false === block.scope
-    ? null
-    : new Scope;
-  this.block = block;
-};
-
-

Return this frame's scope or the parent scope -for scope-less blocks.

- -

- -
  • return: Scope

  • api: public

-
-
Frame.prototype.__defineGetter__('scope', function(){
-  return this._scope || this.parent.scope;
-});
-
-

Lookup the given local variable name.

- -

- -
  • param: String name

  • return: Node

  • api: private

-
-
Frame.prototype.lookup = function(name){
-  return this.scope.lookup(name)
-};
-
-

Custom inspect.

- -

- -
  • return: String

  • api: public

-
-
Frame.prototype.inspect = function(){
-  return '[Frame '
-    + (false === this.block.scope
-        ? 'scope-less'
-        : this.scope.inspect())
-    + ']';
-};
-
-

stylus

lib/stylus.js
-

Module dependencies. -

-
-
var Renderer = require('./renderer')
-  , nodes = require('./nodes')
-  , utils = require('./utils');
-
-

Export render as the module. -

-
-
exports = module.exports = render;
-
-

Library version. -

-
-
exports.version = '0.8.0';
-
-

Expose nodes. -

-
-
exports.nodes = nodes;
-
-

Expose BIFs. -

-
-
exports.functions = require('./functions');
-
-

Expose utils. -

-
-
exports.utils = require('./utils');
-
-

Expose middleware. -

-
-
exports.middleware = require('./middleware');
-
-

Convert the given css to stylus source.

- -

- -
  • param: String css

  • return: String

  • api: public

-
-
exports.convertCSS = require('./convert/css');
-
-

Parse the given str with options and return the AST.

- -

Examples

- -
css.parse(str);
-// raw ast comprised of nodes
-
-css.parse(str).toObject();
-// plain object representation
-
-css.parse(str).toJSON();
-// JSON representation
- -

- -
  • param: String str

  • param: Object options

  • return: Object

  • api: public

-
-
exports.parse = function(str, options){
-  var renderer = new Renderer(str, options);
-  try {
-    return renderer.parser.parse();
-  } catch (err) {
-    throw utils.formatException(
-        renderer
-      , err
-      , options);
-  }
-};
-
-

Render the given str with options and callback fn(err, css).

- -

- -
  • param: String str

  • param: Object | Function options

  • param: Function fn

  • api: public

-
-
exports.render = function(str, options, fn){
-  if ('function' == typeof options) fn = options, options = {};
-  new Renderer(str, options).render(fn);
-};
-
-

Return a new Renderer for the given str and options.

- -

- -
  • param: String str

  • param: Object options

  • return: Renderer

  • api: public

-
-
function render(str, options) {
-  return new Renderer(str, options);
-}
-
-

Expose optional functions. -

-
-
exports.url = require('./functions/url');
-
-

scope

lib/stack/scope.js
-

Initialize a new Scope.

- -
  • api: private

-
-
var Scope = module.exports = function Scope() {
-  this.locals = {};
-};
-
-

Add ident node to the current scope.

- -

- -
  • param: Ident ident

  • api: private

-
-
Scope.prototype.add = function(ident){
-  this.locals[ident.name] = ident.val;
-};
-
-

Lookup the given local variable name.

- -

- -
  • param: String name

  • return: Node

  • api: private

-
-
Scope.prototype.lookup = function(name){
-  return this.locals[name];
-};
-
-

Custom inspect.

- -

- -
  • return: String

  • api: public

-
-
Scope.prototype.inspect = function(){
-  var keys = Object.keys(this.locals).map(function(key){ return '@' + key; });
-  return '[Scope'
-    + (keys.length ? ' ' + keys.join(', ') : '')
-    + ']';
-};
-
-

compiler

lib/visitor/compiler.js
-

Module dependencies. -

-
-
var Visitor = require('./')
-  , nodes = require('../nodes');
-
-

Initialize a new Compiler with the given root Node -and the following options.

- -

Options

- -
  • compress Compress the css output, defaults to false
- -

- -
  • param: Node root

  • api: public

-
-
var Compiler = module.exports = function Compiler(root, options) {
-  options = options || {};
-  this.compress = options.compress;
-  this.indents = 1;
-  Visitor.call(this, root);
-  this.tree = [];
-};
-
-

Inherit from Visitor.prototype. -

-
-
Compiler.prototype.__proto__ = Visitor.prototype;
-
-

Compile to css, and callback fn(err, css).

- -

- -
  • param: Function fn

  • api: public

-
-
Compiler.prototype.compile = function(fn){
-  this.callback = fn;
-  this.css = this.visit(this.root);
-  fn(null, this.css);
-};
-
-

Return indentation string.

- -

- -
  • return: String

  • api: private

-
-
Compiler.prototype.__defineGetter__('indent', function(){
-  return this.compress
-     ? ''
-     : new Array(this.indents).join('  ');
-});
-
-

Visit Root. -

-
-
Compiler.prototype.visitRoot = function(block){
-  this.buf = '';
-  for (var i = 0, len = block.nodes.length; i &lt; len; ++i) {
-    var node = block.nodes[i];
-    if (node instanceof nodes.Null
-      || node instanceof nodes.Expression
-      || node instanceof nodes.Function
-      || node instanceof nodes.Unit) continue;
-    var ret = this.visit(node);
-    if (ret) this.buf += ret + '\n';
-  }
-  return this.buf;
-};
-
-

Visit Block. -

-
-
Compiler.prototype.visitBlock = function(block){
-  if (block.hasProperties) {
-    var arr = [this.compress ? '{' : ' {'];
-    ++this.indents;
-    for (var i = 0, len = block.nodes.length; i &lt; len; ++i) {
-      this.last = len - 1 == i;
-      var node = block.nodes[i];
-      if (node instanceof nodes.Null
-        || node instanceof nodes.Expression
-        || node instanceof nodes.Function
-        || node instanceof nodes.Group
-        || node instanceof nodes.Unit) continue;
-      arr.push(this.visit(node));
-    }
-    --this.indents;
-    arr.push(this.indent + '}');
-    this.buf += arr.join(this.compress ? '' : '\n');
-    this.buf += '\n';
-  }
-
-  // Nesting
-  for (var i = 0, len = block.nodes.length; i &lt; len; ++i) {
-    this.visit(block.nodes[i]);
-  }
-};
-
-

Visit Keyframes. -

-
-
Compiler.prototype.visitKeyframes = function(node){
-  this.buf += '@-webkit-keyframes '
-    + this.visit(node.name)
-    + (this.compress ? '{' : ' {');
-  ++this.indents;
-  node.frames.forEach(function(frame){
-    if (!this.compress) this.buf += '\n  ';
-    this.buf += this.visit(frame.pos);
-    this.visit(frame.block);
-  }, this);
-  --this.indents;
-  this.buf += '}' + (this.compress ? '' : '\n');
-};
-
-

Visit Media. -

-
-
Compiler.prototype.visitMedia = function(media){
-  this.buf += '@media ' + media.val;
-  this.buf += this.compress ? '{' : ' {\n';
-  ++this.indents;
-  this.visit(media.block);
-  --this.indents;
-  this.buf += '}' + (this.compress ? '' : '\n');
-};
-
-

Visit Page. -

-
-
Compiler.prototype.visitPage = function(page){
-  this.buf += this.indent + '@page';
-  this.buf += page.selector ? ' ' + page.selector : '';
-  this.visit(page.block);
-};
-
-

Visit Function. -

-
-
Compiler.prototype.visitFunction = function(fn){
-  return fn.name;
-};
-
-

Visit Variable. -

-
-
Compiler.prototype.visitVariable = function(variable){
-  return '';
-};
-
-

Visit Charset. -

-
-
Compiler.prototype.visitCharset = function(charset){
-  return '@charset ' + this.visit(charset.val);
-};
-
-

Visit Literal. -

-
-
Compiler.prototype.visitLiteral = function(lit){
-  return lit.val.trim().replace(/^  /gm, '');
-};
-
-

Visit Boolean. -

-
-
Compiler.prototype.visitBoolean = function(bool){
-  return bool.toString();
-};
-
-

Visit RGBA. -

-
-
Compiler.prototype.visitRGBA = function(rgba){
-  return rgba.toString();
-};
-
-

Visit HSLA. -

-
-
Compiler.prototype.visitHSLA = function(hsla){
-  return hsla.rgba.toString();
-};
-
-

Visit Unit. -

-
-
Compiler.prototype.visitUnit = function(unit){
-  var type = unit.type || ''
-    , n = unit.val
-    , float = n != (n | 0);
-
-  // Int
-  if ('px' == type) n = n.toFixed(0);
-  // Compress
-  if (this.compress) {
-    // Zero is always '0'
-    if (0 == unit.val) return '0';
-    // Omit leading '0' on floats
-    if (float &amp;&amp; n &lt; 1) {
-      return n.toString().substr(1) + type;
-    }
-  }
-
-  return n.toString() + type;
-};
-
-

Visit Group. -

-
-
Compiler.prototype.visitGroup = function(group){
-  var self = this
-    , tree = this.tree
-    , prev = tree[tree.length - 1]
-    , curr = [];
-
-  // Construct an array of arrays
-  // representing the selector hierarchy
-  group.nodes.forEach(function(node){
-    curr.push(node.parent
-        ? node
-        : node.val);
-  });
-
-  tree.push(curr);
-
-  // Reverse recurse the
-  // hierarchy array to build
-  // up the selector permutations.
-  // When we reach root, we have our
-  // selector string built
-  var selectors = []
-    , buf = [];
-  function join(arr, i) {
-    if (i) {
-      arr[i].forEach(function(str){
-        buf.unshift(str);
-        join(arr, i - 1);
-        buf.shift();
-      });
-    } else {
-      arr[0].forEach(function(selector){
-        var str = selector;
-        if (buf.length) {
-          for (var i = 0, len = buf.length; i &lt; len; ++i) {
-            if (~buf[i].indexOf('&')) {
-              str = buf[i].replace('&', str);
-            } else {
-              str += ' ' + buf[i];
-            }
-          }
-        }
-        selectors.push(self.indent + str);
-      });
-    }
-  }
-
-  // Join selectors
-  if (group.block.hasProperties) {
-    join(tree, tree.length - 1);
-    this.buf += selectors.join(this.compress ? ',' : ',\n');
-  }
-
-  // Output blocks
-  this.visit(group.block);
-  tree.pop();
-};
-
-

Visit Ident. -

-
-
Compiler.prototype.visitIdent = function(ident){
-  return ident.name;
-};
-
-

Visit String. -

-
-
Compiler.prototype.visitString = function(string){
-  return this.isURL
-    ? string.val
-    : string.toString();
-};
-
-

Visit Null. -

-
-
Compiler.prototype.visitNull = function(node){
-  return '';
-};
-
-

Visit Call. -

-
-
Compiler.prototype.visitCall = function(call){
-  this.isURL = 'url' == call.name;
-  var args = call.args.nodes.map(function(arg){
-    return this.visit(arg);
-  }, this).join(this.compress ? ',' : ', ');
-  if (this.isURL) args = '"' + args + '"';
-  delete this.isURL;
-  return call.name + '(' + args + ')';
-};
-
-

Visit Import. -

-
-
Compiler.prototype.visitImport = function(import){
-  return '@import ' + this.visit(import.path) + ';';
-};
-
-

Visit Expression. -

-
-
Compiler.prototype.visitExpression = function(expr){
-  return expr.nodes.map(function(node){
-    return this.visit(node);
-  }, this).join(expr.isList
-      ? (this.compress ? ',' : ', ')
-      : (this.isURL ? '' : ' '));
-};
-
-

Visit Property. -

-
-
Compiler.prototype.visitProperty = function(prop){
-  var self = this
-    , val = this.visit(prop.expr);
-  return this.indent + (prop.name || prop.segments.join(''))
-    + (this.compress ? ':' + val : ': ' + val)
-    + (this.compress
-        ? (this.last ? '' : ';')
-        : ';');
-};
-
-

utils

lib/utils.js
-

Module dependencies. -

-
-
var nodes = require('./nodes')
-  , inspect = require('sys').inspect
-  , fs = require('fs');
-
-

Attempt to lookup path within paths from tail to head. -Optionally a path to ignore may be passed.

- -

- -
  • param: String path

  • param: String paths

  • param: String ignore

  • return: String

  • api: private

-
-
exports.lookup = function(path, paths, ignore){
-  var lookup
-    , i = paths.length;
-
-  // Absolute
-  if ('/' == path[0]) {
-    try {
-      fs.statSync(path);
-      return path;
-    } catch (err) {
-      // Ignore, continue on
-      // to trying relative lookup.
-      // Needed for url(/images/foo.png)
-      // for example
-    }
-  }
-
-  // Relative
-  while (i--) {
-    try {
-      lookup = paths[i] + '/' + path;
-      if (ignore == lookup) continue;
-      fs.statSync(lookup);
-      return lookup;
-    } catch (err) {
-      // Ignore
-    }
-  }
-};
-
-

Format the given err in context to renderer.

- -

- -
  • param: Renderer renderer

  • param: Error err

  • param: Object options

  • return: Error

  • api: private

-
-
exports.formatException = function(renderer, err, options){
-  var lineno = renderer.evaluator
-      ? renderer.evaluator.lineno
-      : renderer.parser.lexer.lineno
-    , contextLineno = lineno - 2
-    , contextLines = options.context || 8
-    , lastWidth = (contextLineno + contextLines).toString().length;
-
-  var src = (err.str || renderer.str).split('\n')
-    .slice(contextLineno, contextLineno + contextLines)
-    .map(function(line){
-      var n = ++contextLineno
-        , width = n.toString().length
-        , pad = Array(lastWidth - width + 1).join(' ');
-      return '  ' + pad + n + ': ' + inspect(line);
-    }).join('\n');
-
-  err.message = renderer.options.filename
-    + ':' + lineno
-    + '\n' + src
-    + '\n\n' + err.message + '\n'
-    + (err.stylusStack ? err.stylusStack + '\n' : '');
-
-  return err;
-};
-
-

Assert that node is of the given type, or throw.

- -

- -
  • param: Node node

  • param: Function type

  • param: String param

  • api: public

-
-
exports.assertType = function(node, type, param){
-  exports.assertPresent(node, param);
-  if (node instanceof type) return;
-  var actual = node.constructor.name
-    , msg = 'expected ' + type.name + ', but got ' + actual + ':' + node;
-  throw new Error('TypeError: ' + msg);
-};
-
-

Assert that node is a String or Ident.

- -

- -
  • param: Node node

  • param: String param

  • api: public

-
-
exports.assertString = function(node, param){
-  exports.assertPresent(node, param);
-  if (node instanceof nodes.String) return;
-  if (node instanceof nodes.Ident) return;
-  var actual = node.constructor.name
-    , msg = 'expected String or Ident, but got ' + actual + ':' + node;
-  throw new Error('TypeError: ' + msg);
-};
-
-

Assert that node is a RGBA or HSLA.

- -

- -
  • param: Node node

  • param: String param

  • api: public

-
-
exports.assertColor = function(node, param){
-  exports.assertPresent(node, param);
-  if (node instanceof nodes.RGBA) return;
-  if (node instanceof nodes.HSLA) return;
-  var actual = node.constructor.name
-    , msg = 'expected RGBA or HSLA, but got ' + actual + ':' + node;
-  throw new Error('TypeError: ' + msg);
-};
-
-

Assert that param name is given, aka the node is passed.

- -

- -
  • param: Node node

  • param: String name

  • api: public

-
-
exports.assertPresent = function(node, name){
-  if (node) return;
-  if (name) throw new Error('ArgumentError: argument ' + name + ' required');
-  throw new Error('ArgumentError: argument missing');
-};
-
-

Unwrap expr.

- -

Takes an expressions with length of 1 -such as (1 2 3) and unwraps it to 1 2 3.

- -

- -
  • param: Expression expr

  • return: Node

  • api: public

-
-
exports.unwrap = function(expr){
-  if ('expression' != expr.nodeName) return expr;
-  if (1 != expr.nodes.length) return expr;
-  if ('expression' != expr.nodes[0].nodeName) return expr;
-  return expr.nodes[0];
-};
-

token

lib/token.js
-

Module dependencies. -

-
-
var inspect = require('sys').inspect;
-
-

Initialize a new Token with the given type and val.

- -

- -
  • param: String type

  • param: Mixed val

  • api: private

-
-
var Token = exports = module.exports = function Token(type, val) {
-  this.type = type;
-  this.val = val;
-};
-
-

Custom inspect.

- -

- -
  • return: String

  • api: public

-
-
Token.prototype.inspect = function(){
-  var val = ' ' + inspect(this.val);
-  return '[Token:' + this.lineno + ' '
-    + '\x1b[32m' + this.type + '\x1b[0m'
-    + '\x1b[33m' + (this.val ? val : '') + '\x1b[0m'
-    + ']';
-};
-
-

Return type or val.

- -

- -
  • return: String

  • api: public

-
-
Token.prototype.toString = function(){
-  return (undefined === this.val
-    ? this.type
-    : this.val).toString();
-};
-
-

index

lib/visitor/index.js
-

Initialize a new Visitor with the given root Node.

- -

- -
  • param: Node root

  • api: private

-
-
var Visitor = module.exports = function Visitor(root) {
-  this.root = root;
-};
-
-

Visit the given node.

- -

- -
  • param: Node | Array node

  • api: public

-
-
Visitor.prototype.visit = function(node, fn){
-  var method = 'visit' + node.constructor.name
-    , cons = this.constructor.name;
-  if (this[method]) return this[method](node);
-  return node;
-};
-
-
-

evaluator

lib/visitor/evaluator.js
-

Module dependencies. -

-
-
var Visitor = require('./')
-  , nodes = require('../nodes')
-  , Stack = require('../stack')
-  , Frame = require('../stack/frame')
-  , Scope = require('../stack/scope')
-  , utils = require('../utils')
-  , bifs = require('../functions')
-  , dirname = require('path').dirname
-  , colors = require('../colors')
-  , fs = require('fs');
-
-

Initialize a new Evaluator with the given root Node -and the following options.

- -

Options

- -
  • compress Compress the css output, defaults to false
  • warn Warn the user of duplicate function definitions etc
- -

- -
  • param: Node root

  • api: private

-
-
var Evaluator = module.exports = function Evaluator(root, options) {
-  options = options || {};
-  Visitor.call(this, root);
-  this.stack = new Stack;
-  this.imports = options.imports || [];
-  this.functions = options.functions || {};
-  this.paths = options.paths || [];
-  this.filename = options.filename;
-  this.paths.push(dirname(options.filename || '.'));
-  this.stack.push(this.global = new Frame(root));
-  this.warnings = options.warn;
-  this.options = options;
-  this.setup();
-  this.calling = []; // TODO: remove, use stack
-};
-
-

Inherit from Visitor.prototype. -

-
-
Evaluator.prototype.__proto__ = Visitor.prototype;
-
-

Proxy visit to expose node line numbers.

- -

- -
  • param: Node node

  • return: Node

  • api: private

-
-
var visit = Visitor.prototype.visit;
-Evaluator.prototype.visit = function(node){
-  try {
-    return visit.call(this, node);
-  } catch (err) {
-    // TODO: less-lame hack to reference
-    // the origin node source input
-    this.lineno = this.lineno || node.lineno;
-    err.str = err.str || node.source;
-    err.stylusStack = err.stylusStack || this.stack.toString();
-    throw err;
-  }
-};
-
-

Perform evaluation setup:

- -
  • populate global scope
  • iterate imports

    • api: private

-
-
Evaluator.prototype.setup = function(){
-  this.populateGlobalScope();
-  this.imports.forEach(function(file){
-    var expr = new nodes.Expression;
-    expr.push(new nodes.String(file));
-    this.visit(new nodes.Import(expr));
-  }, this);
-};
-
-

Populate the global scope with:

- -
  • css colors

    • api: private

-
-
Evaluator.prototype.populateGlobalScope = function(){
-  var scope = this.global.scope;
-  Object.keys(colors).forEach(function(name){
-    var rgb = colors[name]
-      , rgba = new nodes.RGBA(rgb[0], rgb[1], rgb[2], 1)
-      , node = new nodes.Ident(name, rgba);
-    scope.add(node);
-  });
-};
-
-

Evaluate the tree.

- -

- -
  • return: Node

  • api: private

-
-
Evaluator.prototype.evaluate = function(){
-  return this.visit(this.root);
-};
-
-

Visit Group. -

-
-
Evaluator.prototype.visitGroup = function(group){
-  group.block = this.visit(group.block);
-  return group;
-};
-
-

Visit Charset. -

-
-
Evaluator.prototype.visitCharset = function(charset){
-  return charset;
-};
-
-

Visit Return. -

-
-
Evaluator.prototype.visitReturn = function(ret){
-  ret.expr = this.visit(ret.expr);
-  throw ret;
-};
-
-

Visit Media. -

-
-
Evaluator.prototype.visitMedia = function(media){
-  media.block = this.visit(media.block);
-  return media;
-};
-
-

Visit Keyframes. -

-
-
Evaluator.prototype.visitKeyframes = function(keyframes){
-  keyframes.name = this.visit(keyframes.name).first.name;
-  return keyframes;
-};
-
-

Visit Function. -

-
-
Evaluator.prototype.visitFunction = function(fn){
-  // check local
-  var local = this.stack.currentFrame.scope.lookup(fn.name);
-  if (local) this.warn('local ' + local.nodeName + ' "' + fn.name + '" previously defined in this scope');
-
-  // user-defined
-  var user = this.functions[fn.name];
-  if (user) this.warn('user-defined function "' + fn.name + '" is already defined');
-
-  // BIF
-  var bif = bifs[fn.name];
-  if (bif) this.warn('built-in function "' + fn.name + '" is already defined');
-
-  return fn;
-};
-
-

Visit Each. -

-
-
Evaluator.prototype.visitEach = function(each){
-  var expr = utils.unwrap(this.visit(utils.unwrap(each.expr)))
-    , len = expr.nodes.length
-    , val = new nodes.Ident(each.val)
-    , key = new nodes.Ident(each.key || '__index__')
-    , scope = this.currentScope
-    , block = this.currentBlock
-    , vals = []
-    , body;
-
-  each.block.scope = false;
-  for (var i = 0; i &lt; len; ++i) {
-    val.val = expr.nodes[i];
-    key.val = new nodes.Unit(i);
-    scope.add(val);
-    scope.add(key);
-    body = this.visit(each.block.clone());
-    vals = vals.concat(body.nodes);
-  }
-
-  this.mixin(vals, block);
-  return vals[vals.length - 1];
-};
-
-

Visit Call. -

-
-
Evaluator.prototype.visitCall = function(call){
-  var fn = this.lookup(call.name)
-    , ret;
-
-  // Variable function
-  if (fn &amp;&amp; 'expression' == fn.nodeName) {
-    fn = fn.nodes[0];
-  }
-
-  // Not a function? try user-defined or built-ins
-  if (fn &amp;&amp; 'function' != fn.nodeName) {
-    fn = this.lookupFunction(call.name);
-  }
-
-  // Undefined function, render literal css
-  if (!fn || fn.nodeName != 'function') return this.literalCall(call);
-  this.calling.push(call.name);
-
-  // Massive stack
-  if (this.calling.length &gt; 200) {
-    throw new RangeError('Maximum call stack size exceeded');
-  }
-
-  // First node in expression
-  if (fn instanceof nodes.Expression) fn = fn.first;
-
-  // Evaluate arguments
-  var _ = this.return;
-  this.return = true;
-  var args = this.visit(call.args);
-  this.return = _;
-
-  // Built-in
-  if (fn.fn) {
-    ret = this.invokeBuiltin(fn.fn, args);
-  // User-defined
-  } else if (fn instanceof nodes.Function) {
-    ret = this.invokeFunction(fn, args);
-  }
-
-  this.calling.pop();
-  return ret;
-};
-
-

Visit Ident. -

-
-
Evaluator.prototype.visitIdent = function(ident){
-  // Lookup
-  if (nodes.null == ident.val) {
-    var val = this.lookup(ident.name);
-    return val ? this.visit(val) : ident;
-  // Assign  
-  } else {
-    var _ = this.return;
-    this.return = true;
-    ident.val = this.visit(ident.val);
-    this.return = _;
-    this.currentScope.add(ident);
-    return ident.val;
-  }
-};
-
-

Visit BinOp. -

-
-
Evaluator.prototype.visitBinOp = function(binop){
-  // Special-case "is defined" pseudo binop
-  if ('is defined' == binop.op) return this.isDefined(binop.left);
-
-  var _ = this.return;
-  this.return = true;
-  // Visit operands
-  var op = binop.op
-    , ident = 'ident' == binop.left.nodeName
-    , left = this.visit(binop.left)
-    , right = this.visit(binop.right);
-  this.return = _;
-
-  // First node in expression
-  if (!~['[]', 'in'].indexOf(op)) {
-    left = left.first;
-    right = right.first;
-  }
-
-  // Coercion
-  switch (op) {
-    case '[]':
-    case 'in':
-    case '||':
-    case '&&':
-    case 'is a':
-      break;
-    default:
-      // Special-case '-' against ident
-      if ('-' == op
-        &amp;&amp; 'ident' == left.nodeName
-        &amp;&amp; 'unit' == right.nodeName) {
-        var expr = new nodes.Expression;
-        right.val = -right.val;
-        expr.push(left);
-        expr.push(right);
-        return expr;
-      }
-
-      // Attempt coercion
-      try {
-        right = left.coerce(right);
-      } catch (err) {
-        // Disgregard coercion issues
-        // and simply return false
-        if ('==' == op || '!=' == op) {
-          return nodes.false;
-        } else {
-          throw err;
-        }
-      }
-  }
-
-  // Operate
-  return this.visit(left.operate(op, right));
-};
-
-

Visit UnaryOp. -

-
-
Evaluator.prototype.visitUnaryOp = function(unary){
-  var op = unary.op
-    , node = this.visit(unary.expr).first;
-
-  if ('!' != op) utils.assertType(node, nodes.Unit);
-
-  switch (op) {
-    case '-':
-      node.val = -node.val;
-      break;
-    case '+':
-      node.val = +node.val;
-      break;
-    case '~':
-      node.val = ~node.val;
-      break;
-    case '!':
-      return node.toBoolean().negate();
-  }
-  
-  return node;
-};
-
-

Visit TernaryOp. -

-
-
Evaluator.prototype.visitTernary = function(ternary){
-  var ok = this.visit(ternary.cond).toBoolean();
-  return nodes.true == ok
-    ? this.visit(ternary.trueExpr)
-    : this.visit(ternary.falseExpr);
-};
-
-

Visit Expression. -

-
-
Evaluator.prototype.visitExpression = function(expr){
-  for (var i = 0, len = expr.nodes.length; i &lt; len; ++i) {
-    expr.nodes[i] = this.visit(expr.nodes[i]);
-  }
-  return expr;
-};
-
-

Visit Property. -

-
-
Evaluator.prototype.visitProperty = function(prop){
-  var name = this.interpolate(prop)
-    , fn = this.lookup(name)
-    , call = fn instanceof nodes.Function
-    , literal = ~this.calling.indexOf(name);
-
-  // Function of the same name
-  if (call &amp;&amp; !literal &amp;&amp; !prop.literal) {
-    this.calling.push(name);
-    var ret = this.visit(new nodes.Call(name, prop.expr));
-    this.calling.pop();
-    return ret;
-  // Regular property
-  } else {
-    var _ = this.return;
-    this.return = true;
-    prop.expr = this.visit(prop.expr);
-    prop.name = name;
-    prop.literal = true;
-    this.return = _;
-    return prop;
-  }
-};
-
-

Visit Root. -

-
-
Evaluator.prototype.visitRoot = function(block){
-  for (var i = 0; i &lt; block.nodes.length; ++i) {
-    block.index = this.rootIndex = i;
-    block.nodes[i] = this.visit(block.nodes[i]);
-  }
-  return block;
-};
-
-

Visit Block. -

-
-
Evaluator.prototype.visitBlock = function(block){
-  this.stack.push(new Frame(block));
-  for (var i = 0; i &lt; block.nodes.length; ++i) {
-    block.index = i;
-    try {
-      block.nodes[i] = this.visit(block.nodes[i]);
-    } catch (err) {
-      if (err instanceof nodes.Return) {
-        if (this.return) {
-          this.stack.pop();
-          throw err;
-        } else {
-          block.nodes[i] = err;
-          break;
-        }
-      } else {
-        throw err;
-      }
-    }
-  }
-  this.stack.pop();
-  return block;
-};
-
-

Visit If. -

-
-
Evaluator.prototype.visitIf = function(node){
-  var ret
-    , _ = this.return
-    , block = this.currentBlock
-    , negate = node.negate;
-
-  this.return = true;
-  var ok = this.visit(node.cond).first.toBoolean();
-  this.return = _;
-
-  // Evaluate body
-  if (negate) {
-    // unless
-    if (nodes.false == ok) {
-      ret = this.visit(node.block);
-    }
-  } else {
-    // if
-    if (nodes.true == ok) {
-      ret = this.visit(node.block);
-    // else
-    } else if (node.elses.length) {
-      var elses = node.elses
-        , len = elses.length;
-      for (var i = 0; i &lt; len; ++i) {
-        // else if
-        if (elses[i].cond) {
-          if (nodes.true == this.visit(elses[i].cond).first.toBoolean()) {
-            ret = this.visit(elses[i].block);
-            break;
-          }
-        // else 
-        } else {
-          ret = this.visit(elses[i]);
-        }
-      }
-    }
-  }
-
-  // mixin conditional statements within a selector group
-  if (ret &amp;&amp; !node.postfix &amp;&amp; block.node &amp;&amp; 'group' == block.node.nodeName) {
-    this.mixin(ret.nodes, block);
-    return nodes.null;
-  }
-
-  return ret || nodes.null;
-};
-
-

Visit Import. -

-
-
Evaluator.prototype.visitImport = function(import){
-  var found
-    , root = this.root
-    , i = this.rootIndex
-    , stylus = require('../stylus')
-    , path = this.visit(import.path).first
-    , relative = this.importPath;
-
-  // Enusre string
-  if (!path.string) throw new Error('@import string expected');
-  var name = path = path.string;
-
-  // Literal
-  if (/\.css$/.test(path)) return import;
-  path += '.styl';
-
-  // Lookup
-  if (relative) this.paths.push(relative);
-  found = utils.lookup(path, this.paths, this.filename);
-  found = found || utils.lookup(name + '/index.styl', this.paths, this.filename);
-  if (relative) this.paths.pop();
-
-  // Expose imports
-  import.path = found;
-  if (this.options._imports) this.options._imports.push(import);
-
-  // Throw if import failed
-  if (!found) throw new Error('failed to locate @import file ' + path);
-  this.importPath = dirname(found);
-
-  // Parse the file
-  var str = fs.readFileSync(found, 'utf8')
-    , rest = root.nodes.splice(++i, root.nodes.length);
-
-  stylus.parse(str, {
-      filename: found
-    , root: root
-  });
-
-  rest.forEach(function(node){
-    root.push(node);
-  });
-
-  return nodes.null;
-};
-
-

Invoke fn with args.

- -

- -
  • param: Function fn

  • param: Array args

  • return: Node

  • api: private

-
-
Evaluator.prototype.invokeFunction = function(fn, args){
-  var block = new nodes.Block(fn.block.parent);
-  fn.block.parent = block;
-
-  // Clone the function body
-  // to prevent mutation of subsequent calls
-  // inject argument scope
-  var body = fn.block.clone();
-
-  // mixin block
-  var mixinBlock = this.stack.currentFrame.block;
-
-
-  // new block scope
-  this.stack.push(new Frame(block));
-  var scope = this.currentScope;
-
-  // arguments local
-  scope.add(new nodes.Ident('arguments', args));
-
-  // mixin scope introspection
-  scope.add(new nodes.Ident('mixin', this.return
-    ? nodes.false
-    : new nodes.String(mixinBlock.nodeName)));
-
-  // inject arguments as locals
-  fn.params.nodes.forEach(function(node, i){
-    // rest param support
-    if (node.rest) {
-      node.val = new nodes.Expression;
-      for (var len = args.nodes.length; i &lt; len; ++i) {
-        node.val.push(args.nodes[i]);
-      }
-    // argument default support
-    } else {
-      var arg = args.nodes[i];
-      var val = arg &amp;&amp; !arg.isEmpty
-        ? args.nodes[i]
-        : node.val;
-      node = node.clone();
-      node.val = val;
-      // required argument not satisfied
-      if (node.val instanceof nodes.Null) {
-        throw new Error('argument ' + node + ' required for ' + fn);
-      }
-    }
-
-    scope.add(node);
-  });
-
-  // invoke
-  return this.invoke(body, true);
-};
-
-

Invoke built-in fn with args.

- -

- -
  • param: Function fn

  • param: Array args

  • return: Node

  • api: private

-
-
Evaluator.prototype.invokeBuiltin = function(fn, args){
-  // Map arguments to first node
-  // providing a nicer js api for
-  // BIFs. Functions may specify that
-  // they wish to accept full expressions
-  // via .raw
-  if (fn.raw) {
-    args = args.nodes;
-  } else {
-    args = args.nodes.map(function(node){
-      return node.first;
-    });
-  }
-
-  // Invoke the BIF
-  var body = fn.apply(this, args);
-
-  // Always wrapping allows js functions
-  // to return several values with a single
-  // Expression node
-  var expr = new nodes.Expression;
-  expr.push(body);
-  body = expr;
-
-  // Invoke
-  return this.invoke(body);
-};
-
-

Invoke the given function body.

- -

- -
  • param: Block body

  • return: Node

  • api: private

-
-
Evaluator.prototype.invoke = function(body, stack){
-  var self = this
-    , ret;
-
-  // Return
-  if (this.return) {
-    ret = this.eval(body.nodes);
-    if (stack) this.stack.pop();
-  // Mixin
-  } else {
-    body = this.visit(body);
-    if (stack) this.stack.pop();
-    this.mixin(body.nodes, this.currentBlock);
-    ret = nodes.null;
-  }
-
-  return ret;
-};
-
-

Mixin the given nodes to the given block.

- -

- -
  • param: Array nodes

  • param: Block block

  • api: private

-
-
Evaluator.prototype.mixin = function(nodes, block){
-  var len = block.nodes.length
-    , head = block.nodes.slice(0, block.index)
-    , tail = block.nodes.slice(block.index + 1, len);
-  this._mixin(nodes, head);
-  block.nodes = head.concat(tail);
-};
-
-

Mixin the given nodes to the dest array.

- -

- -
  • param: Array nodes

  • param: Array dest

  • api: private

-
-
Evaluator.prototype._mixin = function(nodes, dest){
-  var node
-    , len = nodes.length;
-  for (var i = 0; i &lt; len; ++i) {
-    switch ((node = nodes[i]).nodeName) {
-      case 'return':
-        return;
-      case 'block':
-        this._mixin(node.nodes, dest);
-        break;
-      default:
-        dest.push(node);
-    }
-  }
-};
-
-

Evaluate the given vals.

- -

- -
  • param: Array vals

  • return: Node

  • api: private

-
-
Evaluator.prototype.eval = function(vals){
-  if (!vals) return nodes.null;
-  var len = vals.length
-    , node = nodes.null;
-
-  try {
-    for (var i = 0; i &lt; len; ++i) {
-      node = vals[i];
-      switch (node.nodeName) {
-        case 'if':
-          if ('block' != node.block.nodeName) {
-            node = this.visit(node);
-            break;
-          }
-        case 'each':
-        case 'block':
-          node = this.visit(node);
-          if (node.nodes) node = this.eval(node.nodes);
-          break;
-        default:
-          node = this.visit(node);
-      }
-    }
-  } catch (err) {
-    if (err instanceof nodes.Return) {
-      return err.expr;
-    } else {
-      throw err;
-    }
-  }
-
-  return node;
-};
-
-

Literal function call.

- -

- -
  • param: Call call

  • return: call

  • api: private

-
-
Evaluator.prototype.literalCall = function(call){
-  call.args = this.visit(call.args);
-  return call;
-};
-
-

Lookup name, with support for JavaScript -functions, and BIFs.

- -

- -
  • param: String name

  • return: Node

  • api: private

-
-
Evaluator.prototype.lookup = function(name){
-  var val;
-  if (val = this.stack.lookup(name)) {
-    return utils.unwrap(val);
-  } else {
-    return this.lookupFunction(name);
-  }
-};
-
-

Map segments in node returning a string.

- -

- -
  • param: Node node

  • return: String

  • api: private

-
-
Evaluator.prototype.interpolate = function(node){
-  var self = this;
-  return node.segments.map(function(node){
-    function toString(node) {
-      switch (node.nodeName) {
-        case 'function':
-        case 'ident':
-          return node.name;
-        case 'literal':
-        case 'string':
-        case 'unit':
-          return node.val;
-        case 'expression':
-          var _ = self.return;
-          self.return = true;
-          var ret = toString(self.visit(node).first); 
-          self.return = _;
-          return ret;
-      }
-    }
-    return toString(node);
-  }).join('');
-};
-
-

Lookup JavaScript user-defined or built-in function.

- -

- -
  • param: String name

  • return: Function

  • api: private

-
-
Evaluator.prototype.lookupFunction = function(name){
-  var fn = this.functions[name] || bifs[name];
-  if (fn) return new nodes.Function(name, fn);
-};
-
-

Check if the given node is an ident, and if it is defined.

- -

- -
  • param: Node node

  • return: Boolean

  • api: private

-
-
Evaluator.prototype.isDefined = function(node){
-  if (node instanceof nodes.Ident) {
-    return nodes.Boolean(this.lookup(node.name));
-  } else {
-    throw new Error('invalid "is defined" check on non-variable ' + node);
-  }
-};
-
-

Warn with the given msg.

- -

- -
  • param: String msg

  • api: private

-
-
Evaluator.prototype.warn = function(msg){
-  if (!this.warnings) return;
-  console.warn('\033[33mWarning:\033[0m ' + msg);
-};
-
-

Return the current Block.

- -

- -
  • return: Block

  • api: private

-
-
Evaluator.prototype.__defineGetter__('currentBlock', function(){
-  return this.stack.currentFrame.block;
-});
-
-

Return the current frame Scope.

- -

- -
  • return: Scope

  • api: private

-
-
Evaluator.prototype.__defineGetter__('currentScope', function(){
-  return this.stack.currentFrame.scope;
-});
-
-

Return the current Frame.

- -

- -
  • return: Frame

  • api: private

-
-
Evaluator.prototype.__defineGetter__('currentFrame', function(){
-  return this.stack.currentFrame;
-});
-
-
\ No newline at end of file