Created
June 10, 2023 06:14
-
-
Save lensanag/18187ad37c0013d483a0d31bca3cde2d to your computer and use it in GitHub Desktop.
automate creation of react components, you can easily update file templates to your needs π
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
// include script in package.json the line number 6 | |
{ | |
"scripts": { | |
"mk:component": "node scripts/component-builder.js" | |
} | |
} | |
// then use: | |
npm run mk:component MyComponent [OPTIONS] | |
npm run mk:component --help | |
*/ | |
import fs from 'fs' | |
/** | |
* body definition of jsx component | |
* @param {string} name | |
* @returns | |
*/ | |
const componentTag = (name) => `import styles from './${name}.module.css'; | |
export default function ${name} () { | |
return (<> | |
<span className={styles.${name}}>${name} needs to be implement π !</span> | |
</>); | |
}; | |
export { ${name} }; | |
` | |
/** | |
* body definition of css component styles | |
* @param {string} name | |
* @returns | |
*/ | |
const stylesTag = (name) => `.${name} { | |
font-weight: bold; | |
font-style: italic; | |
color: red; | |
} | |
` | |
/** | |
* body definition of index file to export component | |
* @param {string} name | |
* @returns | |
*/ | |
const indexTag = (name) => `import ${name} from "./${name}"; | |
export default ${name}; | |
export { ${name} }; | |
` | |
/** | |
* | |
* @param {string} name | |
* @param {boolean} includeDir | |
* @param {string?} differentPath | |
* @returns | |
*/ | |
const Work = (name, includeDir, differentPath = 'components') => { | |
const path = `./src/${differentPath}` + (!includeDir ? '' : '/' + name) | |
const Files = [ | |
[`${path}/${name}.jsx`, componentTag(name)], | |
[`${path}/${name}.module.css`, stylesTag(name)], | |
[`${path}/index.js`, indexTag(name)], | |
] | |
if (!includeDir) { | |
Files.pop() | |
} | |
return [path, Files] | |
} | |
/** | |
* prints multiple strings to console with an optional callback formatter | |
* @param {(string) => string} callback | |
* @param {[string]} strings | |
*/ | |
const GenericPrintMultiple = (strings, callback = (value) => value) => { | |
strings.forEach(string => { | |
console.log(callback(string)) | |
}) | |
} | |
const START_MESSAGE = [ | |
'====================================', | |
' React Component Builder', | |
'====================================', | |
] | |
const OPTIONS = [ | |
' OPTIONS:', | |
' --dir flag to create component directory where to keep component files π (not created by default, optional)', | |
' --preserve flag to preserve previous component directory and files π', | |
' --wipe flag to remove previous component directory π§', | |
' --overwrite flag to overwrite existing files (works with --preserve flag) π', | |
] | |
const EXAMPLES = [ | |
' EXAMPLES: ', | |
' MyComponent --dir', | |
' MyComponent:views/bussines/final', | |
' MyComponent:views/bussines/final --preserve --dir', | |
' OtherComponent:pages/public --preserve --overwrite', | |
' AnotherComponent:components/shared --wipe --dir', | |
] | |
const HELP = [ | |
'', | |
'HELP:', | |
'', | |
...OPTIONS, | |
'', | |
...EXAMPLES, | |
'', | |
] | |
GenericPrintMultiple(START_MESSAGE) | |
if (process.argv.includes('--help') || process.argv.includes('-h')) { | |
GenericPrintMultiple(HELP) | |
process.exit(0) | |
} | |
const args = process.argv.slice(2) | |
if (args.length === 0) { | |
console.log('Please provide a component name') | |
process.exit(1) | |
} | |
const firstArg = args[0] | |
const wipe = args.includes('--wipe') | |
const preserve = args.includes('--preserve') | |
const overwrite = args.includes('--overwrite') | |
const includeDir = args.includes('--dir') | |
if (preserve && wipe) { | |
console.log('You can use only one of --preserve or --wipe flags at time') | |
process.exit(1) | |
} | |
if (firstArg.length === 0) { | |
console.log('Please provide a component name') | |
process.exit(1) | |
} | |
if (!/^[A-Z]{1,1}[a-zA-Z0-9]+:{0,1}[a-zA-Z0-9]+[a-zA-Z0-9/]+[a-zA-Z0-9]+$/.test(firstArg) || firstArg.split('/').includes('')) { | |
console.log('Please provide a valid component name in PascalCase format') | |
process.exit(1) | |
} | |
const [componentName, rootPath] = firstArg.split(':') | |
if (!includeDir && wipe) { | |
console.log('You cannot use --wipe flag without --dir flag to avoid unintended directory deletion π') | |
process.exit(1) | |
} | |
console.log('Starting component creation...') | |
const [componentPath, files] = Work(componentName, includeDir, rootPath) | |
if (includeDir) { | |
if (fs.existsSync(componentPath) && fs.statSync(componentPath).isDirectory()) { | |
if (wipe) { | |
console.log('You choosse remove previous component directory π₯Ά') | |
fs.rmSync(componentPath, { recursive: true }); | |
fs.mkdirSync(componentPath); | |
} else { | |
if (preserve) { | |
console.log('You choosse preserve previous component directory π') | |
} else { | |
GenericPrintMultiple([ | |
'Directory already exist π€¨', | |
'You can use:', | |
...OPTIONS.slice(1), | |
...files.map(([file,]) => file), | |
'Or call the command with -h or --help for examples!' | |
]) | |
process.exit(1) | |
} | |
} | |
} else { | |
fs.mkdirSync(componentPath, { recursive: true }); | |
} | |
} | |
if (files.some(([file,]) => { | |
return fs.existsSync(file) | |
}) && !overwrite) { | |
console.log(`some files already exist in directory '${componentPath}' π€¨, use --overwrite flag to overwrite existing files that match some of:`) | |
GenericPrintMultiple(files.map(([file,]) => file)) | |
process.exit(1) | |
} | |
if (overwrite) { | |
console.log('You choosse overwrite existing files matched π₯Ά'); | |
} | |
files.forEach(([file, tag]) => fs.writeFile( file, tag, () => undefined)); | |
GenericPrintMultiple([ | |
'', | |
'Component created successfully πβ¨!', | |
'', | |
`Next files were created${overwrite ? ' or overwritten' : ''}:`, | |
...files.map(([file,]) => file) | |
]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment