diff --git a/quartz/components/pages/TagContent.tsx b/quartz/components/pages/TagContent.tsx
index 9907e3fc3..205ba8958 100644
--- a/quartz/components/pages/TagContent.tsx
+++ b/quartz/components/pages/TagContent.tsx
@@ -1,12 +1,11 @@
import { QuartzComponentConstructor, QuartzComponentProps } from "../types"
-import { Fragment, jsx, jsxs } from "preact/jsx-runtime"
-import { toJsxRuntime } from "hast-util-to-jsx-runtime"
import style from "../styles/listPage.scss"
import { PageList } from "../PageList"
import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path"
import { QuartzPluginData } from "../../plugins/vfile"
import { Root } from "hast"
import { pluralize } from "../../util/lang"
+import { htmlToJsx } from "../../util/jsx"
const numPages = 10
function TagContent(props: QuartzComponentProps) {
@@ -26,8 +25,7 @@ function TagContent(props: QuartzComponentProps) {
const content =
(tree as Root).children.length === 0
? fileData.description
- : // @ts-ignore
- toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" })
+ : htmlToJsx(fileData.filePath!, tree)
if (tag === "") {
const tags = [...new Set(allFiles.flatMap((data) => data.frontmatter?.tags ?? []))]
diff --git a/quartz/util/jsx.ts b/quartz/util/jsx.ts
new file mode 100644
index 000000000..8cba485ab
--- /dev/null
+++ b/quartz/util/jsx.ts
@@ -0,0 +1,15 @@
+import { toJsxRuntime } from "hast-util-to-jsx-runtime"
+import { QuartzPluginData } from "../plugins/vfile"
+import { Node, Root } from "hast"
+import { Fragment, jsx, jsxs } from "preact/jsx-runtime"
+import { trace } from "./trace"
+import { type FilePath } from "./path"
+
+export function htmlToJsx(fp: FilePath, tree: Node
) {
+ try {
+ // @ts-ignore (preact makes it angry)
+ return toJsxRuntime(tree as Root, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" })
+ } catch (e) {
+ trace(`Failed to parse Markdown in \`${fp}\` into JSX`, e as Error)
+ }
+}
diff --git a/quartz/util/trace.ts b/quartz/util/trace.ts
index c7f3cc339..a33135d64 100644
--- a/quartz/util/trace.ts
+++ b/quartz/util/trace.ts
@@ -4,7 +4,7 @@ import { isMainThread } from "workerpool"
const rootFile = /.*at file:/
export function trace(msg: string, err: Error) {
- const stack = err.stack
+ let stack = err.stack ?? ""
const lines: string[] = []
@@ -12,15 +12,11 @@ export function trace(msg: string, err: Error) {
lines.push(
"\n" +
chalk.bgRed.black.bold(" ERROR ") +
- "\n" +
+ "\n\n" +
chalk.red(` ${msg}`) +
(err.message.length > 0 ? `: ${err.message}` : ""),
)
- if (!stack) {
- return
- }
-
let reachedEndOfLegibleTrace = false
for (const line of stack.split("\n").slice(1)) {
if (reachedEndOfLegibleTrace) {
From b7ae7a99dbd40ffc852642202031b29e98304c1f Mon Sep 17 00:00:00 2001
From: Jacky Zhao
Date: Sat, 21 Oct 2023 21:12:11 -0700
Subject: [PATCH 16/22] fix: styling for nested popover tag in page list
---
quartz/components/TagList.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx
index cb1c121cf..b39b19947 100644
--- a/quartz/components/TagList.tsx
+++ b/quartz/components/TagList.tsx
@@ -36,7 +36,7 @@ TagList.css = `
justify-self: end;
}
-.section-ul .tags {
+.section-li > .section > .tags {
justify-content: flex-end;
}
From 7c01e8dde06abb1a80118b5eddce3e238830ede0 Mon Sep 17 00:00:00 2001
From: Jacky Zhao
Date: Sun, 22 Oct 2023 09:54:12 -0700
Subject: [PATCH 17/22] feat: openLinksInNewTab option for link transformer
---
quartz/components/scripts/spa.inline.ts | 1 +
quartz/plugins/transformers/links.ts | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/quartz/components/scripts/spa.inline.ts b/quartz/components/scripts/spa.inline.ts
index fc5aa7400..31ae14fcb 100644
--- a/quartz/components/scripts/spa.inline.ts
+++ b/quartz/components/scripts/spa.inline.ts
@@ -20,6 +20,7 @@ const isLocalUrl = (href: string) => {
const getOpts = ({ target }: Event): { url: URL; scroll?: boolean } | undefined => {
if (!isElement(target)) return
+ if (target.attributes.getNamedItem("target")?.value === "_blank") return
const a = target.closest("a")
if (!a) return
if ("routerIgnore" in a.dataset) return
diff --git a/quartz/plugins/transformers/links.ts b/quartz/plugins/transformers/links.ts
index e050e00ad..8d16136f3 100644
--- a/quartz/plugins/transformers/links.ts
+++ b/quartz/plugins/transformers/links.ts
@@ -18,11 +18,13 @@ interface Options {
markdownLinkResolution: TransformOptions["strategy"]
/** Strips folders from a link so that it looks nice */
prettyLinks: boolean
+ openLinksInNewTab: boolean
}
const defaultOptions: Options = {
markdownLinkResolution: "absolute",
prettyLinks: true,
+ openLinksInNewTab: false,
}
export const CrawlLinks: QuartzTransformerPlugin | undefined> = (userOpts) => {
@@ -52,6 +54,10 @@ export const CrawlLinks: QuartzTransformerPlugin | undefined> =
node.properties.className ??= []
node.properties.className.push(isAbsoluteUrl(dest) ? "external" : "internal")
+ if (opts.openLinksInNewTab) {
+ node.properties.target = "_blank"
+ }
+
// don't process external links or intra-document anchors
const isInternal = !(isAbsoluteUrl(dest) || dest.startsWith("#"))
if (isInternal) {
From 01fc8e46409ee0fb7311f212726113d35aced82d Mon Sep 17 00:00:00 2001
From: Jacky Zhao
Date: Wed, 25 Oct 2023 09:40:43 -0700
Subject: [PATCH 18/22] fix: disable semi-broken flexsearch cache
---
quartz/components/scripts/search.inline.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/quartz/components/scripts/search.inline.ts b/quartz/components/scripts/search.inline.ts
index a1c3e6ca2..eff4eb1b9 100644
--- a/quartz/components/scripts/search.inline.ts
+++ b/quartz/components/scripts/search.inline.ts
@@ -303,7 +303,6 @@ document.addEventListener("nav", async (e: unknown) => {
// setup index if it hasn't been already
if (!index) {
index = new Document({
- cache: true,
charset: "latin:extra",
optimize: true,
encode: encoder,
From 06ccb89cd7d5a3cade1eb5c2155b9b06e5395b0b Mon Sep 17 00:00:00 2001
From: Blue Rose <134471273+bluerosegarden@users.noreply.github.com>
Date: Tue, 31 Oct 2023 15:53:49 -0500
Subject: [PATCH 19/22] docs: clarifications about globs (#559)
* Add note about fast-glob
* Add warning about non-markdown files
Also added a glob pattern to filter out all non-markdown files outside of a specified folder.
* run npm format
---------
Co-authored-by: wych
---
docs/features/private pages.md | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/docs/features/private pages.md b/docs/features/private pages.md
index 5c3940bc7..638c628b6 100644
--- a/docs/features/private pages.md
+++ b/docs/features/private pages.md
@@ -12,9 +12,17 @@ There may be some notes you want to avoid publishing as a website. Quartz suppor
If you'd like to only publish a select number of notes, you can instead use `Plugin.ExplicitPublish` which will filter out all notes except for any that have `publish: true` in the frontmatter.
+> [!warning]
+> Regardless of the filter plugin used, **all non-markdown files will be emitted and available publically in the final build.** This includes files such as images, voice recordings, PDFs, etc. One way to prevent this and still be able to embed local images is to create a folder specifically for public media and add the following two patterns to the ignorePatterns array.
+>
+> `"!(PublicMedia)**/!(*.md)", "!(*.md)"`
+
## `ignorePatterns`
-This is a field in `quartz.config.ts` under the main [[configuration]] which allows you to specify a list of patterns to effectively exclude from parsing all together. Any valid [glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) pattern works here.
+This is a field in `quartz.config.ts` under the main [[configuration]] which allows you to specify a list of patterns to effectively exclude from parsing all together. Any valid [fast-glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) pattern works here.
+
+> [!note]
+> Bash's glob syntax is slightly different from fast-glob's and using bash's syntax may lead to unexpected results.
Common examples include:
From 05a1c34c6f6973eebcbcc50f50b64c2a0d62e8fa Mon Sep 17 00:00:00 2001
From: Florence <59734957+Pydes-boop@users.noreply.github.com>
Date: Wed, 1 Nov 2023 17:57:32 +0100
Subject: [PATCH 20/22] docs: remove dead link (#561)
---
docs/showcase.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/docs/showcase.md b/docs/showcase.md
index 6814dd06d..3774fe3b6 100644
--- a/docs/showcase.md
+++ b/docs/showcase.md
@@ -9,7 +9,6 @@ Want to see what Quartz can do? Here are some cool community gardens:
- [Brandon Boswell's Garden](https://brandonkboswell.com)
- [Scaling Synthesis - A hypertext research notebook](https://scalingsynthesis.com/)
- [AWAGMI Intern Notes](https://notes.awagmi.xyz/)
-- [Course notes for Information Technology Advanced Theory](https://a2itnotes.github.io/quartz/)
- [Data Dictionary 🧠](https://glossary.airbyte.com/)
- [sspaeti.com's Second Brain](https://brain.sspaeti.com/)
- [oldwinter の数字花园](https://garden.oldwinter.top/)
From 923b72fb67cf3ee9842df630feaed72644470074 Mon Sep 17 00:00:00 2001
From: Jacky Zhao
Date: Wed, 1 Nov 2023 10:03:45 -0700
Subject: [PATCH 21/22] feat: auto-tag releases (closes #560)
---
.github/workflows/ci.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 8915143c4..9b1622cb8 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -45,3 +45,9 @@ jobs:
- name: Ensure Quartz builds, check bundle info
run: npx quartz build --bundleInfo
+
+ - name: Create release tag
+ uses: Klemensas/action-autotag@stable
+ with:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ tag_prefix: "v"
From a62a97c7abcabea4509760e5af957eed66fa0755 Mon Sep 17 00:00:00 2001
From: Emil Rofors
Date: Fri, 3 Nov 2023 16:40:43 -0700
Subject: [PATCH 22/22] docs: add GitLab pages CI (#549)
* add .gitlab-ci.yml
* move GitLab CI to hosting.md
* remove extra folder name
Co-authored-by: Jacky Zhao
* remove test from gitlab instructions
* run prettier
---------
Co-authored-by: Jacky Zhao
---
docs/hosting.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/docs/hosting.md b/docs/hosting.md
index 01d130fd3..a4ca1ea98 100644
--- a/docs/hosting.md
+++ b/docs/hosting.md
@@ -166,3 +166,56 @@ Using `docs.example.com` is an example of a subdomain. They're a simple way of c
3. Go to the [Vercel Dashboard](https://vercel.com/dashboard) and select your Quartz project.
4. Go to the Settings tab and then click Domains in the sidebar
5. Enter your subdomain into the field and press Add
+
+## GitLab Pages
+
+You can configure GitLab CI to build and deploy a Quartz 4 project.
+
+In your local Quartz, create a new file `.gitlab-ci.yaml`.
+
+```yaml title=".gitlab-ci.yaml"
+stages:
+ - build
+ - deploy
+
+variables:
+ NODE_VERSION: "18.14"
+
+build:
+ stage: build
+ rules:
+ - if: '$CI_COMMIT_REF_NAME == "v4"'
+ before_script:
+ - apt-get update -q && apt-get install -y nodejs npm
+ - npm install -g n
+ - n $NODE_VERSION
+ - hash -r
+ - npm ci
+ script:
+ - npx prettier --write .
+ - npm run check
+ - npx quartz build
+ artifacts:
+ paths:
+ - public
+ cache:
+ paths:
+ - ~/.npm/
+ key: "${CI_COMMIT_REF_SLUG}-node-${CI_COMMIT_REF_NAME}"
+ tags:
+ - docker
+
+pages:
+ stage: deploy
+ rules:
+ - if: '$CI_COMMIT_REF_NAME == "v4"'
+ script:
+ - echo "Deploying to GitLab Pages..."
+ artifacts:
+ paths:
+ - public
+```
+
+When `.gitlab-ci.yaml` is commited, GitLab will build and deploy the website as a GitLab Page. You can find the url under `Deploy` -> `Pages` in the sidebar.
+
+By default, the page is private and only visible when logged in to a GitLab account with access to the repository but can be opened in the settings under `Deploy` -> `Pages`.