From 1e357ef5ac85ab55ad19f832513f5ca7a7e54a52 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 21 Oct 2023 20:09:49 -0700 Subject: [PATCH 1/6] fix(style): prioritize base and custom scss over component css --- quartz/plugins/emitters/componentResources.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quartz/plugins/emitters/componentResources.ts b/quartz/plugins/emitters/componentResources.ts index 5cb34804f..116e4e3e0 100644 --- a/quartz/plugins/emitters/componentResources.ts +++ b/quartz/plugins/emitters/componentResources.ts @@ -164,7 +164,7 @@ export const ComponentResources: QuartzEmitterPlugin = (opts?: Partial< addGlobalPageResources(ctx, resources, componentResources) - const stylesheet = joinStyles(ctx.cfg.configuration.theme, styles, ...componentResources.css) + const stylesheet = joinStyles(ctx.cfg.configuration.theme, ...componentResources.css, styles) const prescript = joinScripts(componentResources.beforeDOMLoaded) const postscript = joinScripts(componentResources.afterDOMLoaded) const fps = await Promise.all([ From dc834015d02adcc7edb119fb5224a2a86c614142 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 21 Oct 2023 20:27:49 -0700 Subject: [PATCH 2/6] fix(style): tag float orientation for long tags on page listing --- quartz/components/TagList.tsx | 8 +++++--- quartz/components/styles/listPage.scss | 5 ----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx index c763b14ba..e39186e5f 100644 --- a/quartz/components/TagList.tsx +++ b/quartz/components/TagList.tsx @@ -28,11 +28,13 @@ function TagList({ fileData, displayClass }: QuartzComponentProps) { TagList.css = ` .tags { list-style: none; - display:flex; - flex-wrap: wrap; + display: flex; padding-left: 0; gap: 0.4rem; margin: 1rem 0; + flex-wrap: wrap; + justify-content: flex-end; + justify-self: end; } .tags > li { @@ -42,7 +44,7 @@ TagList.css = ` overflow-wrap: normal; } -a.tag-link { +a.internal.tag-link { border-radius: 8px; background-color: var(--highlight); padding: 0.2rem 0.4rem; diff --git a/quartz/components/styles/listPage.scss b/quartz/components/styles/listPage.scss index 7105a1e86..c8fc9e957 100644 --- a/quartz/components/styles/listPage.scss +++ b/quartz/components/styles/listPage.scss @@ -19,11 +19,6 @@ li.section-li { } } - & > .tags { - justify-self: end; - margin-left: 1rem; - } - & > .desc > h3 > a { background-color: transparent; } From 60b3bc34cb07b5bec87cbd667ea9f804ff14cf3c Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 21 Oct 2023 21:05:46 -0700 Subject: [PATCH 3/6] fix: catch html to jsx errors (closes #547) --- docs/advanced/making plugins.md | 2 +- quartz/components/TagList.tsx | 5 ++++- quartz/components/pages/Content.tsx | 8 +++----- quartz/components/pages/FolderContent.tsx | 6 ++---- quartz/components/pages/TagContent.tsx | 6 ++---- quartz/util/jsx.ts | 15 +++++++++++++++ quartz/util/trace.ts | 8 ++------ 7 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 quartz/util/jsx.ts diff --git a/docs/advanced/making plugins.md b/docs/advanced/making plugins.md index 1f1616f42..d0934ad81 100644 --- a/docs/advanced/making plugins.md +++ b/docs/advanced/making plugins.md @@ -247,7 +247,7 @@ If you are creating an emitter plugin that needs to render components, there are - Your component should use `getQuartzComponents` to declare a list of `QuartzComponents` that it uses to construct the page. See the page on [[creating components]] for more information. - You can use the `renderPage` function defined in `quartz/components/renderPage.tsx` to render Quartz components into HTML. -- If you need to render an HTML AST to JSX, you can use the `toJsxRuntime` function from `hast-util-to-jsx-runtime` library. An example of this can be found in `quartz/components/pages/Content.tsx`. +- If you need to render an HTML AST to JSX, you can use the `htmlToJsx` function from `quartz/util/jsx.ts`. An example of this can be found in `quartz/components/pages/Content.tsx`. For example, the following is a simplified version of the content page plugin that renders every single page. diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx index e39186e5f..cb1c121cf 100644 --- a/quartz/components/TagList.tsx +++ b/quartz/components/TagList.tsx @@ -33,9 +33,12 @@ TagList.css = ` gap: 0.4rem; margin: 1rem 0; flex-wrap: wrap; - justify-content: flex-end; justify-self: end; } + +.section-ul .tags { + justify-content: flex-end; +} .tags > li { display: inline-block; diff --git a/quartz/components/pages/Content.tsx b/quartz/components/pages/Content.tsx index 7490a7ea7..76cecc38c 100644 --- a/quartz/components/pages/Content.tsx +++ b/quartz/components/pages/Content.tsx @@ -1,10 +1,8 @@ +import { htmlToJsx } from "../../util/jsx" import { QuartzComponentConstructor, QuartzComponentProps } from "../types" -import { Fragment, jsx, jsxs } from "preact/jsx-runtime" -import { toJsxRuntime } from "hast-util-to-jsx-runtime" -function Content({ tree }: QuartzComponentProps) { - // @ts-ignore (preact makes it angry) - const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" }) +function Content({ fileData, tree }: QuartzComponentProps) { + const content = htmlToJsx(fileData.filePath!, tree) return
{content}
} diff --git a/quartz/components/pages/FolderContent.tsx b/quartz/components/pages/FolderContent.tsx index a766d4b0b..765f84657 100644 --- a/quartz/components/pages/FolderContent.tsx +++ b/quartz/components/pages/FolderContent.tsx @@ -1,6 +1,4 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "../types" -import { Fragment, jsx, jsxs } from "preact/jsx-runtime" -import { toJsxRuntime } from "hast-util-to-jsx-runtime" import path from "path" import style from "../styles/listPage.scss" @@ -8,6 +6,7 @@ import { PageList } from "../PageList" import { _stripSlashes, simplifySlug } from "../../util/path" import { Root } from "hast" import { pluralize } from "../../util/lang" +import { htmlToJsx } from "../../util/jsx" function FolderContent(props: QuartzComponentProps) { const { tree, fileData, allFiles } = props @@ -29,8 +28,7 @@ function FolderContent(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) return (
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 4/6] 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 5/6] 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 6/6] 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,