UNPKG

ba-block-cli

Version:
331 lines (286 loc) 12 kB
#!/usr/bin/env node // program.args[0] const { program } = require('commander'); const promptly = require('promptly'); const path = require('path'); const pjson = require('./package.json'); let themePath = process.cwd(); let localPath = path.resolve(__dirname, "./src"); const fs = require('fs'); const slugify = require('slugify'); // helper function: returns a promise that gets resolved when the specified event is fired const waitForEvent = (emitter, event) => new Promise((resolve, reject) => emitter.once(event, resolve)); /** * Block validator * @param {Boolean} value * @returns */ const blockValidator = function (value) { if (value != 'y' && value != 'yes') { throw new Error('Module not created.'); } return true; } /** * Create block command */ program .command('block:create') // sub-command name .alias('cr') // alternative sub-command is `al` .option('-n, --name [value]', 'Block name') // args.sugar = value, optional, default is 'Low' .description('Generate block folder with scss/js/php/block files.') // command description // function to execute when command is uses .action(function (args) { block = slugify(args.name, '-').toLowerCase(); if (!fs.existsSync(`${themePath}/blocks/${block}`)) { (async () => { try { const confirm = await promptly.prompt(`Create module with name: ${args.name} [y/n]: `, { blockValidator, retry: false }); // Since retry is true by default, promptly will keep asking for a name until it is valid // Between each prompt, the error message from the validator will be printed if( confirm == 'y' ){ createBlock(args.name); } } catch (err) { console.error(`- ${err.message}`); } })(); }else{ console.log(`Block ${block} already exists.`); } }); /** * Create block function * @param {String} name * @returns {Boolean} */ function createBlock(name) { var block = slugify(name, '-'); if (!fs.existsSync('blocks')) { (async () => { fs.mkdirSync(`${themePath}/blocks`); })(); } block = slugify(block, '-').toLowerCase(); (async () => { try { // Create block folder fs.mkdirSync(`${themePath}/blocks/${block}`, { recursive: true }); // Create block.json var blockContent = fs.readFileSync(`${localPath}/views/block.json`,'utf8'); blockContent = blockContent.replaceAll('default', block); blockContent = blockContent.replaceAll('Default', name); fs.writeFile(`${themePath}/blocks/${block}/block.json`, blockContent, () => {} ); // Create blockname.js var jsContent = fs.readFileSync(`${localPath}/views/block.js`,'utf8'); fs.writeFile(`${themePath}/blocks/${block}/${block}.js`, jsContent, () => {} ); // Create blockname.scss var styleContent = fs.readFileSync(`${localPath}/views/block.scss`, 'utf8'); styleContent = styleContent.replace('block-section-wrapper', `${block}-section-wrapper`); fs.writeFile(`${themePath}/blocks/${block}/${block}.scss`, styleContent, () => {} ); // Create blockname.php var phpContent = fs.readFileSync(`${localPath}/views/block.php`,'utf8'); phpContent = phpContent.replace('Block name', name); phpContent = phpContent.replace('block-section-wrapper', `${block}-section-wrapper`); fs.writeFile(`${themePath}/blocks/${block}/${block}.php`, phpContent, () => {} ); // Create blockname.png const imageReadStreem = fs.createReadStream(`${localPath}/views/block.png`); await waitForEvent(imageReadStreem, 'ready'); const imageWriteStreem = fs.createWriteStream(`${themePath}/blocks/${block}/${block}.png`); await waitForEvent(imageWriteStreem, 'ready'); imageReadStreem.pipe(imageWriteStreem); await waitForEvent(imageReadStreem, 'end'); } catch (err) { console.error(`- ${err.message}`); } })(); return true; } /** * Copy block command */ program .command('block:copy') // sub-command name .alias('cp') // alternative sub-command is `al` .option('-n, --name [value]', 'Block name') // args.sugar = value, optional, default is 'Low' .description('Copy a predefined block and local JSON by name.') // command description // function to execute when command is uses .action(function (args) { block = slugify(args.name, '-').toLowerCase(); if (!fs.existsSync(`${themePath}/blocks/${block}`) && fs.existsSync(`${localPath}/blocks/${block}`)) { (async () => { try { const confirm = await promptly.prompt(`Copy an existing block with name: ${args.name} [y/n]: `, { blockValidator, retry: false }); // Since retry is true by default, promptly will keep asking for a name until it is valid // Between each prompt, the error message from the validator will be printed if (confirm == 'y') { copyBlock(args.name); } } catch (err) { console.error(`- ${err.message}`); } })(); } else if (!fs.existsSync(`${localPath}/blocks/${block}`)) { console.log(`There is no predefined block with name ${args.name}.`); } else { console.log(`Block ${block} already exists.`); } }); /** * Create block function * @param {String} name * @returns {Boolean} */ function copyBlock(name) { var block = slugify(name, '-'); // Check if the blocks folder exists. If doesn't create it if (!fs.existsSync('blocks')) { (async () => { fs.mkdirSync(`${themePath}/blocks`); })(); } // Check if the acf-json folder exists. If doesn't create it if (!fs.existsSync('acf-json')) { (async () => { fs.mkdirSync(`${themePath}/acf-json`); })(); } // Create block slug block = slugify(block, '-').toLowerCase(); (async () => { try { // Create block folder inside the blocks folder in theme root fs.mkdirSync(`${themePath}/blocks/${block}`, { recursive: true }); // Create block.json var blockContent = fs.readFileSync(`${localPath}/views/block.json`,'utf8'); blockContent = blockContent.replaceAll('default', block); blockContent = blockContent.replaceAll('Default', name); fs.writeFile(`${themePath}/blocks/${block}/block.json`, blockContent, () => {} ); // Copy {block}.js var jsContent = fs.readFileSync(`${localPath}/blocks/${block}/${block}.js`,'utf8'); fs.writeFile(`${themePath}/blocks/${block}/${block}.js`, jsContent, () => {} ); // Copy {block}.scss var styleContent = fs.readFileSync(`${localPath}/blocks/${block}/${block}.scss`,'utf8'); fs.writeFile(`${themePath}/blocks/${block}/${block}.scss`, styleContent, () => {} ); // Copy {block}.php var phpContent = fs.readFileSync(`${localPath}/blocks/${block}/${block}.php`,'utf8'); fs.writeFile(`${themePath}/blocks/${block}/${block}.php`, phpContent, () => {} ); // Copy {block}.png const imageReadStreem = fs.createReadStream(`${localPath}/blocks/${block}/${block}.png`); await waitForEvent(imageReadStreem, 'ready'); const imageWriteStreem = fs.createWriteStream(`${themePath}/blocks/${block}/${block}.png`); await waitForEvent(imageWriteStreem, 'ready'); imageReadStreem.pipe(imageWriteStreem); await waitForEvent(imageReadStreem, 'end'); // Copy the local JSON file var jsonContent = fs.readFileSync(`${localPath}/acf-json/${block}.json`,'utf8'), realJson = JSON.parse(jsonContent), key = realJson.key; fs.writeFile(`${themePath}/acf-json/${key}.json`, jsonContent, () => {}); } catch (err) { console.error(`- ${err.message}`); } })(); return true; } /** * Delete block command */ program .command('block:delete') // sub-command name .alias('rm') // alternative sub-command is `al` .option('-n, --name [value]', 'Block name') // args.sugar = value, optional, default is 'Low' .description('Delete block folder containing scss/js/php/block files.') // command description // function to execute when command is uses .action(function (args) { block = slugify(args.name, '-').toLowerCase(); if (fs.existsSync(`${themePath}/blocks/${block}`)) { (async () => { try { const confirm = await promptly.prompt(`Are you sure that you want to delete block: ${args.name} [y/n]: `, { blockValidator, retry: false }); // Since retry is true by default, promptly will keep asking for a name until it is valid // Between each prompt, the error message from the validator will be printed if (confirm == 'y') { block = slugify(args.name, '-').toLowerCase(); fs.rm(`${themePath}/blocks/${block}`, { recursive: true }, err => { if (err) { throw err } console.log(`The ${args.name} block has successfully removed.`); // Check if there is a local JSON file created by this module if (fs.existsSync(`${themePath}/acf-json/${block}.json`)) { fs.rm(`${themePath}/acf-json/${block}.json`, { recursive: true }, err => { if (err) { throw err } console.log(`The ${block}.json local JSON file has successfully removed.`); }); } }); } } catch (err) { console.error(`- ${err.message}`); } })(); } else { console.log(`Block ${block} doesn't exists.`); } }); /** * Output the list of available blocks */ program .command('block:list') .alias('list') .description('Output the list of available blocks') .action(function () { console.log('List of all blocks (use ba-block cp -n "BLOCKNAME" to copy): \n'); fs.readdir(`${localPath}/blocks/`, (err, files) => { files.forEach(file => { console.log(file); }); }); }); /** * Return the current version */ program .version(pjson.version) // set the version for the program .option('-v, --version', 'Output the version number'); /** * Output information about the package */ program .command('block:info') .alias('info') .description('Output information about the package') .action(function () { console.log(` ${pjson.description} Available commands: \n Check the current version of this package: ba-block -v ba-block --version \n Get informations about this package: ba-block info \n Create a new block: ba-block cr -n "BLCOKNAME" \n List of all blocks: ba-block list \n Copy an existing block: ba-block cp -n "BLCOKNAME" \n Remove a block: ba-block rm -n "BLCOKNAME" `); }); /* * Parse */ program .parse(process.argv);