forked from TypeCellOS/BlockNote
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen.ts
99 lines (83 loc) · 3.34 KB
/
gen.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
import * as glob from "glob";
import * as fs from "node:fs";
import * as path from "node:path";
import prettier from "prettier";
import React from "react";
import ReactDOM from "react-dom/server";
import { Project, getExampleProjects, groupProjects } from "./util";
import { fileURLToPath,pathToFileURL } from "url";
import { dirname } from "path";
/**
* This script reads the examples in the /examples folder. These folders initially only need an App.tsx, .bnexample.json and README.md file.
*
* This script then generates a full project, for each example (e.g.: vite.config / tsconfig / package.json files, see the `template-react` dir).
* It also generates playground/src/examples.gen.tsx that has the metadata for all examples combined and is used in the playground.
*
* All of these files are checked in to source control.
*
* (The downside of this is that we have some almost duplicate, generated files in the repo,
* but the upside is anyone can run npm start in any of the examples (and that we can point a codesandbox / repl to the examples directory))
*/
const dir = dirname(fileURLToPath(import.meta.url));
async function writeTemplate(project: Project, templateFile: string) {
const template = await import(pathToFileURL(templateFile).toString());
const ret = await template.default(project);
const targetFilePath = path.join(
"../../",
project.pathFromRoot,
path
.basename(templateFile)
.replace(".template.tsx", "")
.replace(".template.tsx", "")
.replace("\\", "/")
);
let stringOutput: string | undefined = undefined;
if (React.isValidElement(ret)) {
stringOutput = ReactDOM.renderToString(ret);
const prettierConfig = await prettier.resolveConfig(targetFilePath);
stringOutput = prettier.format(stringOutput, {
...prettierConfig,
parser: "html",
}) as string;
} else if (typeof ret === "string") {
stringOutput = ret;
} else if (typeof ret === "object") {
stringOutput = JSON.stringify(ret, undefined, 2);
} else {
throw new Error("unsupported template");
}
fs.writeFileSync(targetFilePath, stringOutput);
// try {
// // fs.unlinkSync(targetFilePath);
// } catch (e) {}
// eslint-disable-next-line no-console
console.log("written", targetFilePath);
}
async function generateCodeForExample(project: Project) {
const templates = glob.sync(
path.join(dir, "./template-react/*.template.tsx").replace(/\\/g, '/')
);
for (const template of templates) {
await writeTemplate(project, template);
}
}
async function generateExamplesData(projects: Project[]) {
// TODO: fix playground?
const target = path.resolve(dir, "../../../playground/src/examples.gen.tsx");
const examples = groupProjects(projects);
let code = `// generated by dev-scripts/examples/gen.ts
export const examples = ${JSON.stringify(examples, undefined, 2)};`;
code = code.replace(/\\\\/g, "/");
// add as any after deps, otherwise const type inference will be too complex for TS
code = code.replace(/("dependencies":\s*{[^}]*})/g, "$1 as any");
fs.writeFileSync(target, code);
}
const projects = getExampleProjects();
for (const project of projects) {
// eslint-disable-next-line no-console
console.log("generating code for example", project);
await generateCodeForExample(project);
}
await generateExamplesData(
projects.filter((p) => p.config?.playground === true)
);