plopfile.js (231 lines of code) (raw):

const fs = require('fs'); // eslint-disable-line const PATH = 'components/{{pascalCase name}}'; const REACT_PATH = 'adapters/react/{{pascalCase name}}React'; const VUE_PATH = 'adapters/vue/{{pascalCase name}}Vue'; const PLOP_PATH = 'plopTemplates/Component'; const PLOP_REACT = 'plopTemplates/reactAdapters'; const PLOP_VUE = 'plopTemplates/vueAdapters'; const reactActions = [ { type: 'add', path: `${REACT_PATH}/src/{{pascalCase name}}.tsx`, templateFile: `${PLOP_REACT}/src/Component.tsx.hbs` }, { type: 'add', path: `${REACT_PATH}/src/I{{pascalCase name}}.tsx`, templateFile: `${PLOP_REACT}/src/IComponent.tsx.hbs` }, { type: 'add', path: `${REACT_PATH}/src/index.tsx`, templateFile: `${PLOP_REACT}/src/index.tsx.hbs` }, { type: 'add', path: `${REACT_PATH}/.babelrc`, templateFile: `${PLOP_REACT}/.babelrc.hbs` }, { type: 'add', path: `${REACT_PATH}/package.json`, templateFile: `${PLOP_REACT}/package.json.hbs` }, { type: 'add', path: `${REACT_PATH}/{{pascalCase name}}.stories.tsx`, templateFile: `${PLOP_REACT}/index.stories.tsx.hbs` }, { type: 'add', path: `${REACT_PATH}/README.md`, templateFile: `${PLOP_REACT}/README.md.hbs` }, { type: 'add', path: `${REACT_PATH}/tsconfig.json`, templateFile: `${PLOP_REACT}/tsconfig.json.hbs` }, // import react adaptor in gatsby site so markdown files will display { type: 'modify', path: 'www/src/templates/Component/Component.tsx', pattern: /(@@ GENERATOR IMPORT COMPONENT)/g, template: "$1\nimport '@rhythm-ui/{{packageName name}}-react';", }, /** * Adds new dependency to gatsby site package.json * ASSUMPTIONS for this to work: * 1. at least one other @rhythm-ui/some-react-component exists in file * 2. the newly added package is not the last package listed (as it adds a comma * and this will not be valid json if added at end) */ { type: 'modify', path: 'www/package.json', pattern: /("@rhythm-ui\/[a-zA-Z-]*": "\^[0-9]*.[0-9]*.[0-9]*",)/, template: "$1\n\"@rhythm-ui/{{packageName name}}-react\": \"^0.1.0\",", } ]; const vueActions = [ { type: 'add', path: `${VUE_PATH}/README.md`, templateFile: `${PLOP_VUE}/readme.md.hbs` }, { type: 'add', path: `${VUE_PATH}/src/{{pascalCase name}}.vue`, templateFile: `${PLOP_VUE}/src/Component.vue.hbs` }, { type: 'add', path: `${VUE_PATH}/src/index.ts`, templateFile: `${PLOP_VUE}/src/index.ts.hbs` }, { type: 'add', path: `${VUE_PATH}/.babelrc`, templateFile: `${PLOP_VUE}/.babelrc.hbs` }, { type: 'add', path: `${VUE_PATH}/package.json`, templateFile: `${PLOP_VUE}/package.json.hbs` }, { type: 'add', path: `${VUE_PATH}/{{pascalCase name}}.stories.tsx`, templateFile: `${PLOP_VUE}/index.stories.tsx.hbs` }, { type: 'add', path: `${VUE_PATH}/tsconfig.json`, templateFile: `${PLOP_VUE}/tsconfig.json.hbs` }, ]; const isNotEmpty = name => { return ( value ) => { return value.length === 0 ? `${name} is required` : true; } }; const checkFile = file => { try { fs.accessSync(file, fs.constants.R_OK); return true; } catch (err) { return false; } }; const checkComponent = () => { const choices = []; fs .readdirSync('./components') .forEach(file => { if (!checkFile(`adapters/react/${file}React`)) { choices.push(file) } }); return choices }; const ensureRui = text => `rui ${text.replace(/Rui/gi, "")}`; // converts 'rui component name' and for a package we just need 'component-name' const packageName = text => text.replace(/rui/gi, "").trim().split(' ').join('-').toLowerCase(); module.exports = plop => { plop.setHelper('packageName', packageName); plop.setGenerator('component', { description: 'create a new component', //prompts are user inputs that provided as arguments to the templates prompts: [ { // Raw text input type: 'input', // Variable name for this input name: 'name', // Prompt to display on command line message: 'What is your component name?', // validate the field is not empty validate: isNotEmpty( 'name'), //format the component to have Rui filter: ensureRui }, { type: 'list', name: 'adapter', message: 'Do you also need an adapter?', choices: ['Not yet', 'React', 'Vue'], }, ], actions: data => { let actions = []; actions = actions.concat([ { type: 'add', path: `${PATH}/tsconfig.json`, templateFile: `${PLOP_PATH}/tsconfig.json.hbs` }, { type: 'add', path: `${PATH}/.babelrc`, templateFile: `${PLOP_PATH}/.babelrc.hbs` }, { type: 'add', path: `${PATH}/package.json`, templateFile: `${PLOP_PATH}/package.json.hbs` }, { type: 'add', path: `${PATH}/readme.md`, templateFile: `${PLOP_PATH}/readme.md.hbs` }, //src files - component, css and index { type: 'add', path: `${PATH}/src/{{pascalCase name}}.ts`, templateFile: `${PLOP_PATH}/src/Component.ts.hbs` }, { type: 'add', path: `${PATH}/src/{{pascalCase name}}.css.ts`, templateFile: `${PLOP_PATH}/src/Component.css.ts.hbs` }, { type: 'add', path: `${PATH}/src/index.ts`, templateFile: `${PLOP_PATH}/src/index.ts.hbs` }, { type: 'add', path: `${PATH}/tests/{{pascalCase name}}.test.ts`, templateFile: `${PLOP_PATH}/tests/Component.test.ts.hbs` }, { type: 'add', path: `${PATH}/tests/tsconfig.json`, templateFile: `${PLOP_PATH}/tests/tsconfig.json.hbs` } ]); if (data.adapter === 'React' || data.adapter === 'Both') { actions = actions.concat(reactActions) } if (data.adapter === 'Vue' || data.adapter === 'Both') { actions = actions.concat(vueActions) } return actions }, }); plop.setGenerator('adapter', { description: 'Create an adapter that wraps the html component', //prompts are user inputs that provided as arguments to the templates prompts: [ { type: 'list', name: 'name', message: 'Please chose your component', choices: () => { return checkComponent() }, }, { type: 'list', name: 'adapter', message: 'Please chose an adapter', choices: ['React', 'Vue'], }, ], actions: data => { let actions = []; if (data.adapter === 'React' || data.adapter === 'Both') { actions = actions.concat(reactActions) } if (data.adapter === 'Vue' || data.adapter === 'Both') { actions = actions.concat(vueActions) } return actions }, }) };