214 lines
6.5 KiB
Plaintext
214 lines
6.5 KiB
Plaintext
|
import { renderSlotToString } from "../../runtime/server/index.js";
|
||
|
import { renderJSX } from "../../runtime/server/jsx.js";
|
||
|
import { chunkToString } from "../../runtime/server/render/index.js";
|
||
|
import { AstroCookies } from "../cookies/index.js";
|
||
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
||
|
import {
|
||
|
computeCurrentLocale,
|
||
|
computePreferredLocale,
|
||
|
computePreferredLocaleList
|
||
|
} from "./context.js";
|
||
|
const clientAddressSymbol = Symbol.for("astro.clientAddress");
|
||
|
const responseSentSymbol = Symbol.for("astro.responseSent");
|
||
|
function getFunctionExpression(slot) {
|
||
|
if (!slot)
|
||
|
return;
|
||
|
if (slot.expressions?.length !== 1)
|
||
|
return;
|
||
|
return slot.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 != null ? String(res) : 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;
|
||
|
}
|
||
|
}
|
||
|
function createResult(args) {
|
||
|
const { params, request, resolve, locals } = args;
|
||
|
const url = new URL(request.url);
|
||
|
const headers = new Headers();
|
||
|
headers.set("Content-Type", "text/html");
|
||
|
const response = {
|
||
|
status: args.status,
|
||
|
statusText: "OK",
|
||
|
headers
|
||
|
};
|
||
|
Object.defineProperty(response, "headers", {
|
||
|
value: response.headers,
|
||
|
enumerable: true,
|
||
|
writable: false
|
||
|
});
|
||
|
let cookies = args.cookies;
|
||
|
let preferredLocale = void 0;
|
||
|
let preferredLocaleList = void 0;
|
||
|
let currentLocale = void 0;
|
||
|
const result = {
|
||
|
styles: args.styles ?? /* @__PURE__ */ new Set(),
|
||
|
scripts: args.scripts ?? /* @__PURE__ */ new Set(),
|
||
|
links: args.links ?? /* @__PURE__ */ new Set(),
|
||
|
componentMetadata: args.componentMetadata ?? /* @__PURE__ */ new Map(),
|
||
|
renderers: args.renderers,
|
||
|
clientDirectives: args.clientDirectives,
|
||
|
compressHTML: args.compressHTML,
|
||
|
partial: args.partial,
|
||
|
pathname: args.pathname,
|
||
|
cookies,
|
||
|
/** This function returns the `Astro` faux-global */
|
||
|
createAstro(astroGlobal, props, slots) {
|
||
|
const astroSlots = new Slots(result, slots, args.logger);
|
||
|
const Astro = {
|
||
|
// @ts-expect-error
|
||
|
__proto__: astroGlobal,
|
||
|
get clientAddress() {
|
||
|
if (!(clientAddressSymbol in request)) {
|
||
|
if (args.adapterName) {
|
||
|
throw new AstroError({
|
||
|
...AstroErrorData.ClientAddressNotAvailable,
|
||
|
message: AstroErrorData.ClientAddressNotAvailable.message(args.adapterName)
|
||
|
});
|
||
|
} else {
|
||
|
throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
|
||
|
}
|
||
|
}
|
||
|
return Reflect.get(request, clientAddressSymbol);
|
||
|
},
|
||
|
get cookies() {
|
||
|
if (cookies) {
|
||
|
return cookies;
|
||
|
}
|
||
|
cookies = new AstroCookies(request);
|
||
|
result.cookies = cookies;
|
||
|
return cookies;
|
||
|
},
|
||
|
get preferredLocale() {
|
||
|
if (preferredLocale) {
|
||
|
return preferredLocale;
|
||
|
}
|
||
|
if (args.locales) {
|
||
|
preferredLocale = computePreferredLocale(request, args.locales);
|
||
|
return preferredLocale;
|
||
|
}
|
||
|
return void 0;
|
||
|
},
|
||
|
get preferredLocaleList() {
|
||
|
if (preferredLocaleList) {
|
||
|
return preferredLocaleList;
|
||
|
}
|
||
|
if (args.locales) {
|
||
|
preferredLocaleList = computePreferredLocaleList(request, args.locales);
|
||
|
return preferredLocaleList;
|
||
|
}
|
||
|
return void 0;
|
||
|
},
|
||
|
get currentLocale() {
|
||
|
if (currentLocale) {
|
||
|
return currentLocale;
|
||
|
}
|
||
|
if (args.locales) {
|
||
|
currentLocale = computeCurrentLocale(
|
||
|
request,
|
||
|
args.locales,
|
||
|
args.routingStrategy,
|
||
|
args.defaultLocale
|
||
|
);
|
||
|
if (currentLocale) {
|
||
|
return currentLocale;
|
||
|
}
|
||
|
}
|
||
|
return void 0;
|
||
|
},
|
||
|
params,
|
||
|
props,
|
||
|
locals,
|
||
|
request,
|
||
|
url,
|
||
|
redirect(path, status) {
|
||
|
if (request[responseSentSymbol]) {
|
||
|
throw new AstroError({
|
||
|
...AstroErrorData.ResponseSentError
|
||
|
});
|
||
|
}
|
||
|
return new Response(null, {
|
||
|
status: status || 302,
|
||
|
headers: {
|
||
|
Location: path
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
response,
|
||
|
slots: astroSlots
|
||
|
};
|
||
|
return Astro;
|
||
|
},
|
||
|
resolve,
|
||
|
response,
|
||
|
_metadata: {
|
||
|
hasHydrationScript: false,
|
||
|
rendererSpecificHydrationScripts: /* @__PURE__ */ new Set(),
|
||
|
hasRenderedHead: false,
|
||
|
hasDirectives: /* @__PURE__ */ new Set(),
|
||
|
headInTree: false,
|
||
|
extraHead: [],
|
||
|
propagators: /* @__PURE__ */ new Set()
|
||
|
}
|
||
|
};
|
||
|
return result;
|
||
|
}
|
||
|
export {
|
||
|
createResult
|
||
|
};
|