UNPKG

1.81 kBJavaScriptView Raw
1// tooling
2import getReplacedString from './get-replaced-string';
3import getValueAsObject from './get-value-as-object';
4import setVariable from './set-variable';
5import transformNode from './transform-node';
6
7// transform @each at-rules
8export default function transformEachAtrule(rule, opts) {
9 // if @each is supported
10 if (opts.transform.includes('@each')) {
11 // @each options
12 const { varname, incname, list } = getEachOpts(rule, opts);
13 const replacements = [];
14
15 Object.keys(list).forEach(
16 key => {
17 // set the current variable
18 setVariable(rule, varname, list[key], opts);
19
20 // conditionally set the incremenator variable
21 if (incname) {
22 setVariable(rule, incname, key, opts);
23 }
24
25 // clone the @each at-rule
26 const clone = rule.clone({
27 parent: rule.parent,
28 variables: rule.variables
29 });
30
31 // transform the clone children
32 transformNode(clone, opts);
33
34 // push the clone children to the replacements array
35 replacements.push(...clone.nodes);
36 }
37 );
38
39 // replace the @each at-rule with the replacements
40 rule.parent.insertBefore(rule, replacements);
41
42 rule.remove();
43 }
44}
45
46// return the @each statement options (@each NAME in LIST, @each NAME ITERATOR in LIST)
47const getEachOpts = (node, opts) => {
48 const params = node.params.split(matchInOperator);
49 const args = (params[0] || '').trim().split(' ');
50 const varname = args[0].trim().slice(1);
51 const incname = args.length > 1 && args[1].trim().slice(1);
52 const rawlist = getValueAsObject(
53 getReplacedString(
54 params.slice(1).join(matchInOperator),
55 node,
56 opts
57 )
58 );
59 const list = 'string' === typeof rawlist ? [rawlist] : rawlist;
60
61 return { varname, incname, list };
62};
63
64// match the opertor separating the name and iterator from the list
65const matchInOperator = ' in ';