mirror of
				https://github.com/ZetaKebab/quartz.git
				synced 2025-10-31 13:39:49 +00:00 
			
		
		
		
	perf: compute mapping of folder name to file data for faster breadcrumbs
This commit is contained in:
		| @@ -16,10 +16,10 @@ For example, here's what the default configuration looks like: | |||||||
|  |  | ||||||
| ```typescript title="quartz.layout.ts" | ```typescript title="quartz.layout.ts" | ||||||
| Component.Breadcrumbs({ | Component.Breadcrumbs({ | ||||||
|   spacerSymbol: ">", // symbol between crumbs |   spacerSymbol: "❯", // symbol between crumbs | ||||||
|   rootName: "Home", // name of first/root element |   rootName: "Home", // name of first/root element | ||||||
|   resolveFrontmatterTitle: false, // wether to resolve folder names through frontmatter titles (more computationally expensive) |   resolveFrontmatterTitle: true, // whether to resolve folder names through frontmatter titles | ||||||
|   hideOnRoot: true, // wether to hide breadcrumbs on root `index.md` page |   hideOnRoot: true, // whether to hide breadcrumbs on root `index.md` page | ||||||
| }) | }) | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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<BreadcrumbOptions>) => { | export default ((opts?: Partial<BreadcrumbOptions>) => { | ||||||
|   // Merge options with defaults |   // Merge options with defaults | ||||||
|   const options: BreadcrumbOptions = { ...defaultOptions, ...opts } |   const options: BreadcrumbOptions = { ...defaultOptions, ...opts } | ||||||
|  |  | ||||||
|  |   // computed index of folder name to its associated file data | ||||||
|  |   let folderIndex: Map<string, QuartzPluginData> | undefined | ||||||
|  |  | ||||||
|   function Breadcrumbs({ fileData, allFiles, displayClass }: QuartzComponentProps) { |   function Breadcrumbs({ fileData, allFiles, displayClass }: QuartzComponentProps) { | ||||||
|     // Hide crumbs on root if enabled |     // Hide crumbs on root if enabled | ||||||
|     if (options.hideOnRoot && fileData.slug === "index") { |     if (options.hideOnRoot && fileData.slug === "index") { | ||||||
| @@ -70,28 +58,39 @@ export default ((opts?: Partial<BreadcrumbOptions>) => { | |||||||
|     const firstEntry = formatCrumb(options.rootName, fileData.slug!, "/" as SimpleSlug) |     const firstEntry = formatCrumb(options.rootName, fileData.slug!, "/" as SimpleSlug) | ||||||
|     const crumbs: CrumbData[] = [firstEntry] |     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 |     // Split slug into hierarchy/parts | ||||||
|     const slugParts = fileData.slug?.split("/") |     const slugParts = fileData.slug?.split("/") | ||||||
|     if (slugParts) { |     if (slugParts) { | ||||||
|       // full path until current part |       // full path until current part | ||||||
|       let currentPath = "" |       let currentPath = "" | ||||||
|       for (let i = 0; i < slugParts.length - 1; i++) { |       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 |         // Try to resolve frontmatter folder title | ||||||
|         if (options?.resolveFrontmatterTitle) { |         const currentFile = folderIndex?.get(curPathSegment) | ||||||
|           // try to find file for current path |  | ||||||
|           const currentFile = findCurrentFile(allFiles, currentTitle) |  | ||||||
|         if (currentFile) { |         if (currentFile) { | ||||||
|             currentTitle = currentFile.frontmatter!.title |           curPathSegment = currentFile.frontmatter!.title | ||||||
|           } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Add current slug to full path |         // Add current slug to full path | ||||||
|         currentPath += slugParts[i] + "/" |         currentPath += slugParts[i] + "/" | ||||||
|  |  | ||||||
|         // Format and add current crumb |         // 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) |         crumbs.push(crumb) | ||||||
|       } |       } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jacky Zhao
					Jacky Zhao