Fork me on GitHub

Running JSLint in Automated Build Scripts

At VendAsta we use automated build scripts and a TeamCity server for continuous integration. Whenever someone commits code to a project, a whole suite of automated build targets are run against the code base to check things like unit tests, python syntax (via pylint) and code coverage. One thing that was missing from the mix was the automated running of jslint to check the syntax of our ever-increasing corpus of JavaScript code. As it turns out, adding this to our ANT targets wasn’t all that difficult.

The only real difficulty you are likely to encounter in creating a JSLint target for your build scripts is that JSLint is, itself, written in JavaScript. Other helpful libraries such as JSMin or the YUICompressor from Yahoo are distributed as jar files and can be executed easily with an exec block with the executable set to java. With JSLint, however, you are going to need a JavaScript engine which you can execute from the command line in order to run the JSLint script to validate your JavaScript code. This actually sounds harder than it is.

For our implementation, I chose to use the Rhino engine since there is documented support for JSLint on it, and even a handy helper file to include in your system: rhino.js. Grab a copy of Rhino (the actual file you’ll want to include is js.jar), the Rhino helper script I just mentioned and JSLint itself. Place them all together into some sort of tools directory in your project. Ours is located in /tools/ant.

Now comes the fun part, writing the actual target in ANT. For our purposes, we want to process all .js files contained in a particular location, as defined in a build property called jsdir. We also want to ignore any files that are contained in a vendor subdirectory of jsdir, as we should not need to worry about third-party scripts that don’t pass JSLint. Let’s get things started with our basic, empty target:

Listing 1: The basic, empty jslint file

1
2
3
4
5
6
<!--
jslint - Runs lint checks on js files
-->
<target name="jslint">

</target>

Within the target there are two things we are going to need. First a way to reference all of the files we want to operate over and second, the actual call to run JSLint on those files. For the first requirement we’ll use a pathconvert tag with a nested fileset. The pathconvert will allow us to generate a space-separated list of files and stuff that into a property which we’ll call jsfiles. The fileset block will do the actual work of finding the files in question. It will operate over ${jsdir} including all .js files and excluding all .js files in the vendor subdirectory. Listing 2 shows the pathconvert block added to our empty target.

Listing 2: The pathconvert block added to our target

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!--
jslint - Runs lint checks on js files
-->
<target name="jslint">
    <pathconvert pathsep=" " property="jsfiles">
        <fileset dir="${jsdir}">
            <include name="**/*.js"/>
            <exclude name="vendor/**/*.js"/>
        </fileset>
    </pathconvert>
</target>

Finally, it is time to add the actual call to JSLint. To allow our build scripts to work for multiple projects, we have pushed as much information into properties that get defined in project-specific files as possible. The location of the Rhino jar (js.jar) is placed into the property js.jar and the location of the JSLint script (jslint.js) is placed into the property jslint.js. With those properties suitably defined elsewhere, we have the final piece of our puzzle: the exec block. We have the executable set to java and failonerror set to true, so that our target will appropriately fail when JSLint fails to give our code a passing grade. The final target, including the exec block can be seen in listing 3.

Listing 3: The final target

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!--
jslint - Runs lint checks on js files
-->
<target name="jslint">
    <pathconvert pathsep=" " property="jsfiles">
        <fileset dir="${jsdir}">
            <include name="**/*.js"/>
            <exclude name="vendor/**/*.js"/>
        </fileset>
    </pathconvert>
    <exec dir="${jsdir}" executable="java" failonerror="true">
        <arg line="-jar ${js.jar} ${jslint.js} ${jsfiles}"/>
    </exec>
</target>

Put all together, the pathconvert block stuffs the list of files to work on into the property ${jsfiles} which is then passed as an argument to the jslint.js file. The jslint.js file is itself the first argument passed to the Rhino JavaScript engine (js.jar) which is run directly by java. Running your ant jslint target should give you some nice feedback on the syntax of your JavaScript code.

Comments !

About

Jeffery Read is a Python developer with over a decade of professional development experience. He lives in Saskatoon, SK, Canada.