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