kjelsrud.dev/node_modules/astro/dist/runtime/server/render/page.js
2023-07-19 21:31:30 +02:00

168 lines
5.6 KiB
JavaScript

import { AstroError, AstroErrorData } from "../../../core/errors/index.js";
import { isHTMLString } from "../escape.js";
import { createResponse } from "../response.js";
import {
isAstroComponentFactory,
isAstroComponentInstance,
isHeadAndContent,
isRenderTemplateResult,
renderAstroTemplateResult
} from "./astro/index.js";
import { chunkToByteArray, encoder, HTMLParts } from "./common.js";
import { renderComponent } from "./component.js";
import { maybeRenderHead } from "./head.js";
const needsHeadRenderingSymbol = Symbol.for("astro.needsHeadRendering");
function nonAstroPageNeedsHeadInjection(pageComponent) {
return needsHeadRenderingSymbol in pageComponent && !!pageComponent[needsHeadRenderingSymbol];
}
async function iterableToHTMLBytes(result, iterable, onDocTypeInjection) {
const parts = new HTMLParts();
let i = 0;
for await (const chunk of iterable) {
if (isHTMLString(chunk)) {
if (i === 0) {
i++;
if (!/<!doctype html/i.test(String(chunk))) {
parts.append(`${result.compressHTML ? "<!DOCTYPE html>" : "<!DOCTYPE html>\n"}`, result);
if (onDocTypeInjection) {
await onDocTypeInjection(parts);
}
}
}
}
parts.append(chunk, result);
}
return parts.toArrayBuffer();
}
async function bufferHeadContent(result) {
const iterator = result._metadata.propagators.values();
while (true) {
const { value, done } = iterator.next();
if (done) {
break;
}
const returnValue = await value.init(result);
if (isHeadAndContent(returnValue)) {
result._metadata.extraHead.push(returnValue.head);
}
}
}
async function renderPage(result, componentFactory, props, children, streaming, route) {
var _a, _b;
if (!isAstroComponentFactory(componentFactory)) {
result._metadata.headInTree = ((_a = result.componentMetadata.get(componentFactory.moduleId)) == null ? void 0 : _a.containsHead) ?? false;
const pageProps = { ...props ?? {}, "server:root": true };
let output;
let head = "";
try {
if (nonAstroPageNeedsHeadInjection(componentFactory)) {
const parts = new HTMLParts();
for await (const chunk of maybeRenderHead()) {
parts.append(chunk, result);
}
head = parts.toString();
}
const renderResult = await renderComponent(
result,
componentFactory.name,
componentFactory,
pageProps,
null
);
if (isAstroComponentInstance(renderResult)) {
output = renderResult.render();
} else {
output = renderResult;
}
} catch (e) {
if (AstroError.is(e) && !e.loc) {
e.setLocation({
file: route == null ? void 0 : route.component
});
}
throw e;
}
const bytes = await iterableToHTMLBytes(result, output, async (parts) => {
parts.append(head, result);
});
return new Response(bytes, {
headers: new Headers([
["Content-Type", "text/html; charset=utf-8"],
["Content-Length", bytes.byteLength.toString()]
])
});
}
result._metadata.headInTree = ((_b = result.componentMetadata.get(componentFactory.moduleId)) == null ? void 0 : _b.containsHead) ?? false;
const factoryReturnValue = await componentFactory(result, props, children);
const factoryIsHeadAndContent = isHeadAndContent(factoryReturnValue);
if (isRenderTemplateResult(factoryReturnValue) || factoryIsHeadAndContent) {
await bufferHeadContent(result);
const templateResult = factoryIsHeadAndContent ? factoryReturnValue.content : factoryReturnValue;
let iterable = renderAstroTemplateResult(templateResult);
let init = result.response;
let headers = new Headers(init.headers);
let body;
if (streaming) {
body = new ReadableStream({
start(controller) {
async function read() {
let i = 0;
try {
for await (const chunk of iterable) {
if (isHTMLString(chunk)) {
if (i === 0) {
if (!/<!doctype html/i.test(String(chunk))) {
controller.enqueue(
encoder.encode(
`${result.compressHTML ? "<!DOCTYPE html>" : "<!DOCTYPE html>\n"}`
)
);
}
}
}
if (chunk instanceof Response) {
throw new AstroError({
...AstroErrorData.ResponseSentError
});
}
const bytes = chunkToByteArray(result, chunk);
controller.enqueue(bytes);
i++;
}
controller.close();
} catch (e) {
if (AstroError.is(e) && !e.loc) {
e.setLocation({
file: route == null ? void 0 : route.component
});
}
controller.error(e);
}
}
read();
}
});
} else {
body = await iterableToHTMLBytes(result, iterable);
headers.set("Content-Length", body.byteLength.toString());
}
let response = createResponse(body, { ...init, headers });
return response;
}
if (!(factoryReturnValue instanceof Response)) {
throw new AstroError({
...AstroErrorData.OnlyResponseCanBeReturned,
message: AstroErrorData.OnlyResponseCanBeReturned.message(
route == null ? void 0 : route.route,
typeof factoryReturnValue
),
location: {
file: route == null ? void 0 : route.component
}
});
}
return factoryReturnValue;
}
export {
renderPage
};