make layouts simpler to think about

This commit is contained in:
Jacky Zhao 2023-07-25 23:37:24 -07:00
parent 93c4d4358d
commit de372b4471
8 changed files with 117 additions and 122 deletions

View File

@ -4,17 +4,9 @@ title: Making your own plugins
This part of the documentation will assume you have some basic coding knowledge and will include code snippets that describe the interface of what Quartz plugins should look like. This part of the documentation will assume you have some basic coding knowledge and will include code snippets that describe the interface of what Quartz plugins should look like.
## Transformers ![[quartz-transform-pipeline.png]]
```ts ## Transformers
export type QuartzTransformerPluginInstance = {
name: string
textTransform?: (src: string | Buffer) => string | Buffer
markdownPlugins?: () => PluggableList
htmlPlugins?: () => PluggableList
externalResources?: () => Partial<StaticResources>
}
```
## Filters ## Filters

View File

@ -75,8 +75,10 @@ transformers: [
] ]
``` ```
If you'd like to make your own plugins, read the guide on [[making plugins]] for more information.
### Layout ### Layout
Certain emitters may also output [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML) files. To make sure that Certain emitters may also output [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML) files. To enable easy customization, these emitters allow you to fully rearrange the layout of the page.
### Components ### Components

View File

@ -6,8 +6,6 @@ draft: true
- images in same folder are broken on shortest path mode - images in same folder are broken on shortest path mode
- watch mode for config/source code - watch mode for config/source code
- publish metadata https://help.obsidian.md/Editing+and+formatting/Metadata#Metadata+for+Obsidian+Publish
- metadata aliases: https://help.obsidian.md/Editing+and+formatting/Metadata#Predefined+metadata
- block links: https://help.obsidian.md/Linking+notes+and+files/Internal+links#Link+to+a+block+in+a+note - block links: https://help.obsidian.md/Linking+notes+and+files/Internal+links#Link+to+a+block+in+a+note
- note/header/block transcludes: https://help.obsidian.md/Linking+notes+and+files/Embedding+files - note/header/block transcludes: https://help.obsidian.md/Linking+notes+and+files/Embedding+files

View File

@ -1,83 +1,46 @@
import { GlobalConfiguration, PageLayout, QuartzConfig } from "./quartz/cfg" import { QuartzConfig } from "./quartz/cfg"
import * as Component from "./quartz/components"
import * as Plugin from "./quartz/plugins" import * as Plugin from "./quartz/plugins"
const generalConfiguration: GlobalConfiguration = {
pageTitle: "🪴 Quartz 4.0",
enableSPA: true,
enablePopovers: true,
analytics: {
provider: "plausible",
},
baseUrl: "quartz.jzhao.xyz",
ignorePatterns: ["private", "templates"],
theme: {
typography: {
header: "Schibsted Grotesk",
body: "Source Sans Pro",
code: "IBM Plex Mono",
},
colors: {
lightMode: {
light: "#faf8f8",
lightgray: "#e5e5e5",
gray: "#b8b8b8",
darkgray: "#4e4e4e",
dark: "#2b2b2b",
secondary: "#284b63",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
},
darkMode: {
light: "#161618",
lightgray: "#393639",
gray: "#646464",
darkgray: "#d4d4d4",
dark: "#ebebec",
secondary: "#7b97aa",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
},
},
},
}
const sharedPageComponents = {
head: Component.Head(),
header: [],
footer: Component.Footer({
links: {
GitHub: "https://github.com/jackyzha0/quartz",
"Discord Community": "https://discord.gg/cRFFHYye7t",
},
}),
}
const contentPageLayout: PageLayout = {
beforeBody: [Component.ArticleTitle(), Component.ReadingTime(), Component.TagList()],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.Darkmode(),
Component.DesktopOnly(Component.TableOfContents()),
],
right: [Component.Graph(), Component.Backlinks()],
}
const listPageLayout: PageLayout = {
beforeBody: [Component.ArticleTitle()],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.Darkmode(),
],
right: [],
}
const config: QuartzConfig = { const config: QuartzConfig = {
configuration: generalConfiguration, configuration: {
pageTitle: "🪴 Quartz 4.0",
enableSPA: true,
enablePopovers: true,
analytics: {
provider: "plausible",
},
baseUrl: "quartz.jzhao.xyz",
ignorePatterns: ["private", "templates"],
theme: {
typography: {
header: "Schibsted Grotesk",
body: "Source Sans Pro",
code: "IBM Plex Mono",
},
colors: {
lightMode: {
light: "#faf8f8",
lightgray: "#e5e5e5",
gray: "#b8b8b8",
darkgray: "#4e4e4e",
dark: "#2b2b2b",
secondary: "#284b63",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
},
darkMode: {
light: "#161618",
lightgray: "#393639",
gray: "#646464",
darkgray: "#d4d4d4",
dark: "#ebebec",
secondary: "#7b97aa",
tertiary: "#84a59d",
highlight: "rgba(143, 159, 169, 0.15)",
},
},
},
},
plugins: { plugins: {
transformers: [ transformers: [
Plugin.FrontMatter(), Plugin.FrontMatter(),
@ -96,21 +59,9 @@ const config: QuartzConfig = {
emitters: [ emitters: [
Plugin.AliasRedirects(), Plugin.AliasRedirects(),
Plugin.ComponentResources({ fontOrigin: "googleFonts" }), Plugin.ComponentResources({ fontOrigin: "googleFonts" }),
Plugin.ContentPage({ Plugin.ContentPage(),
...sharedPageComponents, Plugin.FolderPage(),
...contentPageLayout, Plugin.TagPage(),
pageBody: Component.Content(),
}),
Plugin.FolderPage({
...sharedPageComponents,
...listPageLayout,
pageBody: Component.FolderContent(),
}),
Plugin.TagPage({
...sharedPageComponents,
...listPageLayout,
pageBody: Component.TagContent(),
}),
Plugin.ContentIndex({ Plugin.ContentIndex({
enableSiteMap: true, enableSiteMap: true,
enableRSS: true, enableRSS: true,

39
quartz.layout.ts Normal file
View File

@ -0,0 +1,39 @@
import { PageLayout } from "./quartz/cfg"
import * as Component from "./quartz/components"
// components shared across all pages
export const sharedPageComponents = {
head: Component.Head(),
header: [],
footer: Component.Footer({
links: {
GitHub: "https://github.com/jackyzha0/quartz",
"Discord Community": "https://discord.gg/cRFFHYye7t",
},
}),
}
// components for pages that display a single page (e.g. a single note)
export const defaultContentPageLayout: PageLayout = {
beforeBody: [Component.ArticleTitle(), Component.ReadingTime(), Component.TagList()],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.Darkmode(),
Component.DesktopOnly(Component.TableOfContents()),
],
right: [Component.Graph(), Component.Backlinks()],
}
// components for pages that display lists of pages (e.g. tags or folders)
export const defaultListPageLayout: PageLayout = {
beforeBody: [Component.ArticleTitle()],
left: [
Component.PageTitle(),
Component.MobileOnly(Component.Spacer()),
Component.Search(),
Component.Darkmode(),
],
right: [],
}

View File

@ -5,22 +5,25 @@ import BodyConstructor from "../../components/Body"
import { pageResources, renderPage } from "../../components/renderPage" import { pageResources, renderPage } from "../../components/renderPage"
import { FullPageLayout } from "../../cfg" import { FullPageLayout } from "../../cfg"
import { FilePath, canonicalizeServer } from "../../path" import { FilePath, canonicalizeServer } from "../../path"
import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
import { Content } from "../../components"
export const ContentPage: QuartzEmitterPlugin<FullPageLayout> = (opts) => { export const ContentPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOpts) => {
if (!opts) { const opts: FullPageLayout = {
throw new Error( ...sharedPageComponents,
"ContentPage must be initialized with options specifiying the components to use", ...defaultContentPageLayout,
) pageBody: Content(),
...userOpts,
} }
const { head: Head, header, beforeBody, pageBody: Content, left, right, footer: Footer } = opts const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
const Header = HeaderConstructor() const Header = HeaderConstructor()
const Body = BodyConstructor() const Body = BodyConstructor()
return { return {
name: "ContentPage", name: "ContentPage",
getQuartzComponents() { getQuartzComponents() {
return [Head, Header, Body, ...header, ...beforeBody, Content, ...left, ...right, Footer] return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
}, },
async emit(ctx, content, resources, emit): Promise<FilePath[]> { async emit(ctx, content, resources, emit): Promise<FilePath[]> {
const cfg = ctx.cfg.configuration const cfg = ctx.cfg.configuration

View File

@ -7,20 +7,25 @@ import { ProcessedContent, defaultProcessedContent } from "../vfile"
import { FullPageLayout } from "../../cfg" import { FullPageLayout } from "../../cfg"
import path from "path" import path from "path"
import { CanonicalSlug, FilePath, ServerSlug, canonicalizeServer, joinSegments } from "../../path" import { CanonicalSlug, FilePath, ServerSlug, canonicalizeServer, joinSegments } from "../../path"
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
import { FolderContent } from "../../components"
export const FolderPage: QuartzEmitterPlugin<FullPageLayout> = (opts) => { export const FolderPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => {
if (!opts) { const opts: FullPageLayout = {
throw new Error("ErrorPage must be initialized with options specifiying the components to use") ...sharedPageComponents,
...defaultListPageLayout,
pageBody: FolderContent(),
...userOpts,
} }
const { head: Head, header, beforeBody, pageBody: Content, left, right, footer: Footer } = opts const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
const Header = HeaderConstructor() const Header = HeaderConstructor()
const Body = BodyConstructor() const Body = BodyConstructor()
return { return {
name: "FolderPage", name: "FolderPage",
getQuartzComponents() { getQuartzComponents() {
return [Head, Header, Body, ...header, ...beforeBody, Content, ...left, ...right, Footer] return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
}, },
async emit(ctx, content, resources, emit): Promise<FilePath[]> { async emit(ctx, content, resources, emit): Promise<FilePath[]> {
const fps: FilePath[] = [] const fps: FilePath[] = []

View File

@ -12,20 +12,25 @@ import {
getAllSegmentPrefixes, getAllSegmentPrefixes,
joinSegments, joinSegments,
} from "../../path" } from "../../path"
import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
import { TagContent } from "../../components"
export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (opts) => { export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => {
if (!opts) { const opts: FullPageLayout = {
throw new Error("TagPage must be initialized with options specifiying the components to use") ...sharedPageComponents,
...defaultListPageLayout,
pageBody: TagContent(),
...userOpts,
} }
const { head: Head, header, beforeBody, pageBody: Content, left, right, footer: Footer } = opts const { head: Head, header, beforeBody, pageBody, left, right, footer: Footer } = opts
const Header = HeaderConstructor() const Header = HeaderConstructor()
const Body = BodyConstructor() const Body = BodyConstructor()
return { return {
name: "TagPage", name: "TagPage",
getQuartzComponents() { getQuartzComponents() {
return [Head, Header, Body, ...header, ...beforeBody, Content, ...left, ...right, Footer] return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
}, },
async emit(ctx, content, resources, emit): Promise<FilePath[]> { async emit(ctx, content, resources, emit): Promise<FilePath[]> {
const fps: FilePath[] = [] const fps: FilePath[] = []