/*! * Stylus - Unit * Copyright(c) 2010 LearnBoost * MIT Licensed */ /** * Module dependencies. */ var Node = require('./node') , nodes = require('./'); /** * Initialize a new `Unit` with the given `val` and unit `type` * such as "px", "pt", "in", etc. * * @param {String} val * @param {String} type * @api public */ var Unit = module.exports = function Unit(val, type){ Node.call(this); this.val = val; this.type = type; }; /** * Inherit from `Node.prototype`. */ Unit.prototype.__proto__ = Node.prototype; /** * Return Boolean based on the unit value. * * @return {Boolean} * @api public */ Unit.prototype.toBoolean = function(){ return nodes.Boolean(this.type ? true : this.val); }; /** * Return unit string. * * @return {String} * @api public */ Unit.prototype.toString = function(){ var n = this.val; if ('px' == this.type) n = n.toFixed(0); return n + (this.type || ''); }; /** * Return a clone of this node. * * @return {Node} * @api public */ Unit.prototype.clone = function(){ var clone = new Unit(this.val, this.type); clone.lineno = this.lineno; clone.filename = this.filename; 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){ var type = this.type || right.first.type; // swap color if ('rgba' == right.nodeName || 'hsla' == right.nodeName) { return right.operate(op, this); } // operate if (this.shouldCoerce(op)) { // percentages if (('-' == op || '+' == op) && '%' == right.type) { right.val = this.val * (right.val / 100); } else { right = this.coerce(right.first); } switch (op) { case '-': return new Unit(this.val - right.val, type); case '+': return new Unit(this.val + right.val, type); case '/': return new Unit(this.val / right.val, type); case '*': return new Unit(this.val * right.val, type); case '%': return new Unit(this.val % right.val, type); case '**': return new Unit(Math.pow(this.val, right.val), 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; } } 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 ('unit' == other.nodeName) { 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'); } default: return new nodes.Unit(b.val, a.type); } } else if ('string' == other.nodeName) { 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); } };