Ned Batchelder just wrote about checking javascript syntax in Django, so I figured it was about time to document how I use jslint:
Jslint can be run and configured in the browser by copy/pasting your code into http://www.jslint.com/ . Now, that’s not a thing you want to do after every javascript change, right? So there’s also a command line version for Rhino. Rhino is a command line javascript runner.
On debian/ubuntu, just do aptitude install rhino and download the jslint.js file. You don’t need to type the lengthly commandline on that jslint page: on ubuntu you can just type rhino path/to/jslint.js path/to/your.js. Beware: as far as I could see, it did not accept multiple javascript files to test, so testing *.js will in fact only test the first one.
This led me to write a small python script that calls rhino with jslint and does some directory walking to find javascript files and calls jslint on all of them:
#!/usr/bin/python
# Place this file somewhere as ``jslint`` (preferrably
# without the .py) and make it executable. Place a
# downloaded jslint.js in the same directory.
import os
import commands
import sys
RHINO = 'rhino' # "aptitude install rhino" on ubuntu.
JSLINT = os.path.abspath(os.path.join(
os.path.dirname(__file__), 'jslint.js'))
def main():
if not len(sys.argv) > 1:
print "Usage: jslint script1.js [script2.js...]"
print " or: jslint directory"
sys.exit(1)
javascript_files = sys.argv[1:]
if len(javascript_files) == 1:
possible_dir = javascript_files[0]
if os.path.isdir(possible_dir):
javascript_files = []
for (dirpath, dirnames, filenames) in os.walk(
possible_dir):
javascript_files += [
os.path.join(dirpath, filename)
for filename in filenames
if filename.endswith('.js')]
for javascript_file in javascript_files:
(status, output) = commands.getstatusoutput(
' '.join([RHINO, JSLINT, javascript_file]))
if status == 0:
# Success!
print "%s is OK" % javascript_file
else:
print "Error checking %s" % javascript_file
print "exit code:", status
print output
sys.exit(status)
sys.exit(0)
if __name__ == '__main__':
main()
Jslint is pretty picky, so you need to tame it a bit. Most common things you need to do:
You do that by adding a few comment lines to the top of your javascript file, like this:
// jslint configuration; btw: don't put a space before 'jslint' below.
/*jslint browser: true */
/*global $, OpenLayers, window, updateLayer */
Some of the things that jslint enforces:
The last thing is to add jslint checking to Hudson. Continuous integration should also mean continuous checking of your javascript code. I just added a manual “shell” step that calls the above jslint-running python script with the correct path. The script does a sys.exit() with a non-zero value if something goes wrong, so if you return that exit code to hudson, hudson will treat it as a full-blown test failure.
It really helped me to get a good feeling about the health of my javascript files!
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):