0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

fix(rendering): prevent removal of necessary <astro-slot> elements (#10317)

* fix(rendering): prevent removal of necessary `<astro-slot>` elements

* add test

* add changeset

* missed a spot

* adjust test

* assume `supportsAstroStaticSlot`

* bring back accidentally removed `markHTMLString` call
This commit is contained in:
Arsh 2024-03-07 21:55:03 +05:30 committed by GitHub
parent 3de48e8f62
commit 33583e8b31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 56 additions and 5 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Fixes an issue where elements slotted within interactive framework components disappeared after hydration.

View file

@ -0,0 +1,6 @@
---
const Tag = 'div';
---
<Tag>
<slot />
</Tag>

View file

@ -0,0 +1,4 @@
<script>
export let id;
</script>
<div {id}>Slot goes here:<slot /></div>

View file

@ -0,0 +1,23 @@
---
import Poly from '../components/Poly.astro';
import Stuff from '../components/Stuff.svelte';
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
<Poly>
<Stuff client:load id="hydratable">poo</Stuff>
</Poly>
<Poly>
<Stuff id="ssr-only">bar</Stuff>
</Poly>
</body>
</html>

View file

@ -1,5 +1,6 @@
import { expect } from '@playwright/test';
import { prepareTestFactory } from './shared-component-tests.js';
import { waitForHydrate } from './test-utils.js';
const { test, createTests } = prepareTestFactory({ root: './fixtures/svelte-component/' });
@ -35,3 +36,13 @@ test.describe('Svelte components lifecycle', () => {
expect((await toggle.textContent()).trim()).toBe('open');
});
});
test.describe('Slotting content into svelte components', () => {
test('should stay after hydration', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/with-slots'));
const hydratableElement = page.locator('#hydratable');
await waitForHydrate(page, hydratableElement);
await expect(hydratableElement).toHaveText("Slot goes here:poo");
});
});

View file

@ -67,7 +67,8 @@ function isHTMLComponent(Component: unknown) {
const ASTRO_SLOT_EXP = /<\/?astro-slot\b[^>]*>/g;
const ASTRO_STATIC_SLOT_EXP = /<\/?astro-static-slot\b[^>]*>/g;
function removeStaticAstroSlot(html: string, supportsAstroStaticSlot: boolean) {
function removeStaticAstroSlot(html: string, supportsAstroStaticSlot = true) {
const exp = supportsAstroStaticSlot ? ASTRO_STATIC_SLOT_EXP : ASTRO_SLOT_EXP;
return html.replace(exp, '');
}
@ -310,7 +311,7 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr
} else if (html && html.length > 0) {
destination.write(
markHTMLString(
removeStaticAstroSlot(html, renderer?.ssr?.supportsAstroStaticSlot ?? false)
removeStaticAstroSlot(html, renderer?.ssr?.supportsAstroStaticSlot)
)
);
}
@ -391,7 +392,8 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr
})
);
}
destination.write(markHTMLString(renderElement('astro-island', island, false)));
const renderedElement = renderElement('astro-island', island, false);
destination.write(markHTMLString(renderedElement));
},
};
}

View file

@ -18,9 +18,9 @@ describe('Slots with client: directives', () => {
assert.equal($('script').length, 1);
});
it('Astro slot tags are cleaned', async () => {
it('Astro slot tags are kept', async () => {
const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html);
assert.equal($('astro-slot').length, 0);
assert.equal($('astro-slot').length, 1);
});
});