stylus
Version:
Robust, expressive, and feature-rich CSS superset
245 lines (207 loc) • 4.2 kB
JavaScript
/*!
* Stylus - Object
* Copyright (c) Automattic <developer.wordpress.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var Node = require('./node')
, nodes = require('./')
, nativeObj = {}.constructor;
module.exports = class Object extends Node {
/**
* Initialize a new `Object`.
*
* @api public
*/
constructor() {
super();
this.vals = {};
this.keys = {};
}
/**
* Set `key` to `val`.
*
* @param {String} key
* @param {Node} val
* @return {Object} for chaining
* @api public
*/
setValue(key, val) {
this.vals[key] = val;
return this;
};
/**
* Alias for `setValue` for compatible API
*/
get set() {
return this.setValue;
}
/**
* Set `key` to `val`.
*
* @param {String} key
* @param {Node} val
* @return {Object} for chaining
* @api public
*/
setKey(key, val) {
this.keys[key] = val;
return this;
};
/**
* Return length.
*
* @return {Number}
* @api public
*/
get length() {
return nativeObj.keys(this.vals).length;
};
/**
* Get `key`.
*
* @param {String} key
* @return {Node}
* @api public
*/
get(key) {
return this.vals[key] || nodes.null;
};
/**
* Has `key`?
*
* @param {String} key
* @return {Boolean}
* @api public
*/
has(key) {
return key in this.vals;
};
/**
* Operate on `right` with the given `op`.
*
* @param {String} op
* @param {Node} right
* @return {Node}
* @api public
*/
operate(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 super.operate(op, right);
}
};
/**
* Return Boolean based on the length of this object.
*
* @return {Boolean}
* @api public
*/
toBoolean() {
return new nodes.Boolean(this.length);
};
/**
* Convert object to string with properties.
*
* @return {String}
* @api private
*/
toBlock() {
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
*/
clone(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
*/
toJSON() {
return {
__type: 'Object',
vals: this.vals,
keys: this.keys,
lineno: this.lineno,
column: this.column,
filename: this.filename
};
};
/**
* Return "{ <prop>: <val> }"
*
* @return {String}
* @api public
*/
toString() {
var obj = {};
for (var prop in this.vals) {
obj[prop] = this.vals[prop].toString();
}
return JSON.stringify(obj);
};
};