react-folder-generator
Advanced tools
+122
| # Component Generator CLI | ||
| A simple Node.js CLI tool to scaffold React component boilerplate with flexible styling options. | ||
| ## 🚀 Features | ||
| - Supports JavaScript (`.jsx`) and TypeScript (`.tsx`) | ||
| - Supports multiple styling formats: CSS, SCSS, CSS Modules, SCSS Modules | ||
| - Optional scoped styling | ||
| - Auto-generates component and style files | ||
| - Validates input and prevents overwriting existing components | ||
| ## 📦 Installation | ||
| Make sure you have Node.js installed. | ||
| ```bash | ||
| npm install -g <your-cli-package-name> | ||
| ``` | ||
| Or if using locally: | ||
| ```bash | ||
| git clone https://github.com/<your-github-username>/<repo-name>.git | ||
| cd <repo-name> | ||
| npm install | ||
| ``` | ||
| ## 🔧 Usage | ||
| ```bash | ||
| generate-component <ComponentName> [options] | ||
| ``` | ||
| ### 📘 Examples | ||
| #### Basic Component (JSX + CSS) | ||
| ```bash | ||
| generate-component Button | ||
| ``` | ||
| Creates: | ||
| - `Button/index.jsx` | ||
| - `Button/index.css` | ||
| #### TypeScript + SCSS Module + Scoped Style | ||
| ```bash | ||
| generate-component AlertBox --ts --module-scss --scoped-style | ||
| ``` | ||
| Creates: | ||
| - `AlertBox/AlertBox.tsx` | ||
| - `AlertBox/AlertBox.module.scss` | ||
| #### JavaScript + SCSS | ||
| ```bash | ||
| generate-component Card --scss | ||
| ``` | ||
| Creates: | ||
| - `Card/index.jsx` | ||
| - `Card/index.scss` | ||
| #### TypeScript + CSS Module | ||
| ```bash | ||
| generate-component Modal --ts --module-css | ||
| ``` | ||
| Creates: | ||
| - `Modal/index.tsx` | ||
| - `Modal/index.module.css` | ||
| ## 🛠 Options | ||
| | Option | Description | | ||
| |--------------------|----------------------------------------------| | ||
| | `--ts` | Use TypeScript (`.tsx`) | | ||
| | `--js` | Use JavaScript (`.jsx`) (default) | | ||
| | `--css` | Include plain CSS | | ||
| | `--scss` | Include SCSS | | ||
| | `--module-css` | Use CSS Modules | | ||
| | `--module-scss` | Use SCSS Modules | | ||
| | `--scoped-style` | Use scoped style file with component name | | ||
| > ⚠️ You can only choose one of `--css`, `--scss`, `--module-css`, or `--module-scss` per component. | ||
| ## 📁 Output Structure | ||
| When using: | ||
| ```bash | ||
| generate-component Example --ts --scss --scoped-style | ||
| ``` | ||
| It creates: | ||
| ``` | ||
| Example/ | ||
| ├── Example.tsx | ||
| └── Example.scss | ||
| ``` | ||
| ## 👤 Author | ||
| **Afriduzzaman** | ||
| Experienced Web Developer | React, Angular, Ionic, React Native | ||
| GitHub: [https://github.com/Thetourist2051](https://github.com/Thetourist2051) | ||
| Email: [thetourist2051@gmail.com] | ||
| --- | ||
| ## 📝 License | ||
| MIT | ||
| --- | ||
| Feel free to contribute or raise issues! |
@@ -5,3 +5,3 @@ #!/usr/bin/env node | ||
| import path from 'path'; | ||
| import {argv} from "process" | ||
| import { argv } from 'process'; | ||
@@ -15,2 +15,9 @@ // Colors for console output | ||
| // Convert any case to PascalCase | ||
| function toPascalCase(str) { | ||
| return str.replace(/(\w)(\w*)/g, (_, firstChar, rest) => | ||
| firstChar.toUpperCase() + rest.toLowerCase() | ||
| ); | ||
| } | ||
| // Simple argument parser | ||
@@ -32,7 +39,7 @@ function parseArgs() { | ||
| if (arg.startsWith('--')) { | ||
| const option = arg.slice(2); | ||
| const option = arg.slice(2).replace(/-([a-z])/g, (g) => g[1].toUpperCase()); | ||
| if (option in result) { | ||
| result[option] = true; | ||
| } | ||
| } else { | ||
| } else if (!arg.startsWith('-')) { | ||
| result._.push(arg); | ||
@@ -46,10 +53,12 @@ } | ||
| const options = parseArgs(); | ||
| const componentName = options._[0]; | ||
| const rawComponentName = options._[0]; | ||
| // Validate component name | ||
| if (!componentName || !/^[A-Z][a-zA-Z0-9]*$/.test(componentName)) { | ||
| console.error(colors.red + 'Please provide a valid component name (PascalCase, alphanumeric)' + colors.reset); | ||
| // Validate and normalize component name | ||
| if (!rawComponentName || !/^[a-zA-Z0-9]+$/.test(rawComponentName)) { | ||
| console.error(colors.red + 'Please provide a valid component name (alphanumeric)' + colors.reset); | ||
| process.exit(1); | ||
| } | ||
| const componentName = toPascalCase(rawComponentName); | ||
| // Determine file extensions and styles | ||
@@ -60,3 +69,3 @@ const componentExt = options.ts ? 'tsx' : 'jsx'; | ||
| // Determine base filename (either component name or 'index' based on scopedStyle) | ||
| // Determine base filename (either PascalCase component name or 'index' based on scopedStyle) | ||
| const baseFileName = useScopedStyle ? componentName : 'index'; | ||
@@ -93,5 +102,2 @@ | ||
| // Generate index content | ||
| const indexContent = `export { default } from './${baseFileName}';\n`; | ||
| // Write files | ||
@@ -109,3 +115,3 @@ try { | ||
| `${componentName}.${styleExt}` : | ||
| `${baseFileName}.${styleExt}`; | ||
| `index.${styleExt}`; | ||
@@ -118,12 +124,5 @@ fs.writeFileSync( | ||
| // Index file | ||
| fs.writeFileSync( | ||
| path.join(componentDir, 'index.ts'), | ||
| indexContent | ||
| ); | ||
| console.log(colors.green + `Successfully created component "${componentName}" with:` + colors.reset); | ||
| console.log(colors.green + `- ${baseFileName}.${componentExt}` + colors.reset); | ||
| if (styleExt) console.log(colors.green + `- ${useScopedStyle ? componentName : baseFileName}.${styleExt}` + colors.reset); | ||
| console.log(colors.green + '- index.ts' + colors.reset); | ||
| if (styleExt) console.log(colors.green + `- ${useScopedStyle ? componentName : 'index'}.${styleExt}` + colors.reset); | ||
| } catch (err) { | ||
@@ -150,20 +149,28 @@ console.error(colors.red + `Error creating files: ${err.message}` + colors.reset); | ||
| const isTypeScript = componentExt === 'tsx'; | ||
| const styleImport = styleExt ? `import './${useScopedStyle ? componentName : baseFileName}.${styleExt}';\n` : ''; | ||
| const propsInterface = isTypeScript ? | ||
| `interface ${componentName}Props { | ||
| const styleFile = useScopedStyle ? `${componentName}.${styleExt}` : `index.${styleExt}`; | ||
| const styleImport = styleExt ? `import './${styleFile}';\n` : ''; | ||
| if (isTypeScript) { | ||
| return `import React from 'react'; | ||
| ${styleImport} | ||
| interface ${componentName}Props { | ||
| // Add your props here | ||
| }\n\n` : ''; | ||
| } | ||
| const componentType = isTypeScript ? | ||
| `React.FC<${componentName}Props>` : | ||
| '() => JSX.Element'; | ||
| const ${componentName}: React.FC<${componentName}Props> = ({}) => { | ||
| return ( | ||
| <div className="${useScopedStyle ? componentName.toLowerCase() : 'container'}"> | ||
| {/* Your component content */} | ||
| </div> | ||
| ); | ||
| }; | ||
| const className = useScopedStyle ? | ||
| `${componentName.toLowerCase()}` : | ||
| 'container'; | ||
| return `import React from 'react'; | ||
| ${styleImport}${propsInterface}const ${componentName}: ${componentType} = ({}) => { | ||
| export default ${componentName}; | ||
| `; | ||
| } else { | ||
| return `import React from 'react'; | ||
| ${styleImport} | ||
| const ${componentName} = (props) => { | ||
| return ( | ||
| <div className="${className}"> | ||
| <div className="${useScopedStyle ? componentName.toLowerCase() : 'container'}"> | ||
| {/* Your component content */} | ||
@@ -176,2 +183,3 @@ </div> | ||
| `; | ||
| } | ||
| } | ||
@@ -178,0 +186,0 @@ |
+1
-1
| { | ||
| "name": "react-folder-generator", | ||
| "version": "1.1.0", | ||
| "version": "2.0.0", | ||
| "description": "A CLI tool to generate React component folders with TypeScript and CSS files", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
| # create-react-folder | ||
| A CLI tool to quickly generate React component folders with TypeScript/JavaScript and various style file options. |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
8776
45.44%163
5.16%122
2950%