UNPKG

2.07 kBJavaScriptView Raw
1// tooling
2import { list } from 'postcss';
3import transformNode from './transform-node';
4import getReplacedString from './get-replaced-string';
5
6// transform @if at-rules
7export default function transformIfAtrule(rule, opts) {
8 // @if options
9 const isTruthy = isIfTruthy(rule, opts);
10 const next = rule.next();
11
12 // if @if is supported
13 if (opts.transform.includes('@if')) {
14 // if the expression is truthy
15 if (isTruthy) {
16 // transform the @if at-rule children
17 transformNode(rule, opts);
18
19 // replace the @if at-rule with its children
20 rule.parent.insertBefore(rule, rule.nodes);
21 }
22
23 // remove the @if at-rule
24 rule.remove();
25 }
26
27 // if @else is supported
28 if (opts.transform.includes('@else') && isElseRule(next)) {
29 // if the expression is falsey
30 if (!isTruthy) {
31 // transform the @else at-rule children
32 transformNode(next, opts);
33
34 // replace the @else at-rule with its children
35 next.parent.insertBefore(next, next.nodes);
36 }
37
38 // remove the @else at-rule
39 next.remove();
40 }
41}
42
43// return whether the @if at-rule is truthy
44const isIfTruthy = (node, opts) => {
45 // @if statement options (@if EXPRESSION, @if LEFT OPERATOR RIGHT)
46 const params = list.space(node.params);
47 const left = getInterprettedString(getReplacedString(params[0] || '', node, opts));
48 const operator = params[1];
49 const right = getInterprettedString(getReplacedString(params[2] || '', node, opts));
50
51 // evaluate the expression
52 const isTruthy = !operator && left ||
53 operator === '==' && left === right ||
54 operator === '!=' && left !== right ||
55 operator === '<' && left < right ||
56 operator === '<=' && left <= right ||
57 operator === '>' && left > right ||
58 operator === '>=' && left >= right;
59
60 return isTruthy;
61};
62
63// return the value as a boolean, number, or string
64const getInterprettedString = value => 'true' === value
65 ? true
66: 'false' === value
67 ? false
68: isNaN(value)
69 ? value
70: Number(value);
71
72// return whether the node is an else at-rule
73const isElseRule = node => Object(node) === node && 'atrule' === node.type && 'else' === node.name;