Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(build): use base64 for inline SVG if it contains both single and double quotes #15271

Merged
merged 15 commits into from
Dec 15, 2023
Merged
5 changes: 4 additions & 1 deletion packages/vite/src/node/plugins/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,17 @@ export async function urlToBuiltUrl(
)
}

const nestedQuotesRE = /"[^"']*'[^"]*"|'[^'"]*"[^']*'/

// Inspired by https://github.com/iconify/iconify/blob/main/packages/utils/src/svg/url.ts
function svgToDataURL(content: Buffer): string {
const stringContent = content.toString()
// If the SVG contains some text or HTML, any transformation is unsafe, and given that double quotes would then
// need to be escaped, the gain to use a data URI would be ridiculous if not negative
if (
stringContent.includes('<text') ||
stringContent.includes('<foreignObject')
stringContent.includes('<foreignObject') ||
nestedQuotesRE.test(stringContent)
) {
return `data:image/svg+xml;base64,${content.toString('base64')}`
} else {
Expand Down
12 changes: 12 additions & 0 deletions playground/data-uri/__tests__/data-uri.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ test('base64', async () => {
expect(await page.textContent('.base64')).toBe('hi')
})

test('svg data uri minify', async () => {
const sqdqs = await page.getByTestId('sqdqs').boundingBox()
const sqsdqs = await page.getByTestId('sqsdqs').boundingBox()
const dqsqs = await page.getByTestId('dqsqs').boundingBox()
const dqssqs = await page.getByTestId('dqssqs').boundingBox()

expect(sqdqs.height).toBe(100)
expect(sqsdqs.height).toBe(100)
expect(dqsqs.height).toBe(100)
expect(dqssqs.height).toBe(100)
})

test.runIf(isBuild)('should compile away the import for build', async () => {
const file = findAssetFile('index')
expect(file).not.toMatch('import')
Expand Down
1 change: 1 addition & 0 deletions playground/data-uri/double-quote-in-single-quotes.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions playground/data-uri/double-quotes-in-single-quotes.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions playground/data-uri/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@
document.querySelector(el).textContent = text
}
</script>

<script type="module" src="./main.js"></script>

<div id="sqdqs"></div>
<div id="sqsdqs"></div>
<div id="dqsqs"></div>
<div id="dqssqs"></div>
18 changes: 18 additions & 0 deletions playground/data-uri/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sqdqs from './single-quote-in-double-quotes.svg'
import sqsdqs from './single-quotes-in-double-quotes.svg'
import dqsqs from './double-quote-in-single-quotes.svg'
import dqssqs from './double-quotes-in-single-quotes.svg'

document.querySelector('#sqdqs').innerHTML = `
<img data-testid="sqdqs" src="${sqdqs}" class="sqdqs" alt="load failed" />
`
document.querySelector('#sqsdqs').innerHTML = `
<img data-testid="sqsdqs" src="${sqsdqs}" class="sqsdqs" alt="load failed" />
`

document.querySelector('#dqsqs').innerHTML = `
<img data-testid="dqsqs" src="${dqsqs}" class="dqsqs" alt="load failed" />
`
document.querySelector('#dqssqs').innerHTML = `
<img data-testid="dqssqs" src="${dqssqs}" class="dqssqs" alt="load failed" />
`
1 change: 1 addition & 0 deletions playground/data-uri/single-quote-in-double-quotes.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions playground/data-uri/single-quotes-in-double-quotes.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.