├── Testing-Tasks.md ├── Community.md ├── Exit-Codes.md ├── README.md ├── Help-Resources.md ├── Blog-2014-03-14-Grunt-0.4.4-released.md ├── package.json ├── Development-helpers.md ├── Grunt-Plugins.md ├── Home.md ├── Blog-2013-03-13-Grunt-0.4.1-released.md ├── Blog-2014-03-07-Grunt-0.4.3-released.md ├── Plugin-Release-Candidate-Versions.md ├── Blog-2013-02-18-Grunt-0.4.0-released.md ├── grunt.fail.md ├── grunt.event.md ├── Using-the-CLI.md ├── Blog-2013-02-15-Updating-plugins-to-Grunt-0.4.md ├── Blog-2014-05-12-Grunt-0.4.5-released.md ├── Built-with-Grunt-Badge.md ├── Creating-plugins.md ├── Blog-2013-11-21-Grunt-0.4.2-released.md ├── Using-plugins.md ├── Development-Team.md ├── grunt.md ├── grunt.option.md ├── Installing-grunt.md ├── grunt.template.md ├── Roadmap.md ├── grunt.config.md ├── grunt.log.md ├── grunt.util.md ├── Frequently-Asked-Questions.md ├── Who-uses-Grunt.md ├── Sample-Gruntfile.md ├── Contributing.md ├── grunt.task.md ├── Inside-Tasks.md ├── Creating-tasks.md ├── Getting-started.md ├── Upgrading-from-0.3-to-0.4.md ├── grunt.file.md ├── Configuring-tasks.md └── Project-Scaffolding.md /Testing-Tasks.md: -------------------------------------------------------------------------------- 1 | _TODO_ -------------------------------------------------------------------------------- /Community.md: -------------------------------------------------------------------------------- 1 | Please see the [[Help Resources]] page. -------------------------------------------------------------------------------- /Exit-Codes.md: -------------------------------------------------------------------------------- 1 | * `0` - No errors! 2 | * `1` - Fatal error 3 | * `2` - Missing gruntfile error 4 | * `3` - Task error 5 | * `4` - Template processing error 6 | * `5` - Invalid shell auto-completion rules error 7 | * `6` - Warning -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##[View Grunt Documentation](http://gruntjs.com/getting-started) 2 | 3 | This repository contains the wiki files for the official grunt documentation. 4 | Grunt documentation is based on the [Gollum Wiki](https://github.com/gollum/gollum/wiki) 5 | -------------------------------------------------------------------------------- /Help-Resources.md: -------------------------------------------------------------------------------- 1 | ## IRC 2 | 3 | You can visit us in [#grunt on irc.freenode.net](http://webchat.freenode.net/?channels=grunt) 4 | 5 | ## Forums 6 | 7 | You can post a question at [StackOverflow and tag it with "gruntjs"](http://stackoverflow.com/questions/tagged/gruntjs). -------------------------------------------------------------------------------- /Blog-2014-03-14-Grunt-0.4.4-released.md: -------------------------------------------------------------------------------- 1 | Grunt 0.4.4 is now available on [npm](https://npmjs.org/package/grunt). 2 | 3 | This release fixes a [regression](https://github.com/gruntjs/grunt/pull/1026) that was introduced in version 0.4.3. 4 | 5 | See the changelog [here](https://github.com/gruntjs/grunt/blob/v0.4.4/CHANGELOG). 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-docs", 3 | "version": "0.2.0", 4 | "description": "This repository contains the wiki files for the official grunt documentation. Grunt documentation is based on the [Gollum Wiki](https://github.com/gollum/gollum/wiki)", 5 | "repository": { 6 | "type": "git", 7 | "url": "git://github.com/gruntjs/grunt-docs.git" 8 | }, 9 | "author": "GruntJS Team", 10 | "license": "MIT", 11 | "bugs": { 12 | "url": "https://github.com/gruntjs/grunt-docs/issues" 13 | }, 14 | "homepage": "https://github.com/gruntjs/grunt-docs" 15 | } 16 | -------------------------------------------------------------------------------- /Development-helpers.md: -------------------------------------------------------------------------------- 1 | Good to do when publishing everything all-at-once. 2 | 3 | ```shell 4 | eachdir grunt grunt-{contrib,lib}-* -- 'git pull' 5 | eachdir grunt grunt-{contrib,lib}-* -- 'rm -rf node_modules; linken . --src ..; npm install' 6 | 7 | # Make sure symlinks were created, if not there's a version mismatch 8 | eachdir grunt grunt-{contrib,lib}-* -- 'll node_modules | grep grunt' 9 | 10 | # Make sure everything passes 11 | eachdir grunt grunt-{contrib,lib}-* -- grunt 12 | 13 | # Make sure all versions are final 14 | eachdir grunt grunt-{contrib,lib}-* -- 'git branch; node -pe "require(\"./package.json\").version"' 15 | ``` -------------------------------------------------------------------------------- /Grunt-Plugins.md: -------------------------------------------------------------------------------- 1 | This plugin listing is automatically generated from the npm module database. 2 | Officially maintained "contrib" plugins are marked with a star 3 | icon. 4 | 5 | To install and use any plugin listed here, checkout [how to install and use the Grunt plugins section](http://gruntjs.com/getting-started#installing-grunt-and-gruntplugins). 6 | 7 | You may also be interested on how to [create your own Grunt plugin](http://gruntjs.com/creating-plugins). 8 | 9 | 10 | In order for a Grunt plugin to be listed here, it must be published on 11 | npm with the 12 | gruntplugin keyword. 13 | Additionally, we recommend that you use the 14 | gruntplugin grunt-init template 15 | when creating a Grunt plugin. 16 | -------------------------------------------------------------------------------- /Home.md: -------------------------------------------------------------------------------- 1 | > Welcome to the home of **Grunt**, a JavaScript automation tool. 2 | 3 | Stable Version: **0.4.5** 4 | 5 | Development Version: **master** 6 | 7 | ## Documentation 8 | * [[Getting Started]] 9 | * [[Configuring Tasks]] 10 | * [[Sample Gruntfile]] 11 | * [[Creating Tasks]] 12 | * [[Creating Plugins]] 13 | * [[Using the CLI]] 14 | 15 | ### Advanced 16 | * [[API]] 17 | * [[Installing Grunt]] 18 | * [[Frequently Asked Questions]] 19 | * [[Project Scaffolding]] 20 | 21 | ### Community 22 | * [[Help Resources]] 23 | * [[Who uses Grunt]] 24 | * [[Built with Grunt Badge]] 25 | * [[Contributing]] 26 | * [[Development Team]] 27 | 28 | ### Migration guides 29 | * [[Upgrading from 0.3 to 0.4]] 30 | 31 | ## API 32 | * [[grunt]] 33 | * [[grunt.config]] 34 | * [[grunt.event]] 35 | * [[grunt.fail]] 36 | * [[grunt.file]] 37 | * [[grunt.log]] 38 | * [[grunt.option]] 39 | * [[grunt.task]] 40 | * [[grunt.template]] 41 | * [[grunt.util]] 42 | 43 | ### Other 44 | * [[Inside Tasks]] 45 | * [[Exit Codes]] 46 | -------------------------------------------------------------------------------- /Blog-2013-03-13-Grunt-0.4.1-released.md: -------------------------------------------------------------------------------- 1 | Grunt 0.4.1 is now available from [npm](https://npmjs.org/package/grunt). 2 | 3 | This patch release fixes a number of minor issues that cropped up with the recent release of [Node.js v0.10.0](http://blog.nodejs.org/2013/03/11/node-v0-10-0-stable/), most notably due to changes in the [path](http://nodejs.org/api/path.html) API. If you want to use the latest version of Node.js in your projects, you should probably update Grunt to `~0.4.1` in the [package.json](http://gruntjs.com/getting-started#package.json) file for those projects. 4 | 5 | Either way, Grunt still works with Node.js v0.8.x, so you don't *need* to update if you haven't upgraded to Node.js v0.10.0. 6 | 7 | In addition to the Node.js v0.10.0 changes, we used this opportunity to fix a number of other small issues, like properly handling multibyte I/O when spawning child processes and ensuring the [Gruntfile](http://gruntjs.com/getting-started#the-gruntfile) name is case-insensitive. For a complete list of changes, see the [v0.4.0 - v0.4.1 changelog](https://github.com/gruntjs/grunt/compare/v0.4.0...v0.4.1). 8 | -------------------------------------------------------------------------------- /Blog-2014-03-07-Grunt-0.4.3-released.md: -------------------------------------------------------------------------------- 1 | Grunt 0.4.3 is now available on [npm](https://npmjs.org/package/grunt). 2 | 3 | This is mostly a bugfix release. Thanks to [Jonathan Krause](https://github.com/jonykrause), 4 | [PatrickJS](https://github.com/gdi2290), [Jason Cust](https://github.com/GlobalDomestic), 5 | [Fabio Crisci](https://github.com/piuccio), [James M. Greene](https://github.com/JamesMGreene) 6 | and [Mike Pennisi](https://github.com/jugglinmike) for their pull requests. 7 | 8 | In addition to closing over 30 issues, we have extracted `grunt.util` into 9 | [its own module](https://github.com/gruntjs/grunt-legacy-util). As mentioned 10 | in the [0.4.2](http://gruntjs.com/blog/2013-11-21-grunt-0.4.2-released) release, 11 | we are in process of deprecating the `grunt.util.*` API. Task developers who use 12 | these APIs should update their plugins to use the libraries recommended in 13 | the [grunt-legacy-util](https://github.com/gruntjs/grunt-legacy-util) README. 14 | You may use `grunt-legacy-util` directly as a stopgap, but we will no longer be supporting it. 15 | 16 | For a full list of changes, see the 0.4.3 changelog [here](https://github.com/gruntjs/grunt/blob/v0.4.3/CHANGELOG). 17 | 18 | **Happy Grunting!** 19 | -------------------------------------------------------------------------------- /Plugin-Release-Candidate-Versions.md: -------------------------------------------------------------------------------- 1 | Note: because these are pre-release versions, please follow the instructions in the "Installing a published development version of Grunt" section of the [Installing Grunt guide](https://github.com/gruntjs/grunt/wiki/Installing-grunt). And as a reminder, **do not** specify a version range (using ~ or <=) when including a pre-release version of Grunt or Grunt plugin in your project. 2 | 3 | Grunt contrib plugins published to npm that work with Grunt 0.4.0rc8: 4 | 5 | - grunt-contrib-clean@0.4.0rc6 6 | - grunt-contrib-coffee@0.4.0rc7 7 | - grunt-contrib-compass@0.1.1rc8 8 | - grunt-contrib-compress@0.4.0rc7 9 | - grunt-contrib-concat@0.1.2rc6 10 | - grunt-contrib-connect@0.1.1rc6 11 | - grunt-contrib-copy@0.4.0rc7 12 | - grunt-contrib-handlebars@0.5.4rc7 13 | - grunt-contrib-htmlmin@0.1.1rc7 14 | - grunt-contrib-imagemin@0.1.1rc8 15 | - grunt-contrib-jade@0.4.0.rc7 16 | - grunt-contrib-jasmine@0.3.0rc7 17 | - grunt-contrib-jshint@0.1.1rc6 18 | - grunt-contrib-jst@0.4.0rc7 19 | - grunt-contrib-less@0.5.0rc7 20 | - grunt-contrib-livereload@0.1.0rc8 21 | - grunt-contrib-mincss@0.4.0rc7 22 | - grunt-contrib-nodeunit@0.1.2rc6 23 | - grunt-contrib-qunit@0.1.1rc6 24 | - grunt-contrib-requirejs@0.4.0rc7 25 | - grunt-contrib-sass@0.2.2rc7 26 | - grunt-contrib-stylus@0.4.0rc7 27 | - grunt-contrib-uglify@0.1.1rc6 28 | - grunt-contrib-watch@0.2.0rc7 29 | - grunt-contrib-yuidoc@0.4.0rc7 -------------------------------------------------------------------------------- /Blog-2013-02-18-Grunt-0.4.0-released.md: -------------------------------------------------------------------------------- 1 | As of this morning, Grunt v0.4 final is available on npm! For a lengthy writeup on the release, please see [@tkellen's](http://goingslowly.com) article [on the Bocoup blog](http://weblog.bocoup.com/tearing-grunt-apart/). 2 | 3 | ### The Biggest Stuff 4 | 5 | 1. Grunt no longer ships with built in tasks. They've been extracted into officially maintained, standalone plugins under the grunt-contrib namespace. See the [plugin listing](http://gruntjs.com/plugins) on our website for more details. 6 | 7 | 2. Grunt no longer ships with a binary. In order to get the `grunt` command, install [grunt-cli](http://github.com/gruntjs/grunt-cli) globally with `npm install -g grunt-cli`. This package will run any version of Grunt (including 0.3x) after it's been installed locally to your project. 8 | 9 | ### The Future 10 | 11 | Grunt v0.5 will ship with support for a new plugin format called [node-task](http://github.com/tkellen/node-task). It defines a stateless, promise-based, event emitting API that doesn't depend on Grunt. It has a real-live spec, and the Grunt team is working with the front-end developer community in the hopes that compliant modules will be compatible with every task runner under the sun. 12 | 13 | ### Grunt on 14 | If you'd like to know more about Grunt, please read our [Getting Started Guide](http://gruntjs.com/getting-started), and check out all of the ways you can [configure your tasks](http://gruntjs.com/configuring-tasks), too. -------------------------------------------------------------------------------- /grunt.fail.md: -------------------------------------------------------------------------------- 1 | For when something goes horribly wrong. 2 | 3 | See the [fail lib source](https://github.com/gruntjs/grunt/blob/master/lib/grunt/fail.js) for more information. 4 | 5 | ## The fail API 6 | 7 | If something explodes (or is about to explode) inside a task, it can force Grunt to abort. See the [exit codes documentation](Exit-Codes) for a list of all built-in Grunt exit codes. 8 | 9 | Note that any method marked with a ☃ (unicode snowman) is also available directly on the `grunt` object. Just so you know. See the [API main page](grunt) for more usage information. 10 | 11 | ### grunt.fail.warn ☃ 12 | Display a warning and abort Grunt immediately. Grunt will continue processing tasks if the `--force` command-line option was specified. The `error` argument can be a string message or an error object. 13 | 14 | ```javascript 15 | grunt.fail.warn(error [, errorcode]) 16 | ``` 17 | 18 | If `--stack` is specified on the command-line and an error object was specified, a stack trace will be logged. 19 | 20 | _This method is also available as `grunt.warn`._ 21 | 22 | ### grunt.fail.fatal ☃ 23 | Display a warning and abort Grunt immediately. The `error` argument can be a string message or an error object. 24 | 25 | ```javascript 26 | grunt.fail.fatal(error [, errorcode]) 27 | ``` 28 | 29 | If `--stack` is specified on the command-line and an error object was specified, a stack trace will be logged. 30 | 31 | A beep is emitted on fatal unless the `--no-color` option is specified. 32 | 33 | _This method is also available as `grunt.fatal`._ 34 | -------------------------------------------------------------------------------- /grunt.event.md: -------------------------------------------------------------------------------- 1 | Even though only the most relevant methods are listed on this page, the full [EventEmitter2 API][ee2] is available on the `grunt.event` object. Event namespaces may be specified with the `.` (dot) separator, and namespace wildcards have been enabled. 2 | 3 | *Note that Grunt doesn't yet emit any events, but can still be useful in your own tasks.* 4 | 5 | [ee2]: https://github.com/hij1nx/EventEmitter2 6 | 7 | ### grunt.event.on 8 | Adds a listener to the end of the listeners array for the specified event. 9 | 10 | ```js 11 | grunt.event.on(event, listener) 12 | ``` 13 | 14 | ### grunt.event.once 15 | Adds a **one time** listener for the event. The listener is invoked only the first time the event is fired, after which it is removed. 16 | 17 | ```js 18 | grunt.event.once(event, listener) 19 | ``` 20 | 21 | ### grunt.event.many 22 | Adds a listener that will execute **n times** for the event before being removed. 23 | 24 | ```js 25 | grunt.event.many(event, timesToListen, listener) 26 | ``` 27 | 28 | ### grunt.event.off 29 | Remove a listener from the listener array for the specified event. 30 | 31 | ```js 32 | grunt.event.off(event, listener) 33 | ``` 34 | 35 | ### grunt.event.removeAllListeners 36 | Removes all listeners, or those of the specified event. 37 | 38 | ```js 39 | grunt.event.removeAllListeners([event]) 40 | ``` 41 | 42 | ### grunt.event.emit 43 | Execute each of the listeners that may be listening for the specified event name in order with the list of arguments. 44 | 45 | ```js 46 | grunt.event.emit(event, [arg1], [arg2], [...]) 47 | ``` -------------------------------------------------------------------------------- /Using-the-CLI.md: -------------------------------------------------------------------------------- 1 | ## Installing the CLI 2 | 3 | Run `sudo npm install -g grunt-cli`. 4 | 5 | The `grunt` command-line interface comes with a series of options. Use `grunt -h` from your terminal to show these options. 6 | 7 | ### --help, -h 8 | Display help text 9 | 10 | ### --base, -b 11 | Specify an alternate base path. By default, all file paths are relative to the `Gruntfile`. 12 | 13 | Alternative to `grunt.file.setBase(...)` 14 | 15 | ### --no-color 16 | Disable colored output. 17 | 18 | ### --gruntfile 19 | Specify an alternate `Gruntfile`. 20 | 21 | By default, grunt looks in the current or parent directories for the nearest `Gruntfile.js` or `Gruntfile.coffee` file. 22 | 23 | ### --debug, -d 24 | Enable debugging mode for tasks that support it. 25 | 26 | ### --stack 27 | Print a stack trace when exiting with a warning or fatal error. 28 | 29 | ### --force, -f 30 | A way to force your way past warnings. 31 | 32 | Want a suggestion? Don't use this option, fix your code. 33 | 34 | ### --tasks 35 | Additional directory paths to scan for task and "extra" files. 36 | 37 | Alternative to `grunt.loadTasks(...)` 38 | 39 | ### --npm 40 | Npm-installed grunt plugins to scan for task and "extra" files. 41 | 42 | Alternative to `grunt.loadNpmTasks(...)` 43 | 44 | ### --no-write 45 | Disable writing files (dry run). 46 | 47 | ### --verbose, -v 48 | 49 | Verbose mode. A lot more information output. 50 | 51 | ### --version, -V 52 | Print the grunt version. Combine with --verbose for more info. 53 | 54 | ### --completion 55 | Output shell auto-completion rules. See the grunt-cli documentation for more information. 56 | -------------------------------------------------------------------------------- /Blog-2013-02-15-Updating-plugins-to-Grunt-0.4.md: -------------------------------------------------------------------------------- 1 | If your plugin is not already Grunt 0.4 compatible, would you please consider updating it? For an overview of what's changed, please see our [migration guide](https://github.com/gruntjs/grunt/wiki/Upgrading-from-0.3-to-0.4). 2 | 3 | If you'd like to develop against the final version of Grunt before Monday, please specify `"grunt": "0.4.0rc8"` as a devDependency in your project. After Monday's release, you'll be able to use `"grunt": "~0.4.0"` to actually publish your plugin. If you depend on any plugins from the grunt-contrib series, please see our [list of release candidates](https://github.com/gruntjs/grunt/wiki/Plugin-Release-Candidate-Versions) for compatible versions. All of these will be updated to final status when Grunt 0.4 is published. 4 | 5 | Also, in an effort to reduce duplication of effort and fragmentation in the developer community, could you review the [grunt-contrib](https://github.com/gruntjs) series of plugins to see if any of your functionality overlaps significantly with them? Grunt-contrib is community maintained with 40+ contributors—we'd love to discuss any additions you'd like to make. 6 | 7 | Finally, we're working on a new task format that doesn't depend on Grunt: it's called [node-task](https://github.com/tkellen/node-task). Once this is complete, there will be one more conversion, and then we'll never ask you to upgrade your plugins to support our changes again. Until that happens, thanks for bearing with us! 8 | 9 | If you have any questions about how to proceed, please respond here, or join us in `#grunt on irc.freenode.net`. 10 | 11 | Thanks, we really appreciate your work! -------------------------------------------------------------------------------- /Blog-2014-05-12-Grunt-0.4.5-released.md: -------------------------------------------------------------------------------- 1 | Grunt 0.4.5 is now available on [npm](https://www.npmjs.org/package/grunt). 2 | 3 | Thanks to [Gary Burgess](https://github.com/garyb), [James Smith](https://github.com/jmeas) and [Carlos Mantilla](https://github.com/ceoaliongroo) for their patches. Also, thanks to [Vlad Filippov](https://github.com/vladikoff) for helping triage issues, troubleshooting Windows CI testing and putting together the changelog. 4 | 5 | In this release, we closed around a dozen issues, added the much-requested [grunt.task.exists](http://gruntjs.com/api/grunt.task#grunt.task.exists) and [grunt.config.merge](http://gruntjs.com/api/grunt.config#grunt.config.merge) methods, and set up Windows CI testing through [AppVeyor](http://www.appveyor.com/). Additionally, the logging API has been broken out into a separate module, [grunt-legacy-log](https://github.com/gruntjs/grunt-legacy-log), in order to facilitate maintenance. 6 | 7 | For a full list of changes, see the [0.4.5 changelog](https://github.com/gruntjs/grunt/blob/v0.4.5/CHANGELOG). 8 | 9 | Additionally, we have accepted a number of patches for [Grunt contrib plugins](http://gruntjs.com/plugins/contrib) and would like to thank [Kevin Mårtensson](https://github.com/kevva), [Alexander Futekov](https://github.com/futekov), [Shinnosuke Watanabe](https://github.com/shinnn), [Shane Daniel](https://github.com/simshanith), [Artem Sapegin](https://github.com/sapegin), [Christoph Pojer](https://github.com/cpojer), [Zhang Yichao](https://github.com/echaozh), [Jevon Wright](https://github.com/soundasleep), [Jacob Lauritzen](https://github.com/Jacse), [XhmikosR](https://github.com/XhmikosR) and [Edan Schwartz](https://github.com/eschwartz) for their contributions. 10 | 11 | **Happy Grunting!** 12 | -------------------------------------------------------------------------------- /Built-with-Grunt-Badge.md: -------------------------------------------------------------------------------- 1 | Do you use Grunt in a project and want to proudly display that in your project README or on your project website? Now you can with the "Built with Grunt" badge! 2 | 3 | [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) 4 | 5 | ## Using the Badge 6 | 7 | Just copy the following Markdown code snippet and paste it right underneath the headline in your project README. You can also put it on your project website homepage or footer. 8 | 9 | ``` 10 | [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) 11 | ``` 12 | 13 | If you need an HTML version, we've got you covered. 14 | 15 | ```html 16 | Built with Grunt 17 | ``` 18 | 19 | ## For example... 20 | 21 | As you can see, the "Built with Grunt" badge is modern, stylish, and has been designed to fit nicely next to all your project's other mini-badges. You can put it first, last, or anywhere in the middle. Have fun! 22 | 23 | [![NPM version](https://badge.fury.io/js/grunt.png)](http://badge.fury.io/) 24 | [![Coverage Status](https://s3.amazonaws.com/assets.coveralls.io/badges/coveralls_100.png)](https://coveralls.io/) 25 | [![Build Status](https://secure.travis-ci.org/gruntjs/grunt.png?branch=master)](http://travis-ci.org/) 26 | [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) 27 | 28 | ## Shout-outs 29 | 30 | Let us know if you are using the "Built with Grunt" badge by [tweeting at @gruntjs](http://twitter.com/gruntjs). 31 | 32 | _We'd like to especially thank [MaxCDN](http://www.maxcdn.com/) for hosting this badge and for [sponsoring open source development](http://www.maxcdn.com/company/open-source/)._ 33 | 34 | -------------------------------------------------------------------------------- /Creating-plugins.md: -------------------------------------------------------------------------------- 1 | 1. Install [grunt-init](https://github.com/gruntjs/grunt-init) with `npm install -g grunt-init` 2 | 2. Install the gruntplugin template with `git clone git://github.com/gruntjs/grunt-init-gruntplugin.git ~/.grunt-init/gruntplugin` 3 | 3. Run `grunt-init gruntplugin` in an empty directory. 4 | 4. Run `npm install` to prepare the development environment. 5 | 5. Author your plugin. 6 | 6. Run `npm publish` to publish the Grunt plugin to npm! 7 | 8 | ## Notes 9 | 10 | ### Naming your task 11 | 12 | The "grunt-contrib" namespace is reserved for tasks maintained by the Grunt team, please name your task something appropriate that avoids that naming scheme. 13 | 14 | ### Debugging 15 | Grunt hides error stack traces by default, but they can be enabled for easier task debugging with the `--stack` option. If you want Grunt to always log stack traces on errors, create an alias in your shell. Eg, in bash, you could do `alias grunt='grunt --stack'`. 16 | 17 | ### Storing task files 18 | 19 | Only store data files in a .grunt/[npm-module-name]/ directory at the project's root and clean up after yourself when appropriate. This is not a solution for temporary scratch files, use one of the common npm modules (eg [temporary](https://npmjs.org/package/temporary), [tmp](https://npmjs.org/package/tmp)) that take advantage of the OS level temporary directories for that case. 20 | 21 | ### Avoid Changing the Current Working Directory: `process.cwd()` 22 | By default, the current working directory is set to be the directory that contains the gruntfile. The user can change it using `grunt.file.setBase()` in their gruntfile, but plugins should take care to not change it. 23 | 24 | `path.resolve('foo')` can be used to get the absolute path of the filepath 'foo' relative to the `Gruntfile`. 25 | 26 | ### Creating your task 27 | 28 | You might also want to know how to [create your own tasks](http://gruntjs.com/creating-tasks) or take a look at the [API](http://gruntjs.com/api) reference. 29 | -------------------------------------------------------------------------------- /Blog-2013-11-21-Grunt-0.4.2-released.md: -------------------------------------------------------------------------------- 1 | Grunt 0.4.2 is now available on [npm](https://npmjs.org/package/grunt). 2 | 3 | This release should address a lot of issues for Windows developers, such as pipe-redirection, console output and BOM preservation. 4 | 5 | Besides a number of bug fixes, we have made a few decisions going forward regarding external dependencies in Grunt. **These external libraries are deprecated and should now be required as npm modules:** 6 | 7 | * Use [glob](https://npmjs.org/package/glob) instead of `grunt.file.glob` 8 | * Use [minimatch](https://npmjs.org/package/minimatch) instead of `grunt.file.minimatch` 9 | * Use [findup](https://npmjs.org/package/findup) instead of `grunt.file.findup` 10 | * Use [lodash](https://npmjs.org/package/lodash) instead of `grunt.util._` 11 | * Use [underscore.string](https://npmjs.org/package/underscore.string) instead of `grunt.util._.str` 12 | * Use [hooker](https://npmjs.org/package/hooker) instead of `grunt.util.hooker` 13 | * Use [async](https://npmjs.org/package/async) instead of `grunt.util.async` 14 | * Use [getobject](https://github.com/cowboy/node-getobject) instead of `grunt.util.namespace` 15 | 16 | If you want to use these external libraries in your tasks, please install them as you would [Grunt or any Grunt plugin](http://gruntjs.com/getting-started#installing-grunt-and-gruntplugins) using `npm install --save-dev`. For example, if you used `grunt.util._` before, you'll now require [Lo-Dash](http://lodash.com/) instead with `npm install lodash --save-dev`. 17 | 18 | ```js 19 | // Then change this code: 20 | var newArr = grunt.util._.map(arr, fn); 21 | 22 | // To this: 23 | var _ = require('lodash'); 24 | var newArr = _.map(arr, fn); 25 | ``` 26 | 27 | The team is also looking for feedback about the future of Grunt, so if you have time, please join the 0.5.0 milestone 28 | [discussions](https://github.com/gruntjs/grunt/issues?direction=desc&milestone=7&page=1&sort=updated&state=open). 29 | 30 | See the 0.4.2 changelog [here](https://github.com/gruntjs/grunt/blob/v0.4.2/CHANGELOG). 31 | 32 | **Happy Grunting!** -------------------------------------------------------------------------------- /Using-plugins.md: -------------------------------------------------------------------------------- 1 | Grunt plugins define tasks that implement certain build steps and can be reused across multiple projects. The examples will use the plugin _"grunt-contrib-uglify"_. Check the [Grunt website](http://gruntjs.com/) for a list of available plugins. 2 | 3 | ## Installing a Grunt plugin 4 | 5 | The first step to using an existing Grunt plugin is to install it.Grunt plugins are packaged as node modules and can be installed using [npm](http://npmjs.org) like this: 6 | 7 | `npm install --save-dev grunt-contrib-uglify` 8 | 9 | This will install the Grunt plugin _"grunt-contrib-uglify"_ locally into the `node_modules` folder (cf. [npm folders](https://npmjs.org/doc/folders.html)). 10 | Plugins must be installed locally to avoid version conflicts when working with multiple projects. 11 | 12 | Specifying `--save-dev` as option automatically adds this Grunt plugin to the _"devDependency"_ section in the `package.json` file. This file lists all node dependencies of a project. 13 | Adding the Grunt plugin there will allow other developers working on the project to simply run `npm install` to locally install these required dependencies. 14 | 15 | ## Loading plugin tasks 16 | 17 | Now that the plugin is installed, it is time to tell Grunt about it and let it load all defined tasks. To do this, add the following line to your `Gruntfile.js`: 18 | 19 | `grunt.loadNpmTasks('grunt-contrib-uglify')` 20 | 21 | This line should be added within the top level function scope (not the initConfig section) where other `grunt.registerTask()` calls are made. 22 | 23 | ## Running plugin tasks 24 | 25 | Plugin tasks can be run like other Grunt tasks either by specifying them on the command line: 26 | 27 | `grunt uglify` 28 | 29 | Or by registering a new task alias which calls this task, and running that task: 30 | 31 | `grunt.registerTask("dist", ["uglify"])` 32 | 33 | ## Configuring plugins 34 | 35 | Plugin configuration depends on the specific plugin, so check the plugin's documentation for further information. Generally the configuration is located in the `initConfig` section of the Gruntfile. 36 | 37 | **TODO**: Configuration Targets/options (Merge [Configuring tasks](Configuring tasks)?) -------------------------------------------------------------------------------- /Development-Team.md: -------------------------------------------------------------------------------- 1 | | | | | 2 | | ------------- | ----------- | 3 | | ![](https://avatars0.githubusercontent.com/u/54051?s=100) | **Ben Alman** | [GitHub](https://github.com/cowboy), [Twitter](https://twitter.com/cowboy), [Website](http://benalman.com/) | 4 | | ![](https://avatars3.githubusercontent.com/u/1004324?s=100) | **Tyler Kellen** | [GitHub](https://github.com/tkellen), [Twitter](https://twitter.com/tkellen), [Website](http://goingslowly.com/) | 5 | | ![](https://avatars2.githubusercontent.com/u/99604?s=100) | **Kyle Robinson Young** | [GitHub](https://github.com/shama), [Twitter](https://twitter.com/shamakry), [Website](http://dontkry.com/) | 6 | | ![](https://avatars3.githubusercontent.com/u/128755?s=100) | **Vlad Filippov** | [GitHub](https://github.com/vladikoff), [Twitter](https://twitter.com/vladikoff), [Website](http://vf.io/) | 7 | | ![](https://avatars0.githubusercontent.com/u/170270?s=100) | **Sindre Sorhus** | [GitHub](https://github.com/sindresorhus), [Twitter](https://twitter.com/sindresorhus), [Website](http://sindresorhus.com/hi/) | 8 | | ![](https://avatars0.githubusercontent.com/u/1379244?s=100) | **Isaac Durazo** | [GitHub](https://github.com/isaacdurazo), [Twitter](https://twitter.com/isaacdurazo), [Website](http://www.isaacdurazo.com/) | 9 | | ![](https://avatars3.githubusercontent.com/u/842798?s=100) | **Jarrod Overson** | [GitHub](https://github.com/tkellen), [Twitter](https://twitter.com/jsoverson), [Website](http://jarrodoverson.com/) | 10 | | ![](https://avatars1.githubusercontent.com/u/181635?s=100) | **Tim Branyen** | [GitHub](https://github.com/tbranyen), [Twitter](https://twitter.com/tbranyen), [Website](http://tbranyen.com/) | 11 | | ![](https://avatars2.githubusercontent.com/u/52585?s=100) | **Jörn Zaefferer** | [GitHub](https://github.com/jzaefferer), [Twitter](https://twitter.com/bassistance), [Website](http://bassistance.de/) | 12 | | ![](https://avatars2.githubusercontent.com/u/2322305?s=100) | **James Smith**| [GitHub](https://github.com/jmeas), [Twitter](https://twitter.com/jmeaspls), [Website](http://www.jmeas.com/) | 13 | | ![](https://avatars2.githubusercontent.com/u/515722?s=100) | **Dave Geddes** | [GitHub](https://github.com/geddski) | 14 | | | | | 15 | -------------------------------------------------------------------------------- /grunt.md: -------------------------------------------------------------------------------- 1 | Grunt exposes all of its methods and properties on the `grunt` object that gets passed into the `module.exports` function exported in your [Gruntfile](Getting-started), Grunt plugin or in a [tasks file](Creating-tasks). 2 | 3 | Nearly all of the following methods are defined elsewhere, but are provided directly on the `grunt` object for convenience. See the individual api section docs for detailed explanations and examples. 4 | 5 | ## Config 6 | 7 | ### grunt.initConfig 8 | _This method is an alias for the [grunt.config.init](grunt.config#grunt.config.init) method._ 9 | 10 | 11 | ## Creating Tasks 12 | 13 | ### grunt.registerTask 14 | _This method is an alias for the [grunt.task.registerTask](grunt.task#grunt.task.registerTask) method._ 15 | 16 | ### grunt.registerMultiTask 17 | _This method is an alias for the [grunt.task.registerMultiTask](grunt.task#grunt.task.registerMultiTask) method._ 18 | 19 | ### grunt.renameTask 20 | _This method is an alias for the [grunt.task.renameTask](grunt.task#grunt.task.renameTask) method._ 21 | 22 | ## Loading Externally-Defined Tasks 23 | 24 | ### grunt.loadTasks 25 | _This method is an alias for the [grunt.task.loadTasks](grunt.task#grunt.task.loadTasks) method._ 26 | 27 | ### grunt.loadNpmTasks 28 | _This method is an alias for the [grunt.task.loadNpmTasks](grunt.task#grunt.task.loadNpmTasks) method._ 29 | 30 | 31 | ## Warnings and Fatal Errors 32 | 33 | ### grunt.warn 34 | _This method is an alias for the [grunt.fail.warn](grunt.fail#grunt.fail.warn) method._ 35 | 36 | ### grunt.fatal 37 | _This method is an alias for the [grunt.fail.fatal](grunt.fail#grunt.fail.fatal) method._ 38 | 39 | 40 | ## Command-line Options 41 | 42 | ### grunt.option 43 | Retrieve the value of a command-line option, eg. `debug`. Note that for each command-line option, the inverse can be tested, eg. `no-debug`. 44 | 45 | ```javascript 46 | grunt.option(optionName) 47 | ``` 48 | 49 | ## Miscellaneous 50 | 51 | ### grunt.package 52 | The current Grunt `package.json` metadata, as an object. 53 | 54 | ```javascript 55 | grunt.package 56 | ``` 57 | 58 | ### grunt.version 59 | The current Grunt version, as a string. This is just a shortcut to the `grunt.package.version` property. 60 | 61 | ```javascript 62 | grunt.version 63 | ``` 64 | -------------------------------------------------------------------------------- /grunt.option.md: -------------------------------------------------------------------------------- 1 | The Grunt option API is for sharing parameters across multiple tasks and accessing parameters set on the command line. 2 | 3 | An example would be a flag to target whether your build is for development or staging. On the command line: `grunt deploy --target=staging` would cause `grunt.option('target')` to return `"staging"`. 4 | 5 | An example `Gruntfile` to utilize the `target` option could be: 6 | 7 | ```javascript 8 | grunt.initConfig({ 9 | compass: { 10 | dev: { 11 | options: { 12 | /* ... */ 13 | outputStyle: 'expanded' 14 | }, 15 | }, 16 | staging: { 17 | options: { 18 | /* ... */ 19 | outputStyle: 'compressed' 20 | }, 21 | }, 22 | }, 23 | }); 24 | var target = grunt.option('target') || 'dev'; 25 | grunt.registerTask('deploy', ['compass:' + target]); 26 | ``` 27 | 28 | As you run `grunt deploy` your stylesheets would default to the `dev` target and output the CSS in the expanded format. If you ran `grunt deploy --target=staging` the `staging` target would instead be ran and your CSS would be in the compressed format. 29 | 30 | `grunt.option` can be used within tasks as well, for example: 31 | 32 | ```javascript 33 | grunt.registerTask('upload', 'Upload code to specified target.', function(n) { 34 | var target = grunt.option('target'); 35 | // do something useful with target here 36 | }); 37 | grunt.registerTask('deploy', ['validate', 'upload']); 38 | ``` 39 | 40 | _Note that boolean options can be specified using just a key without a value. For example, running `grunt deploy --staging` on the command line would cause `grunt.option('staging')` to return `true`._ 41 | 42 | 43 | ### grunt.option ☃ 44 | Gets or sets an option. 45 | 46 | ```javascript 47 | grunt.option(key[, val]) 48 | ``` 49 | 50 | Boolean options can be negated by prepending `no-` onto the `key`. For example: 51 | 52 | ```javascript 53 | grunt.option('staging', false); 54 | var isDev = grunt.option('no-staging'); 55 | // isDev === true 56 | ``` 57 | 58 | ### grunt.option.init 59 | Initialize `grunt.option`. If `initObject` is omitted option will be initialized to an empty object otherwise will be set to `initObject`. 60 | 61 | ```javascript 62 | grunt.option.init([initObject]) 63 | ``` 64 | 65 | ### grunt.option.flags 66 | Returns the options as an array of command line parameters. 67 | 68 | ```javascript 69 | grunt.option.flags() 70 | ``` 71 | -------------------------------------------------------------------------------- /Installing-grunt.md: -------------------------------------------------------------------------------- 1 | This document explains how to install specific versions of Grunt and Grunt plugins. If you haven't read the [[Getting Started]] guide, you should check that out first. 2 | 3 | ## Overview 4 | Grunt and Grunt plugins should be defined as [devDependencies](https://npmjs.org/doc/json.html#devDependencies) in your project's [package.json](https://npmjs.org/doc/json.html). This will allow you to install all of your project's dependencies with a single command: `npm install`. The current stable and development versions of Grunt are always listed on the wiki's [home page](https://github.com/gruntjs/grunt/wiki/). 5 | 6 | ## Installing a specific version 7 | If you need a specific version of Grunt or a Grunt plugin, run `npm install grunt@VERSION --save-dev` where `VERSION` is the version you need. This will install the specified version, adding it to your package.json devDependencies. 8 | 9 | Note that a [tilde version range] will be used in your `package.json` when you add the `--save-dev` flag to `npm install`. This is typically good, as new patch releases of the specified version will automatically be upgraded as development continues, per [semver]. 10 | 11 | [tilde version range]: https://npmjs.org/doc/json.html#Tilde-Version-Ranges 12 | [semver]: http://semver.org 13 | 14 | ## Installing a published development version 15 | Periodically, as new functionality is being developed, Grunt builds may be published to npm. These builds will _never_ be installable without explicitly specifying a version number, and will typically have a build number or alpha/beta/release candidate designation. 16 | 17 | Like installing a specific version of grunt, run `npm install grunt@VERSION --save-dev` where `VERSION` is the version you need, and npm will install that version of Grunt in your project folder, adding it to your `package.json` devDependencies. 18 | 19 | Note that regardless of the version you specify, a [tilde version range][] will be specified in `package.json`. **This is very bad**, as new, possibly incompatible, patch releases of the specified development version may be installed by npm, breaking your build. 20 | 21 | _In this case it is **very important** that you manually edit your `package.json` and remove the ~ (tilde) from the version number. This will lock in the exact development version that you have specified._ 22 | 23 | The same process may be used to install a published development version of a Grunt plugin. 24 | 25 | ## Installing directly from github 26 | If you want to install a bleeding-edge, unpublished version of Grunt or Grunt plugin, follow the instructions for specifying a [git URL as a dependency](https://npmjs.org/doc/json.html#Git-URLs-as-Dependencies) and be sure to specify an actual commit SHA (not a branch name) as the `commit-ish`. This will guarantee that your project always uses that exact version of grunt. 27 | 28 | The specified git URL may be that of the official Grunt repo or a fork. -------------------------------------------------------------------------------- /grunt.template.md: -------------------------------------------------------------------------------- 1 | Template strings can be processed manually using the provided template functions. In addition, the config.get method (used by many tasks) automatically expands `<% %>` style template strings specified as config data inside the `Gruntfile`. 2 | 3 | ### grunt.template.process 4 | Process a [Lo-Dash template](http://lodash.com/docs/#template) string. The `template` argument will be processed recursively until there are no more templates to process. 5 | 6 | The default data object is the entire config object, but if `options.data` is set, that object will be used instead. The default template delimiters are `<% %>` but if `options.delimiters` is set to a custom delimiter name (set with [`grunt.template.addDelimiters`](#grunt.template.adddelimiters)), those template delimiters will be used instead. 7 | 8 | ```js 9 | grunt.template.process(template [, options]) 10 | ``` 11 | 12 | Inside templates, the `grunt` object is exposed so that you can do things like `<%= grunt.template.today('yyyy') %>`. _Note that if the data object already has a `grunt` property, the `grunt` API will not be accessible in templates._ 13 | 14 | In this example, the `baz` property is processed recursively until there are no more `<% %>` templates to process. 15 | 16 | ```js 17 | var obj = { 18 | foo: 'c', 19 | bar: 'b<%= foo %>d', 20 | baz: 'a<%= bar %>e' 21 | }; 22 | grunt.template.process('<%= baz %>', {data: obj}) // 'abcde' 23 | ``` 24 | 25 | ### grunt.template.setDelimiters 26 | Set the [Lo-Dash template](http://lodash.com/docs/#template) delimiters to a predefined set in case `grunt.util._.template` needs to be called manually. The `config` delimiters `<% %>` are included by default. 27 | 28 | _You probably won't need to use this method, because you'll be using `grunt.template.process` which uses this method internally._ 29 | 30 | ```js 31 | grunt.template.setDelimiters(name) 32 | ``` 33 | 34 | ### grunt.template.addDelimiters 35 | Add a named set of [Lo-Dash template](http://lodash.com/docs/#template) delimiters. You probably won't need to use this method, because the built-in delimiters should be sufficient, but you could always add `{% %}` or `[% %]` style delimiters. 36 | 37 | The `name` argument should be unique since it is how we access the delimiters from `grunt.template.setDelimiters` and as an option for `grunt.template.process`. 38 | 39 | ```js 40 | grunt.template.addDelimiters(name, opener, closer) 41 | ``` 42 | 43 | In this example, if we were to use the `{% %}` style mentioned above we would use the following: 44 | 45 | ```js 46 | grunt.template.addDelimiters('myDelimiters', '{%', '%}') 47 | ``` 48 | 49 | ## Helpers 50 | 51 | ### grunt.template.date 52 | Format a date using the [dateformat library](https://github.com/felixge/node-dateformat). 53 | 54 | ```js 55 | grunt.template.date(date, format) 56 | ``` 57 | 58 | In this example, a specific date is formatted as month/day/year. 59 | 60 | ```js 61 | grunt.template.date(847602000000, 'yyyy-mm-dd') // '1996-11-10' 62 | ``` 63 | 64 | ### grunt.template.today 65 | Format today's date using the [dateformat library](https://github.com/felixge/node-dateformat). 66 | 67 | ```js 68 | grunt.template.today(format) 69 | ``` 70 | 71 | In this example, today's date is formatted as a 4-digit year. 72 | 73 | ```js 74 | grunt.template.today('yyyy') // '2014' 75 | ``` 76 | 77 | _(somebody remind me to update this date every year so the docs appear current)_ 78 | -------------------------------------------------------------------------------- /Roadmap.md: -------------------------------------------------------------------------------- 1 | ## Grunt 0.next 2 | 3 | * Drop Node.JS 0.8 support 4 | * New logging (https://github.com/cowboy/node-prolog) 5 | * A logger to listen to events and output them to the console. Deals with stderr/stdout, or Grunt itself has this built in. 6 | * node-task (https://github.com/node-task) 7 | * Tasks as npm modules that can be required and run independent of any task runner (if you want to manually build a compliant config object to execute it). Can pipe data between multiple tasks (think coffeescript transpilation + uglify in a single step). All task output emitted as events. 8 | * A library for parsing configurations (merge options, template expansion, glob expansion (using lib from item #2) from the current Gruntfile format, into a valid form for running node-task compliant modules. Will support user-defined middleware for controlling config output. 9 | * A task runner which uses config parsing library from item #3 to execute node-task compatible modules (can be used programmatically, or via cli). Supports defining "alias" tasks which compile a set of tasks which can be run in parallel See: http://github.com/gruntjs/grunt 10 | 11 | ## Grunt 0.5 12 | 13 | ### Update Release 14 | 15 | * Updates dependencies 16 | * Removes external libraries under `grunt.util.` 17 | * A library for glob expansion that handles arrays of globs, negation, etc. See https://github.com/cowboy/node-globule 18 | 19 | See https://github.com/gruntjs/grunt/issues/1045 for updated information. 20 | 21 | 22 | 23 | 24 | 25 | 26 | ## Out of Date Information / Drafts 27 | 28 | **0.5 Gruntfile Ideas** 29 | ```js 30 | var grunt = require('grunt'); 31 | 32 | grunt.initConfig({ 33 | // defaults for cli 34 | grunt: { 35 | dryRun: true, 36 | stack: true, 37 | verbose: true, 38 | // what about defining loggers specific to a task? 39 | // is this required in your gruntfile or on by default? 40 | logger: [require('grunt-logger')] 41 | }, 42 | jshint: { 43 | // ... 44 | }, 45 | concat: { 46 | // ... 47 | }, 48 | min: { 49 | // ... 50 | } 51 | }); 52 | 53 | grunt.registerTask(require('grunt-contrib-jshint')); 54 | grunt.registerTask(require('grunt-contrib-concat')); 55 | grunt.registerTask(require('grunt-contrib-uglify'), 'min'); // optional second param renames 56 | 57 | // generates a node-task compliant object and runs grunt.registerTask on it 58 | grunt.registerTask('name','description', function (config) { 59 | //... 60 | }); 61 | 62 | // load a set of tasks to be run in parallel 63 | grunt.registerTask('name', ['jshint', 'concat'], { parallel:true }); 64 | 65 | // i think the cli should call this, but putting it here because you mentioned thinking it should go here. 66 | grunt.run(); 67 | ``` 68 | ***Please ignore the section below. It is a jumbled mess/work in progress and should not be considered anything resembling a roadmap.*** 69 | 70 | 527 - parallel execution of tasks 71 | 545 - conditional compilation (probably belongs on the watch task) 72 | 493 - cwd handling 73 | 74 | * more specific error codes 75 | * Task not found 76 | * Task failed 77 | * Task requirement not met 78 | * Config requirement not met 79 | 80 | ## grunt-log 81 | * Log to stderr/stdout. [#586](https://github.com/gruntjs/grunt/issues/586) [#570](https://github.com/gruntjs/grunt/issues/570) [#120](https://github.com/gruntjs/grunt/issues/120) 82 | * https://github.com/tkellen/grunt-decoupled/tree/master/grunt-log 83 | 84 | ## grunt-file 85 | * https://github.com/tkellen/grunt-decoupled/tree/master/grunt-file 86 | 87 | ## grunt-util 88 | * https://github.com/tkellen/grunt-decoupled/tree/master/grunt-util 89 | -------------------------------------------------------------------------------- /grunt.config.md: -------------------------------------------------------------------------------- 1 | Access project-specific configuration data defined in the `Gruntfile`. 2 | 3 | Note that any method marked with a ☃ (unicode snowman) is also available directly on the `grunt` object, and any method marked with a ☆ (white star) is also available inside tasks on the `this` object. Just so you know. 4 | 5 | ## Initializing Config Data 6 | _Note that the following method is also available on the `grunt` object as `grunt.initConfig`._ 7 | 8 | ### grunt.config.init ☃ 9 | Initialize a configuration object for the current project. The specified `configObject` is used by tasks and can be accessed using the `grunt.config` method. Nearly every project's `Gruntfile` will call this method. 10 | 11 | ```js 12 | grunt.config.init(configObject) 13 | ``` 14 | 15 | Note that any specified `<% %>` template strings will be processed when config data is retrieved. 16 | 17 | This example contains sample config data for the [grunt-contrib-jshint plugin](https://github.com/gruntjs/grunt-contrib-jshint) `jshint` task: 18 | 19 | ```js 20 | grunt.config.init({ 21 | jshint: { 22 | all: ['lib/*.js', 'test/*.js', 'Gruntfile.js'] 23 | } 24 | }); 25 | ``` 26 | 27 | See the [[Getting started]] guide for more configuration examples. 28 | 29 | _This method is also available as `grunt.initConfig`._ 30 | 31 | 32 | ## Accessing Config Data 33 | The following methods allow Grunt configuration data to be accessed either via dot-delimited string like `'pkg.author.name'` or via array of property name parts like `['pkg', 'author', 'name']`. 34 | 35 | Note that if a specified property name contains a `.` dot, it must be escaped with a literal backslash, eg. `'concat.dist/built\\.js'`. If an array of parts is specified, Grunt will handle the escaping internally with the `grunt.config.escape` method. 36 | 37 | ### grunt.config 38 | Get or set a value from the project's Grunt configuration. This method serves as an alias to other methods; if two arguments are passed, `grunt.config.set` is called, otherwise `grunt.config.get` is called. 39 | 40 | ```js 41 | grunt.config([prop [, value]]) 42 | ``` 43 | 44 | ### grunt.config.get 45 | Get a value from the project's Grunt configuration. If `prop` is specified, that property's value is returned, or `null` if that property is not defined. If `prop` isn't specified, a copy of the entire config object is returned. Templates strings will be recursively processed using the `grunt.config.process` method. 46 | 47 | ```js 48 | grunt.config.get([prop]) 49 | ``` 50 | 51 | ### grunt.config.process 52 | Process a value, recursively expanding `<% %>` templates (via the `grunt.template.process` method) in the context of the Grunt config, as they are encountered. this method is called automatically by `grunt.config.get` but _not_ by `grunt.config.getRaw`. 53 | 54 | ```js 55 | grunt.config.process(value) 56 | ``` 57 | 58 | If any retrieved value is entirely a single `'<%= foo %>'` or `'<%= foo.bar %>'` template string, and the specified `foo` or `foo.bar` property is a non-string (and not `null` or `undefined`) value, it will be expanded to the _actual_ value. That, combined with grunt's task system automatically flattening arrays, can be extremely useful. 59 | 60 | ### grunt.config.getRaw 61 | Get a raw value from the project's Grunt configuration, without processing `<% %>` template strings. If `prop` is specified, that property's value is returned, or `null` if that property is not defined. If `prop` isn't specified, a copy of the entire config object is returned. 62 | 63 | ```js 64 | grunt.config.getRaw([prop]) 65 | ``` 66 | 67 | ### grunt.config.set 68 | Set a value into the project's Grunt configuration. 69 | 70 | ```js 71 | grunt.config.set(prop, value) 72 | ``` 73 | 74 | Note that any specified `<% %>` template strings will only be processed when config data is retrieved. 75 | 76 | ### grunt.config.escape 77 | Escape `.` dots in the given `propString`. This should be used for property names that contain dots. 78 | 79 | ```js 80 | grunt.config.escape(propString) 81 | ``` 82 | 83 | ### grunt.config.merge 84 | *Added in 0.4.5* 85 | 86 | Recursively merges properties of the specified `configObject` into the current project configuration. 87 | 88 | ```js 89 | grunt.config.merge(configObject) 90 | ``` 91 | You can use this method to append configuration options, targets, etc., to already defined tasks, for example: 92 | ```js 93 | grunt.config.merge({ 94 | watch: { 95 | files: ["path/to/files"], 96 | tasks: ["task"] 97 | } 98 | }); 99 | ``` 100 | 101 | ## Requiring Config Data 102 | _Note that the method listed below is also available inside tasks on the `this` object as `this.requiresConfig`._ 103 | 104 | ### grunt.config.requires ☆ 105 | Fail the current task if one or more required config properties is missing, `null` or `undefined`. One or more string or array config properties may be specified. 106 | 107 | ```js 108 | grunt.config.requires(prop [, prop [, ...]]) 109 | ``` 110 | 111 | _This method is also available inside tasks as `this.requiresConfig`._ 112 | -------------------------------------------------------------------------------- /grunt.log.md: -------------------------------------------------------------------------------- 1 | Output messages to the console. 2 | 3 | See the [log lib source](https://github.com/gruntjs/grunt-legacy-log/blob/master/index.js) for more information. 4 | 5 | ## The log API 6 | Grunt output should look consistent, and maybe even pretty. As such, there is a plethora of logging methods, and a few useful patterns. All of the methods that actually log something are chainable. 7 | 8 | _Note: all methods available under `grunt.verbose` work exactly like `grunt.log` methods, but only log if the `--verbose` command-line option was specified._ 9 | 10 | ### grunt.log.write / grunt.verbose.write 11 | Log the specified `msg` string, with no trailing newline. 12 | 13 | ```javascript 14 | grunt.log.write(msg) 15 | ``` 16 | 17 | ### grunt.log.writeln / grunt.verbose.writeln 18 | Log the specified `msg` string, with trailing newline. 19 | 20 | ```javascript 21 | grunt.log.writeln([msg]) 22 | ``` 23 | 24 | ### grunt.log.error / grunt.verbose.error 25 | If `msg` string is omitted, logs `ERROR` in red, otherwise logs `>> msg`, with trailing newline. 26 | 27 | ```javascript 28 | grunt.log.error([msg]) 29 | ``` 30 | 31 | ### grunt.log.errorlns / grunt.verbose.errorlns 32 | Log an error with `grunt.log.error`, wrapping text to 80 columns using `grunt.log.wraptext`. 33 | 34 | ```javascript 35 | grunt.log.errorlns(msg) 36 | ``` 37 | 38 | ### grunt.log.ok / grunt.verbose.ok 39 | If `msg` string is omitted, logs `OK` in green, otherwise logs `>> msg`, with trailing newline. 40 | 41 | ```javascript 42 | grunt.log.ok([msg]) 43 | ``` 44 | 45 | ### grunt.log.oklns / grunt.verbose.oklns 46 | Log an ok message with `grunt.log.ok`, wrapping text to 80 columns using `grunt.log.wraptext`. 47 | 48 | ```javascript 49 | grunt.log.oklns(msg) 50 | ``` 51 | 52 | ### grunt.log.subhead / grunt.verbose.subhead 53 | Log the specified `msg` string in **bold**, with trailing newline. 54 | 55 | ```javascript 56 | grunt.log.subhead(msg) 57 | ``` 58 | 59 | ### grunt.log.writeflags / grunt.verbose.writeflags 60 | Log a list of `obj` properties (good for debugging flags). 61 | 62 | ```javascript 63 | grunt.log.writeflags(obj, prefix) 64 | ``` 65 | 66 | ### grunt.log.debug / grunt.verbose.debug 67 | Logs a debugging message, but only if the `--debug` command-line option was specified. 68 | 69 | ```javascript 70 | grunt.log.debug(msg) 71 | ``` 72 | 73 | ## Verbose and Notverbose 74 | All logging methods available under `grunt.verbose` work exactly like their `grunt.log` counterparts, but only log if the `--verbose` command-line option was specified. There is also a "notverbose" counterpart available at both `grunt.log.notverbose` and `grunt.log.verbose.or`. In fact, the `.or` property can be used on both `verbose` and `notverbose` to effectively toggle between the two. 75 | 76 | ### grunt.verbose / grunt.log.verbose 77 | This object contains all methods of `grunt.log` but only logs if the `--verbose` command-line option was specified. 78 | 79 | ```javascript 80 | grunt.verbose 81 | ``` 82 | 83 | ### grunt.verbose.or / grunt.log.notverbose 84 | This object contains all methods of `grunt.log` but only logs if the `--verbose` command-line option was _not_ specified. 85 | 86 | ```javascript 87 | grunt.verbose.or 88 | ``` 89 | 90 | ## Utility Methods 91 | These methods don't actually log, they just return strings that can be used in other methods. 92 | 93 | ### grunt.log.wordlist 94 | Returns a comma-separated list of `arr` array items. 95 | 96 | ```javascript 97 | grunt.log.wordlist(arr [, options]) 98 | ``` 99 | 100 | The `options` object has these possible properties, and default values: 101 | 102 | ```javascript 103 | var options = { 104 | // The separator string (can be colored). 105 | separator: ', ', 106 | // The array item color (specify false to not colorize). 107 | color: 'cyan', 108 | }; 109 | ``` 110 | 111 | ### grunt.log.uncolor 112 | Removes all color information from a string, making it suitable for testing `.length` or perhaps logging to a file. 113 | 114 | ```javascript 115 | grunt.log.uncolor(str) 116 | ``` 117 | 118 | ### grunt.log.wraptext 119 | Wrap `text` string to `width` characters with `\n`, ensuring that words are not split in the middle unless absolutely necessary. 120 | 121 | ```javascript 122 | grunt.log.wraptext(width, text) 123 | ``` 124 | 125 | ### grunt.log.table 126 | Wrap `texts` array of strings to columns `widths` characters wide. A wrapper for the `grunt.log.wraptext` method that can be used to generate output in columns. 127 | 128 | ```javascript 129 | grunt.log.table(widths, texts) 130 | ``` 131 | 132 | ## An Example 133 | 134 | A common pattern is to only log when in `--verbose` mode OR if an error occurs, like so: 135 | 136 | ```javascript 137 | grunt.registerTask('something', 'Do something interesting.', function(arg) { 138 | var msg = 'Doing something...'; 139 | grunt.verbose.write(msg); 140 | try { 141 | doSomethingThatThrowsAnExceptionOnError(arg); 142 | // Success! 143 | grunt.verbose.ok(); 144 | } catch(e) { 145 | // Something went wrong. 146 | grunt.verbose.or.write(msg).error().error(e.message); 147 | grunt.fail.warn('Something went wrong.'); 148 | } 149 | }); 150 | ``` 151 | 152 | An explanation of the above code: 153 | 154 | 1. `grunt.verbose.write(msg);` logs the message (no newline), but only in `--verbose` mode. 155 | 2. `grunt.verbose.ok();` logs OK in green, with a newline. 156 | 3. `grunt.verbose.or.write(msg).error().error(e.message);` does a few things: 157 | 1. `grunt.verbose.or.write(msg)` logs the message (no newline) if not in `--verbose` mode, and returns the `notverbose` object. 158 | 2. `.error()` logs ERROR in red, with a newline, and returns the `notverbose` object. 159 | 3. `.error(e.message);` logs the actual error message (and returns the `notverbose` object). 160 | 4. `grunt.fail.warn('Something went wrong.');` logs a warning in bright yellow, exiting Grunt with exit code 1, unless `--force` was specified. 161 | 162 | Take a look at the [grunt-contrib-* tasks source code](https://github.com/gruntjs) for more examples. 163 | -------------------------------------------------------------------------------- /grunt.util.md: -------------------------------------------------------------------------------- 1 | Miscellaneous utilities for your Gruntfile and tasks. 2 | 3 | ### grunt.util.kindOf 4 | Return the "kind" of a value. Like `typeof` but returns the internal `[[Class]]` value. Possible results are `"number"`, `"string"`, `"boolean"`, `"function"`, `"regexp"`, `"array"`, `"date"`, `"error"`, `"null"`, `"undefined"` and the catch-all `"object"`. 5 | 6 | ```js 7 | grunt.util.kindOf(value) 8 | ``` 9 | 10 | ### grunt.util.error 11 | Return a new Error instance (that can be thrown) with the appropriate message. If an Error object is specified instead of `message` that object will be returned. 12 | Also, if an Error object is specified for `origError` and Grunt was run with the `--stack` option, the original Error stack will be dumped. 13 | 14 | ```js 15 | grunt.util.error(message [, origError]) 16 | ``` 17 | 18 | ### grunt.util.linefeed 19 | The linefeed character, normalized for the current operating system. (`\r\n` on Windows, `\n` otherwise) 20 | 21 | ### grunt.util.normalizelf 22 | Given a string, return a new string with all the linefeeds normalized for the current operating system. (`\r\n` on Windows, `\n` otherwise) 23 | 24 | ```js 25 | grunt.util.normalizelf(string) 26 | ``` 27 | 28 | ### grunt.util.recurse 29 | Recurse through nested objects and arrays, executing `callbackFunction` for each non-object value. If `continueFunction` returns `false`, a given object or value will be skipped. 30 | 31 | ```js 32 | grunt.util.recurse(object, callbackFunction, continueFunction) 33 | ``` 34 | 35 | ### grunt.util.repeat 36 | Return string `str` repeated `n` times. 37 | 38 | ```js 39 | grunt.util.repeat(n, str) 40 | ``` 41 | 42 | ### grunt.util.pluralize 43 | Given `str` of `"a/b"`, If `n` is `1`, return `"a"` otherwise `"b"`. You can specify a custom separator if '/' doesn't work for you. 44 | 45 | ```js 46 | grunt.util.pluralize(n, str, separator) 47 | ``` 48 | 49 | ### grunt.util.spawn 50 | Spawn a child process, keeping track of its stdout, stderr and exit code. The method returns a reference to the spawned child. When the child exits, the `doneFunction` is called. 51 | 52 | ```js 53 | grunt.util.spawn(options, doneFunction) 54 | ``` 55 | 56 | The `options` object has these possible properties: 57 | 58 | ```js 59 | var options = { 60 | // The command to execute. It should be in the system path. 61 | cmd: commandToExecute, 62 | // If specified, the same grunt bin that is currently running will be 63 | // spawned as the child command, instead of the "cmd" option. Defaults 64 | // to false. 65 | grunt: boolean, 66 | // An array of arguments to pass to the command. 67 | args: arrayOfArguments, 68 | // Additional options for the Node.js child_process spawn method. 69 | opts: nodeSpawnOptions, 70 | // If this value is set and an error occurs, it will be used as the value 71 | // and null will be passed as the error value. 72 | fallback: fallbackValue 73 | }; 74 | ``` 75 | 76 | The `doneFunction` accepts these arguments: 77 | 78 | ```js 79 | function doneFunction(error, result, code) { 80 | // If the exit code was non-zero and a fallback wasn't specified, an Error 81 | // object, otherwise null. 82 | error 83 | // The result object is an object with the properties .stdout, .stderr, and 84 | // .code (exit code). 85 | result 86 | // When result is coerced to a string, the value is stdout if the exit code 87 | // was zero, the fallback if the exit code was non-zero and a fallback was 88 | // specified, or stderr if the exit code was non-zero and a fallback was 89 | // not specified. 90 | String(result) 91 | // The numeric exit code. 92 | code 93 | } 94 | ``` 95 | 96 | ### grunt.util.toArray 97 | Given an array or array-like object, return an array. Great for converting `arguments` objects into arrays. 98 | 99 | ```js 100 | grunt.util.toArray(arrayLikeObject) 101 | ``` 102 | 103 | ### grunt.util.callbackify 104 | Normalizes both "returns a value" and "passes result to a callback" functions to always pass a result to the specified callback. If the original function returns a value, that value will now be passed to the callback, which is specified as the last argument, after all other predefined arguments. If the original function passed a value to a callback, it will continue to do so. 105 | 106 | ```js 107 | grunt.util.callbackify(syncOrAsyncFunction) 108 | ``` 109 | 110 | This example might better illustrate: 111 | 112 | ```js 113 | function add1(a, b) { 114 | return a + b; 115 | } 116 | function add2(a, b, callback) { 117 | callback(a + b); 118 | } 119 | 120 | var fn1 = grunt.util.callbackify(add1); 121 | var fn2 = grunt.util.callbackify(add2); 122 | 123 | fn1(1, 2, function(result) { 124 | console.log('1 plus 2 equals ' + result); 125 | }); 126 | fn2(1, 2, function(result) { 127 | console.log('1 plus 2 equals ' + result); 128 | }); 129 | ``` 130 | 131 | ## Internal libraries 132 | 133 | ### grunt.util.namespace 134 | An internal library for resolving deeply-nested properties in objects. 135 | 136 | ### grunt.util.task 137 | An internal library for task running. 138 | 139 | ## External libraries 140 | *Deprecated* 141 | 142 | __All external libraries that are listed below are now deprecated.__ 143 | 144 | Please use __npm__ to manage these external libraries in your project's dependencies. 145 | 146 | For example if you want to use [Lo-Dash](https://npmjs.org/package/lodash), install it first: `npm install lodash`, then 147 | use it in your `Gruntfile`: `var _ = require('lodash');`. 148 | 149 | #### grunt.util._ 150 | *Deprecated* 151 | 152 | [Lo-Dash](http://lodash.com/) and [Underscore.string](https://github.com/epeli/underscore.string) 153 | 154 | `grunt.util._.str` is available for methods that conflict with existing Lo-Dash methods. 155 | 156 | #### grunt.util.async 157 | *Deprecated* 158 | 159 | [Async](https://github.com/caolan/async) - Async utilities for node and the browser. 160 | 161 | #### grunt.util.hooker 162 | *Deprecated* 163 | 164 | [JavaScript Hooker](https://github.com/cowboy/javascript-hooker) - Monkey-patch (hook) functions for debugging and stuff. 165 | -------------------------------------------------------------------------------- /Frequently-Asked-Questions.md: -------------------------------------------------------------------------------- 1 | ## How do I install grunt? 2 | For general installation instructions, please read the [[Getting Started]] guide. If you need more specific information after having read that, read the comprehensive [[Installing grunt]] guide. 3 | 4 | ## When will I be able to use in-development feature 'X'? 5 | Installing both published and unpublished development versions of Grunt is covered in the [[Installing grunt]] guide. 6 | 7 | ## Does Grunt work on Windows? 8 | Grunt works fine on Windows, because [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) both work fine on Windows. Usually the problematic part is [Cygwin](http://www.cygwin.com/), because it bundles an outdated version of Node.js. 9 | 10 | The best way to avoid this issue is to use the [msysGit installer](http://msysgit.github.com/) to install the `git` binary and the [Node.js installer](http://nodejs.org/#download) to install the `node` and `npm` binaries, and to use the built-in [Windows command prompt](http://www.cs.princeton.edu/courses/archive/spr05/cos126/cmd-prompt.html) or [PowerShell](http://support.microsoft.com/kb/968929) instead of Cygwin. 11 | 12 | ## Why doesn't my asynchronous task complete? 13 | Chances are this is happening because you have forgotten to call the [this.async](grunt.task#wiki-this-async) method to tell Grunt that your task is asynchronous. For simplicity's sake, Grunt uses a synchronous coding style, which can be switched to asynchronous by calling `this.async()` within the task body. 14 | 15 | Note that passing `false` to the `done()` function tells Grunt that the task has failed. 16 | 17 | For example: 18 | 19 | ```javascript 20 | grunt.registerTask('asyncme', 'My asynchronous task.', function() { 21 | var done = this.async(); 22 | doSomethingAsync(done); 23 | }); 24 | ``` 25 | 26 | ## How do I enable shell tab auto-completion? 27 | To enable bash tab auto-completion for grunt, add the following line to your `~/.bashrc` file: 28 | 29 | ```bash 30 | eval "$(grunt --completion=bash)" 31 | ``` 32 | 33 | This assumes that Grunt has been installed globally with `npm install -g grunt`. Currently, the only supported shell is bash. 34 | 35 | ## How can I share parameters across multiple tasks? 36 | While each task can accept its own parameters, there are a few options available for sharing parameters across multiple tasks. 37 | 38 | ### "Dynamic" alias tasks 39 | **This is the preferred method for sharing parameters across multiple tasks.** 40 | 41 | Whereas [alias tasks](grunt#wiki-grunt-registerTask) are necessarily simple, a regular task can use [grunt.task.run](grunt.task#wiki-grunt-task-run) to make it effectively function as a "dynamic" alias task. In this example, running `grunt build:001` on the command line would result in the `foo:001`, `bar:001` and `baz:001` tasks being run. 42 | 43 | ```javascript 44 | grunt.registerTask('build', 'Run all my build tasks.', function(n) { 45 | if (n == null) { 46 | grunt.warn('Build num must be specified, like build:001.'); 47 | } 48 | grunt.task.run('foo:' + n, 'bar:' + n, 'baz:' + n); 49 | }); 50 | ``` 51 | 52 | ### -- options 53 | 54 | Another way to share a parameter across multiple tasks would be to use [grunt.option](grunt#wiki-grunt-option). In this example, running `grunt deploy --target=staging` on the command line would cause `grunt.option('target')` to return `"staging"`. 55 | 56 | ```javascript 57 | grunt.registerTask('upload', 'Upload code to specified target.', function(n) { 58 | var target = grunt.option('target'); 59 | // do something useful with target here 60 | }); 61 | grunt.registerTask('deploy', ['validate', 'upload']); 62 | ``` 63 | 64 | _Note that boolean options can be specified using just a key without a value. For example, running `grunt deploy --staging` on the command line would cause `grunt.option('staging')` to return `true`._ 65 | 66 | ### Globals and configs 67 | 68 | In other cases, you may want to expose a way to set configuration or global values. In those cases, register a task that sets its arguments as a global or config value. 69 | 70 | In this example, running `grunt set_global:name:peter set_config:target:staging deploy` on the command line would cause `global.name` to be `"peter"` and `grunt.config('target')` to return `"staging"`. Presumably, the `deploy` task would use those values. 71 | 72 | ```javascript 73 | grunt.registerTask('set_global', 'Set a global variable.', function(name, val) { 74 | global[name] = val; 75 | }); 76 | 77 | grunt.registerTask('set_config', 'Set a config property.', function(name, val) { 78 | grunt.config.set(name, val); 79 | }); 80 | ``` 81 | 82 | ## How I get a stack trace when an error occurs? 83 | 84 | Use the `--stack` option to see stack traces. Such as `grunt task --stack` 85 | 86 | ## Why am I getting a "Maximum call stack size exceeded" error? 87 | 88 | You probably created an alias task with the same name as one of your regular tasks. 89 | Example: `grunt.registerTask('uglify', ['uglify:my_target']);` should be `grunt.registerTask('myUglify', ['uglify:my_target']);`. 90 | 91 | ## How do I uninstall or remove unwanted plugins? 92 | 93 | At least two ways. One way is to use `npm uninstall [GRUNT_PLUGIN] --save-dev`, this will remove the plugin from your `package.json` and from `node_modules`. You may also delete the dependencies you don't want from your `package.json` manually and then run `npm prune`. 94 | 95 | ## Error "Fail to install with npm error: No compatible version found" 96 | 97 | Make sure you have the latest stable version of [NPM and Node.JS](http://nodejs.org/) 98 | 99 | 100 | *** 101 | 102 | 103 | ## grunt 0.3 Questions 104 | 105 | ## On Windows with Grunt 0.3, why does my JS editor open when I try to run grunt? 106 | If you're in the same directory as the [Gruntfile](Getting-started), Windows tries to execute _that file_ when you type grunt. So you need to type `grunt.cmd` instead. 107 | 108 | An alternative would be to use the `DOSKEY` command to create a Grunt macro, following [these directions](http://devblog.point2.com/2010/05/14/setup-persistent-aliases-macros-in-windows-command-prompt-cmd-exe-using-doskey/). That would allow you to use `grunt` instead of `grunt.cmd`. 109 | 110 | This is the `DOSKEY` command you'd use: 111 | 112 | ``` 113 | DOSKEY grunt=grunt.cmd $* 114 | ``` 115 | -------------------------------------------------------------------------------- /Who-uses-Grunt.md: -------------------------------------------------------------------------------- 1 | This is just a short list of companies and projects that use Grunt. 2 | If you've used Grunt in a project and would like it listed on this page, 3 | [please edit this page](https://github.com/gruntjs/grunt-docs/blob/master/Who-uses-Grunt.md). 4 | 5 | ### [INK](http://ink.sapo.pt) 6 | 7 | ### [Adobe](http://www.adobe.com/) 8 | - [Brackets](http://brackets.io/) ([Gruntfile](https://github.com/adobe/brackets/blob/master/Gruntfile.js)) 9 | - [CSS FilterLab](http://html.adobe.com/webstandards/csscustomfilters/cssfilterlab/) ([Gruntfile](https://github.com/adobe/cssfilterlab/blob/master/grunt.js)) 10 | 11 | ### [jQuery](http://jquery.com/) 12 | - [jQuery](http://jquery.com/) - ([Gruntfile](https://github.com/jquery/jquery/blob/master/Gruntfile.js)) 13 | - [jQuery UI](http://jqueryui.com/) - ([Gruntfile](https://github.com/jquery/jquery-ui/blob/master/Gruntfile.js)) 14 | - [QUnit](http://qunitjs.com/) - ([Gruntfile](https://github.com/jquery/qunit/blob/master/Gruntfile.js)) 15 | 16 | ### [Twitter](https://twitter.com/) 17 | - [Tweetdeck](http://www.tweetdeck.com/) 18 | - [Typeahead](https://github.com/twitter/typeahead.js) ([Gruntfile](https://github.com/twitter/typeahead.js/blob/master/Gruntfile.js)) 19 | 20 | ### [Mozilla](https://mozilla.org/) 21 | - [Firefox Accounts projects](https://accounts.firefox.com) ([Gruntfile](https://github.com/mozilla/fxa-content-server/blob/master/Gruntfile.js), [Gruntfile](https://github.com/mozilla/fxa-auth-server/blob/master/Gruntfile.js), [Gruntfile](https://github.com/mozilla/fxa-js-client/blob/master/Gruntfile.js)) 22 | 23 | ### [Bootstrap](http://getbootstrap.com/) 24 | - [Gruntfile](https://github.com/twbs/bootstrap/blob/master/Gruntfile.js) 25 | 26 | ### [Cloudant](https://cloudant.com/) 27 | - [Backbone Cloudant](https://github.com/cloudant-labs/backbone.cloudant) ([Gruntfile](https://github.com/cloudant-labs/backbone.cloudant/blob/master/Gruntfile.js)) 28 | 29 | ### [Bitovi](http://bitovi.com/) 30 | - [CanJS](http://canjs.us/) ([Gruntfile](https://github.com/bitovi/canjs/blob/master/Gruntfile.js)) 31 | 32 | ### [TestObject](https://www.testobject.com) 33 | 34 | ### [Filament Group](http://filamentgroup.com/) 35 | - [X-rayHTML](https://github.com/filamentgroup/X-rayHTML) ([Gruntfile](https://github.com/filamentgroup/X-rayHTML/blob/master/grunt.js)) 36 | - [Grunticon](https://github.com/filamentgroup/grunticon) ([Gruntfile](https://github.com/filamentgroup/grunticon/blob/master/Gruntfile.js)) 37 | 38 | ### [Fuel UX](http://exacttarget.github.com/fuelux/) 39 | - [Fuel UX](http://exacttarget.github.com/fuelux/) ([Gruntfile](https://github.com/ExactTarget/fuelux/blob/master/Gruntfile.js)) 40 | 41 | ### [SauceLabs](https://saucelabs.com/) 42 | - [Appium](https://saucelabs.com/appium) ([Gruntfile](https://github.com/appium/appium/blob/master/Gruntfile.js)) 43 | 44 | ### [Modernizr](http://modernizr.com/) 45 | - [Modernizr](http://modernizr.com/) ([Gruntfile](https://github.com/Modernizr/Modernizr/blob/master/Gruntfile.js)) 46 | 47 | ### [Opera](http://opera.com) 48 | - [Opera GitHub Projects](https://github.com/operasoftware) 49 | 50 | ### [LiveChat](http://www.livechatinc.com) 51 | - [LiveChat Grunt Workflow](http://developers.livechatinc.com/blog/how-livechat-uses-grunt-js-for-easy-product-deployment/) 52 | 53 | ### [WordPress](https://wordpress.org/) 54 | - [WordPress Build Process](https://make.wordpress.org/core/2013/08/06/a-new-frontier-for-core-development/) ([Gruntfile](https://core.trac.wordpress.org/browser/trunk/Gruntfile.js)) 55 | - [bbPress](https://bbpress.org) ([Gruntfile](https://bbpress.trac.wordpress.org/browser/trunk/Gruntfile.js)) 56 | - [BuddyPress](https://buddypress.org) ([Gruntfile](https://buddypress.trac.wordpress.org/browser/trunk/Gruntfile.js)) 57 | 58 | ### [Walmart](http://www.walmart.com/) 59 | - [Thorax](https://github.com/walmartlabs/thorax) ([Gruntfile](https://github.com/walmartlabs/thorax/blob/master/Gruntfile.js)) 60 | - [Lumbar](http://walmartlabs.github.io/lumbar/) ([Gruntfile](https://github.com/walmartlabs/lumbar/blob/master/Gruntfile.js)) 61 | 62 | ### [Bazaarvoice](http://www.bazaarvoice.com/) 63 | 64 | ### [dscout](http://dscout.com/) 65 | - [Velge](https://github.com/dscout/velge) ([Gruntfile](https://github.com/dscout/velge/blob/master/Gruntfile.js)) 66 | 67 | ### [Ghost](https://ghost.org/) 68 | - [Gruntfile](https://github.com/TryGhost/Ghost/blob/master/Gruntfile.js) 69 | 70 | ### [JS Bin](http://jsbin.com/) 71 | - [Gruntfile](https://github.com/remy/jsbin/blob/master/Gruntfile.js) 72 | 73 | ### [SitePen](http://sitepen.com/) 74 | - [generator-dojo](https://github.com/bryanforbes/generator-dojo/) ([Gruntfile](https://github.com/bryanforbes/generator-dojo/blob/master/app/templates/Gruntfile.js)) 75 | - [Intern](http://theintern.io/) ([Gruntfile](https://github.com/theintern/intern-examples/blob/master/grunt-example/Gruntfile.js)) 76 | 77 | ### [Phaser](http://phaser.io/) 78 | - [phaser](https://github.com/photonstorm/phaser/) ([Gruntfile](https://github.com/photonstorm/phaser/blob/master/Gruntfile.js)) 79 | 80 | ### [BufferApp](https://bufferapp.com) 81 | 82 | ### [Shopetti](https://www.shopetti.com) 83 | 84 | ### [Consunet Pty Ltd](https://www.consunet.com.au) 85 | - [WhisperNote](https://www.consunet.com.au/products/whispernote/) - ([Gruntfile](https://github.com/Consunet/Apps/blob/master/WhisperNote/Gruntfile.js)) 86 | - [EveryPass](https://www.consunet.com.au/products/everypass/) - ([Gruntfile](https://github.com/Consunet/Apps/blob/master/EveryPass/Gruntfile.js)) 87 | 88 | ### [Assemble](http://assemble.io/) 89 | - [Gruntfile](https://github.com/assemble/assemble/blob/master/Gruntfile.js) 90 | 91 | ### [Sourcey](http://sourcey.com) 92 | - [Mesh](https://github.com/sourcey/mesh) ([Gruntfile](https://github.com/sourcey/mesh/blob/master/Gruntfile.js)) 93 | - [Symple](https://github.com/sourcey/symple) ([Gruntfile](https://github.com/sourcey/symple/blob/master/client/Gruntfile.js)) 94 | 95 | ### [Happy Cog](http://happycog.com) 96 | 97 | ### [MadGlory](http://madglory.com) 98 | 99 | ### [Victoria's Secret](http://www.victoriassecret.com) 100 | 101 | ### [Clevertim CRM](http://www.clevertim.com) 102 | 103 | ### [Kickoff](http://tmwagency.github.io/kickoff/) 104 | - [Gruntfile](https://github.com/tmwagency/kickoff/blob/master/Gruntfile.js) 105 | 106 | ### [Vodori](http://vodori.com) 107 | 108 | ### [Jimdo](http://www.jimdo.com/) 109 | - [angular-spectrum-colorpicker](https://github.com/Jimdo/angular-spectrum-colorpicker) ([Gruntfile](https://github.com/Jimdo/angular-spectrum-colorpicker/blob/master/Gruntfile.js)) 110 | - [angular-directive-seed](https://github.com/Jimdo/angular-directive-seed) ([Gruntfile](https://github.com/Jimdo/angular-directive-seed/blob/master/Gruntfile.js)) 111 | 112 | ### [Crowdfunder.co.uk](http://www.crowdfunder.co.uk/) 113 | 114 | -------------------------------------------------------------------------------- /Sample-Gruntfile.md: -------------------------------------------------------------------------------- 1 | Below we walk through a sample `Gruntfile`, but if you're looking for a quick example, here's one: 2 | 3 | ```js 4 | module.exports = function(grunt) { 5 | 6 | grunt.initConfig({ 7 | jshint: { 8 | files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'], 9 | options: { 10 | globals: { 11 | jQuery: true 12 | } 13 | } 14 | }, 15 | watch: { 16 | files: ['<%= jshint.files %>'], 17 | tasks: ['jshint'] 18 | } 19 | }); 20 | 21 | grunt.loadNpmTasks('grunt-contrib-jshint'); 22 | grunt.loadNpmTasks('grunt-contrib-watch'); 23 | 24 | grunt.registerTask('default', ['jshint']); 25 | 26 | }; 27 | ``` 28 | 29 | The entire `Gruntfile` is at the bottom of this page, but if you keep reading we'll walk through it a step at a time, using the following five Grunt plugins: 30 | 31 | - [grunt-contrib-uglify](https://github.com/gruntjs/grunt-contrib-uglify) 32 | - [grunt-contrib-qunit](https://github.com/gruntjs/grunt-contrib-qunit) 33 | - [grunt-contrib-concat](https://github.com/gruntjs/grunt-contrib-concat) 34 | - [grunt-contrib-jshint](https://github.com/gruntjs/grunt-contrib-jshint) 35 | - [grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch) 36 | 37 | The first part is the "wrapper" function, which encapsulates your Grunt configuration. 38 | 39 | ```javascript 40 | module.exports = function(grunt) { 41 | } 42 | ``` 43 | 44 | Within that function we can initialize our configuration object: 45 | 46 | ```javascript 47 | grunt.initConfig({ 48 | }); 49 | ``` 50 | 51 | Next we can read in the project settings from the `package.json` file into the `pkg` property. This allows us to refer to the values of properties within our `package.json` file, as we'll see shortly. 52 | 53 | ```javascript 54 | pkg: grunt.file.readJSON('package.json') 55 | ``` 56 | 57 | This leaves us with this so far: 58 | 59 | ```javascript 60 | module.exports = function(grunt) { 61 | grunt.initConfig({ 62 | pkg: grunt.file.readJSON('package.json') 63 | }); 64 | }; 65 | ``` 66 | 67 | Now we can define configuration for each of the tasks we have. The configuration object for a task lives as a property on the configuration object, that's named the same as the task. So the "concat" task goes in our config object under the "concat" key. Below is my configuration object for the "concat" task. 68 | 69 | ```javascript 70 | concat: { 71 | options: { 72 | // define a string to put between each file in the concatenated output 73 | separator: ';' 74 | }, 75 | dist: { 76 | // the files to concatenate 77 | src: ['src/**/*.js'], 78 | // the location of the resulting JS file 79 | dest: 'dist/<%= pkg.name %>.js' 80 | } 81 | } 82 | ``` 83 | 84 | Note how I refer to the `name` property that's in the JSON file. We access this using `pkg.name` as earlier we defined the `pkg` property to be the result of loading the `package.json` file, which is then parsed to a JavaScript object. Grunt has simple template engine to output the values of properties in the configuration object. Here I tell the concat task to concatenate all files that exist within `src/` and end in `.js`. 85 | 86 | Now lets configure the uglify plugin, which minifies our JavaScript: 87 | 88 | ```javascript 89 | uglify: { 90 | options: { 91 | // the banner is inserted at the top of the output 92 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' 93 | }, 94 | dist: { 95 | files: { 96 | 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] 97 | } 98 | } 99 | } 100 | ``` 101 | 102 | This tells uglify to create a file within `dist/` that contains the result of minifying the JavaScript files. Here I use `<%= concat.dist.dest %>` so uglify will minify the file that the concat task produces. 103 | 104 | The QUnit plugin is really simple to set up. You just need to give it the location of the test runner files, which are the HTML files QUnit runs on. 105 | 106 | ```javascript 107 | qunit: { 108 | files: ['test/**/*.html'] 109 | }, 110 | ``` 111 | 112 | The JSHint plugin is also very simple to configure: 113 | 114 | ```javascript 115 | jshint: { 116 | // define the files to lint 117 | files: ['gruntfile.js', 'src/**/*.js', 'test/**/*.js'], 118 | // configure JSHint (documented at http://www.jshint.com/docs/) 119 | options: { 120 | // more options here if you want to override JSHint defaults 121 | globals: { 122 | jQuery: true, 123 | console: true, 124 | module: true 125 | } 126 | } 127 | } 128 | ``` 129 | 130 | JSHint simply takes an array of files and then an object of options. These are all [documented on the JSHint site](http://www.jshint.com/docs/). If you're happy with the JSHint defaults, there's no need to redefine them in the Gruntfile. 131 | 132 | Finally we have the watch plugin: 133 | 134 | ```javascript 135 | watch: { 136 | files: ['<%= jshint.files %>'], 137 | tasks: ['jshint', 'qunit'] 138 | } 139 | ``` 140 | 141 | This can be run on the command line with `grunt watch`. When it detects any of the files specified have changed (here, I just use the same files I told JSHint to check), it will run the tasks you specify, in the order they appear. 142 | 143 | Finally, we have to load in the Grunt plugins we need. These should have all been installed through npm. 144 | 145 | ```javascript 146 | grunt.loadNpmTasks('grunt-contrib-uglify'); 147 | grunt.loadNpmTasks('grunt-contrib-jshint'); 148 | grunt.loadNpmTasks('grunt-contrib-qunit'); 149 | grunt.loadNpmTasks('grunt-contrib-watch'); 150 | grunt.loadNpmTasks('grunt-contrib-concat'); 151 | ``` 152 | 153 | And finally set up some tasks. Most important is the default task: 154 | 155 | 156 | ```javascript 157 | // this would be run by typing "grunt test" on the command line 158 | grunt.registerTask('test', ['jshint', 'qunit']); 159 | 160 | // the default task can be run just by typing "grunt" on the command line 161 | grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); 162 | ``` 163 | 164 | And here's the finished `Gruntfile`: 165 | 166 | ```javascript 167 | module.exports = function(grunt) { 168 | 169 | grunt.initConfig({ 170 | pkg: grunt.file.readJSON('package.json'), 171 | concat: { 172 | options: { 173 | separator: ';' 174 | }, 175 | dist: { 176 | src: ['src/**/*.js'], 177 | dest: 'dist/<%= pkg.name %>.js' 178 | } 179 | }, 180 | uglify: { 181 | options: { 182 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' 183 | }, 184 | dist: { 185 | files: { 186 | 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] 187 | } 188 | } 189 | }, 190 | qunit: { 191 | files: ['test/**/*.html'] 192 | }, 193 | jshint: { 194 | files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'], 195 | options: { 196 | // options here to override JSHint defaults 197 | globals: { 198 | jQuery: true, 199 | console: true, 200 | module: true, 201 | document: true 202 | } 203 | } 204 | }, 205 | watch: { 206 | files: ['<%= jshint.files %>'], 207 | tasks: ['jshint', 'qunit'] 208 | } 209 | }); 210 | 211 | grunt.loadNpmTasks('grunt-contrib-uglify'); 212 | grunt.loadNpmTasks('grunt-contrib-jshint'); 213 | grunt.loadNpmTasks('grunt-contrib-qunit'); 214 | grunt.loadNpmTasks('grunt-contrib-watch'); 215 | grunt.loadNpmTasks('grunt-contrib-concat'); 216 | 217 | grunt.registerTask('test', ['jshint', 'qunit']); 218 | 219 | grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); 220 | 221 | }; 222 | ``` 223 | 224 | -------------------------------------------------------------------------------- /Contributing.md: -------------------------------------------------------------------------------- 1 | There are a number of Grunt projects. 2 | 3 | * [grunt](https://github.com/gruntjs/grunt) - the main Grunt project 4 | * [grunt-init](https://github.com/gruntjs/grunt-init) - the standalone grunt-init project scaffolding tool 5 | * [gruntjs.com](https://github.com/gruntjs/gruntjs.com) - the gruntjs.com website 6 | * [grunt-contrib collection](https://github.com/gruntjs/grunt-contrib) - a collection of all Grunt "contrib" plugins 7 | 8 | In addition, each individual grunt-contrib plugin is a separate repository listed on the [gruntjs org homepage](https://github.com/gruntjs). 9 | 10 | ## Contributors License Agreement 11 | 12 | Most forms of contribution aside from providing support to other users requires that you **[sign and submit](http://dojofoundation.org/about/cla)** a Contributors License Agreement (or "CLA" for short) with the Dojo Foundation. 13 | 14 | 15 | In summary, the CLA asserts that when you donate fixes or documentation, you both own the code that you're submitting and that the Dojo Foundation can in turn license that code to other people. 16 | 17 | Sending in a CLA is a one-time thing, and once it's done, you're in the clear to start contributing to all Dojo Foundation projects! To be effective, though, you need to know a little bit about how contributors and Committers coordinate their work, so getting involved and asking questions should be your first step. 18 | 19 | For more on CLAs, read [Alex Russell's Why Do I Need to Sign This?](http://alex.dojotoolkit.org/2008/06/why-do-i-need-to-sign-this/). 20 | 21 | ## Want to contribute? 22 | 23 | If you want to contribute, but don't know where to get started, this is for you. 24 | Issues that are linked below were marked as __needs PR__, this means they need a pull request to be fixed. 25 | Choose any of these issues and make sure to comment if you are working on them. 26 | 27 | * grunt-init - [Contribution guidelines should go into contributing.md](https://github.com/gruntjs/grunt-init/issues/5) 28 | * grunt-contrib-jade - [Add support for basedir option](https://github.com/gruntjs/grunt-contrib-jade/issues/64) 29 | * grunt-init-gruntfile - [Doesn't generate a package.json](https://github.com/gruntjs/grunt-init-gruntfile/issues/6) 30 | * grunt-contrib-coffee - [Support the process option](https://github.com/gruntjs/grunt-contrib-coffee/issues/61) 31 | * grunt - [--gruntfile parameter broken with parent directories](https://github.com/gruntjs/grunt/issues/950) 32 | * grunt-contrib-compress - [Add bzip2 support](https://github.com/gruntjs/grunt-contrib-compress/issues/47) 33 | * grunt-contrib-jasmine - [Enhance logging](https://github.com/gruntjs/grunt-contrib-jasmine/issues/80) 34 | * grunt-contrib-less [Sourcemaps with multiple src files](https://github.com/gruntjs/grunt-contrib-less/issues/89) 35 | 36 | # Non-code contributions 37 | 38 | If you don't feel like writing code you can still contribute to the project! 39 | 40 | * You may submit updates and improvements to the [documentation](https://github.com/gruntjs/grunt-docs). 41 | * Submit articles and guides which are also part of the [documentation](https://github.com/gruntjs/grunt-docs). 42 | * Help Grunt user by answering questions on [StackOverflow](http://stackoverflow.com/questions/tagged/gruntjs), [IRC](http://gruntjs.com/help-resources#irc) and [GitHub](https://github.com/organizations/gruntjs/dashboard/issues/repos?direction=asc&sort=created&state=open). 43 | 44 | ## Filing issues 45 | If something isn't working like you think it should, please read [the documentation](https://github.com/gruntjs/grunt/wiki), especially the [[Getting Started]] guide. If you'd like to chat with someone, [[pop into IRC|contributing#discussing-grunt]] discussing-grunt and ask your question there. 46 | 47 | If you have a question not covered in the documentation or want to report a bug, the best way to ensure it gets addressed is to file it in the appropriate issues tracker. 48 | 49 | * **If there's an issue with grunt, grunt-init, a grunt-lib-??? module, or a specific grunt-contrib-??? plugin** 50 | * Please file an issue on that project's issues tracker. 51 | * **If you'd like to contribute a new plugin** 52 | * Please file an issue on the [grunt-contrib collection issues tracker](https://github.com/gruntjs/grunt-contrib/issues). We don't accept all plugins, but we'll certainly consider yours. 53 | * **If there's an issue with the [website](http://gruntjs.com/)** 54 | * Please file an issue on the [gruntjs.com website issues tracker](https://github.com/gruntjs/gruntjs.com/issues). 55 | * **If there's an issue that isn't specific to any of the above** 56 | * Please file an issue on the [grunt issues tracker](https://github.com/gruntjs/grunt/issues) and let us know why you're filing it there. 57 | 58 | ### Simplify the issue 59 | Try to [reduce your code](http://www.webkit.org/quality/reduction.html) to the bare minimum required to reproduce the issue. This makes it much easier (and much faster) to isolate and fix the issue. 60 | 61 | ### Explain the issue 62 | If we can't reproduce the issue, we can't fix it. Please list the exact steps required to reproduce the issue. Include versions of your OS, Node.js, grunt, etc. Include relevant logs or sample code. 63 | 64 | ## Discussing grunt 65 | Join the [freenode](http://freenode.net/) IRC #grunt channel. We've got a bot and everything. 66 | 67 | _No private messages, please._ 68 | 69 | ## Modifying grunt 70 | First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. 71 | 72 | 1. Ensure grunt-cli is installed (see the [[Getting started]] guide for more information) 73 | 1. Fork and clone the repo. 74 | 1. Check out the master branch (most grunt/grunt-contrib development happens there). 75 | 1. Run `npm install` to install all Grunt dependencies. 76 | 1. Run `npm uninstall grunt` this will remove the extra Grunt in your `node_modules`, see [npm issue 3958](https://github.com/npm/npm/issues/3958) 77 | 1. Run `grunt` to Grunt grunt. 78 | 79 | Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing has broken. 80 | 81 | ### Submitting pull requests 82 | 83 | 1. Create a new branch, please don't work in `master` directly. 84 | 1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail. 85 | 1. Fix stuff. 86 | 1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done. 87 | 1. Update the documentation to reflect any changes. 88 | 1. Push to your fork and submit a pull request. 89 | 90 | ### Syntax 91 | 92 | * Two space indents. Don't use tabs anywhere. Use `\t` if you need a tab character in a string. 93 | * No trailing whitespace, except in markdown files where a linebreak must be forced. 94 | * Don't go overboard with the whitespace. 95 | * No more than [one assignment](http://benalman.com/news/2012/05/multiple-var-statements-javascript/) per `var` statement. 96 | * Delimit strings with single-quotes `'`, not double-quotes `"`. 97 | * Prefer `if` and `else` to ["clever"](http://programmers.stackexchange.com/a/25281) uses of `? :` conditional or `||`, `&&` logical operators. 98 | * Comments are great. Just put them _before_ the line of code, _not_ at the _end_ of the line. 99 | * **When in doubt, follow the conventions you see used in the source already.** 100 | 101 | ### READMEs 102 | All of the grunt-contrib-* plugins use [grunt-contrib-internal](https://github.com/gruntjs/grunt-contrib-internal) to construct the `README.md` and `CONTRIBUTING.md` files. The source files are located in the corresponding `docs/` folder. The change logs in the READMEs are generated from the `CHANGELOG` file. 103 | 104 | When submitting changes to the README files please just edit the source files rather than the README directly. 105 | -------------------------------------------------------------------------------- /grunt.task.md: -------------------------------------------------------------------------------- 1 | Register, run and load external tasks. 2 | 3 | See the [task lib source](https://github.com/gruntjs/grunt/blob/master/lib/grunt/task.js) and [task util lib source](https://github.com/gruntjs/grunt/blob/master/lib/util/task.js) for more information. 4 | 5 | ## The task API 6 | While a task is running, Grunt exposes many task-specific utility properties and methods inside the task function via the `this` object. See the [[Inside tasks]] guide for a list of these properties and methods. 7 | 8 | Many utility properties and methods are available inside of tasks via the `this` object. 9 | 10 | Note that any method marked with a ☃ (unicode snowman) is also available directly on the `grunt` object. Just so you know. See the [API main page](grunt) for more usage information. 11 | 12 | ## Creating Tasks 13 | 14 | ### grunt.task.registerTask ☃ 15 | Register an "alias task" or a task function. This method supports the following two signatures: 16 | 17 | **Alias task** 18 | 19 | If a task list is specified, the new task will be an alias for one or more other tasks. Whenever this "alias task" is run, every specified task in `taskList` will be run, in the order specified. The `taskList` argument must be an array of tasks. 20 | 21 | ```javascript 22 | grunt.task.registerTask(taskName, taskList) 23 | ``` 24 | 25 | This example alias task defines a "default" task whereby the "jshint", "qunit", "concat" and "uglify" tasks are run automatically if Grunt is executed without any tasks specified: 26 | 27 | ```javascript 28 | task.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); 29 | ``` 30 | 31 | Task arguments can be specified as well. In this example, the alias "dist" runs both the "concat" and "uglify" tasks, each with the "dist" argument: 32 | 33 | ```javascript 34 | task.registerTask('dist', ['concat:dist', 'uglify:dist']); 35 | ``` 36 | 37 | **Function task** 38 | 39 | If a `description` and `taskFunction` are passed, the specified function will be executed whenever the task is run. In addition, the specified description will be shown when `grunt --help` is run. Task-specific properties and methods are available inside the task function as properties of the `this` object. The task function can return `false` to indicate that the task has failed. 40 | 41 | Note that the `grunt.task.registerMultiTask` method, explained below, can be used to define a special type of task known as a "multi task." 42 | 43 | ```javascript 44 | grunt.task.registerTask(taskName, description, taskFunction) 45 | ``` 46 | 47 | This example task logs `foo, testing 123` if Grunt is run via `grunt foo:testing:123`. If the task is run without arguments as `grunt foo` the task logs `foo, no args`. 48 | 49 | ```javascript 50 | grunt.task.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) { 51 | if (arguments.length === 0) { 52 | grunt.log.writeln(this.name + ", no args"); 53 | } else { 54 | grunt.log.writeln(this.name + ", " + arg1 + " " + arg2); 55 | } 56 | }); 57 | ``` 58 | 59 | See the [creating tasks](Creating-tasks) documentation for more examples of tasks and alias tasks. 60 | 61 | _This method is also available as [grunt.registerTask](grunt)._ 62 | 63 | ### grunt.task.registerMultiTask ☃ 64 | Register a "multi task." A multi task is a task that implicitly iterates over all of its named sub-properties (AKA targets) if no target was specified. In addition to the default properties and methods, extra multi task-specific properties are available inside the task function as properties of the `this` object. 65 | 66 | Many of the contrib tasks, including the [jshint task](https://github.com/gruntjs/grunt-contrib-jshint), [concat task](https://github.com/gruntjs/grunt-contrib-concat) and [uglify task](https://github.com/gruntjs/grunt-contrib-uglify) are multi tasks. 67 | 68 | ```javascript 69 | grunt.task.registerMultiTask(taskName, description, taskFunction) 70 | ``` 71 | 72 | Given the specified configuration, this example multi task would log `foo: 1,2,3` if Grunt was run via `grunt log:foo`, or it would log `bar: hello world` if Grunt was run via `grunt log:bar`. If Grunt was run as `grunt log` however, it would log `foo: 1,2,3` then `bar: hello world` then `baz: false`. 73 | 74 | ```javascript 75 | grunt.initConfig({ 76 | log: { 77 | foo: [1, 2, 3], 78 | bar: 'hello world', 79 | baz: false 80 | } 81 | }); 82 | 83 | grunt.task.registerMultiTask('log', 'Log stuff.', function() { 84 | grunt.log.writeln(this.target + ': ' + this.data); 85 | }); 86 | ``` 87 | 88 | See the [creating tasks](Creating-tasks) documentation for more examples of multi tasks. 89 | 90 | _This method is also available as [grunt.registerMultiTask](grunt)._ 91 | 92 | ### grunt.task.requires 93 | 94 | Fail the task if some other task failed or never ran. 95 | 96 | ```javascript 97 | grunt.task.requires(taskName); 98 | ``` 99 | 100 | ### grunt.task.exists 101 | *Added in 0.4.5* 102 | 103 | Check with the name, if a task exists in the registered tasks. Return a boolean. 104 | 105 | ```javascript 106 | grunt.task.exists(name) 107 | ``` 108 | 109 | ### grunt.task.renameTask ☃ 110 | Rename a task. This might be useful if you want to override the default behavior of a task, while retaining the old name. 111 | 112 | _Note that if a task has been renamed, the [this.name](inside-tasks#this.name) and [this.nameArgs](inside-tasks#this.nameArgs) properties will change accordingly._ 113 | 114 | ```javascript 115 | grunt.task.renameTask(oldname, newname) 116 | ``` 117 | 118 | _This method is also available as [grunt.renameTask](grunt)._ 119 | 120 | ## Loading Externally-Defined Tasks 121 | For most projects, tasks will be defined in the [Gruntfile](Getting-started). For larger projects, or in cases where tasks need to be shared across projects, tasks can be loaded from one or more external directories or Npm-installed Grunt plugins. 122 | 123 | ### grunt.task.loadTasks ☃ 124 | Load task-related files from the specified directory, relative to the [Gruntfile](Getting-started). This method can be used to load task-related files from a local Grunt plugin by specifying the path to that plugin's "tasks" subdirectory. 125 | 126 | ```javascript 127 | grunt.task.loadTasks(tasksPath) 128 | ``` 129 | 130 | _This method is also available as [grunt.loadTasks](grunt)._ 131 | 132 | ### grunt.task.loadNpmTasks ☃ 133 | Load tasks from the specified Grunt plugin. This plugin must be installed locally via npm, and must be relative to the [Gruntfile](Getting-started). Grunt plugins can be created by using the [grunt-init gruntplugin template](https://github.com/gruntjs/grunt-init): `grunt init:gruntplugin`. 134 | 135 | ```javascript 136 | grunt.task.loadNpmTasks(pluginName) 137 | ``` 138 | 139 | _This method is also available as [grunt.loadNpmTasks](grunt)._ 140 | 141 | 142 | ## Queueing Tasks 143 | Grunt automatically enqueues and runs all tasks specified on the command line, but individual tasks can enqueue additional tasks to be run. 144 | 145 | ### grunt.task.run 146 | Enqueue one or more tasks. Every specified task in `taskList` will be run immediately after the current task completes, in the order specified. The task list can be an array of tasks or individual task arguments. 147 | 148 | ```javascript 149 | grunt.task.run(taskList) 150 | ``` 151 | 152 | ### grunt.task.clearQueue 153 | Empty the task queue completely. Unless additional tasks are enqueued, no more tasks will be run. 154 | 155 | ```javascript 156 | grunt.task.clearQueue() 157 | ``` 158 | 159 | ### grunt.task.normalizeMultiTaskFiles 160 | Normalizes a task target configuration object into an array of src-dest file mappings. This method is used internally by the multi task system [this.files / grunt.task.current.files](grunt.task#wiki-this-files) property. 161 | 162 | ```javascript 163 | grunt.task.normalizeMultiTaskFiles(data [, targetname]) 164 | ``` 165 | -------------------------------------------------------------------------------- /Inside-Tasks.md: -------------------------------------------------------------------------------- 1 | While a task is running, Grunt exposes many task-specific utility properties and methods inside the task function via the `this` object. This same object is also exposed as `grunt.task.current` for use in [templates](grunt.template), eg. the property `this.name` is also available as `grunt.task.current.name`. 2 | 3 | ## Inside All Tasks 4 | 5 | ### this.async 6 | If a task is asynchronous, this method must be invoked to instruct Grunt to wait. It returns a handle to a "done" function that should be called when the task has completed. Either `false` or an `Error` object may be passed to the done function to instruct Grunt that the task has failed. 7 | 8 | If the `this.async` method isn't invoked, the task will execute synchronously. 9 | 10 | ```javascript 11 | // Tell Grunt this task is asynchronous. 12 | var done = this.async(); 13 | // Your async code. 14 | setTimeout(function() { 15 | // Let's simulate an error, sometimes. 16 | var success = Math.random() > 0.5; 17 | // All done! 18 | done(success); 19 | }, 1000); 20 | ``` 21 | 22 | ### this.requires 23 | If one task depends on the successful completion of another task (or tasks), this method can be used to force Grunt to abort if the other task didn't run, or if the other task failed. The tasks list can be an array of task names or individual task names, as arguments. 24 | 25 | Note that this won't actually run the specified task(s), it will just fail the current task if they haven't already run successfully. 26 | 27 | ```javascript 28 | this.requires(tasksList) 29 | ``` 30 | 31 | ### this.requiresConfig 32 | Fail the current task if one or more required [config](grunt.config) properties is missing. One or more string or array config properties may be specified. 33 | 34 | ```javascript 35 | this.requiresConfig(prop [, prop [, ...]]) 36 | ``` 37 | 38 | See the [grunt.config documentation](grunt.config) for more information about config properties. 39 | 40 | _This method is an alias for the [grunt.config.requires](grunt.config#grunt.config.requires) method._ 41 | 42 | ### this.name 43 | The name of the task, as defined in `grunt.registerTask`. For example, if a "sample" task was run as `grunt sample` or `grunt sample:foo`, inside the task function, `this.name` would be `"sample"`. 44 | 45 | _Note that if a task has been renamed with [grunt.task.renameTask](grunt.task#grunt.task.renameTask) this property will reflect the new name._ 46 | 47 | 48 | ### this.nameArgs 49 | The name of the task, including any colon-separated arguments or flags specified on the command-line. For example, if a "sample" task was run as `grunt sample:foo`, inside the task function, `this.nameArgs` would be `"sample:foo"`. 50 | 51 | _Note that if a task has been renamed with [grunt.task.renameTask](grunt.task#grunt.task.renameTask) this property will reflect the new name._ 52 | 53 | ### this.args 54 | An array of arguments passed to the task. For example, if a "sample" task was run as `grunt sample:foo:bar`, inside the task function, `this.args` would be `["foo", "bar"]`. 55 | 56 | _Note that in multi tasks, the current target is omitted from the `this.args` array._ 57 | 58 | ### this.flags 59 | An object generated from the arguments passed to the task. For example, if a "sample" task was run as `grunt sample:foo:bar`, inside the task function, `this.flags` would be `{foo: true, bar: true}`. 60 | 61 | _Note that inside multi tasks, the target name is **not** set as a flag._ 62 | 63 | ### this.errorCount 64 | The number of [grunt.log.error](grunt.log#grunt.log.error) calls that occurred during this task. This can be used to fail a task if errors were logged during the task. 65 | 66 | ### this.options 67 | Returns an options object. Properties of the optional `defaultsObj` argument will be overridden by any task-level `options` object properties, which will be further overridden in multi tasks by any target-level `options` object properties. 68 | 69 | ```js 70 | this.options([defaultsObj]) 71 | ``` 72 | 73 | This example shows how a task might use the `this.options` method: 74 | 75 | ```js 76 | var options = this.options({ 77 | enabled: false, 78 | }); 79 | 80 | doSomething(options.enabled); 81 | ``` 82 | 83 | The [Configuring tasks](configuring-tasks#options) guide shows an example of how options may be specified, from the task user's point of view. 84 | 85 | ## Inside Multi Tasks 86 | 87 | ### this.target 88 | In a multi task, this property contains the name of the target currently being iterated over. For example, if a "sample" multi task was run as `grunt sample:foo` with the config data `{sample: {foo: "bar"}}`, inside the task function, `this.target` would be `"foo"`. 89 | 90 | ### this.files 91 | In a multi task, all files specified using any Grunt-supported [file formats and options](configuring-tasks#files), [globbing patterns](configuring-tasks#globbing-patterns) or [dynamic mappings](configuring-tasks#building-the-files-object-dynamically) will automatically be normalized into a single format: the [Files Array file format](configuring-tasks#files-array-format). 92 | 93 | What this means is that tasks don't need to contain a ton of boilerplate for explicitly handling custom file formats, globbing patterns, mapping source files to destination files or filtering out files or directories. _A task user can just specify files per the [Configuring tasks](configuring-tasks#files) guide, and **Grunt will handle all the details.**_ 94 | 95 | Your task should iterate over the `this.files` array, utilizing the `src` and `dest` properties of each object in that array. The `this.files` property will always be an array. The `src` property will also always be an array, in case your task cares about multiple source files per destination file. 96 | 97 | _Note that it's possible that nonexistent files might be included in `src` values, so you may want to explicitly test that source files exist before using them._ 98 | 99 | This example shows how a simple "concat" task might use the `this.files` property: 100 | 101 | ```js 102 | this.files.forEach(function(file) { 103 | var contents = file.src.filter(function(filepath) { 104 | // Remove nonexistent files (it's up to you to filter or warn here). 105 | if (!grunt.file.exists(filepath)) { 106 | grunt.log.warn('Source file "' + filepath + '" not found.'); 107 | return false; 108 | } else { 109 | return true; 110 | } 111 | }).map(function(filepath) { 112 | // Read and return the file's source. 113 | return grunt.file.read(filepath); 114 | }).join('\n'); 115 | // Write joined contents to destination filepath. 116 | grunt.file.write(file.dest, contents); 117 | // Print a success message. 118 | grunt.log.writeln('File "' + file.dest + '" created.'); 119 | }); 120 | ``` 121 | 122 | _If you need the original file object properties, they are available on each individual file object under the `orig` property, but there is no known use-case for accessing the original properties._ 123 | 124 | ### this.filesSrc 125 | In a multi task, all `src` files specified via any [file format](configuring-tasks#files) are reduced to a single array. If your task is "read only" and doesn't care about destination filepaths, use this array instead of `this.files`. 126 | 127 | This example shows how a simple "lint" task might use the `this.filesSrc` property: 128 | 129 | ```js 130 | // Lint specified files. 131 | var files = this.filesSrc; 132 | var errorCount = 0; 133 | files.forEach(function(filepath) { 134 | if (!lint(grunt.file.read(filepath))) { 135 | errorCount++; 136 | } 137 | }); 138 | 139 | // Fail task if errors were logged. 140 | if (errorCount > 0) { return false; } 141 | 142 | // Otherwise, print a success message. 143 | grunt.log.ok('Files lint free: ' + files.length); 144 | ``` 145 | 146 | ### this.data 147 | In a multi task, this is the actual data stored in the Grunt config object for the given target. 148 | For example, if a "sample" multi task was run as `grunt sample:foo` with the config data `{sample: {foo: "bar"}}`, inside the task function, `this.data` would be `"bar"`. 149 | 150 | _It is recommended that `this.options` `this.files` and `this.filesSrc` are used instead of `this.data`, as their values are normalized._ 151 | -------------------------------------------------------------------------------- /Creating-tasks.md: -------------------------------------------------------------------------------- 1 | Tasks are grunt's bread and butter. The stuff you do most often, like `jshint` or `nodeunit`. Every time Grunt is run, you specify one or more tasks to run, which tells Grunt what you'd like it to do. 2 | 3 | If you don't specify a task, but a task named "default" has been defined, that task will run (unsurprisingly) by default. 4 | 5 | ## Alias Tasks 6 | If a task list is specified, the new task will be an alias for one or more other tasks. Whenever this "alias task" is run, every specified tasks in `taskList` will be run, in the order specified. The `taskList` argument must be an array of tasks. 7 | 8 | ```javascript 9 | grunt.registerTask(taskName, [description, ] taskList) 10 | ``` 11 | 12 | This example alias task defines a "default" task whereby the "jshint", "qunit", "concat" and "uglify" tasks are run automatically if Grunt is executed without specifying any tasks: 13 | 14 | ```javascript 15 | grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']); 16 | ``` 17 | 18 | Task arguments can be specified as well. In this example, the alias "dist" runs both the "concat" and "uglify" tasks, each with a "dist" argument: 19 | 20 | ```javascript 21 | grunt.registerTask('dist', ['concat:dist', 'uglify:dist']); 22 | ``` 23 | 24 | ## Multi Tasks 25 | When a multi task is run, Grunt looks for a property of the same name in the Grunt configuration. Multi-tasks can have multiple configurations, defined using arbitrarily named "targets." 26 | 27 | Specifying both a task and target like `grunt concat:foo` or `grunt concat:bar` will process just the specified target's configuration, while running `grunt concat` will iterate over _all_ targets, processing each in turn. Note that if a task has been renamed with [grunt.task.renameTask](grunt.task#grunt.task.renameTask), Grunt will look for a property with the _new_ task name in the config object. 28 | 29 | Most of the contrib tasks, including the [grunt-contrib-jshint plugin jshint task](https://github.com/gruntjs/grunt-contrib-jshint#jshint-task) and [grunt-contrib-concat plugin concat task](https://github.com/gruntjs/grunt-contrib-concat#concat-task) are multi tasks. 30 | 31 | ```javascript 32 | grunt.registerMultiTask(taskName, [description, ] taskFunction) 33 | ``` 34 | 35 | Given the specified configuration, this example multi task would log `foo: 1,2,3` if Grunt was run via `grunt log:foo`, or it would log `bar: hello world` if Grunt was run via `grunt log:bar`. If Grunt was run as `grunt log` however, it would log `foo: 1,2,3` then `bar: hello world` then `baz: false`. 36 | 37 | ```javascript 38 | grunt.initConfig({ 39 | log: { 40 | foo: [1, 2, 3], 41 | bar: 'hello world', 42 | baz: false 43 | } 44 | }); 45 | 46 | grunt.registerMultiTask('log', 'Log stuff.', function() { 47 | grunt.log.writeln(this.target + ': ' + this.data); 48 | }); 49 | ``` 50 | 51 | 52 | ## "Basic" Tasks 53 | When a basic task is run, Grunt doesn't look at the configuration or environment—it just runs the specified task function, passing any specified colon-separated arguments in as function arguments. 54 | 55 | ```javascript 56 | grunt.registerTask(taskName, [description, ] taskFunction) 57 | ``` 58 | 59 | This example task logs `foo, testing 123` if Grunt is run via `grunt foo:testing:123`. If the task is run without arguments as `grunt foo` the task logs `foo, no args`. 60 | 61 | ```javascript 62 | grunt.registerTask('foo', 'A sample task that logs stuff.', function(arg1, arg2) { 63 | if (arguments.length === 0) { 64 | grunt.log.writeln(this.name + ", no args"); 65 | } else { 66 | grunt.log.writeln(this.name + ", " + arg1 + " " + arg2); 67 | } 68 | }); 69 | ``` 70 | 71 | ## Custom tasks 72 | You can go crazy with tasks. If your tasks don't follow the "multi task" structure, use a custom task. 73 | 74 | ```javascript 75 | grunt.registerTask('default', 'My "default" task description.', function() { 76 | grunt.log.writeln('Currently running the "default" task.'); 77 | }); 78 | ``` 79 | 80 | Inside a task, you can run other tasks. 81 | 82 | ```javascript 83 | grunt.registerTask('foo', 'My "foo" task.', function() { 84 | // Enqueue "bar" and "baz" tasks, to run after "foo" finishes, in-order. 85 | grunt.task.run('bar', 'baz'); 86 | // Or: 87 | grunt.task.run(['bar', 'baz']); 88 | }); 89 | ``` 90 | 91 | Tasks can be asynchronous. 92 | 93 | ```javascript 94 | grunt.registerTask('asyncfoo', 'My "asyncfoo" task.', function() { 95 | // Force task into async mode and grab a handle to the "done" function. 96 | var done = this.async(); 97 | // Run some sync stuff. 98 | grunt.log.writeln('Processing task...'); 99 | // And some async stuff. 100 | setTimeout(function() { 101 | grunt.log.writeln('All done!'); 102 | done(); 103 | }, 1000); 104 | }); 105 | ``` 106 | 107 | Tasks can access their own name and arguments. 108 | 109 | ```javascript 110 | grunt.registerTask('foo', 'My "foo" task.', function(a, b) { 111 | grunt.log.writeln(this.name, a, b); 112 | }); 113 | 114 | // Usage: 115 | // grunt foo foo:bar 116 | // logs: "foo", undefined, undefined 117 | // logs: "foo", "bar", undefined 118 | // grunt foo:bar:baz 119 | // logs: "foo", "bar", "baz" 120 | ``` 121 | 122 | Tasks can fail if any errors were logged. 123 | 124 | ```javascript 125 | grunt.registerTask('foo', 'My "foo" task.', function() { 126 | if (failureOfSomeKind) { 127 | grunt.log.error('This is an error message.'); 128 | } 129 | 130 | // Fail by returning false if this task had errors 131 | if (ifErrors) { return false; } 132 | 133 | grunt.log.writeln('This is the success message'); 134 | }); 135 | ``` 136 | 137 | When tasks fail, all subsequent tasks will be aborted unless `--force` was specified. 138 | 139 | ```javascript 140 | grunt.registerTask('foo', 'My "foo" task.', function() { 141 | // Fail synchronously. 142 | return false; 143 | }); 144 | 145 | grunt.registerTask('bar', 'My "bar" task.', function() { 146 | var done = this.async(); 147 | setTimeout(function() { 148 | // Fail asynchronously. 149 | done(false); 150 | }, 1000); 151 | }); 152 | ``` 153 | 154 | Tasks can be dependent on the successful execution of other tasks. Note that `grunt.task.requires` won't actually RUN the other task(s). It'll just check to see that it has run and not failed. 155 | 156 | ```javascript 157 | grunt.registerTask('foo', 'My "foo" task.', function() { 158 | return false; 159 | }); 160 | 161 | grunt.registerTask('bar', 'My "bar" task.', function() { 162 | // Fail task if "foo" task failed or never ran. 163 | grunt.task.requires('foo'); 164 | // This code executes if the "foo" task ran successfully. 165 | grunt.log.writeln('Hello, world.'); 166 | }); 167 | 168 | // Usage: 169 | // grunt foo bar 170 | // doesn't log, because foo failed. 171 | // grunt bar 172 | // doesn't log, because foo never ran. 173 | ``` 174 | 175 | Tasks can fail if required configuration properties don't exist. 176 | 177 | ```javascript 178 | grunt.registerTask('foo', 'My "foo" task.', function() { 179 | // Fail task if "meta.name" config prop is missing 180 | // Format 1: String 181 | grunt.config.requires('meta.name'); 182 | // or Format 2: Array 183 | grunt.config.requires(['meta', 'name']); 184 | // Log... conditionally. 185 | grunt.log.writeln('This will only log if meta.name is defined in the config.'); 186 | }); 187 | ``` 188 | 189 | Tasks can access configuration properties. 190 | 191 | ```javascript 192 | grunt.registerTask('foo', 'My "foo" task.', function() { 193 | // Log the property value. Returns null if the property is undefined. 194 | grunt.log.writeln('The meta.name property is: ' + grunt.config('meta.name')); 195 | // Also logs the property value. Returns null if the property is undefined. 196 | grunt.log.writeln('The meta.name property is: ' + grunt.config(['meta', 'name'])); 197 | }); 198 | ``` 199 | 200 | Take a look at the [contrib tasks](https://github.com/gruntjs/) for more examples. 201 | 202 | ## CLI options / environment 203 | 204 | Use `process.env` to access the [environment variables](http://en.wikipedia.org/wiki/Environment_variable). 205 | 206 | Read more about the available command-line options on the [Using the CLI](http://gruntjs.com/using-the-cli) page. 207 | 208 | ## Why doesn't my asynchronous task complete? 209 | Chances are this is happening because you have forgotten to call the [this.async](http://gruntjs.com/api/inside-tasks#this.async) method to tell Grunt that your task is asynchronous. For simplicity's sake, Grunt uses a synchronous coding style, which can be switched to asynchronous by calling `this.async()` within the task body. 210 | 211 | Note that passing `false` to the `done()` function tells Grunt that the task has failed. 212 | 213 | For example: 214 | 215 | ```javascript 216 | grunt.registerTask('asyncme', 'My asynchronous task.', function() { 217 | var done = this.async(); 218 | doSomethingAsync(done); 219 | }); 220 | ``` 221 | 222 | ## Extra Reference 223 | 224 | Checkout the [API](http://gruntjs.com/api) documentation if you need extra reference to create your tasks. 225 | -------------------------------------------------------------------------------- /Getting-started.md: -------------------------------------------------------------------------------- 1 | Grunt and Grunt plugins are installed and managed via [npm](https://npmjs.org/), the [Node.js](http://nodejs.org/) package manager. 2 | Grunt 0.4.x requires stable Node.js versions `>= 0.8.0`. Odd version numbers of Node.js are considered unstable development versions. 3 | 4 | Before setting up Grunt ensure that your [npm](https://npmjs.org/) is up-to-date by running `npm update -g npm` (this might require `sudo` on certain systems). 5 | 6 | If you already have installed Grunt and is now searching for some quick reference, please checkout our [`Gruntfile` example](/sample-gruntfile) and how to [configure a task](/configuring-tasks). 7 | 8 | ## Installing the CLI 9 | **Using Grunt 0.3? Please see [Grunt 0.3 Notes](upgrading-from-0.3-to-0.4#grunt-0.3-notes)** 10 | 11 | In order to get started, you'll want to install Grunt's command line interface (CLI) globally. You may need to use sudo (for OSX, *nix, BSD etc) or run your command shell as Administrator (for Windows) to do this. 12 | 13 | ```shell 14 | npm install -g grunt-cli 15 | ``` 16 | 17 | This will put the `grunt` command in your system path, allowing it to be run from any directory. 18 | 19 | Note that installing `grunt-cli` does not install the Grunt task runner! The job of the Grunt CLI is simple: run the version of Grunt which has been installed next to a `Gruntfile`. 20 | This allows multiple versions of Grunt to be installed on the same machine simultaneously. 21 | 22 | ## How the CLI works 23 | 24 | Each time `grunt` is run, it looks for a locally installed Grunt using node's `require()` system. Because of this, you can run `grunt` from any subfolder in your project. 25 | 26 | If a locally installed Grunt is found, the CLI loads the local installation of the Grunt library, applies the configuration from your `Gruntfile`, and executes any tasks you've requested for it to run. To really understand what is happening, [read the code](https://github.com/gruntjs/grunt-cli/blob/master/bin/grunt). 27 | 28 | ## Working with an existing Grunt project 29 | Assuming that the Grunt CLI has been installed and that the project has already been configured with a `package.json` and a `Gruntfile`, it's very easy to start working with Grunt: 30 | 31 | 1. Change to the project's root directory. 32 | 1. Install project dependencies with `npm install`. 33 | 1. Run Grunt with `grunt`. 34 | 35 | That's really all there is to it. Installed Grunt tasks can be listed by running `grunt --help` but it's usually a good idea to start with the project's documentation. 36 | 37 | ## Preparing a new Grunt project 38 | A typical setup will involve adding two files to your project: `package.json` and the `Gruntfile`. 39 | 40 | **package.json**: This file is used by [npm] to store metadata for projects published as npm modules. You will list grunt and the Grunt plugins your project needs as [devDependencies] in this file. 41 | 42 | **Gruntfile**: This file is named `Gruntfile.js` or `Gruntfile.coffee` and is used to configure or define tasks and load Grunt plugins. 43 | **When this documentation mentions a `Gruntfile` it is talking about a file, which is either a `Gruntfile.js` or a `Gruntfile.coffee`**. 44 | 45 | ## package.json 46 | 47 | The `package.json` file belongs in the root directory of your project, next to the `Gruntfile`, and should be committed with your project source. Running `npm install` in the same folder as a `package.json` file will install the correct version of each dependency listed therein. 48 | 49 | There are a few ways to create a `package.json` file for your project: 50 | 51 | * Most [grunt-init] templates will automatically create a project-specific `package.json` file. 52 | * The [npm init] command will create a basic `package.json` file. 53 | * Start with the example below, and expand as needed, following this [specification][json]. 54 | 55 | ```js 56 | { 57 | "name": "my-project-name", 58 | "version": "0.1.0", 59 | "devDependencies": { 60 | "grunt": "~0.4.5", 61 | "grunt-contrib-jshint": "~0.10.0", 62 | "grunt-contrib-nodeunit": "~0.4.1", 63 | "grunt-contrib-uglify": "~0.5.0" 64 | } 65 | } 66 | ``` 67 | 68 | ### Installing Grunt and gruntplugins 69 | The easiest way to add Grunt and gruntplugins to an existing `package.json` is with the command `npm install --save-dev`. Not only will this install `` locally, but it will automatically be added to the [devDependencies] section, using a [tilde version range]. 70 | 71 | For example, this will install the latest version of Grunt in your project folder, adding it to your devDependencies: 72 | 73 | ```shell 74 | npm install grunt --save-dev 75 | ``` 76 | 77 | The same can be done for gruntplugins and other node modules. As seen in the following example installing the JSHint task module: 78 | 79 | ```shell 80 | npm install grunt-contrib-jshint --save-dev 81 | ``` 82 | 83 | Checkout the current available gruntplugins to be installed and used on your project at the [plugins](http://gruntjs.com/plugins) page. 84 | 85 | Be sure to commit the updated `package.json` file with your project when you're done! 86 | 87 | ## The Gruntfile 88 | The `Gruntfile.js` or `Gruntfile.coffee` file is a valid JavaScript or CoffeeScript file that belongs in the root directory of your project, next to the `package.json` file, and should be committed with your project source. 89 | 90 | A `Gruntfile` is comprised of the following parts: 91 | 92 | * The "wrapper" function 93 | * Project and task configuration 94 | * Loading Grunt plugins and tasks 95 | * Custom tasks 96 | 97 | ### An example Gruntfile 98 | In the following `Gruntfile`, project metadata is imported into the Grunt config from the project's `package.json` file and the [grunt-contrib-uglify] plugin's `uglify` task is configured to minify a source file and generate a banner comment dynamically using that metadata. When `grunt` is run on the command line, the `uglify` task will be run by default. 99 | 100 | ```js 101 | module.exports = function(grunt) { 102 | 103 | // Project configuration. 104 | grunt.initConfig({ 105 | pkg: grunt.file.readJSON('package.json'), 106 | uglify: { 107 | options: { 108 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' 109 | }, 110 | build: { 111 | src: 'src/<%= pkg.name %>.js', 112 | dest: 'build/<%= pkg.name %>.min.js' 113 | } 114 | } 115 | }); 116 | 117 | // Load the plugin that provides the "uglify" task. 118 | grunt.loadNpmTasks('grunt-contrib-uglify'); 119 | 120 | // Default task(s). 121 | grunt.registerTask('default', ['uglify']); 122 | 123 | }; 124 | ``` 125 | 126 | Now that you've seen the whole `Gruntfile`, let's look at its component parts. 127 | 128 | ### The "wrapper" function 129 | Every `Gruntfile` (and gruntplugin) uses this basic format, and all of your Grunt code must be specified inside this function: 130 | 131 | ```js 132 | module.exports = function(grunt) { 133 | // Do grunt-related things in here 134 | }; 135 | ``` 136 | 137 | ### Project and task configuration 138 | Most Grunt tasks rely on configuration data defined in an object passed to the [[grunt.initConfig|grunt#grunt.initconfig]] method. 139 | 140 | In this example, `grunt.file.readJSON('package.json')` imports the JSON metadata stored in `package.json` into the grunt config. Because `<% %>` template strings may reference any config properties, configuration data like filepaths and file lists may be specified this way to reduce repetition. 141 | 142 | You may store any arbitrary data inside of the configuration object, and as long as it doesn't conflict with properties your tasks require, it will be otherwise ignored. Also, because this is JavaScript, you're not limited to JSON; you may use any valid JS here. You can even programmatically generate the configuration if necessary. 143 | 144 | Like most tasks, the [grunt-contrib-uglify] plugin's `uglify` task expects its configuration to be specified in a property of the same name. Here, the `banner` option is specified, along with a single uglify target named `build` that minifies a single source file to a single destination file. 145 | 146 | ```js 147 | // Project configuration. 148 | grunt.initConfig({ 149 | pkg: grunt.file.readJSON('package.json'), 150 | uglify: { 151 | options: { 152 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' 153 | }, 154 | build: { 155 | src: 'src/<%= pkg.name %>.js', 156 | dest: 'build/<%= pkg.name %>.min.js' 157 | } 158 | } 159 | }); 160 | ``` 161 | 162 | ### Loading Grunt plugins and tasks 163 | Many commonly used tasks like [concatenation], [minification][grunt-contrib-uglify] and [linting] are available as [grunt plugins](https://github.com/gruntjs). As long as a plugin is specified in `package.json` as a dependency, and has been installed via `npm install`, it may be enabled inside your `Gruntfile` with a simple command: 164 | 165 | ```js 166 | // Load the plugin that provides the "uglify" task. 167 | grunt.loadNpmTasks('grunt-contrib-uglify'); 168 | ``` 169 | 170 | **Note:** the `grunt --help` command will list all available tasks. 171 | 172 | ### Custom tasks 173 | You can configure Grunt to run one or more tasks by default by defining a `default` task. In the following example, running `grunt` at the command line without specifying a task will run the `uglify` task. This is functionally the same as explicitly running `grunt uglify` or even `grunt default`. Any number of tasks (with or without arguments) may be specified in the array. 174 | 175 | ```js 176 | // Default task(s). 177 | grunt.registerTask('default', ['uglify']); 178 | ``` 179 | 180 | If your project requires tasks not provided by a Grunt plugin, you may define custom tasks right inside the `Gruntfile`. For example, this `Gruntfile` defines a completely custom `default` task that doesn't even utilize task configuration: 181 | 182 | ```js 183 | module.exports = function(grunt) { 184 | 185 | // A very basic default task. 186 | grunt.registerTask('default', 'Log some stuff.', function() { 187 | grunt.log.write('Logging some stuff...').ok(); 188 | }); 189 | 190 | }; 191 | ``` 192 | 193 | Custom project-specific tasks don't need to be defined in the `Gruntfile`; they may be defined in external `.js` files and loaded via the [[grunt.loadTasks|grunt#grunt.loadtasks]] method. 194 | 195 | ## Further Reading 196 | 197 | * The [[Installing grunt]] guide has detailed information about installing specific, production or in-development, versions of Grunt and grunt-cli. 198 | * The [[Configuring Tasks]] guide has an in-depth explanation on how to configure tasks, targets, options and files inside the `Gruntfile`, along with an explanation of templates, globbing patterns and importing external data. 199 | * The [[Creating Tasks]] guide lists the differences between the types of Grunt tasks and shows a number of sample tasks and configurations. 200 | * For more information about writing custom tasks or Grunt plugins, check out the [[developer documentation|grunt]]. 201 | 202 | [npm]: https://npmjs.org/ 203 | [devDependencies]: https://npmjs.org/doc/json.html#devDependencies 204 | [json]: https://npmjs.org/doc/json.html 205 | [npm init]: https://npmjs.org/doc/init.html 206 | [grunt-init]: Project-Scaffolding 207 | [tilde version range]: https://npmjs.org/doc/misc/semver.html#Ranges 208 | [grunt-contrib-uglify]: http://github.com/gruntjs/grunt-contrib-uglify 209 | [concatenation]: https://github.com/gruntjs/grunt-contrib-concat 210 | [linting]: https://github.com/gruntjs/grunt-contrib-jshint 211 | [grunt.loadTasks]: https://github.com/gruntjs/grunt/wiki/grunt.task 212 | -------------------------------------------------------------------------------- /Upgrading-from-0.3-to-0.4.md: -------------------------------------------------------------------------------- 1 | _Note that even if you are familiar with grunt, it would be worthwhile to read the new [[Getting started]] guide._ 2 | 3 | Grunt is now split into three parts: `grunt`, `grunt-cli` and `grunt-init`. 4 | 5 | 1. The npm module `grunt` should be installed locally to your project. It contains the code and logic for running tasks, loading plugins, etc. 6 | 2. The npm module `grunt-cli` should be installed globally. It puts the `grunt` command in your PATH so you can execute it anywhere. By itself, it doesn't do anything; its job is to load and run the Grunt that has been installed locally to your project, regardless of the version. For more information about why this has changed, please read [npm 1.0: Global vs Local installation](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation). 7 | 3. The `init` task has been broken into its own npm module, `grunt-init`. It should be installed globally with `npm install -g grunt-init` and run with the `grunt-init` command. In the coming months, [Yeoman](http://yeoman.io/) will completely replace grunt-init. See the [grunt-init project page](https://github.com/gruntjs/grunt-init) for more information. 8 | 9 | 10 | ## Grunt 0.3 Notes 11 | 12 | If you are upgrading from Grunt 0.3, make sure to uninstall global `grunt`: 13 | 14 | ```shell 15 | npm uninstall -g grunt 16 | ``` 17 | 18 | _Note that for 0.3.x, plugin names and task configuration options may be different than those shown in "The Gruntfile" section._ 19 | 20 | _This file was named `grunt.js` for 0.3.x versions of Grunt._ 21 | 22 | ## Pre-existing tasks and plugins 23 | All `grunt-contrib-*` series plugins are Grunt 0.4 ready. However, it is highly unlikely that third party plugins written for Grunt 0.3 will continue to work with 0.4 until they have been updated. We are actively working with plugin authors to ensure this happens as swiftly as possible. 24 | 25 | _A forthcoming Grunt release will be focused on decoupling grunt's architecture so that plugins are not affected by future updates._ 26 | 27 | ## Requirements 28 | * Grunt now requires Node.js version `>= 0.8.0` 29 | 30 | ## The Gruntfile 31 | * The "Gruntfile" has changed from `grunt.js` to `Gruntfile.js`. 32 | * CoffeeScript is supported in your `Gruntfile.coffee` project `Gruntfile` or `*.coffee` task files (transpiling to JS happens automatically). 33 | 34 | See the "The Gruntfile" section of the [[Getting started]] guide for more information. 35 | 36 | ## Core Tasks are now Grunt Plugins 37 | The eight core tasks that were included in Grunt 0.3 are now separate Grunt plugins. Each is a discrete npm module that must be installed as a plugin per the "Loading Grunt plugins and tasks" section of the [[Getting started]] guide. 38 | 39 | * concat → [grunt-contrib-concat](https://github.com/gruntjs/grunt-contrib-concat) plugin 40 | * init → stand-alone [grunt-init] utility 41 | * lint → [grunt-contrib-jshint](https://github.com/gruntjs/grunt-contrib-jshint) plugin 42 | * min → [grunt-contrib-uglify](https://github.com/gruntjs/grunt-contrib-uglify) plugin 43 | * qunit → [grunt-contrib-qunit](https://github.com/gruntjs/grunt-contrib-qunit) plugin 44 | * server → [grunt-contrib-connect](https://github.com/gruntjs/grunt-contrib-connect) plugin 45 | * test → [grunt-contrib-nodeunit](https://github.com/gruntjs/grunt-contrib-nodeunit) plugin 46 | * watch → [grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch) plugin 47 | 48 | Some task names and options have changed. Be sure to see each plugin's documentation as linked above for the latest configuration details. 49 | 50 | ## Configuration 51 | The configuration format for Grunt 0.4 tasks has been standardized and greatly enhanced. See the [[Configuring tasks]] guide, as well as individual plugin documentation for more information. 52 | 53 | * File globbing (wildcard) patterns may now be negated to exclude matched files. 54 | * Tasks now support a standard `options` object. 55 | * Tasks now support a standard `files` object. 56 | 57 | `<% %>` style template strings specified as config data inside the `Gruntfile` are automatically expanded, see the [[grunt.template]] documentation for more information. 58 | 59 | **Directives have been removed**, but their functionality has been retained. These replacements can be made: 60 | 61 | * `''` → `'<%= prop.subprop %>'` 62 | * `''` → `grunt.file.readJSON('file.json')` 63 | * `''` → `grunt.template.process(grunt.file.read('file.js'))` 64 | 65 | Instead of specifying a banner in a file list with `''` or `''`, the [grunt-contrib-concat](https://github.com/gruntjs/grunt-contrib-concat) and [grunt-contrib-uglify](https://github.com/gruntjs/grunt-contrib-uglify) plugins each have a `banner` option. 66 | 67 | Instead of stripping banners from files individually with `''`, the [grunt-contrib-concat](https://github.com/gruntjs/grunt-contrib-concat) and [grunt-contrib-uglify](https://github.com/gruntjs/grunt-contrib-uglify) plugins each have an option to strip/preserve banners. 68 | 69 | ## Alias task changes 70 | When specifying an alias task, the list of tasks to run must now be specified as an array. 71 | 72 | ```js 73 | // v0.3.x (old format) 74 | grunt.registerTask('default', 'jshint nodeunit concat'); 75 | // v0.4.x (new format) 76 | grunt.registerTask('default', ['jshint', 'nodeunit', 'concat']); 77 | ``` 78 | 79 | ## Task arguments may now contain spaces 80 | The aforementioned alias task change (task lists must be specified as an array) makes this possible. Just be sure to surround task arguments containing spaces with quotes when specifying them on the command line, so they can be properly parsed. 81 | 82 | ```shell 83 | grunt my-task:argument-without-spaces "other-task:argument with spaces" 84 | ``` 85 | 86 | ## Character encodings 87 | The [file.defaultEncoding](grunt.file#wiki-grunt-file-defaultEncoding) method was added to normalize character encodings, and all `grunt.file` methods have been updated to support the specified encoding. 88 | 89 | ## Helpers 90 | Grunt's helper system has been removed in favor of node `require`. For a concise example on how to share functionality between Grunt plugins, please see [grunt-lib-legacyhelpers](https://github.com/gruntjs/grunt-lib-legacyhelpers). Plugin authors are encouraged to upgrade their plugins. 91 | 92 | ## API 93 | The Grunt API saw substantial changes from 0.3 to 0.4. 94 | 95 | * [grunt](grunt) 96 | * Removed `grunt.registerHelper` and `grunt.renameHelper` methods. 97 | * [grunt.config](grunt.config) 98 | * Changed [config.get](grunt.config#wiki-grunt-config-get) method to automatically recursively expand `<% %>` templates. 99 | * Added [config.getRaw](grunt.config#wiki-grunt-config-getRaw) method that will retrieve raw (unexpanded) config data. 100 | * Changed [config.process](grunt.config#wiki-grunt-config-process) method to now process a value as if it had been retrieved from the config, expanding templates recursively. This method is called internally inside of `config.get`, but _not_ inside of `config.getRaw`. 101 | * [grunt.event](grunt.event) added so that tasks may emit events. 102 | * [grunt.fail](grunt.fail) 103 | * Won't emit a beep if `--no-color` option specified. 104 | * Added `fail.code` exit code map. 105 | * Removed `fail.warnAlternate` method. 106 | * [grunt.file](grunt.file) 107 | * Tasks are no longer automatically loaded from `~/.grunt/tasks/` directory (install them locally to your project!). 108 | * Added [file.defaultEncoding](grunt.file#wiki-grunt-file-defaultEncoding) method for normalizing character encoding across all `grunt.file` methods. 109 | * Added [file.delete](grunt.file#wiki-grunt-file-delete) method. 110 | * Added relatively self-explanatory [file.exists](grunt.file#wiki-grunt-file-exists), [file.isDir](grunt.file#wiki-grunt-file-isDir), [file.isFile](grunt.file#wiki-grunt-file-isFile), [file.isLink](grunt.file#wiki-grunt-file-isLink), [file.isPathCwd](grunt.file#wiki-grunt-file-isPathCwd), [file.isPathInCwd](grunt.file#wiki-grunt-file-isPathInCwd), [file.doesPathContain](grunt.file#wiki-grunt-file-doesPathContain), [file.arePathsEquivalent](grunt.file#wiki-grunt-file-arePathsEquivalent) testing methods. 111 | * Added [file.match](grunt.file#wiki-grunt-file-match) and [file.isMatch](grunt.file#wiki-grunt-file-isMatch) methods to facilitate matching wildcard patterns against file paths. 112 | * Added [file.expandMapping](grunt.file#wiki-grunt-file-expandMapping) method for use in generating 1-to-1 src-dest file mappings. 113 | * Added [file.readYAML](grunt.file#wiki-grunt-file-readYAML) method. 114 | * Changed [file.findup](grunt.file#wiki-grunt-file-findup) to use the [findup-sync](https://github.com/cowboy/node-findup-sync) module. 115 | * Changed [file.glob](grunt.file#wiki-grunt-file-glob) to use the [glob](https://github.com/isaacs/node-glob) module. 116 | * Added [file.minimatch](grunt.file#wiki-grunt-file-minimatch) which exposes the [minimatch](https://github.com/isaacs/minimatch) module. 117 | * Removed `file.userDir` method (moved into [grunt-init]). 118 | * Removed `file.clearRequireCache` method. 119 | * Removed `file.expandFiles` and `file.expandDirs` methods, use the `filter` option of `file.expand` instead. 120 | * Removed `file.expandFileURLs` method. Don't specify URLs where files should be specified (eg. the qunit task now allows for a `urls` option). 121 | * [grunt.task](grunt#wiki-grunt-task) 122 | * Tasks registered with both [task.registerTask](grunt.task#wiki-grunt-task-registerTask) and [task.registerMultiTask](grunt.task#wiki-grunt-task-registerMultiTask) get a `this.options` method. 123 | * Added [task.normalizeMultiTaskFiles](grunt.task#wiki-grunt-task-normalizeMultiTaskFiles) method to facilitate the normalization of multi task `files` objects into the `this.file` property. 124 | * Removed `task.registerHelper` and `task.renameHelper` methods. 125 | * Removed `task.searchDirs` property. 126 | * Removed `task.expand` `task.expandDirs` `task.expandFiles` `task.getFile` `task.readDefaults` methods (moved into [grunt-init]). 127 | * [grunt.package](grunt#wiki-grunt-package) reflects the metadata stored in grunt's `package.json`. 128 | * [grunt.version](grunt#wiki-grunt-version) is the current version of Grunt as a string. 129 | * [grunt.template](grunt.template) 130 | * Added [template.addDelimiters](grunt.template#wiki-grunt-template-addDelimiters) method to add new template delimiters. 131 | * Added [template.setDelimiters](grunt.template#wiki-grunt-template-setDelimiters) method to select template delimiters. 132 | * The `init` and `user` template delimiters have been removed, but you can add them in again if you need to with `template.addDelimiters` ([grunt-init] uses this to enable the `{% %}` template delimiters). 133 | * [grunt.util](grunt.util) replaces the now-removed `grunt.utils`. 134 | * Changed `util._` to use [Lo-Dash](http://lodash.com/) 135 | * Added the [util.callbackify](grunt.util#wiki-grunt-util-callbackify) method. 136 | * Changed the [util.spawn](grunt.util#wiki-grunt-util-spawn) method to be much better behaved and pass more consistent arguments into its callback. 137 | 138 | ## Task / plugin authors 139 | **Plugin authors, please indicate clearly on your repository README which version number of your Grunt plugin breaks compatibility with Grunt 0.3.** 140 | 141 | ### Tasks 142 | * Multi tasks 143 | * Multiple src-dest file mappings may now be specified per target in a `files` object (this is optional). 144 | * [this.files / grunt.task.current.files](grunt.task#wiki-this-files) 145 | * The `this.files` property is an array of src-dest file mapping objects to be iterated over in your multi task. It will always be an array, and you should always iterate over it, even if the most common use case is to specify a single file. 146 | * Each src-dest file mapping object has a `src` and `dest` property (and possibly others, depending on what the user specified). The `src` property is already expanded from whatever glob pattern the user may have specified. 147 | * [this.filesSrc / grunt.task.current.filesSrc](grunt.task#wiki-this-filesSrc) 148 | * The `this.filesSrc` property is a reduced, uniqued array of all files matched by all specified `src` properties. Useful for read-only tasks. 149 | * [this.options / grunt.task.current.options](grunt.task#wiki-this-options) 150 | * The `this.options` method may be used within tasks to normalize options. Inside a task, you may specify options defaults like: `var options = this.options({option: 'defaultvalue', ...});` 151 | 152 | ### Plugins 153 | * An updated `gruntplugin` template has been created for Grunt 0.4-compatible plugins, and is available in the standalone [grunt-init]. 154 | 155 | ## Troubleshooting 156 | * If you had previously installed a development version of Grunt 0.4 or any grunt-contrib plugins, be sure to flush your npm cache with `npm cache clean` first to ensure that you are pulling the final version of Grunt and grunt-contrib plugins. 157 | 158 | [grunt-init]: https://github.com/gruntjs/grunt-init -------------------------------------------------------------------------------- /grunt.file.md: -------------------------------------------------------------------------------- 1 | There are many provided methods for reading and writing files, traversing the filesystem and finding files by matching globbing patterns. Many of these methods are wrappers around built-in Node.js file functionality, but with additional error handling, logging and character encoding normalization. 2 | 3 | _Note: all file paths are relative to the `Gruntfile` unless the current working directory is changed with `grunt.file.setBase` or the `--base` command-line option._ 4 | 5 | ## Character encoding 6 | 7 | ### grunt.file.defaultEncoding 8 | Set this property to change the default encoding used by all `grunt.file` methods. Defaults to `'utf8'`. If you do have to change this value, it's recommended that you change it as early as possible inside your Gruntfile. 9 | 10 | ```js 11 | grunt.file.defaultEncoding = 'utf8'; 12 | ``` 13 | 14 | 15 | ### grunt.file.preserveBOM 16 | *Added in 0.4.2* 17 | 18 | Whether to preserve the Byte Order Mark (BOM) on `file.read` rather than strip it. 19 | ```js 20 | grunt.file.preserveBOM = false; 21 | ``` 22 | 23 | ## Reading and writing 24 | 25 | ### grunt.file.read 26 | Read and return a file's contents. Returns a string, unless `options.encoding` is `null` in which case it returns a [Buffer](http://nodejs.org/docs/latest/api/buffer.html). 27 | 28 | ```js 29 | grunt.file.read(filepath [, options]) 30 | ``` 31 | 32 | The `options` object has these possible properties: 33 | 34 | ```js 35 | var options = { 36 | // If an encoding is not specified, default to grunt.file.defaultEncoding. 37 | // If specified as null, returns a non-decoded Buffer instead of a string. 38 | encoding: encodingName 39 | }; 40 | ``` 41 | 42 | ### grunt.file.readJSON 43 | Read a file's contents, parsing the data as JSON and returning the result. See `grunt.file.read` for a list of supported options. 44 | 45 | ```js 46 | grunt.file.readJSON(filepath [, options]) 47 | ``` 48 | 49 | ### grunt.file.readYAML 50 | Read a file's contents, parsing the data as YAML and returning the result. See `grunt.file.read` for a list of supported options. 51 | 52 | ```js 53 | grunt.file.readYAML(filepath [, options]) 54 | ``` 55 | 56 | ### grunt.file.write 57 | Write the specified contents to a file, creating intermediate directories if necessary. Strings will be encoded using the specified character encoding, [Buffers](http://nodejs.org/docs/latest/api/buffer.html) will be written to disk as-specified. 58 | 59 | _If the `--no-write` command-line option is specified, the file won't actually be written._ 60 | 61 | ```js 62 | grunt.file.write(filepath, contents [, options]) 63 | ``` 64 | 65 | The `options` object has these possible properties: 66 | 67 | ```js 68 | var options = { 69 | // If an encoding is not specified, default to grunt.file.defaultEncoding. 70 | // If `contents` is a Buffer, encoding is ignored. 71 | encoding: encodingName 72 | }; 73 | ``` 74 | 75 | ### grunt.file.copy 76 | Copy a source file to a destination path, creating intermediate directories if necessary. 77 | 78 | _If the `--no-write` command-line option is specified, the file won't actually be written._ 79 | 80 | ```js 81 | grunt.file.copy(srcpath, destpath [, options]) 82 | ``` 83 | 84 | The `options` object has these possible properties: 85 | 86 | ```js 87 | var options = { 88 | // If an encoding is not specified, default to grunt.file.defaultEncoding. 89 | // If null, the `process` function will receive a Buffer instead of String. 90 | encoding: encodingName, 91 | // The source file contents, source file path, and destination file path 92 | // are passed into this function, whose return value will be used as the 93 | // destination file's contents. If this function returns `false`, the file 94 | // copy will be aborted. 95 | process: processFunction, 96 | // These optional globbing patterns will be matched against the filepath 97 | // (not the filename) using grunt.file.isMatch. If any specified globbing 98 | // pattern matches, the file won't be processed via the `process` function. 99 | // If `true` is specified, processing will be prevented. 100 | noProcess: globbingPatterns 101 | }; 102 | ``` 103 | 104 | ### grunt.file.delete 105 | Delete the specified filepath. Will delete files and folders recursively. 106 | 107 | _Will not delete the current working directory or files outside the current working directory unless the `--force` command-line option is specified._ 108 | 109 | _If the `--no-write` command-line option is specified, the filepath won't actually be deleted._ 110 | 111 | ```js 112 | grunt.file.delete(filepath [, options]) 113 | ``` 114 | 115 | The `options` object has one possible property: 116 | 117 | ```js 118 | var options = { 119 | // Enable deleting outside the current working directory. This option may 120 | // be overridden by the --force command-line option. 121 | force: true 122 | }; 123 | ``` 124 | 125 | ## Directories 126 | 127 | ### grunt.file.mkdir 128 | Works like `mkdir -p`. Create a directory along with any intermediate directories. If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. 129 | 130 | _If the `--no-write` command-line option is specified, directories won't actually be created._ 131 | 132 | ```js 133 | grunt.file.mkdir(dirpath [, mode]) 134 | ``` 135 | 136 | ### grunt.file.recurse 137 | Recurse into a directory, executing `callback` for each file. 138 | 139 | ```js 140 | grunt.file.recurse(rootdir, callback) 141 | ``` 142 | 143 | The callback function receives the following arguments: 144 | 145 | ```js 146 | function callback(abspath, rootdir, subdir, filename) { 147 | // The full path to the current file, which is nothing more than 148 | // the rootdir + subdir + filename arguments, joined. 149 | abspath 150 | // The root director, as originally specified. 151 | rootdir 152 | // The current file's directory, relative to rootdir. 153 | subdir 154 | // The filename of the current file, without any directory parts. 155 | filename 156 | } 157 | ``` 158 | 159 | ## Globbing patterns 160 | It is often impractical to specify all source filepaths individually, so Grunt supports filename expansion (also know as globbing) via the built-in [node-glob](https://github.com/isaacs/node-glob) library. 161 | 162 | See the "Globbing patterns" section of the [[Configuring tasks]] guide for globbing pattern examples. 163 | 164 | 165 | ### grunt.file.expand 166 | Return a unique array of all file or directory paths that match the given globbing pattern(s). This method accepts either comma separated globbing patterns or an array of globbing patterns. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant. 167 | 168 | ```js 169 | grunt.file.expand([options, ] patterns) 170 | ``` 171 | 172 | File paths are relative to the `Gruntfile` unless the current working directory is changed with `grunt.file.setBase` or the `--base` command-line option. 173 | 174 | The `options` object supports all [minimatch library](https://github.com/isaacs/minimatch) options, and a few others. For example: 175 | 176 | * `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that is passed the matched `src` filepath and returns `true` or `false`. 177 | * `nonull` Retain `src` patterns even if they fail to match files. Combined with grunt's `--verbose` flag, this option can help debug file path issues. 178 | * `matchBase` Patterns without slashes will match just the basename part. Eg. this makes `*.js` work like `**/*.js`. 179 | * `cwd` Patterns will be matched relative to this path, and all returned filepaths will also be relative to this path. 180 | 181 | ### grunt.file.expandMapping 182 | Returns an array of src-dest file mapping objects. For each source file matched by a specified pattern, join that file path to the specified `dest`. This file path may be flattened or renamed, depending on the options specified. See the `grunt.file.expand` method documentation for an explanation of how the `patterns` and `options` arguments may be specified. 183 | 184 | ```js 185 | grunt.file.expandMapping(patterns, dest [, options]) 186 | ``` 187 | 188 | _Note that while this method may be used to programmatically generate a `files` array for a multi task, the declarative syntax for doing this described in the "Building the files object dynamically" section of the [[Configuring tasks]] guide is preferred._ 189 | 190 | In addition to those the `grunt.file.expand` method supports, the `options` object also supports these properties: 191 | 192 | ```js 193 | var options = { 194 | // The directory from which patterns are matched. Any string specified as 195 | // cwd is effectively stripped from the beginning of all matched paths. 196 | cwd: String, 197 | // Remove the path component from all matched src files. The src file path 198 | // is still joined to the specified dest. 199 | flatten: Boolean, 200 | // Remove anything after (and including) either the first or last "." in the 201 | // destination path (indicated by options.extDot), then append this value. 202 | ext: String, 203 | // *Added in 0.4.3* 204 | // Indicates where the period demarcating the extension is located. Can take: 205 | // - 'first' (extension begins after the first period in the file name) 206 | // - 'last' (extension begins after the last period) 207 | // Default: 'first' 208 | extDot: String, 209 | // If specified, this function will be responsible for returning the final 210 | // dest filepath. By default, it joins dest and matchedSrcPath like so: 211 | rename: function(dest, matchedSrcPath, options) { 212 | return path.join(dest, matchedSrcPath); 213 | } 214 | }; 215 | ``` 216 | 217 | ### grunt.file.match 218 | Match one or more globbing patterns against one or more file paths. Returns a uniqued array of all file paths that match any of the specified globbing patterns. Both the `patterns` and `filepaths` argument can be a single string or array of strings. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant. 219 | 220 | ```js 221 | grunt.file.match([options, ] patterns, filepaths) 222 | ``` 223 | 224 | The `options` object supports all [minimatch library](https://github.com/isaacs/minimatch) options. For example, if `options.matchBase` is true, patterns without slashes will match against the basename of the path even if it contains slashes, eg. pattern `*.js` will match filepath `path/to/file.js`. 225 | 226 | ### grunt.file.isMatch 227 | This method contains the same signature and logic as the `grunt.file.match` method, but simply returns `true` if any files were matched, otherwise `false`. 228 | 229 | ## File types 230 | 231 | ### grunt.file.exists 232 | Does the given path exist? Returns a boolean. 233 | 234 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 235 | 236 | ```js 237 | grunt.file.exists(path1 [, path2 [, ...]]) 238 | ``` 239 | 240 | ### grunt.file.isLink 241 | Is the given path a symbolic link? Returns a boolean. 242 | 243 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 244 | 245 | ```js 246 | grunt.file.isLink(path1 [, path2 [, ...]]) 247 | ``` 248 | 249 | Returns false if the path doesn't exist. 250 | 251 | ### grunt.file.isDir 252 | Is the given path a directory? Returns a boolean. 253 | 254 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 255 | 256 | ```js 257 | grunt.file.isDir(path1 [, path2 [, ...]]) 258 | ``` 259 | 260 | Returns false if the path doesn't exist. 261 | 262 | ### grunt.file.isFile 263 | Is the given path a file? Returns a boolean. 264 | 265 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 266 | 267 | ```js 268 | grunt.file.isFile(path1 [, path2 [, ...]]) 269 | ``` 270 | 271 | Returns false if the path doesn't exist. 272 | 273 | ## Paths 274 | 275 | ### grunt.file.isPathAbsolute 276 | Is a given file path absolute? Returns a boolean. 277 | 278 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 279 | 280 | ```js 281 | grunt.file.isPathAbsolute(path1 [, path2 [, ...]]) 282 | ``` 283 | 284 | ### grunt.file.arePathsEquivalent 285 | Do all the specified paths refer to the same path? Returns a boolean. 286 | 287 | ```js 288 | grunt.file.arePathsEquivalent(path1 [, path2 [, ...]]) 289 | ``` 290 | 291 | ### grunt.file.doesPathContain 292 | Are all descendant path(s) contained within the specified ancestor path? Returns a boolean. 293 | 294 | _Note: does not check to see if paths actually exist._ 295 | 296 | ```js 297 | grunt.file.doesPathContain(ancestorPath, descendantPath1 [, descendantPath2 [, ...]]) 298 | ``` 299 | 300 | ### grunt.file.isPathCwd 301 | Is a given file path the CWD? Returns a boolean. 302 | 303 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 304 | 305 | ```js 306 | grunt.file.isPathCwd(path1 [, path2 [, ...]]) 307 | ``` 308 | 309 | ### grunt.file.isPathInCwd 310 | Is a given file path inside the CWD? Note: CWD is not _inside_ CWD. Returns a boolean. 311 | 312 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 313 | 314 | ```js 315 | grunt.file.isPathInCwd(path1 [, path2 [, ...]]) 316 | ``` 317 | 318 | ### grunt.file.setBase 319 | Change grunt's current working directory (CWD). By default, all file paths are relative to the `Gruntfile`. This works just like the `--base` command-line option. 320 | 321 | ```js 322 | grunt.file.setBase(path1 [, path2 [, ...]]) 323 | ``` 324 | 325 | Like the Node.js [path.join](http://nodejs.org/docs/latest/api/path.html#path_path_join_path1_path2) method, this method will join all arguments together and normalize the resulting path. 326 | 327 | ## External libraries 328 | *Deprecated* 329 | 330 | __All external libraries that are listed below are now deprecated.__ 331 | 332 | Please use __npm__ to manage these external libraries in your project's dependencies. 333 | 334 | For example if you want use [Lo-Dash](https://npmjs.org/package/lodash), install it first `npm install lodash`, then 335 | use it in your `Gruntfile`: `var _ = require('lodash');` 336 | 337 | ### grunt.file.glob 338 | *Deprecated* 339 | 340 | [glob](https://github.com/isaacs/node-glob) - File globbing utility. 341 | 342 | ### grunt.file.minimatch 343 | *Deprecated* 344 | 345 | [minimatch](https://github.com/isaacs/minimatch) - File pattern matching utility. 346 | 347 | ### grunt.file.findup 348 | *Deprecated* 349 | 350 | [findup-sync](https://github.com/cowboy/node-findup-sync) - Search upwards for matching file patterns. 351 | -------------------------------------------------------------------------------- /Configuring-tasks.md: -------------------------------------------------------------------------------- 1 | This guide explains how to configure tasks for your project using a `Gruntfile`. If you don't know what a `Gruntfile` is, please read the [[Getting Started]] guide and check out a [[Sample Gruntfile]]. 2 | 3 | ## Grunt Configuration 4 | Task configuration is specified in your `Gruntfile` via the `grunt.initConfig` method. This configuration will mostly be under task-named properties, but may contain any arbitrary data. As long as properties don't conflict with properties your tasks require, they will be otherwise ignored. 5 | 6 | Also, because this is JavaScript, you're not limited to JSON; you may use any valid JavaScript here. You may even programmatically generate the configuration if necessary. 7 | 8 | ```js 9 | grunt.initConfig({ 10 | concat: { 11 | // concat task configuration goes here. 12 | }, 13 | uglify: { 14 | // uglify task configuration goes here. 15 | }, 16 | // Arbitrary non-task-specific properties. 17 | my_property: 'whatever', 18 | my_src_files: ['foo/*.js', 'bar/*.js'], 19 | }); 20 | ``` 21 | 22 | ## Task Configuration and Targets 23 | 24 | When a task is run, Grunt looks for its configuration under a property of the same name. Multi-tasks can have multiple configurations, defined using arbitrarily named "targets." In the example below, the `concat` task has `foo` and `bar` targets, while the `uglify` task only has a `bar` target. 25 | 26 | ```js 27 | grunt.initConfig({ 28 | concat: { 29 | foo: { 30 | // concat task "foo" target options and files go here. 31 | }, 32 | bar: { 33 | // concat task "bar" target options and files go here. 34 | }, 35 | }, 36 | uglify: { 37 | bar: { 38 | // uglify task "bar" target options and files go here. 39 | }, 40 | }, 41 | }); 42 | ``` 43 | Specifying both a task and target like `grunt concat:foo` or `grunt concat:bar` will process just the specified target's configuration, while running `grunt concat` will iterate over _all_ targets, processing each in turn. Note that if a task has been renamed with [grunt.task.renameTask](grunt.task#grunt.task.renameTask), Grunt will look for a property with the _new_ task name in the config object. 44 | 45 | ## Options 46 | Inside a task configuration, an `options` property may be specified to override built-in defaults. In addition, each target may have an `options` property which is specific to that target. Target-level options will override task-level options. 47 | 48 | The `options` object is optional and may be omitted if not needed. 49 | 50 | ```js 51 | grunt.initConfig({ 52 | concat: { 53 | options: { 54 | // Task-level options may go here, overriding task defaults. 55 | }, 56 | foo: { 57 | options: { 58 | // "foo" target options may go here, overriding task-level options. 59 | }, 60 | }, 61 | bar: { 62 | // No options specified; this target will use task-level options. 63 | }, 64 | }, 65 | }); 66 | ``` 67 | 68 | ## Files 69 | Because most tasks perform file operations, Grunt has powerful abstractions for declaring on which files the task should operate. There are several ways to define **src-dest** (source-destination) file mappings, offering varying degrees of verbosity and control. Any multi task will understand all the following formats, so choose whichever format best meets your needs. 70 | 71 | All files formats support `src` and `dest` but the "Compact" and "Files Array" formats support a few additional properties: 72 | 73 | * `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that is passed the matched `src` filepath and returns `true` or `false`. 74 | * `nonull` If set to `true` then the operation will include non-matching patterns. Combined with grunt's `--verbose` flag, this option can help debug file path issues. 75 | * `dot` Allow patterns to match filenames starting with a period, even if the pattern does not explicitly have a period in that spot. 76 | * `matchBase` If set, patterns without slashes will be matched against the basename of the path if it contains slashes. For example, a?b would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. 77 | * `expand` Process a dynamic src-dest file mapping, see ["Building the files object dynamically"](configuring-tasks#building-the-files-object-dynamically) for more information. 78 | * Other properties will be passed into the underlying libs as matching options. See the [node-glob][] and [minimatch][] documentation for more options. 79 | 80 | ### Compact Format 81 | This form allows a single **src-dest** (source-destination) file mapping per-target. It is most commonly used for read-only tasks, like [grunt-contrib-jshint](https://github.com/gruntjs/grunt-contrib-jshint), where a single `src` property is needed, and no `dest` key is relevant. This format also supports additional properties per src-dest file mapping. 82 | 83 | ```js 84 | grunt.initConfig({ 85 | jshint: { 86 | foo: { 87 | src: ['src/aa.js', 'src/aaa.js'] 88 | }, 89 | }, 90 | concat: { 91 | bar: { 92 | src: ['src/bb.js', 'src/bbb.js'], 93 | dest: 'dest/b.js', 94 | }, 95 | }, 96 | }); 97 | ``` 98 | 99 | ### Files Object Format 100 | This form supports multiple src-dest mappings per-target, where the property name is the destination file, and its value is the source file(s). Any number of src-dest file mappings may be specified in this way, but additional properties may not be specified per mapping. 101 | 102 | ```js 103 | grunt.initConfig({ 104 | concat: { 105 | foo: { 106 | files: { 107 | 'dest/a.js': ['src/aa.js', 'src/aaa.js'], 108 | 'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'], 109 | }, 110 | }, 111 | bar: { 112 | files: { 113 | 'dest/b.js': ['src/bb.js', 'src/bbb.js'], 114 | 'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'], 115 | }, 116 | }, 117 | }, 118 | }); 119 | ``` 120 | 121 | ### Files Array Format 122 | This form supports multiple src-dest file mappings per-target, while also allowing additional properties per mapping. 123 | 124 | ```js 125 | grunt.initConfig({ 126 | concat: { 127 | foo: { 128 | files: [ 129 | {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'}, 130 | {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'}, 131 | ], 132 | }, 133 | bar: { 134 | files: [ 135 | {src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b/', nonull: true}, 136 | {src: ['src/bb1.js', 'src/bbb1.js'], dest: 'dest/b1/', filter: 'isFile'}, 137 | ], 138 | }, 139 | }, 140 | }); 141 | ``` 142 | 143 | ### Older Formats 144 | The **dest-as-target** file format is a holdover from before multi tasks and targets existed, where the destination filepath is actually the target name. Unfortunately, because target names are filepaths, running `grunt task:target` can be awkward. Also, you can't specify target-level options or additional properties per src-dest file mapping. 145 | 146 | Consider this format deprecated, and avoid it where possible. 147 | 148 | ```js 149 | grunt.initConfig({ 150 | concat: { 151 | 'dest/a.js': ['src/aa.js', 'src/aaa.js'], 152 | 'dest/b.js': ['src/bb.js', 'src/bbb.js'], 153 | }, 154 | }); 155 | ``` 156 | 157 | ### Custom Filter Function 158 | The `filter` property can help you target files with a greater level of detail. Simply use a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats). The following will clean only if the pattern matches an actual file: 159 | 160 | ```js 161 | grunt.initConfig({ 162 | clean: { 163 | foo: { 164 | src: ['tmp/**/*'], 165 | filter: 'isFile', 166 | }, 167 | }, 168 | }); 169 | ``` 170 | 171 | Or create your own `filter` function and return `true` or `false` whether the file should be matched. For example the following will only clean folders that are empty: 172 | 173 | ```js 174 | grunt.initConfig({ 175 | clean: { 176 | foo: { 177 | src: ['tmp/**/*'], 178 | filter: function(filepath) { 179 | return (grunt.file.isDir(filepath) && require('fs').readdirSync(filepath).length === 0); 180 | }, 181 | }, 182 | }, 183 | }); 184 | ``` 185 | 186 | ### Globbing patterns 187 | It is often impractical to specify all source filepaths individually, so Grunt supports filename expansion (also know as globbing) via the built-in [node-glob][] and [minimatch][] libraries. 188 | 189 | [node-glob]: https://github.com/isaacs/node-glob 190 | [minimatch]: https://github.com/isaacs/minimatch 191 | 192 | While this isn't a comprehensive tutorial on globbing patterns, know that in a filepath: 193 | 194 | * `*` matches any number of characters, but not `/` 195 | * `?` matches a single character, but not `/` 196 | * `**` matches any number of characters, including `/`, as long as it's the only thing in a path part 197 | * `{}` allows for a comma-separated list of "or" expressions 198 | * `!` at the beginning of a pattern will negate the match 199 | 200 | All most people need to know is that `foo/*.js` will match all files ending with `.js` in the `foo/` subdirectory, but `foo/**/*.js` will match all files ending with `.js` in the `foo/` subdirectory _and all of its subdirectories_. 201 | 202 | Also, in order to simplify otherwise complicated globbing patterns, Grunt allows arrays of file paths or globbing patterns to be specified. Patterns are processed in-order, with `!`-prefixed matches excluding matched files from the result set. The result set is uniqued. 203 | 204 | For example: 205 | 206 | ```js 207 | // You can specify single files: 208 | {src: 'foo/this.js', dest: ...} 209 | // Or arrays of files: 210 | {src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...} 211 | // Or you can generalize with a glob pattern: 212 | {src: 'foo/th*.js', dest: ...} 213 | 214 | // This single node-glob pattern: 215 | {src: 'foo/{a,b}*.js', dest: ...} 216 | // Could also be written like this: 217 | {src: ['foo/a*.js', 'foo/b*.js'], dest: ...} 218 | 219 | // All .js files, in foo/, in alpha order: 220 | {src: ['foo/*.js'], dest: ...} 221 | // Here, bar.js is first, followed by the remaining files, in alpha order: 222 | {src: ['foo/bar.js', 'foo/*.js'], dest: ...} 223 | 224 | // All files except for bar.js, in alpha order: 225 | {src: ['foo/*.js', '!foo/bar.js'], dest: ...} 226 | // All files in alpha order, but with bar.js at the end. 227 | {src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...} 228 | 229 | // Templates may be used in filepaths or glob patterns: 230 | {src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'} 231 | // But they may also reference file lists defined elsewhere in the config: 232 | {src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...} 233 | ``` 234 | 235 | For more on glob pattern syntax, see the [node-glob][] and [minimatch][] documentation. 236 | 237 | ### Building the files object dynamically 238 | When you want to process many individual files, a few additional properties may be used to build a files list dynamically. These properties may be specified in both "Compact" and "Files Array" mapping formats. 239 | 240 | `expand` Set to `true` to enable the following options: 241 | 242 | * `cwd` All `src` matches are relative to (but don't include) this path. 243 | * `src` Pattern(s) to match, relative to the `cwd`. 244 | * `dest` Destination path prefix. 245 | * `ext` Replace any existing extension with this value in generated `dest` paths. 246 | * `extDot` Used to indicate where the period indicating the extension is located. Can take either `'first'` (extension begins after the first period in the file name) or `'last'` (extension begins after the last period), and is set by default to `'first'` *[Added in 0.4.3]* 247 | * `flatten` Remove all path parts from generated `dest` paths. 248 | * `rename` This function is called for each matched `src` file, (after extension renaming and flattening). The `dest` 249 | and matched `src` path are passed in, and this function must return a new `dest` value. If the same `dest` is returned 250 | more than once, each `src` which used it will be added to an array of sources for it. 251 | 252 | In the following example, the `uglify` task will see the same list of src-dest file mappings for both the `static_mappings` and `dynamic_mappings` targets, because Grunt will automatically expand the `dynamic_mappings` files object into 4 individual static src-dest file mappings—assuming 4 files are found—when the task runs. 253 | 254 | Any combination of static src-dest and dynamic src-dest file mappings may be specified. 255 | 256 | ```js 257 | grunt.initConfig({ 258 | uglify: { 259 | static_mappings: { 260 | // Because these src-dest file mappings are manually specified, every 261 | // time a new file is added or removed, the Gruntfile has to be updated. 262 | files: [ 263 | {src: 'lib/a.js', dest: 'build/a.min.js'}, 264 | {src: 'lib/b.js', dest: 'build/b.min.js'}, 265 | {src: 'lib/subdir/c.js', dest: 'build/subdir/c.min.js'}, 266 | {src: 'lib/subdir/d.js', dest: 'build/subdir/d.min.js'}, 267 | ], 268 | }, 269 | dynamic_mappings: { 270 | // Grunt will search for "**/*.js" under "lib/" when the "uglify" task 271 | // runs and build the appropriate src-dest file mappings then, so you 272 | // don't need to update the Gruntfile when files are added or removed. 273 | files: [ 274 | { 275 | expand: true, // Enable dynamic expansion. 276 | cwd: 'lib/', // Src matches are relative to this path. 277 | src: ['**/*.js'], // Actual pattern(s) to match. 278 | dest: 'build/', // Destination path prefix. 279 | ext: '.min.js', // Dest filepaths will have this extension. 280 | extDot: 'first' // Extensions in filenames begin after the first dot 281 | }, 282 | ], 283 | }, 284 | }, 285 | }); 286 | ``` 287 | 288 | ## Templates 289 | Templates specified using `<% %>` delimiters will be automatically expanded when tasks read them from the config. Templates are expanded recursively until no more remain. 290 | 291 | The entire config object is the context in which properties are resolved. Additionally, `grunt` and its methods are available inside templates, eg. `<%= grunt.template.today('yyyy-mm-dd') %>`. 292 | 293 | * `<%= prop.subprop %>` Expand to the value of `prop.subprop` in the config, regardless of type. Templates like this can be used to reference not only string values, but also arrays or other objects. 294 | * `<% %>` Execute arbitrary inline JavaScript code. This is useful with control flow or looping. 295 | 296 | Given the sample `concat` task configuration below, running `grunt concat:sample` will generate a file named `build/abcde.js` by concatenating the banner `/* abcde */` with all files matching `foo/*.js` + `bar/*.js` + `baz/*.js`. 297 | 298 | ```js 299 | grunt.initConfig({ 300 | concat: { 301 | sample: { 302 | options: { 303 | banner: '/* <%= baz %> */\n', // '/* abcde */\n' 304 | }, 305 | src: ['<%= qux %>', 'baz/*.js'], // [['foo/*.js', 'bar/*.js'], 'baz/*.js'] 306 | dest: 'build/<%= baz %>.js', // 'build/abcde.js' 307 | }, 308 | }, 309 | // Arbitrary properties used in task configuration templates. 310 | foo: 'c', 311 | bar: 'b<%= foo %>d', // 'bcd' 312 | baz: 'a<%= bar %>e', // 'abcde' 313 | qux: ['foo/*.js', 'bar/*.js'], 314 | }); 315 | ``` 316 | 317 | ## Importing External Data 318 | In the following Gruntfile, project metadata is imported into the Grunt config from a `package.json` file, and the [grunt-contrib-uglify plugin](http://github.com/gruntjs/grunt-contrib-uglify) `uglify` task is configured to minify a source file and generate a banner comment dynamically using that metadata. 319 | 320 | Grunt has `grunt.file.readJSON` and `grunt.file.readYAML` methods for importing JSON and YAML data. 321 | 322 | ```js 323 | grunt.initConfig({ 324 | pkg: grunt.file.readJSON('package.json'), 325 | uglify: { 326 | options: { 327 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' 328 | }, 329 | dist: { 330 | src: 'src/<%= pkg.name %>.js', 331 | dest: 'dist/<%= pkg.name %>.min.js' 332 | } 333 | } 334 | }); 335 | ``` 336 | -------------------------------------------------------------------------------- /Project-Scaffolding.md: -------------------------------------------------------------------------------- 1 | ## grunt-init 2 | Grunt-init is a scaffolding tool used to automate project creation. It will build an entire directory structure based on current environment and answers to some questions. The exact files and contents created depend on the template chosen along with the answers to the questions asked. 3 | 4 | _Note: This standalone utility used to be built-in to Grunt as the "init" task. See the Grunt [Upgrading from 0.3 to 0.4](http://gruntjs.com/upgrading-from-0.3-to-0.4) guide for more information about this change._ 5 | 6 | ## Installation 7 | In order to use grunt-init, you'll want to install it globally. 8 | 9 | ```shell 10 | npm install -g grunt-init 11 | ``` 12 | 13 | This will put the `grunt-init` command in your system path, allowing it to be run from anywhere. 14 | 15 | _Notes: You may need to use sudo or run your command shell as Administrator to do this._ 16 | 17 | ## Usage 18 | * Get program help and a listing of available templates with `grunt-init --help` 19 | * Create a project based around an available template with `grunt-init TEMPLATE` 20 | * Create a project based around a arbitrarily-located template with `grunt-init /path/to/TEMPLATE` 21 | 22 | Note that most templates generate their files in the current directory, so be sure to change to a new directory first if you don't want to overwrite existing files. 23 | 24 | ## Installing templates 25 | Once templates are installed into your `~/.grunt-init/` directory (`%USERPROFILE%\.grunt-init\` on Windows) they will be available for use via grunt-init. It's recommended that you use git to clone a template into that directory. For example, the [grunt-init-jquery](https://github.com/gruntjs/grunt-init-jquery) template can be installed like so: 26 | 27 | ``` 28 | git clone https://github.com/gruntjs/grunt-init-jquery.git ~/.grunt-init/jquery 29 | ``` 30 | 31 | _Note: if you want to make the template available locally as "foobarbaz" you could specify `~/.grunt-init/foobarbaz` while cloning. Grunt-init will use the actual template directory name as it exists inside of the `~/.grunt-init/` directory._ 32 | 33 | A few grunt-init templates are maintained officially: 34 | 35 | * [grunt-init-commonjs](https://github.com/gruntjs/grunt-init-commonjs) - Create a commonjs module, including Nodeunit unit tests. ([sample "generated" repo](https://github.com/gruntjs/grunt-init-commonjs-sample/tree/generated) | [creation transcript](https://github.com/gruntjs/grunt-init-commonjs-sample#project-creation-transcript)) 36 | * [grunt-init-gruntfile](https://github.com/gruntjs/grunt-init-gruntfile) - Create a basic Gruntfile. ([sample "generated" repo](https://github.com/gruntjs/grunt-init-gruntfile-sample/tree/generated) | [creation transcript](https://github.com/gruntjs/grunt-init-gruntfile-sample#project-creation-transcript)) 37 | * [grunt-init-gruntplugin](https://github.com/gruntjs/grunt-init-gruntplugin) - Create a Grunt plugin, including Nodeunit unit tests. ([sample "generated" repo](https://github.com/gruntjs/grunt-init-gruntplugin-sample/tree/generated) | [creation transcript](https://github.com/gruntjs/grunt-init-gruntplugin-sample#project-creation-transcript)) 38 | * [grunt-init-jquery](https://github.com/gruntjs/grunt-init-jquery) - Create a jQuery plugin, including QUnit unit tests. ([sample "generated" repo](https://github.com/gruntjs/grunt-init-jquery-sample/tree/generated) | [creation transcript](https://github.com/gruntjs/grunt-init-jquery-sample#project-creation-transcript)) 39 | * [grunt-init-node](https://github.com/gruntjs/grunt-init-node) - Create a Node.js module, including Nodeunit unit tests. ([sample "generated" repo](https://github.com/gruntjs/grunt-init-node-sample/tree/generated) | [creation transcript](https://github.com/gruntjs/grunt-init-node-sample#project-creation-transcript)) 40 | 41 | ## Custom templates 42 | You can create and use custom templates. Your template must follow the same structure as the aforementioned templates. 43 | 44 | A sample template named `my-template` would follow this general file structure: 45 | 46 | * `my-template/template.js` - the main template file. 47 | * `my-template/rename.json` - template-specific rename rules, processed as templates. 48 | * `my-template/root/` - files to be copied into the target location. 49 | 50 | Assuming these files exist at `/path/to/my-template`, the command `grunt-init /path/to/my-template` would be used to process the template. Multiple uniquely-named templates may exist in the same directory. 51 | 52 | Additionally, if you place this custom template in your `~/.grunt-init/` directory (`%USERPROFILE%\.grunt-init\` on Windows) it will be automatically available to be used with just `grunt-init my-template`. 53 | 54 | ### Copying files 55 | As long as a template uses the `init.filesToCopy` and `init.copyAndProcess` methods, any files in the `root/` subdirectory will be copied to the current directory when the init template is run. 56 | 57 | Note that all copied files will be processed as templates, with any `{% %}` template being processed against the collected `props` data object, unless the `noProcess` option is set. See the [jquery template](https://github.com/gruntjs/grunt-init-jquery) for an example. 58 | 59 | ### Renaming or excluding template files 60 | The `rename.json` describes `sourcepath` to `destpath` rename mappings. The `sourcepath` must be the path of the file-to-be-copied relative to the `root/` folder, but the `destpath` value can contain `{% %}` templates, describing what the destination path will be. 61 | 62 | If `false` is specified as a `destpath` the file will not be copied. Also, glob patterns are supported for `srcpath`. 63 | 64 | ## Specifying default prompt answers 65 | Each init prompt either has a default value hard-coded or it looks at the current environment to attempt to determine that default value. If you want to override a particular prompt's default value, you can do so in the optional OS X or Linux `~/.grunt-init/defaults.json` or Windows `%USERPROFILE%\.grunt-init\defaults.json` file. 66 | 67 | For example, my `defaults.json` file looks like this, because I want to use a slightly different name than the default name, I want to exclude my email address, and I want to specify an author url automatically. 68 | 69 | ```json 70 | { 71 | "author_name": "\"Cowboy\" Ben Alman", 72 | "author_email": "none", 73 | "author_url": "http://benalman.com/" 74 | } 75 | ``` 76 | 77 | _Note: until all the built-in prompts have been documented, you can find their names and default values in the [source code](https://github.com/gruntjs/grunt-init/blob/master/tasks/init.js)._ 78 | 79 | ## Defining an init template 80 | 81 | ### exports.description 82 | This brief template description will be displayed along with the template name when the user runs `grunt init` or `grunt-init ` to display a list of all available init templates. 83 | 84 | ```js 85 | exports.description = descriptionString; 86 | ``` 87 | 88 | ### exports.notes 89 | If specified, this optional extended description will be displayed before any prompts are displayed. This is a good place to give the user a little help explaining naming conventions, which prompts may be required or optional, etc. 90 | 91 | ```js 92 | exports.notes = notesString; 93 | ``` 94 | 95 | ### exports.warnOn 96 | If this optional (but recommended) wildcard pattern or array of wildcard patterns is matched, Grunt will abort with a warning that the user can override with `--force`. This is very useful in cases where the init template could potentially override existing files. 97 | 98 | ```js 99 | exports.warnOn = wildcardPattern; 100 | ``` 101 | 102 | While the most common value will be `'*'`, matching any file or directory, the [minimatch](https://github.com/isaacs/minimatch) wildcard pattern syntax used allows for a lot of flexibility. For example: 103 | 104 | ```js 105 | exports.warnOn = 'Gruntfile.js'; // Warn on a Gruntfile.js file. 106 | exports.warnOn = '*.js'; // Warn on any .js file. 107 | exports.warnOn = '*'; // Warn on any non-dotfile or non-dotdir. 108 | exports.warnOn = '.*'; // Warn on any dotfile or dotdir. 109 | exports.warnOn = '{.*,*}'; // Warn on any file or dir (dot or non-dot). 110 | exports.warnOn = '!*/**'; // Warn on any file (ignoring dirs). 111 | exports.warnOn = '*.{png,gif,jpg}'; // Warn on any image file. 112 | 113 | // This is another way of writing the last example. 114 | exports.warnOn = ['*.png', '*.gif', '*.jpg']; 115 | ``` 116 | 117 | ### exports.template 118 | While the `exports` properties are defined outside this function, all the actual init code is specified inside. Three arguments are passed into this function. The `grunt` argument is a reference to grunt, containing all the [grunt methods and libs](api/grunt). The `init` argument is an object containing methods and properties specific to this init template. The `done` argument is a function that must be called when the init template is done executing. 119 | 120 | ```js 121 | exports.template = function(grunt, init, done) { 122 | // See the "Inside an init template" section. 123 | }; 124 | ``` 125 | 126 | ## Inside an init template 127 | 128 | ### init.addLicenseFiles 129 | Add properly-named license files to the files object. 130 | 131 | ```js 132 | var files = {}; 133 | var licenses = ['MIT']; 134 | init.addLicenseFiles(files, licenses); 135 | // files === {'LICENSE-MIT': 'licenses/LICENSE-MIT'} 136 | ``` 137 | 138 | ### init.availableLicenses 139 | Return an array of available licenses. 140 | 141 | ```js 142 | var licenses = init.availableLicenses(); 143 | // licenses === [ 'Apache-2.0', 'GPL-2.0', 'MIT', 'MPL-2.0' ] 144 | ``` 145 | 146 | ### init.copy 147 | Given an absolute or relative source path, and an optional relative 148 | destination path, copy a file, optionally processing it through the 149 | passed callback. 150 | 151 | ```js 152 | init.copy(srcpath[, destpath], options) 153 | ``` 154 | 155 | ### init.copyAndProcess 156 | Iterate over all files in the passed object, copying the source file to 157 | the destination, processing the contents. 158 | 159 | ```js 160 | init.copyAndProcess(files, props[, options]) 161 | ``` 162 | 163 | ### init.defaults 164 | User-specified default init values from `defaults.json`. 165 | 166 | ```js 167 | init.defaults 168 | ``` 169 | 170 | ### init.destpath 171 | Absolute destination file path. 172 | 173 | ```js 174 | init.destpath() 175 | ``` 176 | 177 | ### init.expand 178 | Same as [grunt.file.expand](https://github.com/gruntjs/grunt/wiki/grunt.file#wiki-grunt-file-expand). 179 | 180 | Return a unique array of all file or directory paths that match the given wildcard pattern(s). This method accepts either comma separated wildcard patterns or an array of wildcard patterns. Paths matching patterns that begin with ! will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant. 181 | 182 | ```js 183 | init.expand([options, ] patterns) 184 | ``` 185 | 186 | ### init.filesToCopy 187 | Return an object containing files to copy with their absolute source path and relative destination path, renamed (or omitted) according to rules in rename.json (if it exists). 188 | 189 | ```js 190 | var files = init.filesToCopy(props); 191 | /* files === { '.gitignore': 'template/root/.gitignore', 192 | '.jshintrc': 'template/root/.jshintrc', 193 | 'Gruntfile.js': 'template/root/Gruntfile.js', 194 | 'README.md': 'template/root/README.md', 195 | 'test/test_test.js': 'template/root/test/name_test.js' } */ 196 | ``` 197 | 198 | ### init.getFile 199 | Get a single task file path. 200 | 201 | ```js 202 | init.getFile(filepath[, ...]) 203 | ``` 204 | 205 | ### init.getTemplates 206 | Returns an object of all the available templates. 207 | 208 | ```js 209 | init.getTemplates() 210 | ``` 211 | 212 | ### init.initSearchDirs 213 | Initialize the directories to search for init templates. `template` is the 214 | location of a template. Will also include `~/.grunt-init/` and the core init 215 | tasks within grunt-init. 216 | 217 | ```js 218 | init.initSearchDirs([filename]) 219 | ``` 220 | 221 | ### init.process 222 | Start up the process to begin prompting for input. 223 | 224 | ```js 225 | init.process(options, prompts, done) 226 | ``` 227 | 228 | ```js 229 | init.process({}, [ 230 | // Prompt for these values 231 | init.prompt('name'), 232 | init.prompt('description'), 233 | init.prompt('version') 234 | ], function(err, props) { 235 | // All finished, do something with the properties 236 | }); 237 | ``` 238 | 239 | ### init.prompt 240 | Prompt a user for a value. 241 | 242 | ```js 243 | init.prompt(name[, default]) 244 | ``` 245 | 246 | ### init.prompts 247 | An object of all the prompts. 248 | 249 | ```js 250 | var prompts = init.prompts; 251 | ``` 252 | 253 | ### init.readDefaults 254 | Read JSON defaults from task files (if they exist), merging them into one data object. 255 | 256 | ```js 257 | init.readDefaults(filepath[, ...]) 258 | ``` 259 | 260 | ### init.renames 261 | The rename rules for the template. 262 | 263 | ```js 264 | var renames = init.renames; 265 | // renames === { 'test/name_test.js': 'test/{%= name %}_test.js' } 266 | ``` 267 | 268 | ### init.searchDirs 269 | An array of directories to search for templates in. 270 | 271 | ```js 272 | var dirs = init.searchDirs; 273 | /* dirs === [ '/Users/shama/.grunt-init', 274 | '/usr/local/lib/node_modules/grunt-init/templates' ] */ 275 | ``` 276 | 277 | ### init.srcpath 278 | Search init template paths for filename and return an absolute path. 279 | 280 | ```js 281 | init.srcpath(filepath[, ...]) 282 | ``` 283 | 284 | ### init.userDir 285 | Returns the absolute path to the user's template directory. 286 | 287 | ```js 288 | var dir = init.userDir(); 289 | // dir === '/Users/shama/.grunt-init' 290 | ``` 291 | 292 | ### init.writePackageJSON 293 | Save a package.json file in the destination directory. The callback can be used to post-process properties to add/remove/whatever. 294 | 295 | ```js 296 | init.writePackageJSON(filename, props[, callback]) 297 | ``` 298 | 299 | ## Built-in prompts 300 | 301 | ### author_email 302 | Author's email address to use in the `package.json`. Will attempt to find a default value from the user's git config. 303 | 304 | ### author_name 305 | Author's full name to use in the `package.json` and copyright notices. Will attempt to find a default value from the user's git config. 306 | 307 | ### author_url 308 | A public URL to the author's website to use in the `package.json`. 309 | 310 | ### bin 311 | A relative path from the project root for a cli script. 312 | 313 | ### bugs 314 | A public URL to the project's issues tracker. Will default to the github issue tracker if the project has a github repository. 315 | 316 | ### description 317 | A description of the project. Used in the `package.json` and README files. 318 | 319 | ### grunt_version 320 | A valid semantic version range descriptor of Grunt the project requires. 321 | 322 | ### homepage 323 | A public URL to the project's home page. Will default to the github url if a github repository. 324 | 325 | ### jquery_version 326 | If a jQuery project, the version of jQuery the project requires. Must be a valid semantic version range descriptor. 327 | 328 | ### licenses 329 | The license(s) for the project. Multiple licenses are separated by spaces. The licenses built-in are: `MIT`, `MPL-2.0`, `GPL-2.0`, and `Apache-2.0`. Defaults to `MIT`. Add custom licenses with [init.addLicenseFiles](#initaddlicensefiles). 330 | 331 | ### main 332 | The primary entry point of the project. Defaults to the project name within the `lib` folder. 333 | 334 | ### name 335 | The name of the project. Will be used heavily throughout the project template. Defaults to the current working directory. 336 | 337 | ### node_version 338 | The version of Node.js the project requires. Must be a valid semantic version range descriptor. 339 | 340 | ### npm_test 341 | The command to run tests on your project. Defaults to `grunt`. 342 | 343 | ### repository 344 | Project's git repository. Defaults to a guess of a github url. 345 | 346 | ### title 347 | A human readable project name. Defaults to the actual project name altered to be more human readable. 348 | 349 | ### version 350 | The version of the project. Defaults to the first valid semantic version, `0.1.0`. 351 | --------------------------------------------------------------------------------