Comparing version 0.41.3 to 0.42.0
@@ -27,6 +27,5 @@ /*! | ||
function Converter(css) { | ||
var cssom = require('cssom'); | ||
var parse = require('css-parse'); | ||
this.css = css; | ||
this.types = cssom.CSSRule; | ||
this.root = cssom.parse(css); | ||
this.root = parse(css, { position: false }); | ||
this.indents = 0; | ||
@@ -43,3 +42,3 @@ } | ||
Converter.prototype.stylus = function(){ | ||
return this.visitRules(this.root.cssRules); | ||
return this.visitRules(this.root.stylesheet.rules); | ||
}; | ||
@@ -61,3 +60,3 @@ | ||
* | ||
* @param {CSSRule} node | ||
* @param {*} node | ||
* @return {String} | ||
@@ -69,6 +68,12 @@ * @api private | ||
switch (node.type) { | ||
case this.types.STYLE_RULE: | ||
return this.visitStyle(node); | ||
case this.types.MEDIA_RULE: | ||
return this.visitMedia(node); | ||
case 'rule': | ||
case 'comment': | ||
case 'charset': | ||
case 'media': | ||
case 'import': | ||
case 'document': | ||
case 'keyframes': | ||
case 'page': | ||
var name = node.type[0].toUpperCase() + node.type.slice(1); | ||
return this['visit' + name](node); | ||
} | ||
@@ -80,3 +85,3 @@ }; | ||
* | ||
* @param {CSSRule} node | ||
* @param {Array} node | ||
* @return {String} | ||
@@ -95,5 +100,5 @@ * @api private | ||
/** | ||
* Visit CSSMediaRule `node`. | ||
* Visit Media `node`. | ||
* | ||
* @param {CSSMediaRule} node | ||
* @param {Media} node | ||
* @return {String} | ||
@@ -104,9 +109,97 @@ * @api private | ||
Converter.prototype.visitMedia = function(node){ | ||
var buf = this.indent + '@media '; | ||
for (var i = 0, len = node.media.length; i < len; ++i) { | ||
buf += node.media[i]; | ||
var buf = this.indent + '@media ' + node.media; | ||
buf += '\n'; | ||
++this.indents; | ||
buf += this.visitRules(node.rules); | ||
--this.indents; | ||
return buf; | ||
}; | ||
/** | ||
* Visit Declaration `node`. | ||
* | ||
* @param {Declaration} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitDeclaration = function(node){ | ||
if ('comment' == node.type) { | ||
return this.visitComment(node); | ||
} else { | ||
var buf = this.indent + node.property + ': ' + node.value + '\n'; | ||
return buf; | ||
} | ||
}; | ||
/** | ||
* Visit Rule `node`.` | ||
* | ||
* @param {Rule} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitRule = function(node){ | ||
var buf = this.indent + node.selectors.join(',\n') + '\n'; | ||
++this.indents; | ||
for (var i = 0, len = node.declarations.length; i < len; ++i) { | ||
buf += this.visitDeclaration(node.declarations[i]); | ||
} | ||
--this.indents; | ||
return buf + '\n'; | ||
}; | ||
/** | ||
* Visit Comment `node`.` | ||
* | ||
* @param {Comment} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitComment = function(node){ | ||
var buf = this.indent + '/*' + node.comment + '*/'; | ||
return buf + '\n'; | ||
}; | ||
/** | ||
* Visit Charset `node`.` | ||
* | ||
* @param {Charset} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitCharset = function(node){ | ||
var buf = this.indent + '@charset ' + node.charset; | ||
return buf + '\n'; | ||
}; | ||
/** | ||
* Visit Import `node`.` | ||
* | ||
* @param {Import} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitImport = function(node){ | ||
var buf = this.indent + '@import ' + node.import; | ||
return buf + '\n'; | ||
}; | ||
/** | ||
* Visit Document `node`.` | ||
* | ||
* @param {Document} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitDocument = function(node){ | ||
var buf = this.indent + '@' + node.vendor + 'document ' + node.document; | ||
buf += '\n'; | ||
++this.indents; | ||
buf += this.visitRules(node.cssRules); | ||
buf += this.visitRules(node.rules); | ||
--this.indents; | ||
@@ -117,5 +210,5 @@ return buf; | ||
/** | ||
* Visit CSSStyleRule `node`.` | ||
* Visit Keyframes `node`.` | ||
* | ||
* @param {CSSStyleRule} node | ||
* @param {Keyframes} node | ||
* @return {String} | ||
@@ -125,15 +218,49 @@ * @api private | ||
Converter.prototype.visitStyle = function(node){ | ||
var buf = this.indent + node.selectorText + '\n'; | ||
Converter.prototype.visitKeyframes = function(node){ | ||
var buf = this.indent + '@keyframes ' + node.name; | ||
buf += '\n'; | ||
++this.indents; | ||
for (var i = 0, len = node.style.length; i < len; ++i) { | ||
var prop = node.style[i] | ||
, val = node.style[prop] | ||
, importance = node.style['_importants'][prop] ? ' !important' : ''; | ||
if (prop) { | ||
buf += this.indent + prop + ': ' + val + importance + '\n'; | ||
} | ||
for (var i = 0, len = node.keyframes.length; i < len; ++i) { | ||
buf += this.visitKeyframe(node.keyframes[i]); | ||
} | ||
--this.indents; | ||
return buf + '\n'; | ||
}; | ||
return buf; | ||
}; | ||
/** | ||
* Visit Keyframe `node`.` | ||
* | ||
* @param {Keyframe} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitKeyframe = function(node){ | ||
var buf = this.indent + node.values.join('\n,'); | ||
buf += '\n'; | ||
++this.indents; | ||
for (var i = 0, len = node.declarations.length; i < len; ++i) { | ||
buf += this.visitDeclaration(node.declarations[i]); | ||
} | ||
--this.indents; | ||
return buf; | ||
}; | ||
/** | ||
* Visit Page `node`.` | ||
* | ||
* @param {Page} node | ||
* @return {String} | ||
* @api private | ||
*/ | ||
Converter.prototype.visitPage = function(node){ | ||
var buf = this.indent + '@page' + (node.selectors.length ? ' ' + node.selectors.join(', ') : ''); | ||
buf += '\n'; | ||
++this.indents; | ||
for (var i = 0, len = node.declarations.length; i < len; ++i) { | ||
buf += this.visitDeclaration(node.declarations[i]); | ||
} | ||
--this.indents; | ||
return buf; | ||
}; |
@@ -494,9 +494,14 @@ | ||
exports.use = function(plugin){ | ||
utils.assertString(plugin, 'path'); | ||
exports.use = function(plugin, options){ | ||
utils.assertString(plugin, 'plugin'); | ||
if (options) { | ||
utils.assertType(options, 'object', 'options'); | ||
options = parseObject(options); | ||
} | ||
// lookup | ||
plugin = plugin.string; | ||
var found = utils.lookup(plugin, this.options.paths, this.options.filename); | ||
if (!found) throw new Error('failed to locate plugin file ' + plugin); | ||
if (!found) throw new Error('failed to locate plugin file "' + plugin + '"'); | ||
@@ -506,5 +511,5 @@ // use | ||
if ('function' != typeof fn) { | ||
throw new Error('plugin ' + path + ' does not export a function'); | ||
throw new Error('plugin "' + plugin + '" does not export a function'); | ||
} | ||
this.renderer.use(fn(this.options)); | ||
this.renderer.use(fn(options || this.options)); | ||
} | ||
@@ -1085,4 +1090,5 @@ | ||
/** | ||
* Return the current selector. | ||
* Return the current selector or compile `sel` selector. | ||
* | ||
* @param {String} [sel] | ||
* @return {String} | ||
@@ -1092,4 +1098,14 @@ * @api public | ||
exports.selector = function selector(){ | ||
return this.currentSelector; | ||
exports.selector = function selector(sel){ | ||
var stack = this.selectorStack | ||
, group; | ||
if (sel && 'string' == sel.nodeName) { | ||
if (!~sel.val.indexOf('&') && '/' !== sel.val.charAt(0)) return sel.val; | ||
group = new nodes.Group; | ||
sel = new nodes.Selector([sel.val]); | ||
sel.val = sel.segments.join(''); | ||
group.push(sel); | ||
stack.push(group.nodes); | ||
} | ||
return stack.length ? utils.compileSelectors(stack).join(',') : '&'; | ||
}; | ||
@@ -1155,1 +1171,41 @@ | ||
} | ||
/** | ||
* Attempt to parse object node to the javascript object. | ||
* | ||
* @param {Object} obj | ||
* @return {Object} | ||
* @api private | ||
*/ | ||
function parseObject(obj){ | ||
obj = obj.vals; | ||
for (var key in obj) { | ||
var nodes = obj[key].nodes[0].nodes; | ||
if (nodes && nodes.length) { | ||
obj[key] = []; | ||
for (var i = 0, len = nodes.length; i < len; ++i) { | ||
obj[key].push(convert(nodes[i])); | ||
} | ||
} else { | ||
obj[key] = convert(obj[key].first); | ||
} | ||
} | ||
return obj; | ||
function convert(node){ | ||
switch (node.nodeName) { | ||
case 'object': | ||
return parseObject(node); | ||
case 'boolean': | ||
return node.isTrue; | ||
case 'unit': | ||
return node.type ? node.toString() : +node.val; | ||
case 'string': | ||
case 'literal': | ||
return node.val; | ||
default: | ||
return node.toString(); | ||
} | ||
} | ||
} |
@@ -203,2 +203,3 @@ | ||
|| this.boolean() | ||
|| this.atblock() | ||
|| this.ident() | ||
@@ -520,2 +521,14 @@ || this.op() | ||
/** | ||
* '@block' | ||
*/ | ||
atblock: function() { | ||
var captures; | ||
if (captures = /^@block[ \t]*/.exec(this.str)) { | ||
this.skip(captures); | ||
return new Token('atblock'); | ||
} | ||
}, | ||
/** | ||
* '@scope' ([^{\n]+) | ||
@@ -533,3 +546,3 @@ */ | ||
/** | ||
* '@' ('import' | 'keyframes' | 'charset' | 'page' | 'font-face') | ||
* '@' ('import' | 'require' | 'keyframes' | 'charset' | 'page' | 'font-face') | ||
*/ | ||
@@ -539,3 +552,3 @@ | ||
var captures; | ||
if (captures = /^@(import|(?:-(\w+)-)?keyframes|charset|font-face|page)[ \t]*/.exec(this.str)) { | ||
if (captures = /^@(import|require|(?:-(\w+)-)?keyframes|charset|font-face|page)[ \t]*/.exec(this.str)) { | ||
this.skip(captures); | ||
@@ -542,0 +555,0 @@ var vendor = captures[2] |
@@ -51,3 +51,3 @@ | ||
/** | ||
* Check if this block has bubbling nodes. | ||
* Check if this block has @media nodes. | ||
* | ||
@@ -58,6 +58,6 @@ * @return {Boolean} | ||
Block.prototype.__defineGetter__('hasBubbling', function(){ | ||
Block.prototype.__defineGetter__('hasMedia', function(){ | ||
for (var i = 0, len = this.nodes.length; i < len; ++i) { | ||
var nodeName = this.nodes[i].nodeName; | ||
if ('media' == nodeName || 'fontface' == nodeName) { | ||
if ('media' == nodeName) { | ||
return true; | ||
@@ -64,0 +64,0 @@ } |
@@ -21,5 +21,6 @@ | ||
var Import = module.exports = function Import(expr){ | ||
var Import = module.exports = function Import(expr, once){ | ||
Node.call(this); | ||
this.path = expr; | ||
this.once = once || false; | ||
}; | ||
@@ -41,3 +42,3 @@ | ||
Import.prototype.clone = function(){ | ||
var clone = new Import(this.path.clone()); | ||
var clone = new Import(this.path.clone(), this.once); | ||
clone.lineno = this.lineno; | ||
@@ -44,0 +45,0 @@ clone.filename = this.filename; |
@@ -49,2 +49,3 @@ | ||
exports.MozDocument = require('./mozdocument'); | ||
exports.Atblock = require('./atblock'); | ||
@@ -51,0 +52,0 @@ /** |
@@ -194,3 +194,3 @@ | ||
RGBA.prototype.operate = function(op, right){ | ||
right = right.first; | ||
if ('in' != op) right = right.first | ||
@@ -197,0 +197,0 @@ switch (op) { |
@@ -58,2 +58,3 @@ | ||
, '.' | ||
, '/' | ||
]; | ||
@@ -396,5 +397,2 @@ | ||
if ('=' == this.lookahead(i).type && this.bracketed) | ||
return true; | ||
if (this.looksLikeAttributeSelector(i)) | ||
@@ -476,2 +474,3 @@ return true; | ||
var type = this.lookahead(n).type; | ||
if ('=' == type && this.bracketed) return true; | ||
return ('ident' == type || 'string' == type) | ||
@@ -509,2 +508,3 @@ && ']' == this.lookahead(n + 1).type | ||
case 'root': | ||
case 'atblock': | ||
case 'selector': | ||
@@ -523,2 +523,17 @@ case 'conditional': | ||
/** | ||
* Try to assign @block to the node. | ||
* | ||
* @param {Expression} expr | ||
* @private | ||
*/ | ||
assignAtblock: function(expr) { | ||
try { | ||
expr.push(this.atblock(expr)); | ||
} catch(err) { | ||
this.error('invalid right-hand side operand in assignment, got {peek}'); | ||
} | ||
}, | ||
/** | ||
* statement | ||
@@ -584,2 +599,3 @@ * | statement 'if' expression | ||
* | import | ||
* | require | ||
* | media | ||
@@ -612,2 +628,3 @@ * | scope | ||
case 'import': | ||
case 'require': | ||
case 'extend': | ||
@@ -639,2 +656,3 @@ case 'media': | ||
case '.': | ||
case '/': | ||
return this.selector(); | ||
@@ -797,2 +815,17 @@ case '+': | ||
/** | ||
* @block | ||
* | ||
* @param {Expression} [node] | ||
*/ | ||
atblock: function(node){ | ||
if (!node) this.expect('atblock'); | ||
node = new nodes.Atblock; | ||
this.state.push('atblock'); | ||
node.block = this.block(node, false); | ||
this.state.pop(); | ||
return node; | ||
}, | ||
/** | ||
* scope | ||
@@ -866,6 +899,16 @@ */ | ||
this.allowPostfix = true; | ||
return new nodes.Import(this.expression()); | ||
return new nodes.Import(this.expression(), false); | ||
}, | ||
/** | ||
* require expression | ||
*/ | ||
require: function() { | ||
this.expect('require'); | ||
this.allowPostfix = true; | ||
return new nodes.Import(this.expression(), true); | ||
}, | ||
/** | ||
* charset string | ||
@@ -1066,2 +1109,3 @@ */ | ||
case '-moz-document': | ||
case 'atblock': | ||
case 'font-face': | ||
@@ -1096,2 +1140,3 @@ return '[' == la | ||
case 'conditional': | ||
case 'atblock': | ||
return this.property(); | ||
@@ -1258,3 +1303,4 @@ default: | ||
var expr = this.list(); | ||
if (expr.isEmpty) this.error('invalid right-hand side operand in assignment, got {peek}') | ||
// @block support | ||
if (expr.isEmpty) this.assignAtblock(expr); | ||
node = new nodes.Ident(name, expr); | ||
@@ -1335,8 +1381,7 @@ this.state.pop(); | ||
/** | ||
* ident '(' expression ')' | ||
* '+'? ident '(' expression ')' | ||
*/ | ||
functionCall: function() { | ||
var withBlock = false; | ||
if (this.accept('+')) withBlock = true; | ||
var withBlock = this.accept('+'); | ||
if ('url' == this.peek().val.name) return this.url(); | ||
@@ -1685,2 +1730,4 @@ var name = this.expect('function').val.name; | ||
node.val = this.expression(); | ||
// @block support | ||
if (node.val.isEmpty) this.assignAtblock(node.val); | ||
} | ||
@@ -1704,3 +1751,7 @@ } | ||
this.skipSpaces(); | ||
if (this.accept('=')) node.val = this.expression(); | ||
if (this.accept('=')) { | ||
node.val = this.expression(); | ||
// @block support | ||
if (node.val.isEmpty) this.assignAtblock(node.val); | ||
} | ||
} | ||
@@ -1744,2 +1795,3 @@ return node; | ||
* | object | ||
* | atblock | ||
* | '(' expression ')' '%'? | ||
@@ -1771,5 +1823,6 @@ */ | ||
return this.next().val; | ||
case '{': | ||
if (this.stateAllowsObject()) return this.object(); | ||
return; | ||
case this.stateAllowsObject() && '{': | ||
return this.object(); | ||
case 'atblock': | ||
return this.atblock(); | ||
case 'ident': | ||
@@ -1776,0 +1829,0 @@ return this.ident(); |
@@ -91,8 +91,3 @@ | ||
if (frame && (val = frame.lookup(name))) { | ||
switch (val.first.nodeName) { | ||
case 'ident': | ||
return this.lookup(val.first.name) || val; | ||
default: | ||
return val; | ||
} | ||
return val; | ||
} | ||
@@ -147,2 +142,2 @@ } while (block = block.parent); | ||
return buf.join('\n'); | ||
}; | ||
}; |
@@ -15,2 +15,3 @@ | ||
, resolve = require('path').resolve | ||
, glob = require('glob') | ||
, fs = require('fs'); | ||
@@ -26,5 +27,5 @@ | ||
exports.absolute = function(path){ | ||
exports.absolute = function(path){ | ||
// On Windows the path could start with a drive letter, i.e. a:\\ or two leading backslashes | ||
return path.substr(0, 2) == '\\\\' || path[0] == '/' || /^[a-z]:\\/i.test(path); | ||
return path.substr(0, 2) == '\\\\' || '/' === path.charAt(0) || /^[a-z]:\\/i.test(path); | ||
}; | ||
@@ -76,2 +77,33 @@ | ||
/** | ||
* Like `utils.lookup` but uses `glob` to find files. | ||
* | ||
* @param {String} path | ||
* @param {String} paths | ||
* @param {String} ignore | ||
* @return {Array} | ||
* @api private | ||
*/ | ||
exports.find = function(path, paths, ignore) { | ||
var lookup | ||
, found | ||
, i = paths.length; | ||
// Absolute | ||
if (exports.absolute(path)) { | ||
if ((found = glob.sync(path)).length) { | ||
return found; | ||
} | ||
} | ||
// Relative | ||
while (i--) { | ||
lookup = join(paths[i], path); | ||
if (ignore == lookup) continue; | ||
if ((found = glob.sync(lookup)).length) { | ||
return found; | ||
} | ||
} | ||
}; | ||
/** | ||
* Format the given `err` with the given `options`. | ||
@@ -337,10 +369,10 @@ * | ||
, buf = [] | ||
, hiddenSelectorRegexp = /^\s*\$/; | ||
, hiddenSelectorRegexp = /^\s*\/?\$/; | ||
function interpolateParent(selector, buf) { | ||
var str = selector.val.trim(); | ||
var str = selector.val.replace(/^\//g, '').trim(); | ||
if (buf.length) { | ||
for (var i = 0, len = buf.length; i < len; ++i) { | ||
if (~buf[i].indexOf('&')) { | ||
str = buf[i].replace(/&/g, str).trim(); | ||
if (~buf[i].indexOf('&') || '/' === buf[i].charAt(0)) { | ||
str = buf[i].replace(/&/g, str).replace(/^\//g, '').trim(); | ||
} else { | ||
@@ -351,3 +383,3 @@ str += ' ' + buf[i].trim(); | ||
} | ||
return str; | ||
return str.trim(); | ||
} | ||
@@ -380,3 +412,6 @@ | ||
return selectors; | ||
// Return the list with unique selectors only | ||
return selectors.filter(function(value, index, self){ | ||
return self.indexOf(value) === index; | ||
}); | ||
}; |
@@ -20,3 +20,5 @@ | ||
, bifs = require('../functions') | ||
, basename = require('path').basename | ||
, dirname = require('path').dirname | ||
, relative = require('path').relative | ||
, join = require('path').join | ||
@@ -45,2 +47,66 @@ , colors = require('../colors') | ||
/** | ||
* Import `file` and return Block node. | ||
* | ||
* @api private | ||
*/ | ||
function importFile(node, file, literal, index) { | ||
var importStack = this.importStack | ||
, Parser = require('../parser'); | ||
// Handling the `require` | ||
if (node.once) { | ||
if (this.requireHistory[file]) return nodes.null; | ||
this.requireHistory[file] = true; | ||
if (literal && !this.includeCSS) { | ||
return node; | ||
} | ||
} | ||
// Expose imports | ||
node.path = file; | ||
node.dirname = dirname(file); | ||
// Store the modified time | ||
fs.stat(file, function(err, stat){ | ||
if (err) return; | ||
node.mtime = stat.mtime; | ||
}); | ||
this.paths.push(node.dirname); | ||
// Avoid overflows from importing the same file over again | ||
if (file === importStack[importStack.length - 1]) return nodes.null; | ||
if (this.options._imports) this.options._imports.push(node); | ||
// Parse the file | ||
importStack.push(file); | ||
nodes.filename = file; | ||
var str = fs.readFileSync(file, 'utf8'); | ||
if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, '\n')); | ||
// parse | ||
var block = new nodes.Block | ||
, parser = new Parser(str, utils.merge({ root: block }, this.options)); | ||
try { | ||
block = parser.parse(); | ||
} catch (err) { | ||
err.filename = file; | ||
err.lineno = parser.lexer.lineno; | ||
err.input = str; | ||
throw err; | ||
} | ||
// Evaluate imported "root" | ||
block.parent = this.root; | ||
block.scope = false; | ||
var ret = this.visit(block); | ||
importStack.pop(); | ||
if (importStack.length || index) this.paths.pop(); | ||
return ret; | ||
} | ||
/** | ||
* Initialize a new `Evaluator` with the given `root` Node | ||
@@ -75,2 +141,3 @@ * and the following `options`. | ||
this.importStack = []; | ||
this.requireHistory = {}; | ||
this.return = 0; | ||
@@ -175,2 +242,40 @@ }; | ||
/** | ||
* Lookup index file for @import. | ||
* | ||
* @param {String} name | ||
* @return {Array} | ||
* @api private | ||
*/ | ||
Evaluator.prototype.lookupIndex = function(name){ | ||
// foo/index.styl | ||
var found = utils.find(join(name, 'index.styl'), this.paths, this.filename) | ||
, self = this | ||
, dir = dirname(this.filename); | ||
if (!found) { | ||
// foo/foo.styl | ||
found = utils.find(join(name, basename(name).replace(/\.styl/i, '') + '.styl'), this.paths, this.filename); | ||
} | ||
if (!found && !~name.indexOf('node_modules')) { | ||
// node_modules/foo/.. or node_modules/foo.styl/.. | ||
found = lookupPackage(join('node_modules', name)); | ||
} | ||
return found; | ||
function lookupPackage(dir) { | ||
var package = utils.lookup(join(dir, 'package.json'), self.paths, self.filename); | ||
if (!package) { | ||
return /\.styl$/i.test(dir) ? self.lookupIndex(dir) : lookupPackage(dir + '.styl'); | ||
} | ||
var main = require(relative(__dirname, package)).main; | ||
if (main) { | ||
found = utils.find(join(dir, main), self.paths, self.filename); | ||
} else { | ||
found = self.lookupIndex(dir); | ||
} | ||
return found; | ||
} | ||
}; | ||
/** | ||
* Visit Group. | ||
@@ -433,2 +538,4 @@ */ | ||
debug('%s is user-defined', call); | ||
// Evaluate mixin block | ||
if (call.block) call.block = this.visit(call.block); | ||
ret = this.invokeFunction(fn, args, call.block); | ||
@@ -646,2 +753,11 @@ } | ||
/** | ||
* Visit Atblock. | ||
*/ | ||
Evaluator.prototype.visitAtblock = function(atblock){ | ||
atblock.block = this.visit(atblock.block); | ||
return atblock; | ||
}; | ||
/** | ||
* Visit If. | ||
@@ -659,2 +775,4 @@ */ | ||
node.block.scope = node.block.hasMedia; | ||
// Evaluate body | ||
@@ -678,2 +796,3 @@ if (negate) { | ||
if (elses[i].cond) { | ||
elses[i].block.scope = elses[i].block.hasMedia; | ||
this.return++; | ||
@@ -688,2 +807,3 @@ cond = this.visit(elses[i].cond).first.toBoolean(); | ||
} else { | ||
elses[i].scope = elses[i].hasMedia; | ||
ret = this.visit(elses[i]); | ||
@@ -715,5 +835,3 @@ } | ||
var block = this.currentBlock; | ||
if ('group' != block.node.nodeName) { | ||
block = this.targetBlock && this.targetBlock.node.extends ? this.targetBlock : this.closestGroup; | ||
} | ||
if ('group' != block.node.nodeName) block = this.closestGroup; | ||
block.node.extends.push(selector); | ||
@@ -730,7 +848,4 @@ return nodes.null; | ||
var root = this.root | ||
, Parser = require('../parser') | ||
, path = this.visit(imported.path).first | ||
, includeCSS = this.includeCSS | ||
, importStack = this.importStack | ||
var path = this.visit(imported.path).first | ||
, nodeName = imported.once ? 'require' : 'import' | ||
, found | ||
@@ -744,6 +859,11 @@ , literal | ||
// url() passed | ||
if ('url' == path.name) return imported; | ||
if ('url' == path.name) { | ||
if (imported.once) throw new Error('You cannot @require a url'); | ||
return imported; | ||
} | ||
// Ensure string | ||
if (!path.string) throw new Error('@import string expected'); | ||
if (!path.string) throw new Error('@' + nodeName + ' string expected'); | ||
var name = path = path.string; | ||
@@ -753,2 +873,3 @@ | ||
if (/url\s*\(\s*['"]?(?:https?:)?\/\//i.test(path)) { | ||
if (imported.once) throw new Error('You cannot @require a url'); | ||
return imported; | ||
@@ -760,3 +881,5 @@ } | ||
literal = true; | ||
if (!includeCSS) return imported; | ||
if (!imported.once && !this.includeCSS) { | ||
return imported; | ||
} | ||
} | ||
@@ -768,5 +891,5 @@ | ||
// Lookup | ||
found = utils.lookup(path, this.paths, this.filename); | ||
found = utils.find(path, this.paths, this.filename); | ||
if (!found) { | ||
found = utils.lookup(join(name, 'index.styl'), this.paths, this.filename); | ||
found = this.lookupIndex(name); | ||
index = true; | ||
@@ -776,44 +899,11 @@ } | ||
// Throw if import failed | ||
if (!found) throw new Error('failed to locate @import file ' + path); | ||
if (!found) throw new Error('failed to locate @' + nodeName + ' file ' + path); | ||
var block = new nodes.Block; | ||
// Expose imports | ||
imported.path = found; | ||
imported.dirname = dirname(found); | ||
// Store the modified time | ||
fs.stat(found, function(err, stat){ | ||
if (err) return; | ||
imported.mtime = stat.mtime; | ||
}); | ||
this.paths.push(imported.dirname); | ||
if (this.options._imports) this.options._imports.push(imported); | ||
// Parse the file | ||
importStack.push(found); | ||
nodes.filename = found; | ||
var str = fs.readFileSync(found, 'utf8'); | ||
if (literal && !this.resolveURL) return new nodes.Literal(str.replace(/\r\n?/g, "\n")); | ||
// parse | ||
var block = new nodes.Block | ||
, parser = new Parser(str, utils.merge({ root: block }, this.options)); | ||
try { | ||
block = parser.parse(); | ||
} catch (err) { | ||
err.filename = found; | ||
err.lineno = parser.lexer.lineno; | ||
err.input = str; | ||
throw err; | ||
for (var i = 0, len = found.length; i < len; ++i) { | ||
block.push(importFile.call(this, imported, found[i], literal, index)); | ||
} | ||
// Evaluate imported "root" | ||
block.parent = root; | ||
block.scope = false; | ||
var ret = this.visit(block); | ||
importStack.pop(); | ||
if (importStack.length || index) this.paths.pop(); | ||
return ret; | ||
return block; | ||
}; | ||
@@ -837,3 +927,3 @@ | ||
var body = fn.block.clone(); | ||
body.scope = fn.block.hasBubbling; | ||
body.scope = fn.block.hasMedia; | ||
@@ -957,4 +1047,2 @@ // mixin block | ||
} else { | ||
var targetFrame = this.stack[this.stack.length - 2]; | ||
if (targetFrame) this.targetBlock = targetFrame.block; | ||
body = this.visit(body); | ||
@@ -1020,9 +1108,10 @@ if (stack) this.stack.pop(); | ||
node = this.visit(node.first); | ||
var name = node.nodeName; | ||
if ('object' == name || 'block' == name) { | ||
'block' == name | ||
? this.mixin(node.nodes, this.currentBlock) | ||
// HACK | ||
: this.mixinObject(node); | ||
return nodes.null; | ||
switch (node.nodeName) { | ||
case 'object': | ||
this.mixinObject(node); | ||
return nodes.null; | ||
case 'block': | ||
case 'atblock': | ||
this.mixin(node.nodes, this.currentBlock); | ||
return nodes.null; | ||
} | ||
@@ -1041,3 +1130,3 @@ }; | ||
, root = this.root | ||
, str = '@block ' + object.toBlock() | ||
, str = '$block ' + object.toBlock() | ||
, parser = new Parser(str, utils.merge({ root: block }, this.options)) | ||
@@ -1148,2 +1237,3 @@ , block; | ||
case 'fontface': | ||
case 'media': | ||
case 'page': | ||
@@ -1215,9 +1305,9 @@ nodes = block.nodes; | ||
/** | ||
* Return the current selector. | ||
* Return the current selectors stack. | ||
* | ||
* @return {String} | ||
* @return {Array} | ||
* @api private | ||
*/ | ||
Evaluator.prototype.__defineGetter__('currentSelector', function(){ | ||
Evaluator.prototype.__defineGetter__('selectorStack', function(){ | ||
var block | ||
@@ -1234,3 +1324,3 @@ , stack = []; | ||
} | ||
return stack.length ? utils.compileSelectors(stack).join(',') : '&'; | ||
return stack; | ||
}); | ||
@@ -1237,0 +1327,0 @@ |
@@ -72,2 +72,3 @@ | ||
case 'unit': | ||
case 'atblock': | ||
continue; | ||
@@ -101,2 +102,3 @@ default: | ||
case 'unit': | ||
case 'atblock': | ||
continue; | ||
@@ -103,0 +105,0 @@ default: |
{ | ||
"name": "stylus", | ||
"description": "Robust, expressive, and feature-rich CSS superset", | ||
"version": "0.41.3", | ||
"version": "0.42.0", | ||
"author": "TJ Holowaychuk <tj@vision-media.ca>", | ||
@@ -28,6 +28,7 @@ "keywords": [ | ||
"dependencies": { | ||
"cssom": "0.2.x", | ||
"css-parse": "1.7.x", | ||
"mkdirp": "0.3.x", | ||
"debug": "*", | ||
"sax": "0.5.x" | ||
"sax": "0.5.x", | ||
"glob": "3.2.x" | ||
}, | ||
@@ -34,0 +35,0 @@ "devDependencies": { |
Sorry, the diff of this file is not supported yet
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
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
267543
69
10166
5
14
+ Addedcss-parse@1.7.x
+ Addedglob@3.2.x
+ Addedcss-parse@1.7.0(transitive)
+ Addedglob@3.2.11(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedlru-cache@2.7.3(transitive)
+ Addedminimatch@0.3.0(transitive)
+ Addedsigmund@1.0.1(transitive)
- Removedcssom@0.2.x
- Removedcssom@0.2.5(transitive)