├── .npmrc ├── .gitignore ├── test ├── fixtures │ ├── dontlint_gruntfile.txt │ ├── missingsemicolon.js │ ├── nodemodule.js │ ├── extract.html │ ├── wrule.js │ └── lint.txt └── jshint_test.js ├── .mailmap ├── .jshintignore ├── CONTRIBUTING.md ├── docs ├── jshint-overview.md ├── jshint-examples.md └── jshint-options.md ├── AUTHORS ├── package.json ├── .jshintrc ├── .github └── workflows │ └── test.yml ├── LICENSE-MIT ├── Gruntfile.js ├── tasks ├── jshint.js └── lib │ └── jshint.js ├── CHANGELOG └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | lockfile-version=2 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | tmp -------------------------------------------------------------------------------- /test/fixtures/dontlint_gruntfile.txt: -------------------------------------------------------------------------------- 1 | Dont lint me! -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Michał Gołębiowski-Owczarek 2 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | test/fixtures/dontlint.txt 2 | node_modules/** 3 | -------------------------------------------------------------------------------- /test/fixtures/missingsemicolon.js: -------------------------------------------------------------------------------- 1 | var missingsemicolon = true 2 | -------------------------------------------------------------------------------- /test/fixtures/nodemodule.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function() { 4 | }; 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please see the [Contributing to grunt](https://gruntjs.com/contributing) guide for information on contributing to this project. 2 | -------------------------------------------------------------------------------- /test/fixtures/extract.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/fixtures/wrule.js: -------------------------------------------------------------------------------- 1 | // throws "not defined" errors, 2 | // but we are testing to make sure we can ignore that warning by code. 3 | something = ''; 4 | -------------------------------------------------------------------------------- /docs/jshint-overview.md: -------------------------------------------------------------------------------- 1 | Task targets, files and options may be specified according to the grunt [Configuring tasks](https://gruntjs.com/configuring-tasks) guide. 2 | -------------------------------------------------------------------------------- /test/fixtures/lint.txt: -------------------------------------------------------------------------------- 1 | // This file is encoded with UTF-16 BE, which produces an error on character 0 with JSHint -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | "Cowboy" Ben Alman (http://benalman.com/) 2 | Tyler Kellen (http://goingslowly.com/) 3 | Kyle Robinson Young (http://dontkry.com/) 4 | Vlad Filippov (http://vladfilippov.com/) 5 | Tony Lukasavage 6 | Thomas Boyt 7 | Szymon Przybylski 8 | Spencer Alger 9 | Sebastiaan Deckers 10 | Rob Wierzbowski 11 | Patrick Williams 12 | Nick Schonning 13 | Nick Babcock 14 | Michał Gołębiowski-Owczarek 15 | Kosei Moriyama 16 | Juan Pablo Buritica 17 | James Beavers 18 | Eugene Kashida 19 | Cliffano Subagio 20 | Allan K. Jensen 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grunt-contrib-jshint", 3 | "description": "Validate files with JSHint", 4 | "version": "3.2.0", 5 | "author": { 6 | "name": "Grunt Team", 7 | "url": "https://gruntjs.com/" 8 | }, 9 | "repository": "gruntjs/grunt-contrib-jshint", 10 | "license": "MIT", 11 | "engines": { 12 | "node": ">=10" 13 | }, 14 | "main": "tasks/jshint.js", 15 | "scripts": { 16 | "test": "grunt test" 17 | }, 18 | "dependencies": { 19 | "chalk": "~4.1.2", 20 | "hooker": "^0.2.3", 21 | "jshint": "~2.13.6" 22 | }, 23 | "devDependencies": { 24 | "grunt": "^1.4.1", 25 | "grunt-contrib-internal": "^7.0.0", 26 | "grunt-contrib-nodeunit": "^4.0.0" 27 | }, 28 | "keywords": [ 29 | "gruntplugin" 30 | ], 31 | "files": [ 32 | "tasks" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "boss": true, // true: Tolerate assignments where comparisons would be expected 3 | "curly": true, // true: Require {} for every new block or scope 4 | "eqeqeq": true, // true: Require triple equals (===) for comparison 5 | "eqnull": true, // true: Tolerate use of `== null` 6 | "immed": true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` 7 | "latedef": true, // true: Require variables/functions to be defined before being used 8 | "newcap": true, // true: Require capitalization of all constructor functions e.g. `new F()` 9 | "noarg": true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 10 | "sub": true, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 11 | "undef": true, // true: Require all non-global variables to be declared (prevents global leaks) 12 | "unused": true, 13 | "node": true, // Node.js 14 | "-W117": true // true: Ignore `not defined` errors as an example of using a rule (W117) by code. 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: [push, pull_request] 4 | 5 | env: 6 | FORCE_COLOR: 2 7 | 8 | jobs: 9 | run: 10 | name: Node ${{ matrix.node }} on ${{ matrix.os }} 11 | runs-on: ${{ matrix.os }} 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | node: [12, 14, 16] 17 | os: [ubuntu-latest, windows-latest] 18 | 19 | steps: 20 | - name: Clone repository 21 | uses: actions/checkout@v4 22 | 23 | - name: Set up Node.js 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node }} 27 | 28 | - name: Install npm dependencies 29 | run: npm ci 30 | 31 | - name: Run tests 32 | run: npm test 33 | 34 | # We test multiple Windows shells because of prior stdout buffering issues 35 | # filed against Grunt. https://github.com/joyent/node/issues/3584 36 | - name: Run PowerShell tests 37 | run: "npm test # PowerShell" # Pass comment to PS for easier debugging 38 | shell: powershell 39 | if: startsWith(matrix.os, 'windows') 40 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 "Cowboy" Ben Alman, contributors 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-contrib-jshint 3 | * https://gruntjs.com/ 4 | * 5 | * Copyright (c) 2016 "Cowboy" Ben Alman, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | module.exports = function(grunt) { 12 | 13 | // Project configuration. 14 | grunt.initConfig({ 15 | jshint: { 16 | allFiles: [ 17 | 'Gruntfile.js', 18 | 'tasks/**/*.js', 19 | '<%= nodeunit.tests %>' 20 | ], 21 | individualFiles: { 22 | files: [ 23 | {src: 'Gruntfile.js'}, 24 | {src: 'tasks/**/*.js'}, 25 | {src: '<%= nodeunit.tests %>'} 26 | ] 27 | }, 28 | withReporterShouldFail: { 29 | options: { 30 | reporter: 'checkstyle', 31 | reporterOutput: 'tmp/report.xml', 32 | force: true 33 | }, 34 | src: [ 35 | 'test/fixtures/missingsemicolon.js', 36 | 'test/fixtures/wrule.js' 37 | ] 38 | }, 39 | ignoresSupportGruntFile: { 40 | src: ['test/fixtures/dontlint_gruntfile.txt'], 41 | options: { 42 | ignores: 'test/fixtures/dontlint_gruntfile.txt' 43 | } 44 | }, 45 | // this rule should ignore node_modules and dontlint.txt using .jshintignore. 46 | // only nodemodule.js should be linted 47 | ignoresSupportIgnoreFile: { 48 | src: ['test/fixtures/dontlint.txt', 'node_modules/**', 'test/fixtures/nodemodule.js'] 49 | }, 50 | options: { 51 | jshintrc: '.jshintrc' 52 | } 53 | }, 54 | 55 | // Unit tests. 56 | nodeunit: { 57 | tests: ['test/*_test.js'] 58 | } 59 | }); 60 | 61 | // Actually load this plugin's task(s). 62 | grunt.loadTasks('tasks'); 63 | 64 | // These plugins provide necessary tasks. 65 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 66 | grunt.loadNpmTasks('grunt-contrib-internal'); 67 | 68 | // Whenever the "test" task is run, run the "nodeunit" task. 69 | grunt.registerTask('test', ['jshint', 'nodeunit']); 70 | 71 | // By default, lint and run all tests. 72 | grunt.registerTask('default', ['test', 'build-contrib']); 73 | 74 | }; 75 | -------------------------------------------------------------------------------- /tasks/jshint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-contrib-jshint 3 | * https://gruntjs.com/ 4 | * 5 | * Copyright (c) 2016 "Cowboy" Ben Alman, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | module.exports = function(grunt) { 12 | 13 | var path = require('path'); 14 | var hooker = require('hooker'); 15 | var jshint = require('./lib/jshint').init(grunt); 16 | 17 | grunt.registerMultiTask('jshint', 'Validate files with JSHint.', function() { 18 | var done = this.async(); 19 | 20 | // Merge task-specific and/or target-specific options with these defaults. 21 | var options = this.options({ 22 | force: false, 23 | reporter: null, 24 | reporterOutputRelative: true 25 | }); 26 | 27 | // Report JSHint errors but dont fail the task 28 | var force = options.force; 29 | delete options.force; 30 | 31 | // Whether to output the report to a file 32 | var reporterOutput = options.reporterOutput; 33 | 34 | // Hook into stdout to capture report 35 | var output = ''; 36 | if (reporterOutput) { 37 | hooker.hook(process.stdout, 'write', { 38 | pre: function(out) { 39 | output += out; 40 | return hooker.preempt(); 41 | } 42 | }); 43 | } 44 | 45 | jshint.lint(this.filesSrc, options, function(results, data) { 46 | var failed = 0; 47 | if (results.length > 0) { 48 | // Fail task if errors were logged except if force was set. 49 | failed = force; 50 | if (jshint.usingGruntReporter === true) { 51 | 52 | var numErrors = grunt.util._.reduce(results, function(memo, result) { 53 | return memo + (result.error ? 1 : 0); 54 | }, 0); 55 | 56 | var numFiles = data.length; 57 | grunt.log.error(numErrors + ' ' + grunt.util.pluralize(numErrors, 'error/errors') + ' in ' + 58 | numFiles + ' ' + grunt.util.pluralize(numFiles, 'file/files')); 59 | } 60 | } else { 61 | if (jshint.usingGruntReporter === true && data.length > 0) { 62 | grunt.log.ok(data.length + ' ' + grunt.util.pluralize(data.length, 'file/files') + ' lint free.'); 63 | } 64 | } 65 | 66 | // Write the output of the reporter if wanted 67 | if (reporterOutput) { 68 | hooker.unhook(process.stdout, 'write'); 69 | reporterOutput = grunt.template.process(reporterOutput); 70 | var destDir = path.dirname(reporterOutput); 71 | if (!grunt.file.exists(destDir)) { 72 | grunt.file.mkdir(destDir); 73 | } 74 | grunt.file.write(reporterOutput, output); 75 | grunt.log.ok('Report "' + reporterOutput + '" created.'); 76 | } 77 | 78 | done(failed); 79 | }); 80 | }); 81 | 82 | }; 83 | -------------------------------------------------------------------------------- /docs/jshint-examples.md: -------------------------------------------------------------------------------- 1 | # Usage examples 2 | 3 | ## Wildcards 4 | In this example, running `grunt jshint:all` (or `grunt jshint` because `jshint` is a [multi task](https://gruntjs.com/configuring-tasks#task-configuration-and-targets)) will lint the project's Gruntfile as well as all JavaScript files in the `lib` and `test` directories and their subdirectories, using the default JSHint options. 5 | 6 | ```js 7 | // Project configuration. 8 | grunt.initConfig({ 9 | jshint: { 10 | all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'] 11 | } 12 | }); 13 | ``` 14 | 15 | ## Linting before and after concatenating 16 | In this example, running `grunt jshint` will lint both the "beforeconcat" set and "afterconcat" sets of files. This is not ideal, because `dist/output.js` may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) `concat` task. 17 | 18 | In this case, you should lint the "beforeconcat" files first, then concat, then lint the "afterconcat" files, by running `grunt jshint:beforeconcat concat jshint:afterconcat`. 19 | 20 | ```js 21 | // Project configuration. 22 | grunt.initConfig({ 23 | concat: { 24 | dist: { 25 | src: ['src/foo.js', 'src/bar.js'], 26 | dest: 'dist/output.js' 27 | } 28 | }, 29 | jshint: { 30 | beforeconcat: ['src/foo.js', 'src/bar.js'], 31 | afterconcat: ['dist/output.js'] 32 | } 33 | }); 34 | ``` 35 | 36 | ## Specifying JSHint options and globals 37 | 38 | In this example, custom JSHint options are specified. Note that when `grunt jshint:uses_defaults` is run, those files are linted using the default options, but when `grunt jshint:with_overrides` is run, those files are linted using _merged_ task/target options. 39 | 40 | ```js 41 | // Project configuration. 42 | grunt.initConfig({ 43 | jshint: { 44 | options: { 45 | curly: true, 46 | eqeqeq: true, 47 | eqnull: true, 48 | browser: true, 49 | globals: { 50 | jQuery: true 51 | }, 52 | }, 53 | uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'], 54 | with_overrides: { 55 | options: { 56 | curly: false, 57 | undef: true, 58 | }, 59 | files: { 60 | src: ['dir3/**/*.js', 'dir4/**/*.js'] 61 | }, 62 | } 63 | }, 64 | }); 65 | ``` 66 | 67 | ## Ignoring specific warnings 68 | 69 | If you would like to ignore a specific warning: 70 | 71 | ```shell 72 | [L24:C9] W015: Expected '}' to have an indentation at 11 instead at 9. 73 | ``` 74 | 75 | You can toggle it by prepending `-` to the warning id as an option: 76 | 77 | ```js 78 | grunt.initConfig({ 79 | jshint: { 80 | ignore_warning: { 81 | options: { 82 | '-W015': true, 83 | }, 84 | src: ['**/*.js'], 85 | }, 86 | }, 87 | }); 88 | ``` 89 | -------------------------------------------------------------------------------- /docs/jshint-options.md: -------------------------------------------------------------------------------- 1 | # Options 2 | 3 | Any specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options. 4 | 5 | [JSHint]: http://jshint.com/ 6 | [JSHint documentation]: http://jshint.com/docs/ 7 | 8 | A few additional options are supported: 9 | 10 | 11 | ## globals 12 | 13 | Type: `Object` 14 | Default: `null` 15 | 16 | A map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the `JSHINT` function as its third argument. See the [JSHint documentation][] for more information. 17 | 18 | 19 | ## jshintrc 20 | 21 | Type: `String` or `true` 22 | Default: `null` 23 | 24 | If set to `true`, no config will be sent to JSHint and JSHint will search for `.jshintrc` files relative to the files being linted. 25 | 26 | If a filename is specified, options and globals defined therein will be used. The `jshintrc` file must be valid JSON and looks something like this: 27 | 28 | ```json 29 | { 30 | "curly": true, 31 | "eqnull": true, 32 | "eqeqeq": true, 33 | "undef": true, 34 | "globals": { 35 | "jQuery": true 36 | } 37 | } 38 | ``` 39 | 40 | *Be aware that `jshintrc` settings are not merged with your Grunt options.* 41 | 42 | 43 | ## extensions 44 | 45 | Type: `String` 46 | Default: `''` 47 | 48 | A list of non-dot-js extensions to check. 49 | 50 | 51 | ## ignores 52 | 53 | Type: `Array` 54 | Default: `null` 55 | 56 | A list of files and dirs to ignore. This will override your `.jshintignore` file if set and does not merge. 57 | 58 | 59 | ## force 60 | 61 | Type: `Boolean` 62 | Default: `false` 63 | 64 | Set `force` to `true` to report JSHint errors but not fail the task. 65 | 66 | 67 | ## reporter 68 | 69 | Type: `String` 70 | Default: `null` 71 | 72 | Allows you to modify this plugins output. By default it will use a built-in Grunt reporter. Set the path to your own custom reporter or to one of the built-in JSHint reporters: `jslint` or `checkstyle`. 73 | 74 | See also: [Writing your own JSHint reporter.](http://jshint.com/docs/reporters/) 75 | 76 | You can also use an external reporter. For example [jshint-stylish](https://github.com/sindresorhus/jshint-stylish): 77 | 78 | ``` 79 | $ npm install --save-dev jshint-stylish 80 | ``` 81 | 82 | ```js 83 | options: { 84 | reporter: require('jshint-stylish') 85 | } 86 | ``` 87 | 88 | ## reporterOutput 89 | 90 | Type: `String` 91 | Default: `null` 92 | 93 | Specify a filepath to output the results of a reporter. If `reporterOutput` is specified then all output will be written to the given filepath instead of printed to stdout. 94 | 95 | #### reporterOutputRelative 96 | 97 | Type: `Boolean` 98 | Default: `true` 99 | 100 | Results of a reporter will use a relative filepath to `reporterOutput`. If set to `false` then filepaths will appear relative to the current folder. Unless `reporterOutput` is not set this option will not have any effect. 101 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v3.2.0: 2 | date: 2022-02-17 3 | changes: 4 | - Bump dependencies, including jshint. 5 | v3.0.0: 6 | date: 2020-10-20 7 | changes: 8 | - Bump dependencies. 9 | - Switch to GitHub actions. 10 | - Ensures errors in stdoutEqual callback are logged. 11 | - Requires Node 10+. 12 | v2.1.0: 13 | date: 2019-03-18 14 | changes: 15 | - Bump dependencies. 16 | - Update to latest JSHint 17 | v2.0.0: 18 | date: 2018-09-22 19 | changes: 20 | - Bump devDependencies. 21 | - Drop Node.js < 6 support. 22 | v1.1.0: 23 | date: 2016-11-23 24 | changes: 25 | - Fix relative output 26 | - Bump minor version 27 | v1.0.0: 28 | date: 2016-02-16 29 | changes: 30 | - Replace String prototype colors with chalk. 31 | - Update Grunt peerDep to `>=0.4.0`. 32 | v0.12.0: 33 | date: 2016-01-17 34 | changes: 35 | - Update to JSHint ~2.9.0. 36 | v0.11.3: 37 | date: 2015-09-03 38 | changes: 39 | - Update to JSHint ~2.8.0. 40 | v0.11.2: 41 | date: 2015-04-16 42 | changes: 43 | - Fix default value of the `reporter` option. 44 | v0.11.1: 45 | date: 2015-03-20 46 | changes: 47 | - Fix io.js compatibility issues. 48 | - Other fixes to pathing. 49 | v0.11.0: 50 | date: 2015-01-22 51 | changes: 52 | - Update to JSHint ~2.6.0. 53 | v0.10.0: 54 | date: 2014-04-02 55 | changes: 56 | - Update to JSHint 2.5.0. 57 | v0.9.2: 58 | date: 2014-03-12 59 | changes: 60 | - Fixes a bug where `reporterOutput` was still passed to JSHint. 61 | v0.9.1: 62 | date: 2014-03-12 63 | changes: 64 | - Don't pass `reporterOutput` option to JSHint. 65 | v0.9.0: 66 | date: 2014-03-12 67 | changes: 68 | - Replace deprecated `grunt.util._.clone` with `Object.create()`. 69 | - Replace deprecated `grunt.util.hooker` with hooker lib. 70 | - Enhancing the readability of the output. 71 | - Reporter output is relative to the output file. 72 | - Pass JSHint options to the external reporter. 73 | v0.8.0: 74 | date: 2013-12-25 75 | changes: 76 | - Update to JSHint 2.4.0. 77 | v0.7.2: 78 | date: 2013-11-16 79 | changes: 80 | - Only print file name once per error. 81 | v0.7.1: 82 | date: 2013-10-31 83 | changes: 84 | - Ability to set jshintrc option to true to use JSHint's native ability for finding .jshintrc files relative to the linted files. 85 | v0.7.0: 86 | date: 2013-10-23 87 | changes: 88 | - Update to JSHint 2.3.0. 89 | v0.6.5: 90 | date: 2013-10-23 91 | changes: 92 | - Fix output when `maxerr` is low. 93 | v0.6.4: 94 | date: 2013-08-29 95 | changes: 96 | - jshintrc now loaded by JSHint allowing comments. 97 | v0.6.3: 98 | date: 2013-08-15 99 | changes: 100 | - Fix module location for JSHint 2.1.10. 101 | v0.6.2: 102 | date: 2013-07-29 103 | changes: 104 | - Update to JSHint 2.1.7. 105 | v0.6.1: 106 | date: 2013-07-27 107 | changes: 108 | - Peg JSHint to 2.1.4 until breaking changes in 2.1.5 are fixed. 109 | v0.6.0: 110 | date: 2013-06-02 111 | changes: 112 | - Don't always succeed the task when using a custom reporter. 113 | - Bump JSHint to 2.1.3. 114 | v0.5.4: 115 | date: 2013-05-22 116 | changes: 117 | - Fix default reporter to show offending file. 118 | v0.5.3: 119 | date: 2013-05-19 120 | changes: 121 | - "Performance: Execute the reporter once rather than per file." 122 | v0.5.2: 123 | date: 2013-05-18 124 | changes: 125 | - Fix printing too many erroneous ignored file errors. 126 | v0.5.1: 127 | date: 2013-05-17 128 | changes: 129 | - Fix for when only 1 file is lint free. 130 | v0.5.0: 131 | date: 2013-05-17 132 | changes: 133 | - Bump to JSHint 2.0. 134 | - Add support for .jshintignore files and ignores option. 135 | - Add support for `extensions` option. 136 | - Add support for custom reporters and output report to a file. 137 | v0.4.3: 138 | date: 2013-04-08 139 | changes: 140 | - Fix evaluation of `predef` option when it's an object. 141 | v0.4.2: 142 | date: 2013-04-08 143 | changes: 144 | - Avoid wiping `force` option when jshintrc is used. 145 | v0.4.1: 146 | date: 2013-04-06 147 | changes: 148 | - Fix to allow object type for deprecated predef. 149 | v0.4.0: 150 | date: 2013-04-04 151 | changes: 152 | - Revert task level options to override jshintrc files. 153 | v0.3.0: 154 | date: 2013-03-13 155 | changes: 156 | - Bump to JSHint 1.1.0. 157 | - Add force option to report JSHint errors but not fail the task. 158 | - Add error/warning code to message. 159 | - Allow task level options to override jshintrc file. 160 | v0.2.0: 161 | date: 2013-02-26 162 | changes: 163 | - Bump to JSHint 1.0. 164 | v0.1.1: 165 | date: 2013-02-15 166 | changes: 167 | - First official release for Grunt 0.4.0. 168 | v0.1.1rc6: 169 | date: 2013-01-18 170 | changes: 171 | - Updating grunt/gruntplugin dependencies to rc6. 172 | - Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. 173 | v0.1.1rc5: 174 | date: 2013-01-09 175 | changes: 176 | - Updating to work with grunt v0.4.0rc5. 177 | - Switching to `this.filesSrc` API. 178 | v0.1.0: 179 | date: 2012-10-18 180 | changes: 181 | - Work in progress, not yet officially released. 182 | -------------------------------------------------------------------------------- /tasks/lib/jshint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt-contrib-jshint 3 | * https://gruntjs.com/ 4 | * 5 | * Copyright (c) 2016 "Cowboy" Ben Alman, contributors 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var path = require('path'); 12 | var chalk = require('chalk'); 13 | var jshintcli = require('jshint/src/cli'); 14 | 15 | exports.init = function(grunt) { 16 | var exports = { 17 | usingGruntReporter: false 18 | }; 19 | 20 | var pad = function(msg, length) { 21 | while (msg.length < length) { 22 | msg = ' ' + msg; 23 | } 24 | return msg; 25 | }; 26 | 27 | // Select a reporter (if not using the default Grunt reporter) 28 | // Copied from jshint/src/cli/cli.js until that part is exposed 29 | exports.selectReporter = function(options) { 30 | switch (true) { 31 | // JSLint reporter 32 | case options.reporter === 'jslint': 33 | case options['jslint-reporter']: 34 | options.reporter = 'jshint/src/reporters/jslint_xml.js'; 35 | break; 36 | 37 | // CheckStyle (XML) reporter 38 | case options.reporter === 'checkstyle': 39 | case options['checkstyle-reporter']: 40 | options.reporter = 'jshint/src/reporters/checkstyle.js'; 41 | break; 42 | 43 | // Reporter that displays additional JSHint data 44 | case options['show-non-errors']: 45 | options.reporter = 'jshint/src/reporters/non_error.js'; 46 | break; 47 | 48 | // Custom reporter 49 | case options.reporter !== null && options.reporter !== undefined: 50 | options.reporter = path.resolve(process.cwd(), options.reporter.toString()); 51 | } 52 | 53 | var reporter; 54 | if (options.reporter) { 55 | try { 56 | reporter = require(options.reporter).reporter; 57 | exports.usingGruntReporter = false; 58 | } catch (err) { 59 | grunt.fatal(err); 60 | } 61 | } 62 | 63 | // Use the default Grunt reporter if none are found 64 | if (!reporter) { 65 | reporter = exports.reporter; 66 | exports.usingGruntReporter = true; 67 | } 68 | 69 | return reporter; 70 | }; 71 | 72 | // Default Grunt JSHint reporter 73 | exports.reporter = function(results, data) { 74 | // Dont report empty data as its an ignored file 75 | if (data.length < 1) { 76 | grunt.log.error('0 files linted. Please check your ignored files.'); 77 | return; 78 | } 79 | 80 | if (results.length === 0) { 81 | // Success! 82 | grunt.verbose.ok(); 83 | return; 84 | } 85 | 86 | var options = data[0].options; 87 | 88 | grunt.log.writeln(); 89 | 90 | var lastfile = null; 91 | // Iterate over all errors. 92 | results.forEach(function(result) { 93 | 94 | // Only print file name once per error 95 | if (result.file !== lastfile) { 96 | grunt.log.writeln(chalk.bold(result.file ? ' ' + result.file : '')); 97 | } 98 | lastfile = result.file; 99 | 100 | var e = result.error; 101 | 102 | // Sometimes there's no error object. 103 | if (!e) { 104 | return; 105 | } 106 | 107 | if (e.evidence) { 108 | // Manually increment errorcount since we're not using grunt.log.error(). 109 | grunt.fail.errorcount++; 110 | 111 | // No idea why JSHint treats tabs as options.indent # characters wide, but it 112 | // does. See issue: https://github.com/jshint/jshint/issues/430 113 | // Replacing tabs with appropriate spaces (i.e. columns) ensures that 114 | // caret will line up correctly. 115 | var evidence = e.evidence.replace(/\t/g, grunt.util.repeat(options.indent, ' ')); 116 | 117 | grunt.log.writeln(pad(e.line.toString(), 7) + ' |' + chalk.gray(evidence)); 118 | grunt.log.write(grunt.util.repeat(9, ' ') + grunt.util.repeat(e.character - 1, ' ') + '^ '); 119 | grunt.verbose.write('[' + e.code + '] '); 120 | grunt.log.writeln(e.reason); 121 | 122 | } else { 123 | // Generic "Whoops, too many errors" error. 124 | grunt.log.error(e.reason); 125 | } 126 | }); 127 | grunt.log.writeln(); 128 | }; 129 | 130 | // Run JSHint on the given files with the given options 131 | exports.lint = function(files, options, done) { 132 | var cliOptions = { 133 | verbose: grunt.option('verbose'), 134 | extensions: '' 135 | }; 136 | 137 | // A list of non-dot-js extensions to check 138 | if (options.extensions) { 139 | cliOptions.extensions = options.extensions; 140 | delete options.extensions; 141 | } 142 | 143 | // A list ignored files 144 | if (options.ignores) { 145 | if (typeof options.ignores === 'string') { 146 | options.ignores = [options.ignores]; 147 | } 148 | cliOptions.ignores = options.ignores; 149 | delete options.ignores; 150 | } 151 | 152 | // Option to extract JS from HTML file 153 | if (options.extract) { 154 | cliOptions.extract = options.extract; 155 | delete options.extract; 156 | } 157 | var reporterOutputDir; 158 | // Get reporter output directory for relative paths in reporters 159 | if (options.hasOwnProperty('reporterOutput')) { 160 | if (options.reporterOutput) { 161 | reporterOutputDir = path.dirname(options.reporterOutput); 162 | } 163 | delete options.reporterOutput; 164 | } 165 | 166 | // Select a reporter to use 167 | var reporter = exports.selectReporter(options); 168 | 169 | // Remove bad options that may have came in from the cli 170 | ['reporter', 'reporterOutputRelative', 'jslint-reporter', 'checkstyle-reporter', 'show-non-errors'].forEach(function(opt) { 171 | if (options.hasOwnProperty(opt)) { 172 | delete options[opt]; 173 | } 174 | }); 175 | 176 | if (options.jshintrc === true) { 177 | // let jshint find the options itself 178 | delete cliOptions.config; 179 | } else if (options.jshintrc) { 180 | // Read JSHint options from a specified jshintrc file. 181 | cliOptions.config = jshintcli.loadConfig(options.jshintrc); 182 | } else { 183 | // Enable/disable debugging if option explicitly set. 184 | if (grunt.option('debug') !== undefined) { 185 | options.devel = options.debug = grunt.option('debug'); 186 | // Tweak a few things. 187 | if (grunt.option('debug')) { 188 | options.maxerr = Infinity; 189 | } 190 | } 191 | // pass all of the remaining options directly to jshint 192 | cliOptions.config = options; 193 | } 194 | 195 | // Run JSHint on all file and collect results/data 196 | var allResults = []; 197 | var allData = []; 198 | cliOptions.args = files; 199 | cliOptions.reporter = function(results, data) { 200 | if (reporterOutputDir) { 201 | results.forEach(function(datum) { 202 | datum.file = path.relative(reporterOutputDir, datum.file); 203 | }); 204 | } 205 | reporter(results, data, options); 206 | allResults = allResults.concat(results); 207 | allData = allData.concat(data); 208 | }; 209 | jshintcli.run(cliOptions); 210 | done(allResults, allData); 211 | }; 212 | 213 | return exports; 214 | }; 215 | -------------------------------------------------------------------------------- /test/jshint_test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var grunt = require('grunt'); 5 | var hooker = require('hooker'); 6 | var jshint = require('../tasks/lib/jshint').init(grunt); 7 | 8 | var fixtures = path.join(__dirname, 'fixtures'); 9 | 10 | // Helper for testing stdout 11 | var stdoutEqual = function(callback, done) { 12 | var actual = ''; 13 | // Hook process.stdout.write 14 | hooker.hook(process.stdout, 'write', { 15 | // This gets executed before the original process.stdout.write. 16 | pre: function(result) { 17 | // Concatenate uncolored result onto actual. 18 | actual += grunt.log.uncolor(result); 19 | // Prevent the original process.stdout.write from executing. 20 | return hooker.preempt(); 21 | } 22 | }); 23 | // Execute the logging code to be tested. 24 | try { 25 | callback(); 26 | } catch (error) { 27 | hooker.unhook(process.stdout, 'write'); 28 | throw error; 29 | } 30 | // Restore process.stdout.write to its original value. 31 | hooker.unhook(process.stdout, 'write'); 32 | // Actually test the actually-logged stdout string to the expected value. 33 | done(actual); 34 | }; 35 | 36 | exports.jshint = { 37 | basic: function(test) { 38 | test.expect(1); 39 | var files = [path.join(fixtures, 'missingsemicolon.js')]; 40 | var options = {}; 41 | jshint.lint(files, options, function(results) { 42 | test.equal(results[0].error.reason, 'Missing semicolon.', 'Should report a missing semicolon.'); 43 | test.done(); 44 | }); 45 | }, 46 | jshintrc: function(test) { 47 | test.expect(1); 48 | var files = [path.join(fixtures, 'nodemodule.js')]; 49 | var options = { 50 | jshintrc: path.join(__dirname, '..', '.jshintrc') 51 | }; 52 | jshint.lint(files, options, function(results) { 53 | test.ok(results.length === 0, 'Should not have reported any errors with supplied .jshintrc'); 54 | test.done(); 55 | }); 56 | }, 57 | passTheJshintrcBuck: function(test) { 58 | test.expect(1); 59 | var files = [path.join(fixtures, 'nodemodule.js')]; 60 | var options = { 61 | jshintrc: true 62 | }; 63 | jshint.lint(files, options, function(results) { 64 | test.ok(results.length === 0, 'Should not have reported any errors, .jshintrc must not have been found'); 65 | test.done(); 66 | }); 67 | }, 68 | defaultReporter: function(test) { 69 | test.expect(2); 70 | grunt.log.muted = false; 71 | var files = [path.join(fixtures, 'nodemodule.js')]; 72 | var options = {}; 73 | stdoutEqual(function() { 74 | jshint.lint(files, options, function() {}); 75 | }, function(result) { 76 | test.ok(jshint.usingGruntReporter, 'Should be using the default grunt reporter.'); 77 | test.ok(result.indexOf('\'module\' is not defined.') !== -1, 'Should have reported errors with the default grunt reporter.'); 78 | test.done(); 79 | }); 80 | }, 81 | defaultReporterErrors: function(test) { 82 | test.expect(3); 83 | grunt.log.muted = false; 84 | var files = [path.join(fixtures, 'nodemodule.js'), path.join(fixtures, 'missingsemicolon.js')]; 85 | var options = {}; 86 | stdoutEqual(function() { 87 | jshint.lint(files, options, function() {}); 88 | }, function(result) { 89 | test.ok(jshint.usingGruntReporter, 'Should be using the default grunt reporter.'); 90 | test.ok(result.match(/nodemodule\.js/g).length === 1, 'Should have reported nodemodule.js only once.'); 91 | test.ok(result.match(/missingsemicolon\.js/g).length === 1, 'Should have reported missingsemicolon.js only once.'); 92 | test.done(); 93 | }); 94 | }, 95 | alternateReporter: function(test) { 96 | test.expect(2); 97 | var files = [path.join(fixtures, 'nodemodule.js')]; 98 | var options = { 99 | reporter: 'jslint' 100 | }; 101 | stdoutEqual(function() { 102 | jshint.lint(files, options, function() {}); 103 | }, function(result) { 104 | test.ok(jshint.usingGruntReporter === false, 'Should NOT be using the default grunt reporter.'); 105 | test.ok(result.indexOf('') !== -1, 'Should have reported errors with the jslint reporter.'); 106 | test.done(); 107 | }); 108 | }, 109 | reporterOutput: function(test) { 110 | test.expect(1); 111 | var result = grunt.file.read(path.join('tmp', 'report.xml')); 112 | var filename = path.relative('tmp', path.join(fixtures, 'missingsemicolon.js')); 113 | test.ok(result.indexOf('') !== -1, 'Should have reported errors with the checkstyle reporter.'); 114 | test.done(); 115 | }, 116 | dontBlowUp: function(test) { 117 | test.expect(1); 118 | var files = [path.join(fixtures, 'lint.txt')]; 119 | jshint.lint(files, {}, function(results) { 120 | test.equal(results[0].error.code, 'E024', 'It should not blow up if an error occurs on character 0.'); 121 | test.done(); 122 | }); 123 | }, 124 | jshintignoreInGruntfile: function(test) { 125 | test.expect(1); 126 | var files = [path.join(fixtures, 'dontlint_gruntfile.txt')]; 127 | var options = { 128 | ignores: 'test/fixtures/dontlint_gruntfile.txt' 129 | }; 130 | jshint.lint(files, options, function(results, data) { 131 | test.equal(data.length, 0, 'Should not have linted a file listed in the Gruntfile ignores setting'); 132 | test.done(); 133 | }); 134 | }, 135 | jshintignore: function(test) { 136 | test.expect(1); 137 | var files = [path.join(fixtures, 'dontlint.txt')]; 138 | jshint.lint(files, {}, function(results, data) { 139 | test.equal(data.length, 0, 'Should not have linted a file listed in the .jshintignore.'); 140 | test.done(); 141 | }); 142 | }, 143 | ignoresOption: function(test) { 144 | test.expect(1); 145 | var files = [path.join(fixtures, 'lint.txt')]; 146 | var options = { 147 | ignores: files 148 | }; 149 | jshint.lint(files, options, function(results, data) { 150 | test.equal(data.length, 0, 'Should not have linted a file listed in the ignores option.'); 151 | test.done(); 152 | }); 153 | }, 154 | singleReportCall: function(test) { 155 | test.expect(2); 156 | 157 | // stub jshint.reporter 158 | var reporterCallCount = 0; 159 | jshint.reporter = function() { 160 | reporterCallCount++; 161 | }; 162 | 163 | var files = [path.join(fixtures, 'dontlint.txt'), path.join(fixtures, 'lint.txt')]; 164 | jshint.lint(files, {}, function(results, data) { 165 | test.equal(data.length, 1, 'Should not have linted a file listed in the .jshintignore.'); 166 | test.equal(reporterCallCount, 1, 'Should have called the reporter once.'); 167 | test.done(); 168 | }); 169 | }, 170 | extractOption: function(test) { 171 | test.expect(2); 172 | var files = [path.join(fixtures, 'extract.html')]; 173 | var options = { 174 | extract: 'always' 175 | }; 176 | jshint.lint(files, options, function(results) { 177 | test.equal(results[0].error.reason, 'Missing semicolon.', 'Should report a missing semicolon.'); 178 | test.equal(results.length, 1, 'Should report only one.'); 179 | test.done(); 180 | }); 181 | } 182 | }; 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # grunt-contrib-jshint v3.2.0 [![Build Status](https://github.com/gruntjs/grunt-contrib-jshint/workflows/Tests/badge.svg)](https://github.com/gruntjs/grunt-contrib-jshint/actions?workflow=Tests) 2 | 3 | > Validate files with JSHint 4 | 5 | 6 | 7 | ## Getting Started 8 | 9 | If you haven't used [Grunt](https://gruntjs.com/) before, be sure to check out the [Getting Started](https://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](https://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command: 10 | 11 | ```shell 12 | npm install grunt-contrib-jshint --save-dev 13 | ``` 14 | 15 | Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript: 16 | 17 | ```js 18 | grunt.loadNpmTasks('grunt-contrib-jshint'); 19 | ``` 20 | 21 | 22 | 23 | 24 | ## Jshint task 25 | _Run this task with the `grunt jshint` command._ 26 | 27 | Task targets, files and options may be specified according to the grunt [Configuring tasks](https://gruntjs.com/configuring-tasks) guide. 28 | 29 | ### Options 30 | 31 | Any specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options. 32 | 33 | [JSHint]: http://jshint.com/ 34 | [JSHint documentation]: http://jshint.com/docs/ 35 | 36 | A few additional options are supported: 37 | 38 | 39 | #### globals 40 | 41 | Type: `Object` 42 | Default: `null` 43 | 44 | A map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the `JSHINT` function as its third argument. See the [JSHint documentation][] for more information. 45 | 46 | 47 | #### jshintrc 48 | 49 | Type: `String` or `true` 50 | Default: `null` 51 | 52 | If set to `true`, no config will be sent to JSHint and JSHint will search for `.jshintrc` files relative to the files being linted. 53 | 54 | If a filename is specified, options and globals defined therein will be used. The `jshintrc` file must be valid JSON and looks something like this: 55 | 56 | ```json 57 | { 58 | "curly": true, 59 | "eqnull": true, 60 | "eqeqeq": true, 61 | "undef": true, 62 | "globals": { 63 | "jQuery": true 64 | } 65 | } 66 | ``` 67 | 68 | *Be aware that `jshintrc` settings are not merged with your Grunt options.* 69 | 70 | 71 | #### extensions 72 | 73 | Type: `String` 74 | Default: `''` 75 | 76 | A list of non-dot-js extensions to check. 77 | 78 | 79 | #### ignores 80 | 81 | Type: `Array` 82 | Default: `null` 83 | 84 | A list of files and dirs to ignore. This will override your `.jshintignore` file if set and does not merge. 85 | 86 | 87 | #### force 88 | 89 | Type: `Boolean` 90 | Default: `false` 91 | 92 | Set `force` to `true` to report JSHint errors but not fail the task. 93 | 94 | 95 | #### reporter 96 | 97 | Type: `String` 98 | Default: `null` 99 | 100 | Allows you to modify this plugins output. By default it will use a built-in Grunt reporter. Set the path to your own custom reporter or to one of the built-in JSHint reporters: `jslint` or `checkstyle`. 101 | 102 | See also: [Writing your own JSHint reporter.](http://jshint.com/docs/reporters/) 103 | 104 | You can also use an external reporter. For example [jshint-stylish](https://github.com/sindresorhus/jshint-stylish): 105 | 106 | ``` 107 | $ npm install --save-dev jshint-stylish 108 | ``` 109 | 110 | ```js 111 | options: { 112 | reporter: require('jshint-stylish') 113 | } 114 | ``` 115 | 116 | #### reporterOutput 117 | 118 | Type: `String` 119 | Default: `null` 120 | 121 | Specify a filepath to output the results of a reporter. If `reporterOutput` is specified then all output will be written to the given filepath instead of printed to stdout. 122 | 123 | ###### reporterOutputRelative 124 | 125 | Type: `Boolean` 126 | Default: `true` 127 | 128 | Results of a reporter will use a relative filepath to `reporterOutput`. If set to `false` then filepaths will appear relative to the current folder. Unless `reporterOutput` is not set this option will not have any effect. 129 | 130 | ### Usage examples 131 | 132 | #### Wildcards 133 | In this example, running `grunt jshint:all` (or `grunt jshint` because `jshint` is a [multi task](https://gruntjs.com/configuring-tasks#task-configuration-and-targets)) will lint the project's Gruntfile as well as all JavaScript files in the `lib` and `test` directories and their subdirectories, using the default JSHint options. 134 | 135 | ```js 136 | // Project configuration. 137 | grunt.initConfig({ 138 | jshint: { 139 | all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'] 140 | } 141 | }); 142 | ``` 143 | 144 | #### Linting before and after concatenating 145 | In this example, running `grunt jshint` will lint both the "beforeconcat" set and "afterconcat" sets of files. This is not ideal, because `dist/output.js` may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) `concat` task. 146 | 147 | In this case, you should lint the "beforeconcat" files first, then concat, then lint the "afterconcat" files, by running `grunt jshint:beforeconcat concat jshint:afterconcat`. 148 | 149 | ```js 150 | // Project configuration. 151 | grunt.initConfig({ 152 | concat: { 153 | dist: { 154 | src: ['src/foo.js', 'src/bar.js'], 155 | dest: 'dist/output.js' 156 | } 157 | }, 158 | jshint: { 159 | beforeconcat: ['src/foo.js', 'src/bar.js'], 160 | afterconcat: ['dist/output.js'] 161 | } 162 | }); 163 | ``` 164 | 165 | #### Specifying JSHint options and globals 166 | 167 | In this example, custom JSHint options are specified. Note that when `grunt jshint:uses_defaults` is run, those files are linted using the default options, but when `grunt jshint:with_overrides` is run, those files are linted using _merged_ task/target options. 168 | 169 | ```js 170 | // Project configuration. 171 | grunt.initConfig({ 172 | jshint: { 173 | options: { 174 | curly: true, 175 | eqeqeq: true, 176 | eqnull: true, 177 | browser: true, 178 | globals: { 179 | jQuery: true 180 | }, 181 | }, 182 | uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'], 183 | with_overrides: { 184 | options: { 185 | curly: false, 186 | undef: true, 187 | }, 188 | files: { 189 | src: ['dir3/**/*.js', 'dir4/**/*.js'] 190 | }, 191 | } 192 | }, 193 | }); 194 | ``` 195 | 196 | #### Ignoring specific warnings 197 | 198 | If you would like to ignore a specific warning: 199 | 200 | ```shell 201 | [L24:C9] W015: Expected '}' to have an indentation at 11 instead at 9. 202 | ``` 203 | 204 | You can toggle it by prepending `-` to the warning id as an option: 205 | 206 | ```js 207 | grunt.initConfig({ 208 | jshint: { 209 | ignore_warning: { 210 | options: { 211 | '-W015': true, 212 | }, 213 | src: ['**/*.js'], 214 | }, 215 | }, 216 | }); 217 | ``` 218 | 219 | 220 | ## Release History 221 | 222 | * 2022-02-17   v3.2.0   Bump dependencies, including jshint. 223 | * 2020-10-20   v3.0.0   Bump dependencies. Switch to GitHub actions. Ensures errors in stdoutEqual callback are logged. Requires Node 10+. 224 | * 2019-03-18   v2.1.0   Bump dependencies. Update to latest JSHint 225 | * 2018-09-22   v2.0.0   Bump devDependencies. Drop Node.js < 6 support. 226 | * 2016-11-23   v1.1.0   Fix relative output Bump minor version 227 | * 2016-02-16   v1.0.0   Replace String prototype colors with chalk. Update Grunt peerDep to `>=0.4.0`. 228 | * 2016-01-17   v0.12.0   Update to JSHint ~2.9.0. 229 | * 2015-09-03   v0.11.3   Update to JSHint ~2.8.0. 230 | * 2015-04-16   v0.11.2   Fix default value of the `reporter` option. 231 | * 2015-03-20   v0.11.1   Fix io.js compatibility issues. Other fixes to pathing. 232 | * 2015-01-22   v0.11.0   Update to JSHint ~2.6.0. 233 | * 2014-04-02   v0.10.0   Update to JSHint 2.5.0. 234 | * 2014-03-12   v0.9.2   Fixes a bug where `reporterOutput` was still passed to JSHint. 235 | * 2014-03-12   v0.9.1   Don't pass `reporterOutput` option to JSHint. 236 | * 2014-03-12   v0.9.0   Replace deprecated `grunt.util._.clone` with `Object.create()`. Replace deprecated `grunt.util.hooker` with hooker lib. Enhancing the readability of the output. Reporter output is relative to the output file. Pass JSHint options to the external reporter. 237 | * 2013-12-25   v0.8.0   Update to JSHint 2.4.0. 238 | * 2013-11-16   v0.7.2   Only print file name once per error. 239 | * 2013-10-31   v0.7.1   Ability to set jshintrc option to true to use JSHint's native ability for finding .jshintrc files relative to the linted files. 240 | * 2013-10-23   v0.7.0   Update to JSHint 2.3.0. 241 | * 2013-10-23   v0.6.5   Fix output when `maxerr` is low. 242 | * 2013-08-29   v0.6.4   jshintrc now loaded by JSHint allowing comments. 243 | * 2013-08-15   v0.6.3   Fix module location for JSHint 2.1.10. 244 | * 2013-07-29   v0.6.2   Update to JSHint 2.1.7. 245 | * 2013-07-27   v0.6.1   Peg JSHint to 2.1.4 until breaking changes in 2.1.5 are fixed. 246 | * 2013-06-02   v0.6.0   Don't always succeed the task when using a custom reporter. Bump JSHint to 2.1.3. 247 | * 2013-05-22   v0.5.4   Fix default reporter to show offending file. 248 | * 2013-05-19   v0.5.3   Performance: Execute the reporter once rather than per file. 249 | * 2013-05-18   v0.5.2   Fix printing too many erroneous ignored file errors. 250 | * 2013-05-17   v0.5.1   Fix for when only 1 file is lint free. 251 | * 2013-05-17   v0.5.0   Bump to JSHint 2.0. Add support for .jshintignore files and ignores option. Add support for `extensions` option. Add support for custom reporters and output report to a file. 252 | * 2013-04-08   v0.4.3   Fix evaluation of `predef` option when it's an object. 253 | * 2013-04-08   v0.4.2   Avoid wiping `force` option when jshintrc is used. 254 | * 2013-04-06   v0.4.1   Fix to allow object type for deprecated predef. 255 | * 2013-04-04   v0.4.0   Revert task level options to override jshintrc files. 256 | * 2013-03-13   v0.3.0   Bump to JSHint 1.1.0. Add force option to report JSHint errors but not fail the task. Add error/warning code to message. Allow task level options to override jshintrc file. 257 | * 2013-02-26   v0.2.0   Bump to JSHint 1.0. 258 | * 2013-02-15   v0.1.1   First official release for Grunt 0.4.0. 259 | * 2013-01-18   v0.1.1rc6   Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions. 260 | * 2013-01-09   v0.1.1rc5   Updating to work with grunt v0.4.0rc5. Switching to `this.filesSrc` API. 261 | * 2012-10-18   v0.1.0   Work in progress, not yet officially released. 262 | 263 | --- 264 | 265 | Task submitted by ["Cowboy" Ben Alman](http://benalman.com/) 266 | 267 | *This file was generated on Thu Feb 17 2022 21:24:56.* 268 | --------------------------------------------------------------------------------