Skip to content

Commit

Permalink
Update Vitepress configuration and sidebar builder
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Feb 6, 2024
1 parent de9e252 commit 461d5c5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 203 deletions.
9 changes: 3 additions & 6 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { defineConfig } from 'vitepress';
import { transformerTwoslash } from 'vitepress-plugin-twoslash';
import { getRegisteredMarkdownTheme } from '../shared/utils';
// https://vitepress.dev/reference/site-config
import { builder } from '../shared/multipleSidebarBuilder';

// https://vitepress.dev/reference/site-config
export default defineConfig({
markdown: {
lineNumbers: true,
Expand Down Expand Up @@ -32,7 +33,7 @@ export default defineConfig({
{ text: 'Contact', link: '../contact.md' },
],
logo: '/favicon.ico',
sidebar: builder.emitSidebar(), //getSidebar(),
sidebar: builder.emitSidebar(),
outline: {
level: 'deep',
},
Expand All @@ -45,10 +46,6 @@ export default defineConfig({
search: {
provider: 'local',
},
// docFooter: {
// prev: false,
// next: false,
// },
editLink: {
pattern: ({ filePath }) => {
return `/~https://github.com/sharpchen/sharpchen.github.io/edit/main/docs/${filePath}`;
Expand Down
5 changes: 0 additions & 5 deletions docs/about.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
---
prev: false
next: false
---

# About me

This is a personal blog for documenting my learning journey of various things(primarily programming).
Expand Down
67 changes: 2 additions & 65 deletions docs/shared/multipleSidebarBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Enumerable from 'linq';
import { DefaultTheme } from 'vitepress';
import { DirectoryInfo, FileInfo, Path, documentRoot } from '../shared/FileSystem';
import { folderToSidebarItems } from './utils';
const docRoot = documentRoot();
export const builder = {
base: `/${docRoot.name}` as string | undefined,
Expand Down Expand Up @@ -28,68 +28,5 @@ export const builder = {
emitSidebar: function (): DefaultTheme.SidebarMulti {
return this.sidebar;
},
emitRewrites: function (): Record<string, string> {
return this.rewrites;
},
registerRewritesAuto: function () {
if (!Object.keys(this.sidebar).length) throw new Error('sidebar not set');
for (const sidebarRoute in this.sidebar) {
if (Object.prototype.hasOwnProperty.call(this.sidebar, sidebarRoute)) {
const sidebar = (this.sidebar as DefaultTheme.SidebarMulti)[sidebarRoute] as DefaultTheme.SidebarItem[];
const { items: collapsibleOrLinkOnly } = sidebar[0]; // the items of first is the actual content
let index: string;
// if no second level
if (Enumerable.from(collapsibleOrLinkOnly!).any(i => i.items === void 0)) {
index = Enumerable.from(collapsibleOrLinkOnly!)
.where(i => i.link !== void 0)
.firstOrDefault()?.link!;
this.rewrites[`${index}`] = `${sidebarRoute}index.html`;
continue;
}
// find a collapsible
const parentOfIndex = Enumerable.from(collapsibleOrLinkOnly!)
.where(i => i.items !== void 0 && i.items.length > 0)
.orderBy(i => i.text)
.firstOrDefault();
index = Enumerable.from(parentOfIndex?.items!)
.where(i => i.link !== void 0)
.orderBy(i => i.text)
.firstOrDefault()?.link!;
this.rewrites[`${index}`] = `${sidebarRoute}index.html`;
}
}
return this;
},
};
builder.registerSidebarAuto().registerRewritesAuto();

function filesToSidebarItems(files: FileInfo[], base: string): DefaultTheme.SidebarItem[] {
return files.map(file => {
const link = `${base}/${file.name}`;
return {
text: Path.GetFileNameWithoutExtension(file.name),
link: link.substring(0, link.lastIndexOf('.')),
};
});
}

function folderToSidebarItems(folder: DirectoryInfo, base: string): DefaultTheme.SidebarItem[] {
if (!folder.exists) throw new Error(`folder: ${folder.name} not found`);
const subs = folder.getDirectories();
// load files in this folder
let items: DefaultTheme.SidebarItem[] = folder.getFiles().length
? filesToSidebarItems(folder.getFiles(), `${base}/${folder.name}`)
: [];
for (const index in subs) {
if (Object.prototype.hasOwnProperty.call(subs, index)) {
const sub = subs[index];
const currentSidebarItem: DefaultTheme.SidebarItem = {
collapsed: false,
text: sub.name.replace(/^\d+\.\s*/, ''), // remove leading index
items: folderToSidebarItems(sub, `${base}/${folder.name}`),
};
items.push(currentSidebarItem);
}
}
return items;
}
builder.registerSidebarAuto();
159 changes: 32 additions & 127 deletions docs/shared/utils.ts
Original file line number Diff line number Diff line change
@@ -1,141 +1,46 @@
/**
* - Converts a document name to corresponding registered route name.
* @param fullName name of document root folder
* @returns corresponding route name registered statically
*/
export function routeNameOfDocument(fullName: string): string {
const ret = fullName.split(' ').join('').toLowerCase();
return ret;
}

/**
* truncateUrl('http://.../pages/document/.../xx.md', 'pages')
* @param url url to truncate
* @param prefix prefix to be truncated
* @returns
*/
export function truncateUrl(url: string, prefix: string): string {
const index = url.indexOf(prefix);
if (index === -1) {
return url;
}
return url.substring(index + prefix.length);
}

/**
*
* @param mdLink `http://../../xx.md`
* @returns `http://../../xx.html`
*/
export function mdLinkToHtmlLink(mdLink: string) {
if (mdLink.endsWith('.md')) {
return `${mdLink.substring(0, mdLink.lastIndexOf('.md'))}.html`;
}
return mdLink;
}

export function tryCompare(x: string, y: string): number {
if (startsWithIndex(x) && startsWithIndex(y)) {
const xNum = parseInt(x.substring(0, x.indexOf('.')));
const yNum = parseInt(y.substring(0, y.indexOf('.')));
return compareIntegers(xNum, yNum);
}
return x.localeCompare(y);
}
function startsWithIndex(input: string): boolean {
const regex = /^\d+\./;
return regex.test(input);
}

function compareIntegers(a: number, b: number): number {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}

import * as fs from 'fs';
import path from 'path';
import * as shikiji from 'shikiji';
import { DefaultTheme } from 'vitepress';
import { themes } from '../../.github/workflows/beforeBuild/sync-themes.mjs';
import * as registeredInfo from '../[docRoute].paths';
import * as featureData from '../data/Features.data';
import { Path, documentRoot, projectRoot } from './FileSystem';
export function getSidebar(): DefaultTheme.Sidebar | undefined {
const docRoot = documentRoot();
const registeredDocs = registeredInfo.default.paths();
// get all registered doc parents
const docParents = docRoot
.getDirectories()
.filter(x => !x.name.startsWith('.'))
.map(x => {
return {
name: x.name,
docDir: x.getDirectories().filter(d => d.name === 'docs')[0],
};
})
.filter(x => registeredDocs.filter(y => y.params.docRoute === routeNameOfDocument(x.name)).length !== 0);
// generate sidebar for each docDir
return docParents
.map(x => {
// if has chapters
if (x.docDir.getDirectories().length !== 0) {
const subs = x.docDir.getDirectories();
return {
// chapter level
text: getDocNameWithEmoji(x.name),
collapsed: true,
items: subs.map(s => {
return {
// doc level
collapsed: true,
text: s.name,
items: s.getFiles().map(f => {
return {
text: Path.GetFileNameWithoutExtension(f.fullName),
link: Path.GetRelativePath(projectRoot().fullName, f.fullName),
};
}),
};
}),
};
} else {
return {
collapsed: true,
text: getDocNameWithEmoji(x.name),
items: x.docDir
.getFiles()
.map(f => {
return {
text: Path.GetFileNameWithoutExtension(f.fullName),
link: Path.GetRelativePath(projectRoot().fullName, f.fullName),
};
})
.sort((x, y) => tryCompare(x.text, y.text)),
};
}
})
.flat();
}
type CustomMarkdownTheme = keyof typeof themes; //'Eva Dark' | 'Eva Light' | 'Rider Dark' | 'Darcula';
export async function getRegisteredMarkdownTheme(theme: CustomMarkdownTheme): Promise<shikiji.ThemeRegistration> {
import { FileInfo, Path, DirectoryInfo, projectRoot } from './FileSystem';

export async function getRegisteredMarkdownTheme(theme: keyof typeof themes): Promise<shikiji.ThemeRegistration> {
let isThemeRegistered = (await shikiji.getSingletonHighlighter()).getLoadedThemes().find(x => x === theme);
if (!isThemeRegistered) {
const myTheme = JSON.parse(fs.readFileSync(path.join(projectRoot().fullName, `public/${theme}.json`), 'utf8'));
(await shikiji.getSingletonHighlighter()).loadTheme(myTheme);
}
return (await shikiji.getSingletonHighlighter()).getTheme(theme);
}
function getDocNameWithEmoji(docName: string): string {
const features = featureData.default.load();
if (docName.toLowerCase() === 'articles') return `📰 ${docName}`;
const emoji = features.find(x => x.title === docName)?.icon;
if (emoji) {
return `${emoji} ${docName}`;

export function filesToSidebarItems(files: FileInfo[], base: string): DefaultTheme.SidebarItem[] {
return files.map(file => {
const link = `${base}/${file.name}`;
return {
text: Path.GetFileNameWithoutExtension(file.name),
link: link.substring(0, link.lastIndexOf('.')),
};
});
}

export function folderToSidebarItems(folder: DirectoryInfo, base: string): DefaultTheme.SidebarItem[] {
if (!folder.exists) throw new Error(`folder: ${folder.name} not found`);
const subs = folder.getDirectories();
// load files in this folder
let items: DefaultTheme.SidebarItem[] = folder.getFiles().length
? filesToSidebarItems(folder.getFiles(), `${base}/${folder.name}`)
: [];
for (const index in subs) {
if (Object.prototype.hasOwnProperty.call(subs, index)) {
const sub = subs[index];
const currentSidebarItem: DefaultTheme.SidebarItem = {
collapsed: false,
text: sub.name.replace(/^\d+\.\s*/, ''), // remove leading index
items: folderToSidebarItems(sub, `${base}/${folder.name}`),
};
items.push(currentSidebarItem);
}
}
return docName;
return items;
}

0 comments on commit 461d5c5

Please sign in to comment.