Skip to content

Commit

Permalink
fix(assets): fix svg inline in css url (#14714)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy authored Oct 20, 2023
1 parent c5f2d60 commit eef4aaa
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 3 deletions.
16 changes: 13 additions & 3 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ const inlineRE = /[?&]inline\b/
const inlineCSSRE = /[?&]inline-css\b/
const styleAttrRE = /[?&]style-attr\b/
const varRE = /^var\(/i
const nonEscapedDoubleQuoteRe = /(?<!\\)(")/g

const cssBundleName = 'style.css'

Expand Down Expand Up @@ -1512,10 +1513,19 @@ async function doUrlReplace(
return matched
}

const newUrl = await replacer(rawUrl)
let newUrl = await replacer(rawUrl)
// The new url might need wrapping even if the original did not have it, e.g. if a space was added during replacement
if (wrap === '' && newUrl !== encodeURI(newUrl)) {
// The new url might need wrapping even if the original did not have it, e.g. if a space was added during replacement
wrap = "'"
wrap = '"'
}
// If wrapping in single quotes and newUrl also contains single quotes, switch to double quotes.
// Give preference to double quotes since SVG inlining converts double quotes to single quotes.
if (wrap === "'" && newUrl.includes("'")) {
wrap = '"'
}
// Escape double quotes if they exist (they also tend to be rarer than single quotes)
if (wrap === '"' && newUrl.includes('"')) {
newUrl = newUrl.replace(nonEscapedDoubleQuoteRe, '\\"')
}
return `${funcName}(${wrap}${newUrl}${wrap})`
}
Expand Down
12 changes: 12 additions & 0 deletions playground/assets/__tests__/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,18 @@ describe('css url() references', () => {
// generate non-relative base for public path in CSS
expect(css).not.toMatch(`../icon.png`)
})

test('url() with svg', async () => {
expect(await getBg('.css-url-svg')).toMatch(
isBuild ? /data:image\/svg\+xml,.+/ : '/foo/bar/nested/fragment-bg.svg',
)
})

test('image-set() with svg', async () => {
expect(await getBg('.css-image-set-svg')).toMatch(
isBuild ? /data:image\/svg\+xml,.+/ : '/foo/bar/nested/fragment-bg.svg',
)
})
})

describe('image', () => {
Expand Down
13 changes: 13 additions & 0 deletions playground/assets/css/css-url.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions playground/assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ <h2>CSS url references</h2>
<span style="background: #fff">CSS background (aliased)</span>
</div>

<div class="css-url-svg">
<span style="background: #fff">CSS SVG background</span>
</div>

<div class="css-image-set-svg">
<span style="background: #fff">CSS SVG background with image-set</span>
</div>

<h2>Unicode URL</h2>
<div>
<code class="unicode-url"></code>
Expand Down

0 comments on commit eef4aaa

Please sign in to comment.