UNPKG

generator-bat

Version:

BAT, the Backbone Application Template; a Yeoman generator collection created by marviq

218 lines (184 loc) 7.08 kB
// // Mix in template utilities for generators. // 'use strict'; var _ = require( 'lodash' ) , chalk = require( 'chalk' ) , fsCore = require( 'fs' ) , path = require( 'path' ) ; module.exports = { /** * Churn out a commonly styled generator description. * * @method: _description * * @param {String} what String injected into the common descriptor template. * * @return {String} The expanded description. */ _description: function ( what ) { return chalk.bold( 'This is the ' + chalk.cyan( what ) + ' generator for BAT, the Backbone Application Template' + ' created by ' + chalk.blue( 'marv' ) + chalk.red( 'iq' ) + '.' ); } , /** * Takes an array of prompt definitions, as would be passed to `this.prompt()`, filters away those for which valid values have been supplied via the * identically named command line options, fills the `this.templateData` object with those values and returns the pruned list. * @method _promptPruneByOptions * * @param {Array} prompts An array of prompt definitions as would be passed to `this.prompt()`. * * @return {Array} The prompts for which no valid value has been supplied through a command line option. */ _promptsPruneByOptions: function ( prompts ) { var options = this.options , data = this.templateData , remaining = [] , prompt , name , value , final , index , validate , filter ; for ( index = prompts.length; index--; ) { prompt = prompts[ index ]; name = prompt.name; value = options[ name ]; final = null; if ( value != null ) { if ( !(( validate = prompt.validate )) || validate( value )) { final = (( filter = prompt.filter )) ? filter( value ) : value; } } if ( final != null ) { data[ name ] = final; } else { remaining.unshift( prompt ); } } return remaining; } , /** * Process template files; either copying them as-is from `#sourceRoot()` to `#destinationRoot()`, or expanding them with `#templateData` first. * * @method _templatesProcess * * @param {Array|Object} templates * * - Either an array of template files to copy or expand keeping relative paths identical in both roots. * In this case, the destination path will be cleared from any '@' exempt markers that may be present in the * source path. * * - Or an object hash mapping source- to destination paths relative to each root respectively. * In this case, the destination path is used as-is. * * In either case, the hash- or array element values can be simple strings or arrays. * * * A string indicates to do a simple `#fs.copy()`; * * An array indicates to use `fs.copyTpl()` instead, its first element providing the path and the (optional) second element becoming the `options` * arguments to `#fs.copyTpl()`. */ _templatesProcess: function ( templates ) { /* jshint forin: false */ var src, dst, args, method , fs = this.fs ; for ( src in templates ) { dst = templates[ src ]; if ( _.isArray( dst ) ) { // Template expansion needed. method = fs.copyTpl; args = [ this.templateData ].concat( dst.slice( 1, 2 )); dst = dst[ 0 ]; } else { method = fs.copy; args = []; } if ( /^\d+$/.test( src )) // numeric index, ergo: `templates` is an `Array`. { src = dst; // Remove exempt markers. // dst = dst.replace( /(^|\/)@/g, '$1' ); } args.unshift( this.templatePath( src ), this.destinationPath( dst )); method.apply( fs, args ); } } , /** * Make a symbolic link within `#destinationRoot()`. * * @method _symLink * * @param {String} src The path relative to `#destinationRoot()` that should become the target of the symbolic link. * @param {String} dst The path relative to `#destinationRoot()` that should become the symbolic link. * */ _symLink: function ( src, dst ) { src = this.destinationPath( src ); dst = this.destinationPath( dst ); this.conflicter.checkForCollision( dst , this.fs.read( src ) , ( err, status ) => { if ( 'identical' === status ) { return; } // The symlink may exist, but may link to a nonexistent file in which case `status` will be `'create'`, so try unlinking it anyway. // try { fsCore.unlinkSync( dst ); } catch ( error ) { if ( 'ENOENT' !== error.code ) { throw error; } } src = path.relative( path.dirname( dst ), src ); fsCore.symlinkSync( src, dst ); this.log( chalk.magenta( 'symlinked' ) + ' -> ' + src ); } ); } , /** * Test whether the destination root is safely empty for generating an app in. * * @method _isRootSafe * * @return {Boolean Whether the destination root is safely empty for generating an app in. */ _isRootSafe: function () { var root = this.destinationRoot() , entries = fsCore.readdirSync( root ) , safe = [ '.git' ] ; return 0 === _.difference( entries, safe ).length; } } ;