/* This file is part of the Notesnook project (https://notesnook.com/) Copyright (C) 2023 Streetwriters (Private) Limited This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import { CacheProvider } from "@emotion/react"; import createEmotionServer from "@emotion/server/create-instance"; import type { EntryContext } from "@remix-run/node"; import { RemixServer } from "@remix-run/react"; import { renderToString } from "react-dom/server"; import { createEmotionCache } from "./styles/createEmotionCache"; import { Head } from "./root"; import { ThemeDark } from "@notesnook/theme"; globalThis.DEFAULT_THEME = ThemeDark; export default function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext ) { // swap out default component with const defaultRoot = remixContext.routeModules.root; remixContext.routeModules.root = { ...defaultRoot, default: Head }; const head = renderToString( ); // restore the default root component remixContext.routeModules.root = defaultRoot; const cache = createEmotionCache(); const { extractCriticalToChunks, constructStyleTagsFromChunks } = createEmotionServer(cache); const body = renderToString( ); const styles = constructStyleTagsFromChunks(extractCriticalToChunks(body)); const html = `${head}${styles}
${body}
`; responseHeaders.set("Content-Type", "text/html; charset=utf-8"); const nonce = remixContext.staticHandlerContext?.loaderData?.root?.cspScriptNonce; if (nonce) responseHeaders.set( "Content-Security-Policy", getContentSecurityPolicy(nonce) ); return new Response(html, { status: responseStatusCode, headers: responseHeaders }); } function getContentSecurityPolicy(nonce?: string) { let script_src: string; if (typeof nonce === "string") { script_src = `'self' 'report-sample' 'nonce-${nonce}'`; } else if (process.env.NODE_ENV === "development") { // Allow the component to load without a nonce in the error pages script_src = "'self' 'report-sample'"; } else { script_src = "'self' 'report-sample'"; } const connect_src = process.env.NODE_ENV === "development" ? "'self' ws://localhost:*" : "'self' https://notesnook.com/api/v1/reports/submit"; return ( `script-src ${script_src} 'strict-dynamic'; ` + `connect-src ${connect_src}; ` + "form-action 'self'; " + "object-src 'none'; " + "block-all-mixed-content; " + "base-uri 'self'; manifest-src 'self'" ); }