diff --git a/quartz.config.ts b/quartz.config.ts index ab7e990..d1fe184 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -56,9 +56,9 @@ const config: QuartzConfig = { ], emitters: [ Plugin.ContentPage({ - head: Component.Head, - header: [Component.PageTitle, Component.Spacer, Component.Darkmode], - body: [Component.ArticleTitle, Component.ReadingTime, Component.TableOfContents, Component.Content] + head: Component.Head(), + header: [Component.PageTitle(), Component.Spacer(), Component.Darkmode()], + body: [Component.ArticleTitle(), Component.ReadingTime(), Component.TableOfContents(), Component.Content()] }) ] }, diff --git a/quartz/components/ArticleTitle.tsx b/quartz/components/ArticleTitle.tsx index 02725c6..37950c4 100644 --- a/quartz/components/ArticleTitle.tsx +++ b/quartz/components/ArticleTitle.tsx @@ -1,6 +1,6 @@ -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" -export default function ArticleTitle({ fileData }: QuartzComponentProps) { +function ArticleTitle({ fileData }: QuartzComponentProps) { const title = fileData.frontmatter?.title const displayTitle = fileData.slug === "index" ? undefined : title if (displayTitle) { @@ -9,3 +9,5 @@ export default function ArticleTitle({ fileData }: QuartzComponentProps) { return null } } + +export default (() => ArticleTitle) satisfies QuartzComponentConstructor diff --git a/quartz/components/Body.tsx b/quartz/components/Body.tsx index b8ad34b..0130828 100644 --- a/quartz/components/Body.tsx +++ b/quartz/components/Body.tsx @@ -1,8 +1,8 @@ import clipboardScript from './scripts/clipboard.inline' import clipboardStyle from './styles/clipboard.scss' -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" -export default function Body({ children }: QuartzComponentProps) { +function Body({ children }: QuartzComponentProps) { return <article> {children} </article> @@ -10,3 +10,6 @@ export default function Body({ children }: QuartzComponentProps) { Body.afterDOMLoaded = clipboardScript Body.css = clipboardStyle + +export default (() => Body) satisfies QuartzComponentConstructor + diff --git a/quartz/components/Content.tsx b/quartz/components/Content.tsx index c010f2a..71d0f35 100644 --- a/quartz/components/Content.tsx +++ b/quartz/components/Content.tsx @@ -1,9 +1,11 @@ -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import { Fragment, jsx, jsxs } from 'preact/jsx-runtime' import { toJsxRuntime } from "hast-util-to-jsx-runtime" -export default function Content({ tree }: QuartzComponentProps) { +function Content({ tree }: QuartzComponentProps) { // @ts-ignore (preact makes it angry) const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: 'html' }) return content } + +export default (() => Content) satisfies QuartzComponentConstructor diff --git a/quartz/components/Darkmode.tsx b/quartz/components/Darkmode.tsx index 2170253..49f61c7 100644 --- a/quartz/components/Darkmode.tsx +++ b/quartz/components/Darkmode.tsx @@ -3,8 +3,9 @@ // see: https://v8.dev/features/modules#defer import darkmodeScript from "./scripts/darkmode.inline" import styles from './styles/darkmode.scss' +import { QuartzComponentConstructor } from "./types" -export default function Darkmode() { +function Darkmode() { return <div class="darkmode"> <input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex={-1} /> <label id="toggle-label-light" for="darkmode-toggle" tabIndex={-1}> @@ -48,3 +49,5 @@ export default function Darkmode() { Darkmode.beforeDOMLoaded = darkmodeScript Darkmode.css = styles + +export default (() => Darkmode) satisfies QuartzComponentConstructor diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx index 37c0aba..16125da 100644 --- a/quartz/components/Head.tsx +++ b/quartz/components/Head.tsx @@ -1,7 +1,7 @@ import { resolveToRoot } from "../path" -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" -export default function Head({ fileData, externalResources }: QuartzComponentProps) { +function Head({ fileData, externalResources }: QuartzComponentProps) { const slug = fileData.slug! const title = fileData.frontmatter?.title ?? "Untitled" const description = fileData.description ?? "No description provided" @@ -9,7 +9,7 @@ export default function Head({ fileData, externalResources }: QuartzComponentPro const baseDir = resolveToRoot(slug) const iconPath = baseDir + "/static/icon.png" const ogImagePath = baseDir + "/static/og-image.png" - + return <head> <title>{title}</title> <meta charSet="utf-8" /> @@ -28,3 +28,5 @@ export default function Head({ fileData, externalResources }: QuartzComponentPro {js.filter(resource => resource.loadTime === "beforeDOMReady").map(resource => <script key={resource.src} {...resource} spa-preserve />)} </head> } + +export default (() => Head) satisfies QuartzComponentConstructor diff --git a/quartz/components/Header.tsx b/quartz/components/Header.tsx index 8b06863..197c4e5 100644 --- a/quartz/components/Header.tsx +++ b/quartz/components/Header.tsx @@ -1,6 +1,6 @@ -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" -export default function Header({ children }: QuartzComponentProps) { +function Header({ children }: QuartzComponentProps) { return <header> {children} </header> @@ -21,3 +21,5 @@ header > h1 { flex: auto; } ` + +export default (() => Header) satisfies QuartzComponentConstructor diff --git a/quartz/components/PageTitle.tsx b/quartz/components/PageTitle.tsx index 080b74d..fe6ec3d 100644 --- a/quartz/components/PageTitle.tsx +++ b/quartz/components/PageTitle.tsx @@ -1,9 +1,11 @@ import { resolveToRoot } from "../path" -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" -export default function({ cfg, fileData }: QuartzComponentProps) { +function PageTitle({ cfg, fileData }: QuartzComponentProps) { const title = cfg.siteTitle const slug = fileData.slug! const baseDir = resolveToRoot(slug) return <h1><a href={baseDir}>{title}</a></h1> } + +export default (() => PageTitle) satisfies QuartzComponentConstructor diff --git a/quartz/components/ReadingTime.tsx b/quartz/components/ReadingTime.tsx index 39110f9..cac8711 100644 --- a/quartz/components/ReadingTime.tsx +++ b/quartz/components/ReadingTime.tsx @@ -1,7 +1,7 @@ -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import readingTime from "reading-time" -export default function ReadingTime({ fileData }: QuartzComponentProps) { +function ReadingTime({ fileData }: QuartzComponentProps) { const text = fileData.text const isHomePage = fileData.slug === "index" if (text && !isHomePage) { @@ -18,3 +18,5 @@ ReadingTime.css = ` opacity: 0.5; } ` + +export default (() => ReadingTime) satisfies QuartzComponentConstructor diff --git a/quartz/components/Spacer.tsx b/quartz/components/Spacer.tsx index 02b1093..34ea084 100644 --- a/quartz/components/Spacer.tsx +++ b/quartz/components/Spacer.tsx @@ -1,3 +1,7 @@ -export default function() { +import { QuartzComponentConstructor } from "./types" + +function Spacer() { return <div class="spacer"></div> } + +export default (() => Spacer) satisfies QuartzComponentConstructor diff --git a/quartz/components/TableOfContents.tsx b/quartz/components/TableOfContents.tsx index 1f331ed..531c61d 100644 --- a/quartz/components/TableOfContents.tsx +++ b/quartz/components/TableOfContents.tsx @@ -1,7 +1,7 @@ -import { QuartzComponentProps } from "./types" +import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/toc.scss" -export default function TableOfContents({ fileData }: QuartzComponentProps) { +function TableOfContents({ fileData }: QuartzComponentProps) { if (!fileData.toc) { return null } @@ -17,3 +17,5 @@ export default function TableOfContents({ fileData }: QuartzComponentProps) { } TableOfContents.css = style + +export default (() => TableOfContents) satisfies QuartzComponentConstructor diff --git a/quartz/components/types.ts b/quartz/components/types.ts index cb84edc..0b9b0eb 100644 --- a/quartz/components/types.ts +++ b/quartz/components/types.ts @@ -18,4 +18,4 @@ export type QuartzComponent = ComponentType<QuartzComponentProps> & { afterDOMLoaded?: string, } -export type QuartzComponentConstructor<Options extends object> = (opts: Options) => QuartzComponent +export type QuartzComponentConstructor<Options extends object | undefined = undefined> = (opts: Options) => QuartzComponent diff --git a/quartz/plugins/emitters/contentPage.tsx b/quartz/plugins/emitters/contentPage.tsx index b7059f8..9b789ef 100644 --- a/quartz/plugins/emitters/contentPage.tsx +++ b/quartz/plugins/emitters/contentPage.tsx @@ -5,9 +5,9 @@ import { render } from "preact-render-to-string" import { GlobalConfiguration } from "../../cfg" import { QuartzComponent } from "../../components/types" import { resolveToRoot } from "../../path" -import Header from "../../components/Header" +import HeaderConstructor from "../../components/Header" import { QuartzComponentProps } from "../../components/types" -import Body from "../../components/Body" +import BodyConstructor from "../../components/Body" interface Options { head: QuartzComponent @@ -20,6 +20,10 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => { throw new Error("ContentPage must be initialized with options specifiying the components to use") } + const { head: Head, header, body } = opts + const Header = HeaderConstructor() + const Body = BodyConstructor() + return { name: "ContentPage", getQuartzComponents() { @@ -28,7 +32,6 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => { async emit(cfg: GlobalConfiguration, content: ProcessedContent[], resources: StaticResources, emit: EmitCallback): Promise<string[]> { const fps: string[] = [] - const { head: Head, header, body } = opts for (const [tree, file] of content) { const baseDir = resolveToRoot(file.data.slug!) const pageResources: StaticResources = {