123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- /*!
- * Stylus - Unit
- * Copyright (c) Automattic <developer.wordpress.com>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node')
- , nodes = require('./');
- /**
- * Unit conversion table.
- */
- var FACTOR_TABLE = {
- 'mm': {val: 1, label: 'mm'},
- 'cm': {val: 10, label: 'mm'},
- 'in': {val: 25.4, label: 'mm'},
- 'pt': {val: 25.4/72, label: 'mm'},
- 'ms': {val: 1, label: 'ms'},
- 's': {val: 1000, label: 'ms'},
- 'Hz': {val: 1, label: 'Hz'},
- 'kHz': {val: 1000, label: 'Hz'}
- };
- /**
- * 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(){
- return this.val + (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.column = this.column;
- clone.filename = this.filename;
- return clone;
- };
- /**
- * Return a JSON representation of this node.
- *
- * @return {Object}
- * @api public
- */
- Unit.prototype.toJSON = function(){
- return {
- __type: 'Unit',
- val: this.val,
- type: this.type,
- lineno: this.lineno,
- column: this.column,
- filename: this.filename
- };
- };
- /**
- * 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)) {
- right = right.first;
- // percentages
- if ('%' != this.type && ('-' == op || '+' == op) && '%' == right.type) {
- right = new Unit(this.val * (right.val / 100), '%');
- } else {
- right = this.coerce(right);
- }
- switch (op) {
- case '-':
- return new Unit(this.val - right.val, type);
- case '+':
- // keyframes interpolation
- type = type || (right.type == '%' && right.type);
- 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;
- if (start < end) {
- do {
- expr.push(new nodes.Unit(start));
- } while (inclusive ? ++start <= end : ++start < end);
- } else {
- 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
- , factorA = FACTOR_TABLE[a.type]
- , factorB = FACTOR_TABLE[b.type];
- if (factorA && factorB && (factorA.label == factorB.label)) {
- var bVal = b.val * (factorB.val / factorA.val);
- return new nodes.Unit(bVal, a.type);
- } else {
- return new nodes.Unit(b.val, a.type);
- }
- } else if ('string' == other.nodeName) {
- // keyframes interpolation
- if ('%' == other.val) return new nodes.Unit(0, '%');
- var val = parseFloat(other.val);
- if (isNaN(val)) Node.prototype.coerce.call(this, other);
- return new nodes.Unit(val);
- } else {
- return Node.prototype.coerce.call(this, other);
- }
- };
|