Comparing version 0.45.1 to 0.46.0
@@ -246,3 +246,3 @@ /*! | ||
Converter.prototype.visitKeyframe = function(node){ | ||
var buf = this.indent + node.values.join('\n,'); | ||
var buf = this.indent + node.values.join(', '); | ||
buf += '\n'; | ||
@@ -249,0 +249,0 @@ ++this.indents; |
@@ -516,3 +516,3 @@ | ||
/** | ||
* Unquote the given `str`. | ||
* Unquote the given `string`. | ||
* | ||
@@ -538,2 +538,16 @@ * Examples: | ||
/** | ||
* Like `unquote` but tries to convert | ||
* the given `str` to a Stylus node. | ||
* | ||
* @param {String} str | ||
* @return {Node} | ||
* @api public | ||
*/ | ||
exports.convert = function convert(str){ | ||
utils.assertString(str, 'str'); | ||
return parseString(str.string); | ||
}; | ||
/** | ||
* Assign `type` to the given `unit` or return `unit`'s type. | ||
@@ -540,0 +554,0 @@ * |
@@ -57,3 +57,2 @@ | ||
function Lexer(str, options) { | ||
var self = this; | ||
options = options || {}; | ||
@@ -65,14 +64,2 @@ this.stash = []; | ||
function comment(str, val, offset, s) { | ||
var commentIdx = s.lastIndexOf('//', offset) | ||
, inComment = s.lastIndexOf('/*', offset) > s.lastIndexOf('*/', offset) | ||
|| (~commentIdx && commentIdx > s.lastIndexOf('\n', offset) | ||
&& commentIdx > s.lastIndexOf("'", offset) | ||
&& commentIdx > s.lastIndexOf('"', offset)); | ||
++self.lineno; | ||
return inComment | ||
? str | ||
: val; | ||
}; | ||
// Remove UTF-8 BOM. | ||
@@ -83,6 +70,4 @@ if ('\uFEFF' == str.charAt(0)) str = str.slice(1); | ||
.replace(/\s+$/, '\n') | ||
.replace(/\r\n?/g, '\n') | ||
.replace(/\\ *\n/g, ' ') | ||
.replace(/([,(]|:(?!\/\/[^ ])) *(?:\/\/[^\n]*)?\n\s*/g, comment) | ||
.replace(/\s*\n[ \t]*([,)])/g, comment); | ||
.replace(/\r\n?/g, '\n'); | ||
}; | ||
@@ -108,3 +93,2 @@ | ||
this.str = tmp; | ||
this.prevIndents = 0; | ||
return buf.concat(tok.inspect()).join('\n'); | ||
@@ -149,2 +133,3 @@ }, | ||
var tok = this.stashed() || this.advance(); | ||
switch (tok.type) { | ||
@@ -321,2 +306,3 @@ case 'newline': | ||
case '}': --braces; break; | ||
case '\n': ++this.lineno; break; | ||
} | ||
@@ -635,5 +621,2 @@ css += c; | ||
// Reset state | ||
this.isVariable = false; | ||
// Blank line | ||
@@ -640,0 +623,0 @@ if ('\n' == this.str[0]) { |
@@ -238,3 +238,6 @@ /*! | ||
pathB = pathB.split(sep); | ||
if (!pathA[pathA.length - 1]) pathA.pop(); | ||
if (!pathB[0]) pathB.shift(); | ||
var overlap = []; | ||
while (pathA[pathA.length - 1] == pathB[0]) { | ||
@@ -241,0 +244,0 @@ overlap.push(pathA.pop()); |
@@ -44,3 +44,6 @@ | ||
for (var i = 0, len = this.nodes.length; i < len; ++i) { | ||
if ('property' == this.nodes[i].nodeName) { | ||
var node = this.nodes[i]; | ||
// real property or unquoted literal | ||
if ('property' == node.nodeName | ||
|| (!node.css && 'literal' == node.nodeName)) { | ||
return true; | ||
@@ -47,0 +50,0 @@ } |
@@ -121,5 +121,6 @@ | ||
if ('unit' == unit.nodeName) { | ||
var i = unit.val; | ||
var i = unit.val < 0 ? len + unit.val : unit.val | ||
, n = i; | ||
while (i-- > len) self.nodes[i] = nodes.null; | ||
self.nodes[unit.val] = val; | ||
self.nodes[n] = val; | ||
} else if ('string' == unit.nodeName) { | ||
@@ -138,3 +139,3 @@ node = self.nodes[0]; | ||
if ('unit' == unit.nodeName) { | ||
node = vals[unit.val]; | ||
node = vals[unit.val < 0 ? vals.length + unit.val : unit.val]; | ||
} else if ('string' == unit.nodeName && 'object' == vals[0].nodeName) { | ||
@@ -141,0 +142,0 @@ node = vals[0].get(unit.val); |
@@ -19,9 +19,11 @@ | ||
* @param {String} str | ||
* @param {Boolean} [css] | ||
* @api public | ||
*/ | ||
var Literal = module.exports = function Literal(str){ | ||
var Literal = module.exports = function Literal(str, css){ | ||
Node.call(this); | ||
this.val = str; | ||
this.string = str; | ||
this.css = css; | ||
this.prefixed = false; | ||
@@ -108,2 +110,3 @@ }; | ||
string: this.string, | ||
css: this.css, | ||
prefixed: this.prefixed, | ||
@@ -110,0 +113,0 @@ lineno: this.lineno, |
@@ -44,2 +44,3 @@ | ||
clone.name = this.name; | ||
if (this.literal) clone.literal = this.literal; | ||
clone.lineno = this.lineno; | ||
@@ -68,2 +69,3 @@ clone.filename = this.filename; | ||
if (this.expr) json.expr = this.expr; | ||
if (this.literal) json.literal = this.literal; | ||
return json; | ||
@@ -70,0 +72,0 @@ }; |
@@ -60,2 +60,22 @@ | ||
/** | ||
* Merges this query list with the `other`. | ||
* | ||
* @param {QueryList} other | ||
* @return {QueryList} | ||
* @api private | ||
*/ | ||
QueryList.prototype.merge = function(other){ | ||
var list = new QueryList | ||
, merged; | ||
this.nodes.forEach(function(query){ | ||
for (var i = 0, len = other.nodes.length; i < len; ++i){ | ||
merged = query.merge(other.nodes[i]); | ||
if (merged) list.push(merged); | ||
} | ||
}); | ||
return list; | ||
}; | ||
/** | ||
* Return "<a>, <b>, <c>" | ||
@@ -62,0 +82,0 @@ * |
@@ -23,2 +23,3 @@ | ||
this.nodes = []; | ||
this.type = ''; | ||
this.predicate = ''; | ||
@@ -43,2 +44,3 @@ }; | ||
clone.predicate = this.predicate; | ||
clone.type = this.type; | ||
for (var i = 0, len = this.nodes.length; i < len; ++i) { | ||
@@ -64,2 +66,71 @@ clone.push(this.nodes[i].clone(parent, clone)); | ||
/** | ||
* Return resolved type of this query. | ||
* | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Query.prototype.__defineGetter__('resolvedType', function(){ | ||
if (this.type) { | ||
return this.type.nodeName | ||
? this.type.string | ||
: this.type; | ||
} | ||
}); | ||
/** | ||
* Return resolved predicate of this query. | ||
* | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Query.prototype.__defineGetter__('resolvedPredicate', function(){ | ||
if (this.predicate) { | ||
return this.predicate.nodeName | ||
? this.predicate.string | ||
: this.predicate; | ||
} | ||
}); | ||
/** | ||
* Merges this query with the `other`. | ||
* | ||
* @param {Query} other | ||
* @return {Query} | ||
* @api private | ||
*/ | ||
Query.prototype.merge = function(other){ | ||
var query = new Query | ||
, p1 = this.resolvedPredicate | ||
, p2 = other.resolvedPredicate | ||
, t1 = this.resolvedType | ||
, t2 = other.resolvedType | ||
, type, pred; | ||
// Stolen from Sass :D | ||
t1 = t1 || t2; | ||
t2 = t2 || t1; | ||
if (('not' == p1) ^ ('not' == p2)) { | ||
if (t1 == t2) return; | ||
type = ('not' == p1) ? t2 : t1; | ||
pred = ('not' == p1) ? p2 : p1; | ||
} else if (('not' == p1) && ('not' == p2)) { | ||
if (t1 != t2) return; | ||
type = t1; | ||
pred = 'not'; | ||
} else if (t1 != t2) { | ||
return; | ||
} else { | ||
type = t1; | ||
pred = p1 || p2; | ||
} | ||
query.predicate = pred; | ||
query.type = type; | ||
query.nodes = this.nodes.concat(other.nodes); | ||
return query; | ||
}; | ||
/** | ||
* Return "<a> and <b> and <c>" | ||
@@ -72,6 +143,12 @@ * | ||
Query.prototype.toString = function(){ | ||
var pred = this.predicate ? this.predicate + ' ' : ''; | ||
return pred + this.nodes.map(function(expr){ | ||
return expr.toString(); | ||
}).join(' and '); | ||
var pred = this.predicate ? this.predicate + ' ' : '' | ||
, type = this.type || '' | ||
, len = this.nodes.length | ||
, str = pred + type; | ||
if (len) { | ||
str += (type && ' and ') + this.nodes.map(function(expr){ | ||
return expr.toString(); | ||
}).join(' and '); | ||
} | ||
return str; | ||
}; | ||
@@ -90,2 +167,3 @@ | ||
predicate: this.predicate, | ||
type: this.type, | ||
nodes: this.nodes, | ||
@@ -92,0 +170,0 @@ lineno: this.lineno, |
@@ -68,2 +68,3 @@ | ||
clone.inherits = this.inherits; | ||
clone.val = this.val; | ||
clone.segments = this.segments.map(function(node){ return node.clone(parent, clone); }); | ||
@@ -85,2 +86,3 @@ return clone; | ||
segments: this.segments, | ||
val: this.val, | ||
lineno: this.lineno, | ||
@@ -87,0 +89,0 @@ filename: this.filename |
@@ -361,3 +361,4 @@ | ||
isPseudoSelector: function(n){ | ||
return ~pseudoSelectors.indexOf(this.lookahead(n).val.name); | ||
var val = this.lookahead(n).val; | ||
return val && ~pseudoSelectors.indexOf(val.name); | ||
}, | ||
@@ -414,2 +415,14 @@ | ||
/** | ||
* Skip the given `tokens`. | ||
* | ||
* @param {Array} tokens | ||
* @api private | ||
*/ | ||
skip: function(tokens) { | ||
while (~tokens.indexOf(this.peek().type)) | ||
this.next(); | ||
}, | ||
/** | ||
* Consume whitespace. | ||
@@ -419,4 +432,3 @@ */ | ||
skipWhitespace: function() { | ||
while (~['space', 'indent', 'outdent', 'newline'].indexOf(this.peek().type)) | ||
this.next(); | ||
this.skip(['space', 'indent', 'outdent', 'newline']); | ||
}, | ||
@@ -492,2 +504,7 @@ | ||
if (':' == this.lookahead(i).type && !this.isPseudoSelector(i + 1) | ||
&& ('indent' == this.lookahead(i + 1).type | ||
|| 'function' == this.lookahead(i + 1).type)) | ||
return false; | ||
if (('=' == this.lookahead(i).type || 'function' == this.lookahead(i).type) | ||
@@ -540,4 +557,4 @@ && '{' == this.lookahead(i + 1).type) | ||
if (this.css) { | ||
if (';' == this.lookahead(i) || | ||
'}' == this.lookahead(i)) | ||
if (';' == this.lookahead(i).type || | ||
'}' == this.lookahead(i - 1).type) | ||
return false; | ||
@@ -607,4 +624,6 @@ } | ||
// if a = 1 { | ||
// @media foo.bar { | ||
case 'expression': | ||
case 'assignment': | ||
case 'media': | ||
return !this.cond; | ||
@@ -806,3 +825,3 @@ } | ||
delim = 'outdent'; | ||
this.expect('indent'); | ||
this.accept('indent'); | ||
} | ||
@@ -995,4 +1014,4 @@ | ||
this.expect('media'); | ||
this.state.push('media'); | ||
var media = new nodes.Media(this.queries()); | ||
this.state.push('media'); | ||
media.block = this.block(media); | ||
@@ -1008,6 +1027,10 @@ this.state.pop(); | ||
queries: function() { | ||
var queries = new nodes.QueryList; | ||
var queries = new nodes.QueryList | ||
, skip = ['comment', 'newline', 'space']; | ||
do { | ||
this.skip(skip); | ||
queries.push(this.query()); | ||
} while(this.accept(',')); | ||
this.skip(skip); | ||
} while (this.accept(',')); | ||
return queries; | ||
@@ -1028,4 +1051,2 @@ }, | ||
this.skipSpacesAndComments(); | ||
// hash values support | ||
@@ -1035,3 +1056,5 @@ if ('ident' == this.peek().type | ||
|| '[' == this.lookahead(2).type)) { | ||
this.cond = true; | ||
expr = this.expression(); | ||
this.cond = false; | ||
query.push(new nodes.QueryExpr(expr.nodes)); | ||
@@ -1046,6 +1069,6 @@ return query; | ||
if (id = this.accept('ident')) { | ||
query.push(new nodes.QueryExpr([id.val])); | ||
query.type = id.val; | ||
query.predicate = pred; | ||
} else { | ||
query.push(new nodes.QueryExpr([pred])); | ||
query.type = pred; | ||
} | ||
@@ -1058,4 +1081,5 @@ this.skipSpacesAndComments(); | ||
do { | ||
this.accept('indent'); | ||
query.push(this.queryExpr()); | ||
} while(this.accept('&&')); | ||
} while (this.accept('&&')); | ||
@@ -1162,4 +1186,3 @@ return query; | ||
keyframes: function() { | ||
var pos | ||
, tok = this.expect('keyframes') | ||
var tok = this.expect('keyframes') | ||
, keyframes; | ||
@@ -1229,2 +1252,4 @@ | ||
return this.expression(); | ||
} else if (this.looksLikeSelector() && this.stateAllowsSelector()) { | ||
return this.selector(); | ||
} | ||
@@ -1630,2 +1655,3 @@ // Assignment []= | ||
do { | ||
this.accept('newline') || this.accept('indent'); | ||
// keyword | ||
@@ -1641,2 +1667,3 @@ if ('ident' == this.peek().type && ':' == this.lookahead(2).type) { | ||
} while (this.accept(',')); | ||
this.accept('outdent'); | ||
@@ -1651,4 +1678,15 @@ return args; | ||
list: function() { | ||
var node = this.expression(); | ||
var node | ||
, indent | ||
, prev; | ||
if (this.inProperty) { | ||
indent = this.accept('indent'); | ||
} | ||
node = this.expression(); | ||
while (this.accept(',')) { | ||
prev = this.lexer.prev; | ||
if (',' == prev.type) { | ||
indent = this.accept('newline') || this.accept('indent'); | ||
} | ||
if (node.isList) { | ||
@@ -1662,2 +1700,6 @@ list.push(this.expression()); | ||
} | ||
if (indent || ('ident' == this.lookahead(2).type | ||
&& ':' == this.lookahead(3).type)) { | ||
this.accept('outdent'); | ||
} | ||
} | ||
@@ -1937,4 +1979,4 @@ return node; | ||
object: function(){ | ||
var id, val; | ||
var obj = new nodes.Object; | ||
var obj = new nodes.Object | ||
, id, val, comma; | ||
this.expect('{'); | ||
@@ -1944,9 +1986,14 @@ this.skipWhitespace(); | ||
while (!this.accept('}')) { | ||
if (this.accept('comment') | ||
|| this.accept('newline')) continue; | ||
if (!comma) this.accept(','); | ||
id = this.accept('ident') || this.accept('string'); | ||
if (!id) this.error('expected "ident" or "string", got {peek}'); | ||
id = id.val.hash; | ||
this.skipSpacesAndComments(); | ||
this.expect(':'); | ||
val = this.expression(); | ||
obj.set(id, val); | ||
this.accept(','); | ||
comma = this.accept(','); | ||
this.skipWhitespace(); | ||
@@ -1974,4 +2021,7 @@ } | ||
var op | ||
, unit | ||
, node; | ||
this.skipSpacesAndComments(); | ||
// Parenthesis | ||
@@ -1983,3 +2033,6 @@ if (this.accept('(')) { | ||
--this.parens; | ||
if (this.accept('%')) expr.push(new nodes.Ident('%')); | ||
// (2 + 3)%, (2 + 3)px etc. | ||
if (unit = this.accept('%') || this.accept('ident')) { | ||
expr.push(new nodes.Ident(unit.val.string || '%')); | ||
} | ||
return expr; | ||
@@ -1986,0 +2039,0 @@ } |
@@ -124,10 +124,5 @@ /*! | ||
case 'unit': | ||
continue; | ||
case 'media': | ||
case 'atrule': | ||
// Prevent double-writing the @media/@font-face declarations when | ||
// nested inside of a function/mixin | ||
if (node.block.parent.scope) { | ||
continue; | ||
} | ||
continue; | ||
default: | ||
@@ -168,3 +163,5 @@ arr.push(this.visit(node)); | ||
case 'literal': | ||
this.buf += this.visit(node) + '\n'; | ||
if (node.css) { | ||
this.buf += this.visit(node) + '\n'; | ||
} | ||
break; | ||
@@ -204,6 +201,7 @@ } | ||
Compiler.prototype.visitMedia = function(media){ | ||
if (!media.hasProperties) return ''; | ||
var val = media.val; | ||
if (!media.hasProperties || !val.nodes.length) return ''; | ||
this.buf += '@media '; | ||
this.visit(media.val); | ||
this.visit(val); | ||
this.buf += this.compress ? '{' : ' {\n'; | ||
@@ -232,4 +230,6 @@ ++this.indents; | ||
Compiler.prototype.visitQuery = function(node){ | ||
var len = node.nodes.length; | ||
if (node.predicate) this.buf += node.predicate + ' '; | ||
for (var i = 0, len = node.nodes.length; i < len; ++i) { | ||
if (node.type) this.buf += node.type + (len ? ' and ' : ''); | ||
for (var i = 0; i < len; ++i) { | ||
this.visit(node.nodes[i]); | ||
@@ -236,0 +236,0 @@ if (len - 1 != i) this.buf += ' and '; |
@@ -26,19 +26,2 @@ | ||
/** | ||
* Clone the block node within the each loop so we don't keep | ||
* extending the same block in multiple contexts | ||
* | ||
* @param {Node} | ||
* @return {Node} | ||
*/ | ||
function cloneNode (node) { | ||
if (node.block && node.block.node) { | ||
node.block.node = node.block.node.clone(); | ||
} | ||
if (node.nodes && node.nodes.length) { | ||
node.nodes.map(cloneNode); | ||
} | ||
return node; | ||
} | ||
/** | ||
* Import `file` and return Block node. | ||
@@ -81,3 +64,3 @@ * | ||
var str = fs.readFileSync(file, 'utf8'); | ||
if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n')); | ||
if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n'), true); | ||
@@ -99,2 +82,3 @@ // parse | ||
block = block.clone(this.root); | ||
block.parent = this.root; | ||
block.scope = false; | ||
@@ -286,3 +270,8 @@ var ret = this.visit(block); | ||
Evaluator.prototype.visitQuery = function(node){ | ||
var val; | ||
node.predicate = this.visit(node.predicate); | ||
node.type = this.visit(node.type); | ||
if (val = this.lookup(node.type)) { | ||
node.type = val.first.string || val.first.name; | ||
} | ||
node.nodes.forEach(this.visit, this); | ||
@@ -298,3 +287,3 @@ return node; | ||
var val; | ||
node.name = node.name || this.interpolate(node); | ||
node.name = this.interpolate(node); | ||
if (node.expr) { | ||
@@ -305,5 +294,2 @@ this.return++; | ||
} | ||
if (val = this.lookup(node.name)) { | ||
node.name = val.first.string || val.first.name; | ||
} | ||
return node; | ||
@@ -398,3 +384,3 @@ }; | ||
this.return++; | ||
var expr = utils.unwrap(this.visit(utils.unwrap(each.expr))) | ||
var expr = utils.unwrap(this.visit(each.expr)) | ||
, len = expr.nodes.length | ||
@@ -413,6 +399,6 @@ , val = new nodes.Ident(each.val) | ||
function visitBody(body) { | ||
body = each.block.clone(); | ||
body.nodes.map(cloneNode); | ||
body = self.visit(body); | ||
function visitBody(key, val) { | ||
scope.add(val); | ||
scope.add(key); | ||
body = self.visit(each.block.clone()); | ||
vals = vals.concat(body.nodes); | ||
@@ -427,5 +413,3 @@ } | ||
key.val = obj.get(prop); | ||
scope.add(val); | ||
scope.add(key); | ||
visitBody(body); | ||
visitBody(key, val); | ||
} | ||
@@ -436,5 +420,3 @@ } else { | ||
key.val = new nodes.Unit(i); | ||
scope.add(val); | ||
scope.add(key); | ||
visitBody(body); | ||
visitBody(key, val); | ||
} | ||
@@ -496,8 +478,6 @@ } | ||
this.return++; | ||
var args = this.visit(call.args) | ||
, mapCopy = {}; | ||
var args = this.visit(call.args); | ||
for (var key in args.map) { | ||
mapCopy[key] = args.map[key]; | ||
args.map[key] = this.visit(mapCopy[key].clone()); | ||
args.map[key] = this.visit(args.map[key].clone()); | ||
} | ||
@@ -518,7 +498,2 @@ this.return--; | ||
// restore kwargs | ||
for (key in mapCopy) { | ||
args.map[key] = mapCopy[key]; | ||
} | ||
this.calling.pop(); | ||
@@ -569,3 +544,4 @@ this.ignoreColors = false; | ||
, left = this.visit(binop.left) | ||
, right = this.visit(binop.right); | ||
, right = ('||' == op || '&&' == op) | ||
? binop.right : this.visit(binop.right); | ||
@@ -665,3 +641,3 @@ // HACK: ternary | ||
, fn = this.lookup(name) | ||
, call = fn && 'function' == fn.nodeName | ||
, call = fn && 'function' == fn.first.nodeName | ||
, literal = ~this.calling.indexOf(name) | ||
@@ -672,5 +648,6 @@ , _prop = this.property; | ||
if (call && !literal && !prop.literal) { | ||
var args = nodes.Arguments.fromExpression(utils.unwrap(prop.expr)); | ||
var args = nodes.Arguments.fromExpression(utils.unwrap(prop.expr.clone())); | ||
prop.name = name; | ||
this.property = prop; | ||
this.property.expr = this.visit(prop.expr); | ||
var ret = this.visit(new nodes.Call(name, args)); | ||
@@ -953,2 +930,3 @@ this.property = _prop; | ||
node.val.preserve = true; | ||
node.val.isList = args.isList; | ||
// argument default support | ||
@@ -1251,2 +1229,4 @@ } else { | ||
while (index--) { | ||
// ignore current property | ||
if (this.property == nodes[index]) continue; | ||
other = this.interpolate(nodes[index]); | ||
@@ -1259,3 +1239,4 @@ if (name == other) return nodes[index].clone(); | ||
while (len--) { | ||
if ('property' != nodes[len].nodeName) continue; | ||
if ('property' != nodes[len].nodeName | ||
|| this.property == nodes[len]) continue; | ||
other = this.interpolate(nodes[len]); | ||
@@ -1262,0 +1243,0 @@ if (name == other) return nodes[len].clone(); |
@@ -59,2 +59,65 @@ | ||
/** | ||
* Bubble up the given `node`. | ||
* | ||
* @param {Node} node | ||
* @api private | ||
*/ | ||
Normalizer.prototype.bubble = function(node){ | ||
var props = [] | ||
, other = [] | ||
, self = this; | ||
function filterProps(block) { | ||
block.nodes.forEach(function(node) { | ||
node = self.visit(node); | ||
switch (node.nodeName) { | ||
case 'property': | ||
props.push(node); | ||
break; | ||
case 'block': | ||
filterProps(node); | ||
break; | ||
default: | ||
other.push(node); | ||
} | ||
}); | ||
} | ||
filterProps(node.block); | ||
if (props.length) { | ||
var selector = new nodes.Selector([new nodes.Literal('&')]) | ||
, parentGroup = node.block.parent.node; | ||
selector.lineno = node.lineno; | ||
selector.filename = node.filename; | ||
selector.val = '&'; | ||
var group = new nodes.Group; | ||
group.lineno = node.lineno; | ||
group.filename = node.filename; | ||
var block = new nodes.Block(node.block, group); | ||
block.lineno = node.lineno; | ||
block.filename = node.filename; | ||
props.forEach(function(prop){ | ||
block.push(prop); | ||
}); | ||
group.push(selector); | ||
group.block = block; | ||
node.block.nodes = []; | ||
node.block.push(group); | ||
other.forEach(function(n){ | ||
node.block.push(n); | ||
}); | ||
node.group = parentGroup.clone(); | ||
node.bubbled = true; | ||
} | ||
}; | ||
/** | ||
* Visit Root. | ||
@@ -139,8 +202,4 @@ */ | ||
for (var k = 0, len = parts.length; k < len; ++k){ | ||
var part = parts[k].trim(); | ||
// Treat parts without `&` as interpolated from the root | ||
if (!~part.indexOf('&') && part.charAt(0) != '/') { | ||
part = '/' + part; | ||
} | ||
var s = new nodes.Selector([part]); | ||
var part = parts[k].trim() | ||
, s = new nodes.Selector([part]); | ||
s.val = part; | ||
@@ -174,19 +233,15 @@ s.block = group.block; | ||
Normalizer.prototype.visitMedia = function(media){ | ||
var props = [] | ||
, other = [] | ||
var medias = [] | ||
, self = this; | ||
function filterProps(block) { | ||
block.nodes.forEach(function(node) { | ||
function mergeQueries(block) { | ||
block.nodes.forEach(function(node, i){ | ||
node = self.visit(node); | ||
switch (node.nodeName) { | ||
case 'property': | ||
props.push(node); | ||
break; | ||
case 'block': | ||
filterProps(node); | ||
break; | ||
default: | ||
other.push(node); | ||
if ('media' == node.nodeName) { | ||
node.val = media.val.merge(node.val); | ||
medias.push(node); | ||
block.nodes[i] = nodes.null; | ||
} else if (node.block) { | ||
mergeQueries(node.block); | ||
} | ||
@@ -196,40 +251,22 @@ }); | ||
filterProps(media.block); | ||
this.bubble(media); | ||
mergeQueries(media.block); | ||
// Fake self-referencing group to contain | ||
// any props that are floating | ||
// directly on the @media declaration | ||
if (props.length) { | ||
var selfLiteral = new nodes.Literal('&'); | ||
selfLiteral.lineno = media.lineno; | ||
selfLiteral.filename = media.filename; | ||
var selfSelector = new nodes.Selector([selfLiteral]); | ||
selfSelector.lineno = media.lineno; | ||
selfSelector.filename = media.filename; | ||
selfSelector.val = selfLiteral.val; | ||
var propertyGroup = new nodes.Group; | ||
propertyGroup.lineno = media.lineno; | ||
propertyGroup.filename = media.filename; | ||
var propertyBlock = new nodes.Block(media.block, propertyGroup); | ||
propertyBlock.lineno = media.lineno; | ||
propertyBlock.filename = media.filename; | ||
props.forEach(function(prop){ | ||
propertyBlock.push(prop); | ||
if (medias.length) { | ||
var block = new nodes.Block(media.block); | ||
block.push(media); | ||
medias.forEach(function(node){ | ||
if (node.bubbled) { | ||
if (!media.block.parent.node) { | ||
node.group.block = node.block.nodes[0].block; | ||
node.block.nodes[0] = node.group; | ||
} | ||
media.block.parent.push(node); | ||
} | ||
block.push(node); | ||
}); | ||
propertyGroup.push(selfSelector); | ||
propertyGroup.block = propertyBlock; | ||
media.block.nodes = []; | ||
media.block.push(propertyGroup); | ||
other.forEach(function(node){ | ||
media.block.push(node); | ||
}); | ||
return block; | ||
} else { | ||
return media; | ||
} | ||
return media; | ||
} | ||
@@ -236,0 +273,0 @@ |
{ | ||
"name": "stylus", | ||
"description": "Robust, expressive, and feature-rich CSS superset", | ||
"version": "0.45.1", | ||
"version": "0.46.0", | ||
"author": "TJ Holowaychuk <tj@vision-media.ca>", | ||
@@ -36,3 +36,3 @@ "keywords": [ | ||
"devDependencies": { | ||
"should": "*", | ||
"should": "2.x", | ||
"mocha": "*", | ||
@@ -39,0 +39,0 @@ "jscoverage": "0.3.8" |
@@ -8,3 +8,3 @@ # Stylus [![Build Status](https://travis-ci.org/LearnBoost/stylus.svg?branch=master)](https://travis-ci.org/LearnBoost/stylus) | ||
```bash | ||
$ npm install stylus | ||
$ npm install stylus -g | ||
``` | ||
@@ -11,0 +11,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
309015
11853