1+ import fs from "node:fs" ;
2+ import path from "node:path" ;
3+ import { fileURLToPath } from "node:url" ;
14import { defineConfig } from "vitepress" ;
25import {
36 groupIconMdPlugin ,
47 localIconLoader ,
58 groupIconVitePlugin ,
69} from "vitepress-plugin-group-icons" ;
710
11+ const configDir = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
12+ const docsSrcDir = path . resolve ( configDir , "../src" ) ;
813const repoUrl = "https://github.com/BlueLua" ;
914const siteOrigin = "https://BlueLua.github.io" ;
1015const siteBasePath = "/" ;
@@ -31,6 +36,95 @@ const websiteJsonLd = {
3136 description : siteDescription ,
3237} ;
3338
39+ function listProjects ( ) {
40+ return fs
41+ . readdirSync ( docsSrcDir , { withFileTypes : true } )
42+ . filter ( ( entry ) => entry . isDirectory ( ) )
43+ . map ( ( entry ) => entry . name )
44+ . filter ( ( project ) =>
45+ fs . existsSync ( path . join ( docsSrcDir , project , "index.md" ) ) ,
46+ )
47+ . sort ( ) ;
48+ }
49+
50+ function titleFromFile ( file ) {
51+ return file . replace ( / \. m d $ / , "" ) . replace ( / - / g, " " ) ;
52+ }
53+
54+ function titleFromDir ( dir ) {
55+ if ( dir === "api" ) return "API" ;
56+
57+ return dir . replace ( / - / g, " " ) . replace ( / \b \w / g, ( char ) => char . toUpperCase ( ) ) ;
58+ }
59+
60+ function pageItem ( project , relativeFile ) {
61+ const slug = relativeFile . replace ( / \. m d $ / , "" ) ;
62+ const file = path . basename ( relativeFile ) ;
63+
64+ return {
65+ text : titleFromFile ( file ) ,
66+ link : `/${ project } /${ slug } ` ,
67+ } ;
68+ }
69+
70+ function listMarkdownFiles ( project , relativeDir = "" ) {
71+ const dir = path . join ( docsSrcDir , project , relativeDir ) ;
72+
73+ return fs
74+ . readdirSync ( dir , { withFileTypes : true } )
75+ . filter ( ( entry ) => entry . isFile ( ) )
76+ . map ( ( entry ) => entry . name )
77+ . filter ( ( file ) => file . endsWith ( ".md" ) && file !== "index.md" )
78+ . sort ( ) ;
79+ }
80+
81+ function listNestedDocDirs ( project ) {
82+ const dir = path . join ( docsSrcDir , project ) ;
83+
84+ return fs
85+ . readdirSync ( dir , { withFileTypes : true } )
86+ . filter ( ( entry ) => entry . isDirectory ( ) )
87+ . map ( ( entry ) => entry . name )
88+ . filter ( ( name ) => listMarkdownFiles ( project , name ) . length > 0 )
89+ . sort ( ) ;
90+ }
91+
92+ function buildSidebar ( ) {
93+ return Object . fromEntries (
94+ listProjects ( ) . map ( ( project ) => {
95+ const pages = listMarkdownFiles ( project ) ;
96+ const nestedDirs = listNestedDocDirs ( project ) ;
97+
98+ return [
99+ `/${ project } /` ,
100+ [
101+ {
102+ text : project ,
103+ items : [
104+ { text : "Overview" , link : `/${ project } /` } ,
105+ ...pages . map ( ( file ) => pageItem ( project , file ) ) ,
106+ ] ,
107+ } ,
108+ ...nestedDirs . map ( ( dir ) => ( {
109+ text : titleFromDir ( dir ) ,
110+ collapsed : false ,
111+ items : listMarkdownFiles ( project , dir ) . map ( ( file ) =>
112+ pageItem ( project , `${ dir } /${ file } ` ) ,
113+ ) ,
114+ } ) ) ,
115+ ] ,
116+ ] ;
117+ } ) ,
118+ ) ;
119+ }
120+
121+ function buildProjectNavItems ( ) {
122+ return listProjects ( ) . map ( ( project ) => ( {
123+ text : project ,
124+ link : `/${ project } /` ,
125+ } ) ) ;
126+ }
127+
34128export default defineConfig ( {
35129 srcDir : "./src" ,
36130 title : "BlueLua" ,
@@ -79,17 +173,14 @@ export default defineConfig({
79173 { text : "Home" , link : "/" } ,
80174 {
81175 text : "Projects" ,
82- items : [
83- { text : "evdev" , link : "evdev" } ,
84- { text : "timeutil" , link : "timeutil" } ,
85- { text : "tty" , link : "tty" } ,
86- ] ,
176+ items : buildProjectNavItems ( ) ,
87177 } ,
88178 { text : "GitHub" , link : "https://github.com/BlueLua" } ,
89179 {
90180 text : "🇵🇸 Free Palestine" ,
91181 link : "https://techforpalestine.org/learn-more" ,
92182 } ,
93183 ] ,
184+ sidebar : buildSidebar ( ) ,
94185 } ,
95186} ) ;
0 commit comments