1+ ---
2+ import { type CollectionEntry } from ' astro:content'
3+
4+ import { getBlogCollection } from ' astro-pure/server'
5+ import { cn } from ' astro-pure/utils'
6+
7+ export const prerender = true
8+ export const partial = true
9+
10+ const docsCollection = (await getBlogCollection (' docs' )) as CollectionEntry <' docs' >[]
11+ // Group docs by id first part (setup, integrations, advanced, etc.)
12+ const docsByCate = docsCollection .reduce ((acc : { [key : string ]: typeof docsCollection }, doc ) => {
13+ const id = doc .id .split (' /' )[0 ]
14+ if (! acc [id ]) acc [id ] = [] as typeof docsCollection
15+ acc [id ].push (doc )
16+ return acc
17+ }, {})
18+
19+ const docCategories = {
20+ " grpc_goat_docs" : ' gRPC Goat Docs' ,
21+ // integrations: 'Integrations',
22+ // advanced: 'Advanced'
23+ }
24+
25+ type Props = {
26+ title? : boolean
27+ class? : string
28+ }
29+
30+ const { title = true , class : className, ... props } = Astro .props
31+ ---
32+
33+ <docs-toc class ={ cn (' not-prose' , className )} {... props }>
34+ { title && <h2 class = ' text-foreground font-semibold' >DOCS</h2 >}
35+ <ul class =' mt-4 flex flex-col gap-y-5' >
36+ {
37+ Object .entries (docCategories ).map (([id , title ]: [string , string ]) => (
38+ <li >
39+ <h3 class = ' text-muted-foreground text-xs tracking-widest uppercase' >{ title } </h3 >
40+ <ul class = ' mt-2 flex flex-col' >
41+ { docsByCate [id ]
42+ ?.sort ((a , b ) => a .data .order - b .data .order )
43+ ?.map ((doc ) => (
44+ <li class = ' docs-item flex relative ms-2 px-3 py-1 text-foreground/75 transition-all rounded-2xl' >
45+ <a class = ' flex-1 hover:text-foreground' href = { ` /docs/${doc .id } ` } >
46+ { doc .data .title }
47+ </a >
48+ </li >
49+ ))}
50+ </ul >
51+ </li >
52+ ))
53+ }
54+ </ul >
55+ </docs-toc>
56+
57+ <style >
58+ docs-toc .docs-item::before {
59+ content: '';
60+ display: block;
61+ position: absolute;
62+ top: 5%;
63+ bottom: 5%;
64+ left: -0.5rem;
65+ width: 2px;
66+ background-color: hsl(var(--input) / var(--un-bg-opacity));
67+ }
68+
69+ docs-toc :global(.docs-item.docs-hl) {
70+ background-color: hsl(var(--muted) / var(--un-bg-opacity));
71+ font-weight: 500;
72+ & a {
73+ color: hsl(var(--primary) / var(--un-text-opacity));
74+ }
75+
76+ &::before {
77+ background-color: hsl(var(--primary) / var(--un-bg-opacity));
78+ }
79+ }
80+ </style >
81+
82+ <script >
83+ class DocsTOC extends HTMLElement {
84+ link: string = ''
85+
86+ constructor() {
87+ super()
88+
89+ this.link = window.location.pathname
90+ }
91+
92+ connectedCallback() {
93+ const links = this.querySelectorAll('a')
94+ links.forEach((link) => {
95+ if (link.getAttribute('href') === this.link) {
96+ link.parentElement?.classList.add('docs-hl')
97+ }
98+ })
99+ }
100+ }
101+
102+ customElements.define('docs-toc', DocsTOC)
103+ </script >
0 commit comments