jshint is an awesome tool. It finds undeclared variables, missing semicolons, functions that are too complex and other potential problems in your JavaScript. It is extremely easy to setup jshint to run on file changes, pre-commit or inside your text editor as your program.
With the rise of server-side templating, a lot of projects include JavaScript code inside html files. The js code inside HTML or any other template language is usually NOT linted. At some point I even created a tool called dirty-water to measure number of JS lines inside EJS templates. Once one has a number, one can drive it down, for example by switching to AngularJs ;)
jshint CLI tool
Turns out, the current stable version of jshint (>2.4 released in December of 2013) has a command-line option --extract that allows to strip HTML and lint the remaining JavaScript code. You can read the official announcement, and here is an example index.html
1 |
|
1 | $ jshint --extract=auto index.html |
The parser replaced HTML with blank lines, the linting errors thus have correct line numbers.
The --extract option has 3 values:
- default: no extraction, tries to parse each file as JavaScript code
- always: always strips HTML tags
- auto: looks at the start of the file, checking if it starts with an opening angular bracket <.
grunt-contrib-jshint
I usually do not run jshint directly from command line, using grunt-contrib-jshint instead. Recently, this grunt plugin added support for extract option, passing it to the jshint cli, see source fragment. Unfortunately this version (0.9.0-pre) has not been published to NPM yet, if you would like to lint js inside your html files today, you could use the latest plugin directly from github. In your package.json specify the repo url instead of the version
"devDependencies": {
"grunt": "~0.4.2",
"grunt-contrib-jshint": "git://github.com/gruntjs/grunt-contrib-jshint.git"
}
I suggest using separate sets of settings to lint your server-side (Node) and browser code. A sample Gruntfile.js can easily set this up:
1 | /* global module, require */ |
1 | $ grunt |
As always I am using jshint-stylish as a reporter.
Indentation problem
If you set jshint to check the indentation, the indentation is confused by the default script code offset, for example:
1 |
|
generates errors:
$ jshint --extract=auto index.html
index.html: line 6, col 5, Expected 'var' to have an indentation at 1 instead at 5.
This is due to the HTML tag stripping: it literally removes everything but JavaScript, leaving the block of code offset in the otherwise empty file. If we print the intermediate result, the linter is looking at this code:
|
| /*jshint indent:2 */
| var foo = 'foo';
I forked jshint and added stripping leading offset from the JavaScript code extracted from HTML. Each js fragment will be offset by the amount of leading whitespace from the first line. In the previous example, the output js fragment would be
|
|/*jshint indent:2 */
|var foo = 'foo';
which passes jshint.
Update
My pull request made its way into jshint 2.4.4. Now you can check the white space in JavaScript inside HTML!