diff --git a/.changeset/unlucky-otters-end.md b/.changeset/unlucky-otters-end.md new file mode 100644 index 000000000000..8ad26bc694eb --- /dev/null +++ b/.changeset/unlucky-otters-end.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Added an error message when the second argument of Astro.slots.render is not an array diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 58fd77980698..19aa85695a9b 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -203,7 +203,7 @@ export interface AstroGlobal extends AstroGlobalPartial { */ has(slotName: string): boolean; /** - * Asychronously renders this slot and returns HTML + * Asynchronously renders this slot and returns a string * * Example usage: * ```astro @@ -216,6 +216,21 @@ export interface AstroGlobal extends AstroGlobalPartial { * * ``` * + * A second parameters can be used to pass arguments to a slotted callback + * + * Example usage: + * ```astro + * --- + * html = await Astro.slots.render('default', ["Hello", "World"]) + * --- + * ``` + * Each item in the array will be passed as an argument that you can use like so: + * ```astro + * + * {(hello, world) =>
{hello}, {world}!
} + *
+ * ``` + * * [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroslots) */ render(slotName: string, args?: any[]): Promise; diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 32dcdd91602a..dc5be4a079a5 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -55,10 +55,13 @@ class Slots { #cache = new Map(); #result: SSRResult; #slots: Record | null; + #loggingOpts: LogOptions; - constructor(result: SSRResult, slots: Record | null) { + constructor(result: SSRResult, slots: Record | null, logging: LogOptions) { this.#result = result; this.#slots = slots; + this.#loggingOpts = logging; + if (slots) { for (const key of Object.keys(slots)) { if ((this as any)[key] !== undefined) { @@ -92,11 +95,20 @@ class Slots { if (!cacheable) { const component = await this.#slots[name](); const expression = getFunctionExpression(component); - if (expression) { - const slot = expression(...args); - return await renderSlot(this.#result, slot).then((res) => - res != null ? String(res) : res + + if (!Array.isArray(args)) { + warn( + this.#loggingOpts, + 'Astro.slots.render', + `Expected second parameter to be an array, received a ${typeof args}. If you're trying to pass an array as a single argument and getting unexpected results, make sure you're passing your array as a item of an array. Ex: Astro.slots.render('default', [["Hello", "World"]])` ); + } else { + if (expression) { + const slot = expression(...args); + return await renderSlot(this.#result, slot).then((res) => + res != null ? String(res) : res + ); + } } } const content = await renderSlot(this.#result, this.#slots[name]).then((res) => @@ -146,7 +158,7 @@ export function createResult(args: CreateResultArgs): SSRResult { props: Record, slots: Record | null ) { - const astroSlots = new Slots(result, slots); + const astroSlots = new Slots(result, slots, args.logging); const Astro = { __proto__: astroGlobal,