├── .gitignore ├── .travis.yml ├── .editorconfig ├── .jshintrc ├── app ├── templates │ ├── _package.json │ └── _Gruntfile.js ├── USAGE └── index.js ├── LICENSE ├── package.json ├── README.md └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | temp/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 'iojs' 5 | - '0.12' 6 | - '0.10' 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "undef": true, 15 | "unused": true, 16 | "strict": true 17 | } 18 | -------------------------------------------------------------------------------- /app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= _.slugify(appname) %>", 3 | "version": "<%= version %>", 4 | "dependencies": {}, 5 | "devDependencies": { 6 | "grunt": "~0.4.2", 7 | "grunt-contrib-watch": "~0.5.3",<% if (minConcat) { %> 8 | "grunt-contrib-concat": "~0.3.0", 9 | "grunt-contrib-uglify": "~0.2.7",<% } %> 10 | "grunt-contrib-jshint": "~0.7.2", 11 | "grunt-contrib-<%= testTask %>": "*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Creates a basic Grunt Javascript Task Runner configuration 3 | 4 | Options: 5 | Is the DOM involved in ANY way? 6 | Includes either the Qunit or Nodeunit test framework 7 | Will files be concatenated or minified? 8 | Includes the concatenate and minify Grunt tasks 9 | 10 | Example: 11 | yo gruntfile 12 | 13 | This will create: 14 | package.json: Development packages installed by npm 15 | Gruntfile.js: Configuration for the task runner 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-gruntfile", 3 | "version": "0.1.4", 4 | "description": "A gruntfile generator for Yeoman", 5 | "keywords": [ 6 | "yeoman-generator", 7 | "scaffold", 8 | "grunt", 9 | "gruntfile", 10 | "build", 11 | "task", 12 | "runner" 13 | ], 14 | "homepage": "https://github.com/yeoman/generator-gruntfile", 15 | "bugs": "https://github.com/yeoman/generator-gruntfile/issues", 16 | "author": { 17 | "name": "Addy Osmani", 18 | "email": "addyosmani@gmail.com", 19 | "url": "https://github.com/addyosmani" 20 | }, 21 | "main": "app/index.js", 22 | "files": [ 23 | "app" 24 | ], 25 | "repository": "yeoman/generator-gruntfile", 26 | "scripts": { 27 | "test": "mocha --reporter spec" 28 | }, 29 | "dependencies": { 30 | "grunt": "~0.4.1", 31 | "underscore.string": "^3.0.3", 32 | "yeoman-generator": "~0.16.0" 33 | }, 34 | "devDependencies": { 35 | "mocha": "*" 36 | }, 37 | "engines": { 38 | "node": ">=0.10.0" 39 | }, 40 | "licenses": [ 41 | { 42 | "type": "MIT" 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ------- 2 | 3 | > [!CAUTION] 4 | > **This repository is archived and no longer actively maintained.** 5 | > 6 | > We are no longer accepting issues, feature requests, or pull requests. 7 | > For additional support or questions, please visit the [Maintenance Reboot plan](https://github.com/yeoman/yeoman/issues/1779). 8 | 9 | ------- 10 | 11 | # gruntfile Generator [![Build Status](https://secure.travis-ci.org/yeoman/generator-gruntfile.svg?branch=master)](https://travis-ci.org/yeoman/generator-gruntfile) 12 | 13 | > Create a gruntfile module with [Yeoman](http://yeoman.io), including nodeunit unit tests. 14 | 15 | This generator is based of 16 | [grunt-init-gruntfile](https://github.com/gruntjs/grunt-init-gruntfile), authored by the 17 | magnificient GruntJS team. 18 | 19 | Maintained by [Addy Osmani](https://github.com/addyosmani). 20 | 21 | [Yeoman]: http://yeoman.io/ 22 | 23 | 24 | ## Installation 25 | 26 | Install this generator by running: `npm install -g generator-gruntfile`. 27 | 28 | 29 | ## Usage 30 | 31 | At the command-line, cd into an empty directory, run this command and follow the prompts. 32 | 33 | ``` 34 | yo gruntfile 35 | ``` 36 | 37 | _Note that this template will generate files in the current directory, so be sure to change to a new directory first if you don't want to overwrite existing files._ 38 | 39 | 40 | ## License 41 | 42 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 43 | -------------------------------------------------------------------------------- /app/templates/_Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 'use strict'; 3 | // Project configuration 4 | grunt.initConfig({ 5 | // Metadata 6 | pkg: grunt.file.readJSON('package.json'), 7 | banner: '/*! <%%= pkg.name %> - v<%%= pkg.version %> - ' + 8 | '<%%= grunt.template.today("yyyy-mm-dd") %>\n' + 9 | '<%%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + 10 | '* Copyright (c) <%%= grunt.template.today("yyyy") %> <%%= pkg.author.name %>;' + 11 | ' Licensed <%%= props.license %> */\n', 12 | // Task configuration<% if (minConcat) { %> 13 | concat: { 14 | options: { 15 | banner: '<%%= banner %>', 16 | stripBanners: true 17 | }, 18 | dist: { 19 | src: ['<%= libDir %>/<%= appname %>.js'], 20 | dest: 'dist/<%= appname %>.js' 21 | } 22 | }, 23 | uglify: { 24 | options: { 25 | banner: '<%%= banner %>' 26 | }, 27 | dist: { 28 | src: '<%%= concat.dist.dest %>', 29 | dest: 'dist/<%= appname %>.min.js' 30 | } 31 | },<% } %><% if (!hasJshint) {%> 32 | jshint: { 33 | options: { 34 | node: true, 35 | curly: true, 36 | eqeqeq: true, 37 | immed: true, 38 | latedef: true, 39 | newcap: true, 40 | noarg: true, 41 | sub: true, 42 | undef: true, 43 | unused: true, 44 | eqnull: true,<% if (dom) { %> 45 | browser: true,<% } %><% if (jquery || testTask === 'qunit') { %> 46 | globals: { jQuery: true },<% } %> 47 | boss: true 48 | },<% } %> 49 | gruntfile: { 50 | src: 'gruntfile.js' 51 | }, 52 | lib_test: { 53 | src: ['<%= libDir %>/**/*.js', '<%= testDir %>/**/*.js'] 54 | } 55 | },<% if (dom) { %> 56 | <%= testTask %>: { 57 | files: ['<%= testDir %>/**/*.html'] 58 | },<% } else { %> 59 | <%= testTask %>: { 60 | files: ['<%= testDir %>/**/*_test.js'] 61 | },<% } %> 62 | watch: { 63 | gruntfile: { 64 | files: '<%%= jshint.gruntfile.src %>', 65 | tasks: ['jshint:gruntfile'] 66 | }, 67 | lib_test: { 68 | files: '<%%= jshint.lib_test.src %>', 69 | tasks: ['jshint:lib_test', '<%= testTask %>'] 70 | } 71 | } 72 | }); 73 | 74 | // These plugins provide necessary tasks<% if (minConcat) { %> 75 | grunt.loadNpmTasks('grunt-contrib-concat'); 76 | grunt.loadNpmTasks('grunt-contrib-uglify');<% } %> 77 | grunt.loadNpmTasks('grunt-contrib-<%= testTask %>'); 78 | grunt.loadNpmTasks('grunt-contrib-jshint'); 79 | grunt.loadNpmTasks('grunt-contrib-watch'); 80 | 81 | // Default task 82 | grunt.registerTask('default', ['jshint', '<%= testTask %>'<%= minConcat ? ", 'concat', 'uglify'" : "" %>]); 83 | }; 84 | 85 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var yeoman = require('yeoman-generator'); 3 | var slugify = require('underscore.string/slugify'); 4 | 5 | var GruntfileGenerator = yeoman.generators.Base.extend({ 6 | initializing: function () { 7 | this.pkg = require('../package.json'); 8 | 9 | // Check if package.json or jshint config exist 10 | // to determine if they should be created later 11 | if (this.dest.exists('package.json')) { 12 | this.packageJSON = this.dest.readJSON('package.json'); 13 | this.appname = slugify(this.packageJSON.name || this.appname); 14 | this.version = this.packageJSON.version || this.version; 15 | this.hasJshint = this.packageJSON.hasOwnProperty('jshintConfig') || this.dest.exists('.jshintrc'); 16 | } else { 17 | this.hasJshint = this.dest.exists('.jshintrc'); 18 | } 19 | 20 | function prefer(arr, preferred) { 21 | for (var i = 0; i < preferred.length; ++i) { 22 | if (arr.indexOf(preferred[i]) !== -1) { 23 | return preferred[i]; 24 | } 25 | } 26 | return preferred[0]; 27 | } 28 | 29 | var dirs = this.dest.expand({ filter: 'isDirectory' }, '*').map(function (d) { 30 | return d.slice(0, -1); 31 | }); 32 | 33 | this.jquery = this.dest.expand({ filter: 'isFile' }, '**/jquery*.js').length > 0; 34 | this.libDir = prefer(dirs, ['lib', 'src']); 35 | this.testDir = prefer(dirs, ['test', 'tests', 'unit', 'spec']); 36 | }, 37 | 38 | prompting: function () { 39 | var done = this.async(); 40 | 41 | if (!this.options['skip-install-message']) { 42 | this.log(this.yeoman); 43 | this.log('This template tries to guess file and directory paths, but ' + 44 | 'you will most likely need to edit the generated Gruntfile.js file before ' + 45 | 'running grunt. _If you run grunt after generating the Gruntfile, and ' + 46 | 'it exits with errors, edit the file!_'); 47 | } 48 | 49 | var prompts = [{ 50 | type: 'checkbox', 51 | name: 'features', 52 | message: 'What more would you like?', 53 | choices: [{ 54 | name: 'Is the DOM involved in ANY way?', 55 | value: 'dom', 56 | checked: true 57 | }, { 58 | name: 'Will files be concatenated or minified?', 59 | value: 'minConcat', 60 | checked: true 61 | }] 62 | }]; 63 | 64 | this.prompt(prompts, function (answers) { 65 | function hasFeature(feat) { 66 | return answers.features.indexOf(feat) !== -1; 67 | } 68 | 69 | this.dom = hasFeature('dom'); 70 | this.minConcat = hasFeature('minConcat'); 71 | this.testTask = hasFeature('dom') ? 'qunit' : 'nodeunit'; 72 | 73 | if (!this.version) { 74 | this.version = '0.0.0'; 75 | } 76 | 77 | done(); 78 | }.bind(this)); 79 | }, 80 | 81 | configuring: function () { 82 | this.config.save(); 83 | }, 84 | 85 | writing: function () { 86 | if (!this.packageJSON) { 87 | this.template('_package.json', 'package.json'); 88 | } 89 | this.template('_Gruntfile.js', 'Gruntfile.js'); 90 | }, 91 | 92 | install: function () { 93 | if (!this.options['skip-install']) { 94 | this.installDependencies(); 95 | } 96 | } 97 | }); 98 | 99 | module.exports = GruntfileGenerator; 100 | 101 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /*global beforeEach, describe, it */ 2 | 'use strict'; 3 | 4 | var file = require('yeoman-generator').file; 5 | var helpers = require('yeoman-generator').test; 6 | var path = require('path'); 7 | 8 | describe('gruntfile:app empty project', function () { 9 | var generator; 10 | 11 | beforeEach(function (done) { 12 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 13 | if (err) { 14 | done(err); 15 | } 16 | generator = helpers.createGenerator('gruntfile:app', ['../../app']); 17 | generator.options['skip-install'] = true; 18 | generator.options['skip-install-message'] = true; 19 | done(); 20 | }); 21 | }); 22 | 23 | it('creates expected files', function (done) { 24 | var expected = ['Gruntfile.js', 'package.json']; 25 | 26 | helpers.mockPrompt(generator, { 27 | features: [ 28 | 'dom', 29 | 'minConcat' 30 | ] 31 | }); 32 | 33 | generator.run({}, function () { 34 | helpers.assertFile(expected); 35 | helpers.assertFileContent('./package.json', /"version": "0.0.0"/); 36 | done(); 37 | }); 38 | }); 39 | }); 40 | 41 | describe('gruntfile:app with existing package.json', function () { 42 | var generator; 43 | 44 | beforeEach(function (done) { 45 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 46 | if (err) { 47 | done(err); 48 | } 49 | file.write('package.json', '{"name": "my lib", "jshintConfig":{}, "version": "0.1.0"}'); 50 | generator = helpers.createGenerator('gruntfile:app', ['../../app']); 51 | generator.options['skip-install-message'] = true; 52 | generator.options['skip-install'] = true; 53 | done(); 54 | }); 55 | }); 56 | 57 | it('creates expected files', function (done) { 58 | var expected = ['Gruntfile.js', 'package.json']; 59 | 60 | helpers.mockPrompt(generator, { 61 | features: [ 62 | 'dom', 63 | 'minConcat' 64 | ] 65 | }); 66 | 67 | generator.run({}, function () { 68 | helpers.assertFile(expected); 69 | done(); 70 | }); 71 | }); 72 | 73 | it('does not replace existing package.json', function (done) { 74 | helpers.mockPrompt(generator, { 75 | features: [ 76 | 'dom', 77 | 'minConcat' 78 | ] 79 | }); 80 | 81 | generator.run({}, function () { 82 | helpers.assertFileContent('./package.json', /jshintConfig/); 83 | helpers.assertFileContent('./package.json', /"version": "0.1.0"/); 84 | done(); 85 | }); 86 | }); 87 | 88 | it('should slugify the appname properly', function(done){ 89 | helpers.mockPrompt(generator, { 90 | features: [ 91 | 'dom', 92 | 'minConcat' 93 | ] 94 | }); 95 | 96 | generator.run({}, function () { 97 | helpers.assertFileContent('./Gruntfile.js', /my-lib/); 98 | done(); 99 | }); 100 | }); 101 | 102 | it('does not conflict with jshintConfig property', function (done) { 103 | helpers.mockPrompt(generator, { 104 | features: [ 105 | 'dom', 106 | 'minConcat' 107 | ] 108 | }); 109 | 110 | generator.run({}, function () { 111 | helpers.assertNoFileContent('./Gruntfile.js', /jshint: {/); 112 | done(); 113 | }); 114 | }); 115 | }); 116 | 117 | --------------------------------------------------------------------------------