diff --git a/package-lock.json b/package-lock.json index 4847103d..6d922f47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "chalk": "^4.1.2", "cli-spinner": "^0.2.10", "esbuild-sass-plugin": "^2.9.0", - "flamethrower-router": "^0.0.0-meme.12", "github-slugger": "^2.0.0", "globby": "^13.1.4", "gray-matter": "^4.0.3", @@ -22,9 +21,12 @@ "hast-util-to-string": "^2.0.0", "is-absolute-url": "^4.0.1", "mdast-util-find-and-replace": "^2.2.2", + "mdast-util-to-string": "^3.2.0", + "micromorph": "^0.4.5", "preact": "^10.14.1", "preact-render-to-string": "^6.0.3", "pretty-time": "^1.1.0", + "reading-time": "^1.5.0", "rehype-autolink-headings": "^6.1.1", "rehype-katex": "^6.0.3", "rehype-pretty-code": "^0.9.6", @@ -1523,11 +1525,6 @@ "node": ">=8" } }, - "node_modules/flamethrower-router": { - "version": "0.0.0-meme.12", - "resolved": "https://registry.npmjs.org/flamethrower-router/-/flamethrower-router-0.0.0-meme.12.tgz", - "integrity": "sha512-PWcNrjzItwk61RTk/SbbKJNcAgl6qCXH8xkZjGjUGV/dgKAnURci+k+Yk8emubUQWTdAd1kSqujy0VRjoeEgxg==" - }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -3006,6 +3003,11 @@ "node": ">=8.6" } }, + "node_modules/micromorph": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/micromorph/-/micromorph-0.4.5.tgz", + "integrity": "sha512-Erasr0xiDvDeEhh7B/k7RFTwwfaAX10D7BMorNpokkwDh6XsRLYWDPaWF1m5JQeMSkGdqlEtQ8s68NcdDWuGgw==" + }, "node_modules/mime-db": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", @@ -3268,6 +3270,11 @@ "node": ">=8.10.0" } }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + }, "node_modules/rehype-autolink-headings": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz", diff --git a/package.json b/package.json index fe5a5178..810cf5e9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "chalk": "^4.1.2", "cli-spinner": "^0.2.10", "esbuild-sass-plugin": "^2.9.0", - "flamethrower-router": "^0.0.0-meme.12", "github-slugger": "^2.0.0", "globby": "^13.1.4", "gray-matter": "^4.0.3", @@ -38,9 +37,12 @@ "hast-util-to-string": "^2.0.0", "is-absolute-url": "^4.0.1", "mdast-util-find-and-replace": "^2.2.2", + "mdast-util-to-string": "^3.2.0", + "micromorph": "^0.4.5", "preact": "^10.14.1", "preact-render-to-string": "^6.0.3", "pretty-time": "^1.1.0", + "reading-time": "^1.5.0", "rehype-autolink-headings": "^6.1.1", "rehype-katex": "^6.0.3", "rehype-pretty-code": "^0.9.6", diff --git a/quartz.config.ts b/quartz.config.ts index 3a1d4334..ab7e9908 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -39,23 +39,23 @@ const config: QuartzConfig = { }, plugins: { transformers: [ - new Plugin.FrontMatter(), - new Plugin.Description(), - new Plugin.TableOfContents({ showByDefault: true }), - new Plugin.CreatedModifiedDate({ + Plugin.FrontMatter(), + Plugin.Description(), + Plugin.TableOfContents({ showByDefault: true }), + Plugin.CreatedModifiedDate({ priority: ['frontmatter', 'filesystem'] // you can add 'git' here for last modified from Git but this makes the build slower }), - new Plugin.GitHubFlavoredMarkdown(), - new Plugin.ObsidianFlavoredMarkdown(), - new Plugin.ResolveLinks(), - new Plugin.SyntaxHighlighting(), - new Plugin.Katex(), + Plugin.GitHubFlavoredMarkdown(), + Plugin.ObsidianFlavoredMarkdown(), + Plugin.ResolveLinks(), + Plugin.SyntaxHighlighting(), + Plugin.Katex(), ], filters: [ - new Plugin.RemoveDrafts() + Plugin.RemoveDrafts() ], emitters: [ - new Plugin.ContentPage({ + Plugin.ContentPage({ head: Component.Head, header: [Component.PageTitle, Component.Spacer, Component.Darkmode], body: [Component.ArticleTitle, Component.ReadingTime, Component.TableOfContents, Component.Content] diff --git a/quartz/components/TableOfContents.tsx b/quartz/components/TableOfContents.tsx index 8192da42..1f331ed5 100644 --- a/quartz/components/TableOfContents.tsx +++ b/quartz/components/TableOfContents.tsx @@ -1,24 +1,19 @@ import { QuartzComponentProps } from "./types" import style from "./styles/toc.scss" -export default function TableOfContents({ fileData, position }: QuartzComponentProps) { +export default function TableOfContents({ fileData }: QuartzComponentProps) { if (!fileData.toc) { return null } - if (position === 'body') { - // TODO: animate this - return
-

Table of Contents

- -
- } else if (position === 'sidebar') { - // TODO - } + return
+

Table of Contents

+ +
} TableOfContents.css = style diff --git a/quartz/components/types.ts b/quartz/components/types.ts index 93f6a4bf..cb84edcd 100644 --- a/quartz/components/types.ts +++ b/quartz/components/types.ts @@ -10,7 +10,6 @@ export type QuartzComponentProps = { cfg: GlobalConfiguration children: QuartzComponent[] | JSX.Element[] tree: Node - position?: 'sidebar' | 'header' | 'body' } export type QuartzComponent = ComponentType & { @@ -18,3 +17,5 @@ export type QuartzComponent = ComponentType & { beforeDOMLoaded?: string, afterDOMLoaded?: string, } + +export type QuartzComponentConstructor = (opts: Options) => QuartzComponent diff --git a/quartz/plugins/emitters/contentPage.tsx b/quartz/plugins/emitters/contentPage.tsx index d44b709d..b7059f81 100644 --- a/quartz/plugins/emitters/contentPage.tsx +++ b/quartz/plugins/emitters/contentPage.tsx @@ -15,66 +15,64 @@ interface Options { body: QuartzComponent[] } -export class ContentPage extends QuartzEmitterPlugin { - name = "ContentPage" - opts: Options - - constructor(opts: Options) { - super() - this.opts = opts +export const ContentPage: QuartzEmitterPlugin = (opts) => { + if (!opts) { + throw new Error("ContentPage must be initialized with options specifiying the components to use") } - getQuartzComponents(): QuartzComponent[] { - return [this.opts.head, Header, ...this.opts.header, ...this.opts.body] - } + return { + name: "ContentPage", + getQuartzComponents() { + return [opts.head, Header, ...opts.header, ...opts.body] + }, + async emit(cfg: GlobalConfiguration, content: ProcessedContent[], resources: StaticResources, emit: EmitCallback): Promise { + const fps: string[] = [] - async emit(cfg: GlobalConfiguration, content: ProcessedContent[], resources: StaticResources, emit: EmitCallback): Promise { - const fps: string[] = [] + const { head: Head, header, body } = opts + for (const [tree, file] of content) { + const baseDir = resolveToRoot(file.data.slug!) + const pageResources: StaticResources = { + css: [baseDir + "/index.css", ...resources.css], + js: [ + { src: baseDir + "/prescript.js", loadTime: "beforeDOMReady" }, + ...resources.js, + { src: baseDir + "/postscript.js", loadTime: "afterDOMReady", type: 'module' } + ] + } - const { head: Head, header, body } = this.opts - for (const [tree, file] of content) { - const baseDir = resolveToRoot(file.data.slug!) - const pageResources: StaticResources = { - css: [baseDir + "/index.css", ...resources.css], - js: [ - { src: baseDir + "/prescript.js", loadTime: "beforeDOMReady" }, - ...resources.js, - { src: baseDir + "/postscript.js", loadTime: "afterDOMReady", type: 'module' } - ] + const componentData: QuartzComponentProps = { + fileData: file.data, + externalResources: pageResources, + cfg, + children: [], + tree + } + + const doc = + + +
+
+ {header.map(HeaderComponent => )} +
+ + {body.map(BodyComponent => )} + +
+ + {pageResources.js.filter(resource => resource.loadTime === "afterDOMReady").map(resource =>