less
Version:
Leaner CSS
196 lines • 8.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var node_1 = tslib_1.__importDefault(require("./node"));
var selector_1 = tslib_1.__importDefault(require("./selector"));
var mixin_definition_1 = tslib_1.__importDefault(require("./mixin-definition"));
var default_1 = tslib_1.__importDefault(require("../functions/default"));
var MixinCall = function (elements, args, index, currentFileInfo, important) {
this.selector = new selector_1.default(elements);
this.arguments = args || [];
this._index = index;
this._fileInfo = currentFileInfo;
this.important = important;
this.allowRoot = true;
this.setParent(this.selector, this);
};
MixinCall.prototype = Object.assign(new node_1.default(), {
type: 'MixinCall',
accept: function (visitor) {
if (this.selector) {
this.selector = visitor.visit(this.selector);
}
if (this.arguments.length) {
this.arguments = visitor.visitArray(this.arguments);
}
},
eval: function (context) {
var mixins;
var mixin;
var mixinPath;
var args = [];
var arg;
var argValue;
var rules = [];
var match = false;
var i;
var m;
var f;
var isRecursive;
var isOneFound;
var candidates = [];
var candidate;
var conditionResult = [];
var defaultResult;
var defFalseEitherCase = -1;
var defNone = 0;
var defTrue = 1;
var defFalse = 2;
var count;
var originalRuleset;
var noArgumentsFilter;
this.selector = this.selector.eval(context);
function calcDefGroup(mixin, mixinPath) {
var f, p, namespace;
for (f = 0; f < 2; f++) {
conditionResult[f] = true;
default_1.default.value(f);
for (p = 0; p < mixinPath.length && conditionResult[f]; p++) {
namespace = mixinPath[p];
if (namespace.matchCondition) {
conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, context);
}
}
if (mixin.matchCondition) {
conditionResult[f] = conditionResult[f] && mixin.matchCondition(args, context);
}
}
if (conditionResult[0] || conditionResult[1]) {
if (conditionResult[0] != conditionResult[1]) {
return conditionResult[1] ?
defTrue : defFalse;
}
return defNone;
}
return defFalseEitherCase;
}
for (i = 0; i < this.arguments.length; i++) {
arg = this.arguments[i];
argValue = arg.value.eval(context);
if (arg.expand && Array.isArray(argValue.value)) {
argValue = argValue.value;
for (m = 0; m < argValue.length; m++) {
args.push({ value: argValue[m] });
}
}
else {
args.push({ name: arg.name, value: argValue });
}
}
noArgumentsFilter = function (rule) { return rule.matchArgs(null, context); };
for (i = 0; i < context.frames.length; i++) {
if ((mixins = context.frames[i].find(this.selector, null, noArgumentsFilter)).length > 0) {
isOneFound = true;
// To make `default()` function independent of definition order we have two "subpasses" here.
// At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
// and build candidate list with corresponding flags. Then, when we know all possible matches,
// we make a final decision.
for (m = 0; m < mixins.length; m++) {
mixin = mixins[m].rule;
mixinPath = mixins[m].path;
isRecursive = false;
for (f = 0; f < context.frames.length; f++) {
if ((!(mixin instanceof mixin_definition_1.default)) && mixin === (context.frames[f].originalRuleset || context.frames[f])) {
isRecursive = true;
break;
}
}
if (isRecursive) {
continue;
}
if (mixin.matchArgs(args, context)) {
candidate = { mixin: mixin, group: calcDefGroup(mixin, mixinPath) };
if (candidate.group !== defFalseEitherCase) {
candidates.push(candidate);
}
match = true;
}
}
default_1.default.reset();
count = [0, 0, 0];
for (m = 0; m < candidates.length; m++) {
count[candidates[m].group]++;
}
if (count[defNone] > 0) {
defaultResult = defFalse;
}
else {
defaultResult = defTrue;
if ((count[defTrue] + count[defFalse]) > 1) {
throw { type: 'Runtime',
message: "Ambiguous use of `default()` found when matching for `".concat(this.format(args), "`"),
index: this.getIndex(), filename: this.fileInfo().filename };
}
}
for (m = 0; m < candidates.length; m++) {
candidate = candidates[m].group;
if ((candidate === defNone) || (candidate === defaultResult)) {
try {
mixin = candidates[m].mixin;
if (!(mixin instanceof mixin_definition_1.default)) {
originalRuleset = mixin.originalRuleset || mixin;
mixin = new mixin_definition_1.default('', [], mixin.rules, null, false, null, originalRuleset.visibilityInfo());
mixin.originalRuleset = originalRuleset;
}
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.getIndex(), filename: this.fileInfo().filename, stack: e.stack };
}
}
}
if (match) {
return rules;
}
}
}
if (isOneFound) {
throw { type: 'Runtime',
message: "No matching definition was found for `".concat(this.format(args), "`"),
index: this.getIndex(), filename: this.fileInfo().filename };
}
else {
throw { type: 'Name',
message: "".concat(this.selector.toCSS().trim(), " is undefined"),
index: this.getIndex(), filename: this.fileInfo().filename };
}
},
_setVisibilityToReplacement: function (replacement) {
var i, rule;
if (this.blocksVisibility()) {
for (i = 0; i < replacement.length; i++) {
rule = replacement[i];
rule.addVisibilityBlock();
}
}
},
format: function (args) {
return "".concat(this.selector.toCSS().trim(), "(").concat(args ? args.map(function (a) {
var argValue = '';
if (a.name) {
argValue += "".concat(a.name, ":");
}
if (a.value.toCSS) {
argValue += a.value.toCSS();
}
else {
argValue += '???';
}
return argValue;
}).join(', ') : '', ")");
}
});
exports.default = MixinCall;
//# sourceMappingURL=mixin-call.js.map