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