@yak/react 0.0.0-stage → 10.0.0-rc.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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -2
  3. package/dist/context/baseContext.d.ts +5 -0
  4. package/dist/context/baseContext.js +8 -0
  5. package/dist/context/baseContext.js.map +1 -0
  6. package/dist/context/index.d.ts +20 -0
  7. package/dist/context/index.js +15 -0
  8. package/dist/context/index.js.map +1 -0
  9. package/dist/context/index.server.d.ts +9 -0
  10. package/dist/context/index.server.js +17 -0
  11. package/dist/context/index.server.js.map +1 -0
  12. package/dist/cross-file-resolver/index.d.ts +199 -0
  13. package/dist/cross-file-resolver/index.js +569 -0
  14. package/dist/cross-file-resolver/index.js.map +1 -0
  15. package/dist/index.d.ts +320 -0
  16. package/dist/index.js +2 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/internal.d.ts +452 -0
  19. package/dist/internal.js +363 -0
  20. package/dist/internal.js.map +1 -0
  21. package/dist/isolated-source-eval/index.d.ts +30 -0
  22. package/dist/isolated-source-eval/index.js +317 -0
  23. package/dist/isolated-source-eval/index.js.map +1 -0
  24. package/dist/isolated-source-eval/worker.js +59 -0
  25. package/dist/isolated-source-eval/worker.js.map +1 -0
  26. package/dist/jsx-dev-runtime.d.ts +7 -0
  27. package/dist/jsx-dev-runtime.js +2 -0
  28. package/dist/jsx-dev-runtime.js.map +1 -0
  29. package/dist/jsx-runtime.d.ts +38 -0
  30. package/dist/jsx-runtime.js +2 -0
  31. package/dist/jsx-runtime.js.map +1 -0
  32. package/dist/loaders/turbo-loader.d.ts +15 -0
  33. package/dist/loaders/turbo-loader.js +816 -0
  34. package/dist/loaders/turbo-loader.js.map +1 -0
  35. package/dist/loaders/vite-plugin.d.ts +103 -0
  36. package/dist/loaders/vite-plugin.js +885 -0
  37. package/dist/loaders/vite-plugin.js.map +1 -0
  38. package/dist/loaders/webpack-loader.d.ts +12 -0
  39. package/dist/loaders/webpack-loader.js +710 -0
  40. package/dist/loaders/webpack-loader.js.map +1 -0
  41. package/dist/rsbuild/index.d.ts +29 -0
  42. package/dist/rsbuild/index.js +51 -0
  43. package/dist/rsbuild/index.js.map +1 -0
  44. package/dist/static/chunk-DK3Fl9T5.js +1 -0
  45. package/dist/static/index.d.ts +28 -0
  46. package/dist/static/index.js +2 -0
  47. package/dist/static/index.js.map +1 -0
  48. package/dist/withYak/index.d.ts +112 -0
  49. package/dist/withYak/index.js +171 -0
  50. package/dist/withYak/index.js.map +1 -0
  51. package/loaders/lib/resolveCrossFileSelectors.ts +161 -0
  52. package/loaders/turbo-evaluator.ts +134 -0
  53. package/loaders/turbo-loader.ts +184 -0
  54. package/loaders/vite-plugin.ts +28 -0
  55. package/loaders/webpack-loader.ts +41 -0
  56. package/package.json +155 -3
  57. package/rsbuild/index.ts +91 -0
  58. package/runtime/__tests__/atoms.test.tsx +48 -0
  59. package/runtime/__tests__/attrs.test.tsx +490 -0
  60. package/runtime/__tests__/cssLiteral.test.tsx +503 -0
  61. package/runtime/__tests__/cssProp.test.tsx +392 -0
  62. package/runtime/__tests__/cssPropTest.tsx +227 -0
  63. package/runtime/__tests__/foldedJsxParity.test.tsx +117 -0
  64. package/runtime/__tests__/styled.test.tsx +653 -0
  65. package/runtime/__tests__/tsconfig.json +18 -0
  66. package/runtime/__tests__/typeTest.tsx +374 -0
  67. package/runtime/atoms.tsx +36 -0
  68. package/runtime/context/README.md +84 -0
  69. package/runtime/context/baseContext.tsx +5 -0
  70. package/runtime/context/index.server.tsx +22 -0
  71. package/runtime/context/index.tsx +36 -0
  72. package/runtime/cssLiteral.tsx +214 -0
  73. package/runtime/globalStyle.tsx +54 -0
  74. package/runtime/index.ts +37 -0
  75. package/runtime/internal.ts +42 -0
  76. package/runtime/internals/mergeClassNames.ts +23 -0
  77. package/runtime/internals/mergeCssProp.ts +69 -0
  78. package/runtime/internals/propMarkers.ts +20 -0
  79. package/runtime/internals/unitPostFix.ts +34 -0
  80. package/runtime/jsx-dev-runtime.ts +6 -0
  81. package/runtime/jsx-runtime.ts +48 -0
  82. package/runtime/keyframes.tsx +30 -0
  83. package/runtime/mocks/cssLiteral.ts +74 -0
  84. package/runtime/mocks/globalStyle.ts +14 -0
  85. package/runtime/mocks/keyframes.ts +29 -0
  86. package/runtime/mocks/styled.ts +8 -0
  87. package/runtime/publicStyledApi.ts +159 -0
  88. package/runtime/styled.tsx +372 -0
  89. package/runtime/styledDom.tsx +139 -0
  90. package/withYak/allow-global-css.ts +94 -0
  91. package/withYak/index.ts +268 -0
@@ -0,0 +1,816 @@
1
+ import { createRequire } from "node:module";
2
+ import { transform } from "@swc/core";
3
+ import { dirname } from "node:path";
4
+ import { relative } from "path";
5
+ import { parse } from "@babel/parser";
6
+ import { statSync } from "node:fs";
7
+
8
+ //#region \0rolldown/runtime.js
9
+ var __defProp = Object.defineProperty;
10
+ var __esmMin = (fn, res, err) => () => {
11
+ if (err) throw err[0];
12
+ try {
13
+ return fn && (res = fn(fn = 0)), res;
14
+ } catch (e) {
15
+ throw err = [e], e;
16
+ }
17
+ };
18
+ var __exportAll = (all, no_symbols) => {
19
+ let target = {};
20
+ for (var name in all) {
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true
24
+ });
25
+ }
26
+ if (!no_symbols) {
27
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
28
+ }
29
+ return target;
30
+ };
31
+
32
+ //#endregion
33
+ //#region ../yak-internals/cross-file-resolver/parseModule.ts
34
+ async function parseModule(context, modulePath) {
35
+ try {
36
+ if ((modulePath.endsWith(".yak.ts") || modulePath.endsWith(".yak.tsx") || modulePath.endsWith(".yak.js") || modulePath.endsWith(".yak.jsx")) && context.evaluateYakModule) return {
37
+ type: "yak",
38
+ exports: {
39
+ importYak: false,
40
+ named: objectToModuleExport(await context.evaluateYakModule(modulePath)),
41
+ all: []
42
+ },
43
+ path: modulePath
44
+ };
45
+ if (context.cache?.parse === void 0) return await uncachedParseModule(context, modulePath);
46
+ const cached = context.cache.parse.get(modulePath);
47
+ if (cached === void 0) {
48
+ const parsedModule = await uncachedParseModule(context, modulePath);
49
+ context.cache.parse.set(modulePath, parsedModule);
50
+ if (context.cache.parse.addDependency) context.cache.parse.addDependency(modulePath, modulePath);
51
+ return parsedModule;
52
+ }
53
+ return cached;
54
+ } catch (error) {
55
+ const causeMessage = error instanceof Error ? error.message : String(error);
56
+ throw new Error(`Error parsing file "${modulePath}"\n Caused by: ${causeMessage}`);
57
+ }
58
+ }
59
+ async function uncachedParseModule(context, modulePath) {
60
+ const exports = await context.extractExports(modulePath);
61
+ if (!exports.importYak) return {
62
+ type: "regular",
63
+ path: modulePath,
64
+ exports
65
+ };
66
+ const transformed = await context.getTransformed(modulePath);
67
+ const mixins = parseMixins(transformed.code);
68
+ return {
69
+ type: "regular",
70
+ path: modulePath,
71
+ js: transformed,
72
+ exports,
73
+ styledComponents: parseStyledComponents(transformed.code),
74
+ mixins
75
+ };
76
+ }
77
+ function parseMixins(sourceContents) {
78
+ const mixinParts = sourceContents.split("/*YAK EXPORTED MIXIN:");
79
+ let mixins = {};
80
+ for (let i = 1; i < mixinParts.length; i++) {
81
+ const [comment] = mixinParts[i].split("*/", 1);
82
+ const position = comment.indexOf("\n");
83
+ const name = comment.slice(0, position);
84
+ mixins[name] = {
85
+ type: "mixin",
86
+ value: comment.slice(position + 1),
87
+ nameParts: name.split(":").map((part) => decodeURIComponent(part))
88
+ };
89
+ }
90
+ return mixins;
91
+ }
92
+ function parseStyledComponents(sourceContents) {
93
+ const styledParts = sourceContents.split("/*YAK EXPORTED STYLED:");
94
+ let styledComponents = {};
95
+ for (let i = 1; i < styledParts.length; i++) {
96
+ const [comment] = styledParts[i].split("*/", 1);
97
+ const [componentName, className] = comment.split(":");
98
+ styledComponents[componentName] = {
99
+ type: "styled-component",
100
+ nameParts: componentName.split("."),
101
+ value: `.${className}`
102
+ };
103
+ }
104
+ return styledComponents;
105
+ }
106
+ function objectToModuleExport(object) {
107
+ return Object.fromEntries(Object.entries(object).map(([key, value]) => {
108
+ if (typeof value === "string" || typeof value === "number") return [key, {
109
+ type: "constant",
110
+ value
111
+ }];
112
+ else if (value && (typeof value === "object" || Array.isArray(value))) return [key, {
113
+ type: "record",
114
+ value: objectToModuleExport(value)
115
+ }];
116
+ else return [key, {
117
+ type: "unsupported",
118
+ hint: String(value)
119
+ }];
120
+ }));
121
+ }
122
+
123
+ //#endregion
124
+ //#region ../yak-internals/cross-file-resolver/Errors.ts
125
+ var CauseError = class CauseError extends Error {
126
+ constructor(message, options) {
127
+ super(`${message}${options?.cause ? `\n Caused by: ${typeof options.cause === "object" && options.cause !== null && "message" in options.cause ? options.cause.message : String(options.cause)}` : ""}`);
128
+ if (options?.cause instanceof CauseError && options.cause.circular) this.circular = true;
129
+ }
130
+ };
131
+ var ResolveError = class extends CauseError {};
132
+ var UnsupportedExportError = class extends ResolveError {};
133
+ var CircularDependencyError = class extends CauseError {
134
+ constructor(message, options) {
135
+ super(message, options);
136
+ this.circular = true;
137
+ }
138
+ };
139
+
140
+ //#endregion
141
+ //#region ../yak-internals/cross-file-resolver/resolveCrossFileConstant.ts
142
+ const yakCssImportRegex = /--yak-css-import:\s*url\("([^"]+)",?(|mixin|selector)\)(;?)/g;
143
+ async function resolveCrossFileConstant(context, filePath, css) {
144
+ const resolveCrossFileConstant = context.cache?.resolveCrossFileConstant;
145
+ if (resolveCrossFileConstant === void 0) return uncachedResolveCrossFileConstant(context, filePath, css);
146
+ const cacheKey = await sha1(filePath + ":" + css);
147
+ const cached = resolveCrossFileConstant.get(cacheKey);
148
+ if (cached === void 0) {
149
+ const resolvedCrossFilConstantPromise = uncachedResolveCrossFileConstant(context, filePath, css);
150
+ resolveCrossFileConstant.set(cacheKey, resolvedCrossFilConstantPromise);
151
+ if (resolveCrossFileConstant.addDependency) {
152
+ resolveCrossFileConstant.addDependency(cacheKey, filePath);
153
+ resolvedCrossFilConstantPromise.then((value) => {
154
+ for (const dep of value.dependencies) resolveCrossFileConstant.addDependency(cacheKey, dep);
155
+ });
156
+ }
157
+ return resolvedCrossFilConstantPromise;
158
+ }
159
+ return cached;
160
+ }
161
+ async function uncachedResolveCrossFileConstant(context, filePath, css) {
162
+ const yakImports = await parseYakCssImport(context, filePath, css);
163
+ if (yakImports.length === 0) return {
164
+ resolved: css,
165
+ dependencies: []
166
+ };
167
+ try {
168
+ const dependencies = /* @__PURE__ */ new Set();
169
+ const resolvedValues = await Promise.all(yakImports.map(async ({ moduleSpecifier, specifier }) => {
170
+ const { resolved: resolvedModule } = await resolveModule(context, moduleSpecifier);
171
+ const resolvedValue = await resolveModuleSpecifierRecursively(context, resolvedModule, specifier);
172
+ for (const dependency of resolvedValue.from) dependencies.add(dependency);
173
+ return resolvedValue;
174
+ }));
175
+ let result = css;
176
+ for (let i = yakImports.length - 1; i >= 0; i--) {
177
+ const { position, size, importKind, specifier, semicolon } = yakImports[i];
178
+ const resolved = resolvedValues[i];
179
+ let replacement;
180
+ if (resolved.type === "unresolved-tag") replacement = importKind === "mixin" ? "" : "undefined";
181
+ else {
182
+ if (importKind === "selector") {
183
+ if (resolved.type !== "styled-component" && resolved.type !== "constant") throw new Error(`Found "${resolved.type}" but expected a selector - did you forget a semicolon after "${specifier.join(".")}"?`);
184
+ }
185
+ replacement = resolved.type === "styled-component" ? resolved.value : resolved.value + (["}", ";"].includes(String(resolved.value).trimEnd().slice(-1)) ? "" : semicolon);
186
+ }
187
+ result = result.slice(0, position) + String(replacement) + result.slice(position + size);
188
+ }
189
+ return {
190
+ resolved: result,
191
+ dependencies: Array.from(dependencies)
192
+ };
193
+ } catch (error) {
194
+ throw new CauseError(`Error while resolving cross-file selectors in file "${filePath}"`, { cause: error });
195
+ }
196
+ }
197
+ async function parseYakCssImport(context, filePath, css) {
198
+ const yakImports = [];
199
+ for (const match of css.matchAll(yakCssImportRegex)) {
200
+ const [fullMatch, encodedArguments, importKind, semicolon] = match;
201
+ const [moduleSpecifier, ...specifier] = encodedArguments.split(":").map((entry) => decodeURIComponent(entry));
202
+ yakImports.push({
203
+ encodedArguments,
204
+ moduleSpecifier: await context.resolve(moduleSpecifier, filePath),
205
+ specifier,
206
+ importKind,
207
+ semicolon,
208
+ position: match.index,
209
+ size: fullMatch.length
210
+ });
211
+ }
212
+ return yakImports;
213
+ }
214
+ async function resolveModule(context, filePath) {
215
+ if (context.cache?.resolve === void 0) return uncachedResolveModule(context, filePath);
216
+ const cached = context.cache.resolve.get(filePath);
217
+ if (cached === void 0) {
218
+ const resolvedPromise = uncachedResolveModule(context, filePath);
219
+ context.cache.resolve.set(filePath, resolvedPromise);
220
+ if (context.cache.resolve.addDependency) {
221
+ context.cache.resolve.addDependency(filePath, filePath);
222
+ resolvedPromise.then((value) => {
223
+ for (const dep of value.dependencies) context.cache.resolve.addDependency(filePath, dep);
224
+ });
225
+ }
226
+ return resolvedPromise;
227
+ }
228
+ return cached;
229
+ }
230
+ async function uncachedResolveModule(context, filePath) {
231
+ const parsedModule = await context.parse(filePath);
232
+ const exports = parsedModule.exports;
233
+ if (parsedModule.type !== "regular") return {
234
+ resolved: {
235
+ path: parsedModule.path,
236
+ exports
237
+ },
238
+ dependencies: []
239
+ };
240
+ const dependencies = /* @__PURE__ */ new Set();
241
+ if (parsedModule.styledComponents) Object.values(parsedModule.styledComponents).map((styledComponent) => {
242
+ if (styledComponent.nameParts.length === 1) exports.named[styledComponent.nameParts[0]] = {
243
+ type: "styled-component",
244
+ className: styledComponent.value
245
+ };
246
+ else {
247
+ let exportEntry = exports.named[styledComponent.nameParts[0]];
248
+ if (!exportEntry) {
249
+ exportEntry = {
250
+ type: "record",
251
+ value: {}
252
+ };
253
+ exports.named[styledComponent.nameParts[0]] = exportEntry;
254
+ } else if (exportEntry.type !== "record") throw new CauseError(`Error parsing file "${parsedModule.path}"`, { cause: `"${styledComponent.nameParts[0]}" is not a record` });
255
+ let current = exportEntry.value;
256
+ for (let i = 1; i < styledComponent.nameParts.length - 1; i++) {
257
+ let next = current[styledComponent.nameParts[i]];
258
+ if (!next) {
259
+ next = {
260
+ type: "record",
261
+ value: {}
262
+ };
263
+ current[styledComponent.nameParts[i]] = next;
264
+ } else if (next.type !== "record") throw new CauseError(`Error parsing file "${parsedModule.path}"`, { cause: `"${styledComponent.nameParts.slice(0, i + 1).join(".")}" is not a record` });
265
+ current = next.value;
266
+ }
267
+ current[styledComponent.nameParts[styledComponent.nameParts.length - 1]] = {
268
+ type: "styled-component",
269
+ className: styledComponent.value
270
+ };
271
+ }
272
+ });
273
+ if (parsedModule.mixins) await Promise.all(Object.values(parsedModule.mixins).map(async (mixin) => {
274
+ const { resolved, dependencies: deps } = await resolveCrossFileConstant(context, parsedModule.path, mixin.value);
275
+ for (const dep of deps) dependencies.add(dep);
276
+ if (mixin.nameParts.length === 1) exports.named[mixin.nameParts[0]] = {
277
+ type: "mixin",
278
+ value: resolved
279
+ };
280
+ else {
281
+ let exportEntry = exports.named[mixin.nameParts[0]];
282
+ if (!exportEntry) {
283
+ exportEntry = {
284
+ type: "record",
285
+ value: {}
286
+ };
287
+ exports.named[mixin.nameParts[0]] = exportEntry;
288
+ } else if (exportEntry.type !== "record") throw new CauseError(`Error parsing file "${parsedModule.path}"`, { cause: `"${mixin.nameParts[0]}" is not a record` });
289
+ let current = exportEntry.value;
290
+ for (let i = 1; i < mixin.nameParts.length - 1; i++) {
291
+ let next = current[mixin.nameParts[i]];
292
+ if (!next) {
293
+ next = {
294
+ type: "record",
295
+ value: {}
296
+ };
297
+ current[mixin.nameParts[i]] = next;
298
+ } else if (next.type !== "record") throw new CauseError(`Error parsing file "${parsedModule.path}"`, { cause: `"${mixin.nameParts.slice(0, i + 1).join(".")}" is not a record` });
299
+ current = next.value;
300
+ }
301
+ current[mixin.nameParts[mixin.nameParts.length - 1]] = {
302
+ type: "mixin",
303
+ value: resolved
304
+ };
305
+ }
306
+ }));
307
+ return {
308
+ resolved: {
309
+ path: parsedModule.path,
310
+ exports
311
+ },
312
+ dependencies: Array.from(dependencies)
313
+ };
314
+ }
315
+ async function resolveModuleSpecifierRecursively(context, resolvedModule, specifiers, seen = /* @__PURE__ */ new Set()) {
316
+ const exportName = specifiers[0];
317
+ const exportValue = resolvedModule.exports.named[exportName];
318
+ if (exportValue !== void 0) {
319
+ if (seen.has(resolvedModule.path + ":" + exportName)) throw new CircularDependencyError(`Unable to resolve "${specifiers.join(".")}" in module "${resolvedModule.path}"`, { cause: "Circular dependency detected" });
320
+ seen.add(resolvedModule.path + ":" + exportName);
321
+ return resolveModuleExport(context, resolvedModule.path, exportValue, specifiers, seen);
322
+ }
323
+ let i = 1;
324
+ for (const from of resolvedModule.exports.all) {
325
+ if (context.exportAllLimit && i++ > context.exportAllLimit) throw new ResolveError(`Unable to resolve "${specifiers.join(".")}" in module "${resolvedModule.path}"`, { cause: `More than ${context.exportAllLimit} star exports are not supported for performance reasons` });
326
+ try {
327
+ const resolved = await resolveModuleExport(context, resolvedModule.path, {
328
+ type: "re-export",
329
+ from,
330
+ name: exportName
331
+ }, specifiers, seen);
332
+ if (seen.has(resolvedModule.path + ":*")) throw new CircularDependencyError(`Unable to resolve "${specifiers.join(".")}" in module "${resolvedModule.path}"`, { cause: "Circular dependency detected" });
333
+ seen.add(resolvedModule.path + ":*");
334
+ return resolved;
335
+ } catch (error) {
336
+ if (!(error instanceof ResolveError)) throw error;
337
+ if (error.circular) throw error;
338
+ }
339
+ }
340
+ throw new ResolveError(`Unable to resolve "${specifiers.join(".")}"`, { cause: `no matching export found in module "${resolvedModule.path}"` });
341
+ }
342
+ async function resolveModuleExport(context, filePath, moduleExport, specifiers, seen) {
343
+ const failureMessage = `Unable to resolve "${specifiers.join(".")}" in module "${filePath}"`;
344
+ try {
345
+ switch (moduleExport.type) {
346
+ case "re-export": {
347
+ const { resolved: reExportedModule } = await resolveModule(context, await context.resolve(moduleExport.from, filePath));
348
+ const resolved = await resolveModuleSpecifierRecursively(context, reExportedModule, [moduleExport.name, ...specifiers.slice(1)], seen);
349
+ if (resolved) resolved.from.push(filePath);
350
+ return resolved;
351
+ }
352
+ case "namespace-re-export": {
353
+ const { resolved: reExportedModule } = await resolveModule(context, await context.resolve(moduleExport.from, filePath));
354
+ const resolved = await resolveModuleSpecifierRecursively(context, reExportedModule, specifiers.slice(1), seen);
355
+ if (resolved) resolved.from.push(filePath);
356
+ return resolved;
357
+ }
358
+ case "styled-component": return {
359
+ type: "styled-component",
360
+ from: [filePath],
361
+ source: filePath,
362
+ name: specifiers[specifiers.length - 1],
363
+ value: moduleExport.className
364
+ };
365
+ case "tag-template": return {
366
+ type: "unresolved-tag",
367
+ from: [filePath],
368
+ source: filePath,
369
+ name: specifiers[specifiers.length - 1]
370
+ };
371
+ case "constant": return {
372
+ type: "constant",
373
+ from: [filePath],
374
+ source: filePath,
375
+ value: moduleExport.value
376
+ };
377
+ case "record": return resolveModuleExport(context, filePath, resolveSpecifierInRecord(moduleExport, specifiers[0], specifiers.slice(1)), specifiers, seen);
378
+ case "mixin": return {
379
+ type: "mixin",
380
+ from: [filePath],
381
+ source: filePath,
382
+ value: moduleExport.value
383
+ };
384
+ case "unsupported": throw new UnsupportedExportError(failureMessage, { cause: explainUnsupported(filePath, specifiers.join("."), moduleExport.hint, moduleExport.source) });
385
+ }
386
+ } catch (error) {
387
+ if (error instanceof UnsupportedExportError) throw error;
388
+ throw new ResolveError(failureMessage, { cause: error });
389
+ }
390
+ }
391
+ function explainUnsupported(filePath, specifier, hint, source) {
392
+ const isYakFile = /\.yak\.(?:ts|tsx|js|jsx)$/.test(filePath);
393
+ const docs = "https://yak.js.org/docs/migration-from-styled-components#move-some-code-to-yak-files";
394
+ const snippet = source ? renderSourceSnippet(filePath, source, hint ?? "") : void 0;
395
+ const lines = [];
396
+ if (isYakFile) {
397
+ const got = hint ? ` (got \`${hint}\`)` : "";
398
+ lines.push(`\`${specifier}\` evaluated to a value that cannot be inlined into CSS${got}.`);
399
+ if (snippet) lines.push(snippet);
400
+ lines.push(` help: replace it with a string, number, or plain object/array of those`, ` see: ${docs}`);
401
+ return lines.join("\n");
402
+ }
403
+ const got = hint ? ` (got a ${hint})` : "";
404
+ lines.push(`\`${specifier}\` is not a string or number literal${got}.`);
405
+ if (snippet) lines.push(snippet);
406
+ lines.push(` help: rename "${filePath}" to "${suggestYakFileName(filePath)}" so its exports run at build time`, ` (or replace \`${specifier}\` with a literal value)`, ` see: ${docs}`);
407
+ return lines.join("\n");
408
+ }
409
+ function suggestYakFileName(filePath) {
410
+ const match = filePath.match(/^(.*)\.(ts|tsx|js|jsx)$/);
411
+ if (!match) return filePath;
412
+ return `${match[1]}.yak.${match[2]}`;
413
+ }
414
+ function renderSourceSnippet(filePath, source, label) {
415
+ const startLine = source.start.line;
416
+ const startCol = source.start.column;
417
+ const caretLen = source.end.line === startLine ? Math.max(1, source.end.column - startCol) : Math.max(1, source.lineText.length - startCol);
418
+ const lineNumStr = String(startLine);
419
+ const gutterPad = " ".repeat(lineNumStr.length);
420
+ return [
421
+ ` --> ${filePath}:${startLine}:${startCol + 1}`,
422
+ ` ${gutterPad} |`,
423
+ ` ${lineNumStr} | ${source.lineText}`,
424
+ ` ${gutterPad} | ${" ".repeat(startCol)}${"^".repeat(caretLen)} ${label}`
425
+ ].join("\n");
426
+ }
427
+ function resolveSpecifierInRecord(record, name, specifiers) {
428
+ if (specifiers.length === 0) throw new ResolveError("did not expect an object");
429
+ let depth = 0;
430
+ let current = record;
431
+ while (current && current.type === "record" && depth < specifiers.length) {
432
+ current = current.value[specifiers[depth]];
433
+ depth += 1;
434
+ }
435
+ if (current === void 0 || depth !== specifiers.length) throw new ResolveError(`Unable to resolve "${specifiers.join(".")}" in object/array "${name}"`, { cause: "path not found" });
436
+ if (current.type === "constant" || current.type === "styled-component" || current.type === "mixin") return current;
437
+ if (current.type === "record" && "__yak" in current.value && current.value.__yak.type === "constant") return {
438
+ type: "mixin",
439
+ value: String(current.value.__yak.value)
440
+ };
441
+ throw new ResolveError(`Unable to resolve "${specifiers.join(".")}" in object/array "${name}"`, { cause: "only string and numbers are supported" });
442
+ }
443
+ async function sha1(message) {
444
+ const resultBuffer = await globalThis.crypto.subtle.digest("SHA-1", new TextEncoder().encode(message));
445
+ return Array.from(new Uint8Array(resultBuffer), (byte) => byte.toString(16).padStart(2, "0")).join("");
446
+ }
447
+
448
+ //#endregion
449
+ //#region ../yak-internals/loaders/lib/debugLogger.ts
450
+ function createDebugLogger(debugOptions, rootPath) {
451
+ if (!debugOptions) return () => {};
452
+ const pattern = debugOptions === true ? void 0 : debugOptions.pattern;
453
+ const typesArray = debugOptions === true ? void 0 : debugOptions.types;
454
+ let compiledPattern = null;
455
+ if (pattern) try {
456
+ compiledPattern = new RegExp(pattern);
457
+ } catch (error) {
458
+ throw new Error(`Invalid debug pattern: "${pattern}" is not a valid regular expression. ${error instanceof Error ? error.message : ""}`);
459
+ }
460
+ const types = typesArray ? new Set(typesArray) : null;
461
+ return (messageType, message, filePath) => {
462
+ if (types && !types.has(messageType)) return;
463
+ const relativePath = relative(rootPath, filePath);
464
+ if (!compiledPattern || compiledPattern.test(relativePath)) console.log("🐮 Yak", `[${messageType}]`, relativePath, "\n\n", message);
465
+ };
466
+ }
467
+
468
+ //#endregion
469
+ //#region ../yak-internals/loaders/lib/extractCss.ts
470
+ function extractCss(code) {
471
+ let codeString;
472
+ if (typeof code === "string") codeString = code;
473
+ else if (code instanceof Buffer) codeString = code.toString("utf-8");
474
+ else if (code instanceof ArrayBuffer) codeString = new TextDecoder("utf-8").decode(code);
475
+ else throw new Error("Invalid input type: code must be string, Buffer, or ArrayBuffer");
476
+ const codeParts = codeString.split("/*YAK Extracted CSS:\n");
477
+ let result = "";
478
+ for (let i = 1; i < codeParts.length; i++) {
479
+ const codeUntilEnd = codeParts[i].split("*/")[0];
480
+ result += codeUntilEnd;
481
+ }
482
+ return result;
483
+ }
484
+
485
+ //#endregion
486
+ //#region ../yak-internals/packageNames.ts
487
+ const yakPackageNames = ["@yak/react", "@yak/solid"];
488
+
489
+ //#endregion
490
+ //#region ../yak-internals/loaders/lib/parseExports.ts
491
+ async function parseExports(sourceContents) {
492
+ try {
493
+ const ast = parse(sourceContents, {
494
+ sourceType: "module",
495
+ plugins: ["jsx", "typescript"]
496
+ });
497
+ const moduleExports = {
498
+ importYak: ast.program.body.some((node) => node.type === "ImportDeclaration" && yakPackageNames.includes(node.source.value)),
499
+ named: {},
500
+ all: []
501
+ };
502
+ const variableDeclarations = {};
503
+ const importBindings = {};
504
+ const localExportSpecifiers = [];
505
+ let defaultIdentifier = null;
506
+ for (const node of ast.program.body) {
507
+ if (node.type === "ImportDeclaration") {
508
+ for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") importBindings[specifier.local.name] = {
509
+ type: "re-export",
510
+ from: node.source.value,
511
+ name: specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value
512
+ };
513
+ else if (specifier.type === "ImportDefaultSpecifier") importBindings[specifier.local.name] = {
514
+ type: "re-export",
515
+ from: node.source.value,
516
+ name: "default"
517
+ };
518
+ else if (specifier.type === "ImportNamespaceSpecifier") importBindings[specifier.local.name] = {
519
+ type: "namespace-re-export",
520
+ from: node.source.value
521
+ };
522
+ }
523
+ if (node.type === "VariableDeclaration") {
524
+ for (const decl of node.declarations) if (decl.id.type === "Identifier" && decl.init) variableDeclarations[decl.id.name] = decl.init;
525
+ }
526
+ if (node.type === "ExportNamedDeclaration") {
527
+ if (node.source) for (const specifier of node.specifiers) {
528
+ if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier" && specifier.local.type === "Identifier") moduleExports.named[specifier.exported.name] = {
529
+ type: "re-export",
530
+ from: node.source.value,
531
+ name: specifier.local.name
532
+ };
533
+ if (specifier.type === "ExportNamespaceSpecifier" && specifier.exported.type === "Identifier") moduleExports.named[specifier.exported.name] = {
534
+ type: "namespace-re-export",
535
+ from: node.source.value
536
+ };
537
+ }
538
+ else if (!node.declaration) {
539
+ for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier" && specifier.local.type === "Identifier") localExportSpecifiers.push({
540
+ local: specifier.local.name,
541
+ exported: specifier.exported.name
542
+ });
543
+ } else if (node.declaration.type === "VariableDeclaration") {
544
+ for (const declaration of node.declaration.declarations) if (declaration.id.type === "Identifier" && declaration.init) {
545
+ variableDeclarations[declaration.id.name] = declaration.init;
546
+ const parsed = parseExportValueExpression(declaration.init, sourceContents);
547
+ if (parsed) moduleExports.named[declaration.id.name] = parsed;
548
+ }
549
+ }
550
+ }
551
+ if (node.type === "ExportDefaultDeclaration") {
552
+ if (node.declaration.type === "Identifier") defaultIdentifier = node.declaration.name;
553
+ else if (node.declaration.type === "FunctionDeclaration" || node.declaration.type === "ClassDeclaration") moduleExports.named["default"] = {
554
+ type: "unsupported",
555
+ hint: node.declaration.type,
556
+ source: extractUnsupportedSource(node.declaration.loc, sourceContents)
557
+ };
558
+ else moduleExports.named["default"] = parseExportValueExpression(node.declaration, sourceContents);
559
+ }
560
+ if (node.type === "ExportAllDeclaration") moduleExports.all.push(node.source.value);
561
+ }
562
+ const resolveIdentifier = (name) => {
563
+ if (variableDeclarations[name]) return parseExportValueExpression(variableDeclarations[name], sourceContents);
564
+ return importBindings[name];
565
+ };
566
+ for (const { local, exported } of localExportSpecifiers) {
567
+ const resolved = resolveIdentifier(local);
568
+ if (resolved) moduleExports.named[exported] = resolved;
569
+ }
570
+ if (defaultIdentifier) {
571
+ const resolved = resolveIdentifier(defaultIdentifier);
572
+ if (resolved) moduleExports.named["default"] = resolved;
573
+ }
574
+ return moduleExports;
575
+ } catch (error) {
576
+ throw new Error(`Error parsing exports: ${error.message}`);
577
+ }
578
+ }
579
+ function unpackTSAsExpression(node) {
580
+ if (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") return unpackTSAsExpression(node.expression);
581
+ return node;
582
+ }
583
+ function parseExportValueExpression(node, code) {
584
+ const expression = unpackTSAsExpression(node);
585
+ if (expression.type === "CallExpression" || expression.type === "TaggedTemplateExpression") return { type: "tag-template" };
586
+ else if (expression.type === "StringLiteral" || expression.type === "NumericLiteral") return {
587
+ type: "constant",
588
+ value: expression.value
589
+ };
590
+ else if (expression.type === "UnaryExpression" && expression.operator === "-" && expression.argument.type === "NumericLiteral") return {
591
+ type: "constant",
592
+ value: -expression.argument.value
593
+ };
594
+ else if (expression.type === "TemplateLiteral" && expression.quasis.length === 1) return {
595
+ type: "constant",
596
+ value: expression.quasis[0].value.raw
597
+ };
598
+ else if (expression.type === "ObjectExpression") return {
599
+ type: "record",
600
+ value: parseObjectExpression(expression, code)
601
+ };
602
+ return {
603
+ type: "unsupported",
604
+ hint: expression.type,
605
+ source: extractUnsupportedSource(expression.loc, code)
606
+ };
607
+ }
608
+ function parseObjectExpression(node, code) {
609
+ let result = {};
610
+ for (const property of node.properties) if (property.type === "ObjectProperty" && property.key.type === "Identifier") {
611
+ const key = property.key.name;
612
+ const parsed = parseExportValueExpression(property.value, code);
613
+ if (parsed) result[key] = parsed;
614
+ }
615
+ return result;
616
+ }
617
+ function extractUnsupportedSource(loc, code) {
618
+ if (!loc || !code) return void 0;
619
+ const lineText = code.split(/\r?\n/)[loc.start.line - 1];
620
+ if (lineText === void 0) return void 0;
621
+ return {
622
+ start: {
623
+ line: loc.start.line,
624
+ column: loc.start.column
625
+ },
626
+ end: {
627
+ line: loc.end.line,
628
+ column: loc.end.column
629
+ },
630
+ lineText
631
+ };
632
+ }
633
+
634
+ //#endregion
635
+ //#region ../yak-internals/loaders/lib/swcParserOptions.ts
636
+ const typeScriptWithoutJsx = /\.[mc]?ts$/;
637
+ const typeScriptWithJsx = /\.tsx$/;
638
+ function getSwcParserOptions(filename) {
639
+ const [path] = filename.split("?");
640
+ if (typeScriptWithoutJsx.test(path)) return {
641
+ syntax: "typescript",
642
+ tsx: false,
643
+ dynamicImport: true
644
+ };
645
+ if (typeScriptWithJsx.test(path)) return {
646
+ syntax: "typescript",
647
+ tsx: true,
648
+ dynamicImport: true
649
+ };
650
+ return {
651
+ syntax: "ecmascript",
652
+ jsx: true,
653
+ dynamicImport: true
654
+ };
655
+ }
656
+
657
+ //#endregion
658
+ //#region loaders/turbo-evaluator.ts
659
+ var turbo_evaluator_exports = /* @__PURE__ */ __exportAll({
660
+ createCompilationEvaluator: () => createCompilationEvaluator,
661
+ getEvaluatorSingleton: () => getEvaluatorSingleton
662
+ });
663
+ function invalidateDependenciesWithDiskModifications(evaluator) {
664
+ const modificationTimes = getFileModificationTimes();
665
+ const modifiedDependencies = [];
666
+ for (const [dep, lastModificationTime] of modificationTimes) try {
667
+ const currentModificationTime = statSync(dep).mtimeMs;
668
+ if (currentModificationTime !== lastModificationTime) {
669
+ modifiedDependencies.push(dep);
670
+ modificationTimes.set(dep, currentModificationTime);
671
+ }
672
+ } catch {
673
+ modifiedDependencies.push(dep);
674
+ modificationTimes.delete(dep);
675
+ }
676
+ if (modifiedDependencies.length > 0) evaluator.invalidate(...modifiedDependencies);
677
+ }
678
+ function recordModificationTimes(deps) {
679
+ const modificationTimes = getFileModificationTimes();
680
+ for (const dep of deps) try {
681
+ modificationTimes.set(dep, statSync(dep).mtimeMs);
682
+ } catch {}
683
+ }
684
+ async function createCompilationEvaluator() {
685
+ const evaluator = await getEvaluatorSingleton();
686
+ invalidateDependenciesWithDiskModifications(evaluator);
687
+ return async (modulePath, onDependency) => {
688
+ const result = await evaluator.evaluate(modulePath);
689
+ if (!result.ok) {
690
+ const error = new Error(result.error.message);
691
+ if (result.error.stack) error.stack = result.error.stack;
692
+ throw error;
693
+ }
694
+ recordModificationTimes(result.dependencies);
695
+ if (onDependency) for (const dep of result.dependencies) onDependency(dep);
696
+ return result.value;
697
+ };
698
+ }
699
+ var EVALUATOR_KEY, MTIMES_KEY, getFileModificationTimes, getEvaluatorSingleton;
700
+ var init_turbo_evaluator = __esmMin((() => {
701
+ EVALUATOR_KEY = Symbol.for("@yak/react-evaluator");
702
+ MTIMES_KEY = Symbol.for("@yak/react-mtimes");
703
+ getFileModificationTimes = () => globalThis[MTIMES_KEY] ??= /* @__PURE__ */ new Map();
704
+ getEvaluatorSingleton = async () => {
705
+ const processGlobal = globalThis;
706
+ if (!processGlobal[EVALUATOR_KEY]) {
707
+ processGlobal[EVALUATOR_KEY] = import("../isolated-source-eval/index.js").then(({ createEvaluator }) => createEvaluator());
708
+ process.on("beforeExit", async () => {
709
+ await (await processGlobal[EVALUATOR_KEY]).dispose();
710
+ });
711
+ }
712
+ return processGlobal[EVALUATOR_KEY];
713
+ };
714
+ }));
715
+
716
+ //#endregion
717
+ //#region loaders/turbo-loader.ts
718
+ const yakSwcPluginPath = createRequire(import.meta.url).resolve("@yak/swc");
719
+ const dataUrlImportPrefix = "import \"data:text/css;base64,";
720
+ async function cssExtractLoader(code, sourceMap) {
721
+ const callback = this.async();
722
+ if (!code.includes("@yak/react")) return callback(null, code, sourceMap);
723
+ const { yakPluginOptions, yakOptions: { debug } } = this.getOptions();
724
+ const debugLog = createDebugLogger(debug, this.rootContext);
725
+ const resolveTurbopack = this.getResolve({});
726
+ const transform = createTransform(yakPluginOptions, yakSwcPluginPath);
727
+ const resolveFn = (specifier, importer) => {
728
+ return new Promise((resolve, reject) => {
729
+ resolveTurbopack(dirname(importer), specifier, (err, result) => {
730
+ if (err) return reject(err);
731
+ if (!result) return reject(/* @__PURE__ */ new Error(`Could not resolve ${specifier}`));
732
+ resolve(result);
733
+ });
734
+ });
735
+ };
736
+ const crossFileDeps = /* @__PURE__ */ new Set();
737
+ let evaluate;
738
+ const fsReadFile = (filePath) => {
739
+ crossFileDeps.add(filePath);
740
+ return new Promise((resolve, reject) => this.fs.readFile(filePath, "utf-8", (err, result) => {
741
+ if (err) return reject(err);
742
+ if (!result) return reject(/* @__PURE__ */ new Error(`File not found: ${filePath}`));
743
+ resolve(result);
744
+ }));
745
+ };
746
+ try {
747
+ const result = await transform(code, this.resourcePath, this.rootContext, sourceMap);
748
+ debugLog("ts", result.code, this.resourcePath);
749
+ let css = extractCss(result.code);
750
+ debugLog("css", css, this.resourcePath);
751
+ const { resolved } = await resolveCrossFileConstant({
752
+ parse: (modulePath) => {
753
+ return parseModule({
754
+ extractExports: async (modulePath) => {
755
+ const sourceContents = await fsReadFile(modulePath);
756
+ return parseExports(sourceContents);
757
+ },
758
+ getTransformed: async (modulePath) => {
759
+ const sourceContent = await fsReadFile(modulePath);
760
+ return transform(sourceContent, modulePath, this.rootContext);
761
+ },
762
+ evaluateYakModule: async (modulePath) => {
763
+ crossFileDeps.add(modulePath);
764
+ evaluate ??= await (await Promise.resolve().then(() => (init_turbo_evaluator(), turbo_evaluator_exports))).createCompilationEvaluator();
765
+ return evaluate(modulePath, (dep) => crossFileDeps.add(dep));
766
+ }
767
+ }, modulePath);
768
+ },
769
+ resolve: resolveFn
770
+ }, this.resourcePath, css);
771
+ for (const dep of crossFileDeps) this.addDependency(dep);
772
+ const codeWithCrossFileResolved = replaceDataUrlImport(result.code, resolved);
773
+ debugLog("css-resolved", resolved, this.resourcePath);
774
+ return callback(null, codeWithCrossFileResolved, result.map ? JSON.parse(result.map) : void 0);
775
+ } catch (error) {
776
+ for (const dep of crossFileDeps) this.addDependency(dep);
777
+ return callback(error instanceof Error ? error : new Error(String(error)));
778
+ }
779
+ }
780
+ function replaceDataUrlImport(code, resolvedCss) {
781
+ const lines = code.split("\n");
782
+ const lineIndex = lines.findIndex((line) => line.trimStart().startsWith(dataUrlImportPrefix));
783
+ if (lineIndex === -1) return code;
784
+ lines[lineIndex] = `${dataUrlImportPrefix}${Buffer.from(resolvedCss).toString("base64")}";`;
785
+ return lines.join("\n");
786
+ }
787
+ function createTransform(yakPluginOptions, yakSwcPluginPath) {
788
+ return (data, modulePath, rootPath, sourceMap) => transform(data, {
789
+ filename: modulePath,
790
+ inputSourceMap: sourceMap,
791
+ sourceMaps: true,
792
+ sourceFileName: modulePath,
793
+ sourceRoot: rootPath,
794
+ jsc: {
795
+ parser: getSwcParserOptions(modulePath),
796
+ experimental: {
797
+ keepImportAttributes: true,
798
+ plugins: [[yakSwcPluginPath, yakPluginOptions]]
799
+ },
800
+ transform: { react: { runtime: "preserve" } },
801
+ target: "es2022",
802
+ loose: false,
803
+ minify: {
804
+ compress: false,
805
+ mangle: false
806
+ },
807
+ preserveAllComments: true
808
+ },
809
+ minify: false,
810
+ isModule: true
811
+ });
812
+ }
813
+
814
+ //#endregion
815
+ export { cssExtractLoader as default };
816
+ //# sourceMappingURL=turbo-loader.js.map