Skip to content

Commit

Permalink
fix(css): var in image-set (#7921)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bigfish8 authored May 3, 2022
1 parent 1db7c49 commit e96b908
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 13 deletions.
23 changes: 23 additions & 0 deletions packages/playground/assets/__tests__/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,29 @@ describe('css url() references', () => {
})
})

test('image-set with var', async () => {
const imageSet = await getBg('.css-image-set-with-var')
imageSet.split(', ').forEach((s) => {
expect(s).toMatch(assetMatch)
})
})

test('image-set with mix', async () => {
const imageSet = await getBg('.css-image-set-mix-url-var')
imageSet.split(', ').forEach((s) => {
expect(s).toMatch(assetMatch)
})
})

// not supported in browser now
// https://drafts.csswg.org/css-images-4/#image-set-notation
// test('image-set with multiple descriptor', async () => {
// const imageSet = await getBg('.css-image-set-multiple-descriptor')
// imageSet.split(', ').forEach((s) => {
// expect(s).toMatch(assetMatch)
// })
// })

test('relative in @import', async () => {
expect(await getBg('.css-url-relative-at-imported')).toMatch(assetMatch)
})
Expand Down
23 changes: 23 additions & 0 deletions packages/playground/assets/css/css-url.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@
background-size: 10px;
}

.css-image-set-with-var {
--bg-img: url('../nested/asset.png');
background-image: -webkit-image-set(var(--bg-img) 1x, var(--bg-img) 2x);
background-size: 10px;
}

.css-image-set-mix-url-var {
--bg-img: url('../nested/asset.png');
background-image: -webkit-image-set(
var(--bg-img) 1x,
url('../nested/asset.png') 2x
);
background-size: 10px;
}

.css-image-set-multiple-descriptor {
background-image: -webkit-image-set(
'../nested/asset.png' type('image/png') 1x,
'../nested/asset.png' type('image/png') 2x
);
background-size: 10px;
}

.css-url-public {
background: url('/icon.png');
background-size: 10px;
Expand Down
28 changes: 28 additions & 0 deletions packages/playground/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,34 @@ <h2>CSS url references</h2>
>CSS background with image-set() (relative)</span
>
</div>
<div class="css-image-set-with-var">
<span style="background: #fff">
CSS background image-set() (relative in var)
</span>
</div>
<div class="css-image-set-mix-url-var">
<span style="background: #fff">
CSS background image-set() (mix var and url)
</span>
</div>
<div class="css-image-set-multiple-descriptor">
<span style="background: #fff">
CSS background image-set() (with multiple descriptor)
</span>
</div>
<div
style="
background-image: -webkit-image-set(
'./nested/asset.png' type('image/png') 1x,
'./nested/asset.png' type('image/png') 2x
);
background-size: 10px;
"
>
<span style="background: #fff">
CSS background image-set() (with multiple descriptor)
</span>
</div>
<div class="css-url-relative-at-imported">
<span style="background: #fff"
>CSS background (relative from @imported file in different dir)</span
Expand Down
29 changes: 21 additions & 8 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ const commonjsProxyRE = /\?commonjs-proxy/
const inlineRE = /(\?|&)inline\b/
const inlineCSSRE = /(\?|&)inline-css\b/
const usedRE = /(\?|&)used\b/
const varRE = /^var\(/i

const enum PreprocessLang {
less = 'less',
Expand Down Expand Up @@ -980,7 +981,7 @@ export const cssUrlRE =
export const cssDataUriRE =
/(?<=^|[^\w\-\u0080-\uffff])data-uri\(\s*('[^']+'|"[^"]+"|[^'")]+)\s*\)/
export const importCssRE = /@import ('[^']+\.css'|"[^"]+\.css"|[^'")]+\.css)/
const cssImageSetRE = /image-set\(([^)]+)\)/
const cssImageSetRE = /(?<=image-set\()((?:[\w\-]+\([^\)]*\)|[^)])*)(?=\))/

const UrlRewritePostcssPlugin: PostCSS.PluginCreator<{
replacer: CssUrlReplacer
Expand All @@ -1001,7 +1002,9 @@ const UrlRewritePostcssPlugin: PostCSS.PluginCreator<{
const importer = declaration.source?.input.file
return opts.replacer(rawUrl, importer)
}
const rewriterToUse = isCssUrl ? rewriteCssUrls : rewriteCssImageSet
const rewriterToUse = isCssImageSet
? rewriteCssImageSet
: rewriteCssUrls
promises.push(
rewriterToUse(declaration.value, replacerForDeclaration).then(
(url) => {
Expand Down Expand Up @@ -1054,11 +1057,15 @@ function rewriteCssImageSet(
replacer: CssUrlReplacer
): Promise<string> {
return asyncReplace(css, cssImageSetRE, async (match) => {
const [matched, rawUrl] = match
const url = await processSrcSet(rawUrl, ({ url }) =>
doUrlReplace(url, matched, replacer)
)
return `image-set(${url})`
const [, rawUrl] = match
const url = await processSrcSet(rawUrl, async ({ url }) => {
// the url maybe url(...)
if (cssUrlRE.test(url)) {
return await rewriteCssUrls(url, replacer)
}
return await doUrlReplace(url, url, replacer)
})
return url
})
}
async function doUrlReplace(
Expand All @@ -1073,7 +1080,13 @@ async function doUrlReplace(
wrap = first
rawUrl = rawUrl.slice(1, -1)
}
if (isExternalUrl(rawUrl) || isDataUrl(rawUrl) || rawUrl.startsWith('#')) {

if (
isExternalUrl(rawUrl) ||
isDataUrl(rawUrl) ||
rawUrl.startsWith('#') ||
varRE.test(rawUrl)
) {
return matched
}

Expand Down
13 changes: 8 additions & 5 deletions packages/vite/src/node/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,18 +545,21 @@ interface ImageCandidate {
descriptor: string
}
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
const imageSetUrlRE = /^(?:[\w\-]+\(.*?\)|'.*?'|".*?"|\S*)/
export async function processSrcSet(
srcs: string,
replacer: (arg: ImageCandidate) => Promise<string>
): Promise<string> {
const imageCandidates: ImageCandidate[] = srcs
.split(',')
.map((s) => {
const [url, descriptor] = s
.replace(escapedSpaceCharacters, ' ')
.trim()
.split(' ', 2)
return { url, descriptor }
const src = s.replace(escapedSpaceCharacters, ' ').trim()
const [url] = imageSetUrlRE.exec(src) || []

return {
url,
descriptor: src?.slice(url.length).trim()
}
})
.filter(({ url }) => !!url)

Expand Down

0 comments on commit e96b908

Please sign in to comment.