UNPKG

1.97 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 const transformAndInsertBeforeParent = node => transformNode(node, opts).then(
13 () => node.parent.insertBefore(node, node.nodes)
14 )
15
16 return ifPromise(
17 opts.transform.includes('@if'),
18 () => ifPromise(
19 isTruthy,
20 () => transformAndInsertBeforeParent(rule)
21 ).then(() => {
22 rule.remove();
23 })
24 ).then(() => ifPromise(
25 opts.transform.includes('@else') && isElseRule(next),
26 () => ifPromise(
27 !isTruthy,
28 () => transformAndInsertBeforeParent(next)
29 ).then(() => {
30 next.remove();
31 })
32 ))
33}
34
35const ifPromise = (condition, trueFunction) => Promise.resolve(condition && trueFunction())
36
37// return whether the @if at-rule is truthy
38const isIfTruthy = (node, opts) => {
39 // @if statement options (@if EXPRESSION, @if LEFT OPERATOR RIGHT)
40 const params = list.space(node.params);
41 const left = getInterprettedString(getReplacedString(params[0] || '', node, opts));
42 const operator = params[1];
43 const right = getInterprettedString(getReplacedString(params[2] || '', node, opts));
44
45 // evaluate the expression
46 const isTruthy = !operator && left ||
47 operator === '==' && left === right ||
48 operator === '!=' && left !== right ||
49 operator === '<' && left < right ||
50 operator === '<=' && left <= right ||
51 operator === '>' && left > right ||
52 operator === '>=' && left >= right;
53
54 return isTruthy;
55};
56
57// return the value as a boolean, number, or string
58const getInterprettedString = value => 'true' === value
59 ? true
60: 'false' === value
61 ? false
62: isNaN(value)
63 ? value
64: Number(value);
65
66// return whether the node is an else at-rule
67const isElseRule = node => Object(node) === node && 'atrule' === node.type && 'else' === node.name;