feat(breadcrumb): add optional path-style

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
Aaron Pham 2024-08-03 02:11:58 -04:00
parent bf1c9d1791
commit 0ab1a2ef45
No known key found for this signature in database
GPG Key ID: 18974753009D2BFA
2 changed files with 43 additions and 0 deletions

View File

@ -21,6 +21,7 @@ Component.Breadcrumbs({
resolveFrontmatterTitle: true, // whether to resolve folder names through frontmatter titles
hideOnRoot: true, // whether to hide breadcrumbs on root `index.md` page
showCurrentPage: true, // whether to display the current page in the breadcrumbs
style: "full", // determine the style of breadcrumb, currently support `full`, `letter`, `unique`.
})
```

View File

@ -9,6 +9,8 @@ type CrumbData = {
path: string
}
type CrumbStyle = "full" | "letter" | "unique"
interface BreadcrumbOptions {
/**
* Symbol between crumbs
@ -30,6 +32,17 @@ interface BreadcrumbOptions {
* Whether to display the current page in the breadcrumbs.
*/
showCurrentPage: boolean
/**
* Set a style for breadcrumbs. The following are supported:
* - full (default): show the full path of the breadcrumb.
* - letter: works like full, but will write every folder name using first letter only. The last folder will be displayed in full. For example:
* - `folder` will be shorten to `f`
* - `.config` will be shorten to `.c`
* - unique: works like `letter`, but will make sure every folder name is shortest unique value. For example:
* - `path/path/path/to/file.md` with `unique` will set `p/pa/pat/path/to/file.md`.
* - However, uniqueness does not refer different folder at the same level. For example: `path1/file.md` and `path2/file.md` will both show `p/file.md`
*/
style: CrumbStyle
}
const defaultOptions: BreadcrumbOptions = {
@ -38,6 +51,7 @@ const defaultOptions: BreadcrumbOptions = {
resolveFrontmatterTitle: true,
hideOnRoot: true,
showCurrentPage: true,
style: "full",
}
function formatCrumb(displayName: string, baseSlug: FullSlug, currentSlug: SimpleSlug): CrumbData {
@ -104,6 +118,34 @@ export default ((opts?: Partial<BreadcrumbOptions>) => {
currentPath = joinSegments(currentPath, slugParts[i])
const includeTrailingSlash = !isTagPath || i < 1
switch (options.style) {
case "letter":
if (curPathSegment.startsWith(".")) {
curPathSegment = curPathSegment.slice(0, 2)
} else {
curPathSegment = curPathSegment.charAt(0)
}
break
case "unique":
let uniquePart = curPathSegment.charAt(0)
let maxLength = Math.min(curPathSegment.length, 5)
let isUnique = false
while (!isUnique && uniquePart.length <= maxLength) {
isUnique = true
for (let j = 0; j < i; j++) {
if (slugParts[j].startsWith(uniquePart)) {
isUnique = false
break
}
}
if (!isUnique) {
uniquePart = curPathSegment.slice(0, uniquePart.length + 1)
}
}
curPathSegment = uniquePart
break
}
// Format and add current crumb
const crumb = formatCrumb(
curPathSegment,