astro-ghostcms/.pnpm-store/v3/files/6b/a58547a17cc2c07f369fc1917c6...

226 lines
6.7 KiB
Plaintext

import { AstroJSX, isVNode } from "../../jsx-runtime/index.js";
import {
HTMLString,
escapeHTML,
markHTMLString,
renderToString,
spreadAttributes,
voidElementNames
} from "./index.js";
import { renderComponentToString } from "./render/component.js";
const ClientOnlyPlaceholder = "astro-client-only";
class Skip {
constructor(vnode) {
this.vnode = vnode;
this.count = 0;
}
count;
increment() {
this.count++;
}
haveNoTried() {
return this.count === 0;
}
isCompleted() {
return this.count > 2;
}
static symbol = Symbol("astro:jsx:skip");
}
let originalConsoleError;
let consoleFilterRefs = 0;
async function renderJSX(result, vnode) {
switch (true) {
case vnode instanceof HTMLString:
if (vnode.toString().trim() === "") {
return "";
}
return vnode;
case typeof vnode === "string":
return markHTMLString(escapeHTML(vnode));
case typeof vnode === "function":
return vnode;
case (!vnode && vnode !== 0):
return "";
case Array.isArray(vnode):
return markHTMLString(
(await Promise.all(vnode.map((v) => renderJSX(result, v)))).join("")
);
}
let skip;
if (vnode.props) {
if (vnode.props[Skip.symbol]) {
skip = vnode.props[Skip.symbol];
} else {
skip = new Skip(vnode);
}
} else {
skip = new Skip(vnode);
}
return renderJSXVNode(result, vnode, skip);
}
async function renderJSXVNode(result, vnode, skip) {
if (isVNode(vnode)) {
switch (true) {
case !vnode.type: {
throw new Error(`Unable to render ${result.pathname} because it contains an undefined Component!
Did you forget to import the component or is it possible there is a typo?`);
}
case vnode.type === Symbol.for("astro:fragment"):
return renderJSX(result, vnode.props.children);
case vnode.type.isAstroComponentFactory: {
let props = {};
let slots = {};
for (const [key, value] of Object.entries(vnode.props ?? {})) {
if (key === "children" || value && typeof value === "object" && value["$$slot"]) {
slots[key === "children" ? "default" : key] = () => renderJSX(result, value);
} else {
props[key] = value;
}
}
const str = await renderToString(result, vnode.type, props, slots);
if (str instanceof Response) {
throw str;
}
const html = markHTMLString(str);
return html;
}
case (!vnode.type && vnode.type !== 0):
return "";
case (typeof vnode.type === "string" && vnode.type !== ClientOnlyPlaceholder):
return markHTMLString(await renderElement(result, vnode.type, vnode.props ?? {}));
}
if (vnode.type) {
let extractSlots2 = function(child) {
if (Array.isArray(child)) {
return child.map((c) => extractSlots2(c));
}
if (!isVNode(child)) {
_slots.default.push(child);
return;
}
if ("slot" in child.props) {
_slots[child.props.slot] = [..._slots[child.props.slot] ?? [], child];
delete child.props.slot;
return;
}
_slots.default.push(child);
};
var extractSlots = extractSlots2;
if (typeof vnode.type === "function" && vnode.type["astro:renderer"]) {
skip.increment();
}
if (typeof vnode.type === "function" && vnode.props["server:root"]) {
const output2 = await vnode.type(vnode.props ?? {});
return await renderJSX(result, output2);
}
if (typeof vnode.type === "function") {
if (skip.haveNoTried() || skip.isCompleted()) {
useConsoleFilter();
try {
const output2 = await vnode.type(vnode.props ?? {});
let renderResult;
if (output2?.[AstroJSX]) {
renderResult = await renderJSXVNode(result, output2, skip);
return renderResult;
} else if (!output2) {
renderResult = await renderJSXVNode(result, output2, skip);
return renderResult;
}
} catch (e) {
if (skip.isCompleted()) {
throw e;
}
skip.increment();
} finally {
finishUsingConsoleFilter();
}
} else {
skip.increment();
}
}
const { children = null, ...props } = vnode.props ?? {};
const _slots = {
default: []
};
extractSlots2(children);
for (const [key, value] of Object.entries(props)) {
if (value["$$slot"]) {
_slots[key] = value;
delete props[key];
}
}
const slotPromises = [];
const slots = {};
for (const [key, value] of Object.entries(_slots)) {
slotPromises.push(
renderJSX(result, value).then((output2) => {
if (output2.toString().trim().length === 0)
return;
slots[key] = () => output2;
})
);
}
await Promise.all(slotPromises);
props[Skip.symbol] = skip;
let output;
if (vnode.type === ClientOnlyPlaceholder && vnode.props["client:only"]) {
output = await renderComponentToString(
result,
vnode.props["client:display-name"] ?? "",
null,
props,
slots
);
} else {
output = await renderComponentToString(
result,
typeof vnode.type === "function" ? vnode.type.name : vnode.type,
vnode.type,
props,
slots
);
}
return markHTMLString(output);
}
}
return markHTMLString(`${vnode}`);
}
async function renderElement(result, tag, { children, ...props }) {
return markHTMLString(
`<${tag}${spreadAttributes(props)}${markHTMLString(
(children == null || children == "") && voidElementNames.test(tag) ? `/>` : `>${children == null ? "" : await renderJSX(result, prerenderElementChildren(tag, children))}</${tag}>`
)}`
);
}
function prerenderElementChildren(tag, children) {
if (typeof children === "string" && (tag === "style" || tag === "script")) {
return markHTMLString(children);
} else {
return children;
}
}
function useConsoleFilter() {
consoleFilterRefs++;
if (!originalConsoleError) {
originalConsoleError = console.error;
try {
console.error = filteredConsoleError;
} catch (error) {
}
}
}
function finishUsingConsoleFilter() {
consoleFilterRefs--;
}
function filteredConsoleError(msg, ...rest) {
if (consoleFilterRefs > 0 && typeof msg === "string") {
const isKnownReactHookError = msg.includes("Warning: Invalid hook call.") && msg.includes("https://reactjs.org/link/invalid-hook-call");
if (isKnownReactHookError)
return;
}
originalConsoleError(msg, ...rest);
}
export {
renderJSX
};