add progression script

This commit is contained in:
Mathieu Schimmerling
2022-05-06 20:37:06 +02:00
parent 93e8efbb09
commit 94fe26fb33
6 changed files with 356 additions and 23 deletions

View File

@@ -5,7 +5,6 @@
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": true,
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": [".*", "*.json", "*.md", "*.toml", "*.yml"],

202
README.md
View File

@@ -13,25 +13,185 @@ How do we solve this ? Developers love having framework overview by examples. It
## Roadmap
- [ ] SolidJS
* [x] Reactivity
* [x] Templating
* [x] Lifecycle
* [ ] Component composition
* [ ] Form input
* [ ] Webapp features
* \[ ] Add EmberJS
* \[ ] Add Preact
* \[ ] Add Alpine
* \[ ] Add [Lit](https://lit.dev/)
* \[ ] Add native JS ?
- [ ] Add EmberJS
- [ ] Add Preact
- [ ] Add Alpine
- [ ] Add [Lit](https://lit.dev/)
- [ ] Add native JS ?
## Progression
- [x] Add Angular
- [x] Website (built with Astro)
- [x] Add React
- [x] Add Svelte
- [x] Add Vue 3
<details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/svelte.svg" />
<b>Svelte</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
* [x] Reactivity
* [x] Declare state
* [x] Update state
* [x] Computed state
* [x] Templating
* [x] Minimal template
* [x] Styling
* [x] Loop
* [x] Event click
* [x] Dom ref
* [x] Conditional
* [x] Lifecycle
* [x] On mount
* [x] On unmount
* [x] Component composition
* [x] Props
* [x] Emit to parent
* [x] Slot
* [x] Slot fallback
* [x] Form input
* [x] Input text
* [x] Checkbox
* [x] Radio
* [x] Select
* [x] Webapp features
* [x] Routing
* [x] Router link
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/react.svg" />
<b>React</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
* [x] Reactivity
* [x] Declare state
* [x] Update state
* [x] Computed state
* [x] Templating
* [x] Minimal template
* [x] Styling
* [x] Loop
* [x] Event click
* [x] Dom ref
* [x] Conditional
* [x] Lifecycle
* [x] On mount
* [x] On unmount
* [x] Component composition
* [x] Props
* [x] Emit to parent
* [x] Slot
* [x] Slot fallback
* [x] Form input
* [x] Input text
* [x] Checkbox
* [x] Radio
* [x] Select
* [x] Webapp features
* [x] Routing
* [x] Router link
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/vue.svg" />
<b>Vue 3</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
* [x] Reactivity
* [x] Declare state
* [x] Update state
* [x] Computed state
* [x] Templating
* [x] Minimal template
* [x] Styling
* [x] Loop
* [x] Event click
* [x] Dom ref
* [x] Conditional
* [x] Lifecycle
* [x] On mount
* [x] On unmount
* [x] Component composition
* [x] Props
* [x] Emit to parent
* [x] Slot
* [x] Slot fallback
* [x] Form input
* [x] Input text
* [x] Checkbox
* [x] Radio
* [x] Select
* [x] Webapp features
* [x] Routing
* [x] Router link
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/angular.svg" />
<b>Angular</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/100" /></summary>
* [x] Reactivity
* [x] Declare state
* [x] Update state
* [x] Computed state
* [x] Templating
* [x] Minimal template
* [x] Styling
* [x] Loop
* [x] Event click
* [x] Dom ref
* [x] Conditional
* [x] Lifecycle
* [x] On mount
* [x] On unmount
* [x] Component composition
* [x] Props
* [x] Emit to parent
* [x] Slot
* [x] Slot fallback
* [x] Form input
* [x] Input text
* [x] Checkbox
* [x] Radio
* [x] Select
* [x] Webapp features
* [x] Routing
* [x] Router link
</details><details>
<summary>
<img width="18" height="18" src="https://raw.githubusercontent.com/matschik/component-party/main/public/framework/solid.svg" />
<b>SolidJS</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/53" /></summary>
* [x] Reactivity
* [x] Declare state
* [x] Update state
* [x] Computed state
* [x] Templating
* [x] Minimal template
* [x] Styling
* [x] Loop
* [x] Event click
* [x] Dom ref
* [x] Conditional
* [x] Lifecycle
* [x] On mount
* [x] On unmount
* [ ] Component composition
* [ ] Props
* [ ] Emit to parent
* [ ] Slot
* [ ] Slot fallback
* [ ] Form input
* [ ] Input text
* [ ] Checkbox
* [ ] Radio
* [ ] Select
* [ ] Webapp features
* [ ] Routing
* [ ] Router link
</details>
## Contributing
@@ -48,7 +208,7 @@ This project requires Node.js to be `v14.0.0` or higher, because we use new Java
### Add a framework
1) Fork the project and create a new branch
2) Add the new framework SVG logo in `public/framework`
3) Install the ESLint plugin assiociated to the framework
4) On `config.cjs` and `src/frameworks.js`, add a new entry with SVG link and ESLint configuration
1. Fork the project and create a new branch
2. Add the new framework SVG logo in `public/framework`
3. Install the ESLint plugin assiociated to the framework
4. On `config.cjs` and `src/frameworks.js`, add a new entry with SVG link and ESLint configuration

View File

@@ -33,6 +33,7 @@
"@astrojs/svelte": "^0.1.2",
"@astrojs/tailwind": "^0.1.2",
"@tailwindcss/typography": "^0.5.2",
"@types/mdast": "^3.0.10",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"astro": "^1.0.0-beta.12",
@@ -54,6 +55,7 @@
"prettier-plugin-svelte": "^2.7.0",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"remark": "^14.0.2",
"shiki": "^0.10.1",
"svelte": "^3.47.0",
"tailwindcss": "^3.0.24",

23
pnpm-lock.yaml generated
View File

@@ -9,6 +9,7 @@ specifiers:
'@astrojs/svelte': ^0.1.2
'@astrojs/tailwind': ^0.1.2
'@tailwindcss/typography': ^0.5.2
'@types/mdast': ^3.0.10
'@typescript-eslint/eslint-plugin': ^5.20.0
'@typescript-eslint/parser': ^5.20.0
astro: ^1.0.0-beta.12
@@ -30,6 +31,7 @@ specifiers:
prettier-plugin-svelte: ^2.7.0
prop-types: ^15.8.1
react: ^17.0.2
remark: ^14.0.2
shiki: ^0.10.1
svelte: ^3.47.0
tailwindcss: ^3.0.24
@@ -45,6 +47,7 @@ devDependencies:
'@astrojs/svelte': 0.1.2_age2zvqebpy5wupoa63ks75lhy
'@astrojs/tailwind': 0.1.2
'@tailwindcss/typography': 0.5.2_tailwindcss@3.0.24
'@types/mdast': 3.0.10
'@typescript-eslint/eslint-plugin': 5.22.0_lnjlwhtxjffjmj5o7dnwvwyqxq
'@typescript-eslint/parser': 5.22.0_t725usgvqspm5woeqpaxbfp2qu
astro: 1.0.0-beta.24
@@ -66,6 +69,7 @@ devDependencies:
prettier-plugin-svelte: 2.7.0_kkjbqzpydplecjtkxrgomroeru
prop-types: 15.8.1
react: 17.0.2
remark: 14.0.2
shiki: 0.10.1
svelte: 3.48.0
tailwindcss: 3.0.24
@@ -4329,6 +4333,25 @@ packages:
unist-util-visit: 4.1.0
dev: true
/remark-stringify/10.0.2:
resolution: {integrity: sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw==}
dependencies:
'@types/mdast': 3.0.10
mdast-util-to-markdown: 1.3.0
unified: 10.1.2
dev: true
/remark/14.0.2:
resolution: {integrity: sha512-A3ARm2V4BgiRXaUo5K0dRvJ1lbogrbXnhkJRmD0yw092/Yl0kOCZt1k9ZeElEwkZsWGsMumz6qL5MfNJH9nOBA==}
dependencies:
'@types/mdast': 3.0.10
remark-parse: 10.0.1
remark-stringify: 10.0.2
unified: 10.1.2
transitivePeerDependencies:
- supports-color
dev: true
/resolve-from/4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}

149
scripts/progress.js Normal file
View File

@@ -0,0 +1,149 @@
import { remark } from 'remark';
import fs from 'fs/promises';
import frameworks from '../src/frameworks.js';
import { packageDirectory } from 'pkg-dir';
import nodePath from 'node:path';
import kebabCase from 'lodash.kebabcase';
function removeMarkdownHeadingContent(content, headingValue, replaceContentValue) {
const tree = remark.parse(content);
// find index start
let targetNodeIndexStart;
for (let i = 0; i < tree.children.length; i++) {
const rootNode = tree.children[i];
if (rootNode.type === 'heading' && rootNode?.children[0]?.value === headingValue) {
targetNodeIndexStart = i;
break;
}
}
// find index end
let targetNodeIndexEnd = targetNodeIndexStart;
for (let i = targetNodeIndexStart + 1; i < tree.children.length; i++) {
const rootNode = tree.children[i];
if (rootNode.type === 'heading') {
targetNodeIndexEnd = i;
break;
}
}
tree.children.splice(targetNodeIndexStart + 1, targetNodeIndexEnd - targetNodeIndexStart - 1, {
type: 'text',
value: replaceContentValue || '',
});
const newContent = remark.stringify(tree);
return newContent;
}
async function parseContentDir() {
const rootDir = await packageDirectory();
const contentURL = `${rootDir}/content`;
const rootSectionNames = await fs.readdir(contentURL);
function dirNameToTitle(dirName) {
return capitalize(dirName.split('-').splice(1).join(' '));
}
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
const rootSections = [];
for (const rootSectionName of rootSectionNames) {
const sectionPath = `${contentURL}/${rootSectionName}`;
const sections = [];
const subSectionDirNames = await fs.readdir(sectionPath);
for (const dirName of subSectionDirNames) {
const path = `${sectionPath}/${dirName}`;
const frameworkDirs = await fs.readdir(path);
const frameworkSections = [];
for (const frameworkDir of frameworkDirs) {
const frameworkPath = `${path}/${frameworkDir}`;
const files = [];
const fileNames = await fs.readdir(`${frameworkPath}`);
for (const fileName of fileNames) {
const filePath = `${frameworkPath}/${fileName}`;
const ext = nodePath.parse(filePath).ext.split('.').pop();
files.push({
path: filePath,
fileName,
ext,
//content: await fs.readFile(filePath, 'utf-8'),
});
}
frameworkSections.push({
dirName: frameworkDir,
path: frameworkPath,
files,
});
}
const title = dirNameToTitle(dirName);
sections.push({
id: kebabCase(title),
path,
dirName,
title,
children: frameworkSections,
});
}
rootSections.push({
title: dirNameToTitle(rootSectionName),
children: sections,
});
}
return rootSections;
}
async function main() {
const codeContentDir = await parseContentDir();
const content = await fs.readFile('./README.md', 'utf8');
let newContent = removeMarkdownHeadingContent(content, 'Progression', '{{progression}}');
let progressionContent = '';
for (const framework of frameworks) {
function mdCheck(b) {
return b ? 'x' : ' ';
}
let list = '';
const allChecks = [];
for (const rootDir of codeContentDir) {
let sublist = '';
const checks = [];
for (const subdir of rootDir.children) {
const isChecked = subdir.children.find((n) => n.dirName === framework.id)?.files.length > 0;
checks.push(isChecked);
sublist += ` * [${mdCheck(isChecked)}] ${subdir.title}\n`;
}
list += `* [${mdCheck(checks.every((v) => v))}] ${rootDir.title}\n`;
list += sublist;
allChecks.push(...checks);
}
const percent = Math.ceil((allChecks.filter((v) => v).length / allChecks.length) * 100);
let frameworkContent = `<details>
<summary>
<img width="18" height="18" src="${framework.img}" />
<b>${framework.title}</b>
<img src="https://us-central1-progress-markdown.cloudfunctions.net/progress/${percent}" /></summary>
${list}
</details>`;
progressionContent += frameworkContent;
}
newContent = newContent.replace('{{progression}}', progressionContent);
await fs.writeFile('README.md', newContent);
}
main().catch(console.error);

View File

@@ -112,7 +112,7 @@ export default [
id: 'solid',
title: 'SolidJS',
ext: 'jsx',
img: '/framework/solid.svg',
img: 'https://raw.githubusercontent.com/matschik/component-party/main/public/framework/solid.svg',
eslint: {
files: ['**/solid/*.jsx'],
plugins: ['solid'],