From 1bfad5f0d028862cab06bb259e83eed6d1f9395e Mon Sep 17 00:00:00 2001 From: Anton Bulakh Date: Sun, 5 Jan 2025 01:22:08 +0200 Subject: [PATCH] fix(backlinks): Improve backlink perf and fix aliased backlinks Backlink calculation is quadratic, similar to breadcrumbs before the fix. Apply a similar fix here. Also added alias resolution, so this depends on `file.data.aliases` from #1681, but that can be commented out easily if needed. --- quartz/components/Backlinks.tsx | 40 ++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/quartz/components/Backlinks.tsx b/quartz/components/Backlinks.tsx index e99055e31b2e7..5301161d19a5b 100644 --- a/quartz/components/Backlinks.tsx +++ b/quartz/components/Backlinks.tsx @@ -1,6 +1,6 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/backlinks.scss" -import { resolveRelative, simplifySlug } from "../util/path" +import { FullSlug, resolveRelative, SimpleSlug, simplifySlug } from "../util/path" import { i18n } from "../i18n" import { classNames } from "../util/lang" @@ -15,14 +15,44 @@ const defaultOptions: BacklinksOptions = { export default ((opts?: Partial) => { const options: BacklinksOptions = { ...defaultOptions, ...opts } + let backlinks: Map> | undefined + const Backlinks: QuartzComponent = ({ fileData, allFiles, displayClass, cfg, }: QuartzComponentProps) => { - const slug = simplifySlug(fileData.slug!) - const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug)) + if (!backlinks) { + backlinks = new Map() + + const aliasMap = new Map() + for (const file of allFiles) { + for (const alias of file.aliases ?? []) { + aliasMap.set(simplifySlug(alias), simplifySlug(file.slug!)) + } + } + + for (const file of allFiles) { + const seen = new Set() + for (let link of file.links ?? []) { + link = aliasMap.get(link) ?? link + // avoid aliased duplicates + if (seen.has(link)) { + continue + } + seen.add(link) + let ref = backlinks.get(link) + if (!ref) { + backlinks.set(link, (ref = [])) + } + ref.push({ slug: file.slug!, title: file.frontmatter?.title! }) + } + } + } + + const backlinkFiles = backlinks.get(simplifySlug(fileData.slug!)) ?? [] + if (options.hideWhenEmpty && backlinkFiles.length == 0) { return null } @@ -33,8 +63,8 @@ export default ((opts?: Partial) => { {backlinkFiles.length > 0 ? ( backlinkFiles.map((f) => (
  • - - {f.frontmatter?.title} + + {f.title}
  • ))