From bc02791734aa969ff388c5f7068e402bd0e3862a Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 11 Nov 2023 20:27:51 -0800 Subject: [PATCH 1/5] fix: .date.getTime() based sort --- quartz/plugins/emitters/contentIndex.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/quartz/plugins/emitters/contentIndex.ts b/quartz/plugins/emitters/contentIndex.ts index 2c703685d61e5..c5170c64a09cc 100644 --- a/quartz/plugins/emitters/contentIndex.ts +++ b/quartz/plugins/emitters/contentIndex.ts @@ -6,7 +6,6 @@ import { FilePath, FullSlug, SimpleSlug, simplifySlug } from "../../util/path" import { QuartzEmitterPlugin } from "../types" import { toHtml } from "hast-util-to-html" import path from "path" -import { byDateAndAlphabetical } from "../../components/PageList" export type ContentIndex = Map export type ContentDetails = { @@ -60,7 +59,17 @@ function generateRSSFeed(cfg: GlobalConfiguration, idx: ContentIndex, limit?: nu ` const items = Array.from(idx) - .sort((a, b) => byDateAndAlphabetical(cfg)(a[1], b[1])) + .sort(([_, f1], [__, f2]) => { + if (f1.date && f2.date) { + return f2.date.getTime() - f1.date.getTime() + } else if (f1.date && !f2.date) { + return -1 + } else if (!f1.date && f2.date) { + return 1 + } + + return f1.title.localeCompare(f2.title) + }) .map(([slug, content]) => createURLEntry(simplifySlug(slug), content)) .slice(0, limit ?? idx.size) .join("") From 275bea3051a6f2a7da65fef6dccc7cc52a0a15e3 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 11 Nov 2023 20:46:29 -0800 Subject: [PATCH 2/5] style + cfg: resolve breadcrumb titles by default and change arrow character --- quartz/components/Breadcrumbs.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quartz/components/Breadcrumbs.tsx b/quartz/components/Breadcrumbs.tsx index 467b5a50360e5..f35f8766f1c44 100644 --- a/quartz/components/Breadcrumbs.tsx +++ b/quartz/components/Breadcrumbs.tsx @@ -28,9 +28,9 @@ interface BreadcrumbOptions { } const defaultOptions: BreadcrumbOptions = { - spacerSymbol: ">", + spacerSymbol: "❯", rootName: "Home", - resolveFrontmatterTitle: false, + resolveFrontmatterTitle: true, hideOnRoot: true, } From d1551872ffeb08c34f59dc2042b43562c499b620 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 11 Nov 2023 20:46:57 -0800 Subject: [PATCH 3/5] fix: check if popover exists after fetching and before inserting --- quartz/components/scripts/popover.inline.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/quartz/components/scripts/popover.inline.ts b/quartz/components/scripts/popover.inline.ts index ed3c925ce85c3..9506ec412bdfb 100644 --- a/quartz/components/scripts/popover.inline.ts +++ b/quartz/components/scripts/popover.inline.ts @@ -28,8 +28,11 @@ async function mouseEnterHandler( }) } + const hasAlreadyBeenFetched = () => + [...link.children].some((child) => child.classList.contains("popover")) + // dont refetch if there's already a popover - if ([...link.children].some((child) => child.classList.contains("popover"))) { + if (hasAlreadyBeenFetched()) { return setPosition(link.lastChild as HTMLElement) } @@ -49,6 +52,11 @@ async function mouseEnterHandler( console.error(err) }) + // bailout if another popover exists + if (hasAlreadyBeenFetched()) { + return + } + if (!contents) return const html = p.parseFromString(contents, "text/html") normalizeRelativeURLs(html, targetUrl) From 43d638a6de5a8a11c1a719c596b07ea957c7329a Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 11 Nov 2023 21:06:37 -0800 Subject: [PATCH 4/5] perf: compute mapping of folder name to file data for faster breadcrumbs --- docs/features/breadcrumbs.md | 6 ++-- quartz/components/Breadcrumbs.tsx | 47 +++++++++++++++---------------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/docs/features/breadcrumbs.md b/docs/features/breadcrumbs.md index 94db66ac04d51..20c3b8d65605c 100644 --- a/docs/features/breadcrumbs.md +++ b/docs/features/breadcrumbs.md @@ -16,10 +16,10 @@ For example, here's what the default configuration looks like: ```typescript title="quartz.layout.ts" Component.Breadcrumbs({ - spacerSymbol: ">", // symbol between crumbs + spacerSymbol: "❯", // symbol between crumbs rootName: "Home", // name of first/root element - resolveFrontmatterTitle: false, // wether to resolve folder names through frontmatter titles (more computationally expensive) - hideOnRoot: true, // wether to hide breadcrumbs on root `index.md` page + resolveFrontmatterTitle: true, // whether to resolve folder names through frontmatter titles + hideOnRoot: true, // whether to hide breadcrumbs on root `index.md` page }) ``` diff --git a/quartz/components/Breadcrumbs.tsx b/quartz/components/Breadcrumbs.tsx index f35f8766f1c44..29c73a81b58b1 100644 --- a/quartz/components/Breadcrumbs.tsx +++ b/quartz/components/Breadcrumbs.tsx @@ -41,25 +41,13 @@ function formatCrumb(displayName: string, baseSlug: FullSlug, currentSlug: Simpl } } -// given a folderName (e.g. "features"), search for the corresponding `index.md` file -function findCurrentFile(allFiles: QuartzPluginData[], folderName: string) { - return allFiles.find((file) => { - if (file.slug?.endsWith("index")) { - const folderParts = file.filePath?.split("/") - if (folderParts) { - const name = folderParts[folderParts?.length - 2] - if (name === folderName) { - return true - } - } - } - }) -} - export default ((opts?: Partial) => { // Merge options with defaults const options: BreadcrumbOptions = { ...defaultOptions, ...opts } + // computed index of folder name to its associated file data + let folderIndex: Map | undefined + function Breadcrumbs({ fileData, allFiles, displayClass }: QuartzComponentProps) { // Hide crumbs on root if enabled if (options.hideOnRoot && fileData.slug === "index") { @@ -70,28 +58,39 @@ export default ((opts?: Partial) => { const firstEntry = formatCrumb(options.rootName, fileData.slug!, "/" as SimpleSlug) const crumbs: CrumbData[] = [firstEntry] + if (!folderIndex && options.resolveFrontmatterTitle) { + folderIndex = new Map() + // construct the index for the first time + for (const file of allFiles) { + if (file.slug?.endsWith("index")) { + const folderParts = file.filePath?.split("/") + if (folderParts) { + const folderName = folderParts[folderParts?.length - 2] + folderIndex.set(folderName, file) + } + } + } + } + // Split slug into hierarchy/parts const slugParts = fileData.slug?.split("/") if (slugParts) { // full path until current part let currentPath = "" for (let i = 0; i < slugParts.length - 1; i++) { - let currentTitle = slugParts[i] + let curPathSegment = slugParts[i] - // TODO: performance optimizations/memoizing // Try to resolve frontmatter folder title - if (options?.resolveFrontmatterTitle) { - // try to find file for current path - const currentFile = findCurrentFile(allFiles, currentTitle) - if (currentFile) { - currentTitle = currentFile.frontmatter!.title - } + const currentFile = folderIndex?.get(curPathSegment) + if (currentFile) { + curPathSegment = currentFile.frontmatter!.title } + // Add current slug to full path currentPath += slugParts[i] + "/" // Format and add current crumb - const crumb = formatCrumb(currentTitle, fileData.slug!, currentPath as SimpleSlug) + const crumb = formatCrumb(curPathSegment, fileData.slug!, currentPath as SimpleSlug) crumbs.push(crumb) } From 74c63e448e28d9766f7ec631aac2645384b0975f Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sat, 11 Nov 2023 21:13:10 -0800 Subject: [PATCH 5/5] fix(style): dont internal-link highlight when image (closes #581) --- quartz/styles/base.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss index c72965659eab6..8bb8efb45877e 100644 --- a/quartz/styles/base.scss +++ b/quartz/styles/base.scss @@ -64,7 +64,7 @@ a { color: var(--tertiary) !important; } - &.internal { + &.internal:not(:has(img)) { text-decoration: none; background-color: var(--highlight); padding: 0 0.1rem;