@hypergood/css-core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +1 -0
- package/.prettierrc +1 -0
- package/dist/index.cjs +54 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.cjs +68267 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +9 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.js +68266 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +46 -0
- package/src/atomizer/css-tree.ts +579 -0
- package/src/atomizer/index.ts +291 -0
- package/src/atomizer/tokens.ts +0 -0
- package/src/atomizer/types.ts +3 -0
- package/src/css-js-logger.ts +57 -0
- package/src/evaluate.ts +136 -0
- package/src/index.ts +1 -0
- package/src/plugin.ts +573 -0
- package/src/print.ts +101 -0
- package/src/runtime.ts +27 -0
- package/src/string.ts +37 -0
- package/src/style-cache.ts +171 -0
- package/src/style-object.ts +181 -0
- package/src/style-rule.ts +9 -0
- package/tests/style-object.test.ts +151 -0
- package/tsconfig.json +7 -0
- package/tsup.config.ts +12 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import * as csstree from "css-tree";
|
|
2
|
+
import { StyleRule } from "../style-rule.js";
|
|
3
|
+
import { evaluateLexerNode, LexerNode } from "./css-tree.js";
|
|
4
|
+
import { AtomizerFn } from "./types.js";
|
|
5
|
+
|
|
6
|
+
const atomizers: Record<string, AtomizerFn> = {
|
|
7
|
+
animation: (value) => {
|
|
8
|
+
const ast = csstree.parse(value, { context: "value" });
|
|
9
|
+
const matchResult = csstree.lexer.matchProperty("animation", ast);
|
|
10
|
+
const match = matchResult.matched?.match;
|
|
11
|
+
|
|
12
|
+
// console.log({ match: JSON.stringify(match) });
|
|
13
|
+
|
|
14
|
+
if (!match) return undefined;
|
|
15
|
+
|
|
16
|
+
const animationNames: LexerNode[] = [];
|
|
17
|
+
const animationDurations: LexerNode[] = [];
|
|
18
|
+
const animationDelays: LexerNode[] = [];
|
|
19
|
+
const timingFunctions: LexerNode[] = [];
|
|
20
|
+
const iterations: LexerNode[] = [];
|
|
21
|
+
const fillModes: LexerNode[] = [];
|
|
22
|
+
const playStates: LexerNode[] = [];
|
|
23
|
+
|
|
24
|
+
for (const singleAnimation of match) {
|
|
25
|
+
const keyframesName = singleAnimation.match?.find(
|
|
26
|
+
(n) => n.syntax?.name === "keyframes-name",
|
|
27
|
+
);
|
|
28
|
+
if (keyframesName) {
|
|
29
|
+
animationNames.push(keyframesName);
|
|
30
|
+
}
|
|
31
|
+
const duration = singleAnimation.match?.find(
|
|
32
|
+
(n) => n.syntax?.name === "animation-duration",
|
|
33
|
+
);
|
|
34
|
+
if (duration) {
|
|
35
|
+
animationDurations.push(duration);
|
|
36
|
+
}
|
|
37
|
+
const easing = singleAnimation.match?.find(
|
|
38
|
+
(n) => n.syntax?.name === "easing-function",
|
|
39
|
+
);
|
|
40
|
+
if (easing) {
|
|
41
|
+
timingFunctions.push(easing);
|
|
42
|
+
}
|
|
43
|
+
const delay = singleAnimation.match?.find(
|
|
44
|
+
(n) => n.syntax?.name === "animation-delay",
|
|
45
|
+
);
|
|
46
|
+
if (delay) {
|
|
47
|
+
animationDelays.push(delay);
|
|
48
|
+
}
|
|
49
|
+
const count = singleAnimation.match?.find(
|
|
50
|
+
(n) => n.syntax?.name === "single-animation-iteration-count",
|
|
51
|
+
);
|
|
52
|
+
if (count) {
|
|
53
|
+
iterations.push(count);
|
|
54
|
+
}
|
|
55
|
+
const fillMode = singleAnimation.match?.find(
|
|
56
|
+
(n) => n.syntax?.name === "single-animation-fill-mode",
|
|
57
|
+
);
|
|
58
|
+
if (fillMode) {
|
|
59
|
+
fillModes.push(fillMode);
|
|
60
|
+
}
|
|
61
|
+
const playState = singleAnimation.match?.find(
|
|
62
|
+
(n) => n.syntax?.name === "single-animation-play-state",
|
|
63
|
+
);
|
|
64
|
+
if (playState) {
|
|
65
|
+
playStates.push(playState);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
"animation-name":
|
|
71
|
+
animationNames.map(evaluateLexerNode).join(",") || undefined,
|
|
72
|
+
"animation-iteration-count":
|
|
73
|
+
iterations.map(evaluateLexerNode).join(",") || undefined,
|
|
74
|
+
"animation-delay":
|
|
75
|
+
animationDelays.map(evaluateLexerNode).join(",") || undefined,
|
|
76
|
+
"animation-duration":
|
|
77
|
+
animationDurations.map(evaluateLexerNode).join(",") || undefined,
|
|
78
|
+
"animation-timing-function":
|
|
79
|
+
timingFunctions.map(evaluateLexerNode).join(",") || undefined,
|
|
80
|
+
"animation-fill-mode":
|
|
81
|
+
fillModes.map(evaluateLexerNode).join(",") || undefined,
|
|
82
|
+
"animation-play-state":
|
|
83
|
+
playStates.map(evaluateLexerNode).join(",") || undefined,
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
border: (value) => {
|
|
87
|
+
const ast = csstree.parse(value, { context: "value" });
|
|
88
|
+
const matchResult = csstree.lexer.matchProperty("border", ast);
|
|
89
|
+
const match = matchResult.matched?.match;
|
|
90
|
+
|
|
91
|
+
if (!match) return;
|
|
92
|
+
|
|
93
|
+
const lineWidth = match.find((t) => t.syntax?.name === "line-width");
|
|
94
|
+
const lineStyle = match.find((t) => t.syntax?.name === "line-style");
|
|
95
|
+
const color = match.find((t) => t.syntax?.name === "color");
|
|
96
|
+
|
|
97
|
+
const lineWidthString = evaluateLexerNode(lineWidth);
|
|
98
|
+
const lineStyleString = evaluateLexerNode(lineStyle);
|
|
99
|
+
const colorString = evaluateLexerNode(color);
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
"border-bottom-style": lineStyleString,
|
|
103
|
+
"border-left-style": lineStyleString,
|
|
104
|
+
"border-right-style": lineStyleString,
|
|
105
|
+
"border-top-style": lineStyleString,
|
|
106
|
+
"border-bottom-color": colorString,
|
|
107
|
+
"border-left-color": colorString,
|
|
108
|
+
"border-right-color": colorString,
|
|
109
|
+
"border-top-color": colorString,
|
|
110
|
+
"border-bottom-width": lineWidthString,
|
|
111
|
+
"border-left-width": lineWidthString,
|
|
112
|
+
"border-right-width": lineWidthString,
|
|
113
|
+
"border-top-width": lineWidthString,
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
"border-radius": (value) => {
|
|
117
|
+
const ast = csstree.parse(value, { context: "value" });
|
|
118
|
+
const matchResult = csstree.lexer.matchProperty("border-radius", ast);
|
|
119
|
+
const match = matchResult.matched?.match;
|
|
120
|
+
if (!match) return undefined;
|
|
121
|
+
|
|
122
|
+
const slashIndex = match.findIndex(
|
|
123
|
+
(n) => n.syntax?.type === "Token" && n.syntax.value === "/",
|
|
124
|
+
);
|
|
125
|
+
const horizontalRadiiNodes =
|
|
126
|
+
slashIndex === -1 ? match : match.slice(0, slashIndex);
|
|
127
|
+
let verticalRadiiNodes =
|
|
128
|
+
slashIndex === -1 ? match : match.slice(slashIndex + 1);
|
|
129
|
+
if (!verticalRadiiNodes.length) {
|
|
130
|
+
verticalRadiiNodes = horizontalRadiiNodes;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const horizontalRadiiStrings = horizontalRadiiNodes.map(evaluateLexerNode);
|
|
134
|
+
const verticalRadiiStrings = verticalRadiiNodes.map(evaluateLexerNode);
|
|
135
|
+
|
|
136
|
+
const horizontalRadii = expandRadii(horizontalRadiiStrings);
|
|
137
|
+
const verticalRadii = expandRadii(verticalRadiiStrings);
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
"border-top-left-radius": `${horizontalRadii.topLeft} ${verticalRadii.topLeft}`,
|
|
141
|
+
"border-top-right-radius": `${horizontalRadii.topRight} ${verticalRadii.topRight}`,
|
|
142
|
+
"border-bottom-left-radius": `${horizontalRadii.bottomLeft} ${verticalRadii.bottomLeft}`,
|
|
143
|
+
"border-bottom-right-radius": `${horizontalRadii.bottomRight} ${verticalRadii.bottomRight}`,
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
margin: (value) => {
|
|
147
|
+
const ast = csstree.parse(value, { context: "value" });
|
|
148
|
+
const matchResult = csstree.lexer.matchProperty("margin", ast);
|
|
149
|
+
const match = matchResult.matched?.match;
|
|
150
|
+
if (!match) return undefined;
|
|
151
|
+
|
|
152
|
+
const sizeStrings = match.map(evaluateLexerNode);
|
|
153
|
+
const sizes = expandSizing(sizeStrings);
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
"margin-top": sizes.top,
|
|
157
|
+
"margin-right": sizes.right,
|
|
158
|
+
"margin-bottom": sizes.bottom,
|
|
159
|
+
"margin-left": sizes.left,
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
padding: (value) => {
|
|
163
|
+
const ast = csstree.parse(value, { context: "value" });
|
|
164
|
+
const matchResult = csstree.lexer.matchProperty("padding", ast);
|
|
165
|
+
const match = matchResult.matched?.match;
|
|
166
|
+
if (!match) return undefined;
|
|
167
|
+
|
|
168
|
+
const sizeStrings = match.map(evaluateLexerNode);
|
|
169
|
+
|
|
170
|
+
const sizes = expandSizing(sizeStrings);
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
"padding-top": sizes.top,
|
|
174
|
+
"padding-right": sizes.right,
|
|
175
|
+
"padding-bottom": sizes.bottom,
|
|
176
|
+
"padding-left": sizes.left,
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
function createDefaultAtomizer(property: string) {
|
|
182
|
+
const atomizer: AtomizerFn = (value) => {
|
|
183
|
+
const ast = csstree.parse(value, { context: "value" });
|
|
184
|
+
const matchResult = csstree.lexer.matchProperty(property, ast);
|
|
185
|
+
// if (property === "color") {
|
|
186
|
+
// console.log(JSON.stringify(matchResult));
|
|
187
|
+
// }
|
|
188
|
+
const lexxed = evaluateLexerNode(matchResult.matched);
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
[property]: lexxed,
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
return atomizer;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function expandRadii(radii: string[]): {
|
|
198
|
+
topLeft: string;
|
|
199
|
+
topRight: string;
|
|
200
|
+
bottomLeft: string;
|
|
201
|
+
bottomRight: string;
|
|
202
|
+
} {
|
|
203
|
+
const [r1, r2, r3, r4] = radii;
|
|
204
|
+
switch (radii.length) {
|
|
205
|
+
case 1:
|
|
206
|
+
return {
|
|
207
|
+
topLeft: r1,
|
|
208
|
+
topRight: r1,
|
|
209
|
+
bottomLeft: r1,
|
|
210
|
+
bottomRight: r1,
|
|
211
|
+
};
|
|
212
|
+
case 2:
|
|
213
|
+
return {
|
|
214
|
+
topLeft: r1,
|
|
215
|
+
topRight: r2,
|
|
216
|
+
bottomLeft: r2,
|
|
217
|
+
bottomRight: r1,
|
|
218
|
+
};
|
|
219
|
+
case 3:
|
|
220
|
+
return {
|
|
221
|
+
topLeft: r1,
|
|
222
|
+
topRight: r2,
|
|
223
|
+
bottomLeft: r2,
|
|
224
|
+
bottomRight: r3,
|
|
225
|
+
};
|
|
226
|
+
default:
|
|
227
|
+
return {
|
|
228
|
+
topLeft: r1,
|
|
229
|
+
topRight: r2,
|
|
230
|
+
bottomLeft: r4,
|
|
231
|
+
bottomRight: r3,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function expandSizing(sizes: string[]): {
|
|
236
|
+
top: string;
|
|
237
|
+
right: string;
|
|
238
|
+
bottom: string;
|
|
239
|
+
left: string;
|
|
240
|
+
} {
|
|
241
|
+
const [r1, r2, r3, r4] = sizes;
|
|
242
|
+
switch (sizes.length) {
|
|
243
|
+
case 1:
|
|
244
|
+
return {
|
|
245
|
+
top: r1,
|
|
246
|
+
right: r1,
|
|
247
|
+
bottom: r1,
|
|
248
|
+
left: r1,
|
|
249
|
+
};
|
|
250
|
+
case 2:
|
|
251
|
+
return {
|
|
252
|
+
top: r1,
|
|
253
|
+
right: r2,
|
|
254
|
+
bottom: r1,
|
|
255
|
+
left: r2,
|
|
256
|
+
};
|
|
257
|
+
case 3:
|
|
258
|
+
return {
|
|
259
|
+
top: r1,
|
|
260
|
+
right: r2,
|
|
261
|
+
bottom: r3,
|
|
262
|
+
left: r2,
|
|
263
|
+
};
|
|
264
|
+
default:
|
|
265
|
+
return {
|
|
266
|
+
top: r1,
|
|
267
|
+
right: r2,
|
|
268
|
+
bottom: r3,
|
|
269
|
+
left: r4,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export function atomizeStyleRules(styleRules: StyleRule[]): StyleRule[] {
|
|
275
|
+
return styleRules.flatMap((rule) => {
|
|
276
|
+
const atomizer =
|
|
277
|
+
atomizers[rule.property] || createDefaultAtomizer(rule.property);
|
|
278
|
+
if (!atomizer) return [rule];
|
|
279
|
+
|
|
280
|
+
const atomized = atomizer(rule.value);
|
|
281
|
+
if (!atomized) return [rule];
|
|
282
|
+
|
|
283
|
+
return Object.entries(atomized)
|
|
284
|
+
.filter(([key, value]) => value !== undefined)
|
|
285
|
+
.map(([key, value]) => ({
|
|
286
|
+
...rule,
|
|
287
|
+
property: key,
|
|
288
|
+
value: value!,
|
|
289
|
+
}));
|
|
290
|
+
});
|
|
291
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ViteDevServer } from "vite";
|
|
2
|
+
|
|
3
|
+
const CSS_JS_REGEX = /\.css\.[jt]s/;
|
|
4
|
+
const IMPORT_REGEX =
|
|
5
|
+
/import\s+(?:[\s\S]*?\s+from\s+)?['"]([^'"]+\.css(?:\.[jt]s)?)['"]/g;
|
|
6
|
+
|
|
7
|
+
export function cssJsLogger() {
|
|
8
|
+
const processedFiles = new Map<string, Record<string, unknown>>();
|
|
9
|
+
|
|
10
|
+
async function transform(
|
|
11
|
+
code: string,
|
|
12
|
+
id: string,
|
|
13
|
+
devServer: ViteDevServer | null,
|
|
14
|
+
) {
|
|
15
|
+
if (!devServer) return null;
|
|
16
|
+
|
|
17
|
+
// Skip the .css.ts files themselves - we'll process them from their importers
|
|
18
|
+
const cleanId = id.split("?")[0];
|
|
19
|
+
// if (CSS_JS_REGEX.test(cleanId)) return null;
|
|
20
|
+
|
|
21
|
+
// Only check JS/TS files for imports
|
|
22
|
+
if (!/\.[jt]sx?$/.test(cleanId)) return null;
|
|
23
|
+
|
|
24
|
+
const imports: string[] = [];
|
|
25
|
+
let match;
|
|
26
|
+
while ((match = IMPORT_REGEX.exec(code)) !== null) {
|
|
27
|
+
imports.push(match[1]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
for (const specifier of imports) {
|
|
31
|
+
// Get the import specifier
|
|
32
|
+
if (!specifier) continue;
|
|
33
|
+
|
|
34
|
+
if (!specifier.includes(".css")) continue;
|
|
35
|
+
|
|
36
|
+
// Resolve the full path
|
|
37
|
+
const resolved = await this.resolve(specifier, id);
|
|
38
|
+
if (!resolved) continue;
|
|
39
|
+
|
|
40
|
+
const resolvedPath = resolved.id.split("?")[0];
|
|
41
|
+
|
|
42
|
+
if (!CSS_JS_REGEX.test(resolvedPath)) continue;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
// Now it's safe to load - the module has already been transformed
|
|
46
|
+
const moduleExports = await devServer.ssrLoadModule(resolvedPath);
|
|
47
|
+
processedFiles.set(resolvedPath, moduleExports);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error(`\n❌ Error processing ${resolvedPath}:`, error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { processedFiles, transform };
|
|
57
|
+
}
|
package/src/evaluate.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export type EvaluationResult = {
|
|
2
|
+
confident: boolean;
|
|
3
|
+
value: any;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
const UNKNOWN: EvaluationResult = {
|
|
7
|
+
confident: false,
|
|
8
|
+
value: undefined,
|
|
9
|
+
};
|
|
10
|
+
const known = (value: any) => ({
|
|
11
|
+
confident: true,
|
|
12
|
+
value,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export function evaluateBabelExpression(
|
|
16
|
+
node: babel.types.Node | null | undefined,
|
|
17
|
+
knownConstants: Record<string, any>,
|
|
18
|
+
): EvaluationResult {
|
|
19
|
+
if (!node) return UNKNOWN;
|
|
20
|
+
switch (node.type) {
|
|
21
|
+
case "BinaryExpression":
|
|
22
|
+
return evaluateBinaryExpression(node, knownConstants);
|
|
23
|
+
case "Identifier":
|
|
24
|
+
return evaluateIdentifier(node, knownConstants);
|
|
25
|
+
case "NumericLiteral":
|
|
26
|
+
return evaluateNumericLiteral(node);
|
|
27
|
+
case "MemberExpression":
|
|
28
|
+
return evaluateMemberExpression(node, knownConstants);
|
|
29
|
+
case "ObjectExpression":
|
|
30
|
+
return evaluateObjectExpression(node, knownConstants);
|
|
31
|
+
case "StringLiteral":
|
|
32
|
+
return evaluateStringLiteral(node);
|
|
33
|
+
default:
|
|
34
|
+
return UNKNOWN;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function evaluateBinaryExpression(
|
|
39
|
+
node: babel.types.BinaryExpression,
|
|
40
|
+
knownConstants: Record<string, any>,
|
|
41
|
+
): EvaluationResult {
|
|
42
|
+
const left = evaluateBabelExpression(node.left, knownConstants);
|
|
43
|
+
const right = evaluateBabelExpression(node.right, knownConstants);
|
|
44
|
+
|
|
45
|
+
if (!left.confident || !right.confident) return UNKNOWN;
|
|
46
|
+
|
|
47
|
+
switch (node.operator) {
|
|
48
|
+
case "*":
|
|
49
|
+
return known(left.value * right.value);
|
|
50
|
+
case "+":
|
|
51
|
+
return known(left.value + right.value);
|
|
52
|
+
default:
|
|
53
|
+
return UNKNOWN;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function evaluateIdentifier(
|
|
58
|
+
node: babel.types.Identifier,
|
|
59
|
+
knownConstants: Record<string, any>,
|
|
60
|
+
): EvaluationResult {
|
|
61
|
+
if (node.name in knownConstants) {
|
|
62
|
+
return known(knownConstants[node.name]);
|
|
63
|
+
}
|
|
64
|
+
return UNKNOWN;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function evaluateMemberExpression(
|
|
68
|
+
node: babel.types.MemberExpression,
|
|
69
|
+
knownConstants: Record<string, any>,
|
|
70
|
+
): EvaluationResult {
|
|
71
|
+
const obj = evaluateBabelExpression(node.object, knownConstants);
|
|
72
|
+
|
|
73
|
+
const propertyNode = node.property;
|
|
74
|
+
let property: EvaluationResult;
|
|
75
|
+
if (node.computed) {
|
|
76
|
+
property = evaluateBabelExpression(propertyNode, knownConstants);
|
|
77
|
+
} else {
|
|
78
|
+
if (propertyNode.type === "Identifier") {
|
|
79
|
+
property = known(propertyNode.name);
|
|
80
|
+
} else {
|
|
81
|
+
return UNKNOWN;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!obj.confident || !property.confident) return UNKNOWN;
|
|
86
|
+
|
|
87
|
+
return known(obj.value[property.value]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function evaluateNumericLiteral(
|
|
91
|
+
node: babel.types.NumericLiteral,
|
|
92
|
+
): EvaluationResult {
|
|
93
|
+
return known(node.value);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function evaluateObjectExpression(
|
|
97
|
+
node: babel.types.ObjectExpression,
|
|
98
|
+
knownConstants: Record<string, any>,
|
|
99
|
+
): EvaluationResult {
|
|
100
|
+
let result: any = {};
|
|
101
|
+
|
|
102
|
+
for (const property of node.properties) {
|
|
103
|
+
switch (property.type) {
|
|
104
|
+
case "ObjectMethod":
|
|
105
|
+
return UNKNOWN;
|
|
106
|
+
case "SpreadElement":
|
|
107
|
+
return UNKNOWN;
|
|
108
|
+
case "ObjectProperty": {
|
|
109
|
+
const keyNode = property.key;
|
|
110
|
+
let key: EvaluationResult;
|
|
111
|
+
if (property.computed) {
|
|
112
|
+
key = evaluateBabelExpression(keyNode, knownConstants);
|
|
113
|
+
} else {
|
|
114
|
+
if (keyNode.type === "StringLiteral") {
|
|
115
|
+
key = known(keyNode.value);
|
|
116
|
+
} else if (keyNode.type === "Identifier") {
|
|
117
|
+
key = known(keyNode.name);
|
|
118
|
+
} else {
|
|
119
|
+
return UNKNOWN;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const value = evaluateBabelExpression(property.value, knownConstants);
|
|
123
|
+
if (!key || !key.confident || !value.confident) return UNKNOWN;
|
|
124
|
+
result[key.value] = value.value;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return known(result);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function evaluateStringLiteral(
|
|
133
|
+
node: babel.types.StringLiteral,
|
|
134
|
+
): EvaluationResult {
|
|
135
|
+
return known(node.value);
|
|
136
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./runtime.js";
|