1 | 'use strict';
|
2 |
|
3 | const t = require('babel-types');
|
4 | const generate = require('babel-generator').default;
|
5 | const vm = require('vm');
|
6 | const invariant = require('invariant');
|
7 | const getClassNameFromCache = require('../getClassNameFromCache');
|
8 |
|
9 | function extractStaticTernaries(ternaries, evalContext, cacheObject) {
|
10 | invariant(
|
11 | Array.isArray(ternaries),
|
12 | 'extractStaticTernaries expects param 1 to be an array of ternaries'
|
13 | );
|
14 | invariant(
|
15 | typeof evalContext === 'object' && evalContext !== null,
|
16 | 'extractStaticTernaries expects param 2 to be an object'
|
17 | );
|
18 | invariant(
|
19 | typeof cacheObject === 'object' && cacheObject !== null,
|
20 | 'extractStaticTernaries expects param 3 to be an object'
|
21 | );
|
22 |
|
23 | if (ternaries.length === 0) {
|
24 | return null;
|
25 | }
|
26 |
|
27 | const ternariesByKey = {};
|
28 | for (let idx = -1, len = ternaries.length; ++idx < len; ) {
|
29 | const { name, ternary } = ternaries[idx];
|
30 |
|
31 | const consequentValue = vm.runInContext(
|
32 | generate(ternary.consequent).code,
|
33 | evalContext
|
34 | );
|
35 | const alternateValue = vm.runInContext(
|
36 | generate(ternary.alternate).code,
|
37 | evalContext
|
38 | );
|
39 |
|
40 | const key = generate(ternary.test).code;
|
41 | ternariesByKey[key] = ternariesByKey[key] || {
|
42 | test: ternary.test,
|
43 | consequentStyles: {},
|
44 | alternateStyles: {},
|
45 | };
|
46 | ternariesByKey[key].consequentStyles[name] = consequentValue;
|
47 | ternariesByKey[key].alternateStyles[name] = alternateValue;
|
48 | }
|
49 |
|
50 | const stylesByClassName = {};
|
51 |
|
52 | const ternaryExpression = Object.keys(ternariesByKey)
|
53 | .map((key, idx) => {
|
54 | const { test, consequentStyles, alternateStyles } = ternariesByKey[key];
|
55 | const consequentClassName =
|
56 | getClassNameFromCache(consequentStyles, cacheObject) || '';
|
57 | const alternateClassName =
|
58 | getClassNameFromCache(alternateStyles, cacheObject) || '';
|
59 |
|
60 | if (!consequentClassName && !alternateClassName) {
|
61 | return null;
|
62 | }
|
63 |
|
64 | if (consequentClassName) {
|
65 | stylesByClassName[consequentClassName] = consequentStyles;
|
66 | }
|
67 |
|
68 | if (alternateClassName) {
|
69 | stylesByClassName[alternateClassName] = alternateStyles;
|
70 | }
|
71 |
|
72 | if (consequentClassName && alternateClassName) {
|
73 | if (idx > 0) {
|
74 |
|
75 | return t.binaryExpression(
|
76 | '+',
|
77 | t.stringLiteral(' '),
|
78 | t.conditionalExpression(
|
79 | test,
|
80 | t.stringLiteral(consequentClassName),
|
81 | t.stringLiteral(alternateClassName)
|
82 | )
|
83 | );
|
84 | } else {
|
85 | return t.conditionalExpression(
|
86 | test,
|
87 | t.stringLiteral(consequentClassName),
|
88 | t.stringLiteral(alternateClassName)
|
89 | );
|
90 | }
|
91 | } else {
|
92 |
|
93 | return t.conditionalExpression(
|
94 | test,
|
95 | t.stringLiteral(
|
96 | (idx > 0 && consequentClassName ? ' ' : '') + consequentClassName
|
97 | ),
|
98 | t.stringLiteral(
|
99 | (idx > 0 && alternateClassName ? ' ' : '') + alternateClassName
|
100 | )
|
101 | );
|
102 | }
|
103 | })
|
104 | .filter(f => f)
|
105 | .reduce(
|
106 | (acc, val) => (acc ? t.binaryExpression('+', acc, val) : val),
|
107 | null
|
108 | );
|
109 |
|
110 | if (!ternaryExpression) {
|
111 | return null;
|
112 | }
|
113 |
|
114 | return {
|
115 |
|
116 | stylesByClassName,
|
117 |
|
118 | ternaryExpression,
|
119 | };
|
120 | }
|
121 |
|
122 | module.exports = extractStaticTernaries;
|