quartz-research-note/quartz/components/renderPage.tsx

118 lines
3.2 KiB
TypeScript
Raw Normal View History

2023-07-23 00:27:41 +00:00
import { render } from "preact-render-to-string"
import { QuartzComponent, QuartzComponentProps } from "./types"
2023-07-01 07:03:01 +00:00
import HeaderConstructor from "./Header"
import BodyConstructor from "./Body"
import { JSResourceToScriptElement, StaticResources } from "../util/resources"
import { FullSlug, joinSegments, pathToRoot } from "../util/path"
2023-07-01 07:03:01 +00:00
interface RenderComponents {
head: QuartzComponent
2023-07-23 00:27:41 +00:00
header: QuartzComponent[]
beforeBody: QuartzComponent[]
pageBody: QuartzComponent
left: QuartzComponent[]
right: QuartzComponent[]
footer: QuartzComponent
2023-07-01 07:03:01 +00:00
}
export function pageResources(slug: FullSlug, staticResources: StaticResources): StaticResources {
2023-07-13 07:19:35 +00:00
const baseDir = pathToRoot(slug)
2023-07-02 20:08:29 +00:00
const contentIndexPath = joinSegments(baseDir, "static/contentIndex.json")
2023-07-02 20:08:29 +00:00
const contentIndexScript = `const fetchData = fetch(\`${contentIndexPath}\`).then(data => data.json())`
2023-07-01 07:03:01 +00:00
return {
css: [joinSegments(baseDir, "index.css"), ...staticResources.css],
2023-07-01 07:03:01 +00:00
js: [
{
2023-08-19 23:28:44 +00:00
src: joinSegments(baseDir, "prescript.js"),
loadTime: "beforeDOMReady",
contentType: "external",
},
2023-07-23 00:27:41 +00:00
{
loadTime: "beforeDOMReady",
contentType: "inline",
spaPreserve: true,
script: contentIndexScript,
},
2023-07-01 07:03:01 +00:00
...staticResources.js,
2023-07-23 00:27:41 +00:00
{
2023-08-19 23:28:44 +00:00
src: joinSegments(baseDir, "postscript.js"),
2023-07-23 00:27:41 +00:00
loadTime: "afterDOMReady",
moduleType: "module",
contentType: "external",
},
],
2023-07-01 07:03:01 +00:00
}
}
2023-07-23 00:27:41 +00:00
export function renderPage(
slug: FullSlug,
2023-07-23 00:27:41 +00:00
componentData: QuartzComponentProps,
components: RenderComponents,
pageResources: StaticResources,
): string {
const {
head: Head,
header,
beforeBody,
pageBody: Content,
left,
right,
footer: Footer,
} = components
2023-07-01 07:03:01 +00:00
const Header = HeaderConstructor()
const Body = BodyConstructor()
2023-07-23 00:27:41 +00:00
const LeftComponent = (
2023-07-05 00:14:15 +00:00
<div class="left sidebar">
2023-07-23 00:27:41 +00:00
{left.map((BodyComponent) => (
<BodyComponent {...componentData} />
))}
2023-07-02 20:08:29 +00:00
</div>
2023-07-23 00:27:41 +00:00
)
2023-07-02 20:08:29 +00:00
2023-07-23 00:27:41 +00:00
const RightComponent = (
2023-07-05 00:14:15 +00:00
<div class="right sidebar">
2023-07-23 00:27:41 +00:00
{right.map((BodyComponent) => (
<BodyComponent {...componentData} />
))}
2023-07-02 20:08:29 +00:00
</div>
2023-07-23 00:27:41 +00:00
)
2023-07-02 20:08:29 +00:00
2023-07-23 00:27:41 +00:00
const doc = (
<html>
<Head {...componentData} />
<body data-slug={slug}>
<div id="quartz-root" class="page">
<Body {...componentData}>
{LeftComponent}
<div class="center">
<div class="page-header">
<Header {...componentData}>
{header.map((HeaderComponent) => (
<HeaderComponent {...componentData} />
))}
</Header>
<div class="popover-hint">
{beforeBody.map((BodyComponent) => (
<BodyComponent {...componentData} />
))}
</div>
</div>
2023-07-23 00:27:41 +00:00
<Content {...componentData} />
</div>
2023-07-23 00:27:41 +00:00
{RightComponent}
</Body>
<Footer {...componentData} />
</div>
</body>
{pageResources.js
.filter((resource) => resource.loadTime === "afterDOMReady")
.map((res) => JSResourceToScriptElement(res))}
</html>
)
2023-07-01 07:03:01 +00:00
return "<!DOCTYPE html>\n" + render(doc)
}