Fix slot attribute inside expressions (#3837)

* fix: use slots inside expressions

* test: add test for conditional named slots

* test: fix incorrect test fixture

* chore: update `@astrojs/compiler`

* chore: add test coverage for `switch`

Co-authored-by: Nate Moore <nate@astro.build>
This commit is contained in:
Nate Moore 2022-07-07 13:23:51 -05:00 committed by GitHub
parent c191098b97
commit 5afb807688
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 5 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fix usage of slots inside expressions

View file

@ -80,7 +80,7 @@
"test:e2e:match": "playwright test -g" "test:e2e:match": "playwright test -g"
}, },
"dependencies": { "dependencies": {
"@astrojs/compiler": "^0.17.1", "@astrojs/compiler": "^0.18.0",
"@astrojs/language-server": "^0.13.4", "@astrojs/language-server": "^0.13.4",
"@astrojs/markdown-remark": "^0.11.3", "@astrojs/markdown-remark": "^0.11.3",
"@astrojs/prism": "0.4.1", "@astrojs/prism": "0.4.1",

View file

@ -142,6 +142,19 @@ export async function renderSlot(_result: any, slotted: string, fallback?: any):
return fallback; return fallback;
} }
export function mergeSlots(...slotted: unknown[]) {
const slots: Record<string, () => any> = {};
for (const slot of slotted) {
if (!slot) continue;
if (typeof slot === 'object') {
Object.assign(slots, slot);
} else if (typeof slot === 'function') {
Object.assign(slots, mergeSlots(slot()));
}
}
return slots;
}
export const Fragment = Symbol('Astro.Fragment'); export const Fragment = Symbol('Astro.Fragment');
function guessRenderers(componentUrl?: string): string[] { function guessRenderers(componentUrl?: string): string[] {

View file

@ -114,4 +114,13 @@ describe('Expressions', () => {
expect($('#single-escape').html()).to.equal('Astro &amp; Vite'); expect($('#single-escape').html()).to.equal('Astro &amp; Vite');
}); });
it('Handles switch statements', async () => {
const html = await fixture.readFile('/switch/index.html');
const $ = cheerio.load(html);
expect($('#red').length).to.equal(0);
expect($('#yellow').length).to.equal(1);
expect($('#blue').length).to.equal(0);
});
}); });

View file

@ -30,6 +30,16 @@ describe('Slots', () => {
expect($('#default').text().trim()).to.equal('Default'); expect($('#default').text().trim()).to.equal('Default');
}); });
it('Conditional named slots work', async () => {
const html = await fixture.readFile('/conditional/index.html');
const $ = cheerio.load(html);
expect($('#a').text().trim()).to.equal('A');
expect($('#b').text().trim()).to.equal('B');
expect($('#c').text().trim()).to.equal('C');
expect($('#default').text().trim()).to.equal('Default');
});
it('Slots render fallback content by default', async () => { it('Slots render fallback content by default', async () => {
const html = await fixture.readFile('/fallback/index.html'); const html = await fixture.readFile('/fallback/index.html');
const $ = cheerio.load(html); const $ = cheerio.load(html);

View file

@ -0,0 +1,20 @@
---
let title = 'Switch';
let colors = ['red', 'yellow', 'blue'];
---
<html>
<head>
<title>{title}</title>
</head>
<body>
{() => {
const color = colors[1];
switch (color) {
case 'red': return <div id="red">red</div>;
case 'yellow': return <div id="yellow">yellow</div>
case 'blue': return <div id="blue">blue</div>
}
}}
</body>
</html>

View file

@ -0,0 +1,27 @@
---
import Slotted from '../components/Slotted.astro';
---
<html>
<head>
<!-- Head Stuff -->
</head>
<body>
<Slotted>
{true && <span slot="a">A</span>}
{true ? <span slot="b">B</span> : null}
{() => <span slot="c">C</span>}
{() => {
const value = 0.33;
if (value > 0.25) {
return <span>Default</span>
} else if (value > 0.5) {
return <span>Another</span>
} else if (value > 0.75) {
return <span>Other</span>
}
return <span>Yet Another</span>
}}
</Slotted>
</body>
</html>

View file

@ -483,7 +483,7 @@ importers:
packages/astro: packages/astro:
specifiers: specifiers:
'@astrojs/compiler': ^0.17.1 '@astrojs/compiler': ^0.18.0
'@astrojs/language-server': ^0.13.4 '@astrojs/language-server': ^0.13.4
'@astrojs/markdown-remark': ^0.11.3 '@astrojs/markdown-remark': ^0.11.3
'@astrojs/prism': 0.4.1 '@astrojs/prism': 0.4.1
@ -567,7 +567,7 @@ importers:
yargs-parser: ^21.0.1 yargs-parser: ^21.0.1
zod: ^3.17.3 zod: ^3.17.3
dependencies: dependencies:
'@astrojs/compiler': 0.17.1 '@astrojs/compiler': 0.18.0
'@astrojs/language-server': 0.13.4 '@astrojs/language-server': 0.13.4
'@astrojs/markdown-remark': link:../markdown/remark '@astrojs/markdown-remark': link:../markdown/remark
'@astrojs/prism': link:../astro-prism '@astrojs/prism': link:../astro-prism
@ -2636,8 +2636,8 @@ packages:
leven: 3.1.0 leven: 3.1.0
dev: true dev: true
/@astrojs/compiler/0.17.1: /@astrojs/compiler/0.18.0:
resolution: {integrity: sha512-TawCnNbN00PXVHrps7zk/WwlcxaJQ8gVjk+tel57UQtSt3PmTsarlmq/uX165xKgn2/3Vz5inTNJxoDnr2pZBQ==} resolution: {integrity: sha512-iBX4Fm5FwAnDLJcnH6DII41lla6iLX3gSabZ884P5TuG+CxL3fEew9gZ6AhTUnpyNXuyuYb6+xWQPQdNA9KsXA==}
dev: false dev: false
/@astrojs/language-server/0.13.4: /@astrojs/language-server/0.13.4: