commit 1b07037e877b47beb9aedfd6960ca7bf1ae2b5f2
parent 5f4c4dc76e84bdca49e4f793a6b1172642e0c8ce
Author: Amit Dutta <amitdutta4255@gmail.com>
Date: Thu, 2 Jul 2026 13:02:48 +0530
added breadcrubms
Diffstat:
4 files changed, 158 insertions(+), 9 deletions(-)
diff --git a/docs/.vitepress/theme/components/Breadcrumbs.vue b/docs/.vitepress/theme/components/Breadcrumbs.vue
@@ -0,0 +1,106 @@
+<script setup>
+import { computed } from 'vue'
+import { useRoute, useData } from 'vitepress'
+
+const route = useRoute()
+const { page, theme } = useData()
+
+// Turn "semester_2/tuition/file-name" into readable, linkable crumbs
+const crumbs = computed(() => {
+ const path = route.path
+ .replace(/\.html$/, '')
+ .replace(/^\/|\/$/g, '')
+
+ if (!path || path === 'index') return []
+
+ const segments = path.split('/').filter(Boolean)
+ const result = []
+ let accPath = ''
+
+ segments.forEach((seg, i) => {
+ accPath += '/' + seg
+ const isLast = i === segments.length - 1
+
+ // Last segment: use the real page title if available
+ let label = isLast && page.value.title
+ ? page.value.title
+ : humanize(seg)
+
+ result.push({
+ label,
+ link: isLast ? null : accPath + '/',
+ })
+ })
+
+ return result
+})
+
+function humanize(slug) {
+ return slug
+ .replace(/[-_]/g, ' ')
+ .replace(/\b\w/g, (c) => c.toUpperCase())
+}
+</script>
+
+<template>
+ <nav v-if="crumbs.length" class="bsc-breadcrumbs" aria-label="Breadcrumb">
+ <ol>
+ <li>
+ <a href="/" class="crumb-link">Home</a>
+ <span class="crumb-sep">/</span>
+ </li>
+ <li v-for="(crumb, i) in crumbs" :key="i">
+ <a v-if="crumb.link" :href="crumb.link" class="crumb-link">{{ crumb.label }}</a>
+ <span v-else class="crumb-current">{{ crumb.label }}</span>
+ <span v-if="i < crumbs.length - 1" class="crumb-sep">/</span>
+ </li>
+ </ol>
+ </nav>
+</template>
+
+<style scoped>
+.bsc-breadcrumbs {
+ margin-bottom: 16px;
+ font-size: 13px;
+ overflow-x: auto;
+ white-space: nowrap;
+ scrollbar-width: none;
+}
+
+.bsc-breadcrumbs::-webkit-scrollbar {
+ display: none;
+}
+
+.bsc-breadcrumbs ol {
+ display: flex;
+ align-items: center;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.bsc-breadcrumbs li {
+ display: flex;
+ align-items: center;
+}
+
+.crumb-link {
+ color: var(--vp-c-text-2);
+ text-decoration: none;
+ transition: color 0.15s ease;
+}
+
+.crumb-link:hover {
+ color: var(--vp-c-brand-1);
+}
+
+.crumb-current {
+ color: var(--vp-c-text-1);
+ font-weight: 500;
+}
+
+.crumb-sep {
+ margin: 0 8px;
+ color: var(--vp-c-divider);
+}
+</style>+
\ No newline at end of file
diff --git a/docs/.vitepress/theme/components/CopyLinkButton.vue b/docs/.vitepress/theme/components/CopyLinkButton.vue
@@ -34,14 +34,39 @@ const copied = ref(false)
let resetTimer = null
function copyLink() {
- navigator.clipboard.writeText(window.location.href).then(() => {
- clearTimeout(resetTimer)
- copied.value = true
- resetTimer = setTimeout(() => {
- copied.value = false
- }, 1400)
+ const url = window.location.href
+
+ navigator.clipboard.writeText(url).then(showCopied).catch(() => {
+ fallbackCopy(url)
})
}
+
+function fallbackCopy(text) {
+ const textarea = document.createElement('textarea')
+ textarea.value = text
+ textarea.style.position = 'fixed'
+ textarea.style.opacity = '0'
+ document.body.appendChild(textarea)
+ textarea.focus()
+ textarea.select()
+
+ try {
+ document.execCommand('copy')
+ showCopied()
+ } catch (err) {
+ console.error('Copy failed:', err)
+ }
+
+ document.body.removeChild(textarea)
+}
+
+function showCopied() {
+ clearTimeout(resetTimer)
+ copied.value = true
+ resetTimer = setTimeout(() => {
+ copied.value = false
+ }, 1400)
+}
</script>
<style scoped>
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
@@ -6,6 +6,7 @@ import Footer from './components/Footer.vue'
import SponsorButton from './components/SponsorButton.vue'
import ExternalLinkWarning from './components/ExternalLinkWarning.vue'
import CopyLinkButton from './components/CopyLinkButton.vue'
+import Breadcrumbs from './components/Breadcrumbs.vue'
import './style.css'
export default {
@@ -17,7 +18,10 @@ export default {
h(Banner),
h(ExternalLinkWarning)
]),
- 'doc-before': () => h(CopyLinkButton),
+ 'doc-before': () => h('div', { class: 'bsc-doc-toolbar' }, [
+ h(Breadcrumbs),
+ h(CopyLinkButton)
+ ]),
'doc-after': () => h(Footer),
'nav-bar-content-after': () => h(SponsorButton)
})
diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css
@@ -397,4 +397,18 @@
.DocSearch-Logo {
margin-left: auto !important;
}
-}-
\ No newline at end of file
+}
+
+.bsc-doc-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 16px;
+}
+
+.bsc-doc-toolbar .bsc-breadcrumbs {
+ margin-bottom: 0;
+ flex: 1;
+ min-width: 0;
+}