Skip to content

Instantly share code, notes, and snippets.

@liamross
Last active April 16, 2019 00:50
Show Gist options
  • Save liamross/cd7648c02f66544c1db965a000a7f255 to your computer and use it in GitHub Desktop.
Save liamross/cd7648c02f66544c1db965a000a7f255 to your computer and use it in GitHub Desktop.
A script to quickly spin up a component folder
/*
* This is a helper file for component.js. It provides the string content for
* various component files.
*/
/**
* Builds ComponentNameContainer.js
* @param {string} componentName Name of component.
*/
const container = componentName =>
`import { connect } from 'react-redux';
import Component from './${componentName}';
const mapStateToProps = state => ({});
const mapDispatchToProps = dispatch => ({});
const ${componentName} = connect(
mapStateToProps,
mapDispatchToProps,
)(Component);
export default ${componentName};
`;
/**
* Builds ComponentName.jsx
* @param {string} componentName Name of component.
* @param {boolean} isClass Is component a class.
* @param {string} classPrefix Prefix for class.
*/
const component = (componentName, isClass, classPrefix) =>
!isClass
? `import React from 'react';
import PropTypes from 'prop-types';
import './${componentName}.scss';
const propTypes = {};
const defaultProps = {};
function ${componentName}({}) {
return <div className="${classPrefix}${componentName}">{'Hello World'}</div>;
}
${componentName}.propTypes = propTypes;
${componentName}.defaultProps = defaultProps;
export default ${componentName};
`
: `import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './${componentName}.scss';
const propTypes = {};
const defaultProps = {};
class ${componentName} extends Component {
state = {};
render() {
const {} = this.state;
const {} = this.props;
return <div className="${classPrefix}${componentName}">{'Hello World'}</div>;
}
}
${componentName}.propTypes = propTypes;
${componentName}.defaultProps = defaultProps;
export default ${componentName};
`;
/**
* Builds ComponentName.scss
* @param {string} componentName Name of component.
* @param {string} classPrefix Prefix for class.
*/
const style = (componentName, classPrefix) => `.${classPrefix}${componentName} {
}
`;
module.exports = {
container,
component,
style,
};
'use strict';
const fs = require('fs');
const files = require('./files');
const container = files.container;
const component = files.component;
const style = files.style;
const componentRegex = /^[^-].*/;
const pathRegex = /^--?p(ath)?=/;
const styleRegex = /^--?s(tyle)?=/;
/* eslint-disable */
const log = console.log;
const err = message => console.error('\x1b[41m%s\x1b[0m', message);
/* eslint-enable */
const args = process.argv.slice(2);
const hasHelpFlag = args.includes('-h') || args.includes('--help');
if (hasHelpFlag) {
log(`
Usage: yarn component <ComponentName> [OPTIONS]
ComponentName:
The name of the component to create. This will be appended to any path
specified using the -p= option. For example, if the path is "src/components"
and ComponentName is "Button" then the created component will be located at
"src/components/Button" in your project.
ComponentName can also be a path to create the component within a folder.
For example, if ComponentName is "Common/Button" (and your path is still
"src/components"), then you will create a component at
"src/components/Common/Button".
OPTIONS:
-c, --class Create a class instead of functional component
-r, --redux Has Redux container file
-h, --help Open the help menu
The following options should probably be specified in your package.json
script to avoid re-typing for each component:
-p='<Path>', Specify the path to the component folder
--path='<Path>'
-s='<Prefix>', A prefix for classNames in your components
--style='<Prefix>'
`);
} else {
const componentNamePath = args.find(arg => componentRegex.test(arg));
const pathFlag = args.find(arg => pathRegex.test(arg));
const styleFlag = args.find(arg => styleRegex.test(arg));
const isClass = args.includes('-c') || args.includes('--class');
const isRedux = args.includes('-r') || args.includes('--redux');
let componentPath = '';
let classNamePrefix = '';
if (pathFlag) componentPath = pathFlag.split('=')[1];
if (styleFlag) classNamePrefix = styleFlag.split('=')[1];
if (!componentNamePath) {
err('No component name specified. Must follow the following format:');
err('yarn component <ComponentName> [OPTIONS]');
err('Call `yarn component --help for more information`.');
} else {
const pathSegs = componentNamePath.split('/');
const componentName = pathSegs.pop();
const extendedPath = pathSegs.length ? `/${pathSegs.join('/')}` : '';
const parentDir = `${componentPath}${extendedPath}`;
const dir = `${parentDir}/${componentName}`;
if (!fs.existsSync(parentDir)) {
err(`Unable to find parent directory:`);
err(parentDir);
} else if (fs.existsSync(dir)) {
err(`Component ${componentName} already exists.`);
} else {
// Make folder.
fs.mkdirSync(dir);
// Make container if is Redux.
if (isRedux) {
fs.writeFile(
`${dir}/${componentName}Container.js`,
container(componentName, classNamePrefix),
err => {
if (err) {
err('Error creating container.');
} else {
log('Container was created.');
}
},
);
}
// Make component.
fs.writeFile(
`${dir}/${componentName}.jsx`,
component(componentName, isClass, classNamePrefix),
err => {
if (err) {
err('Error creating component.');
} else {
log('Component was created.');
}
},
);
// Make stylesheet.
fs.writeFile(
`${dir}/${componentName}.scss`,
style(componentName, classNamePrefix),
err => {
if (err) {
err('Error creating sass.');
} else {
log('Sass was created.');
}
},
);
}
}
}
{
"name": "example-package",
"version": "0.0.0",
"description": "An example of how to set up the component script.",
"author": "Liam Ross",
"scripts": {
"__comment": "To create a functional component, call `yarn component MyComponent`",
"make": "node scripts/make/make.js -p='src/components' -s='prefix-'"
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment