@@ -0,0 +1,110 @@
1+const fs = require("fs");
2+const path = require("path");
3+const matter = require("gray-matter");
4+const toml = require("@iarna/toml");
5+
6+// node ./buildPageTree.js [directory] [sort]
7+// eg. node ./buildPageTree docs weight
8+// will produce docs.json in the cache folder.
9+
10+const options = {
11+ engines: {
12+ toml: toml.parse.bind(toml),
13+ },
14+ language: "toml",
15+ delimiters: "+++",
16+};
17+
18+/**
19+ * buildPageTree is written to provide a recursive index of posts
20+ * for nested directories for creating sidebars
21+ * @param {string} path Absolute path to the subdirectory.
22+ * @returns {Object.<string,string|Object<string,string[]|number>>} Title of the directory, child pages, and child directories (recursive structure).
23+ *
24+ */
25+
26+// type PageTree =
27+// { title: string,
28+// pages: [{
29+// title: string,
30+// base: string,
31+// slug: string,
32+// weight: number,
33+// }],
34+// children: { [string]: PageTree },
35+// }
36+
37+function buildPageTree(dirPath, ordering = "", content = false) {
38+ const metadata = matter(
39+ fs.readFileSync(path.join(dirPath, "_index.md")),
40+ options
41+ );
42+ // get a list of contents at the dirPath, with file types so that the item at the dirPath can be identified as file or folder
43+ const children = fs.readdirSync(dirPath, { withFileTypes: true });
44+ // get a list of files
45+ const pages = children.filter((f) => f.isFile() && f.name !== "_index.md");
46+ // get a list of folders
47+ const subdirs = children.filter((f) => f.isDirectory());
48+ // return a pagetree datastructure
49+ return {
50+ title: metadata.data.title,
51+ pages: pages
52+ .map((page) => {
53+ // retrieve topmatter as JSON
54+ const { content, data } = matter(
55+ fs.readFileSync(path.join(dirPath, page.name)),
56+ options
57+ );
58+
59+ return {
60+ title: data.title,
61+ base: page.name,
62+ slug: page.name.replace(/.md$/, ""),
63+ ...(ordering === "weight" && { weight: data?.weight ?? 0 }),
64+ ...(ordering === "date" && {
65+ date: data?.date ?? "2000-01-01T00:00:00.000Z",
66+ }),
67+ };
68+ })
69+ .sort((a, b) => a.weight - b.weight),
70+ children: Object.fromEntries(
71+ subdirs
72+ .sort((a, b) => {
73+ const aMetadata = matter(
74+ fs.readFileSync(path.join(dirPath, a.name, "_index.md")),
75+ options
76+ );
77+ const bMetadata = matter(
78+ fs.readFileSync(path.join(dirPath, b.name, "_index.md")),
79+ options
80+ );
81+ return aMetadata?.data?.weight - bMetadata?.data?.weight || 0;
82+ })
83+ .map((subdir) => [
84+ subdir.name,
85+ buildPageTree(path.join(dirPath, subdir.name), ordering, content),
86+ ])
87+ ),
88+ };
89+}
90+
91+const process = require("process");
92+
93+const arg = process.argv?.[2];
94+const sort = process?.argv?.[3] || "weight";
95+
96+const dir = buildPageTree(path.join(process.cwd(), `content/${arg}`), sort);
97+const fileContents = `${JSON.stringify(dir)}`;
98+
99+try {
100+ fs.readdirSync("cache");
101+} catch (err) {
102+ fs.mkdirSync("cache");
103+}
104+
105+fs.writeFile(`cache/${arg}.json`, fileContents, function (err) {
106+ if (err) return console.error(err);
107+ console.log(`${arg} directory structure created.`);
108+});
109+
110+module.exports = { buildPageTree };