Skip to content

Commit

Permalink
Fixing import by reference
Browse files Browse the repository at this point in the history
- refactored how import reference works
- refactored to-css-visitor (this is side product, it was getting
  complicated)
- fixes issues less#1851, less#1896, less#1878, less#2716, less#1968, less#2162 (same as less#1896)
  • Loading branch information
meri committed Nov 20, 2015
1 parent 73e79b0 commit ead3e29
Show file tree
Hide file tree
Showing 30 changed files with 495 additions and 251 deletions.
1 change: 0 additions & 1 deletion lib/less/contexts.js
Expand Up @@ -30,7 +30,6 @@ var parseCopyProperties = [
// context
'processImports', // option & context - whether to process imports. if false then imports will not be imported.
// Used by the import manager to stop multiple import visitors being created.
'reference', // Used to indicate that the contents are imported by reference
'pluginManager' // Used as the plugin manager for the session
];

Expand Down
5 changes: 2 additions & 3 deletions lib/less/parser/parser.js
Expand Up @@ -35,7 +35,7 @@ var LessError = require('../less-error'),
// Token matching is done with the `$` function, which either takes
// a terminal string or regexp, or a non-terminal function to call.
// It also takes care of moving all the indices forwards.
//
//`
//
var Parser = function Parser(context, imports, fileInfo) {
var parsers,
Expand Down Expand Up @@ -603,7 +603,7 @@ var Parser = function Parser(context, imports, fileInfo) {
if (!elements) {
error("Missing target selector for :extend().");
}
extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
extend = new(tree.Extend)(new(tree.Selector)(elements), option, index, fileInfo);
if (extendList) {
extendList.push(extend);
} else {
Expand Down Expand Up @@ -1474,7 +1474,6 @@ var Parser = function Parser(context, imports, fileInfo) {
parserInput.forget();
return new (tree.Directive)(name, value, rules, index, fileInfo,
context.dumpLineNumbers ? getDebugInfo(index) : null,
false,
isRooted
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/less/transform-tree.js
Expand Up @@ -39,6 +39,7 @@ module.exports = function(root, options) {
var preEvalVisitors = [],
visitors = [
new visitor.JoinSelectorVisitor(),
new visitor.MarkVisibleSelectorsVisitor(true),
new visitor.ExtendVisitor(),
new visitor.ToCSSVisitor({compress: Boolean(options.compress)})
], i;
Expand Down
14 changes: 4 additions & 10 deletions lib/less/tree/anonymous.js
@@ -1,17 +1,18 @@
var Node = require("./node");

var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, referenced) {
var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) {
this.value = value;
this.index = index;
this.mapLines = mapLines;
this.currentFileInfo = currentFileInfo;
this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
this.isReferenced = referenced || false;

this.copyVisibilityInfo(visibilityInfo);
};
Anonymous.prototype = new Node();
Anonymous.prototype.type = "Anonymous";
Anonymous.prototype.eval = function () {
return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.isReferenced);
return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo());
};
Anonymous.prototype.compare = function (other) {
return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
Expand All @@ -22,11 +23,4 @@ Anonymous.prototype.isRulesetLike = function() {
Anonymous.prototype.genCSS = function (context, output) {
output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
};
Anonymous.prototype.markReferenced = function () {
this.isReferenced = true;
};
Anonymous.prototype.getIsReferenced = function () {
return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
};

module.exports = Anonymous;
8 changes: 2 additions & 6 deletions lib/less/tree/comment.js
Expand Up @@ -15,11 +15,7 @@ Comment.prototype.genCSS = function (context, output) {
output.add(this.value);
};
Comment.prototype.isSilent = function(context) {
var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced),
isCompressed = context.compress && this.value[2] !== "!";
return this.isLineComment || isReference || isCompressed;
};
Comment.prototype.markReferenced = function () {
this.isReferenced = true;
var isCompressed = context.compress && this.value[2] !== "!";
return this.isLineComment || isCompressed;
};
module.exports = Comment;
21 changes: 3 additions & 18 deletions lib/less/tree/directive.js
Expand Up @@ -2,7 +2,7 @@ var Node = require("./node"),
Selector = require("./selector"),
Ruleset = require("./ruleset");

var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isReferenced, isRooted) {
var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) {
var i;

this.name = name;
Expand All @@ -21,8 +21,8 @@ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo,
this.index = index;
this.currentFileInfo = currentFileInfo;
this.debugInfo = debugInfo;
this.isReferenced = isReferenced;
this.isRooted = isRooted || false;
this.copyVisibilityInfo(visibilityInfo);
};

Directive.prototype = new Node();
Expand Down Expand Up @@ -79,7 +79,7 @@ Directive.prototype.eval = function (context) {
context.mediaBlocks = mediaBlocksBackup;

return new Directive(this.name, value, rules,
this.index, this.currentFileInfo, this.debugInfo, this.isReferenced, this.isRooted);
this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo());
};
Directive.prototype.variable = function (name) {
if (this.rules) {
Expand All @@ -99,21 +99,6 @@ Directive.prototype.rulesets = function () {
return Ruleset.prototype.rulesets.apply(this.rules[0]);
}
};
Directive.prototype.markReferenced = function () {
var i, rules;
this.isReferenced = true;
if (this.rules) {
rules = this.rules;
for (i = 0; i < rules.length; i++) {
if (rules[i].markReferenced) {
rules[i].markReferenced();
}
}
}
};
Directive.prototype.getIsReferenced = function () {
return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
};
Directive.prototype.outputRuleset = function (context, output, rules) {
var ruleCnt = rules.length, i;
context.tabLevel = (context.tabLevel | 0) + 1;
Expand Down
11 changes: 9 additions & 2 deletions lib/less/tree/element.js
Expand Up @@ -2,7 +2,7 @@ var Node = require("./node"),
Paren = require("./paren"),
Combinator = require("./combinator");

var Element = function (combinator, value, index, currentFileInfo) {
var Element = function (combinator, value, index, currentFileInfo, info) {
this.combinator = combinator instanceof Combinator ?
combinator : new Combinator(combinator);

Expand All @@ -15,6 +15,7 @@ var Element = function (combinator, value, index, currentFileInfo) {
}
this.index = index;
this.currentFileInfo = currentFileInfo;
this.copyVisibilityInfo(info);
};
Element.prototype = new Node();
Element.prototype.type = "Element";
Expand All @@ -29,7 +30,13 @@ Element.prototype.eval = function (context) {
return new Element(this.combinator,
this.value.eval ? this.value.eval(context) : this.value,
this.index,
this.currentFileInfo);
this.currentFileInfo, this.visibilityInfo());
};
Element.prototype.clone = function () {
return new Element(this.combinator,
this.value,
this.index,
this.currentFileInfo, this.visibilityInfo());
};
Element.prototype.genCSS = function (context, output) {
output.add(this.toCSS(context), this.currentFileInfo, this.index);
Expand Down
5 changes: 0 additions & 5 deletions lib/less/tree/expression.js
Expand Up @@ -53,9 +53,4 @@ Expression.prototype.throwAwayComments = function () {
return !(v instanceof Comment);
});
};
Expression.prototype.markReferenced = function () {
this.value.forEach(function (value) {
if (value.markReferenced) { value.markReferenced(); }
});
};
module.exports = Expression;
15 changes: 10 additions & 5 deletions lib/less/tree/extend.js
@@ -1,11 +1,14 @@
var Node = require("./node");
var Node = require("./node"),
Selector = require("./selector");

var Extend = function Extend(selector, option, index) {
var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) {
this.selector = selector;
this.option = option;
this.index = index;
this.object_id = Extend.next_id++;
this.parent_ids = [this.object_id];
this.currentFileInfo = currentFileInfo || {};
this.copyVisibilityInfo(visibilityInfo);

switch(option) {
case "all":
Expand All @@ -26,11 +29,12 @@ Extend.prototype.accept = function (visitor) {
this.selector = visitor.visit(this.selector);
};
Extend.prototype.eval = function (context) {
return new Extend(this.selector.eval(context), this.option, this.index);
return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo());
};
Extend.prototype.clone = function (context) {
return new Extend(this.selector, this.option, this.index);
return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo());
};
//it concatenates (joins) all selectors in selector array
Extend.prototype.findSelfSelectors = function (selectors) {
var selfElements = [],
i,
Expand All @@ -46,6 +50,7 @@ Extend.prototype.findSelfSelectors = function (selectors) {
selfElements = selfElements.concat(selectors[i].elements);
}

this.selfSelectors = [{ elements: selfElements }];
this.selfSelectors = [new Selector(selfElements)];
this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo());
};
module.exports = Extend;
23 changes: 18 additions & 5 deletions lib/less/tree/import.js
Expand Up @@ -17,7 +17,7 @@ var Node = require("./node"),
// `import,push`, we also pass it a callback, which it'll call once
// the file has been fetched, and parsed.
//
var Import = function (path, features, options, index, currentFileInfo) {
var Import = function (path, features, options, index, currentFileInfo, visibilityInfo) {
this.options = options;
this.index = index;
this.path = path;
Expand All @@ -32,6 +32,7 @@ var Import = function (path, features, options, index, currentFileInfo) {
this.css = true;
}
}
this.copyVisibilityInfo(visibilityInfo);
};

//
Expand Down Expand Up @@ -87,7 +88,7 @@ Import.prototype.evalForImport = function (context) {
path = path.value;
}

return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo);
return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo());
};
Import.prototype.evalPath = function (context) {
var path = this.path.eval(context);
Expand All @@ -107,6 +108,20 @@ Import.prototype.evalPath = function (context) {
return path;
};
Import.prototype.eval = function (context) {
var result = this.doEval(context);
if (this.options.reference || this.blocksVisibility()) {
if (result.length || result.length === 0) {
result.forEach(function (node) {
node.addVisibilityBlock();
}
);
} else {
result.addVisibilityBlock();
}
}
return result;
};
Import.prototype.doEval = function (context) {
var ruleset, registry,
features = this.features && this.features.eval(context);

Expand All @@ -126,13 +141,12 @@ Import.prototype.eval = function (context) {
return [];
}
}

if (this.options.inline) {
var contents = new Anonymous(this.root, 0,
{
filename: this.importedFilename,
reference: this.path.currentFileInfo && this.path.currentFileInfo.reference
}, true, true, false);
}, true, true);

return this.features ? new Media([contents], this.features.value) : [contents];
} else if (this.css) {
Expand All @@ -143,7 +157,6 @@ Import.prototype.eval = function (context) {
return newImport;
} else {
ruleset = new Ruleset(null, this.root.rules.slice(0));

ruleset.evalImports(context);

return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules;
Expand Down
6 changes: 4 additions & 2 deletions lib/less/tree/media.js
Expand Up @@ -5,7 +5,7 @@ var Ruleset = require("./ruleset"),
Expression = require("./expression"),
Directive = require("./directive");

var Media = function (value, features, index, currentFileInfo) {
var Media = function (value, features, index, currentFileInfo, visibilityInfo) {
this.index = index;
this.currentFileInfo = currentFileInfo;

Expand All @@ -14,6 +14,7 @@ var Media = function (value, features, index, currentFileInfo) {
this.features = new Value(features);
this.rules = [new Ruleset(selectors, value)];
this.rules[0].allowImports = true;
this.copyVisibilityInfo(visibilityInfo);
};
Media.prototype = new Directive();
Media.prototype.type = "Media";
Expand All @@ -37,7 +38,7 @@ Media.prototype.eval = function (context) {
context.mediaPath = [];
}

var media = new Media(null, [], this.index, this.currentFileInfo);
var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo());
if (this.debugInfo) {
this.rules[0].debugInfo = this.debugInfo;
media.debugInfo = this.debugInfo;
Expand Down Expand Up @@ -77,6 +78,7 @@ Media.prototype.evalTop = function (context) {
var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors();
result = new Ruleset(selectors, context.mediaBlocks);
result.multiMedia = true;
result.copyVisibilityInfo(this.visibilityInfo());
}

delete context.mediaBlocks;
Expand Down
27 changes: 15 additions & 12 deletions lib/less/tree/mixin-call.js
Expand Up @@ -22,7 +22,7 @@ MixinCall.prototype.accept = function (visitor) {
};
MixinCall.prototype.eval = function (context) {
var mixins, mixin, mixinPath, args = [], arg, argValue,
rules = [], rule, match = false, i, m, f, isRecursive, isOneFound,
rules = [], match = false, i, m, f, isRecursive, isOneFound,
candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;

Expand Down Expand Up @@ -127,26 +127,19 @@ MixinCall.prototype.eval = function (context) {
mixin = candidates[m].mixin;
if (!(mixin instanceof MixinDefinition)) {
originalRuleset = mixin.originalRuleset || mixin;
mixin = new MixinDefinition("", [], mixin.rules, null, false);
mixin = new MixinDefinition("", [], mixin.rules, null, false, null, originalRuleset.visibilityInfo());
mixin.originalRuleset = originalRuleset;
}
Array.prototype.push.apply(
rules, mixin.evalCall(context, args, this.important).rules);
var newRules = mixin.evalCall(context, args, this.important).rules;
this._setVisibilityToReplacement(newRules);
Array.prototype.push.apply(rules, newRules);
} catch (e) {
throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
}
}
}

if (match) {
if (!this.currentFileInfo || !this.currentFileInfo.reference) {
for (i = 0; i < rules.length; i++) {
rule = rules[i];
if (rule.markReferenced) {
rule.markReferenced();
}
}
}
return rules;
}
}
Expand All @@ -161,6 +154,16 @@ MixinCall.prototype.eval = function (context) {
index: this.index, filename: this.currentFileInfo.filename };
}
};

MixinCall.prototype._setVisibilityToReplacement = function (replacement) {
var i, rule;
if (this.blocksVisibility()) {
for (i = 0; i < replacement.length; i++) {
rule = replacement[i];
rule.addVisibilityBlock();
}
}
};
MixinCall.prototype.format = function (args) {
return this.selector.toCSS().trim() + '(' +
(args ? args.map(function (a) {
Expand Down

0 comments on commit ead3e29

Please sign in to comment.