Skip to content

Commit 8ce40a4

Browse files
fix(compiler): Support dynamic slot names (#9605)
* chore: try new compiler version * update mergeSlots function * chore: update lock file * add tests * simplify `mergeSlots` code * update compiler version * update lock file * fix failing test We were expecting the source code to produce an error, but in 2.4.0 of the compiler, that generates valid code * chore: changeset * chore: update deps --------- Co-authored-by: Nate Moore <[email protected]> Co-authored-by: Nate Moore <[email protected]>
1 parent 07f13e6 commit 8ce40a4

File tree

9 files changed

+78
-9
lines changed

9 files changed

+78
-9
lines changed

.changeset/red-carrots-fail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"astro": patch
3+
---
4+
5+
Adds support for dynamic slot names

packages/astro/e2e/errors.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ test.describe('Error display', () => {
2525
await page.goto(astro.resolveUrl('/astro-syntax-error'), { waitUntil: 'networkidle' });
2626

2727
const message = (await getErrorOverlayContent(page)).message;
28-
expect(message).toMatch('Unexpected "}"');
28+
expect(message).toMatch('Unexpected "while"');
2929

3030
await Promise.all([
3131
// Wait for page reload
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<h1>{// comment
1+
<h1>{while (true){}}</h1>

packages/astro/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
"test:e2e:match": "playwright test -g"
115115
},
116116
"dependencies": {
117-
"@astrojs/compiler": "^2.3.4",
117+
"@astrojs/compiler": "^2.5.0",
118118
"@astrojs/internal-helpers": "workspace:*",
119119
"@astrojs/markdown-remark": "workspace:*",
120120
"@astrojs/telemetry": "workspace:*",

packages/astro/src/runtime/server/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ import { addAttribute, Renderer } from './render/index.js';
4545

4646
export function mergeSlots(...slotted: unknown[]) {
4747
const slots: Record<string, () => any> = {};
48-
for (const slot of slotted) {
48+
for (let slot of slotted) {
4949
if (!slot) continue;
50+
if (Array.isArray(slot)) {
51+
slot = mergeSlots(...slot);
52+
}
5053
if (typeof slot === 'object') {
5154
Object.assign(slots, slot);
5255
} else if (typeof slot === 'function') {

packages/astro/test/astro-slots.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,26 @@ describe('Slots', () => {
3030
expect($('#default').text().trim()).to.equal('Default');
3131
});
3232

33+
it('Dynamic named slots work with map work', async () => {
34+
const html = await fixture.readFile('/dynamic-map/index.html');
35+
const $ = cheerio.load(html);
36+
37+
expect($('#a').text().trim()).to.equal('A');
38+
expect($('#b').text().trim()).to.equal('B');
39+
expect($('#c').text().trim()).to.equal('C');
40+
expect($('#default').text().trim()).to.equal('Default');
41+
});
42+
43+
it('Dynamic named slots work with for loop', async () => {
44+
const html = await fixture.readFile('/dynamic-for/index.html');
45+
const $ = cheerio.load(html);
46+
47+
expect($('#a').text().trim()).to.equal('A');
48+
expect($('#b').text().trim()).to.equal('B');
49+
expect($('#c').text().trim()).to.equal('C');
50+
expect($('#default').text().trim()).to.equal('Default');
51+
});
52+
3353
it('Conditional named slots work', async () => {
3454
const html = await fixture.readFile('/conditional/index.html');
3555
const $ = cheerio.load(html);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
import Slotted from '../components/Slotted.astro';
3+
4+
const slotNames = ['a', 'b', 'c']
5+
---
6+
7+
<html>
8+
<head>
9+
<!-- Head Stuff -->
10+
</head>
11+
<body>
12+
<Slotted>
13+
{()=>{
14+
const slots:any[] = [];
15+
for (const slotName of slotNames) {
16+
slots.push(<span slot={slotName}>{slotName.toUpperCase()}</span>);
17+
}
18+
return slots;
19+
}
20+
}
21+
<span>Default</span>
22+
</Slotted>
23+
</body>
24+
</html>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
import Slotted from '../components/Slotted.astro';
3+
4+
const slots = ['a', 'b', 'c']
5+
---
6+
7+
<html>
8+
<head>
9+
<!-- Head Stuff -->
10+
</head>
11+
<body>
12+
<Slotted>
13+
{slots.map((slotName)=><span slot={slotName}>{slotName.toUpperCase()}</span>)}
14+
<span>Default</span>
15+
</Slotted>
16+
</body>
17+
</html>

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)