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:
parent
c191098b97
commit
5afb807688
8 changed files with 89 additions and 5 deletions
5
.changeset/smooth-files-attend.md
Normal file
5
.changeset/smooth-files-attend.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix usage of slots inside expressions
|
|
@ -80,7 +80,7 @@
|
|||
"test:e2e:match": "playwright test -g"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/compiler": "^0.17.1",
|
||||
"@astrojs/compiler": "^0.18.0",
|
||||
"@astrojs/language-server": "^0.13.4",
|
||||
"@astrojs/markdown-remark": "^0.11.3",
|
||||
"@astrojs/prism": "0.4.1",
|
||||
|
|
|
@ -142,6 +142,19 @@ export async function renderSlot(_result: any, slotted: string, fallback?: any):
|
|||
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');
|
||||
|
||||
function guessRenderers(componentUrl?: string): string[] {
|
||||
|
|
|
@ -114,4 +114,13 @@ describe('Expressions', () => {
|
|||
|
||||
expect($('#single-escape').html()).to.equal('Astro & 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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -30,6 +30,16 @@ describe('Slots', () => {
|
|||
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 () => {
|
||||
const html = await fixture.readFile('/fallback/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
|
|
20
packages/astro/test/fixtures/astro-expr/src/pages/switch.astro
vendored
Normal file
20
packages/astro/test/fixtures/astro-expr/src/pages/switch.astro
vendored
Normal 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>
|
27
packages/astro/test/fixtures/astro-slots/src/pages/conditional.astro
vendored
Normal file
27
packages/astro/test/fixtures/astro-slots/src/pages/conditional.astro
vendored
Normal 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>
|
|
@ -483,7 +483,7 @@ importers:
|
|||
|
||||
packages/astro:
|
||||
specifiers:
|
||||
'@astrojs/compiler': ^0.17.1
|
||||
'@astrojs/compiler': ^0.18.0
|
||||
'@astrojs/language-server': ^0.13.4
|
||||
'@astrojs/markdown-remark': ^0.11.3
|
||||
'@astrojs/prism': 0.4.1
|
||||
|
@ -567,7 +567,7 @@ importers:
|
|||
yargs-parser: ^21.0.1
|
||||
zod: ^3.17.3
|
||||
dependencies:
|
||||
'@astrojs/compiler': 0.17.1
|
||||
'@astrojs/compiler': 0.18.0
|
||||
'@astrojs/language-server': 0.13.4
|
||||
'@astrojs/markdown-remark': link:../markdown/remark
|
||||
'@astrojs/prism': link:../astro-prism
|
||||
|
@ -2636,8 +2636,8 @@ packages:
|
|||
leven: 3.1.0
|
||||
dev: true
|
||||
|
||||
/@astrojs/compiler/0.17.1:
|
||||
resolution: {integrity: sha512-TawCnNbN00PXVHrps7zk/WwlcxaJQ8gVjk+tel57UQtSt3PmTsarlmq/uX165xKgn2/3Vz5inTNJxoDnr2pZBQ==}
|
||||
/@astrojs/compiler/0.18.0:
|
||||
resolution: {integrity: sha512-iBX4Fm5FwAnDLJcnH6DII41lla6iLX3gSabZ884P5TuG+CxL3fEew9gZ6AhTUnpyNXuyuYb6+xWQPQdNA9KsXA==}
|
||||
dev: false
|
||||
|
||||
/@astrojs/language-server/0.13.4:
|
||||
|
|
Loading…
Reference in a new issue