@styleframe/transpiler 1.0.0

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.
Files changed (57) hide show
  1. package/.tsbuildinfo +1 -0
  2. package/CHANGELOG.md +12 -0
  3. package/package.json +43 -0
  4. package/src/constants.ts +4 -0
  5. package/src/consume/at-rule.test.ts +339 -0
  6. package/src/consume/at-rule.ts +34 -0
  7. package/src/consume/consume.test.ts +259 -0
  8. package/src/consume/consume.ts +60 -0
  9. package/src/consume/container.test.ts +501 -0
  10. package/src/consume/container.ts +73 -0
  11. package/src/consume/css.test.ts +184 -0
  12. package/src/consume/css.ts +17 -0
  13. package/src/consume/declarations.test.ts +210 -0
  14. package/src/consume/declarations.ts +17 -0
  15. package/src/consume/index.ts +12 -0
  16. package/src/consume/primitive.test.ts +52 -0
  17. package/src/consume/primitive.ts +16 -0
  18. package/src/consume/ref.test.ts +84 -0
  19. package/src/consume/ref.ts +22 -0
  20. package/src/consume/root.test.ts +353 -0
  21. package/src/consume/root.ts +19 -0
  22. package/src/consume/selector.test.ts +441 -0
  23. package/src/consume/selector.ts +17 -0
  24. package/src/consume/theme.test.ts +215 -0
  25. package/src/consume/theme.ts +15 -0
  26. package/src/consume/utility.test.ts +696 -0
  27. package/src/consume/utility.ts +31 -0
  28. package/src/consume/variable.test.ts +197 -0
  29. package/src/consume/variable.ts +20 -0
  30. package/src/defaults.ts +21 -0
  31. package/src/generator/genAtRuleQuery.test.ts +148 -0
  32. package/src/generator/genAtRuleQuery.ts +3 -0
  33. package/src/generator/genDeclaration.test.ts +283 -0
  34. package/src/generator/genDeclaration.ts +9 -0
  35. package/src/generator/genDeclarationsBlock.test.ts +278 -0
  36. package/src/generator/genDeclarationsBlock.ts +7 -0
  37. package/src/generator/genDeclareVariable.test.ts +323 -0
  38. package/src/generator/genDeclareVariable.ts +6 -0
  39. package/src/generator/genInlineAtRule.test.ts +351 -0
  40. package/src/generator/genInlineAtRule.ts +5 -0
  41. package/src/generator/genReferenceVariable.test.ts +392 -0
  42. package/src/generator/genReferenceVariable.ts +5 -0
  43. package/src/generator/genSafePropertyName.test.ts +489 -0
  44. package/src/generator/genSafePropertyName.ts +5 -0
  45. package/src/generator/genSafeVariableName.test.ts +358 -0
  46. package/src/generator/genSafeVariableName.ts +21 -0
  47. package/src/generator/genSelector.test.ts +357 -0
  48. package/src/generator/genSelector.ts +5 -0
  49. package/src/generator/index.ts +9 -0
  50. package/src/index.ts +6 -0
  51. package/src/transpile.test.ts +825 -0
  52. package/src/transpile.ts +21 -0
  53. package/src/types.ts +15 -0
  54. package/src/utils.ts +18 -0
  55. package/src/vite-env.d.ts +1 -0
  56. package/tsconfig.json +7 -0
  57. package/vite.config.ts +5 -0
@@ -0,0 +1,358 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { genSafeVariableName } from "./genSafeVariableName";
3
+
4
+ describe("genSafeVariableName", () => {
5
+ it("should add -- prefix to a simple name", () => {
6
+ const result = genSafeVariableName("primary-color");
7
+ expect(result).toBe("--primary-color");
8
+ });
9
+
10
+ it("should preserve existing -- prefix", () => {
11
+ const result = genSafeVariableName("--secondary-color");
12
+ expect(result).toBe("--secondary-color");
13
+ });
14
+
15
+ it("should add -- prefix to camelCase names", () => {
16
+ const result = genSafeVariableName("primaryColor");
17
+ expect(result).toBe("--primaryColor");
18
+ });
19
+
20
+ it("should add -- prefix to snake_case names", () => {
21
+ const result = genSafeVariableName("primary_color");
22
+ expect(result).toBe("--primary_color");
23
+ });
24
+
25
+ it("should add -- prefix to single word names", () => {
26
+ const result = genSafeVariableName("color");
27
+ expect(result).toBe("--color");
28
+ });
29
+
30
+ it("should add -- prefix to names with numbers", () => {
31
+ const result = genSafeVariableName("spacing-2");
32
+ expect(result).toBe("--spacing-2");
33
+ });
34
+
35
+ it("should add -- prefix to names starting with numbers", () => {
36
+ const result = genSafeVariableName("1-column");
37
+ expect(result).toBe("--1-column");
38
+ });
39
+
40
+ it("should add -- prefix to names ending with numbers", () => {
41
+ const result = genSafeVariableName("column-1");
42
+ expect(result).toBe("--column-1");
43
+ });
44
+
45
+ it("should handle names with only numbers", () => {
46
+ const result = genSafeVariableName("123");
47
+ expect(result).toBe("--123");
48
+ });
49
+
50
+ it("should handle single character names", () => {
51
+ const result = genSafeVariableName("x");
52
+ expect(result).toBe("--x");
53
+ });
54
+
55
+ it("should sanitize names with special characters (dots)", () => {
56
+ const result = genSafeVariableName("theme.primary");
57
+ expect(result).toBe("--theme-primary");
58
+ });
59
+
60
+ it("should sanitize names with colons", () => {
61
+ const result = genSafeVariableName("hover:color");
62
+ expect(result).toBe("--hover-color");
63
+ });
64
+
65
+ it("should sanitize names with forward slashes", () => {
66
+ const result = genSafeVariableName("size/large");
67
+ expect(result).toBe("--size-large");
68
+ });
69
+
70
+ it("should sanitize names with backslashes", () => {
71
+ const result = genSafeVariableName("size\\small");
72
+ expect(result).toBe("--size-small");
73
+ });
74
+
75
+ it("should sanitize names with square brackets", () => {
76
+ const result = genSafeVariableName("colors[primary]");
77
+ expect(result).toBe("--colors-primary-");
78
+ });
79
+
80
+ it("should sanitize names with parentheses", () => {
81
+ const result = genSafeVariableName("color(main)");
82
+ expect(result).toBe("--color-main-");
83
+ });
84
+
85
+ it("should sanitize names with curly braces", () => {
86
+ const result = genSafeVariableName("color{primary}");
87
+ expect(result).toBe("--color-primary-");
88
+ });
89
+
90
+ it("should sanitize names with plus signs", () => {
91
+ const result = genSafeVariableName("size+large");
92
+ expect(result).toBe("--size-large");
93
+ });
94
+
95
+ it("should sanitize names with asterisks", () => {
96
+ const result = genSafeVariableName("size*2");
97
+ expect(result).toBe("--size-2");
98
+ });
99
+
100
+ it("should sanitize names with equal signs", () => {
101
+ const result = genSafeVariableName("size=large");
102
+ expect(result).toBe("--size-large");
103
+ });
104
+
105
+ it("should sanitize names with question marks", () => {
106
+ const result = genSafeVariableName("enabled?");
107
+ expect(result).toBe("--enabled-");
108
+ });
109
+
110
+ it("should sanitize names with exclamation marks", () => {
111
+ const result = genSafeVariableName("important!");
112
+ expect(result).toBe("--important-");
113
+ });
114
+
115
+ it("should sanitize names with at signs", () => {
116
+ const result = genSafeVariableName("@media");
117
+ expect(result).toBe("---media");
118
+ });
119
+
120
+ it("should sanitize names with hash symbols", () => {
121
+ const result = genSafeVariableName("#primary");
122
+ expect(result).toBe("---primary");
123
+ });
124
+
125
+ it("should sanitize names with dollar signs", () => {
126
+ const result = genSafeVariableName("$variable");
127
+ expect(result).toBe("---variable");
128
+ });
129
+
130
+ it("should sanitize names with percent signs", () => {
131
+ const result = genSafeVariableName("size%");
132
+ expect(result).toBe("--size-");
133
+ });
134
+
135
+ it("should sanitize names with ampersands", () => {
136
+ const result = genSafeVariableName("black&white");
137
+ expect(result).toBe("--black-white");
138
+ });
139
+
140
+ it("should sanitize names with tildes", () => {
141
+ const result = genSafeVariableName("~approximate");
142
+ expect(result).toBe("---approximate");
143
+ });
144
+
145
+ it("should sanitize names with backticks", () => {
146
+ const result = genSafeVariableName("`template`");
147
+ expect(result).toBe("---template-");
148
+ });
149
+
150
+ it("should sanitize names with single quotes", () => {
151
+ const result = genSafeVariableName("'quoted'");
152
+ expect(result).toBe("---quoted-");
153
+ });
154
+
155
+ it("should sanitize names with double quotes", () => {
156
+ const result = genSafeVariableName('"quoted"');
157
+ expect(result).toBe("---quoted-");
158
+ });
159
+
160
+ it("should sanitize names with spaces", () => {
161
+ const result = genSafeVariableName("my variable");
162
+ expect(result).toBe("--my-variable");
163
+ });
164
+
165
+ it("should sanitize names with tabs", () => {
166
+ const result = genSafeVariableName("my\tvariable");
167
+ expect(result).toBe("--my-variable");
168
+ });
169
+
170
+ it("should sanitize names with newlines", () => {
171
+ const result = genSafeVariableName("my\nvariable");
172
+ expect(result).toBe("--my-variable");
173
+ });
174
+
175
+ it("should handle empty string", () => {
176
+ const result = genSafeVariableName("");
177
+ expect(result).toBe("--unknown-variable");
178
+ });
179
+
180
+ it("should handle name with only dashes", () => {
181
+ const result = genSafeVariableName("---");
182
+ expect(result).toBe("---");
183
+ });
184
+
185
+ it("should handle name with single dash", () => {
186
+ const result = genSafeVariableName("-");
187
+ expect(result).toBe("---");
188
+ });
189
+
190
+ it("should not add prefix to name already starting with --", () => {
191
+ const result = genSafeVariableName("--my-variable");
192
+ expect(result).toBe("--my-variable");
193
+ });
194
+
195
+ it("should normalize name with triple dashes", () => {
196
+ const result = genSafeVariableName("---extra");
197
+ expect(result).toBe("---extra");
198
+ });
199
+
200
+ it("should normalize name with quadruple dashes", () => {
201
+ const result = genSafeVariableName("----super-extra");
202
+ expect(result).toBe("----super-extra");
203
+ });
204
+
205
+ it("should normalize name starting with single dash", () => {
206
+ const result = genSafeVariableName("-webkit");
207
+ expect(result).toBe("---webkit");
208
+ });
209
+
210
+ it("should handle unicode characters", () => {
211
+ const result = genSafeVariableName("颜色");
212
+ expect(result).toBe("--颜色");
213
+ });
214
+
215
+ it("should handle emoji", () => {
216
+ const result = genSafeVariableName("🎨-color");
217
+ expect(result).toBe("--🎨-color");
218
+ });
219
+
220
+ it("should handle emoji only", () => {
221
+ const result = genSafeVariableName("🎉");
222
+ expect(result).toBe("--🎉");
223
+ });
224
+
225
+ it("should handle mixed ASCII and unicode", () => {
226
+ const result = genSafeVariableName("color-颜色");
227
+ expect(result).toBe("--color-颜色");
228
+ });
229
+
230
+ it("should handle Arabic text", () => {
231
+ const result = genSafeVariableName("لون");
232
+ expect(result).toBe("--لون");
233
+ });
234
+
235
+ it("should handle Hebrew text", () => {
236
+ const result = genSafeVariableName("צבע");
237
+ expect(result).toBe("--צבע");
238
+ });
239
+
240
+ it("should handle Cyrillic text", () => {
241
+ const result = genSafeVariableName("цвет");
242
+ expect(result).toBe("--цвет");
243
+ });
244
+
245
+ it("should handle Greek text", () => {
246
+ const result = genSafeVariableName("χρώμα");
247
+ expect(result).toBe("--χρώμα");
248
+ });
249
+
250
+ it("should handle mathematical symbols", () => {
251
+ const result = genSafeVariableName("π-value");
252
+ expect(result).toBe("--π-value");
253
+ });
254
+
255
+ it("should handle currency symbols", () => {
256
+ const result = genSafeVariableName("€-price");
257
+ expect(result).toBe("--€-price");
258
+ });
259
+
260
+ it("should sanitize mixed special characters", () => {
261
+ const result = genSafeVariableName("test@123#$%");
262
+ expect(result).toBe("--test-123---");
263
+ });
264
+
265
+ it("should handle very long names", () => {
266
+ const longName = "a".repeat(1000);
267
+ const result = genSafeVariableName(longName);
268
+ expect(result).toBe("--" + longName);
269
+ });
270
+
271
+ it("should sanitize names with control characters", () => {
272
+ const result = genSafeVariableName("test\0null");
273
+ expect(result).toBe("--test-null");
274
+ });
275
+
276
+ it("should sanitize names with escape sequences", () => {
277
+ const result = genSafeVariableName("test\\nline");
278
+ expect(result).toBe("--test-nline");
279
+ });
280
+
281
+ it("should preserve zero-width characters (non-ASCII < 0x80)", () => {
282
+ const result = genSafeVariableName("test\u200Bzero");
283
+ expect(result).toBe("--test\u200Bzero");
284
+ });
285
+
286
+ it("should be case-sensitive", () => {
287
+ const result1 = genSafeVariableName("MyVariable");
288
+ const result2 = genSafeVariableName("myvariable");
289
+ expect(result1).toBe("--MyVariable");
290
+ expect(result2).toBe("--myvariable");
291
+ expect(result1).not.toBe(result2);
292
+ });
293
+
294
+ it("should sanitize leading whitespace", () => {
295
+ const result = genSafeVariableName(" spacing");
296
+ expect(result).toBe("----spacing");
297
+ });
298
+
299
+ it("should sanitize trailing whitespace", () => {
300
+ const result = genSafeVariableName("spacing ");
301
+ expect(result).toBe("--spacing--");
302
+ });
303
+
304
+ it("should sanitize surrounding whitespace", () => {
305
+ const result = genSafeVariableName(" spacing ");
306
+ expect(result).toBe("----spacing--");
307
+ });
308
+
309
+ it("should sanitize name that looks like it starts with -- but doesn't", () => {
310
+ const result = genSafeVariableName("-​-tricky"); // Zero-width space after first dash
311
+ expect(result).toBe("---​-tricky");
312
+ });
313
+
314
+ it("should handle name with -- in the middle", () => {
315
+ const result = genSafeVariableName("my--variable");
316
+ expect(result).toBe("--my--variable");
317
+ });
318
+
319
+ it("should handle name ending with --", () => {
320
+ const result = genSafeVariableName("variable--");
321
+ expect(result).toBe("--variable--");
322
+ });
323
+
324
+ it("should handle BEM-style names", () => {
325
+ const result = genSafeVariableName("button__text--primary");
326
+ expect(result).toBe("--button__text--primary");
327
+ });
328
+
329
+ it("should sanitize namespace-style names", () => {
330
+ const result = genSafeVariableName("app.theme.color.primary");
331
+ expect(result).toBe("--app-theme-color-primary");
332
+ });
333
+
334
+ it("should sanitize path-style names", () => {
335
+ const result = genSafeVariableName("colors/primary/500");
336
+ expect(result).toBe("--colors-primary-500");
337
+ });
338
+
339
+ it("should handle CSS property-like names", () => {
340
+ const result = genSafeVariableName("margin-top");
341
+ expect(result).toBe("--margin-top");
342
+ });
343
+
344
+ it("should sanitize names that look like CSS functions", () => {
345
+ const result = genSafeVariableName("calc(100%)");
346
+ expect(result).toBe("--calc-100--");
347
+ });
348
+
349
+ it("should sanitize names with HTML entities", () => {
350
+ const result = genSafeVariableName("&nbsp;space");
351
+ expect(result).toBe("---nbsp-space");
352
+ });
353
+
354
+ it("should sanitize names with URL encoding", () => {
355
+ const result = genSafeVariableName("color%20primary");
356
+ expect(result).toBe("--color-20primary");
357
+ });
358
+ });
@@ -0,0 +1,21 @@
1
+ /**
2
+ * CSS variable names must start with -- and can only contain:
3
+ * - letters (a-z, A-Z)
4
+ * - digits (0-9)
5
+ * - hyphens (-)
6
+ * - underscores (_)
7
+ * - non-ASCII characters (code points >= 0x80)
8
+ */
9
+ export function genSafeVariableName(name: string) {
10
+ // Remove -- prefix if present to normalize
11
+ const normalized = name.startsWith("--") ? name.slice(2) : name;
12
+
13
+ // Replace invalid characters with hyphens
14
+ // Keep letters, digits, hyphens, underscores, and non-ASCII chars (>= 0x80)
15
+ const sanitized = normalized.replace(/[^a-zA-Z0-9_\-\u0080-\uFFFF]/g, "-");
16
+
17
+ // Ensure we have a valid name (not empty after sanitization)
18
+ const validName = sanitized || "unknown-variable";
19
+
20
+ return `--${validName}`;
21
+ }