mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
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 <natemoo-re@users.noreply.github.com> Co-authored-by: Nate Moore <nate@astro.build>
This commit is contained in:
parent
07f13e6650
commit
8ce40a417c
9 changed files with 78 additions and 9 deletions
5
.changeset/red-carrots-fail.md
Normal file
5
.changeset/red-carrots-fail.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Adds support for dynamic slot names
|
|
@ -25,7 +25,7 @@ test.describe('Error display', () => {
|
||||||
await page.goto(astro.resolveUrl('/astro-syntax-error'), { waitUntil: 'networkidle' });
|
await page.goto(astro.resolveUrl('/astro-syntax-error'), { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
const message = (await getErrorOverlayContent(page)).message;
|
const message = (await getErrorOverlayContent(page)).message;
|
||||||
expect(message).toMatch('Unexpected "}"');
|
expect(message).toMatch('Unexpected "while"');
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// Wait for page reload
|
// Wait for page reload
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<h1>{// comment
|
<h1>{while (true){}}</h1>
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
"test:e2e:match": "playwright test -g"
|
"test:e2e:match": "playwright test -g"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/compiler": "^2.3.4",
|
"@astrojs/compiler": "^2.5.0",
|
||||||
"@astrojs/internal-helpers": "workspace:*",
|
"@astrojs/internal-helpers": "workspace:*",
|
||||||
"@astrojs/markdown-remark": "workspace:*",
|
"@astrojs/markdown-remark": "workspace:*",
|
||||||
"@astrojs/telemetry": "workspace:*",
|
"@astrojs/telemetry": "workspace:*",
|
||||||
|
|
|
@ -45,8 +45,11 @@ import { addAttribute, Renderer } from './render/index.js';
|
||||||
|
|
||||||
export function mergeSlots(...slotted: unknown[]) {
|
export function mergeSlots(...slotted: unknown[]) {
|
||||||
const slots: Record<string, () => any> = {};
|
const slots: Record<string, () => any> = {};
|
||||||
for (const slot of slotted) {
|
for (let slot of slotted) {
|
||||||
if (!slot) continue;
|
if (!slot) continue;
|
||||||
|
if (Array.isArray(slot)) {
|
||||||
|
slot = mergeSlots(...slot);
|
||||||
|
}
|
||||||
if (typeof slot === 'object') {
|
if (typeof slot === 'object') {
|
||||||
Object.assign(slots, slot);
|
Object.assign(slots, slot);
|
||||||
} else if (typeof slot === 'function') {
|
} else if (typeof slot === 'function') {
|
||||||
|
|
|
@ -30,6 +30,26 @@ describe('Slots', () => {
|
||||||
expect($('#default').text().trim()).to.equal('Default');
|
expect($('#default').text().trim()).to.equal('Default');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Dynamic named slots work with map work', async () => {
|
||||||
|
const html = await fixture.readFile('/dynamic-map/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('Dynamic named slots work with for loop', async () => {
|
||||||
|
const html = await fixture.readFile('/dynamic-for/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('Conditional named slots work', async () => {
|
it('Conditional named slots work', async () => {
|
||||||
const html = await fixture.readFile('/conditional/index.html');
|
const html = await fixture.readFile('/conditional/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
24
packages/astro/test/fixtures/astro-slots/src/pages/dynamic-for.astro
vendored
Normal file
24
packages/astro/test/fixtures/astro-slots/src/pages/dynamic-for.astro
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
import Slotted from '../components/Slotted.astro';
|
||||||
|
|
||||||
|
const slotNames = ['a', 'b', 'c']
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Head Stuff -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Slotted>
|
||||||
|
{()=>{
|
||||||
|
const slots:any[] = [];
|
||||||
|
for (const slotName of slotNames) {
|
||||||
|
slots.push(<span slot={slotName}>{slotName.toUpperCase()}</span>);
|
||||||
|
}
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<span>Default</span>
|
||||||
|
</Slotted>
|
||||||
|
</body>
|
||||||
|
</html>
|
17
packages/astro/test/fixtures/astro-slots/src/pages/dynamic-map.astro
vendored
Normal file
17
packages/astro/test/fixtures/astro-slots/src/pages/dynamic-map.astro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
import Slotted from '../components/Slotted.astro';
|
||||||
|
|
||||||
|
const slots = ['a', 'b', 'c']
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Head Stuff -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Slotted>
|
||||||
|
{slots.map((slotName)=><span slot={slotName}>{slotName.toUpperCase()}</span>)}
|
||||||
|
<span>Default</span>
|
||||||
|
</Slotted>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -489,8 +489,8 @@ importers:
|
||||||
packages/astro:
|
packages/astro:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/compiler':
|
'@astrojs/compiler':
|
||||||
specifier: ^2.3.4
|
specifier: ^2.5.0
|
||||||
version: 2.3.4
|
version: 2.5.0
|
||||||
'@astrojs/internal-helpers':
|
'@astrojs/internal-helpers':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../internal-helpers
|
version: link:../internal-helpers
|
||||||
|
@ -5308,8 +5308,8 @@ packages:
|
||||||
resolution: {integrity: sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==}
|
resolution: {integrity: sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@astrojs/compiler@2.3.4:
|
/@astrojs/compiler@2.5.0:
|
||||||
resolution: {integrity: sha512-33/YtWoBCE0cBUNy1kh78FCDXBoBANX87ShgATlAHECYbG2+buNTAgq4Xgz4t5NgnEHPN21GIBC2Mvvwisoutw==}
|
resolution: {integrity: sha512-ZDluNgMIJT+z+HJcZ6QEJ/KqaFkTkrb+Za6c6VZs8G/nb1LBErL14/iU5EVJ9yu25i4QCLweuBJ3m5df34gZJg==}
|
||||||
|
|
||||||
/@astrojs/language-server@2.5.5(prettier-plugin-astro@0.12.3)(prettier@3.1.1)(typescript@5.2.2):
|
/@astrojs/language-server@2.5.5(prettier-plugin-astro@0.12.3)(prettier@3.1.1)(typescript@5.2.2):
|
||||||
resolution: {integrity: sha512-hk7a8S7bpf//BOA6mMjiYqi/eiYtGPfUfw59eVXdutdRFdwDHtu4jcsLu43ZaId56pAcE8qFjIvJxySvzcxiUA==}
|
resolution: {integrity: sha512-hk7a8S7bpf//BOA6mMjiYqi/eiYtGPfUfw59eVXdutdRFdwDHtu4jcsLu43ZaId56pAcE8qFjIvJxySvzcxiUA==}
|
||||||
|
@ -5323,7 +5323,7 @@ packages:
|
||||||
prettier-plugin-astro:
|
prettier-plugin-astro:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/compiler': 2.3.4
|
'@astrojs/compiler': 2.5.0
|
||||||
'@jridgewell/sourcemap-codec': 1.4.15
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
'@volar/kit': 1.10.10(typescript@5.2.2)
|
'@volar/kit': 1.10.10(typescript@5.2.2)
|
||||||
'@volar/language-core': 1.10.10
|
'@volar/language-core': 1.10.10
|
||||||
|
|
Loading…
Reference in a new issue