UNPKG

astro

Version:

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

73 lines (72 loc) 2.55 kB
import { 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"; function getFunctionExpression(slot) { if (!slot) return; const expressions = slot?.expressions?.filter((e) => isRenderInstruction(e) === false); if (expressions?.length !== 1) return; return expressions[0]; } class Slots { #result; #slots; #logger; constructor(result, slots, logger) { this.#result = result; this.#slots = slots; this.#logger = logger; if (slots) { for (const key of Object.keys(slots)) { if (this[key] !== void 0) { throw new AstroError({ ...AstroErrorData.ReservedSlotName, message: AstroErrorData.ReservedSlotName.message(key) }); } Object.defineProperty(this, key, { get() { return true; }, enumerable: true }); } } } has(name) { if (!this.#slots) return false; return Boolean(this.#slots[name]); } async render(name, args = []) { if (!this.#slots || !this.has(name)) return; const result = this.#result; if (!Array.isArray(args)) { this.#logger.warn( null, `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 (args.length > 0) { const slotValue = this.#slots[name]; const component = typeof slotValue === "function" ? await slotValue(result) : await slotValue; const expression = getFunctionExpression(component); if (expression) { const slot = async () => typeof expression === "function" ? expression(...args) : expression; return await renderSlotToString(result, slot).then((res) => { return res; }); } if (typeof component === "function") { return await renderJSX(result, component(...args)).then( (res) => res != null ? String(res) : res ); } } const content = await renderSlotToString(result, this.#slots[name]); const outHTML = chunkToString(result, content); return outHTML; } } export { Slots };