| | |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "./types" |
| | | import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" |
| | | import breadcrumbsStyle from "./styles/breadcrumbs.scss" |
| | | import { FullSlug, SimpleSlug, resolveRelative } from "../util/path" |
| | | import { FullSlug, SimpleSlug, joinSegments, resolveRelative } from "../util/path" |
| | | import { QuartzPluginData } from "../plugins/vfile" |
| | | import { classNames } from "../util/lang" |
| | | |
| | |
| | | // computed index of folder name to its associated file data |
| | | let folderIndex: Map<string, QuartzPluginData> | undefined |
| | | |
| | | function Breadcrumbs({ fileData, allFiles, displayClass }: QuartzComponentProps) { |
| | | const Breadcrumbs: QuartzComponent = ({ |
| | | fileData, |
| | | allFiles, |
| | | displayClass, |
| | | }: QuartzComponentProps) => { |
| | | // Hide crumbs on root if enabled |
| | | if (options.hideOnRoot && fileData.slug === "index") { |
| | | return <></> |
| | |
| | | for (const file of allFiles) { |
| | | const folderParts = file.slug?.split("/") |
| | | if (folderParts?.at(-1) === "index") { |
| | | // 2nd last to exclude the /index |
| | | const folderName = folderParts?.at(-2) |
| | | if (folderName) { |
| | | folderIndex.set(folderName, file) |
| | | } |
| | | folderIndex.set(folderParts.slice(0, -1).join("/"), file) |
| | | } |
| | | } |
| | | } |
| | |
| | | // Split slug into hierarchy/parts |
| | | const slugParts = fileData.slug?.split("/") |
| | | if (slugParts) { |
| | | // is tag breadcrumb? |
| | | const isTagPath = slugParts[0] === "tags" |
| | | |
| | | // full path until current part |
| | | let currentPath = "" |
| | | |
| | | for (let i = 0; i < slugParts.length - 1; i++) { |
| | | let curPathSegment = slugParts[i] |
| | | |
| | | // Try to resolve frontmatter folder title |
| | | const currentFile = folderIndex?.get(curPathSegment) |
| | | const currentFile = folderIndex?.get(slugParts.slice(0, i + 1).join("/")) |
| | | if (currentFile) { |
| | | const title = currentFile.frontmatter!.title |
| | | if (title !== "index") { |
| | |
| | | } |
| | | |
| | | // Add current slug to full path |
| | | currentPath += slugParts[i] + "/" |
| | | currentPath = joinSegments(currentPath, slugParts[i]) |
| | | const includeTrailingSlash = !isTagPath || i < slugParts.length - 1 |
| | | |
| | | // Format and add current crumb |
| | | const crumb = formatCrumb(curPathSegment, fileData.slug!, currentPath as SimpleSlug) |
| | | const crumb = formatCrumb( |
| | | curPathSegment, |
| | | fileData.slug!, |
| | | (currentPath + (includeTrailingSlash ? "/" : "")) as SimpleSlug, |
| | | ) |
| | | crumbs.push(crumb) |
| | | } |
| | | |
| | |
| | | ) |
| | | } |
| | | Breadcrumbs.css = breadcrumbsStyle |
| | | |
| | | return Breadcrumbs |
| | | }) satisfies QuartzComponentConstructor |