0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00

Exclude hoisted scripts and styles from raw imports (#11509)

This commit is contained in:
Bjorn Lu 2024-07-22 16:10:48 +08:00 committed by GitHub
parent a6c4e67544
commit dfbca06dda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 35 additions and 2 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Excludes hoisted scripts and styles from Astro components imported with `?url` or `?raw`

View file

@ -2,6 +2,7 @@ import npath from 'node:path';
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../core/constants.js';
import type { ModuleLoader, ModuleNode } from '../core/module-loader/index.js';
import { unwrapId } from '../core/util.js';
import { hasSpecialQueries } from '../vite-plugin-utils/index.js';
import { isCSSRequest } from './util.js';
/**
@ -42,6 +43,10 @@ export async function* crawlGraph(
if (id === entry.id) {
scanned.add(id);
// NOTE: It may be worth revisiting if we can crawl direct imports of the module since
// `.importedModules` would also include modules that are dynamically watched, not imported.
// That way we no longer need the below `continue` skips.
// CSS requests `importedModules` are usually from `@import`, but we don't really need
// to crawl into those as the `@import` code are already inlined into this `id`.
// If CSS requests `importedModules` contain non-CSS files, e.g. Tailwind might add HMR
@ -50,6 +55,13 @@ export async function* crawlGraph(
if (isCSSRequest(id)) {
continue;
}
// Some special Vite queries like `?url` or `?raw` are known to be a simple default export
// and doesn't have any imports to crawl. However, since they would `this.addWatchFile` the
// underlying module, our logic would crawl into them anyways which is incorrect as they
// don't take part in the final rendering, so we skip it here.
if (hasSpecialQueries(id)) {
continue;
}
for (const importedModule of entry.importedModules) {
if (!importedModule.id) continue;

View file

@ -162,7 +162,14 @@ describe('Astro basic build', () => {
it('Handles importing .astro?raw correctly', async () => {
const html = await fixture.readFile('/import-queries/raw/index.html');
const $ = cheerio.load(html);
assert.equal($('.raw-value').text(), '<h1>Hello</h1>\n');
const rawValue = $('.raw-value').text();
assert.match(rawValue, /<h1>Hello<\/h1>/);
assert.match(rawValue, /<script>/);
assert.match(rawValue, /<style>/);
// The rest of HTML should not contain any scripts or styles hoisted from the raw import
const otherHtml = html.replace(rawValue, '');
assert.doesNotMatch(otherHtml, /<script/);
assert.doesNotMatch(otherHtml, /<style/);
});
describe('preview', () => {
@ -223,6 +230,13 @@ describe('Astro basic development', () => {
assert.equal(res.status, 200);
const html = await res.text();
const $ = cheerio.load(html);
assert.equal($('.raw-value').text(), '<h1>Hello</h1>\n');
const rawValue = $('.raw-value').text();
assert.match(rawValue, /<h1>Hello<\/h1>/);
assert.match(rawValue, /<script>/);
assert.match(rawValue, /<style>/);
// The rest of HTML should not contain any scripts or styles hoisted from the raw import.
// However we don't check them here as dev plugins could add scripts and styles dynam
assert.doesNotMatch(html, /_content.astro\?astro&type=style/);
assert.doesNotMatch(html, /_content.astro\?astro&type=script/);
});
});

View file

@ -1 +1,3 @@
<h1>Hello</h1>
<script>console.log('Should not log')</script>
<style>h1 { color: red; }</style>