1+ import path from 'node:path'
2+
13import type {
24 LoaderContext ,
35 LoaderDefinitionFunction ,
@@ -203,15 +205,25 @@ function buildProxyRequest(ctx: LoaderContext<KnightedCssLoaderOptions>): string
203205 const sanitizedQuery = buildSanitizedQuery ( ctx . resourceQuery )
204206 const rawRequest = getRawRequest ( ctx )
205207 if ( rawRequest ) {
206- const stripped = stripResourceQuery ( rawRequest )
207- return `${ stripped } ${ sanitizedQuery } `
208+ return rebuildProxyRequestFromRaw ( ctx , rawRequest , sanitizedQuery )
208209 }
209210 const request = `${ ctx . resourcePath } ${ sanitizedQuery } `
210- const context = ctx . context ?? ctx . rootContext ?? process . cwd ( )
211- if ( ctx . utils && typeof ctx . utils . contextify === 'function' ) {
212- return ctx . utils . contextify ( context , request )
211+ return contextifyRequest ( ctx , request )
212+ }
213+
214+ function rebuildProxyRequestFromRaw (
215+ ctx : LoaderContext < KnightedCssLoaderOptions > ,
216+ rawRequest : string ,
217+ sanitizedQuery : string ,
218+ ) : string {
219+ const stripped = stripResourceQuery ( rawRequest )
220+ const loaderDelimiter = stripped . lastIndexOf ( '!' )
221+ const loaderPrefix = loaderDelimiter >= 0 ? stripped . slice ( 0 , loaderDelimiter + 1 ) : ''
222+ let resource = loaderDelimiter >= 0 ? stripped . slice ( loaderDelimiter + 1 ) : stripped
223+ if ( isRelativeSpecifier ( resource ) ) {
224+ resource = makeResourceRelativeToContext ( ctx , ctx . resourcePath )
213225 }
214- return request
226+ return ` ${ loaderPrefix } ${ resource } ${ sanitizedQuery } `
215227}
216228
217229function getRawRequest ( ctx : LoaderContext < KnightedCssLoaderOptions > ) : string | undefined {
@@ -232,6 +244,57 @@ function stripResourceQuery(request: string): string {
232244 return idx >= 0 ? request . slice ( 0 , idx ) : request
233245}
234246
247+ function contextifyRequest (
248+ ctx : LoaderContext < KnightedCssLoaderOptions > ,
249+ request : string ,
250+ ) : string {
251+ const context = ctx . context ?? ctx . rootContext ?? process . cwd ( )
252+ if ( ctx . utils && typeof ctx . utils . contextify === 'function' ) {
253+ return ctx . utils . contextify ( context , request )
254+ }
255+ return rebuildRelativeRequest ( context , request )
256+ }
257+
258+ function rebuildRelativeRequest ( context : string , request : string ) : string {
259+ const queryIndex = request . indexOf ( '?' )
260+ const resourcePath = queryIndex >= 0 ? request . slice ( 0 , queryIndex ) : request
261+ const query = queryIndex >= 0 ? request . slice ( queryIndex ) : ''
262+ const relative = ensureDotPrefixedRelative (
263+ path . relative ( context , resourcePath ) ,
264+ resourcePath ,
265+ )
266+ return `${ relative } ${ query } `
267+ }
268+
269+ function makeResourceRelativeToContext (
270+ ctx : LoaderContext < KnightedCssLoaderOptions > ,
271+ resourcePath : string ,
272+ ) : string {
273+ const context = ctx . context ?? path . dirname ( resourcePath )
274+ if ( ctx . utils && typeof ctx . utils . contextify === 'function' ) {
275+ const result = ctx . utils . contextify ( context , resourcePath )
276+ return stripResourceQuery ( result )
277+ }
278+ return ensureDotPrefixedRelative ( path . relative ( context , resourcePath ) , resourcePath )
279+ }
280+
281+ function ensureDotPrefixedRelative ( relativePath : string , resourcePath : string ) : string {
282+ const fallback = relativePath . length > 0 ? relativePath : path . basename ( resourcePath )
283+ const normalized = normalizeToPosix ( fallback )
284+ if ( normalized . startsWith ( './' ) || normalized . startsWith ( '../' ) ) {
285+ return normalized
286+ }
287+ return `./${ normalized } `
288+ }
289+
290+ function normalizeToPosix ( filePath : string ) : string {
291+ return filePath . split ( path . sep ) . join ( '/' )
292+ }
293+
294+ function isRelativeSpecifier ( specifier : string ) : boolean {
295+ return specifier . startsWith ( './' ) || specifier . startsWith ( '../' )
296+ }
297+
235298interface CombinedModuleOptions {
236299 emitDefault ?: boolean
237300 stableSelectorsLiteral ?: string
0 commit comments