Refactor Server Paradigm.
This commit is contained in:
+1
-1
@@ -1,2 +1,2 @@
|
||||
import type { LivePageDistGenParams } from "../../../types";
|
||||
export default function genWebHTML({ component, pageProps, bundledMap, head: Head, module, meta, routeParams, debug, }: LivePageDistGenParams): Promise<string>;
|
||||
export default function genWebHTML({ component, pageProps, bundledMap, module, routeParams, debug, root_module, }: LivePageDistGenParams): Promise<string>;
|
||||
|
||||
+58
-46
@@ -1,4 +1,4 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { renderToString } from "react-dom/server";
|
||||
import grabContants from "../../../utils/grab-constants";
|
||||
import EJSON from "../../../utils/ejson";
|
||||
@@ -14,56 +14,68 @@ try {
|
||||
_reactVersion = JSON.parse(readFileSync(path.join(process.cwd(), "node_modules/react/package.json"), "utf-8")).version;
|
||||
}
|
||||
catch { }
|
||||
export default async function genWebHTML({ component, pageProps, bundledMap, head: Head, module, meta, routeParams, debug, }) {
|
||||
export default async function genWebHTML({ component, pageProps, bundledMap, module, routeParams, debug, root_module, }) {
|
||||
const { ClientRootElementIDName, ClientWindowPagePropsName } = grabContants();
|
||||
const is_dev = isDevelopment();
|
||||
if (debug) {
|
||||
log.info("component", component);
|
||||
}
|
||||
const componentHTML = renderToString(component);
|
||||
if (debug) {
|
||||
log.info("componentHTML", componentHTML);
|
||||
}
|
||||
const headHTML = Head
|
||||
? renderToString(_jsx(Head, { serverRes: pageProps, ctx: routeParams }))
|
||||
: "";
|
||||
let html = `<!DOCTYPE html>\n`;
|
||||
html += `<html>\n`;
|
||||
html += ` <head>\n`;
|
||||
html += ` <meta charset="utf-8" />\n`;
|
||||
html += ` <meta name="viewport" content="width=device-width, initial-scale=1.0">\n`;
|
||||
if (meta) {
|
||||
html += ` ${grabWebMetaHTML({ meta })}\n`;
|
||||
}
|
||||
if (bundledMap?.css_path) {
|
||||
html += ` <link rel="stylesheet" href="/${bundledMap.css_path}" />\n`;
|
||||
}
|
||||
const serializedProps = (EJSON.stringify(pageProps || {}) || "{}").replace(/<\//g, "<\\/");
|
||||
html += ` <script>window.${ClientWindowPagePropsName} = ${serializedProps}</script>\n`;
|
||||
if (bundledMap?.path) {
|
||||
const dev = isDevelopment();
|
||||
const devSuffix = dev ? "?dev" : "";
|
||||
const importMap = JSON.stringify({
|
||||
imports: {
|
||||
react: `https://esm.sh/react@${_reactVersion}${devSuffix}`,
|
||||
"react-dom": `https://esm.sh/react-dom@${_reactVersion}${devSuffix}`,
|
||||
"react-dom/client": `https://esm.sh/react-dom@${_reactVersion}/client${devSuffix}`,
|
||||
"react/jsx-runtime": `https://esm.sh/react@${_reactVersion}/jsx-runtime${devSuffix}`,
|
||||
"react/jsx-dev-runtime": `https://esm.sh/react@${_reactVersion}/jsx-dev-runtime${devSuffix}`,
|
||||
},
|
||||
});
|
||||
html += ` <script type="importmap">${importMap}</script>\n`;
|
||||
html += ` <script src="/${bundledMap.path}" type="module" id="${AppData["BunextClientHydrationScriptID"]}" async></script>\n`;
|
||||
const page_hydration_script = await grabWebPageHydrationScript();
|
||||
const root_meta = root_module?.meta
|
||||
? typeof root_module.meta == "function" && routeParams
|
||||
? await root_module.meta({ ctx: routeParams, serverRes: pageProps })
|
||||
: typeof root_module.meta == "function"
|
||||
? undefined
|
||||
: root_module.meta
|
||||
: undefined;
|
||||
const page_meta = module?.meta
|
||||
? typeof module.meta == "function" && routeParams
|
||||
? await module.meta({ ctx: routeParams, serverRes: pageProps })
|
||||
: typeof module.meta == "function"
|
||||
? undefined
|
||||
: module.meta
|
||||
: undefined;
|
||||
const html_props = {
|
||||
...module?.html_props,
|
||||
...root_module?.html_props,
|
||||
};
|
||||
const Head = module?.Head;
|
||||
const RootHead = root_module?.Head;
|
||||
const dev = isDevelopment();
|
||||
const devSuffix = dev ? "?dev" : "";
|
||||
const browser_imports = {
|
||||
react: `https://esm.sh/react@${_reactVersion}`,
|
||||
"react-dom": `https://esm.sh/react-dom@${_reactVersion}`,
|
||||
"react-dom/client": `https://esm.sh/react-dom@${_reactVersion}/client`,
|
||||
"react/jsx-runtime": `https://esm.sh/react@${_reactVersion}/jsx-runtime`,
|
||||
};
|
||||
if (dev) {
|
||||
browser_imports["react/jsx-dev-runtime"] =
|
||||
`https://esm.sh/react@${_reactVersion}/jsx-dev-runtime`;
|
||||
}
|
||||
if (isDevelopment()) {
|
||||
html += `<script defer>\n${await grabWebPageHydrationScript()}\n</script>\n`;
|
||||
}
|
||||
if (headHTML) {
|
||||
html += ` ${headHTML}\n`;
|
||||
}
|
||||
html += ` </head>\n`;
|
||||
html += ` <body>\n`;
|
||||
html += ` <div id="${ClientRootElementIDName}">${componentHTML}</div>\n`;
|
||||
html += ` </body>\n`;
|
||||
html += `</html>\n`;
|
||||
const importMap = JSON.stringify({
|
||||
imports: browser_imports,
|
||||
});
|
||||
let final_component = (_jsxs("html", { ...html_props, children: [_jsxs("head", { children: [_jsx("meta", { charSet: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }), root_meta ? grabWebMetaHTML({ meta: root_meta }) : null, page_meta ? grabWebMetaHTML({ meta: page_meta }) : null, bundledMap?.css_path ? (_jsx("link", { rel: "stylesheet", href: `/${bundledMap.css_path}` })) : null, _jsx("script", { dangerouslySetInnerHTML: {
|
||||
__html: `window.${ClientWindowPagePropsName} = ${serializedProps}`,
|
||||
} }), bundledMap?.path ? (_jsxs(_Fragment, { children: [_jsx("script", { type: "importmap", dangerouslySetInnerHTML: {
|
||||
__html: importMap,
|
||||
}, fetchPriority: "high" }), _jsx("script", { src: `/${bundledMap.path}`, type: "module", id: AppData["BunextClientHydrationScriptID"], defer: true })] })) : null, is_dev ? (_jsx("script", { defer: true, dangerouslySetInnerHTML: {
|
||||
__html: page_hydration_script,
|
||||
} })) : null, RootHead ? (_jsx(RootHead, { serverRes: pageProps, ctx: routeParams })) : null, Head ? _jsx(Head, { serverRes: pageProps, ctx: routeParams }) : null] }), _jsx("body", { children: _jsx("div", { id: ClientRootElementIDName, suppressHydrationWarning: !dev, children: component }) })] }));
|
||||
let html = `<!DOCTYPE html>\n`;
|
||||
// const stream = await renderToReadableStream(final_component, {
|
||||
// onError(error: any) {
|
||||
// // This is where you "omit" or handle the errors
|
||||
// // You can log it silently or ignore it
|
||||
// if (error.message.includes('unique "key" prop')) return;
|
||||
// console.error(error);
|
||||
// },
|
||||
// });
|
||||
// // 2. Convert the Web Stream to a String (Bun-optimized)
|
||||
// const htmlBody = await new Response(stream).text();
|
||||
// html += htmlBody;
|
||||
html += renderToString(final_component);
|
||||
return html;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
import type { GrabPageComponentRes } from "../../../types";
|
||||
export default function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, head, meta, routeParams, serverRes, debug, }: GrabPageComponentRes): Promise<Response>;
|
||||
export default function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, routeParams, serverRes, debug, root_module, }: GrabPageComponentRes): Promise<Response>;
|
||||
|
||||
+6
-5
@@ -1,17 +1,17 @@
|
||||
import _ from "lodash";
|
||||
import isDevelopment from "../../../utils/is-development";
|
||||
import { log } from "../../../utils/log";
|
||||
import writeCache from "../../cache/write-cache";
|
||||
import genWebHTML from "./generate-web-html";
|
||||
export default async function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, head, meta, routeParams, serverRes, debug, }) {
|
||||
export default async function generateWebPageResponseFromComponentReturn({ component, module, bundledMap, routeParams, serverRes, debug, root_module, }) {
|
||||
const html = await genWebHTML({
|
||||
component,
|
||||
pageProps: serverRes,
|
||||
bundledMap,
|
||||
module,
|
||||
meta,
|
||||
head,
|
||||
routeParams,
|
||||
debug,
|
||||
root_module,
|
||||
});
|
||||
if (debug) {
|
||||
log.info("html", html);
|
||||
@@ -36,8 +36,9 @@ export default async function generateWebPageResponseFromComponentReturn({ compo
|
||||
Expires: "0",
|
||||
};
|
||||
}
|
||||
const cache_page = module.config?.cachePage || serverRes?.cachePage || false;
|
||||
const expiry_seconds = module.config?.cacheExpiry || serverRes?.cacheExpiry;
|
||||
const config = _.merge(root_module?.config, module.config);
|
||||
const cache_page = config?.cachePage || serverRes?.cachePage || false;
|
||||
const expiry_seconds = config?.cacheExpiry || serverRes?.cacheExpiry;
|
||||
if (cache_page && routeParams?.url) {
|
||||
const key = routeParams.url.pathname + (routeParams.url.search || "");
|
||||
writeCache({
|
||||
|
||||
+40
-58
@@ -4,6 +4,8 @@ import grabPageBundledReactComponent from "./grab-page-bundled-react-component";
|
||||
import _ from "lodash";
|
||||
import { log } from "../../../utils/log";
|
||||
import grabRootFilePath from "./grab-root-file-path";
|
||||
import grabPageServerRes from "./grab-page-server-res";
|
||||
import grabPageServerPath from "./grab-page-server-path";
|
||||
class NotFoundError extends Error {
|
||||
}
|
||||
export default async function grabPageComponent({ req, file_path: passed_file_path, debug, }) {
|
||||
@@ -35,6 +37,7 @@ export default async function grabPageComponent({ req, file_path: passed_file_pa
|
||||
}
|
||||
const bundledMap = global.BUNDLER_CTX_MAP?.[file_path];
|
||||
if (!bundledMap?.path) {
|
||||
console.log(global.BUNDLER_CTX_MAP);
|
||||
const errMsg = `No Bundled File Path for this request path!`;
|
||||
log.error(errMsg);
|
||||
throw new Error(errMsg);
|
||||
@@ -43,72 +46,52 @@ export default async function grabPageComponent({ req, file_path: passed_file_pa
|
||||
log.info(`bundledMap:`, bundledMap);
|
||||
}
|
||||
const { root_file_path } = grabRootFilePath();
|
||||
const root_module = root_file_path
|
||||
? await import(`${root_file_path}?t=${now}`)
|
||||
: undefined;
|
||||
const { server_file_path: root_server_file_path } = root_file_path
|
||||
? grabPageServerPath({ file_path: root_file_path })
|
||||
: {};
|
||||
const root_server_module = root_server_file_path
|
||||
? await import(`${root_server_file_path}?t=${now}`)
|
||||
: undefined;
|
||||
const root_server_fn = root_server_module?.default || root_server_module?.server;
|
||||
const rootServerRes = root_server_fn
|
||||
? await grabPageServerRes({
|
||||
server_function: root_server_fn,
|
||||
url,
|
||||
query: match?.query,
|
||||
routeParams,
|
||||
})
|
||||
: undefined;
|
||||
if (debug) {
|
||||
log.info(`rootServerRes:`, rootServerRes);
|
||||
}
|
||||
const module = await import(`${file_path}?t=${now}`);
|
||||
const { server_file_path } = grabPageServerPath({ file_path });
|
||||
const server_module = server_file_path
|
||||
? await import(`${server_file_path}?t=${now}`)
|
||||
: undefined;
|
||||
if (debug) {
|
||||
log.info(`module:`, module);
|
||||
}
|
||||
const serverRes = await (async () => {
|
||||
const default_props = {
|
||||
url: {
|
||||
..._.pick(url, [
|
||||
"host",
|
||||
"hostname",
|
||||
"pathname",
|
||||
"origin",
|
||||
"port",
|
||||
"search",
|
||||
"searchParams",
|
||||
"hash",
|
||||
"href",
|
||||
"password",
|
||||
"protocol",
|
||||
"username",
|
||||
]),
|
||||
},
|
||||
const server_fn = server_module?.default || server_module?.server;
|
||||
const serverRes = server_fn
|
||||
? await grabPageServerRes({
|
||||
server_function: server_fn,
|
||||
url,
|
||||
query: match?.query,
|
||||
};
|
||||
try {
|
||||
if (routeParams) {
|
||||
const serverData = await module["server"]?.({
|
||||
...routeParams,
|
||||
query: { ...routeParams.query, ...match?.query },
|
||||
});
|
||||
return {
|
||||
...serverData,
|
||||
...default_props,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...default_props,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
...default_props,
|
||||
};
|
||||
}
|
||||
})();
|
||||
routeParams,
|
||||
})
|
||||
: undefined;
|
||||
if (debug) {
|
||||
log.info(`serverRes:`, serverRes);
|
||||
}
|
||||
const meta = module.meta
|
||||
? typeof module.meta == "function" && routeParams
|
||||
? await module.meta({
|
||||
ctx: routeParams,
|
||||
serverRes,
|
||||
})
|
||||
: typeof module.meta == "object"
|
||||
? module.meta
|
||||
: undefined
|
||||
: undefined;
|
||||
if (debug) {
|
||||
log.info(`meta:`, meta);
|
||||
}
|
||||
const Head = module.Head;
|
||||
const mergedServerRes = _.merge(rootServerRes || {}, serverRes || {});
|
||||
const { component } = (await grabPageBundledReactComponent({
|
||||
file_path,
|
||||
root_file_path,
|
||||
server_res: serverRes,
|
||||
server_res: mergedServerRes,
|
||||
})) || {};
|
||||
if (!component) {
|
||||
throw new Error(`Couldn't grab page component`);
|
||||
@@ -118,12 +101,11 @@ export default async function grabPageComponent({ req, file_path: passed_file_pa
|
||||
}
|
||||
return {
|
||||
component,
|
||||
serverRes,
|
||||
serverRes: mergedServerRes,
|
||||
routeParams,
|
||||
module,
|
||||
bundledMap,
|
||||
meta,
|
||||
head: Head,
|
||||
root_module,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
|
||||
@@ -2,21 +2,29 @@ import EJSON from "../../../utils/ejson";
|
||||
import pagePathTransform from "../../../utils/page-path-transform";
|
||||
export default function grabPageReactComponentString({ file_path, root_file_path, server_res, }) {
|
||||
try {
|
||||
const target_path = pagePathTransform({ page_path: file_path });
|
||||
// const target_path = pagePathTransform({ page_path: file_path });
|
||||
// const target_root_path = root_file_path
|
||||
// ? pagePathTransform({ page_path: root_file_path })
|
||||
// : undefined;
|
||||
let tsx = ``;
|
||||
const server_res_json = JSON.stringify(EJSON.stringify(server_res || {}) ?? "{}");
|
||||
// Import Root from its original source path so that all sub-components
|
||||
// that import __root (e.g. AppContext) resolve to the same module instance.
|
||||
// Using the rewritten .bunext/pages/__root would create a separate
|
||||
// createContext() call, breaking context for any sub-component that
|
||||
// imports AppContext via a relative path to the source __root.
|
||||
if (root_file_path) {
|
||||
tsx += `import Root from "${root_file_path}"\n`;
|
||||
}
|
||||
tsx += `import Page from "${target_path}"\n`;
|
||||
tsx += `import Page from "${file_path}"\n`;
|
||||
tsx += `export default function Main() {\n\n`;
|
||||
tsx += `const props = JSON.parse(${server_res_json})\n\n`;
|
||||
tsx += ` return (\n`;
|
||||
if (root_file_path) {
|
||||
tsx += ` <Root suppressHydrationWarning={true} {...props}><Page {...props} /></Root>\n`;
|
||||
tsx += ` <Root {...props}><Page {...props} /></Root>\n`;
|
||||
}
|
||||
else {
|
||||
tsx += ` <Page suppressHydrationWarning={true} {...props} />\n`;
|
||||
tsx += ` <Page {...props} />\n`;
|
||||
}
|
||||
tsx += ` )\n`;
|
||||
tsx += `}\n`;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
type Params = {
|
||||
file_path: string;
|
||||
};
|
||||
export default function grabPageServerPath({ file_path }: Params): {
|
||||
server_file_path: string | undefined;
|
||||
};
|
||||
export {};
|
||||
@@ -0,0 +1,11 @@
|
||||
import { existsSync } from "fs";
|
||||
export default function grabPageServerPath({ file_path }) {
|
||||
const page_server_ts_file = file_path.replace(/\.tsx?$/, ".server.ts");
|
||||
const page_server_tsx_file = file_path.replace(/\.tsx?$/, ".server.tsx");
|
||||
const server_file_path = existsSync(page_server_ts_file)
|
||||
? page_server_ts_file
|
||||
: existsSync(page_server_tsx_file)
|
||||
? page_server_tsx_file
|
||||
: undefined;
|
||||
return { server_file_path };
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { BunextPageModuleServerReturn, BunextPageServerFn, BunxRouteParams } from "../../../types";
|
||||
type Params = {
|
||||
url?: URL;
|
||||
server_function: BunextPageServerFn;
|
||||
query?: Record<string, string>;
|
||||
routeParams?: BunxRouteParams;
|
||||
};
|
||||
export default function grabPageServerRes({ url, query, routeParams, server_function, }: Params): Promise<BunextPageModuleServerReturn>;
|
||||
export {};
|
||||
@@ -0,0 +1,44 @@
|
||||
import _ from "lodash";
|
||||
export default async function grabPageServerRes({ url, query, routeParams, server_function, }) {
|
||||
const default_props = {
|
||||
url: url
|
||||
? {
|
||||
..._.pick(url, [
|
||||
"host",
|
||||
"hostname",
|
||||
"pathname",
|
||||
"origin",
|
||||
"port",
|
||||
"search",
|
||||
"searchParams",
|
||||
"hash",
|
||||
"href",
|
||||
"password",
|
||||
"protocol",
|
||||
"username",
|
||||
]),
|
||||
}
|
||||
: null,
|
||||
query,
|
||||
};
|
||||
try {
|
||||
if (routeParams) {
|
||||
const serverData = await server_function({
|
||||
...routeParams,
|
||||
query: { ...routeParams.query, ...query },
|
||||
});
|
||||
return {
|
||||
...serverData,
|
||||
...default_props,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...default_props,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
...default_props,
|
||||
};
|
||||
}
|
||||
}
|
||||
+36
-15
@@ -1,37 +1,58 @@
|
||||
import isDevelopment from "../../../utils/is-development";
|
||||
import * as esbuild from "esbuild";
|
||||
import tailwindcss from "bun-plugin-tailwind";
|
||||
import grabDirNames from "../../../utils/grab-dir-names";
|
||||
import path from "path";
|
||||
import tailwindEsbuildPlugin from "./tailwind-esbuild-plugin";
|
||||
import BunSkipNonBrowserPlugin from "../../bundler/plugins/bun-skip-browser-plugin";
|
||||
export default async function grabTsxStringModule({ tsx, file_path, }) {
|
||||
const dev = isDevelopment();
|
||||
const { BUNX_CWD_MODULE_CACHE_DIR } = grabDirNames();
|
||||
const trimmed_file_path = file_path
|
||||
.replace(/.*\/src\/pages\//, "")
|
||||
.replace(/\.tsx$/, "");
|
||||
const src_file_path = path.join(BUNX_CWD_MODULE_CACHE_DIR, `${trimmed_file_path}.tsx`);
|
||||
const out_file_path = path.join(BUNX_CWD_MODULE_CACHE_DIR, `${trimmed_file_path}.js`);
|
||||
await esbuild.build({
|
||||
stdin: {
|
||||
contents: tsx,
|
||||
resolveDir: process.cwd(),
|
||||
loader: "tsx",
|
||||
},
|
||||
bundle: true,
|
||||
await Bun.write(src_file_path, tsx);
|
||||
const build = await Bun.build({
|
||||
entrypoints: [src_file_path],
|
||||
format: "esm",
|
||||
target: "es2020",
|
||||
platform: "node",
|
||||
target: "bun",
|
||||
external: ["react", "react-dom"],
|
||||
minify: true,
|
||||
define: {
|
||||
"process.env.NODE_ENV": JSON.stringify(dev ? "development" : "production"),
|
||||
},
|
||||
metafile: true,
|
||||
plugins: [tailwindEsbuildPlugin],
|
||||
jsx: "automatic",
|
||||
write: true,
|
||||
outfile: out_file_path,
|
||||
plugins: [tailwindcss, BunSkipNonBrowserPlugin],
|
||||
jsx: {
|
||||
runtime: "automatic",
|
||||
development: dev,
|
||||
},
|
||||
outdir: BUNX_CWD_MODULE_CACHE_DIR,
|
||||
});
|
||||
Loader.registry.delete(out_file_path);
|
||||
const module = await import(`${out_file_path}?t=${Date.now()}`);
|
||||
return module;
|
||||
}
|
||||
// await esbuild.build({
|
||||
// stdin: {
|
||||
// contents: tsx,
|
||||
// resolveDir: process.cwd(),
|
||||
// loader: "tsx",
|
||||
// },
|
||||
// bundle: true,
|
||||
// format: "esm",
|
||||
// target: "es2020",
|
||||
// platform: "node",
|
||||
// external: ["react", "react-dom"],
|
||||
// minify: true,
|
||||
// define: {
|
||||
// "process.env.NODE_ENV": JSON.stringify(
|
||||
// dev ? "development" : "production",
|
||||
// ),
|
||||
// },
|
||||
// metafile: true,
|
||||
// plugins: [tailwindEsbuildPlugin],
|
||||
// jsx: "automatic",
|
||||
// write: true,
|
||||
// outfile: out_file_path,
|
||||
// });
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ import type { BunextPageModuleMeta } from "../../../types";
|
||||
type Params = {
|
||||
meta: BunextPageModuleMeta;
|
||||
};
|
||||
export default function grabWebMetaHTML({ meta }: Params): string;
|
||||
export default function grabWebMetaHTML({ meta }: Params): import("react/jsx-runtime").JSX.Element;
|
||||
export {};
|
||||
|
||||
+6
-58
@@ -1,61 +1,9 @@
|
||||
import { escape } from "lodash";
|
||||
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
export default function grabWebMetaHTML({ meta }) {
|
||||
let html = ``;
|
||||
if (meta.title) {
|
||||
html += ` <title>${escape(meta.title)}</title>\n`;
|
||||
}
|
||||
if (meta.description) {
|
||||
html += ` <meta name="description" content="${escape(meta.description)}" />\n`;
|
||||
}
|
||||
if (meta.keywords) {
|
||||
const keywords = Array.isArray(meta.keywords)
|
||||
const keywords = meta.keywords
|
||||
? Array.isArray(meta.keywords)
|
||||
? meta.keywords.join(", ")
|
||||
: meta.keywords;
|
||||
html += ` <meta name="keywords" content="${escape(keywords)}" />\n`;
|
||||
}
|
||||
if (meta.author) {
|
||||
html += ` <meta name="author" content="${escape(meta.author)}" />\n`;
|
||||
}
|
||||
if (meta.robots) {
|
||||
html += ` <meta name="robots" content="${escape(meta.robots)}" />\n`;
|
||||
}
|
||||
if (meta.canonical) {
|
||||
html += ` <link rel="canonical" href="${escape(meta.canonical)}" />\n`;
|
||||
}
|
||||
if (meta.themeColor) {
|
||||
html += ` <meta name="theme-color" content="${escape(meta.themeColor)}" />\n`;
|
||||
}
|
||||
if (meta.og) {
|
||||
const { og } = meta;
|
||||
if (og.title)
|
||||
html += ` <meta property="og:title" content="${escape(og.title)}" />\n`;
|
||||
if (og.description)
|
||||
html += ` <meta property="og:description" content="${escape(og.description)}" />\n`;
|
||||
if (og.image)
|
||||
html += ` <meta property="og:image" content="${escape(og.image)}" />\n`;
|
||||
if (og.url)
|
||||
html += ` <meta property="og:url" content="${escape(og.url)}" />\n`;
|
||||
if (og.type)
|
||||
html += ` <meta property="og:type" content="${escape(og.type)}" />\n`;
|
||||
if (og.siteName)
|
||||
html += ` <meta property="og:site_name" content="${escape(og.siteName)}" />\n`;
|
||||
if (og.locale)
|
||||
html += ` <meta property="og:locale" content="${escape(og.locale)}" />\n`;
|
||||
}
|
||||
if (meta.twitter) {
|
||||
const { twitter } = meta;
|
||||
if (twitter.card)
|
||||
html += ` <meta name="twitter:card" content="${escape(twitter.card)}" />\n`;
|
||||
if (twitter.title)
|
||||
html += ` <meta name="twitter:title" content="${escape(twitter.title)}" />\n`;
|
||||
if (twitter.description)
|
||||
html += ` <meta name="twitter:description" content="${escape(twitter.description)}" />\n`;
|
||||
if (twitter.image)
|
||||
html += ` <meta name="twitter:image" content="${escape(twitter.image)}" />\n`;
|
||||
if (twitter.site)
|
||||
html += ` <meta name="twitter:site" content="${escape(twitter.site)}" />\n`;
|
||||
if (twitter.creator)
|
||||
html += ` <meta name="twitter:creator" content="${escape(twitter.creator)}" />\n`;
|
||||
}
|
||||
return html;
|
||||
: meta.keywords
|
||||
: undefined;
|
||||
return (_jsxs(_Fragment, { children: [meta.title && _jsx("title", { children: meta.title }), meta.description && (_jsx("meta", { name: "description", content: meta.description })), keywords && _jsx("meta", { name: "keywords", content: keywords }), meta.author && _jsx("meta", { name: "author", content: meta.author }), meta.robots && _jsx("meta", { name: "robots", content: meta.robots }), meta.canonical && (_jsx("link", { rel: "canonical", href: meta.canonical })), meta.themeColor && (_jsx("meta", { name: "theme-color", content: meta.themeColor })), meta.og?.title && (_jsx("meta", { property: "og:title", content: meta.og.title })), meta.og?.description && (_jsx("meta", { property: "og:description", content: meta.og.description })), meta.og?.image && (_jsx("meta", { property: "og:image", content: meta.og.image })), meta.og?.url && (_jsx("meta", { property: "og:url", content: meta.og.url })), meta.og?.type && (_jsx("meta", { property: "og:type", content: meta.og.type })), meta.og?.siteName && (_jsx("meta", { property: "og:site_name", content: meta.og.siteName })), meta.og?.locale && (_jsx("meta", { property: "og:locale", content: meta.og.locale })), meta.twitter?.card && (_jsx("meta", { name: "twitter:card", content: meta.twitter.card })), meta.twitter?.title && (_jsx("meta", { name: "twitter:title", content: meta.twitter.title })), meta.twitter?.description && (_jsx("meta", { name: "twitter:description", content: meta.twitter.description })), meta.twitter?.image && (_jsx("meta", { name: "twitter:image", content: meta.twitter.image })), meta.twitter?.site && (_jsx("meta", { name: "twitter:site", content: meta.twitter.site })), meta.twitter?.creator && (_jsx("meta", { name: "twitter:creator", content: meta.twitter.creator }))] }));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user