StylusExpressive, dynamic, robust CSS for nodejs | |
| 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.
-
-
- |
-
-Image.prototype.open = function(){
- this.fd = fs.openSync(this.path, 'r');
-};
- |
-
-
-
- Close the file.
-
-
- |
-
-Image.prototype.close = function(){
- if (this.fd) fs.closeSync(this.fd);
-};
- |
-
-
-
- Return the type of image, supports:
-
-
-
-
-
-return: String api: private
- |
-
-Image.prototype.type = function(){
- var type
- , buf = new Buffer(4);
-
- fs.readSync(this.fd, buf, 0, 4, 0);
-
-
- if (x47 == buf[0] && x49 == buf[1] && x46 == buf[2]) type = 'gif';
-
-
- else if (x50 == buf[1] && x4E == buf[2] && x47 == buf[3]) type = 'png';
-
-
- 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]; }
-
-
- switch (type) {
- case 'jpeg':
- throw new Error('image-size() jpeg support not yet implemented');
- break;
- case 'png':
- var buf = new Buffer(8);
-
- 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);
-
- 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];
-};
- |
-
| 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]
-};
- |
-
-
- |
-
| 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';
-};
- |
-
| 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
-
-
-
-
- |
-
-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
-
-
-
-
- |
-
-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)
-
-
-
-
- |
-
-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
-
-
-
-
- |
-
-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
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-exports.unit = function(unit, type){
- utils.assertType(unit, nodes.Unit, 'unit');
-
-
- 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
-
-
-
-
- |
-
-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.
-
-
- |
-
-exports.trace = function(){
- console.log(this.stack);
- return nodes.null;
-};
- |
-
-
-
- Return the opposites of the given positions .
-
-Examples
-
- opposite-position(top left)
- // => bottom right
-
-
-
-
- |
-
-(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);
-
-
- img.open();
- var size = img.size();
- img.close();
-
-
- 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();
-};
- |
-
| 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 .
-
-
-
-
- |
-
-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() {
-
- 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}|&&|\|\||[!<>=?]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])( *)/.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() {
-
- if ('/' == this.str[0] && '/' == this.str[1]) {
- var end = this.str.indexOf('\n');
- if (-1 == end) end = this.str.length;
- this.skip(end);
- return this.advance();
- }
-
-
- if ('/' == this.str[0] && '*' == 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;
-
-
- if (this.indentRe){
- captures = this.indentRe.exec(this.str);
-
- } else {
-
- re = /^\n([\t]*) */;
- captures = re.exec(this.str);
-
-
- if (captures && !captures[1].length) {
- re = /^\n( *)/;
- captures = re.exec(this.str);
- }
-
-
- if (captures && 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');
- }
-
-
- this.isVariable = false;
-
-
- if ('\n' == this.str[0]) {
- ++this.lineno;
- return this.advance();
- }
-
-
- if (this.indentStack.length && indents < this.indentStack[0]) {
- while (this.indentStack.length && this.indentStack[0] > indents) {
- this.stash.push(new Token('outdent'));
- this.indentStack.shift();
- }
- tok = this.stash.pop();
-
- } else if (indents && indents != this.indentStack[0]) {
- this.indentStack.unshift(indents);
- tok = new Token('indent');
-
- } 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);
- }
- }
-};
-
- |
-
| lib/middleware.js |
-
- Module dependencies.
-
- |
-
-var stylus = require('./stylus')
- , fs = require('fs')
- , url = require('url')
- , basename = require('path').basename
- , join = require('path').join
- , ENOENT;
-
-
-
-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 || {};
-
-
- if ('string' == typeof options) {
- options = { src: options };
- }
-
-
- var force = options.force;
-
-
- var src = options.src;
- if (!src) throw new Error('stylus.middleware() requires "src" directory');
-
-
- var dest = options.dest
- ? options.dest
- : src;
-
-
- options.compile = options.compile || function(str, path, fn){
- stylus(str)
- .set('filename', path)
- .set('compress', options.compress)
- .render(fn);
- };
-
-
- return function(req, res, next){
- if ('GET' != req.method && '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'));
-
-
- function error(err) {
- next(ENOENT == err.errno
- ? null
- : err);
- }
-
-
- if (force) return compile();
-
-
- 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);
- });
- });
- });
- }
-
-
- fs.stat(stylusPath, function(err, stylusStats){
- if (err) return error(err);
- fs.stat(cssPath, function(err, cssStats){
-
- if (err) {
- if (ENOENT == err.errno) {
- compile();
- } else {
- next(err);
- }
- } else {
-
- if (stylusStats.mtime > cssStats.mtime) {
- compile();
-
- } else {
- next();
- }
- }
- });
- });
- } else {
- next();
- }
- }
-};
- |
-
| 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 30Kbpaths 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){
-
- var compiler = new Compiler(url);
- compiler.isURL = true;
- var url = url.nodes.map(function(node){
- return compiler.visit(node);
- }).join('');
-
-
- 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;
-
-
- if (!mime) return literal;
-
-
- if (url.protocol) return literal;
-
-
- found = utils.lookup(url.pathname, paths);
-
-
- if (!found) return literal;
-
-
- buf = fs.readFileSync(found);
-
-
- if (buf.length > sizeLimit) return literal;
-
-
- return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + '")');
- };
-
- url.raw = true;
- return url;
-};
- |
-
| 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.
-
-
-
-
- |
-
-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;
-};
- |
-
| 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';
-};
- |
-
| 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 < 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.
-
-
-
-
- |
-
-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);
-};
-
- |
-
| 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;
-};
-
- |
-
| 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.
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-Expression.prototype.clone = function(){
- var clone = new Expression(this.isList);
- clone.lineno = this.lineno;
- for (var i = 0; i < 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 ? ', ' : ' ');
-};
-
-
-
- |
-
| 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.
-
-
-
-
- |
-
-Each.prototype.clone = function(){
- var clone = new Each(
- this.val
- , this.key
- , this.expr.clone()
- , this.block.clone());
- clone.lineno = this.lineno;
- return clone;
-};
- |
-
| 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.
-
-
-
-
- |
-
-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 + '()';
-};
-
- |
-
| lib/nodes/function.js |
-
- Module dependencies.
-
- |
-
-var Node = require('./node');
- |
-
-
-
- Initialize a new Function with name , params , and body .
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-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(', ')
- + ')';
- }
-};
-
- |
-
| lib/nodes/group.js |
-
- Module dependencies.
-
- |
-
-var Node = require('./node');
- |
-
-
-
- Initialize a new Group .
-
-
- |
-
-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 < len; ++i) {
- this.nodes[i].block = block;
- }
-});
- |
-
-
-
- Return a clone of this node.
-
-
-
-
- |
-
-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;
-};
-
- |
-
| 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.
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-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 < .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));
-}
-
- |
-
| lib/nodes/if.js |
-
- Module dependencies.
-
- |
-
-var Node = require('./node');
- |
-
-
-
- Initialize a new If with the given cond .
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-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;
-};
-
- |
-
| 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.
-
-
-
-
- |
-
-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);
- }
-};
-
- |
-
| 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;
-
- |
-
| 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;
- |
-
| 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;
-};
-
- |
-
| 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);
- }
-};
-
- |
-
| 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;
-};
-
- |
-
| lib/nodes/node.js |
-
- Module dependencies.
-
- |
-
-var Evaluator = require('../visitor/evaluator')
- , utils = require('../utils')
- , nodes = require('./');
- |
-
-
-
- Node constructor.
-
-
- |
-
-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.
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-Node.prototype.clone = function(){
- return this;
-};
- |
-
-
-
- Nodes by default evaluate to themselves.
-
-
-
-
- |
-
-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 >= right.hash);
- case '<=':
- return nodes.Boolean(this.hash <= right.hash);
- case '>':
- return nodes.Boolean(this.hash > right.hash);
- case '<':
- return nodes.Boolean(this.hash < 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 < 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 && 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);
-};
-
- |
-
| lib/nodes/null.js |
-
- Module dependencies.
-
- |
-
-var Node = require('./node')
- , nodes = require('./');
- |
-
-
-
- Initialize a new Null node.
-
-
- |
-
-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;
-});
- |
-
| 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.
-
-
-
-
- |
-
-Params.prototype.clone = function(){
- var clone = new Params;
- clone.lineno = this.lineno;
- this.nodes.forEach(function(node){
- clone.push(node.clone());
- });
- return clone;
-};
-
-
- |
-
| 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;
-};
-
- |
-
| 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.
-
-
-
-
- |
-
-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;
-};
-
- |
-
| 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.prototype.clone = function(){
- var clone = new Return(this.expr.clone());
- clone.lineno = this.lineno;
- return clone;
-};
- |
-
| 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.
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-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 < 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);
-
-
- if (r[0] == r[1] && g[0] == g[1] && 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 <= .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 < 0) ++h;
- if (h > 1) --h;
- if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
- if (h * 2 < 1) return m2;
- if (h * 3 < 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));
-}
-
- |
-
| lib/nodes/root.js |
-
- Module dependencies.
-
- |
-
-var Node = require('./node');
- |
-
-
-
- Initialize a new Root node.
-
-
- |
-
-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]';
-};
-
- |
-
| 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.
-
-
-
-
- |
-
-Selector.prototype.clone = function(){
- var clone = new Selector(this.val);
- clone.lineno = this.lineno;
- return clone;
-};
-
- |
-
| 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.
-
-
-
-
- |
-
-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);
- }
-};
-
- |
-
| lib/nodes/ternary.js |
-
- Module dependencies.
-
- |
-
-var Node = require('./node');
- |
-
-
-
- Initialize a new Ternary with cond , trueExpr and falseExpr .
-
-
-
-
- |
-
-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.
-
-
-
-
- |
-
-Ternary.prototype.clone = function(){
- var clone = new Ternary(
- this.cond.clone()
- , this.trueExpr.clone()
- , this.falseExpr.clone());
- clone.lineno = this.lineno;
- return clone;
-};
- |
-
| 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.
-
-
-
-
- |
-
-UnaryOp.prototype.clone = function(){
- var clone = new UnaryOp(this.op, this.expr.clone());
- clone.lineno = this.lineno;
- return clone;
-};
- |
-
| 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.
-
-
-
-
- |
-
-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 <= end : ++start < 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);
- }
-};
-
- |
-
| 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;
-
-
-
- while ('ident' == this.lookahead(i).type
- && 'newline' == this.lookahead(i + 1).type) i += 2;
-
-
-
-
- while (this.isSelectorToken(i)) {
- if (':' == this.lookahead(i++).type
- && this.isPseudoSelector(i))
- return true;
- }
-
-
- if (',' == this.lookahead(i).type
- && 'newline' == this.lookahead(i + 1).type)
- return true;
-
-
- if ('{' == this.lookahead(i).type
- && 'newline' == this.lookahead(i + 1).type)
- return true;
-
-
- if (this.css) {
- if (';' == this.lookahead(i) ||
- '}' == this.lookahead(i))
- return false;
- }
-
-
- 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;
-
-
-
-
-
-
- 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:
-
- 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();
- }
- }
-
-
- 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;
-
-
- if (this.css = this.accept('{')) {
- delim = '}';
- this.skipWhitespace();
- } else {
- delim = 'outdent';
- this.expect('indent');
- }
-
- while (delim != this.peek().type) {
-
- 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);
- }
-
-
- 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());
-
-
- if (this.css = this.accept('{')) {
- this.skipWhitespace();
- } else {
- this.expect('indent');
- }
-
- while (pos = this.accept('unit') || this.accept('ident')) {
-
- 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;
- }
-
-
- this.state.push('keyframe');
- var block = this.block(keyframes);
- keyframes.push(pos, block);
- this.state.pop();
- if (this.css) this.skipWhitespace();
- }
-
-
- 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) {
-
- case '=':
- case '?=':
- case '-=':
- case '+=':
- case '*=':
- case '/=':
- case '%=':
- return this.assignment();
-
- 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':
-
- if (this._ident == this.peek()) {
- return this.id();
- } else {
- this._ident = this.peek();
- switch (this.currentState()) {
-
- case 'for':
- case 'selector':
- return this.property();
-
- case 'root':
- return this.selector();
-
- default:
- return this.operand
- ? this.id()
- : this.expression();
- }
- }
-
- 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();
-
-
- var ident = this.interpolate()
- , ret = prop = new nodes.Property(ident);
-
-
- 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();
-
-
- this.accept(';');
-
- return ret;
- },
- |
-
-
-
- selector ',' selector
-| selector newline selector
-| selector block
-
- |
-
-selector: function() {
- var tok
- , arr
- , val
- , prev
- , parent
- , group = new nodes.Group;
-
-
-
- this.lexer.allowComments = true;
-
- do {
- val = prev = null;
- arr = [];
-
-
- this.accept('newline');
-
-
-
-
- while (tok = this.selectorToken()) {
-
- 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;
- }
-
-
- if (!prev || prev.space) {
- arr.push(val);
- } else {
- arr[arr.length-1] += val;
- }
- prev = tok;
- }
-
-
- 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;
-
-
-
-
- out:
- while (tok = this.lookahead(i++)) {
- switch (tok.type) {
- case 'function': case '(': ++parens; break;
- case ')': if (!--parens) break out;
- }
- }
-
-
- 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;
-
-
- this.state.push('function params');
- this.skipWhitespace();
- var params = this.params();
- this.skipWhitespace();
- this.expect(')');
- this.state.pop();
-
-
- 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 && this.inProperty && !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;
-
-
- if (this.accept('(')) {
- this.parens = true;
- var expr = this.expression();
- this.expect(')');
- this.parens = false;
- return expr;
- }
-
-
- 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();
- }
- }
-};
-
- |
-
| 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 .
-
-
-
-
- |
-
-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 .
-
-
-
-
- |
-
-Renderer.prototype.define = function(name, fn, raw){
- this.options.functions[name] = fn;
- if (undefined != raw) fn.raw = raw;
- return this;
-};
- |
-
-
-
- Import the given file .
-
-
-
-
- |
-
-Renderer.prototype.import = function(file){
- this.options.imports.push(file);
- return this;
-};
-
-
-
- |
-
| lib/stack/index.js |
-
- Module dependencies.
-
- |
-
-var Frame = require('./frame');
- |
-
-
-
- Initialize a new Stack .
-
-
- |
-
-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 < 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 && (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');
-};
- |
-
| 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())
- + ']';
-};
-
- |
-
| 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) .
-
-
-
-
- |
-
-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');
-
- |
-
| lib/stack/scope.js |
-
- Initialize a new Scope .
-
-
- |
-
-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(', ') : '')
- + ']';
-};
-
- |
-
| 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 < 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 < 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';
- }
-
-
- for (var i = 0, len = block.nodes.length; i < 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);
-
-
- if ('px' == type) n = n.toFixed(0);
-
- if (this.compress) {
-
- if (0 == unit.val) return '0';
-
- if (float && n < 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 = [];
-
-
-
- group.nodes.forEach(function(node){
- curr.push(node.parent
- ? node
- : node.val);
- });
-
- tree.push(curr);
-
-
-
-
-
-
- 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 < len; ++i) {
- if (~buf[i].indexOf('&')) {
- str = buf[i].replace('&', str);
- } else {
- str += ' ' + buf[i];
- }
- }
- }
- selectors.push(self.indent + str);
- });
- }
- }
-
-
- if (group.block.hasProperties) {
- join(tree, tree.length - 1);
- this.buf += selectors.join(this.compress ? ',' : ',\n');
- }
-
-
- 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 ? '' : ';')
- : ';');
-};
-
- |
-
| 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;
-
-
- if ('/' == path[0]) {
- try {
- fs.statSync(path);
- return path;
- } catch (err) {
-
-
-
-
- }
- }
-
-
- while (i--) {
- try {
- lookup = paths[i] + '/' + path;
- if (ignore == lookup) continue;
- fs.statSync(lookup);
- return lookup;
- } catch (err) {
-
- }
- }
-};
- |
-
-
-
- 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];
-};
- |
-
| 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();
-};
-
- |
-
| 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;
-};
-
-
- |
-
| 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 falsewarn 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 = [];
-};
- |
-
-
-
- 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) {
-
-
- 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
- |
-
-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:
-
-
- |
-
-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){
-
- var local = this.stack.currentFrame.scope.lookup(fn.name);
- if (local) this.warn('local ' + local.nodeName + ' "' + fn.name + '" previously defined in this scope');
-
-
- var user = this.functions[fn.name];
- if (user) this.warn('user-defined function "' + fn.name + '" is already defined');
-
-
- 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 < 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;
-
-
- if (fn && 'expression' == fn.nodeName) {
- fn = fn.nodes[0];
- }
-
-
- if (fn && 'function' != fn.nodeName) {
- fn = this.lookupFunction(call.name);
- }
-
-
- if (!fn || fn.nodeName != 'function') return this.literalCall(call);
- this.calling.push(call.name);
-
-
- if (this.calling.length > 200) {
- throw new RangeError('Maximum call stack size exceeded');
- }
-
-
- if (fn instanceof nodes.Expression) fn = fn.first;
-
-
- var _ = this.return;
- this.return = true;
- var args = this.visit(call.args);
- this.return = _;
-
-
- if (fn.fn) {
- ret = this.invokeBuiltin(fn.fn, args);
-
- } else if (fn instanceof nodes.Function) {
- ret = this.invokeFunction(fn, args);
- }
-
- this.calling.pop();
- return ret;
-};
- |
-
-
-
- Visit Ident.
-
- |
-
-Evaluator.prototype.visitIdent = function(ident){
-
- if (nodes.null == ident.val) {
- var val = this.lookup(ident.name);
- return val ? this.visit(val) : ident;
-
- } 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){
-
- if ('is defined' == binop.op) return this.isDefined(binop.left);
-
- var _ = this.return;
- this.return = true;
-
- var op = binop.op
- , ident = 'ident' == binop.left.nodeName
- , left = this.visit(binop.left)
- , right = this.visit(binop.right);
- this.return = _;
-
-
- if (!~['[]', 'in'].indexOf(op)) {
- left = left.first;
- right = right.first;
- }
-
-
- switch (op) {
- case '[]':
- case 'in':
- case '||':
- case '&&':
- case 'is a':
- break;
- default:
-
- if ('-' == op
- && 'ident' == left.nodeName
- && 'unit' == right.nodeName) {
- var expr = new nodes.Expression;
- right.val = -right.val;
- expr.push(left);
- expr.push(right);
- return expr;
- }
-
-
- try {
- right = left.coerce(right);
- } catch (err) {
-
-
- if ('==' == op || '!=' == op) {
- return nodes.false;
- } else {
- throw err;
- }
- }
- }
-
-
- 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 < 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);
-
-
- if (call && !literal && !prop.literal) {
- this.calling.push(name);
- var ret = this.visit(new nodes.Call(name, prop.expr));
- this.calling.pop();
- return ret;
-
- } 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 < 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 < 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 = _;
-
-
- if (negate) {
-
- if (nodes.false == ok) {
- ret = this.visit(node.block);
- }
- } else {
-
- if (nodes.true == ok) {
- ret = this.visit(node.block);
-
- } else if (node.elses.length) {
- var elses = node.elses
- , len = elses.length;
- for (var i = 0; i < len; ++i) {
-
- if (elses[i].cond) {
- if (nodes.true == this.visit(elses[i].cond).first.toBoolean()) {
- ret = this.visit(elses[i].block);
- break;
- }
-
- } else {
- ret = this.visit(elses[i]);
- }
- }
- }
- }
-
-
- if (ret && !node.postfix && block.node && '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;
-
-
- if (!path.string) throw new Error('@import string expected');
- var name = path = path.string;
-
-
- if (/\.css$/.test(path)) return import;
- path += '.styl';
-
-
- 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();
-
-
- import.path = found;
- if (this.options._imports) this.options._imports.push(import);
-
-
- if (!found) throw new Error('failed to locate @import file ' + path);
- this.importPath = dirname(found);
-
-
- 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;
-
-
-
-
- var body = fn.block.clone();
-
-
- var mixinBlock = this.stack.currentFrame.block;
-
-
-
- this.stack.push(new Frame(block));
- var scope = this.currentScope;
-
-
- scope.add(new nodes.Ident('arguments', args));
-
-
- scope.add(new nodes.Ident('mixin', this.return
- ? nodes.false
- : new nodes.String(mixinBlock.nodeName)));
-
-
- fn.params.nodes.forEach(function(node, i){
-
- if (node.rest) {
- node.val = new nodes.Expression;
- for (var len = args.nodes.length; i < len; ++i) {
- node.val.push(args.nodes[i]);
- }
-
- } else {
- var arg = args.nodes[i];
- var val = arg && !arg.isEmpty
- ? args.nodes[i]
- : node.val;
- node = node.clone();
- node.val = val;
-
- if (node.val instanceof nodes.Null) {
- throw new Error('argument ' + node + ' required for ' + fn);
- }
- }
-
- scope.add(node);
- });
-
-
- 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){
-
-
-
-
-
- if (fn.raw) {
- args = args.nodes;
- } else {
- args = args.nodes.map(function(node){
- return node.first;
- });
- }
-
-
- var body = fn.apply(this, args);
-
-
-
-
- var expr = new nodes.Expression;
- expr.push(body);
- body = expr;
-
-
- 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;
-
-
- if (this.return) {
- ret = this.eval(body.nodes);
- if (stack) this.stack.pop();
-
- } 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 < 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 < 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;
-});
-
- |
-
-