From 61943b473eb136c3912e61c5a6c09021c00cf77f Mon Sep 17 00:00:00 2001 From: lilnasy <69170106+lilnasy@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:56:12 +0000 Subject: [PATCH 1/6] fix(rendering): remove render instructions from slot expressions --- packages/astro/src/core/render/result.ts | 6 ++++-- .../src/runtime/server/render/astro/render-template.ts | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index e23e87adf7c4..f79f647481b2 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -2,13 +2,15 @@ import type { SSRResult } from '../../@types/astro.js'; import { type ComponentSlots, renderSlotToString } from '../../runtime/server/index.js'; import { renderJSX } from '../../runtime/server/jsx.js'; import { chunkToString } from '../../runtime/server/render/index.js'; +import { isRenderInstruction } from '../../runtime/server/render/instruction.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; import type { Logger } from '../logger/core.js'; function getFunctionExpression(slot: any) { if (!slot) return; - if (slot.expressions?.length !== 1) return; - return slot.expressions[0] as (...args: any[]) => any; + const expressions = slot?.expressions.filter((e: unknown) => isRenderInstruction(e) === false); + if (expressions?.length !== 1) return + return expressions[0] as (...args: any[]) => any; } export class Slots { diff --git a/packages/astro/src/runtime/server/render/astro/render-template.ts b/packages/astro/src/runtime/server/render/astro/render-template.ts index f12344fe86f6..68df865181fb 100644 --- a/packages/astro/src/runtime/server/render/astro/render-template.ts +++ b/packages/astro/src/runtime/server/render/astro/render-template.ts @@ -11,7 +11,7 @@ const renderTemplateResultSym = Symbol.for('astro.renderTemplateResult'); export class RenderTemplateResult { public [renderTemplateResultSym] = true; private htmlParts: TemplateStringsArray; - private expressions: any[]; + public expressions: any[]; private error: Error | undefined; constructor(htmlParts: TemplateStringsArray, expressions: unknown[]) { this.htmlParts = htmlParts; From 822d97df601301e1e7db997066e21cb66fd5447c Mon Sep 17 00:00:00 2001 From: lilnasy <69170106+lilnasy@users.noreply.github.com> Date: Wed, 10 Apr 2024 19:57:01 +0000 Subject: [PATCH 2/6] result.ts -> slots.ts --- packages/astro/src/core/render/index.ts | 2 +- packages/astro/src/core/render/{result.ts => slots.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/astro/src/core/render/{result.ts => slots.ts} (100%) diff --git a/packages/astro/src/core/render/index.ts b/packages/astro/src/core/render/index.ts index 35b5ce76ec8d..db14701b0fde 100644 --- a/packages/astro/src/core/render/index.ts +++ b/packages/astro/src/core/render/index.ts @@ -3,7 +3,7 @@ import type { Pipeline } from '../base-pipeline.js'; export { Pipeline } from '../base-pipeline.js'; export { getParams, getProps } from './params-and-props.js'; export { loadRenderer } from './renderer.js'; -export { Slots } from './result.js'; +export { Slots } from './slots.js'; export interface SSROptions { /** The pipeline instance */ diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/slots.ts similarity index 100% rename from packages/astro/src/core/render/result.ts rename to packages/astro/src/core/render/slots.ts From 52b735ddd24e39630a2c7c7eb70ce5903ff322ee Mon Sep 17 00:00:00 2001 From: lilnasy <69170106+lilnasy@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:10:40 +0000 Subject: [PATCH 3/6] add test --- packages/astro/test/astro-slots.test.js | 11 +++++++++++ .../astro-slots/src/components/FunctionsToAPI.astro | 12 ++++++++++++ .../src/pages/slotted-named-functions.astro | 11 +++++++++++ 3 files changed, 34 insertions(+) create mode 100644 packages/astro/test/fixtures/astro-slots/src/components/FunctionsToAPI.astro create mode 100644 packages/astro/test/fixtures/astro-slots/src/pages/slotted-named-functions.astro diff --git a/packages/astro/test/astro-slots.test.js b/packages/astro/test/astro-slots.test.js index 5653e0421ce3..9c3be9c1b509 100644 --- a/packages/astro/test/astro-slots.test.js +++ b/packages/astro/test/astro-slots.test.js @@ -170,4 +170,15 @@ describe('Slots', () => { assert.notEqual(third.children[0].data, first.children[0].data); } }); + + it("Arguments can be passed to named slots with Astro.slots.render()", async () => { + const html = await fixture.readFile('/slotted-named-functions/index.html'); + const $ = cheerio.load(html); + const before = $("div#before"); + const [ beforeDiv ] = before.children("div") + assert.deepEqual(beforeDiv.firstChild.data, "Test Content BEFORE") + const after = $("div#after"); + const [ afterDiv ] = after.children("div"); + assert.deepEqual(afterDiv.firstChild.data, "Test Content AFTER") + }); }); diff --git a/packages/astro/test/fixtures/astro-slots/src/components/FunctionsToAPI.astro b/packages/astro/test/fixtures/astro-slots/src/components/FunctionsToAPI.astro new file mode 100644 index 000000000000..93d50689fab0 --- /dev/null +++ b/packages/astro/test/fixtures/astro-slots/src/components/FunctionsToAPI.astro @@ -0,0 +1,12 @@ +--- +const content = 'Test Content'; +const beforeConent = await Astro.slots.render("before", [{content}]) +const afterConent = await Astro.slots.render("after", [{content}]) +--- +
+ {beforeConent} +
+
+ {afterConent} +
+ diff --git a/packages/astro/test/fixtures/astro-slots/src/pages/slotted-named-functions.astro b/packages/astro/test/fixtures/astro-slots/src/pages/slotted-named-functions.astro new file mode 100644 index 000000000000..7885af69468e --- /dev/null +++ b/packages/astro/test/fixtures/astro-slots/src/pages/slotted-named-functions.astro @@ -0,0 +1,11 @@ +--- +import Field from '../components/FunctionsToAPI.astro' +--- + +
+ {({content}) =>
{content} BEFORE
} +
+
+ {({content}) =>
{content} AFTER
} +
+
\ No newline at end of file From 71cf4d17327782f4a38dcc8083de9786b70acd8c Mon Sep 17 00:00:00 2001 From: lilnasy <69170106+lilnasy@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:11:24 +0000 Subject: [PATCH 4/6] add changeset --- .changeset/calm-mails-check.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/calm-mails-check.md diff --git a/.changeset/calm-mails-check.md b/.changeset/calm-mails-check.md new file mode 100644 index 000000000000..7de709c1b0ec --- /dev/null +++ b/.changeset/calm-mails-check.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Fixes an issue where functions could not be used as named slots. From aa9e33f510822f88898816c46e158ba20a0694bd Mon Sep 17 00:00:00 2001 From: lilnasy <69170106+lilnasy@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:17:05 +0000 Subject: [PATCH 5/6] appease lint --- packages/astro/test/astro-slots.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/astro/test/astro-slots.test.js b/packages/astro/test/astro-slots.test.js index 9c3be9c1b509..5078ead05ef7 100644 --- a/packages/astro/test/astro-slots.test.js +++ b/packages/astro/test/astro-slots.test.js @@ -174,8 +174,8 @@ describe('Slots', () => { it("Arguments can be passed to named slots with Astro.slots.render()", async () => { const html = await fixture.readFile('/slotted-named-functions/index.html'); const $ = cheerio.load(html); - const before = $("div#before"); - const [ beforeDiv ] = before.children("div") + const befor = $("div#before"); + const [ beforeDiv ] = befor.children("div") assert.deepEqual(beforeDiv.firstChild.data, "Test Content BEFORE") const after = $("div#after"); const [ afterDiv ] = after.children("div"); From 40200e19a07322eed5ec37363b814cabd520f2fd Mon Sep 17 00:00:00 2001 From: lilnasy <69170106+lilnasy@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:21:05 +0000 Subject: [PATCH 6/6] slot may be an arbitrary object --- packages/astro/src/core/render/slots.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/core/render/slots.ts b/packages/astro/src/core/render/slots.ts index f79f647481b2..f6d469b2a704 100644 --- a/packages/astro/src/core/render/slots.ts +++ b/packages/astro/src/core/render/slots.ts @@ -8,7 +8,7 @@ import type { Logger } from '../logger/core.js'; function getFunctionExpression(slot: any) { if (!slot) return; - const expressions = slot?.expressions.filter((e: unknown) => isRenderInstruction(e) === false); + const expressions = slot?.expressions?.filter((e: unknown) => isRenderInstruction(e) === false); if (expressions?.length !== 1) return return expressions[0] as (...args: any[]) => any; }