Jacky Zhao
2023-07-16 3ac6b42e16dca5a44ed3fec2c0314f1dbbc2322b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { render } from "preact-render-to-string";
import { QuartzComponent, QuartzComponentProps } from "./types";
import HeaderConstructor from "./Header"
import BodyConstructor from "./Body"
import { JSResourceToScriptElement, StaticResources } from "../resources";
import { CanonicalSlug, pathToRoot } from "../path";
 
interface RenderComponents {
  head: QuartzComponent
  header: QuartzComponent[],
  beforeBody: QuartzComponent[],
  pageBody: QuartzComponent,
  left: QuartzComponent[],
  right: QuartzComponent[],
  footer: QuartzComponent,
}
 
export function pageResources(slug: CanonicalSlug, staticResources: StaticResources): StaticResources {
  const baseDir = pathToRoot(slug)
 
  const contentIndexPath = baseDir + "/static/contentIndex.json"
  const contentIndexScript = `const fetchData = fetch(\`${contentIndexPath}\`).then(data => data.json())`
 
  return {
    css: [baseDir + "/index.css", ...staticResources.css],
    js: [
      { src: baseDir + "/prescript.js", loadTime: "beforeDOMReady", contentType: "external" },
      { loadTime: "beforeDOMReady", contentType: "inline", spaPreserve: true, script: contentIndexScript },
      ...staticResources.js,
      { src: baseDir + "/postscript.js", loadTime: "afterDOMReady", moduleType: 'module', contentType: "external" }
    ]
  }
}
 
export function renderPage(slug: CanonicalSlug, componentData: QuartzComponentProps, components: RenderComponents, pageResources: StaticResources): string {
  const { head: Head, header, beforeBody, pageBody: Content, left, right, footer: Footer } = components
  const Header = HeaderConstructor()
  const Body = BodyConstructor()
 
  const LeftComponent =
    <div class="left sidebar">
      {left.map(BodyComponent => <BodyComponent {...componentData} />)}
    </div>
 
  const RightComponent =
    <div class="right sidebar">
      {right.map(BodyComponent => <BodyComponent {...componentData} />)}
    </div>
 
  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>
            <Content {...componentData} />
          </div>
          {RightComponent}
        </Body>
        <Footer {...componentData} />
      </div>
    </body>
    {pageResources.js.filter(resource => resource.loadTime === "afterDOMReady").map(res => JSResourceToScriptElement(res))}
  </html>
 
  return "<!DOCTYPE html>\n" + render(doc)
}