From a7e20804f5fe68dff7b71f3065f60e2147d633ba Mon Sep 17 00:00:00 2001 From: Sam Stokes Date: Mon, 4 Dec 2023 18:18:47 -0800 Subject: [PATCH 01/18] feat: Support space-delimited tags in `FrontMatter` transformer (#620) --- quartz/plugins/transformers/frontmatter.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quartz/plugins/transformers/frontmatter.ts b/quartz/plugins/transformers/frontmatter.ts index 04b1105c3..017d3d1f1 100644 --- a/quartz/plugins/transformers/frontmatter.ts +++ b/quartz/plugins/transformers/frontmatter.ts @@ -8,11 +8,13 @@ import { slugTag } from "../../util/path" export interface Options { delims: string | string[] language: "yaml" | "toml" + oneLineTagDelim: string } const defaultOptions: Options = { delims: "---", language: "yaml", + oneLineTagDelim: ",", } export const FrontMatter: QuartzTransformerPlugin | undefined> = (userOpts) => { @@ -20,6 +22,8 @@ export const FrontMatter: QuartzTransformerPlugin | undefined> return { name: "FrontMatter", markdownPlugins() { + const { oneLineTagDelim } = opts + return [ [remarkFrontmatter, ["yaml", "toml"]], () => { @@ -45,7 +49,7 @@ export const FrontMatter: QuartzTransformerPlugin | undefined> if (data.tags && !Array.isArray(data.tags)) { data.tags = data.tags .toString() - .split(",") + .split(oneLineTagDelim) .map((tag: string) => tag.trim()) } From 2c69b0c97d40f76363d20478cb799ce4b7518e56 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 8 Dec 2023 16:55:40 -0800 Subject: [PATCH 02/18] fix: frontmatter coercion (empty string is falsy) --- quartz/plugins/transformers/frontmatter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quartz/plugins/transformers/frontmatter.ts b/quartz/plugins/transformers/frontmatter.ts index 017d3d1f1..6498a070c 100644 --- a/quartz/plugins/transformers/frontmatter.ts +++ b/quartz/plugins/transformers/frontmatter.ts @@ -37,16 +37,16 @@ export const FrontMatter: QuartzTransformerPlugin | undefined> }) // tag is an alias for tags - if (data.tag) { - data.tags = data.tag + if (data.tag !== null) { + data.tags = data.tag.toString() } // coerce title to string - if (data.title) { + if (data.title !== null) { data.title = data.title.toString() } - if (data.tags && !Array.isArray(data.tags)) { + if (data.tags !== null && !Array.isArray(data.tags)) { data.tags = data.tags .toString() .split(oneLineTagDelim) From c6546903f28cf49c573857c620aecc57562c34da Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 10 Dec 2023 06:19:29 -0800 Subject: [PATCH 03/18] fix: reland string coercion in title --- quartz/plugins/transformers/frontmatter.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/quartz/plugins/transformers/frontmatter.ts b/quartz/plugins/transformers/frontmatter.ts index 6498a070c..22b1cc6ec 100644 --- a/quartz/plugins/transformers/frontmatter.ts +++ b/quartz/plugins/transformers/frontmatter.ts @@ -4,6 +4,7 @@ import { QuartzTransformerPlugin } from "../types" import yaml from "js-yaml" import toml from "toml" import { slugTag } from "../../util/path" +import { QuartzPluginData } from "../vfile" export interface Options { delims: string | string[] @@ -37,16 +38,18 @@ export const FrontMatter: QuartzTransformerPlugin | undefined> }) // tag is an alias for tags - if (data.tag !== null) { - data.tags = data.tag.toString() + if (data.tag) { + data.tags = data.tag } // coerce title to string - if (data.title !== null) { + if (data.title) { data.title = data.title.toString() + } else if (data.title === null || data.title === undefined) { + data.title = file.stem ?? "Untitled" } - if (data.tags !== null && !Array.isArray(data.tags)) { + if (data.tags && !Array.isArray(data.tags)) { data.tags = data.tags .toString() .split(oneLineTagDelim) @@ -57,11 +60,7 @@ export const FrontMatter: QuartzTransformerPlugin | undefined> data.tags = [...new Set(data.tags?.map((tag: string) => slugTag(tag)))] ?? [] // fill in frontmatter - file.data.frontmatter = { - title: file.stem ?? "Untitled", - tags: [], - ...data, - } + file.data.frontmatter = data as QuartzPluginData["frontmatter"] } }, ] From 1b92440009965853241d6db44ae233cf62522a75 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Mon, 11 Dec 2023 10:38:55 -0800 Subject: [PATCH 04/18] fix: better error handling on spawnsync failures --- content/.gitkeep | 0 quartz/cli/handlers.js | 34 +++++++++++++++++++++++++++++----- quartz/cli/helpers.js | 4 +++- 3 files changed, 32 insertions(+), 6 deletions(-) delete mode 100644 content/.gitkeep diff --git a/content/.gitkeep b/content/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/quartz/cli/handlers.js b/quartz/cli/handlers.js index 7a83c5d8f..8fd09129c 100644 --- a/quartz/cli/handlers.js +++ b/quartz/cli/handlers.js @@ -443,11 +443,23 @@ export async function handleUpdate(argv) { console.log( "Pulling updates... you may need to resolve some `git` conflicts if you've made changes to components or plugins.", ) - gitPull(UPSTREAM_NAME, QUARTZ_SOURCE_BRANCH) + + try { + gitPull(UPSTREAM_NAME, QUARTZ_SOURCE_BRANCH) + } catch { + console.log(chalk.red("An error occured above while pulling updates.")) + await popContentFolder(contentFolder) + return + } + await popContentFolder(contentFolder) console.log("Ensuring dependencies are up to date") - spawnSync("npm", ["i"], { stdio: "inherit" }) - console.log(chalk.green("Done!")) + const res = spawnSync("npm", ["i"], { stdio: "inherit" }) + if (res.status === 0) { + console.log(chalk.green("Done!")) + } else { + console.log(chalk.red("An error occurred above while installing dependencies.")) + } } /** @@ -504,13 +516,25 @@ export async function handleSync(argv) { console.log( "Pulling updates from your repository. You may need to resolve some `git` conflicts if you've made changes to components or plugins.", ) - gitPull(ORIGIN_NAME, QUARTZ_SOURCE_BRANCH) + try { + gitPull(ORIGIN_NAME, QUARTZ_SOURCE_BRANCH) + } catch { + console.log(chalk.red("An error occured above while pulling updates.")) + await popContentFolder(contentFolder) + return + } } await popContentFolder(contentFolder) if (argv.push) { console.log("Pushing your changes") - spawnSync("git", ["push", "-f", ORIGIN_NAME, QUARTZ_SOURCE_BRANCH], { stdio: "inherit" }) + const res = spawnSync("git", ["push", "-f", ORIGIN_NAME, QUARTZ_SOURCE_BRANCH], { + stdio: "inherit", + }) + if (res.status !== 0) { + console.log(chalk.red(`An error occurred above while pushing to remote ${ORIGIN_NAME}.`)) + return + } } console.log(chalk.green("Done!")) diff --git a/quartz/cli/helpers.js b/quartz/cli/helpers.js index b07d19e3c..702a1b71d 100644 --- a/quartz/cli/helpers.js +++ b/quartz/cli/helpers.js @@ -36,7 +36,9 @@ export function gitPull(origin, branch) { const flags = ["--no-rebase", "--autostash", "-s", "recursive", "-X", "ours", "--no-edit"] const out = spawnSync("git", ["pull", ...flags, origin, branch], { stdio: "inherit" }) if (out.stderr) { - throw new Error(`Error while pulling updates: ${out.stderr}`) + throw new Error(chalk.red(`Error while pulling updates: ${out.stderr}`)) + } else if (out.status !== 0) { + throw new Error(chalk.red("Error while pulling updates")) } } From e6b5ca33c97575a43480fa00b17362ec43dc0313 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Mon, 11 Dec 2023 15:34:21 -0800 Subject: [PATCH 05/18] re-add gitkeep to content --- content/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 content/.gitkeep diff --git a/content/.gitkeep b/content/.gitkeep new file mode 100644 index 000000000..e69de29bb From 4442847b37e6532742e246fedb43fd3d60384545 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Dec 2023 16:07:44 -0800 Subject: [PATCH 06/18] fix: internal link selector specificity --- quartz/styles/base.scss | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss index 2e5edec15..d559435ac 100644 --- a/quartz/styles/base.scss +++ b/quartz/styles/base.scss @@ -64,11 +64,17 @@ a { color: var(--tertiary) !important; } - &.internal:not(:has(> img)) { + &.internal { text-decoration: none; background-color: var(--highlight); padding: 0 0.1rem; border-radius: 5px; + + &:has(> img) { + background-color: none; + border-radius: 0; + padding: 0; + } } } From 66e297c0eacca69da7b88be2a1377e8c1aba6720 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Dec 2023 16:40:24 -0800 Subject: [PATCH 07/18] css: make article no longer relative to prevent z-fighting --- quartz/styles/base.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss index d559435ac..09ce2069b 100644 --- a/quartz/styles/base.scss +++ b/quartz/styles/base.scss @@ -100,7 +100,6 @@ a { } & article { - position: relative; & > h1 { font-size: 2rem; From a464ae50290b9221fa3f1ce8653c62edfc0091f7 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Wed, 13 Dec 2023 16:47:22 -0800 Subject: [PATCH 08/18] fix: format --- quartz/styles/base.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss index 09ce2069b..f65ab4511 100644 --- a/quartz/styles/base.scss +++ b/quartz/styles/base.scss @@ -100,7 +100,6 @@ a { } & article { - & > h1 { font-size: 2rem; } From c35818c336e64e43c54766a670e03cd165b59503 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Thu, 14 Dec 2023 16:48:09 -0800 Subject: [PATCH 09/18] fix: set upstream in sync handler, cleanup docs around setting up github --- docs/setting up your GitHub repository.md | 6 +++++- quartz/cli/handlers.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/setting up your GitHub repository.md b/docs/setting up your GitHub repository.md index 41655179d..ca67e85c9 100644 --- a/docs/setting up your GitHub repository.md +++ b/docs/setting up your GitHub repository.md @@ -12,10 +12,14 @@ At the top of your repository on GitHub.com's Quick Setup page, click the clipb ![[github-quick-setup.png]] -In your terminal of choice, navigate to the root of your Quartz folder. Then, run the following command, replacing `REMOTE-URL` with the URL you just copied from the previous step. +In your terminal of choice, navigate to the root of your Quartz folder. Then, run the following commands, replacing `REMOTE-URL` with the URL you just copied from the previous step. ```bash +# add your repository git remote add origin REMOTE-URL + +# track the main quartz repository for updates +git remote add upstream https://github.com/jackyzha0/quartz.git ``` To verify that you set the remote URL correctly, run the following command. diff --git a/quartz/cli/handlers.js b/quartz/cli/handlers.js index 8fd09129c..586881af9 100644 --- a/quartz/cli/handlers.js +++ b/quartz/cli/handlers.js @@ -528,7 +528,7 @@ export async function handleSync(argv) { await popContentFolder(contentFolder) if (argv.push) { console.log("Pushing your changes") - const res = spawnSync("git", ["push", "-f", ORIGIN_NAME, QUARTZ_SOURCE_BRANCH], { + const res = spawnSync("git", ["push", "-uf", ORIGIN_NAME, QUARTZ_SOURCE_BRANCH], { stdio: "inherit", }) if (res.status !== 0) { From ed9bd43d9f5e6eb29b86646a4df8d41a53ee316d Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Fri, 15 Dec 2023 12:18:29 -0800 Subject: [PATCH 10/18] docs: update showcase --- docs/showcase.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/showcase.md b/docs/showcase.md index a5ed89bc9..1e2ef56ae 100644 --- a/docs/showcase.md +++ b/docs/showcase.md @@ -6,9 +6,9 @@ Want to see what Quartz can do? Here are some cool community gardens: - [Quartz Documentation (this site!)](https://quartz.jzhao.xyz/) - [Jacky Zhao's Garden](https://jzhao.xyz/) +- [Socratica Toolbox](https://toolbox.socratica.info/) - [Brandon Boswell's Garden](https://brandonkboswell.com) - [Scaling Synthesis - A hypertext research notebook](https://scalingsynthesis.com/) -- [AWAGMI Intern Notes](https://notes.awagmi.xyz/) - [Data Dictionary 🧠](https://glossary.airbyte.com/) - [sspaeti.com's Second Brain](https://brain.sspaeti.com/) - [oldwinter の数字花园](https://garden.oldwinter.top/) From 3c01b92cc46589ac4607d994b49f1327dba3f38e Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 16 Dec 2023 11:04:18 -0800 Subject: [PATCH 11/18] docs: note embeds and update git hint --- docs/features/wikilinks.md | 8 ++++++++ docs/setting up your GitHub repository.md | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/docs/features/wikilinks.md b/docs/features/wikilinks.md index 50bbb1bb6..1b005327c 100644 --- a/docs/features/wikilinks.md +++ b/docs/features/wikilinks.md @@ -14,3 +14,11 @@ This is enabled as a part of [[Obsidian compatibility]] and can be configured an - `[[Path to file | Here's the title override]]`: produces a link to `Path to file.md` with the text `Here's the title override` - `[[Path to file#Anchor]]`: produces a link to the anchor `Anchor` in the file `Path to file.md` - `[[Path to file#^block-ref]]`: produces a link to the specific block `block-ref` in the file `Path to file.md` + +### Embeds + +- `![[Path to image]]`: embeds an image into the page +- `![[Path to image|100x145]]`: embeds an image into the page with dimensions 100px by 145px +- `![[Path to file]]`: transclude an entire page +- `![[Path to file#Anchor]]`: transclude everything under the header `Anchor` +- `![[Path to file#^b15695]]`: transclude block with ID `^b15695` diff --git a/docs/setting up your GitHub repository.md b/docs/setting up your GitHub repository.md index ca67e85c9..9d42d199b 100644 --- a/docs/setting up your GitHub repository.md +++ b/docs/setting up your GitHub repository.md @@ -33,3 +33,7 @@ Then, you can sync the content to upload it to your repository. ```bash npx quartz sync ``` + +> [!hint] +> If `npx quartz sync` fails with `fatal: --[no-]autostash option is only valid with --rebase`, you +> may have an outdated version of `git`. Updating `git` should fix this issue. From 14e6b13ff1f087e13e34aa150023a308d47d01b1 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 09:57:46 -0800 Subject: [PATCH 12/18] docs: dont pull on first sync --- docs/setting up your GitHub repository.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setting up your GitHub repository.md b/docs/setting up your GitHub repository.md index 9d42d199b..1b5461b51 100644 --- a/docs/setting up your GitHub repository.md +++ b/docs/setting up your GitHub repository.md @@ -31,7 +31,7 @@ git remote -v Then, you can sync the content to upload it to your repository. ```bash -npx quartz sync +npx quartz sync --no-pull ``` > [!hint] From 972cf0a887fcafa92bd317dd990ea57f2a4d054d Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 12:27:19 -0800 Subject: [PATCH 13/18] feat: support emoji tags (closes #634) --- quartz/plugins/transformers/ofm.ts | 7 ++++--- quartz/util/path.ts | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index 4c6a6dbed..b6d158c71 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -121,9 +121,9 @@ const calloutRegex = new RegExp(/^\[\!(\w+)\]([+-]?)/) const calloutLineRegex = new RegExp(/^> *\[\!\w+\][+-]?.*$/, "gm") // (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line // #(...) -> capturing group, tag itself must start with # -// (?:[-_\p{L}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters, hyphens and/or underscores -// (?:\/[-_\p{L}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" -const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d])+(?:\/[-_\p{L}\d]+)*)/, "gu") +// (?:[-_\p{L}\d\p{Z}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters and symbols, hyphens and/or underscores +// (?:\/[-_\p{L}\d\p{Z}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" +const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d\p{Z}])+(?:\/[-_\p{L}\d\p{Z}]+)*)/, "gu") const blockReferenceRegex = new RegExp(/\^([A-Za-z0-9]+)$/, "g") export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin | undefined> = ( @@ -405,6 +405,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin if (/^\d+$/.test(tag)) { return false } + tag = slugTag(tag) if (file.data.frontmatter && !file.data.frontmatter.tags.includes(tag)) { file.data.frontmatter.tags.push(tag) diff --git a/quartz/util/path.ts b/quartz/util/path.ts index 5cf54b803..92cfabe49 100644 --- a/quartz/util/path.ts +++ b/quartz/util/path.ts @@ -1,4 +1,4 @@ -import { slug } from "github-slugger" +import { slug as slugAnchor } from "github-slugger" import type { Element as HastElement } from "hast" // this file must be isomorphic so it can't use node libs (e.g. path) @@ -43,6 +43,14 @@ export function getFullSlug(window: Window): FullSlug { return res } +function sluggify(s: string): string { + return s + .split("/") + .map((segment) => segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q")) // slugify all segments + .join("/") // always use / as sep + .replace(/\/$/, "") +} + export function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug { fp = _stripSlashes(fp) as FilePath let ext = _getFileExtension(fp) @@ -51,11 +59,7 @@ export function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug { ext = "" } - let slug = withoutFileExt - .split("/") - .map((segment) => segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q")) // slugify all segments - .join("/") // always use / as sep - .replace(/\/$/, "") // remove trailing slash + let slug = sluggify(withoutFileExt) // treat _index as index if (_endsWith(slug, "_index")) { @@ -156,14 +160,10 @@ export function splitAnchor(link: string): [string, string] { return [fp, anchor] } -export function slugAnchor(anchor: string) { - return slug(anchor) -} - export function slugTag(tag: string) { return tag .split("/") - .map((tagSegment) => slug(tagSegment)) + .map((tagSegment) => sluggify(tagSegment)) .join("/") } From d979331dc781e92296166e50512c4aebd7aa66a5 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 12:54:52 -0800 Subject: [PATCH 14/18] fix: remove whitespace unicode from tag regex --- quartz/plugins/transformers/ofm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index b6d158c71..c1bec16af 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -123,7 +123,7 @@ const calloutLineRegex = new RegExp(/^> *\[\!\w+\][+-]?.*$/, "gm") // #(...) -> capturing group, tag itself must start with # // (?:[-_\p{L}\d\p{Z}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters and symbols, hyphens and/or underscores // (?:\/[-_\p{L}\d\p{Z}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" -const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d\p{Z}])+(?:\/[-_\p{L}\d\p{Z}]+)*)/, "gu") +const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d])+(?:\/[-_\p{L}\d]+)*)/, "gu") const blockReferenceRegex = new RegExp(/\^([A-Za-z0-9]+)$/, "g") export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin | undefined> = ( From 150050f379402b052628c436623aa72b1fd54b8b Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 12:59:03 -0800 Subject: [PATCH 15/18] docs: agentic computing in quartz philosophy --- docs/philosophy.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/philosophy.md b/docs/philosophy.md index b8af845fb..af5510aac 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -8,7 +8,9 @@ title: Philosophy of Quartz > > _(The Garden and the Stream)_ -The problem with the file cabinet is that it focuses on efficiency of access and interoperability rather than generativity and creativity. Thinking is not linear, nor is it hierarchical. In fact, not many things are linear or hierarchical at all. Then why is it that most tools and thinking strategies assume a nice chronological or hierarchical order for my thought processes? The ideal tool for thought for me would embrace the messiness of my mind, and organically help insights emerge from chaos instead of forcing an artificial order. A rhizomatic, not arboresecent, form of note taking. +The problem with the file cabinet is that it focuses on efficiency of access and interoperability rather than generativity and creativity. Thinking is not linear, nor is it hierarchical. In fact, not many things are linear or hierarchical at all. Then why is it that most tools and thinking strategies assume a nice chronological or hierarchical order for my thought processes? + +The ideal tool for thought for me would embrace the messiness of my mind, and organically help insights emerge from chaos instead of forcing an artificial order. A rhizomatic, not arboresecent, form of note taking. My goal with a digital garden is not purely as an organizing system and information store (though it works nicely for that). I want my digital garden to be a playground for new ways ideas can connect together. As a result, existing formal organizing systems like Zettelkasten or the hierarchical folder structures of Notion don’t work well for me. There is way too much upfront friction that by the time I’ve thought about how to organize my thought into folders categories, I’ve lost it. @@ -25,4 +27,21 @@ Quartz is designed first and foremost as a tool for publishing [digital gardens] > “[One] who works with the door open gets all kinds of interruptions, but [they] also occasionally gets clues as to what the world is and what might be important.” > — Richard Hamming -**The goal of Quartz is to make sharing your digital garden free and simple.** At its core, Quartz is designed to be easy to use enough for non-technical people to get going but also powerful enough that senior developers can tweak it to work how they'd like it to work. +**The goal of Quartz is to make sharing your digital garden free and simple.** + +--- + +## A garden should be your own + +At its core, Quartz is designed to be easy to use enough for non-technical people to get going but also powerful enough that senior developers can tweak it to work how they'd like it to work. + +1. If you like the default configuration of Quartz and just want to change the content, the only thing that you need to change is the contents of the `content` folder. +2. If you'd like to make basic configuration tweaks but don't want to edit source code, one can tweak the plugins and components in `quartz.config.ts` and `quartz.layout.ts` in a guided manner to their liking. +3. If you'd like to tweak the actual source code of the underlying plugins, components, or even build process, Quartz purposefully ships its full source code to the end user to allow customization at this level too. + +Most software either confines you to either + +1. Makes it easy to tweak content but not the presentation +2. Gives you too many knobs to tune the presentation without good opinionated defaults + +**Quartz should feel powerful but ultimately be an intuitive tool fully within your control.** It should be a piece of [agentic software](https://jzhao.xyz/posts/agentic-computing). Ultimately, it should have the right affordances to nudge users towards good defaults but never dictate what the 'correct' way of using it is. From ad1f964a5f6e290d61979a372de18ad77e24351c Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 13:19:03 -0800 Subject: [PATCH 16/18] docs: graph view tag options --- docs/features/graph view.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/features/graph view.md b/docs/features/graph view.md index c7ddb03e0..4f905c78d 100644 --- a/docs/features/graph view.md +++ b/docs/features/graph view.md @@ -34,6 +34,8 @@ Component.Graph({ linkDistance: 30, // how long should the links be by default? fontSize: 0.6, // what size should the node labels be? opacityScale: 1, // how quickly do we fade out the labels when zooming out? + removeTags: [], // what tags to remove from the graph + showTags: true, // whether to show tags in the graph }, globalGraph: { drag: true, @@ -45,6 +47,8 @@ Component.Graph({ linkDistance: 30, fontSize: 0.6, opacityScale: 1, + removeTags: [], // what tags to remove from the graph + showTags: true, // whether to show tags in the graph }, }) ``` From d2be097b7698c2548915c386aab07ceb320855aa Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 15:09:51 -0800 Subject: [PATCH 17/18] feat: include tag hierarchies in tag listing, sort tag listing --- quartz/components/pages/TagContent.tsx | 6 +++++- quartz/plugins/emitters/tagPage.tsx | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/quartz/components/pages/TagContent.tsx b/quartz/components/pages/TagContent.tsx index a495af5c3..890755bbc 100644 --- a/quartz/components/pages/TagContent.tsx +++ b/quartz/components/pages/TagContent.tsx @@ -28,7 +28,11 @@ function TagContent(props: QuartzComponentProps) { : htmlToJsx(fileData.filePath!, tree) if (tag === "/") { - const tags = [...new Set(allFiles.flatMap((data) => data.frontmatter?.tags ?? []))] + const tags = [ + ...new Set( + allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes), + ), + ].sort((a, b) => a.localeCompare(b)) const tagItemMap: Map = new Map() for (const tag of tags) { tagItemMap.set(tag, allPagesWithTag(tag)) diff --git a/quartz/plugins/emitters/tagPage.tsx b/quartz/plugins/emitters/tagPage.tsx index ad5e1d649..566911983 100644 --- a/quartz/plugins/emitters/tagPage.tsx +++ b/quartz/plugins/emitters/tagPage.tsx @@ -40,6 +40,7 @@ export const TagPage: QuartzEmitterPlugin = (userOpts) => { const tags: Set = new Set( allFiles.flatMap((data) => data.frontmatter?.tags ?? []).flatMap(getAllSegmentPrefixes), ) + // add base tag tags.add("index") From 78b33fc2fb2d2b30e0cdf6fbd50c74efceac1c56 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 17 Dec 2023 16:46:17 -0800 Subject: [PATCH 18/18] fix: release build lock before client refresh --- quartz/build.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quartz/build.ts b/quartz/build.ts index 5752caa46..0ebc52928 100644 --- a/quartz/build.ts +++ b/quartz/build.ts @@ -152,10 +152,10 @@ async function startServing( console.log(chalk.yellow(`Rebuild failed. Waiting on a change to fix the error...`)) } + release() clientRefresh() toRebuild.clear() toRemove.clear() - release() } const watcher = chokidar.watch(".", {