Server-side render content

pull/674/head
Zef Hemel 2024-01-28 15:08:35 +01:00
parent 59eed7966d
commit 7612f1af73
4 changed files with 55 additions and 12 deletions

View File

@ -13,6 +13,9 @@ import { SpaceServer, SpaceServerConfig } from "./instance.ts";
import { KvPrimitives } from "../plugos/lib/kv_primitives.ts"; import { KvPrimitives } from "../plugos/lib/kv_primitives.ts";
import { PrefixedKvPrimitives } from "../plugos/lib/prefixed_kv_primitives.ts"; import { PrefixedKvPrimitives } from "../plugos/lib/prefixed_kv_primitives.ts";
import { base64Encode } from "../plugos/asset_bundle/base64.ts"; import { base64Encode } from "../plugos/asset_bundle/base64.ts";
import { extendedMarkdownLanguage } from "../common/markdown_parser/parser.ts";
import { parse } from "../common/markdown_parser/parse_tree.ts";
import { renderMarkdownToHtml } from "../plugs/markdown/markdown_render.ts";
const authenticationExpirySeconds = 60 * 60 * 24 * 7; // 1 week const authenticationExpirySeconds = 60 * 60 * 24 * 7; // 1 week
@ -108,19 +111,39 @@ export class HttpServer {
} }
// Replaces some template variables in index.html in a rather ad-hoc manner, but YOLO // Replaces some template variables in index.html in a rather ad-hoc manner, but YOLO
renderIndexHtml(spaceServer: SpaceServer) { async renderHtmlPage(spaceServer: SpaceServer, pageName: string) {
console.log("Server side rendering", pageName);
let html = "";
try {
const { data } = await spaceServer.spacePrimitives.readFile(
`${pageName}.md`,
);
const text = new TextDecoder().decode(data);
const tree = parse(extendedMarkdownLanguage, text);
html = renderMarkdownToHtml(tree);
} catch (e: any) {
if (e.message !== "Not found") {
console.error("Error server-side rendering page", e);
}
}
return this.clientAssetBundle.readTextFileSync(".client/index.html") return this.clientAssetBundle.readTextFileSync(".client/index.html")
.replaceAll( .replace(
"{{SPACE_PATH}}", "{{SPACE_PATH}}",
spaceServer.pagesPath.replaceAll("\\", "\\\\"), spaceServer.pagesPath.replaceAll("\\", "\\\\"),
// ); )
).replaceAll( .replace(
"{{TITLE}}",
pageName,
).replace(
"{{SYNC_ONLY}}", "{{SYNC_ONLY}}",
spaceServer.syncOnly ? "true" : "false", spaceServer.syncOnly ? "true" : "false",
).replaceAll( ).replace(
"{{READ_ONLY}}", "{{READ_ONLY}}",
spaceServer.readOnly ? "true" : "false", spaceServer.readOnly ? "true" : "false",
).replaceAll( ).replace(
"{{CONTENT}}",
html,
).replace(
"{{CLIENT_ENCRYPTION}}", "{{CLIENT_ENCRYPTION}}",
spaceServer.clientEncryption ? "true" : "false", spaceServer.clientEncryption ? "true" : "false",
); );
@ -135,7 +158,9 @@ export class HttpServer {
// Fallback, serve the UI index.html // Fallback, serve the UI index.html
this.app.use("*", async (c) => { this.app.use("*", async (c) => {
const spaceServer = await this.ensureSpaceServer(c.req); const spaceServer = await this.ensureSpaceServer(c.req);
return c.html(this.renderIndexHtml(spaceServer), 200, { const url = new URL(c.req.url);
const pageName = decodeURI(url.pathname.slice(1));
return c.html(await this.renderHtmlPage(spaceServer, pageName), 200, {
"Cache-Control": "no-cache", "Cache-Control": "no-cache",
}); });
}); });
@ -175,9 +200,16 @@ export class HttpServer {
) { ) {
// Serve the UI (index.html) // Serve the UI (index.html)
// Note: we're explicitly not setting Last-Modified and If-Modified-Since header here because this page is dynamic // Note: we're explicitly not setting Last-Modified and If-Modified-Since header here because this page is dynamic
return c.html(this.renderIndexHtml(spaceServer), 200, { return c.html(
"Cache-Control": "no-cache", await this.renderHtmlPage(
}); spaceServer,
spaceServer.settings?.indexPage!,
),
200,
{
"Cache-Control": "no-cache",
},
);
} }
try { try {
const assetName = url.pathname.slice(1); const assetName = url.pathname.slice(1);

View File

@ -35,7 +35,7 @@ export class SpaceServer {
authToken?: string; authToken?: string;
hostname: string; hostname: string;
private settings?: BuiltinSettings; settings?: BuiltinSettings;
spacePrimitives!: SpacePrimitives; spacePrimitives!: SpacePrimitives;
jwtIssuer: JWTIssuer; jwtIssuer: JWTIssuer;

View File

@ -309,6 +309,7 @@ export class MainUI {
render(container: Element) { render(container: Element) {
// const ViewComponent = this.ui.ViewComponent.bind(this.ui); // const ViewComponent = this.ui.ViewComponent.bind(this.ui);
container.innerHTML = "";
preactRender(h(this.ViewComponent.bind(this), {}), container); preactRender(h(this.ViewComponent.bind(this), {}), container);
} }
} }

View File

@ -10,7 +10,7 @@
<meta name="theme-color" content="#e1e1e1" media="(prefers-color-scheme: light)"> <meta name="theme-color" content="#e1e1e1" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#262626" media="(prefers-color-scheme: dark)"> <meta name="theme-color" content="#262626" media="(prefers-color-scheme: dark)">
<title>SilverBullet</title> <title>{{TITLE}}</title>
<script> <script>
// Some global variables we need to make this work // Some global variables we need to make this work
Deno = { Deno = {
@ -61,6 +61,16 @@
<body> <body>
<div id="sb-root"> <div id="sb-root">
<div id="sb-main">
<div id="sb-editor">
<div class="cm-editor">
<div class="cm-content">
{{CONTENT}}
</div>
</div>
</div>
</div>
</div> </div>
</body> </body>