next-yak 5.7.2 → 6.1.0-next.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/dist/loaders/css-loader.js +638 -303
- package/dist/loaders/css-loader.js.map +1 -1
- package/loaders/lib/resolveCrossFileSelectors.ts +117 -535
- package/package.json +4 -4
|
@@ -1,215 +1,677 @@
|
|
|
1
1
|
// loaders/css-loader.ts
|
|
2
2
|
import { relative } from "path";
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
// cross-file-resolver/parseModule.ts
|
|
5
|
+
async function parseModule(context, modulePath) {
|
|
6
|
+
try {
|
|
7
|
+
const isYak = modulePath.endsWith(".yak.ts") || modulePath.endsWith(".yak.tsx") || modulePath.endsWith(".yak.js") || modulePath.endsWith(".yak.jsx");
|
|
8
|
+
if (isYak && context.evaluateYakModule) {
|
|
9
|
+
const yakModule = await context.evaluateYakModule(modulePath);
|
|
10
|
+
const yakExports = objectToModuleExport(yakModule);
|
|
11
|
+
return {
|
|
12
|
+
type: "yak",
|
|
13
|
+
exports: { importYak: false, named: yakExports, all: [] },
|
|
14
|
+
path: modulePath
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
if (context.cache?.parse === void 0) {
|
|
18
|
+
return uncachedParseModule(context, modulePath);
|
|
19
|
+
}
|
|
20
|
+
const cached = context.cache.parse.get(modulePath);
|
|
21
|
+
if (cached === void 0) {
|
|
22
|
+
const parsedModule = await uncachedParseModule(context, modulePath);
|
|
23
|
+
context.cache.parse.set(modulePath, parsedModule);
|
|
24
|
+
if (context.cache.parse.addDependency) {
|
|
25
|
+
context.cache.parse.addDependency(modulePath, modulePath);
|
|
26
|
+
}
|
|
27
|
+
return parsedModule;
|
|
28
|
+
}
|
|
29
|
+
return cached;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Error parsing file ${modulePath}: ${error.message}`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function uncachedParseModule(context, modulePath) {
|
|
37
|
+
const exports = await context.extractExports(modulePath);
|
|
38
|
+
if (!exports.importYak) {
|
|
39
|
+
return {
|
|
40
|
+
type: "regular",
|
|
41
|
+
path: modulePath,
|
|
42
|
+
exports
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const transformed = await context.getTransformed(modulePath);
|
|
46
|
+
const mixins = parseMixins(transformed.code);
|
|
47
|
+
const styledComponents = parseStyledComponents(
|
|
48
|
+
transformed.code,
|
|
49
|
+
context.transpilationMode
|
|
50
|
+
);
|
|
51
|
+
return {
|
|
52
|
+
type: "regular",
|
|
53
|
+
path: modulePath,
|
|
54
|
+
js: transformed,
|
|
55
|
+
exports,
|
|
56
|
+
styledComponents,
|
|
57
|
+
mixins
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function parseMixins(sourceContents) {
|
|
61
|
+
const mixinParts = sourceContents.split("/*YAK EXPORTED MIXIN:");
|
|
62
|
+
let mixins = {};
|
|
63
|
+
for (let i = 1; i < mixinParts.length; i++) {
|
|
64
|
+
const [comment] = mixinParts[i].split("*/", 1);
|
|
65
|
+
const position = comment.indexOf("\n");
|
|
66
|
+
const name = comment.slice(0, position);
|
|
67
|
+
const value = comment.slice(position + 1);
|
|
68
|
+
mixins[name] = {
|
|
69
|
+
type: "mixin",
|
|
70
|
+
value,
|
|
71
|
+
nameParts: name.split(":").map((part) => decodeURIComponent(part))
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return mixins;
|
|
75
|
+
}
|
|
76
|
+
function parseStyledComponents(sourceContents, transpilationMode) {
|
|
77
|
+
const styledParts = sourceContents.split("/*YAK EXPORTED STYLED:");
|
|
78
|
+
let styledComponents = {};
|
|
79
|
+
for (let i = 1; i < styledParts.length; i++) {
|
|
80
|
+
const [comment] = styledParts[i].split("*/", 1);
|
|
81
|
+
const [componentName, className] = comment.split(":");
|
|
82
|
+
styledComponents[componentName] = {
|
|
83
|
+
type: "styled-component",
|
|
84
|
+
nameParts: componentName.split("."),
|
|
85
|
+
value: transpilationMode === "Css" ? `.${className}` : `:global(.${className})`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return styledComponents;
|
|
89
|
+
}
|
|
90
|
+
function objectToModuleExport(object) {
|
|
91
|
+
return Object.fromEntries(
|
|
92
|
+
Object.entries(object).map(([key, value]) => {
|
|
93
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
94
|
+
return [key, { type: "constant", value }];
|
|
95
|
+
} else if (value && (typeof value === "object" || Array.isArray(value))) {
|
|
96
|
+
return [
|
|
97
|
+
key,
|
|
98
|
+
{ type: "record", value: objectToModuleExport(value) }
|
|
99
|
+
];
|
|
100
|
+
} else {
|
|
101
|
+
return [key, { type: "unsupported", hint: String(value) }];
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// cross-file-resolver/Errors.ts
|
|
108
|
+
var CauseError = class _CauseError extends Error {
|
|
109
|
+
constructor(message, options) {
|
|
110
|
+
super(
|
|
111
|
+
`${message}${options?.cause ? `
|
|
112
|
+
Caused by: ${typeof options.cause === "object" && options.cause !== null && "message" in options.cause ? options.cause.message : String(options.cause)}` : ""}`
|
|
113
|
+
);
|
|
114
|
+
if (options?.cause instanceof _CauseError && options.cause.circular) {
|
|
115
|
+
this.circular = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var ResolveError = class extends CauseError {
|
|
120
|
+
};
|
|
121
|
+
var CircularDependencyError = class extends CauseError {
|
|
122
|
+
constructor(message, options) {
|
|
123
|
+
super(message, options);
|
|
124
|
+
this.circular = true;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// cross-file-resolver/resolveCrossFileConstant.ts
|
|
8
129
|
var yakCssImportRegex = (
|
|
9
130
|
// Make mixin and selector non optional once we dropped support for the babel plugin
|
|
10
131
|
/--yak-css-import\:\s*url\("([^"]+)",?(|mixin|selector)\)(;?)/g
|
|
11
132
|
);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!compilation) {
|
|
16
|
-
throw new Error("Webpack compilation object not available");
|
|
133
|
+
async function resolveCrossFileConstant(context, filePath, css) {
|
|
134
|
+
if (context.cache?.resolveCrossFileConstant === void 0) {
|
|
135
|
+
return uncachedResolveCrossFileConstant(context, filePath, css);
|
|
17
136
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
137
|
+
const cacheKey = await sha1(filePath + ":" + css);
|
|
138
|
+
const cached = context.cache.resolveCrossFileConstant.get(cacheKey);
|
|
139
|
+
if (cached === void 0) {
|
|
140
|
+
const resolvedCrossFilConstantPromise = uncachedResolveCrossFileConstant(
|
|
141
|
+
context,
|
|
142
|
+
filePath,
|
|
143
|
+
css
|
|
144
|
+
);
|
|
145
|
+
context.cache.resolveCrossFileConstant.set(
|
|
146
|
+
filePath,
|
|
147
|
+
resolvedCrossFilConstantPromise
|
|
148
|
+
);
|
|
149
|
+
if (context.cache.resolveCrossFileConstant.addDependency) {
|
|
150
|
+
context.cache.resolveCrossFileConstant.addDependency(filePath, filePath);
|
|
151
|
+
resolvedCrossFilConstantPromise.then((value) => {
|
|
152
|
+
for (const dep of value.dependencies) {
|
|
153
|
+
context.cache.resolveCrossFileConstant.addDependency(
|
|
154
|
+
filePath,
|
|
155
|
+
dep
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return resolvedCrossFilConstantPromise;
|
|
161
|
+
}
|
|
162
|
+
return cached;
|
|
163
|
+
}
|
|
164
|
+
async function uncachedResolveCrossFileConstant(context, filePath, css) {
|
|
165
|
+
const yakImports = await parseYakCssImport(context, filePath, css);
|
|
166
|
+
if (yakImports.length === 0) {
|
|
167
|
+
return { resolved: css, dependencies: [] };
|
|
24
168
|
}
|
|
25
|
-
return cache;
|
|
26
|
-
};
|
|
27
|
-
async function resolveCrossFileConstant(loader, pathContext, css) {
|
|
28
|
-
const matches = [...css.matchAll(yakCssImportRegex)].map((match) => {
|
|
29
|
-
const [fullMatch, encodedArguments, importKind, semicolon] = match;
|
|
30
|
-
const [moduleSpecifier, ...specifier] = encodedArguments.split(":").map((entry) => decodeURIComponent(entry));
|
|
31
|
-
return {
|
|
32
|
-
encodedArguments,
|
|
33
|
-
moduleSpecifier,
|
|
34
|
-
specifier,
|
|
35
|
-
importKind,
|
|
36
|
-
semicolon,
|
|
37
|
-
position: match.index,
|
|
38
|
-
size: fullMatch.length
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
if (matches.length === 0) return css;
|
|
42
169
|
try {
|
|
170
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
43
171
|
const resolvedValues = await Promise.all(
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
moduleSpecifier
|
|
48
|
-
pathContext
|
|
172
|
+
yakImports.map(async ({ moduleSpecifier, specifier }) => {
|
|
173
|
+
const { resolved: resolvedModule } = await resolveModule(
|
|
174
|
+
context,
|
|
175
|
+
moduleSpecifier
|
|
49
176
|
);
|
|
50
177
|
const resolvedValue = await resolveModuleSpecifierRecursively(
|
|
51
|
-
|
|
52
|
-
|
|
178
|
+
context,
|
|
179
|
+
resolvedModule,
|
|
53
180
|
specifier
|
|
54
181
|
);
|
|
182
|
+
for (const dependency of resolvedValue.from) {
|
|
183
|
+
dependencies.add(dependency);
|
|
184
|
+
}
|
|
55
185
|
return resolvedValue;
|
|
56
186
|
})
|
|
57
187
|
);
|
|
58
188
|
let result = css;
|
|
59
|
-
for (let i =
|
|
60
|
-
const { position, size, importKind, specifier, semicolon } =
|
|
189
|
+
for (let i = yakImports.length - 1; i >= 0; i--) {
|
|
190
|
+
const { position, size, importKind, specifier, semicolon } = yakImports[i];
|
|
61
191
|
const resolved = resolvedValues[i];
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
192
|
+
let replacement;
|
|
193
|
+
if (resolved.type === "unresolved-tag") {
|
|
194
|
+
replacement = importKind === "mixin" ? "" : "undefined";
|
|
195
|
+
} else {
|
|
196
|
+
if (importKind === "selector") {
|
|
197
|
+
if (resolved.type !== "styled-component" && resolved.type !== "constant") {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Found "${resolved.type}" but expected a selector - did you forget a semicolon after "${specifier.join(
|
|
200
|
+
"."
|
|
201
|
+
)}"?`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
69
204
|
}
|
|
205
|
+
replacement = resolved.type === "styled-component" ? resolved.value : resolved.value + // resolved.value can be of two different types:
|
|
206
|
+
// - mixin:
|
|
207
|
+
// ${mixinName};
|
|
208
|
+
// - constant:
|
|
209
|
+
// color: ${value};
|
|
210
|
+
// For mixins the semicolon is already included in the value
|
|
211
|
+
// but for constants it has to be added manually
|
|
212
|
+
(["}", ";"].includes(String(resolved.value).trimEnd().slice(-1)) ? "" : semicolon);
|
|
70
213
|
}
|
|
71
|
-
const replacement = resolved.type === "styled-component" ? resolved.value : resolved.value + // resolved.value can be of two different types:
|
|
72
|
-
// - mixin:
|
|
73
|
-
// ${mixinName};
|
|
74
|
-
// - constant:
|
|
75
|
-
// color: ${value};
|
|
76
|
-
// For mixins the semicolon is already included in the value
|
|
77
|
-
// but for constants it has to be added manually
|
|
78
|
-
(["}", ";"].includes(String(resolved.value).trimEnd().slice(-1)) ? "" : semicolon);
|
|
79
214
|
result = result.slice(0, position) + String(replacement) + result.slice(position + size);
|
|
80
215
|
}
|
|
81
|
-
return result;
|
|
216
|
+
return { resolved: result, dependencies: Array.from(dependencies) };
|
|
82
217
|
} catch (error) {
|
|
83
|
-
throw new
|
|
84
|
-
`Error resolving cross-file selectors
|
|
85
|
-
|
|
218
|
+
throw new CauseError(
|
|
219
|
+
`Error while resolving cross-file selectors in file "${filePath}"`,
|
|
220
|
+
{ cause: error }
|
|
86
221
|
);
|
|
87
222
|
}
|
|
88
223
|
}
|
|
89
|
-
async function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
224
|
+
async function parseYakCssImport(context, filePath, css) {
|
|
225
|
+
const yakImports = [];
|
|
226
|
+
for (const match of css.matchAll(yakCssImportRegex)) {
|
|
227
|
+
const [fullMatch, encodedArguments, importKind, semicolon] = match;
|
|
228
|
+
const [moduleSpecifier, ...specifier] = encodedArguments.split(":").map((entry) => decodeURIComponent(entry));
|
|
229
|
+
yakImports.push({
|
|
230
|
+
encodedArguments,
|
|
231
|
+
moduleSpecifier: await context.resolve(moduleSpecifier, filePath),
|
|
232
|
+
specifier,
|
|
233
|
+
importKind,
|
|
234
|
+
semicolon,
|
|
235
|
+
position: match.index,
|
|
236
|
+
size: fullMatch.length
|
|
96
237
|
});
|
|
97
|
-
}
|
|
238
|
+
}
|
|
239
|
+
return yakImports;
|
|
98
240
|
}
|
|
99
|
-
async function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
241
|
+
async function resolveModule(context, filePath) {
|
|
242
|
+
if (context.cache?.resolve === void 0) {
|
|
243
|
+
return uncachedResolveModule(context, filePath);
|
|
244
|
+
}
|
|
245
|
+
const cached = context.cache.resolve.get(filePath);
|
|
246
|
+
if (cached === void 0) {
|
|
247
|
+
const resolvedPromise = uncachedResolveModule(context, filePath);
|
|
248
|
+
context.cache.resolve.set(filePath, resolvedPromise);
|
|
249
|
+
if (context.cache.resolve.addDependency) {
|
|
250
|
+
context.cache.resolve.addDependency(filePath, filePath);
|
|
251
|
+
resolvedPromise.then((value) => {
|
|
252
|
+
for (const dep of value.dependencies) {
|
|
253
|
+
context.cache.resolve.addDependency(filePath, dep);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return resolvedPromise;
|
|
258
|
+
}
|
|
259
|
+
return cached;
|
|
109
260
|
}
|
|
110
|
-
async function
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
261
|
+
async function uncachedResolveModule(context, filePath) {
|
|
262
|
+
const parsedModule = await context.parse(filePath);
|
|
263
|
+
const exports = parsedModule.exports;
|
|
264
|
+
if (parsedModule.type !== "regular") {
|
|
265
|
+
return {
|
|
266
|
+
resolved: {
|
|
267
|
+
path: parsedModule.path,
|
|
268
|
+
exports
|
|
269
|
+
},
|
|
270
|
+
dependencies: []
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
274
|
+
if (parsedModule.styledComponents) {
|
|
275
|
+
Object.values(parsedModule.styledComponents).map((styledComponent) => {
|
|
276
|
+
if (styledComponent.nameParts.length === 1) {
|
|
277
|
+
exports.named[styledComponent.nameParts[0]] = {
|
|
278
|
+
type: "styled-component",
|
|
279
|
+
className: styledComponent.value
|
|
280
|
+
};
|
|
281
|
+
} else {
|
|
282
|
+
let exportEntry = exports.named[styledComponent.nameParts[0]];
|
|
283
|
+
if (!exportEntry) {
|
|
284
|
+
exportEntry = { type: "record", value: {} };
|
|
285
|
+
exports.named[styledComponent.nameParts[0]] = exportEntry;
|
|
286
|
+
} else if (exportEntry.type !== "record") {
|
|
287
|
+
throw new CauseError(`Error parsing file "${parsedModule.path}"`, {
|
|
288
|
+
cause: `"${styledComponent.nameParts[0]}" is not a record`
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
let current = exportEntry.value;
|
|
292
|
+
for (let i = 1; i < styledComponent.nameParts.length - 1; i++) {
|
|
293
|
+
let next = current[styledComponent.nameParts[i]];
|
|
294
|
+
if (!next) {
|
|
295
|
+
next = { type: "record", value: {} };
|
|
296
|
+
current[styledComponent.nameParts[i]] = next;
|
|
297
|
+
} else if (next.type !== "record") {
|
|
298
|
+
throw new CauseError(`Error parsing file "${parsedModule.path}"`, {
|
|
299
|
+
cause: `"${styledComponent.nameParts.slice(0, i + 1).join(".")}" is not a record`
|
|
300
|
+
});
|
|
123
301
|
}
|
|
124
|
-
|
|
125
|
-
);
|
|
126
|
-
return { type: "yak", exports: mappedModule, filePath };
|
|
127
|
-
}
|
|
128
|
-
const sourceContents = new Promise(
|
|
129
|
-
(resolve, reject) => loader.fs.readFile(filePath, "utf-8", (err, result) => {
|
|
130
|
-
if (err) return reject(err);
|
|
131
|
-
resolve(result || "");
|
|
132
|
-
})
|
|
133
|
-
);
|
|
134
|
-
const tranformedSource = new Promise((resolve, reject) => {
|
|
135
|
-
loader.loadModule(filePath, (err, source) => {
|
|
136
|
-
if (err) return reject(err);
|
|
137
|
-
let sourceString;
|
|
138
|
-
if (typeof source === "string") {
|
|
139
|
-
sourceString = source;
|
|
140
|
-
} else if (source instanceof Buffer) {
|
|
141
|
-
sourceString = source.toString("utf-8");
|
|
142
|
-
} else if (source instanceof ArrayBuffer) {
|
|
143
|
-
sourceString = new TextDecoder("utf-8").decode(source);
|
|
144
|
-
} else {
|
|
145
|
-
throw new Error(
|
|
146
|
-
"Invalid input type: code must be string, Buffer, or ArrayBuffer"
|
|
147
|
-
);
|
|
302
|
+
current = next.value;
|
|
148
303
|
}
|
|
149
|
-
|
|
150
|
-
|
|
304
|
+
current[styledComponent.nameParts[styledComponent.nameParts.length - 1]] = {
|
|
305
|
+
type: "styled-component",
|
|
306
|
+
className: styledComponent.value
|
|
307
|
+
};
|
|
308
|
+
}
|
|
151
309
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
Object.assign(
|
|
155
|
-
exports,
|
|
156
|
-
parseStyledComponents(
|
|
157
|
-
await tranformedSource,
|
|
158
|
-
loader.getOptions().experiments?.transpilationMode
|
|
159
|
-
)
|
|
160
|
-
);
|
|
310
|
+
}
|
|
311
|
+
if (parsedModule.mixins) {
|
|
161
312
|
await Promise.all(
|
|
162
|
-
Object.
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
path
|
|
166
|
-
value
|
|
313
|
+
Object.values(parsedModule.mixins).map(async (mixin) => {
|
|
314
|
+
const { resolved, dependencies: deps } = await resolveCrossFileConstant(
|
|
315
|
+
context,
|
|
316
|
+
parsedModule.path,
|
|
317
|
+
mixin.value
|
|
167
318
|
);
|
|
168
|
-
|
|
169
|
-
|
|
319
|
+
for (const dep of deps) {
|
|
320
|
+
dependencies.add(dep);
|
|
321
|
+
}
|
|
322
|
+
if (mixin.nameParts.length === 1) {
|
|
323
|
+
exports.named[mixin.nameParts[0]] = {
|
|
324
|
+
type: "mixin",
|
|
325
|
+
value: resolved
|
|
326
|
+
};
|
|
170
327
|
} else {
|
|
171
|
-
let exportEntry = exports[nameParts[0]];
|
|
328
|
+
let exportEntry = exports.named[mixin.nameParts[0]];
|
|
172
329
|
if (!exportEntry) {
|
|
173
330
|
exportEntry = { type: "record", value: {} };
|
|
174
|
-
exports[nameParts[0]] = exportEntry;
|
|
331
|
+
exports.named[mixin.nameParts[0]] = exportEntry;
|
|
175
332
|
} else if (exportEntry.type !== "record") {
|
|
176
|
-
throw new Error
|
|
177
|
-
|
|
178
|
-
);
|
|
333
|
+
throw new CauseError(`Error parsing file "${parsedModule.path}"`, {
|
|
334
|
+
cause: `"${mixin.nameParts[0]}" is not a record`
|
|
335
|
+
});
|
|
179
336
|
}
|
|
180
337
|
let current = exportEntry.value;
|
|
181
|
-
for (let i = 1; i < nameParts.length - 1; i++) {
|
|
182
|
-
let next = current[nameParts[i]];
|
|
338
|
+
for (let i = 1; i < mixin.nameParts.length - 1; i++) {
|
|
339
|
+
let next = current[mixin.nameParts[i]];
|
|
183
340
|
if (!next) {
|
|
184
341
|
next = { type: "record", value: {} };
|
|
185
|
-
current[nameParts[i]] = next;
|
|
342
|
+
current[mixin.nameParts[i]] = next;
|
|
186
343
|
} else if (next.type !== "record") {
|
|
187
|
-
throw new
|
|
188
|
-
`Error parsing file ${
|
|
344
|
+
throw new CauseError(
|
|
345
|
+
`Error parsing file "${parsedModule.path}"`,
|
|
346
|
+
{
|
|
347
|
+
cause: `"${mixin.nameParts.slice(0, i + 1).join(".")}" is not a record`
|
|
348
|
+
}
|
|
189
349
|
);
|
|
190
350
|
}
|
|
191
351
|
current = next.value;
|
|
192
352
|
}
|
|
193
|
-
current[nameParts[nameParts.length - 1]] = {
|
|
353
|
+
current[mixin.nameParts[mixin.nameParts.length - 1]] = {
|
|
194
354
|
type: "mixin",
|
|
195
|
-
value:
|
|
355
|
+
value: resolved
|
|
196
356
|
};
|
|
197
357
|
}
|
|
198
358
|
})
|
|
199
359
|
);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
resolved: {
|
|
363
|
+
path: parsedModule.path,
|
|
364
|
+
exports
|
|
365
|
+
},
|
|
366
|
+
dependencies: Array.from(dependencies)
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
async function resolveModuleSpecifierRecursively(context, resolvedModule, specifiers, seen = /* @__PURE__ */ new Set()) {
|
|
370
|
+
const exportName = specifiers[0];
|
|
371
|
+
const exportValue = resolvedModule.exports.named[exportName];
|
|
372
|
+
if (exportValue !== void 0) {
|
|
373
|
+
if (seen.has(resolvedModule.path + ":" + exportName)) {
|
|
374
|
+
throw new CircularDependencyError(
|
|
375
|
+
`Unable to resolve "${specifiers.join(".")}" in module "${resolvedModule.path}"`,
|
|
376
|
+
{ cause: "Circular dependency detected" }
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
seen.add(resolvedModule.path + ":" + exportName);
|
|
380
|
+
return resolveModuleExport(
|
|
381
|
+
context,
|
|
382
|
+
resolvedModule.path,
|
|
383
|
+
exportValue,
|
|
384
|
+
specifiers,
|
|
385
|
+
seen
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
let i = 1;
|
|
389
|
+
for (const from of resolvedModule.exports.all) {
|
|
390
|
+
if (context.exportAllLimit && i++ > context.exportAllLimit) {
|
|
391
|
+
throw new ResolveError(
|
|
392
|
+
`Unable to resolve "${specifiers.join(".")}" in module "${resolvedModule.path}"`,
|
|
393
|
+
{
|
|
394
|
+
cause: `More than ${context.exportAllLimit} star exports are not supported for performance reasons`
|
|
395
|
+
}
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
const resolved = await resolveModuleExport(
|
|
400
|
+
context,
|
|
401
|
+
resolvedModule.path,
|
|
402
|
+
{
|
|
403
|
+
type: "re-export",
|
|
404
|
+
from,
|
|
405
|
+
name: exportName
|
|
406
|
+
},
|
|
407
|
+
specifiers,
|
|
408
|
+
seen
|
|
409
|
+
);
|
|
410
|
+
if (seen.has(resolvedModule.path + ":*")) {
|
|
411
|
+
throw new CircularDependencyError(
|
|
412
|
+
`Unable to resolve "${specifiers.join(".")}" in module "${resolvedModule.path}"`,
|
|
413
|
+
{ cause: "Circular dependency detected" }
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
seen.add(resolvedModule.path + ":*");
|
|
417
|
+
return resolved;
|
|
418
|
+
} catch (error) {
|
|
419
|
+
if (!(error instanceof ResolveError)) {
|
|
420
|
+
throw error;
|
|
421
|
+
}
|
|
422
|
+
if (error.circular) {
|
|
423
|
+
throw error;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
throw new ResolveError(`Unable to resolve "${specifiers.join(".")}"`, {
|
|
428
|
+
cause: `no matching export found in module "${resolvedModule.path}"`
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
async function resolveModuleExport(context, filePath, moduleExport, specifiers, seen) {
|
|
432
|
+
try {
|
|
433
|
+
switch (moduleExport.type) {
|
|
434
|
+
case "re-export": {
|
|
435
|
+
const { resolved: reExportedModule } = await resolveModule(
|
|
436
|
+
context,
|
|
437
|
+
await context.resolve(moduleExport.from, filePath)
|
|
438
|
+
);
|
|
439
|
+
const resolved = await resolveModuleSpecifierRecursively(
|
|
440
|
+
context,
|
|
441
|
+
reExportedModule,
|
|
442
|
+
[moduleExport.name, ...specifiers.slice(1)],
|
|
443
|
+
seen
|
|
444
|
+
);
|
|
445
|
+
if (resolved) {
|
|
446
|
+
resolved.from.push(filePath);
|
|
447
|
+
}
|
|
448
|
+
return resolved;
|
|
449
|
+
}
|
|
450
|
+
case "namespace-re-export": {
|
|
451
|
+
const { resolved: reExportedModule } = await resolveModule(
|
|
452
|
+
context,
|
|
453
|
+
await context.resolve(moduleExport.from, filePath)
|
|
454
|
+
);
|
|
455
|
+
const resolved = await resolveModuleSpecifierRecursively(
|
|
456
|
+
context,
|
|
457
|
+
reExportedModule,
|
|
458
|
+
specifiers.slice(1),
|
|
459
|
+
seen
|
|
460
|
+
);
|
|
461
|
+
if (resolved) {
|
|
462
|
+
resolved.from.push(filePath);
|
|
463
|
+
}
|
|
464
|
+
return resolved;
|
|
465
|
+
}
|
|
466
|
+
case "styled-component": {
|
|
467
|
+
return {
|
|
468
|
+
type: "styled-component",
|
|
469
|
+
from: [filePath],
|
|
470
|
+
source: filePath,
|
|
471
|
+
name: specifiers[specifiers.length - 1],
|
|
472
|
+
value: moduleExport.className
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
// usually at this point `tag-template` exports where already resolved to
|
|
476
|
+
// styled-components if a matching styled-component comment was generated
|
|
477
|
+
// by yak-swc. So resolving a value to a `tag-template` at this stage
|
|
478
|
+
// would mean that the user tried to use the result of a call to a
|
|
479
|
+
// different tag-template than yak's styled in a template. This is usually
|
|
480
|
+
// invalid.
|
|
481
|
+
//
|
|
482
|
+
// But there is an issue with Nextjs. Next build in two passes, once for
|
|
483
|
+
// the server bundle, once for the client bundle. During the server-side
|
|
484
|
+
// build, each module with the `"use client"` directive is transformed to
|
|
485
|
+
// throw errors if the exported symbol are used. This transformation
|
|
486
|
+
// removes the comments generated by `yak-swc`, so instead of the expected
|
|
487
|
+
// `styled-component`, calls to `styled` resolve to a `tag-template`
|
|
488
|
+
// (because no classname was found in the now absent comments).
|
|
489
|
+
//
|
|
490
|
+
// To summarize, if a "use client" bundle exports a styled component that
|
|
491
|
+
// is used in a "standard" module, the resolve logic would throw with
|
|
492
|
+
// "unknown type tag-template".
|
|
493
|
+
//
|
|
494
|
+
// To avoid this error, the resolve logic must handle those `tag-template`
|
|
495
|
+
// with a special type `unresolved-tag`. Those will be interpolated to
|
|
496
|
+
// valid CSS with minimal effect (to avoid CSS syntax error in the case of
|
|
497
|
+
// Nextjs server build)
|
|
498
|
+
case "tag-template": {
|
|
499
|
+
return {
|
|
500
|
+
type: "unresolved-tag",
|
|
501
|
+
from: [filePath],
|
|
502
|
+
source: filePath,
|
|
503
|
+
name: specifiers[specifiers.length - 1]
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
case "constant": {
|
|
507
|
+
return {
|
|
508
|
+
type: "constant",
|
|
509
|
+
from: [filePath],
|
|
510
|
+
source: filePath,
|
|
511
|
+
value: moduleExport.value
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
case "record": {
|
|
515
|
+
const resolvedInRecord = resolveSpecifierInRecord(
|
|
516
|
+
moduleExport,
|
|
517
|
+
specifiers[0],
|
|
518
|
+
specifiers.slice(1)
|
|
519
|
+
);
|
|
520
|
+
return resolveModuleExport(
|
|
521
|
+
context,
|
|
522
|
+
filePath,
|
|
523
|
+
resolvedInRecord,
|
|
524
|
+
specifiers,
|
|
525
|
+
seen
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
case "mixin": {
|
|
529
|
+
return {
|
|
530
|
+
type: "mixin",
|
|
531
|
+
from: [filePath],
|
|
532
|
+
source: filePath,
|
|
533
|
+
value: moduleExport.value
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
}
|
|
205
537
|
} catch (error) {
|
|
206
|
-
throw new
|
|
207
|
-
`
|
|
538
|
+
throw new ResolveError(
|
|
539
|
+
`Unable to resolve "${specifiers.join(".")}" in module "${filePath}"`,
|
|
540
|
+
{ cause: error }
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
throw new ResolveError(
|
|
544
|
+
`Unable to resolve "${specifiers.join(".")}" in module "${filePath}"`,
|
|
545
|
+
{ cause: `unknown type "${moduleExport.type}"` }
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
function resolveSpecifierInRecord(record, name, specifiers) {
|
|
549
|
+
if (specifiers.length === 0) {
|
|
550
|
+
throw new ResolveError("did not expect an object");
|
|
551
|
+
}
|
|
552
|
+
let depth = 0;
|
|
553
|
+
let current = record;
|
|
554
|
+
while (current && current.type === "record" && depth < specifiers.length) {
|
|
555
|
+
current = current.value[specifiers[depth]];
|
|
556
|
+
depth += 1;
|
|
557
|
+
}
|
|
558
|
+
if (current === void 0 || depth !== specifiers.length) {
|
|
559
|
+
throw new ResolveError(
|
|
560
|
+
`Unable to resolve "${specifiers.join(".")}" in object/array "${name}"`,
|
|
561
|
+
{ cause: "path not found" }
|
|
208
562
|
);
|
|
209
563
|
}
|
|
564
|
+
if (current.type === "constant" || current.type === "styled-component" || current.type === "mixin") {
|
|
565
|
+
return current;
|
|
566
|
+
}
|
|
567
|
+
if (current.type === "record" && "__yak" in current.value && current.value.__yak.type === "constant") {
|
|
568
|
+
return { type: "mixin", value: String(current.value.__yak.value) };
|
|
569
|
+
}
|
|
570
|
+
throw new ResolveError(
|
|
571
|
+
`Unable to resolve "${specifiers.join(".")}" in object/array "${name}"`,
|
|
572
|
+
{ cause: "only string and numbers are supported" }
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
async function sha1(message) {
|
|
576
|
+
const resultBuffer = await globalThis.crypto.subtle.digest(
|
|
577
|
+
"SHA-1",
|
|
578
|
+
new TextEncoder().encode(message)
|
|
579
|
+
);
|
|
580
|
+
return Array.from(
|
|
581
|
+
new Uint8Array(resultBuffer),
|
|
582
|
+
(byte) => byte.toString(16).padStart(2, "0")
|
|
583
|
+
).join("");
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// loaders/lib/resolveCrossFileSelectors.ts
|
|
587
|
+
import { parse } from "@babel/parser";
|
|
588
|
+
import traverse from "@babel/traverse";
|
|
589
|
+
var compilationCache = /* @__PURE__ */ new WeakMap();
|
|
590
|
+
async function resolveCrossFileConstant2(loader, pathContext, css) {
|
|
591
|
+
const { resolved } = await resolveCrossFileConstant(
|
|
592
|
+
getResolveContext(loader),
|
|
593
|
+
loader.resourcePath,
|
|
594
|
+
css
|
|
595
|
+
);
|
|
596
|
+
return resolved;
|
|
597
|
+
}
|
|
598
|
+
function getCompilationCache(loader) {
|
|
599
|
+
const compilation = loader._compilation;
|
|
600
|
+
if (!compilation) {
|
|
601
|
+
throw new Error("Webpack compilation object not available");
|
|
602
|
+
}
|
|
603
|
+
let cache = compilationCache.get(compilation);
|
|
604
|
+
if (!cache) {
|
|
605
|
+
cache = {
|
|
606
|
+
parsedFiles: /* @__PURE__ */ new Map()
|
|
607
|
+
};
|
|
608
|
+
compilationCache.set(compilation, cache);
|
|
609
|
+
}
|
|
610
|
+
return cache;
|
|
611
|
+
}
|
|
612
|
+
function getParseContext(loader) {
|
|
613
|
+
return {
|
|
614
|
+
cache: { parse: getCompilationCache(loader).parsedFiles },
|
|
615
|
+
async extractExports(modulePath) {
|
|
616
|
+
const sourceContents = new Promise(
|
|
617
|
+
(resolve, reject) => loader.fs.readFile(modulePath, "utf-8", (err, result) => {
|
|
618
|
+
if (err) return reject(err);
|
|
619
|
+
resolve(result || "");
|
|
620
|
+
})
|
|
621
|
+
);
|
|
622
|
+
return parseExports(await sourceContents);
|
|
623
|
+
},
|
|
624
|
+
async getTransformed(modulePath) {
|
|
625
|
+
const tranformedSource = new Promise((resolve, reject) => {
|
|
626
|
+
loader.loadModule(modulePath, (err, source) => {
|
|
627
|
+
if (err) return reject(err);
|
|
628
|
+
let sourceString;
|
|
629
|
+
if (typeof source === "string") {
|
|
630
|
+
sourceString = source;
|
|
631
|
+
} else if (source instanceof Buffer) {
|
|
632
|
+
sourceString = source.toString("utf-8");
|
|
633
|
+
} else if (source instanceof ArrayBuffer) {
|
|
634
|
+
sourceString = new TextDecoder("utf-8").decode(source);
|
|
635
|
+
} else {
|
|
636
|
+
throw new Error(
|
|
637
|
+
"Invalid input type: code must be string, Buffer, or ArrayBuffer"
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
resolve(sourceString || "");
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
return { code: await tranformedSource };
|
|
644
|
+
},
|
|
645
|
+
async evaluateYakModule(modulePath) {
|
|
646
|
+
return loader.importModule(modulePath);
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function getResolveContext(loader) {
|
|
651
|
+
const parseContext = getParseContext(loader);
|
|
652
|
+
return {
|
|
653
|
+
parse: (modulePath) => parseModule(parseContext, modulePath),
|
|
654
|
+
resolve: async (specifier, importer) => {
|
|
655
|
+
return resolveModule2(loader, specifier, dirname(importer));
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
async function resolveModule2(loader, moduleSpecifier, context) {
|
|
660
|
+
return new Promise((resolve, reject) => {
|
|
661
|
+
loader.resolve(context, moduleSpecifier, (err, result) => {
|
|
662
|
+
if (err) return reject(err);
|
|
663
|
+
if (!result)
|
|
664
|
+
return reject(new Error(`Could not resolve ${moduleSpecifier}`));
|
|
665
|
+
resolve(result);
|
|
666
|
+
});
|
|
667
|
+
});
|
|
210
668
|
}
|
|
211
669
|
async function parseExports(sourceContents) {
|
|
212
|
-
|
|
670
|
+
const moduleExports = {
|
|
671
|
+
importYak: true,
|
|
672
|
+
named: {},
|
|
673
|
+
all: []
|
|
674
|
+
};
|
|
213
675
|
const variableDeclarations = {};
|
|
214
676
|
let defaultIdentifier = null;
|
|
215
677
|
try {
|
|
@@ -228,10 +690,10 @@ async function parseExports(sourceContents) {
|
|
|
228
690
|
if (node.source) {
|
|
229
691
|
node.specifiers.forEach((specifier) => {
|
|
230
692
|
if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier" && specifier.local.type === "Identifier") {
|
|
231
|
-
|
|
693
|
+
moduleExports.named[specifier.exported.name] = {
|
|
232
694
|
type: "re-export",
|
|
233
695
|
from: node.source.value,
|
|
234
|
-
|
|
696
|
+
name: specifier.local.name
|
|
235
697
|
};
|
|
236
698
|
}
|
|
237
699
|
});
|
|
@@ -240,7 +702,7 @@ async function parseExports(sourceContents) {
|
|
|
240
702
|
if (declaration.id.type === "Identifier" && declaration.init) {
|
|
241
703
|
const parsed = parseExportValueExpression(declaration.init);
|
|
242
704
|
if (parsed) {
|
|
243
|
-
|
|
705
|
+
moduleExports.named[declaration.id.name] = parsed;
|
|
244
706
|
}
|
|
245
707
|
}
|
|
246
708
|
});
|
|
@@ -251,9 +713,9 @@ async function parseExports(sourceContents) {
|
|
|
251
713
|
const { specifiers, source } = node;
|
|
252
714
|
specifiers.forEach((specifier) => {
|
|
253
715
|
if (specifier.type === "ExportNamespaceSpecifier" && specifier.exported.type === "Identifier") {
|
|
254
|
-
|
|
255
|
-
type: "
|
|
256
|
-
from:
|
|
716
|
+
moduleExports.named[specifier.exported.name] = {
|
|
717
|
+
type: "namespace-re-export",
|
|
718
|
+
from: source.value
|
|
257
719
|
};
|
|
258
720
|
}
|
|
259
721
|
});
|
|
@@ -263,68 +725,30 @@ async function parseExports(sourceContents) {
|
|
|
263
725
|
if (node.declaration.type === "Identifier") {
|
|
264
726
|
defaultIdentifier = node.declaration.name;
|
|
265
727
|
} else if (node.declaration.type === "FunctionDeclaration" || node.declaration.type === "ClassDeclaration") {
|
|
266
|
-
|
|
728
|
+
moduleExports.named["default"] = {
|
|
267
729
|
type: "unsupported",
|
|
268
730
|
hint: node.declaration.type
|
|
269
731
|
};
|
|
270
732
|
} else {
|
|
271
|
-
|
|
733
|
+
moduleExports.named["default"] = parseExportValueExpression(
|
|
272
734
|
node.declaration
|
|
273
735
|
);
|
|
274
736
|
}
|
|
275
737
|
},
|
|
276
738
|
ExportAllDeclaration({ node }) {
|
|
277
|
-
|
|
278
|
-
exports["*"] ||= {
|
|
279
|
-
type: "star-export",
|
|
280
|
-
from: []
|
|
281
|
-
};
|
|
282
|
-
if (exports["*"].type !== "star-export") {
|
|
283
|
-
throw new Error("Invalid star export state");
|
|
284
|
-
}
|
|
285
|
-
exports["*"].from.push(node.source.value);
|
|
286
|
-
}
|
|
739
|
+
moduleExports.all.push(node.source.value);
|
|
287
740
|
}
|
|
288
741
|
});
|
|
289
742
|
if (defaultIdentifier && variableDeclarations[defaultIdentifier]) {
|
|
290
|
-
|
|
743
|
+
moduleExports.named["default"] = parseExportValueExpression(
|
|
291
744
|
variableDeclarations[defaultIdentifier]
|
|
292
745
|
);
|
|
293
746
|
}
|
|
294
|
-
return
|
|
747
|
+
return moduleExports;
|
|
295
748
|
} catch (error) {
|
|
296
749
|
throw new Error(`Error parsing exports: ${error.message}`);
|
|
297
750
|
}
|
|
298
751
|
}
|
|
299
|
-
function parseMixins(sourceContents) {
|
|
300
|
-
const mixinParts = sourceContents.split("/*YAK EXPORTED MIXIN:");
|
|
301
|
-
let mixins = {};
|
|
302
|
-
for (let i = 1; i < mixinParts.length; i++) {
|
|
303
|
-
const [comment] = mixinParts[i].split("*/", 1);
|
|
304
|
-
const position = comment.indexOf("\n");
|
|
305
|
-
const name = comment.slice(0, position);
|
|
306
|
-
const value = comment.slice(position + 1);
|
|
307
|
-
mixins[name] = {
|
|
308
|
-
type: "mixin",
|
|
309
|
-
value,
|
|
310
|
-
nameParts: name.split(":").map((part) => decodeURIComponent(part))
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
return mixins;
|
|
314
|
-
}
|
|
315
|
-
function parseStyledComponents(sourceContents, transpilationMode) {
|
|
316
|
-
const styledParts = sourceContents.split("/*YAK EXPORTED STYLED:");
|
|
317
|
-
let styledComponents = {};
|
|
318
|
-
for (let i = 1; i < styledParts.length; i++) {
|
|
319
|
-
const [comment] = styledParts[i].split("*/", 1);
|
|
320
|
-
const [componentName, className] = comment.split(":");
|
|
321
|
-
styledComponents[componentName] = {
|
|
322
|
-
type: "styled-component",
|
|
323
|
-
value: transpilationMode === "Css" ? `.${className}` : `:global(.${className})`
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
return styledComponents;
|
|
327
|
-
}
|
|
328
752
|
function unpackTSAsExpression(node) {
|
|
329
753
|
if (node.type === "TSAsExpression") {
|
|
330
754
|
return unpackTSAsExpression(node.expression);
|
|
@@ -334,7 +758,7 @@ function unpackTSAsExpression(node) {
|
|
|
334
758
|
function parseExportValueExpression(node) {
|
|
335
759
|
const expression = unpackTSAsExpression(node);
|
|
336
760
|
if (expression.type === "CallExpression" || expression.type === "TaggedTemplateExpression") {
|
|
337
|
-
return { type: "
|
|
761
|
+
return { type: "tag-template" };
|
|
338
762
|
} else if (expression.type === "StringLiteral" || expression.type === "NumericLiteral") {
|
|
339
763
|
return { type: "constant", value: expression.value };
|
|
340
764
|
} else if (expression.type === "UnaryExpression" && expression.operator === "-" && expression.argument.type === "NumericLiteral") {
|
|
@@ -361,106 +785,17 @@ function parseObjectExpression(node) {
|
|
|
361
785
|
}
|
|
362
786
|
return result;
|
|
363
787
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
`Could not resolve ${specifier.join(".")} in module ${module.filePath} - Multiple star exports are not supported for performance reasons`
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
exportValue = {
|
|
377
|
-
type: "re-export",
|
|
378
|
-
from: starExport.from[0],
|
|
379
|
-
imported: exportName
|
|
380
|
-
};
|
|
381
|
-
} else {
|
|
382
|
-
throw new Error(
|
|
383
|
-
`Could not resolve "${specifier.join(".")}" in module ${module.filePath}`
|
|
384
|
-
);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
if (exportValue.type === "re-export") {
|
|
388
|
-
const importedModule = await parseModule(
|
|
389
|
-
loader,
|
|
390
|
-
exportValue.from,
|
|
391
|
-
path.dirname(module.filePath)
|
|
392
|
-
);
|
|
393
|
-
return resolveModuleSpecifierRecursively(loader, importedModule, [
|
|
394
|
-
exportValue.imported,
|
|
395
|
-
...specifier.slice(1)
|
|
396
|
-
]);
|
|
397
|
-
} else if (exportValue.type === "star-export") {
|
|
398
|
-
const importedModule = await parseModule(
|
|
399
|
-
loader,
|
|
400
|
-
exportValue.from[0],
|
|
401
|
-
path.dirname(module.filePath)
|
|
402
|
-
);
|
|
403
|
-
return resolveModuleSpecifierRecursively(
|
|
404
|
-
loader,
|
|
405
|
-
importedModule,
|
|
406
|
-
specifier.slice(1)
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
if (exportValue.type === "styled-component") {
|
|
410
|
-
return {
|
|
411
|
-
type: "styled-component",
|
|
412
|
-
from: module.filePath,
|
|
413
|
-
name: specifier[specifier.length - 1],
|
|
414
|
-
value: exportValue.value
|
|
415
|
-
};
|
|
416
|
-
} else if (exportValue.type === "constant") {
|
|
417
|
-
return { type: "constant", value: exportValue.value };
|
|
418
|
-
} else if (exportValue.type === "record") {
|
|
419
|
-
let current = exportValue.value;
|
|
420
|
-
let depth = 0;
|
|
421
|
-
do {
|
|
422
|
-
if (typeof current === "string" || typeof current === "number") {
|
|
423
|
-
return {
|
|
424
|
-
type: "constant",
|
|
425
|
-
value: current
|
|
426
|
-
};
|
|
427
|
-
} else if (!current || typeof current !== "object" && !Array.isArray(current)) {
|
|
428
|
-
throw new Error(
|
|
429
|
-
`Error unpacking Record/Array "${exportName}".
|
|
430
|
-
Key "${specifier[depth]}" was of type "${typeof current}" but only String and Number are supported`
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
depth++;
|
|
434
|
-
if (depth === specifier.length && "__yak" in current) {
|
|
435
|
-
return { type: "mixin", value: current["__yak"] };
|
|
436
|
-
} else if (depth === specifier.length && "value" in current) {
|
|
437
|
-
return { type: "constant", value: current["value"] };
|
|
438
|
-
} else if ("value" in current) {
|
|
439
|
-
current = current.value[specifier[depth]];
|
|
440
|
-
} else {
|
|
441
|
-
current = current[specifier[depth]];
|
|
442
|
-
}
|
|
443
|
-
} while (current);
|
|
444
|
-
if (specifier[depth] === void 0) {
|
|
445
|
-
throw new Error(
|
|
446
|
-
`Error unpacking Record/Array - could not extract \`${specifier.slice(0, depth).join(".")}\` is not a string or number`
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
throw new Error(
|
|
450
|
-
`Error unpacking Record/Array - could not extract \`${specifier[depth]}\` from \`${specifier.slice(0, depth).join(".")}\``
|
|
451
|
-
);
|
|
452
|
-
} else if (exportValue.type === "mixin") {
|
|
453
|
-
return { type: "mixin", value: exportValue.value };
|
|
454
|
-
}
|
|
455
|
-
throw new Error(
|
|
456
|
-
`Error unpacking Record/Array - unexpected exportValue "${exportValue.type}" for specifier "${specifier.join(".")}"`
|
|
457
|
-
);
|
|
458
|
-
} catch (error) {
|
|
459
|
-
throw new Error(
|
|
460
|
-
`Error resolving from module ${module.filePath}: ${error.message}
|
|
461
|
-
Extracted values: ${JSON.stringify(module.exports, null, 2)}`
|
|
462
|
-
);
|
|
788
|
+
var DIRNAME_POSIX_REGEX = /^((?:\.(?![^\/]))|(?:(?:\/?|)(?:[\s\S]*?)))(?:\/+?|)(?:(?:\.{1,2}|[^\/]+?|)(?:\.[^.\/]*|))(?:[\/]*)$/;
|
|
789
|
+
var DIRNAME_WIN32_REGEX = /^((?:\.(?![^\\]))|(?:(?:\\?|)(?:[\s\S]*?)))(?:\\+?|)(?:(?:\.{1,2}|[^\\]+?|)(?:\.[^.\\]*|))(?:[\\]*)$/;
|
|
790
|
+
function dirname(path) {
|
|
791
|
+
let dirname2 = DIRNAME_POSIX_REGEX.exec(path)?.[1];
|
|
792
|
+
if (!dirname2) {
|
|
793
|
+
dirname2 = DIRNAME_WIN32_REGEX.exec(path)?.[1];
|
|
794
|
+
}
|
|
795
|
+
if (!dirname2) {
|
|
796
|
+
throw new Error(`Can't extract dirname from ${path}`);
|
|
463
797
|
}
|
|
798
|
+
return dirname2;
|
|
464
799
|
}
|
|
465
800
|
|
|
466
801
|
// loaders/css-loader.ts
|
|
@@ -480,7 +815,7 @@ async function cssExtractLoader(_code, sourceMap) {
|
|
|
480
815
|
debugLog("ts", source);
|
|
481
816
|
const css = extractCss(source, experiments?.transpilationMode);
|
|
482
817
|
debugLog("css", css);
|
|
483
|
-
return
|
|
818
|
+
return resolveCrossFileConstant2(this, this.context, css).then((result) => {
|
|
484
819
|
debugLog("css resolved", css);
|
|
485
820
|
return callback(null, result, sourceMap);
|
|
486
821
|
}, callback);
|