From 3d1ce3f3ad5fc548f52067e5506e089e68719bb1 Mon Sep 17 00:00:00 2001 From: thomas Date: Sun, 24 Sep 2023 21:54:46 +0200 Subject: [PATCH] feat(generator): create generator to transform README files --- apps/crud/README.md | 2 +- apps/testing-todos-list/README.md | 2 +- libs/cli/generators.json | 5 + libs/cli/src/generators/readme/generator.ts | 201 ++++++++++++++++++++ libs/cli/src/generators/readme/schema.json | 7 + 5 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 libs/cli/src/generators/readme/generator.ts create mode 100644 libs/cli/src/generators/readme/schema.json diff --git a/apps/crud/README.md b/apps/crud/README.md index ec34df2..8fadba3 100644 --- a/apps/crud/README.md +++ b/apps/crud/README.md @@ -54,7 +54,7 @@ this.todos = [...this.todos.filter((t) => t.id !== todoUpdated.id), todoUpdated] 4. **nx serve crud** 5. _...work On it_ 6. Commit your work -7. Submit a PR with a title beginning with **Answer:3** that I will review and other dev can review. +7. Submit a PR with a title beginning with **Answer:5** that I will review and other dev can review. Crud solution Crud solution author diff --git a/apps/testing-todos-list/README.md b/apps/testing-todos-list/README.md index 4bd63f0..82bebe9 100644 --- a/apps/testing-todos-list/README.md +++ b/apps/testing-todos-list/README.md @@ -23,7 +23,7 @@ You can also do it with cypress. 6. `npx nx component-test testing-todos-list --watch` to test your application with Cypress 7. _...work on it_ 8. Commit your work -9. Submit a PR with a title beginning with **Answer:28** that I will review and other dev can review. +9. Submit a PR with a title beginning with **Answer:29** that I will review and other dev can review. todo list app testing todo list app testing solution author diff --git a/libs/cli/generators.json b/libs/cli/generators.json index 9dd8e78..a6b249b 100644 --- a/libs/cli/generators.json +++ b/libs/cli/generators.json @@ -4,6 +4,11 @@ "factory": "./src/generators/app/generator", "schema": "./src/generators/app/schema.json", "description": "app generator" + }, + "readme": { + "factory": "./src/generators/readme/generator", + "schema": "./src/generators/readme/schema.json", + "description": "readme generator" } } } diff --git a/libs/cli/src/generators/readme/generator.ts b/libs/cli/src/generators/readme/generator.ts new file mode 100644 index 0000000..db2ddc6 --- /dev/null +++ b/libs/cli/src/generators/readme/generator.ts @@ -0,0 +1,201 @@ +import { Tree, formatFiles } from '@nx/devkit'; +import { readFile, writeFile } from 'fs/promises'; + +const README_FILENAME = 'README.md'; +const OMIT = ['memoized', 'projection', 'testing-table', 'testing-forms']; + +function findReadMe(tree: Tree, path: string): string[] { + let result: string[] = []; + if (!tree.isFile(path)) { + tree.children(path).forEach((child) => { + if (!OMIT.includes(child)) { + if (child === README_FILENAME) { + result.push(path + '/' + child); + } else { + result = result.concat(findReadMe(tree, path + '/' + child)); + } + } + }); + } + return result; +} + +function findDocFile( + tree: Tree, + path: string, + number: string, + result: string[] +) { + if (!tree.isFile(path)) { + tree.children(path).forEach((child) => { + if (child.startsWith(`${number}-`)) { + result.push(path + '/' + child); + } else { + findDocFile(tree, path + '/' + child, number, result); + } + }); + } +} + +function findHref(href) { + const regexHref = new RegExp(/href=("|')(.+?)("|')/); + const matchHref = href.match(regexHref); + + return matchHref[2]; +} + +async function rewriteFile(tree: Tree, file: string) { + console.log('Current file', file); + const buffer = await readFile(file, { encoding: 'utf-8' }); + + const regex = new RegExp(/Answer:(\d+)/); + const match = buffer.match(regex); + + if (!match) throw new Error('NO MATCH'); + + const number = parseInt(match[1], 10); + + const result = []; + findDocFile( + tree, + './docs/src/content/docs/challenges', + String(number), + result + ); + const docFile = result[0]; + + const pathElts = docFile.split('/'); + const link = `https://angular-challenges.vercel.app/challenges/${pathElts.at( + -2 + )}/${pathElts.at(-1)}/`; + + const doc = await readFile(docFile, { encoding: 'utf-8' }); + + const regexTitle = new RegExp(/title:\s(🟢|🟠|🔴)\s(.+?)\n/); + const matchTitle = doc.match(regexTitle); + const title = matchTitle[2]; + + const regexCommand = new RegExp(/npx nx serve\s(.+?)`\s/); + const matchCommand = buffer.match(regexCommand); + + let command = ''; + if (!matchCommand) { + const regexOldCommand = new RegExp(/nx serve\s(.+?)\*/); + command = buffer.match(regexOldCommand)[1]; + } else { + command = matchCommand[1]; + } + + console.log('commande:', command); + + const finalText = `# ${title} + +> Author: Thomas Laforge + +### Run Application + +\`\`\`bash +npx nx serve ${command} +\`\`\` + +### Documentation and Instruction + +Challenge documentation is [here](${link}). +`; + + await writeFile(file, finalText, { encoding: 'utf-8' }); + + ///**** */ + + const regexHref = new RegExp(/Answer:${number}. +::: + +
+ + ❖ Community Answers + + + ▶︎ Author Answer + + `; + + if (href[2].startsWith('https://medium')) { + footerText = `${footerText} + + Blog Post + +
+ `; + } else { + footerText = `${footerText} +`; + } + + const regexHeader = new RegExp(/([\s\S]*?)\s:::note/); + const header = doc.match(regexHeader)[1]; + + console.log('header', header); + + const regexContent = new RegExp( + /Author: Thomas Laforge([\s\S]*?)### Submitting your work/ + ); + const matchContent = buffer.match(regexContent); + + let content = ''; + if (!matchContent) { + const regexOldContent = new RegExp( + /Author: Thomas Laforge([\s\S]*?)## Submitting your work/ + ); + content = buffer.match(regexOldContent)[1]; + } else { + content = matchContent[1]; + } + + const fullDocText = `${header} + +:::note +WIP +::: + +
Challenge #${number}
+ +${content} + +--- + +${footerText} + `; + + await writeFile(docFile, fullDocText, { encoding: 'utf-8' }); +} + +export async function readmeGenerator(tree: Tree) { + const readmeFiles = findReadMe(tree, './apps'); + + for (const f of readmeFiles) { + // const f = './apps/performance/default-onpush/README.md'; + await rewriteFile(tree, f); + } + + await formatFiles(tree); +} + +export default readmeGenerator; diff --git a/libs/cli/src/generators/readme/schema.json b/libs/cli/src/generators/readme/schema.json new file mode 100644 index 0000000..ba8d015 --- /dev/null +++ b/libs/cli/src/generators/readme/schema.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "Readme", + "title": "", + "type": "object", + "properties": {} +}