diff --git a/README.md b/README.md index 0855536..1bc9b85 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ yo rang ## Generators * [rang:screen](#screen) -* rang:partial - TODO +* [rang:partial](#partial) * rang:service - TODO **Note: Generators are to be run from the root directory of your app.** @@ -38,6 +38,16 @@ Example: yo rang:screen ``` +### Partial + +Generates a partial module with a view and optionally a controller + +Example: + +```bash +yo rang:partial +``` + ## Testing ```bash gulp test diff --git a/generators/partial/index.js b/generators/partial/index.js new file mode 100644 index 0000000..e207cc3 --- /dev/null +++ b/generators/partial/index.js @@ -0,0 +1,172 @@ +'use strict'; + +/** + * Dependencies + */ +var yeoman = require('yeoman-generator'); +var util = require('util'); +var chalk = require('chalk'); + +/** + * Configuration + */ +var config = { + appModules: './workspace/scripts/app/appModules.js', + partialsPath: './workspace/scripts/app/partials/', + controllerSubPath: 'controllers/', + viewSubPath: 'templates/' +}; + +/** + * User answers + */ +var userAnswers = { + partialName: null, + createController: null +}; + +/** + * RangPartialGenerator + * + * Always overwrites the file if a conflict occurred. + * @constructor + */ +function RangPartialGenerator() { + yeoman.generators.Base.apply( this, arguments ); + + this.conflicter.force = true; + + /** + * Show information on completion. + */ + this.on('end', function () { + this.log( + '\n\n' + chalk.green('Success!') + ' Partial \'' + userAnswers.partialName + '\' created!' + ); + }.bind( this )); +} + +util.inherits( RangPartialGenerator, yeoman.generators.Base ); + +/** + * Show greeting + */ +RangPartialGenerator.prototype.greeting = function () { + this.log( + chalk.blue("\n _ _ _ \n" + + " | | (_) | |\n" + + " _ __ __ _ _ __ __ _ _ __ __ _ _ __| |_ _ __ _| |\n" + + "| '__/ _` | '_ \\ / _` | | '_ \\ / _` | '__| __| |/ _` | |\n" + + "| | | (_| | | | | (_| | _ | |_) | (_| | | | |_| | (_| | |\n" + + "|_| \\__,_|_| |_|\\__, | (_) | .__/ \\__,_|_| \\__|_|\\__,_|_|\n" + + " __/ | | | \n" + + " |___/ |_| \n") + ); + + this.log( + chalk.yellow('Welcome! I\'ll help you create a module. Answer the following questions.\n') + ); +}; + +/** + * Obtain the information which is needed to generate the module. + */ +RangPartialGenerator.prototype.prompting = function () { + var done = this.async(); + + this.prompt( + [ + { + type : 'input', + name : 'partial', + message : 'Partial name', + validate: function( partial ) { + return ( partial.length ) ? true : 'You must provide a partial name'; + } + }, + { + type : 'confirm', + name : 'controller', + message : 'Need to create a controller?' + } + ], + function ( answers ) { + userAnswers.partialName = answers.partial; + userAnswers.createController = answers.controller; + + done(); + } + ); +}; + +/** +* Create the module files +*/ +RangPartialGenerator.prototype.writing = function () { + var partialPath = config.partialsPath + userAnswers.partialName + '/'; + var controllerPath = partialPath + config.controllerSubPath + userAnswers.partialName + 'Controller.js'; + var viewPath = partialPath + config.viewSubPath + userAnswers.partialName + '.tmpl.html'; + + // template + this.template('./view.tmpl', viewPath, { partial: userAnswers.partialName }, {}); + + if ( userAnswers.createController ) { + + // main + this.template('./main.tmpl', partialPath + '/main.js', { partial: userAnswers.partialName }, {}); + + // controller + this.template('./controller.tmpl', controllerPath, { partial: userAnswers.partialName }, {}); + + } +}; + +/** +* Read an application dependencies +*/ +RangPartialGenerator.prototype._getDependencies = function () { + return this.readFileAsString( config.appModules ); +}; + +/** +* Add module as the application dependency +*/ +RangPartialGenerator.prototype.updateDependencies = function () { + + // do not update dependencies, because the controller is not created + if ( !userAnswers.createController ) { + return; + } + + var appModulesSrc = this._getDependencies(); + var appModules = []; + var lastModule; + + /** + * CommonJS RegExp + * Find all `require('module')` + */ + var cjsRegExp = /require\s*\(\s*["']([^'"\s]+)["']\s*\)/g; + + appModulesSrc.replace( cjsRegExp, function ( module ) { + appModules.push( module ); + }); + + lastModule = appModules.pop(); + + /** + * before: + * require('oldmodule') + * after: + * require('oldmodule'), + * require('module') + */ + appModulesSrc = appModulesSrc.replace( + lastModule, + lastModule + ',\n' + ' require(\'partials/' + userAnswers.partialName + '/main\')' + ); + + this.write( config.appModules, appModulesSrc ); +}; + +module.exports = RangPartialGenerator; diff --git a/generators/partial/templates/controller.tmpl b/generators/partial/templates/controller.tmpl new file mode 100644 index 0000000..f919a3b --- /dev/null +++ b/generators/partial/templates/controller.tmpl @@ -0,0 +1,9 @@ +define(function () { + 'use strict'; + + return { + <%= partial %>Controller: ['$scope', function ( $scope ) { + $scope.partial = '<%= partial %>'; + }] + }; +}); diff --git a/generators/partial/templates/main.tmpl b/generators/partial/templates/main.tmpl new file mode 100644 index 0000000..221ee27 --- /dev/null +++ b/generators/partial/templates/main.tmpl @@ -0,0 +1,14 @@ +define(function ( require ) { + 'use strict'; + + /** + * Dependencies + */ + var angular = require('angular'); + var <%= partial %>Controller = require('./controllers/<%= partial %>Controller'); + + /** + * Module: <%= partial %> partial + */ + return angular.module('app.<%= partial %>', []).controller( <%= partial %>Controller ); +}); \ No newline at end of file diff --git a/generators/partial/templates/view.tmpl b/generators/partial/templates/view.tmpl new file mode 100644 index 0000000..6f0070b --- /dev/null +++ b/generators/partial/templates/view.tmpl @@ -0,0 +1,4 @@ +
+ + Partial successfully created +
diff --git a/generators/screen/index.js b/generators/screen/index.js index c04bca0..5a8c7bd 100644 --- a/generators/screen/index.js +++ b/generators/screen/index.js @@ -35,6 +35,15 @@ function RangScreenGenerator() { yeoman.generators.Base.apply( this, arguments ); this.conflicter.force = true; + + /** + * Show information on completion. + */ + this.on('end', function () { + this.log( + '\n\n' + chalk.green('Success!') + ' Screen \'' + userAnswers.screenName + '\' created!' + ); + }.bind( this )); } util.inherits( RangScreenGenerator, yeoman.generators.Base ); @@ -156,13 +165,4 @@ RangScreenGenerator.prototype.updateDependencies = function () { this.write( config.appModules, appModulesSrc ); }; -/** - * Show information on completion. - */ -RangScreenGenerator.prototype.end = function () { - this.log( - '\n\n' + chalk.green('Success!') + ' Screen \'' + userAnswers.screenName + '\' created!' - ); -}; - module.exports = RangScreenGenerator; diff --git a/test/test-partial-creation.js b/test/test-partial-creation.js new file mode 100644 index 0000000..1ac7f99 --- /dev/null +++ b/test/test-partial-creation.js @@ -0,0 +1,91 @@ +'use strict'; + +/** + * Dependencies + */ +var path = require('path'); +var helpers = require('yeoman-generator').test; +var assert = require('yeoman-generator').assert; +var output = require('./mute'); + +describe('rang:partial generator', function () { + var rangPartial; + var tempFolder = 'tmp/tmpRangPartial'; + var expected = { + withController: { + exist: [ + 'workspace/scripts/app/partials/test/main.js', + 'workspace/scripts/app/partials/test/templates/test.tmpl.html', + 'workspace/scripts/app/partials/test/controllers/testController.js' + ] + }, + withoutController: { + exist: [ + 'workspace/scripts/app/partials/test/templates/test.tmpl.html' + ], + notExist: [ + 'workspace/scripts/app/partials/test/main.js', + 'workspace/scripts/app/partials/test/controllers/testController.js' + ] + } + + }; + + var expectedContent = [ + [ + 'workspace/scripts/app/partials/test/main.js', + /var testController = require\('\.\/controllers\/testController'\);/ + ], + [ 'workspace/scripts/app/partials/test/main.js', /Module: test partial/ ], + [ + 'workspace/scripts/app/partials/test/main.js', + /return angular\.module\('app.test', \[]\)\.controller\( testController \);/ + ], + [ 'workspace/scripts/app/partials/test/controllers/testController.js', /testController:/ ], + [ 'workspace/scripts/app/appModules.js', /require\('partials\/test\/main'\)/ ] + ]; + + beforeEach(function ( done ) { + helpers.testDirectory( path.join( __dirname, tempFolder ), function ( error ) { + if ( error ) { + done( error ); + } + + rangPartial = helpers.createGenerator( 'rang:partial', ['../../../generators/partial'], [], {} ); + rangPartial.on('run', output.mute); + rangPartial.on('end', output.unmute); + + helpers.stub( rangPartial, '_getDependencies', function () { + return "return [\n" + + " require('partials/old/module')\n" + + "];"; + }); + + done(); + }); + }); + + it('should generate the partial without controller', function ( done ) { + helpers.mockPrompt( rangPartial, { partial: 'test', controller: false } ); + + rangPartial.run( {}, function () { + + assert.file( expected.withoutController.exist ); + assert.noFile( expected.withoutController.notExist ); + + done(); + }); + }); + + it('should generate the partial with controller and main files and their content', function ( done ) { + helpers.mockPrompt( rangPartial, { partial: 'test', controller: true } ); + + rangPartial.run( {}, function () { + + assert.file( expected.withController.exist ); + assert.fileContent( expectedContent ); + + done(); + }); + }); +});