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. 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 90% rename from packages/astro/src/core/render/result.ts rename to packages/astro/src/core/render/slots.ts index e23e87adf7c4..f6d469b2a704 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/slots.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; diff --git a/packages/astro/test/astro-slots.test.js b/packages/astro/test/astro-slots.test.js index 5653e0421ce3..5078ead05ef7 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 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"); + 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