make layouts simpler to think about
1 files added
7 files modified
| | |
| | | |
| | | 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 |
| | | export type QuartzTransformerPluginInstance = { |
| | | name: string |
| | | textTransform?: (src: string | Buffer) => string | Buffer |
| | | markdownPlugins?: () => PluggableList |
| | | htmlPlugins?: () => PluggableList |
| | | externalResources?: () => Partial<StaticResources> |
| | | } |
| | | ``` |
| | | ## Transformers |
| | | |
| | | ## Filters |
| | | |
| | |
| | | ] |
| | | ``` |
| | | |
| | | If you'd like to make your own plugins, read the guide on [[making plugins]] for more information. |
| | | |
| | | ### 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 |
| | |
| | | |
| | | - images in same folder are broken on shortest path mode |
| | | - 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 |
| | | - note/header/block transcludes: https://help.obsidian.md/Linking+notes+and+files/Embedding+files |
| | | |
| | |
| | | import { GlobalConfiguration, PageLayout, QuartzConfig } from "./quartz/cfg" |
| | | import * as Component from "./quartz/components" |
| | | import { QuartzConfig } from "./quartz/cfg" |
| | | import * as Plugin from "./quartz/plugins" |
| | | |
| | | const generalConfiguration: GlobalConfiguration = { |
| | | const config: QuartzConfig = { |
| | | configuration: { |
| | | pageTitle: "🪴 Quartz 4.0", |
| | | enableSPA: true, |
| | | enablePopovers: true, |
| | |
| | | }, |
| | | }, |
| | | }, |
| | | } |
| | | |
| | | 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 = { |
| | | configuration: generalConfiguration, |
| | | plugins: { |
| | | transformers: [ |
| | | Plugin.FrontMatter(), |
| | |
| | | emitters: [ |
| | | Plugin.AliasRedirects(), |
| | | Plugin.ComponentResources({ fontOrigin: "googleFonts" }), |
| | | Plugin.ContentPage({ |
| | | ...sharedPageComponents, |
| | | ...contentPageLayout, |
| | | pageBody: Component.Content(), |
| | | }), |
| | | Plugin.FolderPage({ |
| | | ...sharedPageComponents, |
| | | ...listPageLayout, |
| | | pageBody: Component.FolderContent(), |
| | | }), |
| | | Plugin.TagPage({ |
| | | ...sharedPageComponents, |
| | | ...listPageLayout, |
| | | pageBody: Component.TagContent(), |
| | | }), |
| | | Plugin.ContentPage(), |
| | | Plugin.FolderPage(), |
| | | Plugin.TagPage(), |
| | | Plugin.ContentIndex({ |
| | | enableSiteMap: true, |
| | | enableRSS: true, |
| New file |
| | |
| | | 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: [], |
| | | } |
| | |
| | | import { pageResources, renderPage } from "../../components/renderPage" |
| | | import { FullPageLayout } from "../../cfg" |
| | | import { FilePath, canonicalizeServer } from "../../path" |
| | | import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout" |
| | | import { Content } from "../../components" |
| | | |
| | | export const ContentPage: QuartzEmitterPlugin<FullPageLayout> = (opts) => { |
| | | if (!opts) { |
| | | throw new Error( |
| | | "ContentPage must be initialized with options specifiying the components to use", |
| | | ) |
| | | export const ContentPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOpts) => { |
| | | const opts: FullPageLayout = { |
| | | ...sharedPageComponents, |
| | | ...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 Body = BodyConstructor() |
| | | |
| | | return { |
| | | name: "ContentPage", |
| | | 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[]> { |
| | | const cfg = ctx.cfg.configuration |
| | |
| | | import { FullPageLayout } from "../../cfg" |
| | | import path 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) => { |
| | | if (!opts) { |
| | | throw new Error("ErrorPage must be initialized with options specifiying the components to use") |
| | | export const FolderPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => { |
| | | const opts: FullPageLayout = { |
| | | ...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 Body = BodyConstructor() |
| | | |
| | | return { |
| | | name: "FolderPage", |
| | | 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[]> { |
| | | const fps: FilePath[] = [] |
| | |
| | | getAllSegmentPrefixes, |
| | | joinSegments, |
| | | } from "../../path" |
| | | import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout" |
| | | import { TagContent } from "../../components" |
| | | |
| | | export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (opts) => { |
| | | if (!opts) { |
| | | throw new Error("TagPage must be initialized with options specifiying the components to use") |
| | | export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => { |
| | | const opts: FullPageLayout = { |
| | | ...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 Body = BodyConstructor() |
| | | |
| | | return { |
| | | name: "TagPage", |
| | | 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[]> { |
| | | const fps: FilePath[] = [] |