WIP each() re-implementation

This commit is contained in:
Matthew Dean
2018-07-03 23:05:49 -07:00
parent d821a3754f
commit 7a548a6860
4 changed files with 102 additions and 47 deletions

View File

@@ -10,6 +10,7 @@ module.exports = function(environment) {
require('./color');
require('./color-blending');
require('./data-uri')(environment);
require('./list');
require('./math');
require('./number');
require('./string');

View File

@@ -0,0 +1,54 @@
var Dimension = require('../tree/dimension'),
functionRegistry = require('./function-registry');
var getItemsFromNode = function(node) {
// handle non-array values as an array of length 1
// return 'undefined' if index is invalid
var items = Array.isArray(node.value) ?
node.value : Array(node);
return items;
};
functionRegistry.addMultiple({
_SELF: function(n) {
return n;
},
extract: function(values, index) {
index = index.value - 1; // (1-based index)
return getItemsFromNode(values)[index];
},
length: function(values) {
return new Dimension(getItemsFromNode(values).length);
},
each: function(list, ruleset) {
var i = 0, rules = [], rs, newRules;
rs = ruleset.ruleset;
list.value.forEach(function(item) {
i = i + 1;
newRules = rs.rules.slice(0);
newRules.push(new Rule(ruleset && vars.value[1] ? '@' + vars.value[1].value : '@item',
item,
false, false, this.index, this.currentFileInfo));
newRules.push(new Rule(ruleset && vars.value[0] ? '@' + vars.value[0].value : '@index',
new Dimension(i),
false, false, this.index, this.currentFileInfo));
rules.push(new Ruleset([ new(Selector)([ new Element("", '&') ]) ],
newRules,
rs.strictImports,
rs.visibilityInfo()
));
});
return new Ruleset([ new(Selector)([ new Element("", '&') ]) ],
rules,
rs.strictImports,
rs.visibilityInfo()
).eval(this.context);
}
});

View File

@@ -20,15 +20,8 @@ var isa = function (n, Type) {
throw { type: 'Argument', message: 'Second argument to isunit should be a unit or a string.' };
}
return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
},
getItemsFromNode = function(node) {
// handle non-array values as an array of length 1
// return 'undefined' if index is invalid
var items = Array.isArray(node.value) ?
node.value : Array(node);
return items;
};
functionRegistry.addMultiple({
isruleset: function (n) {
return isa(n, DetachedRuleset);
@@ -77,16 +70,5 @@ functionRegistry.addMultiple({
},
'get-unit': function (n) {
return new Anonymous(n.unit);
},
extract: function(values, index) {
index = index.value - 1; // (1-based index)
return getItemsFromNode(values)[index];
},
length: function(values) {
return new Dimension(getItemsFromNode(values).length);
},
_SELF: function(n) {
return n;
}
});

View File

@@ -929,7 +929,7 @@ var Parser = function Parser(context, imports, fileInfo) {
},
args: function (isCall) {
var entities = parsers.entities,
returner = { args:null, variadic: false },
returner = { args: null, variadic: false },
expressions = [], argsSemiColon = [], argsComma = [],
isSemiColonSeparated, expressionContainsNamed, name, nameLoop,
value, arg, expand;
@@ -1065,7 +1065,7 @@ var Parser = function Parser(context, imports, fileInfo) {
// the `{...}` block.
//
definition: function () {
var name, params = [], match, ruleset, cond, variadic = false;
var name, match;
if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
parserInput.peek(/^[^{]*\}/)) {
return;
@@ -1076,32 +1076,10 @@ var Parser = function Parser(context, imports, fileInfo) {
match = parserInput.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
if (match) {
name = match[1];
var argInfo = this.args(false);
params = argInfo.args;
variadic = argInfo.variadic;
// .mixincall("@{a}");
// looks a bit like a mixin definition..
// also
// .mixincall(@a: {rule: set;});
// so we have to be nice and restore
if (!parserInput.$char(')')) {
parserInput.restore('Missing closing \')\'');
return;
}
parserInput.commentStore.length = 0;
if (parserInput.$str('when')) { // Guard
cond = expect(parsers.conditions, 'expected condition');
}
ruleset = parsers.block();
if (ruleset) {
block = this.body(name);
if (block) {
parserInput.forget();
return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
return block;
} else {
parserInput.restore();
}
@@ -1109,6 +1087,41 @@ var Parser = function Parser(context, imports, fileInfo) {
parserInput.forget();
}
},
body: function(name) {
var argInfo, params, variadic, cond, ruleset;
parserInput.save();
argInfo = this.args(false);
params = argInfo.args;
variadic = argInfo.variadic;
// .mixincall("@{a}");
// looks a bit like a mixin definition..
// also
// .mixincall(@a: {rule: set;});
// so we have to be nice and restore
if (!parserInput.$char(')')) {
parserInput.restore('Missing closing \')\'');
return;
}
parserInput.commentStore.length = 0;
if (parserInput.$str('when')) { // Guard
cond = expect(parsers.conditions, 'expected condition');
}
ruleset = parsers.block();
if (ruleset) {
parserInput.forget();
return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
} else {
parserInput.restore();
}
},
ruleLookups: function() {
var rule, args, lookups = [];
@@ -1378,9 +1391,14 @@ var Parser = function Parser(context, imports, fileInfo) {
},
detachedRuleset: function() {
var args;
if (parserInput.$char('(')) {
args = this.mixin.args().args;
expectChar(')');
}
var blockRuleset = this.blockRuleset();
if (blockRuleset) {
return new tree.DetachedRuleset(blockRuleset);
return new tree.DetachedRuleset(blockRuleset, args);
}
},