Skip to content

Commit 397fcb6

Browse files
committed
feat: add breadcrumbs option to frontmatter and implement showBreadcrumbs logic
1 parent f5d1277 commit 397fcb6

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

docs/vitepress-theme/frontmatter.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ The Nimiq Vitepress theme supports the following frontmatter options:
3030
| ------------------ | ------------------ | ----------------------------------------------- | -------------------------------------------------------- |
3131
| `layout` | `'home' \| 'docs'` | `'docs'` | Layout type to use for the page |
3232
| `sidebar` | `boolean` | `true` for docs layout | Whether to show the sidebar |
33+
| `breadcrumbs` | `boolean` | `true` for docs layout, `false` for home layout | Whether to show the breadcrumbs navigation |
3334
| `outline` | `boolean` | `true` if headings exist | Whether to show the outline (table of contents) |
3435
| `secondarySidebar` | `boolean` | `true` for docs layout, `false` for home layout | Whether to show the secondary sidebar |
3536
| `widget` | `boolean` | `true` for docs layout, `false` for home layout | Whether to show the widget area in the secondary sidebar |

packages/nimiq-vitepress-theme/src/composables/__tests__/useBreadcrumbs.test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Breadcrumb } from '../useBreadcrumbs'
2-
import { useRoute } from 'vitepress'
2+
import { useData, useRoute } from 'vitepress'
33
import { describe, expect, it, vi } from 'vitest'
44
import { computed } from 'vue'
55
import { useBreadcrumbs } from '../useBreadcrumbs'
@@ -8,6 +8,7 @@ import { useCurrentModule } from '../useCurrentModule'
88
// Mock dependencies
99
vi.mock('vitepress', () => ({
1010
useRoute: vi.fn(),
11+
useData: vi.fn(),
1112
withBase: (p: string) => `/base${p}`,
1213
}))
1314
vi.mock('../useCurrentModule', () => ({
@@ -32,6 +33,7 @@ describe('useBreadcrumbs', () => {
3233
currentDocModule: computed(() => moduleData),
3334
})
3435
;(useRoute as any).mockReturnValue({ path: '/base/page1/' })
36+
;(useData as any).mockReturnValue({ frontmatter: computed(() => ({})) })
3537

3638
const { breadcrumbs } = useBreadcrumbs()
3739
expect(breadcrumbs.value).toEqual<Breadcrumb[]>([
@@ -63,6 +65,7 @@ describe('useBreadcrumbs', () => {
6365
currentDocModule: computed(() => moduleData),
6466
})
6567
;(useRoute as any).mockReturnValue({ path: '/base/child/' })
68+
;(useData as any).mockReturnValue({ frontmatter: computed(() => ({})) })
6669

6770
const { breadcrumbs } = useBreadcrumbs()
6871
expect(breadcrumbs.value).toEqual<Breadcrumb[]>([
@@ -72,4 +75,52 @@ describe('useBreadcrumbs', () => {
7275
{ text: 'Child' },
7376
])
7477
})
78+
79+
it('should show breadcrumbs by default for docs layout', () => {
80+
const moduleData = {
81+
text: 'Module',
82+
subpath: 'mod',
83+
sidebar: [],
84+
}
85+
;(useCurrentModule as any).mockReturnValue({
86+
currentDocModule: computed(() => moduleData),
87+
})
88+
;(useRoute as any).mockReturnValue({ path: '/base/test/' })
89+
;(useData as any).mockReturnValue({ frontmatter: computed(() => ({})) })
90+
91+
const { showBreadcrumbs } = useBreadcrumbs()
92+
expect(showBreadcrumbs.value).toBe(true)
93+
})
94+
95+
it('should hide breadcrumbs by default for home layout', () => {
96+
const moduleData = {
97+
text: 'Module',
98+
subpath: 'mod',
99+
sidebar: [],
100+
}
101+
;(useCurrentModule as any).mockReturnValue({
102+
currentDocModule: computed(() => moduleData),
103+
})
104+
;(useRoute as any).mockReturnValue({ path: '/base/test/' })
105+
;(useData as any).mockReturnValue({ frontmatter: computed(() => ({ layout: 'home' })) })
106+
107+
const { showBreadcrumbs } = useBreadcrumbs()
108+
expect(showBreadcrumbs.value).toBe(false)
109+
})
110+
111+
it('should respect explicit breadcrumbs frontmatter setting', () => {
112+
const moduleData = {
113+
text: 'Module',
114+
subpath: 'mod',
115+
sidebar: [],
116+
}
117+
;(useCurrentModule as any).mockReturnValue({
118+
currentDocModule: computed(() => moduleData),
119+
})
120+
;(useRoute as any).mockReturnValue({ path: '/base/test/' })
121+
;(useData as any).mockReturnValue({ frontmatter: computed(() => ({ breadcrumbs: false })) })
122+
123+
const { showBreadcrumbs } = useBreadcrumbs()
124+
expect(showBreadcrumbs.value).toBe(false)
125+
})
75126
})

packages/nimiq-vitepress-theme/src/composables/useBreadcrumbs.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRoute, withBase } from 'vitepress'
1+
import { useData, useRoute, withBase } from 'vitepress'
22
import { computed } from 'vue'
33
import { useCurrentModule } from './useCurrentModule'
44

@@ -11,6 +11,15 @@ export interface Breadcrumb {
1111
export function useBreadcrumbs() {
1212
const { currentDocModule } = useCurrentModule()
1313
const route = useRoute()
14+
const { frontmatter } = useData()
15+
16+
const showBreadcrumbs = computed(() => {
17+
if (frontmatter.value.breadcrumbs !== undefined)
18+
return frontmatter.value.breadcrumbs
19+
if (frontmatter.value.layout === 'home')
20+
return false
21+
return true
22+
})
1423

1524
const breadcrumbs = computed<Breadcrumb[]>(() => {
1625
const items: Breadcrumb[] = []
@@ -61,5 +70,6 @@ export function useBreadcrumbs() {
6170

6271
return {
6372
breadcrumbs,
73+
showBreadcrumbs,
6474
}
6575
}

packages/nimiq-vitepress-theme/src/layout/PageContent.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import '../assets/typography.css'
1212
import '../assets/github-callouts.css'
1313
1414
const { page } = useData<NimiqVitepressThemeConfig>()
15-
const { breadcrumbs } = useBreadcrumbs()
15+
const { breadcrumbs, showBreadcrumbs } = useBreadcrumbs()
1616
1717
const { secondarySidebar } = useSecondarySidebar()
1818
@@ -31,7 +31,7 @@ function useEditUrl(relativePath: string): string {
3131
<template>
3232
<div :class="secondarySidebar ? 'f-pr-xs f-pl-xl' : 'f-px-xl'" f-pt-sm f="$px $px-min-48 $px-max-72" f-pb-sm flex="~ gap-16" relative h-full>
3333
<div flex="~ col" h-full flex-1 w="[calc(100vw-2*var(--nq-sidebar-width)-2*var(--f-px))]">
34-
<ul px-32 f-pb-lg flex="~ items-center gap-12">
34+
<ul v-if="showBreadcrumbs" px-32 f-pb-lg flex="~ items-center gap-12">
3535
<li v-for="({ text, icon }, i) in breadcrumbs" :key="text" contents w-max>
3636
<div v-if="icon" :class="icon" />
3737
<span nq-label f-text-2xs w-max>{{ text }}</span>

0 commit comments

Comments
 (0)