@knighted/css 1.1.0-rc.5 → 1.1.0-rc.7

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.
@@ -0,0 +1,470 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.__loaderBridgeInternals = exports.pitch = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const loaderInternals_js_1 = require("./loaderInternals.cjs");
9
+ const styleGraph_js_1 = require("./styleGraph.cjs");
10
+ const DEFAULT_EXPORT_NAME = 'knightedCss';
11
+ const BRIDGE_STYLE_EXTENSIONS = ['.css', '.scss', '.sass', '.less', '.css.ts'];
12
+ const loader = function loader(source) {
13
+ return source;
14
+ };
15
+ const pitch = function pitch(remainingRequest) {
16
+ const resolvedRemainingRequest = resolveRemainingRequest(this, remainingRequest);
17
+ if (isJsLikeResource(this.resourcePath) && (0, loaderInternals_js_1.hasCombinedQuery)(this.resourceQuery)) {
18
+ const callback = getAsyncCallback(this);
19
+ if (!callback) {
20
+ return createCombinedJsBridgeModuleSync(resolvedRemainingRequest);
21
+ }
22
+ readResourceSource(this)
23
+ .then(async (source) => {
24
+ const cssRequests = await collectBridgeStyleRequests(this, source);
25
+ const upstreamRequest = buildUpstreamRequest(resolvedRemainingRequest);
26
+ callback(null, createCombinedJsBridgeModule({
27
+ upstreamRequest: upstreamRequest || '',
28
+ cssRequests,
29
+ emitDefault: false,
30
+ }));
31
+ })
32
+ .catch(error => callback(error));
33
+ return;
34
+ }
35
+ const callback = getAsyncCallback(this);
36
+ if (!callback) {
37
+ const localsRequest = buildProxyRequest(this);
38
+ const upstreamRequest = buildUpstreamRequest(resolvedRemainingRequest);
39
+ const { emitCssModules } = resolveLoaderOptions(this);
40
+ const combined = (0, loaderInternals_js_1.hasCombinedQuery)(this.resourceQuery);
41
+ const skipSyntheticDefault = (0, loaderInternals_js_1.hasNamedOnlyQueryFlag)(this.resourceQuery);
42
+ if ((0, loaderInternals_js_1.hasQueryFlag)(this.resourceQuery, loaderInternals_js_1.TYPES_QUERY_FLAG)) {
43
+ emitKnightedWarning(this, 'The bridge loader does not generate stableSelectors. Remove the "types" query flag.');
44
+ }
45
+ const emitDefault = combined
46
+ ? (0, loaderInternals_js_1.shouldEmitCombinedDefault)({
47
+ detection: 'unknown',
48
+ request: localsRequest,
49
+ skipSyntheticDefault,
50
+ })
51
+ : false;
52
+ const resolvedUpstream = upstreamRequest || localsRequest;
53
+ const resolvedLocals = upstreamRequest || localsRequest;
54
+ return createBridgeModule({
55
+ localsRequest: resolvedLocals,
56
+ upstreamRequest: resolvedUpstream,
57
+ combined,
58
+ emitDefault,
59
+ emitCssModules,
60
+ });
61
+ }
62
+ const localsRequest = buildProxyRequest(this);
63
+ const upstreamRequest = buildUpstreamRequest(resolvedRemainingRequest);
64
+ const { emitCssModules } = resolveLoaderOptions(this);
65
+ const combined = (0, loaderInternals_js_1.hasCombinedQuery)(this.resourceQuery);
66
+ const skipSyntheticDefault = (0, loaderInternals_js_1.hasNamedOnlyQueryFlag)(this.resourceQuery);
67
+ if ((0, loaderInternals_js_1.hasQueryFlag)(this.resourceQuery, loaderInternals_js_1.TYPES_QUERY_FLAG)) {
68
+ emitKnightedWarning(this, 'The bridge loader does not generate stableSelectors. Remove the "types" query flag.');
69
+ }
70
+ const emitDefault = combined
71
+ ? (0, loaderInternals_js_1.shouldEmitCombinedDefault)({
72
+ detection: 'unknown',
73
+ request: localsRequest,
74
+ skipSyntheticDefault,
75
+ })
76
+ : false;
77
+ const resolvedUpstream = upstreamRequest || localsRequest;
78
+ const resolvedLocals = upstreamRequest || localsRequest;
79
+ const collectSource = isJsLikeResource(this.resourcePath)
80
+ ? readResourceSource(this)
81
+ : Promise.resolve(undefined);
82
+ collectSource
83
+ .then(async (source) => {
84
+ const cssRequests = await collectBridgeStyleRequests(this, source);
85
+ callback(null, createBridgeModule({
86
+ localsRequest: resolvedLocals,
87
+ upstreamRequest: resolvedUpstream,
88
+ combined,
89
+ emitDefault,
90
+ emitCssModules,
91
+ cssRequests,
92
+ }));
93
+ })
94
+ .catch(error => callback(error));
95
+ return;
96
+ };
97
+ exports.pitch = pitch;
98
+ loader.pitch = exports.pitch;
99
+ exports.default = loader;
100
+ function resolveLoaderOptions(ctx) {
101
+ const rawOptions = (typeof ctx.getOptions === 'function' ? ctx.getOptions() : {});
102
+ return {
103
+ emitCssModules: rawOptions.emitCssModules !== false,
104
+ };
105
+ }
106
+ function getAsyncCallback(ctx) {
107
+ return typeof ctx.async === 'function' ? ctx.async() : undefined;
108
+ }
109
+ function readResourceSource(ctx) {
110
+ return new Promise((resolve, reject) => {
111
+ ctx.fs.readFile(ctx.resourcePath, (error, data) => {
112
+ if (error) {
113
+ reject(error);
114
+ return;
115
+ }
116
+ if (!data) {
117
+ reject(new Error(`Unable to read ${ctx.resourcePath}`));
118
+ return;
119
+ }
120
+ resolve(data.toString('utf8'));
121
+ });
122
+ });
123
+ }
124
+ async function collectBridgeStyleRequests(ctx, source) {
125
+ const graphImports = await collectStyleGraphImports(ctx);
126
+ const graphPaths = new Set(graphImports.map(filePath => node_path_1.default.resolve(filePath)));
127
+ const graphRequests = graphImports
128
+ .filter(filePath => node_path_1.default.resolve(filePath) !== node_path_1.default.resolve(ctx.resourcePath))
129
+ .map(filePath => buildBridgeCssRequest(filePath));
130
+ if (!source) {
131
+ return dedupeRequests(graphRequests);
132
+ }
133
+ const directSpecifiers = collectStyleImportSpecifiers(source);
134
+ const directRequests = directSpecifiers
135
+ .map(specifier => {
136
+ const [resource, query] = specifier.split('?');
137
+ if (query) {
138
+ return buildBridgeCssRequest(specifier);
139
+ }
140
+ const resolved = resolveStyleSpecifier(resource, ctx.resourcePath);
141
+ if (resolved && graphPaths.has(resolved)) {
142
+ return undefined;
143
+ }
144
+ return buildBridgeCssRequest(specifier);
145
+ })
146
+ .filter((request) => Boolean(request));
147
+ return dedupeRequests([...graphRequests, ...directRequests]);
148
+ }
149
+ async function collectStyleGraphImports(ctx) {
150
+ const cwd = ctx.rootContext ?? node_path_1.default.dirname(ctx.resourcePath);
151
+ const filter = (filePath) => !filePath.includes('node_modules');
152
+ try {
153
+ return await (0, styleGraph_js_1.collectTransitiveStyleImports)(ctx.resourcePath, {
154
+ cwd,
155
+ styleExtensions: BRIDGE_STYLE_EXTENSIONS,
156
+ filter,
157
+ });
158
+ }
159
+ catch {
160
+ return [];
161
+ }
162
+ }
163
+ function resolveStyleSpecifier(specifier, importer) {
164
+ if (!specifier)
165
+ return undefined;
166
+ if (specifier.startsWith('.')) {
167
+ return node_path_1.default.resolve(node_path_1.default.dirname(importer), specifier);
168
+ }
169
+ if (node_path_1.default.isAbsolute(specifier)) {
170
+ return node_path_1.default.resolve(specifier);
171
+ }
172
+ return undefined;
173
+ }
174
+ function dedupeRequests(requests) {
175
+ const seen = new Set();
176
+ const output = [];
177
+ for (const request of requests) {
178
+ if (seen.has(request))
179
+ continue;
180
+ seen.add(request);
181
+ output.push(request);
182
+ }
183
+ return output;
184
+ }
185
+ function collectStyleImportSpecifiers(source) {
186
+ const matches = new Set();
187
+ const importPattern = /(?:import|export)\s+(?:[^'"\n]+\s+from\s+)?['"]([^'"\n]+?\.(?:css|scss|sass|less|css\.ts)(?:\?[^'"\n]+)?)['"]/g;
188
+ let match;
189
+ while ((match = importPattern.exec(source))) {
190
+ if (match[1]) {
191
+ matches.add(match[1]);
192
+ }
193
+ }
194
+ return Array.from(matches);
195
+ }
196
+ function buildBridgeCssRequest(specifier) {
197
+ if (specifier.includes('knighted-css')) {
198
+ return specifier;
199
+ }
200
+ const [resource, query] = specifier.split('?');
201
+ if (query) {
202
+ return `${resource}?${query}&knighted-css`;
203
+ }
204
+ return `${specifier}?knighted-css`;
205
+ }
206
+ function createCombinedJsBridgeModuleSync(remainingRequest) {
207
+ const upstreamRequest = buildUpstreamRequest(remainingRequest);
208
+ return createCombinedJsBridgeModule({
209
+ upstreamRequest: upstreamRequest || '',
210
+ cssRequests: [],
211
+ emitDefault: false,
212
+ });
213
+ }
214
+ function createCombinedJsBridgeModule(options) {
215
+ const upstreamLiteral = JSON.stringify(options.upstreamRequest);
216
+ const cssImports = options.cssRequests.map((request, index) => {
217
+ const literal = JSON.stringify(request);
218
+ return `import * as __knightedStyle${index} from ${literal};`;
219
+ });
220
+ const cssValues = options.cssRequests.map((_, index) => `__knightedStyle${index}.knightedCss`);
221
+ const cssModulesValues = options.cssRequests.map((request, index) => isCssModuleRequest(request)
222
+ ? `__knightedStyle${index}.knightedCssModules`
223
+ : 'undefined');
224
+ const lines = [
225
+ `import * as __knightedUpstream from ${upstreamLiteral};`,
226
+ ...cssImports,
227
+ options.emitDefault
228
+ ? "const __knightedDefault = Object.prototype.hasOwnProperty.call(__knightedUpstream, 'default') ? __knightedUpstream['default'] : undefined;"
229
+ : '',
230
+ `const __knightedCss = [${cssValues.join(', ')}].filter(Boolean).join('\\n');`,
231
+ `const __knightedCssModules = Object.assign({}, ...[${cssModulesValues.join(', ')}].filter(Boolean));`,
232
+ `export const ${DEFAULT_EXPORT_NAME} = __knightedCss;`,
233
+ 'export const knightedCssModules = __knightedCssModules;',
234
+ `export * from ${upstreamLiteral};`,
235
+ ];
236
+ if (options.emitDefault) {
237
+ lines.push('export default __knightedDefault;');
238
+ }
239
+ return lines.filter(Boolean).join('\n');
240
+ }
241
+ function isJsLikeResource(resourcePath) {
242
+ return /\.[cm]?[jt]sx?$/.test(resourcePath);
243
+ }
244
+ function resolveCssText(primary, module) {
245
+ const candidates = [primary, module, module?.default];
246
+ for (const candidate of candidates) {
247
+ if (typeof candidate === 'string') {
248
+ return candidate;
249
+ }
250
+ if (candidate &&
251
+ typeof candidate.toString === 'function') {
252
+ const text = String(candidate.toString());
253
+ if (text && text !== '[object Object]' && text !== '[object Module]') {
254
+ return text;
255
+ }
256
+ }
257
+ }
258
+ return '';
259
+ }
260
+ function resolveCssModules(primary, module) {
261
+ const candidates = [primary, module, module?.default];
262
+ for (const candidate of candidates) {
263
+ if (!candidate || typeof candidate !== 'object')
264
+ continue;
265
+ if (!('locals' in candidate))
266
+ continue;
267
+ const locals = candidate.locals;
268
+ if (!locals || typeof locals !== 'object')
269
+ continue;
270
+ return locals;
271
+ }
272
+ const isStringMapLocal = (value) => {
273
+ const entries = Object.entries(value);
274
+ if (entries.length === 0)
275
+ return false;
276
+ return entries.every(([, entry]) => typeof entry === 'string');
277
+ };
278
+ for (const candidate of candidates) {
279
+ if (!candidate || typeof candidate !== 'object')
280
+ continue;
281
+ if (isStringMapLocal(candidate))
282
+ return candidate;
283
+ }
284
+ const collectNamedExportsLocal = (value) => {
285
+ if (!value || typeof value !== 'object')
286
+ return undefined;
287
+ const output = {};
288
+ for (const [key, entry] of Object.entries(value)) {
289
+ if (key === 'default' || key === '__esModule')
290
+ continue;
291
+ if (typeof entry === 'string') {
292
+ output[key] = entry;
293
+ }
294
+ }
295
+ return Object.keys(output).length > 0 ? output : undefined;
296
+ };
297
+ return collectNamedExportsLocal(module);
298
+ }
299
+ function createBridgeModule(options) {
300
+ const localsLiteral = JSON.stringify(options.localsRequest);
301
+ const upstreamLiteral = JSON.stringify(options.upstreamRequest);
302
+ const cssRequests = options.cssRequests ?? [];
303
+ const cssImports = cssRequests.map((request, index) => {
304
+ const literal = JSON.stringify(request);
305
+ return `import * as __knightedStyle${index} from ${literal};`;
306
+ });
307
+ const cssValues = cssRequests.map((_, index) => `__knightedStyle${index}.knightedCss`);
308
+ const cssModulesValues = cssRequests.map((request, index) => isCssModuleRequest(request)
309
+ ? `__knightedStyle${index}.knightedCssModules`
310
+ : 'undefined');
311
+ const lines = [
312
+ `import * as __knightedLocals from ${localsLiteral};`,
313
+ `import * as __knightedUpstream from ${upstreamLiteral};`,
314
+ ...cssImports,
315
+ `const __knightedDefault =\ntypeof __knightedUpstream.default !== 'undefined'\n ? __knightedUpstream.default\n : __knightedUpstream;`,
316
+ `const __knightedResolveCss = ${resolveCssText.toString()};`,
317
+ `const __knightedResolveCssModules = ${resolveCssModules.toString()};`,
318
+ `const __knightedUpstreamLocals =\n __knightedResolveCssModules(__knightedUpstream, __knightedUpstream);`,
319
+ `const __knightedLocalsExport =\n __knightedUpstreamLocals ??\n __knightedResolveCssModules(__knightedLocals, __knightedLocals) ??\n __knightedLocals;`,
320
+ `const __knightedBaseCss = __knightedResolveCss(__knightedDefault, __knightedUpstream);`,
321
+ `const __knightedCss = [__knightedBaseCss, ${cssValues.join(', ')}].filter(Boolean).join('\\n');`,
322
+ `export const ${DEFAULT_EXPORT_NAME} = __knightedCss;`,
323
+ ];
324
+ if (options.emitCssModules) {
325
+ lines.push(`const __knightedCssModules = Object.assign({}, ...[__knightedLocalsExport ?? __knightedResolveCssModules(\n __knightedDefault,\n __knightedUpstream,\n), ${cssModulesValues.join(', ')}].filter(Boolean));`, 'export const knightedCssModules = __knightedCssModules;');
326
+ }
327
+ if (options.combined) {
328
+ lines.push(`export * from ${localsLiteral};`);
329
+ if (options.emitDefault) {
330
+ lines.push('export default __knightedLocalsExport;');
331
+ }
332
+ }
333
+ else {
334
+ lines.push('export default __knightedCss;');
335
+ }
336
+ return lines.join('\n');
337
+ }
338
+ function buildUpstreamRequest(remainingRequest) {
339
+ if (!remainingRequest) {
340
+ return '';
341
+ }
342
+ const request = remainingRequest.startsWith('!')
343
+ ? remainingRequest
344
+ : `!!${remainingRequest}`;
345
+ return request;
346
+ }
347
+ function isCssModuleRequest(request) {
348
+ const [resource] = request.split('?');
349
+ const lower = resource.toLowerCase();
350
+ return /\.module\.(css|scss|sass|less|css\.ts)$/.test(lower);
351
+ }
352
+ function buildProxyRequest(ctx) {
353
+ const sanitizedQuery = (0, loaderInternals_js_1.buildSanitizedQuery)(ctx.resourceQuery);
354
+ const rawRequest = getRawRequest(ctx);
355
+ if (rawRequest) {
356
+ return rebuildProxyRequestFromRaw(ctx, rawRequest, sanitizedQuery);
357
+ }
358
+ const request = `${ctx.resourcePath}${sanitizedQuery}`;
359
+ return contextifyRequest(ctx, request);
360
+ }
361
+ function resolveRemainingRequest(ctx, remainingRequest) {
362
+ const resolved = remainingRequest || ctx.remainingRequest;
363
+ if (resolved)
364
+ return resolved;
365
+ const loaders = Array.isArray(ctx.loaders) ? ctx.loaders.slice(ctx.loaderIndex + 1) : [];
366
+ if (loaders.length > 0) {
367
+ const loaderRequests = loaders
368
+ .map(loader => {
369
+ if (loader && typeof loader.request === 'string' && loader.request) {
370
+ return loader.request;
371
+ }
372
+ const path = loader && typeof loader.path === 'string' ? loader.path : '';
373
+ const query = loader && typeof loader.query === 'string' ? loader.query : '';
374
+ return path ? `${path}${query}` : '';
375
+ })
376
+ .filter(Boolean);
377
+ if (loaderRequests.length > 0) {
378
+ const resource = `${ctx.resourcePath}${ctx.resourceQuery ?? ''}`;
379
+ return [...loaderRequests, resource].join('!');
380
+ }
381
+ }
382
+ if (typeof ctx.request === 'string' && typeof ctx.loaderIndex === 'number') {
383
+ const parts = ctx.request.split('!').filter(Boolean);
384
+ if (parts.length > 0) {
385
+ const start = Math.min(ctx.loaderIndex + 1, parts.length);
386
+ const next = parts.slice(start).join('!');
387
+ if (next)
388
+ return next;
389
+ }
390
+ }
391
+ return '';
392
+ }
393
+ function rebuildProxyRequestFromRaw(ctx, rawRequest, sanitizedQuery) {
394
+ const stripped = stripResourceQuery(rawRequest);
395
+ const loaderDelimiter = stripped.lastIndexOf('!');
396
+ const loaderPrefix = loaderDelimiter >= 0 ? stripped.slice(0, loaderDelimiter + 1) : '';
397
+ let resource = loaderDelimiter >= 0 ? stripped.slice(loaderDelimiter + 1) : stripped;
398
+ if (isRelativeSpecifier(resource)) {
399
+ resource = makeResourceRelativeToContext(ctx, ctx.resourcePath);
400
+ }
401
+ return `${loaderPrefix}${resource}${sanitizedQuery}`;
402
+ }
403
+ function getRawRequest(ctx) {
404
+ const mod = ctx._module;
405
+ const request = mod?.rawRequest;
406
+ if (typeof request === 'string' && request.length > 0) {
407
+ return request;
408
+ }
409
+ return undefined;
410
+ }
411
+ function stripResourceQuery(request) {
412
+ const idx = request.indexOf('?');
413
+ return idx >= 0 ? request.slice(0, idx) : request;
414
+ }
415
+ function contextifyRequest(ctx, request) {
416
+ const context = ctx.context ?? ctx.rootContext ?? process.cwd();
417
+ if (ctx.utils && typeof ctx.utils.contextify === 'function') {
418
+ return ctx.utils.contextify(context, request);
419
+ }
420
+ return rebuildRelativeRequest(context, request);
421
+ }
422
+ function rebuildRelativeRequest(context, request) {
423
+ const queryIndex = request.indexOf('?');
424
+ const resourcePath = queryIndex >= 0 ? request.slice(0, queryIndex) : request;
425
+ const query = queryIndex >= 0 ? request.slice(queryIndex) : '';
426
+ const relative = ensureDotPrefixedRelative(node_path_1.default.relative(context, resourcePath), resourcePath);
427
+ return `${relative}${query}`;
428
+ }
429
+ function makeResourceRelativeToContext(ctx, resourcePath) {
430
+ const context = ctx.context ?? node_path_1.default.dirname(resourcePath);
431
+ if (ctx.utils && typeof ctx.utils.contextify === 'function') {
432
+ const result = ctx.utils.contextify(context, resourcePath);
433
+ return stripResourceQuery(result);
434
+ }
435
+ return ensureDotPrefixedRelative(node_path_1.default.relative(context, resourcePath), resourcePath);
436
+ }
437
+ function ensureDotPrefixedRelative(relativePath, resourcePath) {
438
+ const fallback = relativePath.length > 0 ? relativePath : node_path_1.default.basename(resourcePath);
439
+ const normalized = normalizeToPosix(fallback);
440
+ if (normalized.startsWith('./') || normalized.startsWith('../')) {
441
+ return normalized;
442
+ }
443
+ return `./${normalized}`;
444
+ }
445
+ function normalizeToPosix(filePath) {
446
+ return filePath.split(node_path_1.default.sep).join('/');
447
+ }
448
+ function isRelativeSpecifier(specifier) {
449
+ return specifier.startsWith('./') || specifier.startsWith('../');
450
+ }
451
+ function emitKnightedWarning(ctx, message) {
452
+ const formatted = `\x1b[33m@knighted/css warning\x1b[0m ${message}`;
453
+ if (typeof ctx.emitWarning === 'function') {
454
+ ctx.emitWarning(new Error(formatted));
455
+ return;
456
+ }
457
+ // eslint-disable-next-line no-console
458
+ console.warn(formatted);
459
+ }
460
+ exports.__loaderBridgeInternals = {
461
+ collectStyleImportSpecifiers,
462
+ buildBridgeCssRequest,
463
+ createCombinedJsBridgeModule,
464
+ isJsLikeResource,
465
+ resolveCssModules,
466
+ resolveCssText,
467
+ buildProxyRequest,
468
+ createBridgeModule,
469
+ };
470
+ //# sourceMappingURL=loaderBridge.cjs.map