-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgeneratepostmeta.ts
112 lines (105 loc) · 2.92 KB
/
generatepostmeta.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const { watch, readFile, writeFile } = require("fs");
const { basename } = require("path");
const { promisify } = require("util");
const { red, yellow, cyan, green } = require("colorette");
const glob = require("tiny-glob");
const mri = require("mri");
const mdx = require("@mdx-js/mdx");
const esbuild = require("esbuild");
const requireFromString = require("require-from-string");
const argv = mri(process.argv.slice(2), {
boolean: ["watch"],
string: [],
alias: {
watch: "w"
},
default: {}
});
const [readFileAsync, writeFileAsync] = [readFile, writeFile].map(promisify);
if (watch && !["win32", "darwin"].some(os => process.platform.indexOf(os))) {
console.log(
yellow(
`postgen.js -> Your OS (${process.platform}) does not support fs.watch`
)
);
process.exit(1);
}
(async () => {
if (argv.watch) {
console.log(cyan("postgen.js -> watching..."));
generatePostsFile({ watch: false });
let debounceTimeout = undefined;
watch(
"src/router/posts",
{
recursive: true
},
(event, filename) => {
if (filename !== "posts.ts") {
debounceTimeout && clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(() => {
generatePostsFile({ watch });
debounceTimeout = undefined;
}, 50);
}
}
);
} else {
generatePostsFile({ watch });
}
})();
const decoder = new TextDecoder("utf-8");
async function generatePostsFile({ watch }) {
try {
const filenames = (await glob(`src/router/posts/**/*.mdx`, {
filesOnly: true,
absolute: true
})).sort((a, b) => (basename(a) < basename(b) ? -1 : 1));
const contents = await Promise.all(
filenames.map(async file => await readFileAsync(file, "utf8"))
);
const posts = await Promise.all(contents.map(async (content, index) => {
const jsx = await mdx(content);
const parsed = await esbuild.build({
platform: "node",
write: false,
bundle: true,
stdin: {
contents: jsx,
sourcefile: filenames[index],
loader: "jsx",
},
});
const cjs = decoder.decode(
parsed.outputFiles[0].contents
);
return {
...requireFromString(cjs).metadata,
id: basename(filenames[index], ".mdx")
};
}));
await writeFileAsync(
"src/store/posts.ts",
`/* generated by /postgen.js */\nexport const metadata = ${JSON.stringify(
posts,
null,
2
)};\n`
);
console.log(
green(
`postgen.js -> Generated src/store/posts.ts (${filenames.length} post${
posts.length > 1 ? "s" : ""
})`
)
);
} catch (e) {
console.error(red(e));
console.log(
red(
`postgen.js -> Failed to grab a list of posts in via src/router/posts/**/*.mdx and create a new all.tsx file importing metadata from each`
)
);
!watch && process.exit(1);
}
}