UNPKG

1.77 kBJavaScriptView Raw
1// tooling
2import { list } from 'postcss';
3import getReplacedString from './get-replaced-string';
4import transformNode from './transform-node';
5import setVariable from './set-variable';
6import waterfall from './waterfall';
7
8// transform @for at-rules
9export default function transformForAtrule(rule, opts) {
10 // if @for is supported
11 if (opts.transform.includes('@for')) {
12 // @for options
13 const { varname, start, end, increment } = getForOpts(rule, opts);
14 const direction = start <= end ? 1 : -1;
15 const replacements = [];
16 const ruleClones = [];
17
18 // for each iteration
19 for (let incrementor = start; incrementor * direction <= end * direction; incrementor += increment * direction) {
20 // set the current variable
21 setVariable(rule, varname, incrementor, opts);
22
23 // clone the @for at-rule
24 const clone = rule.clone({
25 parent: rule.parent,
26 variables: Object.assign({}, rule.variables)
27 });
28
29 ruleClones.push(clone)
30 }
31
32 return waterfall(
33 ruleClones,
34 clone => transformNode(clone, opts).then(
35 () => {
36 replacements.push(...clone.nodes);
37 }
38 )
39 ).then(
40 () => {
41 // replace the @for at-rule with the replacements
42 rule.parent.insertBefore(rule, replacements);
43
44 rule.remove();
45 }
46 )
47 }
48}
49
50// return the @for statement options (@for NAME from START through END, @for NAME from START through END by INCREMENT)
51const getForOpts = (node, opts) => {
52 const params = list.space(node.params);
53 const varname = params[0].trim().slice(1);
54 const start = Number(getReplacedString(params[2], node, opts));
55 const end = Number(getReplacedString(params[4], node, opts));
56 const increment = 6 in params && Number(getReplacedString(params[6], node, opts)) || 1;
57
58 return { varname, start, end, increment };
59};