/*! * Stylus - Object * Copyright (c) Automattic * MIT Licensed */ /** * Module dependencies. */ var Node = require('./node') , nodes = require('./') , nativeObj = {}.constructor; /** * Initialize a new `Object`. * * @api public */ var Object = module.exports = function Object(){ Node.call(this); this.vals = {}; this.keys = {}; }; /** * Inherit from `Node.prototype`. */ Object.prototype.__proto__ = Node.prototype; /** * Set `key` to `val`. * * @param {String} key * @param {Node} val * @return {Object} for chaining * @api public */ Object.prototype.setValue = function(key, val){ this.vals[key] = val; return this; }; /** * Alias for `setValue` for compatible API */ Object.prototype.set = Object.prototype.setValue; /** * Set `key` to `val`. * * @param {String} key * @param {Node} val * @return {Object} for chaining * @api public */ Object.prototype.setKey = function(key, val){ this.keys[key] = val; return this; }; /** * Return length. * * @return {Number} * @api public */ Object.prototype.__defineGetter__('length', function() { return nativeObj.keys(this.vals).length; }); /** * Get `key`. * * @param {String} key * @return {Node} * @api public */ Object.prototype.get = function(key){ return this.vals[key] || nodes.null; }; /** * Has `key`? * * @param {String} key * @return {Boolean} * @api public */ Object.prototype.has = function(key){ return key in this.vals; }; /** * Operate on `right` with the given `op`. * * @param {String} op * @param {Node} right * @return {Node} * @api public */ Object.prototype.operate = function(op, right){ switch (op) { case '.': case '[]': return this.get(right.hash); case '==': var vals = this.vals , a , b; if ('object' != right.nodeName || this.length != right.length) return nodes.false; for (var key in vals) { a = vals[key]; b = right.vals[key]; if (a.operate(op, b).isFalse) return nodes.false; } return nodes.true; case '!=': return this.operate('==', right).negate(); default: return Node.prototype.operate.call(this, op, right); } }; /** * Return Boolean based on the length of this object. * * @return {Boolean} * @api public */ Object.prototype.toBoolean = function(){ return nodes.Boolean(this.length); }; /** * Convert object to string with properties. * * @return {String} * @api private */ Object.prototype.toBlock = function(){ var str = '{' , key , val; for (key in this.vals) { val = this.get(key); if ('object' == val.first.nodeName) { str += key + ' ' + val.first.toBlock(); } else { switch (key) { case '@charset': str += key + ' ' + val.first.toString() + ';'; break; default: str += key + ':' + toString(val) + ';'; } } } str += '}'; return str; function toString(node) { if (node.nodes) { return node.nodes.map(toString).join(node.isList ? ',' : ' '); } else if ('literal' == node.nodeName && ',' == node.val) { return '\\,'; } return node.toString(); } }; /** * Return a clone of this node. * * @return {Node} * @api public */ Object.prototype.clone = function(parent){ var clone = new Object; clone.lineno = this.lineno; clone.column = this.column; clone.filename = this.filename; var key; for (key in this.vals) { clone.vals[key] = this.vals[key].clone(parent, clone); } for (key in this.keys) { clone.keys[key] = this.keys[key].clone(parent, clone); } return clone; }; /** * Return a JSON representation of this node. * * @return {Object} * @api public */ Object.prototype.toJSON = function(){ return { __type: 'Object', vals: this.vals, keys: this.keys, lineno: this.lineno, column: this.column, filename: this.filename }; }; /** * Return "{ : }" * * @return {String} * @api public */ Object.prototype.toString = function(){ var obj = {}; for (var prop in this.vals) { obj[prop] = this.vals[prop].toString(); } return JSON.stringify(obj); };