| quartz.config.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/components/Body.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/components/Head.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/components/Header.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/components/PageTitle.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/components/Spacer.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/components/types.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/emitters/contentPage.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/index.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/transformers/description.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/types.ts | ●●●●● patch | view | raw | blame | history |
quartz.config.ts
@@ -1,7 +1,9 @@ import { QuartzConfig } from "./quartz/cfg" import Body from "./quartz/components/Body" import Darkmode from "./quartz/components/Darkmode" import Head from "./quartz/components/Head" import Header from "./quartz/components/Header" import PageTitle from "./quartz/components/PageTitle" import Spacer from "./quartz/components/Spacer" import { ContentPage, CreatedModifiedDate, @@ -68,9 +70,9 @@ ], emitters: [ new ContentPage({ Head: Head, Header: Header, Body: Body head: Head, header: [PageTitle, Spacer, Darkmode], body: Body }) ] }, quartz/components/Body.tsx
@@ -1,15 +1,14 @@ import { ComponentChildren } from "preact" import clipboardScript from './scripts/clipboard.inline' import clipboardStyle from './styles/clipboard.scss' import { QuartzComponentProps } from "./types" export interface BodyProps { title?: string children: ComponentChildren } export default function Body({ title, children }: BodyProps) { export default function Body({ fileData, children }: QuartzComponentProps) { const title = fileData.frontmatter?.title const displayTitle = fileData.slug === "index" ? undefined : title return <article> {title && <h1>{title}</h1>} <div class="top-section"> {displayTitle && <h1>{displayTitle}</h1>} </div> {children} </article> } quartz/components/Head.tsx
@@ -1,18 +1,15 @@ import { resolveToRoot } from "../path" import { StaticResources } from "../resources" import { QuartzComponentProps } from "./types" export interface HeadProps { title: string description: string slug: string externalResources: StaticResources } export default function Head({ title, description, slug, externalResources }: HeadProps) { export default function Head({ fileData, externalResources }: QuartzComponentProps) { const slug = fileData.slug! const title = fileData.frontmatter?.title ?? "Untitled" const description = fileData.description ?? "No description provided" const { css, js } = externalResources 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" /> quartz/components/Header.tsx
@@ -1,20 +1,10 @@ import { resolveToRoot } from "../path" import Darkmode from "./Darkmode" import style from './styles/header.scss' import { QuartzComponentProps } from "./types" export interface HeaderProps { title: string slug: string } export default function Header({ title, slug }: HeaderProps) { const baseDir = resolveToRoot(slug) export default function Header({ children }: QuartzComponentProps) { return <header> <h1><a href={baseDir}>{title}</a></h1> <div class="spacer"></div> <Darkmode /> {children} </header> } Header.beforeDOMLoaded = Darkmode.beforeDOMLoaded Header.css = style + Darkmode.css Header.css = style quartz/components/PageTitle.tsx
New file @@ -0,0 +1,9 @@ import { resolveToRoot } from "../path" import { QuartzComponentProps } from "./types" export default function({ cfg, fileData }: QuartzComponentProps) { const title = cfg.siteTitle const slug = fileData.slug! const baseDir = resolveToRoot(slug) return <h1><a href={baseDir}>{title}</a></h1> } quartz/components/Spacer.tsx
New file @@ -0,0 +1,3 @@ export default function() { return <div class="spacer"></div> } quartz/components/types.ts
@@ -1,6 +1,16 @@ import { ComponentType } from "preact" import { ComponentType, JSX } from "preact" import { StaticResources } from "../resources" import { QuartzPluginData } from "../plugins/vfile" import { GlobalConfiguration } from "../cfg" export type QuartzComponent<Props> = ComponentType<Props> & { export type QuartzComponentProps = { externalResources: StaticResources fileData: QuartzPluginData cfg: GlobalConfiguration children: QuartzComponent[] | JSX.Element[] } export type QuartzComponent = ComponentType<QuartzComponentProps> & { css?: string, beforeDOMLoaded?: string, afterDOMLoaded?: string, quartz/plugins/emitters/contentPage.tsx
@@ -4,17 +4,16 @@ import { ProcessedContent } from "../vfile" import { Fragment, jsx, jsxs } from 'preact/jsx-runtime' import { render } from "preact-render-to-string" import { HeadProps } from "../../components/Head" import { GlobalConfiguration } from "../../cfg" import { HeaderProps } from "../../components/Header" import { QuartzComponent } from "../../components/types" import { resolveToRoot } from "../../path" import { BodyProps } from "../../components/Body" import Header from "../../components/Header" import { QuartzComponentProps } from "../../components/types" interface Options { Head: QuartzComponent<HeadProps> Header: QuartzComponent<HeaderProps> Body: QuartzComponent<BodyProps> head: QuartzComponent header: QuartzComponent[], body: QuartzComponent } export class ContentPage extends QuartzEmitterPlugin { @@ -26,21 +25,21 @@ this.opts = opts } getQuartzComponents(): QuartzComponent<any>[] { return [...Object.values(this.opts)] getQuartzComponents(): QuartzComponent[] { return [this.opts.head, Header, ...this.opts.header, this.opts.body] } async emit(cfg: GlobalConfiguration, content: ProcessedContent[], resources: StaticResources, emit: EmitCallback): Promise<string[]> { const fps: string[] = [] const { Head, Header, Body } = this.opts const { head: Head, header, body: Body } = this.opts for (const [tree, file] of content) { // @ts-ignore (preact makes it angry) const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: 'html' }) const baseDir = resolveToRoot(file.data.slug!) const pageResources: StaticResources = { css: [baseDir + "/index.css", ...resources.css,], css: [baseDir + "/index.css", ...resources.css], js: [ { src: baseDir + "/prescript.js", loadTime: "beforeDOMReady" }, ...resources.js, @@ -48,17 +47,23 @@ ] } const title = file.data.frontmatter?.title const componentData: QuartzComponentProps = { fileData: file.data, externalResources: pageResources, cfg, children: [content] } const doc = <html> <Head title={title ?? "Untitled"} description={file.data.description ?? "No description provided"} slug={file.data.slug!} externalResources={pageResources} /> <Head {...componentData} /> <body> <div id="quartz-root" class="page"> <Header title={cfg.siteTitle} slug={file.data.slug!} /> <Body title={file.data.slug === "index" ? undefined : title}>{content}</Body> <Header {...componentData} > {header.map(HeaderComponent => <HeaderComponent {...componentData}/>)} </Header> <Body {...componentData}> {content} </Body> </div> </body> {pageResources.js.filter(resource => resource.loadTime === "afterDOMReady").map(resource => <script key={resource.src} {...resource} />)} quartz/plugins/index.ts
@@ -17,7 +17,7 @@ export function emitComponentResources(cfg: GlobalConfiguration, resources: StaticResources, plugins: PluginTypes, emit: EmitCallback) { const fps: string[] = [] const allComponents: Set<QuartzComponent<any>> = new Set() const allComponents: Set<QuartzComponent> = new Set() for (const emitter of plugins.emitters) { const components = emitter.getQuartzComponents() for (const component of components) { quartz/plugins/transformers/description.ts
@@ -29,7 +29,9 @@ () => { return async (tree: HTMLRoot, file) => { const frontMatterDescription = file.data.frontmatter?.description const desc = frontMatterDescription ?? toString(tree) const text = toString(tree) const desc = frontMatterDescription ?? text const sentences = desc.replace(/\s+/g, ' ').split('.') let finalDesc = "" let sentenceIdx = 0 @@ -40,6 +42,7 @@ } file.data.description = finalDesc file.data.text = text } } ] @@ -49,6 +52,7 @@ declare module 'vfile' { interface DataMap { description: string text: string } } quartz/plugins/types.ts
@@ -26,7 +26,7 @@ export abstract class QuartzEmitterPlugin { abstract name: string abstract emit(cfg: GlobalConfiguration, content: ProcessedContent[], resources: StaticResources, emitCallback: EmitCallback): Promise<string[]> abstract getQuartzComponents(): QuartzComponent<any>[] abstract getQuartzComponents(): QuartzComponent[] } export interface PluginTypes {