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(less): handles rewriting relative paths passed Less's data-uri function. #7400

Merged
merged 3 commits into from Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/playground/css/__tests__/css.spec.ts
Expand Up @@ -383,3 +383,11 @@ test('import css in less', async () => {
expect(await getColor('.css-in-less')).toBe('yellow')
expect(await getColor('.css-in-less-2')).toBe('blue')
})

test("relative path rewritten in Less's data-uri", async () => {
// relative path passed to Less's data-uri is rewritten to absolute,
// the Less inlines it
expect(await getBg('.form-box-data-uri')).toMatch(
/^url\("data:image\/svg\+xml,%3Csvg/
)
})
4 changes: 4 additions & 0 deletions packages/playground/css/index.html
Expand Up @@ -49,6 +49,10 @@ <h1>CSS</h1>
<p>Imported Less string:</p>
<pre class="imported-less"></pre>

<div class="form-box-data-uri">
tests Less's `data-uri()` function with relative image paths
</div>

<p class="stylus">Stylus: This should be blue</p>
<p class="stylus-additional-data">
Stylus additionalData: This should be orange
Expand Down
3 changes: 3 additions & 0 deletions packages/playground/css/less.less
@@ -1,6 +1,9 @@
@import '@/nested/nested';
@import './nested/css-in-less.less';

// Test data-uri calls with relative images.
@import './less/components/form.less';

@color: blue;

.less {
Expand Down
4 changes: 4 additions & 0 deletions packages/playground/css/less/components/form.less
@@ -0,0 +1,4 @@
.form-box-data-uri {
// data-uri() calls with relative paths should be replaced just like urls.
background-image: data-uri('../images/backgrounds/form-select.svg');
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 22 additions & 3 deletions packages/vite/src/node/plugins/css.ts
Expand Up @@ -958,6 +958,8 @@ type CssUrlReplacer = (
// https://drafts.csswg.org/css-syntax-3/#identifier-code-point
export const cssUrlRE =
/(?<=^|[^\w\-\u0080-\uffff])url\(\s*('[^']+'|"[^"]+"|[^'")]+)\s*\)/
export const cssDataUriRE =
/(?<=^|[^\w\-\u0080-\uffff])data-uri\(\s*('[^']+'|"[^"]+"|[^'")]+)\s*\)/
export const importCssRE = /@import ('[^']+\.css'|"[^"]+\.css"|[^'")]+\.css)/
const cssImageSetRE = /image-set\(([^)]+)\)/

Expand Down Expand Up @@ -1008,6 +1010,16 @@ function rewriteCssUrls(
})
}

function rewriteCssDataUris(
css: string,
replacer: CssUrlReplacer
): Promise<string> {
return asyncReplace(css, cssDataUriRE, async (match) => {
const [matched, rawUrl] = match
return await doUrlReplace(rawUrl, matched, replacer, 'data-uri')
})
}

function rewriteImportCss(
css: string,
replacer: CssUrlReplacer
Expand All @@ -1033,7 +1045,8 @@ function rewriteCssImageSet(
async function doUrlReplace(
rawUrl: string,
matched: string,
replacer: CssUrlReplacer
replacer: CssUrlReplacer,
funcName: string = 'url'
) {
let wrap = ''
const first = rawUrl[0]
Expand All @@ -1050,7 +1063,7 @@ async function doUrlReplace(
// The new url might need wrapping even if the original did not have it, e.g. if a space was added during replacement
wrap = "'"
}
return `url(${wrap}${newUrl}${wrap})`
return `${funcName}(${wrap}${newUrl}${wrap})`
}

async function doImportCSSReplace(
Expand Down Expand Up @@ -1300,10 +1313,12 @@ async function rebaseUrls(
const content = fs.readFileSync(file, 'utf-8')
// no url()
const hasUrls = cssUrlRE.test(content)
// data-uri() calls
const hasDataUris = cssDataUriRE.test(content)
// no @import xxx.css
const hasImportCss = importCssRE.test(content)

if (!hasUrls && !hasImportCss) {
if (!hasUrls && !hasDataUris && !hasImportCss) {
return { file }
}

Expand Down Expand Up @@ -1332,6 +1347,10 @@ async function rebaseUrls(
rebased = await rewriteCssUrls(rebased || content, rebaseFn)
}

if (hasDataUris) {
rebased = await rewriteCssDataUris(rebased || content, rebaseFn)
}

return {
file,
contents: rebased
Expand Down