]> Untitled Git - lemmy-ui.git/blob - src/server/utils/create-ssr-html.tsx
39725fa52ce47e65ae8880f2bb97f76f4b8da47f
[lemmy-ui.git] / src / server / utils / create-ssr-html.tsx
1 import { Helmet } from "inferno-helmet";
2 import { renderToString } from "inferno-server";
3 import serialize from "serialize-javascript";
4 import sharp from "sharp";
5 import { favIconPngUrl, favIconUrl } from "../../shared/config";
6 import { ILemmyConfig, IsoDataOptionalSite } from "../../shared/interfaces";
7 import { buildThemeList } from "./build-themes-list";
8 import { fetchIconPng } from "./fetch-icon-png";
9
10 const customHtmlHeader = process.env["LEMMY_UI_CUSTOM_HTML_HEADER"] || "";
11
12 let appleTouchIcon: string | undefined = undefined;
13
14 export async function createSsrHtml(
15   root: string,
16   isoData: IsoDataOptionalSite
17 ) {
18   const site = isoData.site_res;
19
20   const fallbackTheme = `<link rel="stylesheet" type="text/css" href="/css/themes/${
21     (await buildThemeList())[0]
22   }.css" />`;
23
24   if (!appleTouchIcon) {
25     appleTouchIcon = site?.site_view.site.icon
26       ? `data:image/png;base64,${sharp(
27           await fetchIconPng(site.site_view.site.icon)
28         )
29           .resize(180, 180)
30           .extend({
31             bottom: 20,
32             top: 20,
33             left: 20,
34             right: 20,
35             background: "#222222",
36           })
37           .png()
38           .toBuffer()
39           .then(buf => buf.toString("base64"))}`
40       : favIconPngUrl;
41   }
42
43   const erudaStr =
44     process.env["LEMMY_UI_DEBUG"] === "true"
45       ? renderToString(
46           <>
47             <script src="//cdn.jsdelivr.net/npm/eruda"></script>
48             <script>eruda.init();</script>
49           </>
50         )
51       : "";
52
53   const helmet = Helmet.renderStatic();
54
55   const config: ILemmyConfig = { wsHost: process.env.LEMMY_UI_LEMMY_WS_HOST };
56
57   return `
58     <!DOCTYPE html>
59     <html ${helmet.htmlAttributes.toString()}>
60     <head>
61     <script>window.isoData = ${serialize(isoData)}</script>
62     <script>window.lemmyConfig = ${serialize(config)}</script>
63   
64     <!-- A remote debugging utility for mobile -->
65     ${erudaStr}
66   
67     <!-- Custom injected script -->
68     ${customHtmlHeader}
69   
70     ${helmet.title.toString()}
71     ${helmet.meta.toString()}
72   
73     <!-- Required meta tags -->
74     <meta name="Description" content="Lemmy">
75     <meta charset="utf-8">
76     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no">
77     <link
78        id="favicon"
79        rel="shortcut icon"
80        type="image/x-icon"
81        href=${site?.site_view.site.icon ?? favIconUrl}
82      />
83   
84     <!-- Web app manifest -->
85     <link rel="manifest" href="/manifest.webmanifest" />
86     <link rel="apple-touch-icon" href=${appleTouchIcon} />
87     <link rel="apple-touch-startup-image" href=${appleTouchIcon} />
88   
89     <!-- Styles -->
90     <link rel="stylesheet" type="text/css" href="/static/styles/styles.css" />
91   
92     <!-- Current theme and more -->
93     ${helmet.link.toString() || fallbackTheme}
94     
95     </head>
96   
97     <body ${helmet.bodyAttributes.toString()}>
98       <noscript>
99         <div class="alert alert-danger rounded-0" role="alert">
100           <b>Javascript is disabled. Actions will not work.</b>
101         </div>
102       </noscript>
103   
104       <div id='root'>${root}</div>
105       <script defer src='/static/js/client.js'></script>
106     </body>
107   </html>
108   `;
109 }