Comparing version 0.38.0 to 0.39.0
@@ -574,3 +574,3 @@ | ||
var re = new RegExp(pattern.val); | ||
return nodes.Boolean(re.test(val.string)); | ||
return new nodes.Boolean(re.test(val.string)); | ||
}; | ||
@@ -659,5 +659,12 @@ | ||
if (expr) { | ||
return expr.nodes | ||
? utils.unwrap(expr).nodes.length | ||
: 1; | ||
if (expr.nodes) { | ||
var nodes = utils.unwrap(expr).nodes; | ||
if (1 == nodes.length && 'object' == nodes[0].nodeName) { | ||
return nodes[0].length; | ||
} else { | ||
return nodes.length; | ||
} | ||
} else { | ||
return 1; | ||
} | ||
} | ||
@@ -1025,2 +1032,21 @@ return 0; | ||
/** | ||
* Merge the object `dest` with the given args. | ||
* | ||
* @param {Object} dest | ||
* @param {Object} ... | ||
* @return {Object} dest | ||
* @api public | ||
*/ | ||
(exports.merge = exports.extend = function merge(dest){ | ||
utils.assertPresent(dest, 'dest'); | ||
dest = utils.unwrap(dest).first; | ||
utils.assertType(dest, 'object', 'dest'); | ||
for (var i = 1, len = arguments.length; i < len; ++i) { | ||
utils.merge(dest.vals, utils.unwrap(arguments[i]).first.vals); | ||
} | ||
return dest; | ||
}).raw = true; | ||
/** | ||
* Attempt to parse unit `str`. | ||
@@ -1042,13 +1068,17 @@ * | ||
/** | ||
* Attempt to parse color | ||
* @param {String} str | ||
* @return {RGBA} | ||
* @api public | ||
*/ | ||
* Attempt to parse color | ||
* | ||
* @param {String} str | ||
* @return {RGBA} | ||
* @api public | ||
*/ | ||
function parseColor(str){ | ||
if (str.substr(0,1) === '#'){ | ||
var m = str.match(/\w{2}/g); | ||
if (str.substr(0,1) === '#') { | ||
// Handle color shorthands (like #abc) | ||
var shorthand = str.length === 4, | ||
m = str.match(shorthand ? /\w/g : /\w{2}/g); | ||
if (!m) return; | ||
m = m.map(function(s){ return parseInt(s, 16) }); | ||
m = m.map(function(s) { return parseInt(shorthand ? s+s : s, 16) }); | ||
return new nodes.RGBA(m[0],m[1],m[2],1); | ||
@@ -1055,0 +1085,0 @@ } |
@@ -11,2 +11,3 @@ /** | ||
, extname = require('path').extname | ||
, sep = require('path').sep | ||
, utils = require('../utils'); | ||
@@ -51,2 +52,3 @@ | ||
, tail = '' | ||
, res | ||
, found; | ||
@@ -58,3 +60,3 @@ | ||
// Lookup | ||
var found = utils.lookup(url.pathname, paths, '', true); | ||
found = utils.lookup(url.pathname, paths, '', true); | ||
@@ -70,3 +72,5 @@ // Failed to lookup | ||
} else { | ||
return new nodes.Literal('url("' + relative(dirname(this.filename), found) + tail + '")'); | ||
res = relative(dirname(this.filename), found) + tail; | ||
if ('\\' == sep) res = res.replace(/\\/g, '/'); | ||
return new nodes.Literal('url("' + res + '")'); | ||
} | ||
@@ -73,0 +77,0 @@ }; |
@@ -425,2 +425,3 @@ | ||
* | ']' | ||
* | '.' | ||
* | '..' | ||
@@ -432,3 +433,3 @@ * | '...' | ||
var captures; | ||
if (captures = /^([.]{2,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])([ \t]*)/.exec(this.str)) { | ||
if (captures = /^([.]{1,3}|&&|\|\||[!<>=?:]=|\*\*|[-+*\/%]=?|[,=?:!~<>&\[\]])([ \t]*)/.exec(this.str)) { | ||
var op = captures[1]; | ||
@@ -435,0 +436,0 @@ this.skip(captures); |
@@ -54,2 +54,12 @@ | ||
return clone; | ||
}; | ||
}; | ||
/** | ||
* Return <left> <op> <right> | ||
* | ||
* @return {String} | ||
* @api public | ||
*/ | ||
BinOp.prototype.toString = function() { | ||
return this.left.toString() + ' ' + this.op + ' ' + this.right.toString(); | ||
}; |
@@ -116,3 +116,4 @@ | ||
, val = utils.unwrap(val) | ||
, len; | ||
, len | ||
, node; | ||
range.forEach(function(unit){ | ||
@@ -124,2 +125,5 @@ len = self.nodes.length; | ||
self.nodes[unit.val] = val; | ||
} else if ('string' == unit.nodeName) { | ||
node = self.nodes[0]; | ||
if (node && 'object' == node.nodeName) node.set(unit.val, val.clone()); | ||
} | ||
@@ -131,8 +135,11 @@ }); | ||
, vals = utils.unwrap(this).nodes | ||
, range = utils.unwrap(right).nodes; | ||
, range = utils.unwrap(right).nodes | ||
, node; | ||
range.forEach(function(unit){ | ||
if ('unit' == unit.nodeName) { | ||
var node = vals[unit.val]; | ||
if (node) expr.push(node); | ||
node = vals[unit.val]; | ||
} else if ('string' == unit.nodeName && 'object' == vals[0].nodeName) { | ||
node = vals[0].get(unit.val); | ||
} | ||
if (node) expr.push(node); | ||
}); | ||
@@ -139,0 +146,0 @@ return expr.isEmpty |
@@ -38,5 +38,7 @@ | ||
exports.Keyframes = require('./keyframes'); | ||
exports.Member = require('./member'); | ||
exports.Charset = require('./charset'); | ||
exports.Import = require('./import'); | ||
exports.Extend = require('./extend'); | ||
exports.Object = require('./object'); | ||
exports.Function = require('./function'); | ||
@@ -43,0 +45,0 @@ exports.Property = require('./property'); |
@@ -162,5 +162,12 @@ | ||
var vals = utils.unwrap(right).nodes | ||
, len = vals.length | ||
, 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) { | ||
// 'prop' in obj | ||
if (1 == len && 'object' == vals[0].nodeName) { | ||
return nodes.Boolean(vals[0].has(this.hash)); | ||
} | ||
for (var i = 0; i < len; ++i) { | ||
if (hash == vals[i].hash) { | ||
@@ -167,0 +174,0 @@ return nodes.true; |
@@ -57,2 +57,3 @@ | ||
, '}' | ||
, '.' | ||
]; | ||
@@ -136,2 +137,13 @@ | ||
/** | ||
* Return previous state. | ||
* | ||
* @return {String} | ||
* @api private | ||
*/ | ||
previousState: function() { | ||
return this.state[this.state.length - 2]; | ||
}, | ||
/** | ||
* Parse the input, then return the root node. | ||
@@ -289,3 +301,3 @@ * | ||
while (la = this.lookahead(i++)) { | ||
if (~['indent', 'outdent', 'newline'].indexOf(la.type)) return; | ||
if (~['indent', 'outdent', 'newline', 'eos'].indexOf(la.type)) return; | ||
if (type == la.type) return true; | ||
@@ -383,2 +395,8 @@ } | ||
if ('ident' == this.lookahead(i).type && '.' == this.lookahead(i + 1).type) | ||
return true; | ||
if (':' == this.lookahead(i).type && !this.isPseudoSelector(i + 1) && this.lineContains('.')) | ||
return false; | ||
// the ':' token within braces signifies | ||
@@ -576,2 +594,3 @@ // a selector. ex: "foo{bar:'baz'}" | ||
case '[': | ||
case '.': | ||
return this.selector(); | ||
@@ -664,4 +683,4 @@ case '*': | ||
this.expect('in'); | ||
this.state.push('for'); | ||
var each = new nodes.Each(val, key, this.expression()); | ||
this.state.push('for'); | ||
each.block = this.block(each, false); | ||
@@ -690,4 +709,4 @@ this.state.pop(); | ||
this.expect('unless'); | ||
this.state.push('conditional'); | ||
var node = new nodes.If(this.expression(), true); | ||
this.state.push('conditional'); | ||
node.block = this.block(node, false); | ||
@@ -704,4 +723,4 @@ this.state.pop(); | ||
this.expect('if'); | ||
this.state.push('conditional'); | ||
var node = new nodes.If(this.expression()); | ||
this.state.push('conditional'); | ||
node.block = this.block(node, false); | ||
@@ -938,3 +957,3 @@ while (this.accept('else')) { | ||
&& 'selector' != this.lookahead(i).type) ; | ||
if ('=' == this.lookahead(i).type) { | ||
if ('=' == this.lookahead(i).type || '[' == this.lookahead(i).type) { | ||
this._ident = this.peek(); | ||
@@ -1565,11 +1584,16 @@ return this.expression(); | ||
/** | ||
* primary ('[' expression ']' '='?)+ | ||
* | primary | ||
* member ('[' expression ']' ('.' id)? '='?)+ | ||
* | member | ||
*/ | ||
subscript: function() { | ||
var node = this.primary(); | ||
var node = this.member() | ||
, id; | ||
while (this.accept('[')) { | ||
node = new nodes.BinOp('[]', node, this.expression()); | ||
this.expect(']'); | ||
if (this.accept('.')) { | ||
id = new nodes.Ident(this.expect('ident').val.string); | ||
node = new nodes.Member(node, id); | ||
} | ||
// TODO: TernaryOp :) | ||
@@ -1585,2 +1609,44 @@ if (this.accept('=')) { | ||
/** | ||
* primary ('.' id)+ | ||
* | primary | ||
*/ | ||
member: function() { | ||
var node = this.primary(); | ||
if (node) { | ||
while (this.accept('.')) { | ||
var id = new nodes.Ident(this.expect('ident').val.string); | ||
node = new nodes.Member(node, id); | ||
} | ||
this.skipSpaces(); | ||
} | ||
return node; | ||
}, | ||
/** | ||
* '{' '}' | ||
* | '{' pair (ws pair)* '}' | ||
*/ | ||
object: function(){ | ||
var id, val; | ||
var obj = new nodes.Object; | ||
this.expect('{'); | ||
this.skipWhitespace(); | ||
while (!this.accept('}')) { | ||
id = this.accept('ident') || this.accept('string'); | ||
if (!id) this.error('expected "ident" or "string", got {peek}'); | ||
id = id.val.hash; | ||
this.expect(':'); | ||
val = this.expression(); | ||
obj.set(id, val); | ||
this.accept(','); | ||
this.skipWhitespace(); | ||
} | ||
return obj; | ||
}, | ||
/** | ||
* unit | ||
@@ -1593,2 +1659,3 @@ * | null | ||
* | literal | ||
* | object | ||
* | '(' expression ')' '%'? | ||
@@ -1620,2 +1687,5 @@ */ | ||
return this.next().val; | ||
case '{': | ||
if ('conditional' == this.previousState() || 'for' == this.previousState()) return; | ||
return this.object(); | ||
case 'ident': | ||
@@ -1622,0 +1692,0 @@ return this.ident(); |
@@ -44,2 +44,3 @@ | ||
options.filename = options.filename || 'stylus'; | ||
options.Evaluator = options.Evaluator || Evaluator; | ||
this.options = options; | ||
@@ -77,3 +78,3 @@ this.str = str; | ||
// evaluate | ||
this.evaluator = new Evaluator(ast, this.options); | ||
this.evaluator = new this.options.Evaluator(ast, this.options); | ||
this.nodes = nodes; | ||
@@ -80,0 +81,0 @@ this.evaluator.renderer = this; |
@@ -242,2 +242,28 @@ | ||
/** | ||
* Visit Object. | ||
*/ | ||
Evaluator.prototype.visitObject = function(obj){ | ||
for (var key in obj.vals) { | ||
obj.vals[key] = this.visit(obj.vals[key]); | ||
} | ||
return obj; | ||
}; | ||
/** | ||
* Visit Member. | ||
*/ | ||
Evaluator.prototype.visitMember = function(node){ | ||
var left = node.left | ||
, right = node.right | ||
, obj = this.visit(left).first; | ||
if ('object' != obj.nodeName) { | ||
throw new Error(left.toString() + ' has no property .' + right); | ||
} | ||
return obj.get(right.name); | ||
}; | ||
/** | ||
* Visit Keyframes. | ||
@@ -300,17 +326,36 @@ */ | ||
, vals = [] | ||
, body; | ||
, self = this | ||
, body | ||
, obj; | ||
this.return--; | ||
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); | ||
function visitBody(body) { | ||
body = each.block.clone(); | ||
body.nodes.map(cloneNode); | ||
body = this.visit(body); | ||
body = self.visit(body); | ||
vals = vals.concat(body.nodes); | ||
} | ||
// for prop in obj | ||
if (1 == len && 'object' == expr.nodes[0].nodeName) { | ||
obj = expr.nodes[0]; | ||
for (var prop in obj.vals) { | ||
val.val = new nodes.String(prop); | ||
key.val = obj.get(prop); | ||
scope.add(val); | ||
scope.add(key); | ||
visitBody(body); | ||
} | ||
} else { | ||
for (var i = 0; i < len; ++i) { | ||
val.val = expr.nodes[i]; | ||
key.val = new nodes.Unit(i); | ||
scope.add(val); | ||
scope.add(key); | ||
visitBody(body); | ||
} | ||
} | ||
this.mixin(vals, block); | ||
@@ -327,2 +372,3 @@ return vals[vals.length - 1] || nodes.null; | ||
var fn = this.lookup(call.name) | ||
, literal | ||
, ret; | ||
@@ -346,3 +392,9 @@ | ||
debug('%s is undefined', call); | ||
var ret = this.literalCall(call); | ||
// Special case for `calc` | ||
if ('calc' == this.unvendorize(call.name)) { | ||
literal = call.args.nodes && call.args.nodes[0]; | ||
if (literal) ret = new nodes.Literal(call.name + literal); | ||
} else { | ||
ret = this.literalCall(call); | ||
} | ||
this.ignoreColors = false; | ||
@@ -616,3 +668,3 @@ return ret; | ||
if (elses[i].cond) { | ||
if (this.visit(elses[i].cond).first.toBoolean().isTrue) { | ||
if (this.visit(elses[i]).first.toBoolean().isTrue) { | ||
ret = this.visit(elses[i].block); | ||
@@ -679,3 +731,3 @@ break; | ||
// Absolute URL | ||
if (/url\s*\(\s*['"]?http/i.test(path)) { | ||
if (/url\s*\(\s*['"]?(?:https?:)?\/\//i.test(path)) { | ||
return imported; | ||
@@ -1238,2 +1290,20 @@ } | ||
/** | ||
* Return the property name without vendor prefix. | ||
* | ||
* @param {String} prop | ||
* @return {String} | ||
* @api public | ||
*/ | ||
Evaluator.prototype.unvendorize = function(prop){ | ||
for (var i = 0, len = this.vendors.length; i < len; i++) { | ||
if ('official' != this.vendors[i]) { | ||
var vendor = '-' + this.vendors[i] + '-'; | ||
if (~prop.indexOf(vendor)) return prop.replace(vendor, ''); | ||
} | ||
} | ||
return prop; | ||
}; | ||
/** | ||
* Return the current frame `Scope`. | ||
@@ -1240,0 +1310,0 @@ * |
@@ -1,22 +0,37 @@ | ||
{ "name": "stylus" | ||
, "description": "Robust, expressive, and feature-rich CSS superset" | ||
, "version": "0.38.0" | ||
, "author": "TJ Holowaychuk <tj@vision-media.ca>" | ||
, "keywords": ["css", "parser", "style", "stylesheets", "jade", "language"] | ||
, "repository": "git://github.com/LearnBoost/stylus" | ||
, "main": "./index.js" | ||
, "browserify": "./lib/browserify.js" | ||
, "engines": { "node": "*" } | ||
, "bin": { "stylus": "./bin/stylus" } | ||
, "scripts" : { "prepublish" : "npm prune", "test": "make test" } | ||
, "dependencies": { | ||
"cssom": "0.2.x" | ||
, "mkdirp": "0.3.x" | ||
, "debug": "*" | ||
, "sax": "0.5.x" | ||
{ | ||
"name": "stylus", | ||
"description": "Robust, expressive, and feature-rich CSS superset", | ||
"version": "0.39.0", | ||
"author": "TJ Holowaychuk <tj@vision-media.ca>", | ||
"keywords": [ | ||
"css", | ||
"parser", | ||
"style", | ||
"stylesheets", | ||
"jade", | ||
"language" | ||
], | ||
"repository": "git://github.com/LearnBoost/stylus", | ||
"main": "./index.js", | ||
"browserify": "./lib/browserify.js", | ||
"engines": { | ||
"node": "*" | ||
}, | ||
"bin": { | ||
"stylus": "./bin/stylus" | ||
}, | ||
"scripts": { | ||
"prepublish": "npm prune", | ||
"test": "make test" | ||
}, | ||
"dependencies": { | ||
"cssom": "0.2.x", | ||
"mkdirp": "0.3.x", | ||
"debug": "*", | ||
"sax": "0.5.x" | ||
}, | ||
"devDependencies": { | ||
"should": "*", | ||
"mocha": "*" | ||
} | ||
, "devDependencies": { | ||
"should": "*" | ||
, "mocha": "*" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
250919
68
9520