0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

fix(css): fix inline query injection for CSS inlining (#11917)

This commit is contained in:
翠 / green 2024-09-10 12:11:57 +09:00 committed by GitHub
parent b9394fa70c
commit 8329d17968
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 14 additions and 18 deletions

View file

@ -9,6 +9,8 @@ interface ImportedStyle {
content: string;
}
const inlineQueryRE = /(?:\?|&)inline(?:$|&)/
/** Given a filePath URL, crawl Vites module graph to find all style imports. */
export async function getStylesForURL(
filePath: URL,
@ -32,21 +34,20 @@ export async function getStylesForURL(
}
// Else try to load it
else {
const url = new URL(importedModule.url, 'http://localhost');
let modId = importedModule.url
// Mark url with ?inline so Vite will return the CSS as plain string, even for CSS modules
url.searchParams.set('inline', '');
const modId = `${decodeURI(url.pathname)}${url.search}`;
if (!inlineQueryRE.test(importedModule.url)) {
if (importedModule.url.includes('?')) {
modId = importedModule.url.replace('?', '?inline&');
} else {
modId += '?inline';
}
}
try {
// The SSR module is possibly not loaded. Load it if it's null.
const ssrModule = await loader.import(modId);
css = ssrModule.default;
} catch {
// Some CSS modules, e.g. from Vue files, may not work with the ?inline query.
// If so, we fallback to a url instead
if (modId.includes('.module.')) {
importedCssUrls.add(importedModule.url);
}
// The module may not be inline-able, e.g. SCSS partials. Skip it as it may already
// be inlined into other modules if it happens to be in the graph.
continue;

View file

@ -225,7 +225,7 @@ describe('CSS', function () {
it('<style module>', async () => {
const el = $('#vue-modules');
const classes = el.attr('class').split(' ');
const moduleClass = classes.find((name) => /^_title_[\w-]+/.test(name));
const moduleClass = classes.find((name) => /^_vueModules_[\w-]+/.test(name));
// 1. check HTML
assert.equal(el.attr('class').includes(moduleClass), true);
@ -405,18 +405,13 @@ describe('CSS', function () {
});
it('resolves CSS from Vue', async () => {
const styles = ['VueModules.vue?vue&type=style&index=0&lang.module.scss'];
for (const style of styles) {
const href = $(`link[href$="${style}"]`).attr('href');
assert.equal((await fixture.fetch(href)).status, 200, style);
}
const allInjectedStyles = $('style').text().replace(/\s*/g, '');
assert.equal(allInjectedStyles.includes('.vue-css{'), true);
assert.equal(allInjectedStyles.includes('.vue-sass{'), true);
assert.equal(allInjectedStyles.includes('.vue-scss{'), true);
assert.equal(allInjectedStyles.includes('.vue-scoped[data-v-'), true);
assert.equal(allInjectedStyles.includes('._vueModules_'), true);
});
it('remove unused styles from client:load components', async () => {

View file

@ -1,10 +1,10 @@
<style module lang="scss">
$type: cursive;
.title {
.vueModules {
font-family: $type;
}
</style>
<template>
<h1 id="vue-modules" :class="$style.title">Vue CSS Modules</h1>
<h1 id="vue-modules" :class="$style.vueModules">Vue CSS Modules</h1>
</template>