make layouts simpler to think about
This commit is contained in:
parent
828a474fa9
commit
31e99c669a
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
135
quartz.config.ts
135
quartz.config.ts
@ -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
39
quartz.layout.ts
Normal 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: [],
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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[] = []
|
||||||
|
@ -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[] = []
|
||||||
|
Loading…
Reference in New Issue
Block a user