11import type { LoaderContext } from 'webpack'
22import { ECacheKey , ILightningCssLoaderConfig } from './interface'
3- import { transform as _transform } from 'lightningcss'
3+ import lightningcss from 'lightningcss'
44import { Buffer } from 'buffer'
55import { getTargets } from './utils'
66
77const LOADER_NAME = `lightningcss-loader`
8+
9+ // match `Custom media query {} is not defined`
10+ // https://github.com/parcel-bundler/lightningcss/blob/master/src/error.rs#L375
11+ const CUSTOM_MEDIA_ERROR_REG = / C u s t o m m e d i a q u e r y ( .+ ?) i s n o t d e f i n e d /
12+ const isCustomMediaError = ( err ?: Error ) => {
13+ const msg = err ?. message
14+ if ( ! msg ?. length ) {
15+ return false
16+ }
17+ const isMatch = CUSTOM_MEDIA_ERROR_REG . test ( msg )
18+ return isMatch
19+ }
20+
821export async function LightningCssLoader (
922 this : LoaderContext < ILightningCssLoaderConfig > ,
1023 source : string ,
@@ -23,21 +36,53 @@ export async function LightningCssLoader(
2336 return
2437 }
2538
26- const transform = implementation ?. transform ?? _transform
39+ const transform = implementation ?. transform ?? lightningcss . transform
40+ const bundle = implementation ?. bundle ?? lightningcss . bundle
41+
42+ const filename = this . resourcePath
43+ const enableSourceMap = this . sourceMap
44+ const targets = getTargets ( { default : userTargets , key : ECacheKey . loader } )
45+ const inputSourceMap =
46+ enableSourceMap && prevMap ? JSON . stringify ( prevMap ) : undefined
2747
2848 try {
49+ const codeBuffer = Buffer . from ( source )
50+
2951 const { code, map } = transform ( {
30- filename : this . resourcePath ,
31- code : Buffer . from ( source ) ,
32- sourceMap : this . sourceMap ,
33- targets : getTargets ( { default : userTargets , key : ECacheKey . loader } ) ,
34- inputSourceMap :
35- this . sourceMap && prevMap ? JSON . stringify ( prevMap ) : undefined ,
52+ filename,
53+ code : codeBuffer ,
54+ sourceMap : enableSourceMap ,
55+ targets,
56+ inputSourceMap,
3657 ...opts ,
3758 } )
3859 const codeAsString = code . toString ( )
3960 done ( null , codeAsString , map && JSON . parse ( map . toString ( ) ) )
4061 } catch ( error : unknown ) {
62+ // support @custom -media queries
63+ const isCustomMediaEnabled = opts ?. drafts ?. customMedia === true
64+ if ( isCustomMediaEnabled ) {
65+ const canBundle =
66+ typeof bundle === 'function' &&
67+ isCustomMediaError ( error as Error ) &&
68+ filename
69+ if ( canBundle ) {
70+ // fallback to bundle API
71+ try {
72+ const { code, map } = bundle ( {
73+ filename,
74+ sourceMap : enableSourceMap ,
75+ targets,
76+ inputSourceMap,
77+ ...opts ,
78+ } )
79+ const codeAsString = code . toString ( )
80+ done ( null , codeAsString , map && JSON . parse ( map . toString ( ) ) )
81+ return
82+ } catch { }
83+ }
84+ }
85+
4186 done ( error as Error )
4287 }
4388}
0 commit comments