1 |
rakinar2 |
575 |
const { lstatSync, read, readdirSync, existsSync } = require("fs"); |
2 |
|
|
const { readFile, writeFile, cp } = require("fs/promises"); |
3 |
|
|
const { glob } = require("glob"); |
4 |
|
|
const path = require("path"); |
5 |
|
|
|
6 |
|
|
(async () => { |
7 |
|
|
const pages = await glob("app/**/page.{tsx,mdx,md}"); |
8 |
|
|
const index = []; |
9 |
|
|
|
10 |
|
|
async function loadDocsIndex( |
11 |
|
|
directory = path.resolve(__dirname, "app/(docs)"), |
12 |
|
|
href = "/", |
13 |
|
|
) { |
14 |
|
|
const data = []; |
15 |
|
|
const files = readdirSync(directory); |
16 |
|
|
|
17 |
|
|
for (const filename of files) { |
18 |
|
|
console.log("INDEXING", filename, directory); |
19 |
|
|
const file = path.resolve(directory, filename); |
20 |
|
|
const stat = lstatSync(file); |
21 |
|
|
|
22 |
|
|
if (stat.isDirectory()) { |
23 |
|
|
const info = await loadDocsIndex( |
24 |
|
|
file, |
25 |
|
|
`${href}${href === "/" ? "" : "/"}${filename}`, |
26 |
|
|
); |
27 |
|
|
const i = info.children.findIndex( |
28 |
|
|
c => |
29 |
|
|
c.name === "page.mdx" || |
30 |
|
|
c.name === "page.md" || |
31 |
|
|
c.name === "page.tsx", |
32 |
|
|
); |
33 |
|
|
const removed = i !== -1 ? info.children.splice(i, 1)[0] : null; |
34 |
|
|
|
35 |
|
|
data.push( |
36 |
|
|
i !== -1 |
37 |
|
|
? { |
38 |
|
|
...info, |
39 |
|
|
children: info.children, |
40 |
|
|
type: "page", |
41 |
|
|
data: info.data ?? removed.data, |
42 |
|
|
} |
43 |
|
|
: info, |
44 |
|
|
); |
45 |
|
|
|
46 |
|
|
continue; |
47 |
|
|
} |
48 |
|
|
|
49 |
|
|
if ( |
50 |
|
|
filename !== "page.tsx" && |
51 |
|
|
filename !== "page.md" && |
52 |
|
|
filename !== "page.mdx" |
53 |
|
|
) |
54 |
|
|
continue; |
55 |
|
|
|
56 |
|
|
const isMDX = file.endsWith(".mdx") || file.endsWith(".md"); |
57 |
|
|
const info = isMDX |
58 |
|
|
? await generateIndexForMDXPage(file) |
59 |
|
|
: await generateIndexForTSXPage(file); |
60 |
|
|
|
61 |
|
|
data.push({ |
62 |
|
|
type: "page", |
63 |
|
|
name: path.basename(filename), |
64 |
|
|
url: file |
65 |
|
|
.replace(/[\/\\]\([a-z0-9A-Z_-]+\)/gi, "") |
66 |
|
|
.replace(/^app[\/\\]/gi, "") |
67 |
|
|
.replace(/page\.(tsx|md|mdx)$/gi, "") |
68 |
|
|
.replace(/\\/g, "/"), |
69 |
|
|
path: file.replace(/\\/g, "/"), |
70 |
|
|
data: { |
71 |
|
|
title: info.title, |
72 |
|
|
short_name: info.short_name, |
73 |
|
|
}, |
74 |
|
|
}); |
75 |
|
|
|
76 |
|
|
console.log("NESTED INDEXED", file); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
const name = path.basename(directory); |
80 |
|
|
|
81 |
|
|
const dirdata = existsSync(path.join(directory, "metadata.json")) |
82 |
|
|
? JSON.parse( |
83 |
|
|
await readFile( |
84 |
|
|
path.join(directory, "metadata.json"), |
85 |
|
|
"utf-8", |
86 |
|
|
), |
87 |
|
|
) |
88 |
|
|
: null; |
89 |
|
|
const children = [...(dirdata?.entries ?? []), ...data]; |
90 |
|
|
|
91 |
|
|
children.sort((a, b) => { |
92 |
|
|
if (dirdata?.sort_as) { |
93 |
|
|
const aIndex = dirdata.sort_as.indexOf(a.name); |
94 |
|
|
const bIndex = dirdata.sort_as.indexOf(b.name); |
95 |
|
|
|
96 |
|
|
if (aIndex !== -1 && bIndex !== -1) { |
97 |
|
|
return aIndex - bIndex; |
98 |
|
|
} else if (aIndex !== -1) { |
99 |
|
|
return -1; |
100 |
|
|
} else if (bIndex !== -1) { |
101 |
|
|
return 1; |
102 |
|
|
} |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
return a.name.localeCompare(b.name); |
106 |
|
|
}); |
107 |
|
|
|
108 |
|
|
return { |
109 |
|
|
type: "directory", |
110 |
|
|
name: name === "(docs)" ? "/" : name, |
111 |
|
|
children: children, |
112 |
|
|
href, |
113 |
|
|
data: dirdata |
114 |
|
|
? { |
115 |
|
|
title: dirdata.title, |
116 |
|
|
short_name: dirdata.short_name, |
117 |
|
|
} |
118 |
|
|
: undefined, |
119 |
|
|
}; |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
for (const page of pages) { |
123 |
|
|
const isMDX = page.endsWith(".mdx") || page.endsWith(".md"); |
124 |
|
|
|
125 |
|
|
index.push( |
126 |
|
|
isMDX |
127 |
|
|
? await generateIndexForMDXPage(page) |
128 |
|
|
: await generateIndexForTSXPage(page), |
129 |
|
|
); |
130 |
|
|
|
131 |
|
|
console.log("DONE ", page); |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
await writeFile(path.join(__dirname, "index.json"), JSON.stringify(index)); |
135 |
|
|
|
136 |
|
|
await writeFile( |
137 |
|
|
path.join(__dirname, "docs_index.json"), |
138 |
|
|
JSON.stringify(await loadDocsIndex(), null, 4), |
139 |
|
|
); |
140 |
|
|
|
141 |
|
|
try { |
142 |
|
|
await cp( |
143 |
|
|
path.join(__dirname, "index.json"), |
144 |
|
|
path.join(__dirname, ".next/server/index.json"), |
145 |
|
|
); |
146 |
|
|
} catch (error) { |
147 |
|
|
console.error(error); |
148 |
|
|
} |
149 |
|
|
})(); |
150 |
|
|
|
151 |
|
|
async function generateIndexForMDXPage(page) { |
152 |
|
|
const contents = await readFile(page, { |
153 |
|
|
encoding: "utf-8", |
154 |
|
|
}); |
155 |
|
|
let [frontmatter, data] = contents |
156 |
|
|
.substring(contents.startsWith("---") ? 3 : 0) |
157 |
|
|
.split("\n---\n"); |
158 |
|
|
|
159 |
|
|
if (!contents.trimStart().startsWith("---")) { |
160 |
|
|
data = frontmatter; |
161 |
|
|
frontmatter = null; |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
const entries = frontmatter |
165 |
|
|
?.split("\n") |
166 |
|
|
.filter(Boolean) |
167 |
|
|
.map(entry => |
168 |
|
|
entry |
169 |
|
|
.split(/:(.*)/s) |
170 |
|
|
.filter(Boolean) |
171 |
|
|
.map((a, i) => { |
172 |
|
|
const trimmed = a.trim(); |
173 |
|
|
return i === 1 && |
174 |
|
|
trimmed.startsWith('"') && |
175 |
|
|
trimmed.endsWith('"') |
176 |
|
|
? trimmed.substring(1, trimmed.length - 1).trim() |
177 |
|
|
: trimmed; |
178 |
|
|
}), |
179 |
|
|
); |
180 |
|
|
|
181 |
|
|
const frontmatterData = entries ? Object.fromEntries(entries) : null; |
182 |
|
|
|
183 |
|
|
return { |
184 |
|
|
...frontmatterData, |
185 |
|
|
data: (data ?? "") |
186 |
|
|
.replace(/^(([\s\r\n]*)import([^.]+);)+/gi, "") |
187 |
|
|
.replace(/^(([\s\r\n]*)export([^.]+);)+/gi, "") |
188 |
|
|
.replace(/([\s\r\n]*)export default ([^;]+);$/gi, "") |
189 |
|
|
.replace(/<\/?[^>]+(>|$)/g, ""), |
190 |
|
|
url: |
191 |
|
|
"/" + |
192 |
|
|
page |
193 |
|
|
.replace(/[\/\\]\([a-z0-9A-Z_-]+\)/gi, "") |
194 |
|
|
.replace(/^app[\/\\]/gi, "") |
195 |
|
|
.replace(/page\.(tsx|md|mdx)$/gi, "") |
196 |
|
|
.replace(/\\/g, "/"), |
197 |
|
|
path: page.replace(/\\/g, "/"), |
198 |
|
|
}; |
199 |
|
|
} |
200 |
|
|
|
201 |
|
|
async function generateIndexForTSXPage(page) { |
202 |
|
|
throw new Error("Not implemented"); |
203 |
|
|
} |