-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
types+don't show deprecated categories in navbar
- Loading branch information
Showing
3 changed files
with
107 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { readdirSync, readFileSync, statSync } from "fs"; | ||
import { sep } from "path"; | ||
import matter from "gray-matter"; | ||
import type { DocCategory, DocFile, DocFrontmatter } from "./types"; | ||
|
||
/** | ||
* Convert a string to title case | ||
* @author Evorp | ||
* @param str - String to convert | ||
* @returns String in title case | ||
*/ | ||
export function toTitleCase(str: string) { | ||
if (!str) return str; | ||
return str | ||
.split(/-|_| /g) | ||
.map((word) => word[0].toUpperCase() + word.slice(1)) | ||
.join(" "); | ||
} | ||
|
||
/** | ||
* Return an array of all filepaths in a directory | ||
* @author Juknum, Evorp | ||
* @param dir - Directory to search | ||
* @param filelist - Used for recursion | ||
* @returns Array of file paths | ||
*/ | ||
export function walkSync(dir: string, filelist: string[] = []) { | ||
// add trailing slash if not present | ||
if (!dir.endsWith(sep)) dir += sep; | ||
for (const file of readdirSync(dir)) { | ||
if (statSync(dir + file).isDirectory()) | ||
// read directories inside directories recursively | ||
filelist = walkSync(dir + file + sep, filelist); | ||
else filelist.push(dir + file); | ||
} | ||
return filelist; | ||
} | ||
|
||
/** | ||
* Read pages folder and map files to a sidebar and navbar compatible format | ||
* @author Evorp | ||
* @param dir - Directory to read | ||
* @returns Array of category objects | ||
*/ | ||
export default function computeCategories(dir: string) { | ||
return walkSync(dir) | ||
.filter((f) => f.endsWith(".md")) | ||
.map((fileName) => { | ||
const file = readFileSync(fileName, { encoding: "utf8" }); | ||
const name = fileName.replace(process.cwd(), "").replace(".md", ""); | ||
// parse yaml frontmatter into object | ||
const frontmatter = matter(file).data as DocFrontmatter; | ||
return { | ||
text: frontmatter.title, | ||
link: name, | ||
// fall back to the parent folder | ||
category: frontmatter.category || toTitleCase(name.split("/").at(-2) || ""), | ||
date: frontmatter.date, | ||
// default false | ||
archived: frontmatter.archived ?? false, | ||
deprecated: frontmatter.deprecated ?? false, | ||
} as DocFile; | ||
}) | ||
.reduce((acc, cur) => { | ||
// because this isn't just an object with the names as keys we need to search | ||
const found = acc.findIndex((v) => v.text === cur.category); | ||
if (found === -1) acc.push({ text: cur.category, collapsed: false, items: [cur] }); | ||
else acc[found].items?.push(cur); | ||
return acc; | ||
}, [] as DocCategory[]) | ||
.map((category) => { | ||
// collapse categories that are entirely archived/deprecated by default | ||
if (category.items.every((i) => i.deprecated || i.archived)) | ||
return { ...category, collapsed: true }; | ||
return category; | ||
}) | ||
.sort(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
export interface DocMeta { | ||
category?: string; | ||
date: string; | ||
archived?: boolean; | ||
deprecated?: boolean; | ||
} | ||
|
||
export interface DocFrontmatter extends DocMeta { | ||
title: string; | ||
} | ||
|
||
// at this point all optional fields are filled | ||
export interface DocFile extends Required<DocMeta> { | ||
text: string; | ||
link: string; | ||
} | ||
|
||
export interface DocCategory { | ||
text: string; | ||
collapsed: boolean; | ||
items: DocFile[]; | ||
} |