Skip to content

Commit 2db893a

Browse files
committed
Switch to genReadme.new
1 parent b5eae83 commit 2db893a

File tree

2 files changed

+334
-5
lines changed

2 files changed

+334
-5
lines changed

genReadme.new.js

Lines changed: 333 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,342 @@
1-
const fs = require("fs");
1+
const fs = require("fs/promises");
22
const path = require("path");
3+
const Fm = require("front-matter");
4+
const Toc = require("markdown-toc");
5+
const prettier = require("prettier");
36
const yargs = require("yargs/yargs");
47
const { hideBin } = require("yargs/helpers");
58
const { usage } = require("yargs");
69

7-
const readmePath = path.resolve(__dirname, "./README.md");
10+
const repositoryRootPath = __dirname;
11+
const readmePath = path.resolve(repositoryRootPath, "./README.md");
12+
const defaultOptions = {
13+
withKey: "title",
14+
withToc: false,
15+
showHeading: true,
16+
headingLevel: 2,
17+
tabLevel: 1,
18+
prefix: "",
19+
suffix: "",
20+
};
821

9-
function main(argv) {
10-
console.log(argv);
22+
async function readContentFromPath(relativePath) {
23+
let MdDoc = await fs.readFile(path.join(repositoryRootPath, relativePath), {
24+
encoding: "utf8",
25+
});
26+
let MdContent = Fm(MdDoc.toString());
27+
let TableOfContents = Toc(MdContent.body).content;
28+
return {
29+
frontmatter: MdContent.attributes,
30+
body: MdContent.body,
31+
toc: TableOfContents,
32+
};
33+
}
34+
35+
async function updateSectionWith(options) {
36+
const {
37+
from,
38+
headingLevel,
39+
name,
40+
path,
41+
prefix,
42+
showHeading,
43+
suffix,
44+
tabLevel,
45+
to,
46+
withKey,
47+
withToc,
48+
} = { ...defaultOptions, ...options };
49+
let md = await readContentFromPath(path);
50+
let oldFences = getFenceForSection(from, name);
51+
let fenceOptions = {
52+
name,
53+
content: md,
54+
tabLevel,
55+
headingLevel,
56+
showHeading,
57+
withKey,
58+
prefix,
59+
suffix,
60+
};
61+
let newFences = generateContentForSection({
62+
...fenceOptions,
63+
withToc: false,
64+
});
65+
let oldTocFences = getFenceForSection(from, name, true);
66+
let newTocFences = generateContentForSection({
67+
...fenceOptions,
68+
withToc: true,
69+
});
70+
let updatedContents = to.replace(oldFences.regex, newFences);
71+
updatedContents = updatedContents.replace(oldTocFences.regex, newTocFences);
72+
if (withToc)
73+
console.log(
74+
`✅ 🗜️ Rewrote Table of Contents for '${md.frontmatter.title}'`
75+
);
76+
console.log(`✅ 📝 Rewrote Section for '${md.frontmatter.title}'`);
77+
return updatedContents;
78+
}
79+
80+
function generateContentForSection(options) {
81+
const {
82+
content,
83+
headingLevel,
84+
name,
85+
prefix,
86+
showHeading,
87+
suffix,
88+
tabLevel,
89+
withKey,
90+
withToc,
91+
} = {
92+
...defaultOptions,
93+
...options,
94+
};
95+
let fence = getFence(name, withToc);
96+
let fenceContent = fence.start + "\n";
97+
if (withToc) {
98+
let lines = content.toc.split("\n");
99+
for (let i = 0, len = lines.length; i < len; i += 1)
100+
fenceContent +=
101+
" ".repeat(tabLevel) + lines[i] + (i !== len - 1 ? "\n" : "");
102+
} else {
103+
fenceContent += showHeading
104+
? `${"#".repeat(headingLevel)} ` +
105+
prefix +
106+
content.frontmatter[withKey] +
107+
suffix +
108+
"\n\n"
109+
: "";
110+
fenceContent += content.body + "\n";
111+
}
112+
fenceContent += fence.end;
113+
return fenceContent;
114+
}
115+
function getFenceForSection(readme, sectionName, isToc = false) {
116+
try {
117+
let fence = getFence(sectionName, isToc);
118+
let regex = new RegExp(`(${fence.start}[\\s\\S]+${fence.end})`, "gm");
119+
return { regex: regex, content: regex.exec(readme.content) };
120+
} catch (err) {
121+
console.error(
122+
`🚨 You've encountered a ${err.name}${err.message} \n` +
123+
`💡 ProTip ➜ Please ensure the comments exist and are separated by a newline.`
124+
);
125+
126+
console.error({ readme, sectionName });
127+
console.error(err);
128+
}
129+
}
130+
function getFence(sectionName, isToc = false) {
131+
let name = isToc ? sectionName + "-toc" : sectionName;
132+
let START_COMMENT = "<!--START-SECTION:" + name + "-->";
133+
let END_COMMENT = "<!--END-SECTION:" + name + "-->";
134+
return { start: START_COMMENT, end: END_COMMENT };
135+
}
136+
137+
async function main(argv) {
138+
let currentReadme = await fs.readFile(readmePath, { encoding: "utf-8" });
139+
140+
let pendingReadme = currentReadme;
141+
pendingReadme = await updateSectionWith({
142+
from: currentReadme,
143+
to: pendingReadme,
144+
name: "setup",
145+
path: "docs/basic/setup.md",
146+
withToc: true,
147+
headingLevel: 1,
148+
prefix: "Section 1: ",
149+
});
150+
pendingReadme = await updateSectionWith({
151+
from: currentReadme,
152+
to: pendingReadme,
153+
name: "basic-type-examples",
154+
path: "docs/basic/getting-started/basic-type-examples.md",
155+
});
156+
pendingReadme = await updateSectionWith({
157+
from: currentReadme,
158+
to: pendingReadme,
159+
name: "function-components",
160+
path: "docs/basic/getting-started/function-components.md",
161+
});
162+
pendingReadme = await updateSectionWith({
163+
from: currentReadme,
164+
to: pendingReadme,
165+
name: "hooks",
166+
path: "docs/basic/getting-started/hooks.md",
167+
});
168+
pendingReadme = await updateSectionWith({
169+
from: currentReadme,
170+
to: pendingReadme,
171+
name: "class-components",
172+
path: "docs/basic/getting-started/class-components.md",
173+
});
174+
pendingReadme = await updateSectionWith({
175+
from: currentReadme,
176+
to: pendingReadme,
177+
name: "default-props",
178+
path: "docs/basic/getting-started/default-props.md",
179+
showHeading: false,
180+
});
181+
pendingReadme = await updateSectionWith({
182+
from: currentReadme,
183+
to: pendingReadme,
184+
name: "forms-and-events",
185+
path: "docs/basic/getting-started/forms-and-events.md",
186+
});
187+
pendingReadme = await updateSectionWith({
188+
from: currentReadme,
189+
to: pendingReadme,
190+
name: "context",
191+
path: "docs/basic/getting-started/context.md",
192+
});
193+
pendingReadme = await updateSectionWith({
194+
from: currentReadme,
195+
to: pendingReadme,
196+
name: "forward-create-ref",
197+
path: "docs/basic/getting-started/forward-create-ref.md",
198+
});
199+
pendingReadme = await updateSectionWith({
200+
from: currentReadme,
201+
to: pendingReadme,
202+
name: "portals",
203+
path: "docs/basic/getting-started/portals.md",
204+
});
205+
pendingReadme = await updateSectionWith({
206+
from: currentReadme,
207+
to: pendingReadme,
208+
name: "error-boundaries",
209+
path: "docs/basic/getting-started/error-boundaries.md",
210+
});
211+
pendingReadme = await updateSectionWith({
212+
from: currentReadme,
213+
to: pendingReadme,
214+
name: "concurrent",
215+
path: "docs/basic/getting-started/concurrent.md",
216+
});
217+
pendingReadme = await updateSectionWith({
218+
from: currentReadme,
219+
to: pendingReadme,
220+
name: "types",
221+
path: "docs/basic/troubleshooting/types.md",
222+
withToc: true,
223+
headingLevel: 1,
224+
});
225+
pendingReadme = await updateSectionWith({
226+
from: currentReadme,
227+
to: pendingReadme,
228+
name: "operators",
229+
path: "docs/basic/troubleshooting/operators.md",
230+
headingLevel: 1,
231+
});
232+
pendingReadme = await updateSectionWith({
233+
from: currentReadme,
234+
to: pendingReadme,
235+
name: "utilities",
236+
path: "docs/basic/troubleshooting/utilities.md",
237+
headingLevel: 1,
238+
});
239+
pendingReadme = await updateSectionWith({
240+
from: currentReadme,
241+
to: pendingReadme,
242+
name: "ts-config",
243+
path: "docs/basic/troubleshooting/ts-config.md",
244+
headingLevel: 1,
245+
});
246+
pendingReadme = await updateSectionWith({
247+
from: currentReadme,
248+
to: pendingReadme,
249+
name: "official-typings-bugs",
250+
path: "docs/basic/troubleshooting/official-typings-bugs.md",
251+
headingLevel: 1,
252+
withKey: "sidebar_label",
253+
prefix: "Troubleshooting Handbook: ",
254+
});
255+
pendingReadme = await updateSectionWith({
256+
from: currentReadme,
257+
to: pendingReadme,
258+
name: "non-ts-files",
259+
path: "docs/basic/troubleshooting/non-ts-files.md",
260+
headingLevel: 1,
261+
});
262+
pendingReadme = await updateSectionWith({
263+
from: currentReadme,
264+
to: pendingReadme,
265+
name: "non-ts-files",
266+
path: "docs/basic/troubleshooting/learn-ts.md",
267+
headingLevel: 1,
268+
});
269+
pendingReadme = await updateSectionWith({
270+
from: currentReadme,
271+
to: pendingReadme,
272+
name: "useful-hooks",
273+
path: "docs/basic/useful-hooks.md",
274+
headingLevel: 1,
275+
});
276+
pendingReadme = await updateSectionWith({
277+
from: currentReadme,
278+
to: pendingReadme,
279+
name: "editor-integration",
280+
path: "docs/basic/editor-integration.md",
281+
headingLevel: 1,
282+
});
283+
pendingReadme = await updateSectionWith({
284+
from: currentReadme,
285+
to: pendingReadme,
286+
name: "linting",
287+
path: "docs/basic/linting.md",
288+
headingLevel: 1,
289+
});
290+
pendingReadme = await updateSectionWith({
291+
from: currentReadme,
292+
to: pendingReadme,
293+
name: "resources",
294+
path: "docs/basic/recommended/resources.md",
295+
headingLevel: 1,
296+
});
297+
pendingReadme = await updateSectionWith({
298+
from: currentReadme,
299+
to: pendingReadme,
300+
name: "talks",
301+
path: "docs/basic/recommended/talks.md",
302+
headingLevel: 1,
303+
});
304+
pendingReadme = await updateSectionWith({
305+
from: currentReadme,
306+
to: pendingReadme,
307+
name: "codebases",
308+
path: "docs/basic/recommended/codebases.md",
309+
headingLevel: 1,
310+
});
311+
pendingReadme = await updateSectionWith({
312+
from: currentReadme,
313+
to: pendingReadme,
314+
name: "learn-ts",
315+
path: "docs/basic/troubleshooting/learn-ts.md",
316+
headingLevel: 1,
317+
withKey: "sidebar_label",
318+
});
319+
pendingReadme = await updateSectionWith({
320+
from: currentReadme,
321+
to: pendingReadme,
322+
name: "examples",
323+
path: "docs/basic/examples.md",
324+
headingLevel: 1,
325+
});
326+
327+
const prettierConfig = await prettier.resolveConfig(readmePath);
328+
pendingReadme = prettier.format(pendingReadme, {
329+
...prettierConfig,
330+
filepath: path.basename(readmePath),
331+
});
332+
333+
if (argv.check) {
334+
if (pendingReadme !== currentReadme) {
335+
throw new Error("Readme is outdated. Forgot to run `yarn gen-readme`?");
336+
}
337+
} else {
338+
await fs.writeFile(readmePath, pendingReadme);
339+
}
11340
}
12341

13342
yargs(hideBin(process.argv))

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"homepage": "https://github.com/typescript-cheatsheets/react-typescript-cheatsheet#readme",
2020
"scripts": {
2121
"format-readme": "prettier --write \"README.md\"",
22-
"gen-readme": "node genReadme.js",
22+
"gen-readme": "node genReadme.new.js",
2323
"format": "prettier --write \"**/*.md\"",
2424
"format:check": "prettier --check \"**/*.md\"",
2525
"postinstall": "cd website && yarn",

0 commit comments

Comments
 (0)