feat(generator): create generator to transform README files

This commit is contained in:
thomas
2023-09-24 21:54:46 +02:00
parent 9d4598d38b
commit 3d1ce3f3ad
5 changed files with 215 additions and 2 deletions

View File

@@ -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.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3Aanswer" target="_blank"><img src="https://img.shields.io/badge/-Solutions-green" alt="Crud solution"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="Crud solution author"/></a>

View File

@@ -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.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="todo list app testing"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A285+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="todo list app testing solution author"/></a>

View File

@@ -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"
}
}
}

View File

@@ -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(/<a href=("|')(.+?)("|')/, 'g');
const href = buffer.match(regexHref).map(findHref);
console.log('HREF', href);
let footerText = `:::note
Start the project by running: \`npx nx serve ${command}\`.
:::
:::tip[Reminder]
Your PR title must start with <b>Answer:${number}</b>.
:::
<div class="article-footer">
<a
href="${href[0]}"
alt="${title} community solutions">
❖ Community Answers
</a>
<a
href='${href[1]}'
alt="${title} solution author">
▶︎ Author Answer
</a>
`;
if (href[2].startsWith('https://medium')) {
footerText = `${footerText}<a
href='${href[2]}'
target="_blank"
rel="noopener noreferrer"
alt="${title} blog article">
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
Blog Post
</a>
</div>
`;
} else {
footerText = `${footerText}</div>
`;
}
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
:::
<div class="chip">Challenge #${number}</div>
${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;

View File

@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "Readme",
"title": "",
"type": "object",
"properties": {}
}