Skip to content

Commit d562aaa

Browse files
committed
feat: support custom media 🍓
1 parent 264e54f commit d562aaa

File tree

1 file changed

+53
-8
lines changed

1 file changed

+53
-8
lines changed

src/loader.ts

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
import type { LoaderContext } from 'webpack'
22
import { ECacheKey, ILightningCssLoaderConfig } from './interface'
3-
import { transform as _transform } from 'lightningcss'
3+
import lightningcss from 'lightningcss'
44
import { Buffer } from 'buffer'
55
import { getTargets } from './utils'
66

77
const 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 = /Custom media query (.+?) is not defined/
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+
821
export 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

Comments
 (0)