rake jslint

JSLint is one of the most valuable tools for a JavaScript developer. Short of being a “compiler”, it’s a “code quality tool” that can keep you from doing things that may come back to haunt you in the future. I’ll leave the detailed explanation to the author, Douglas Crockford - I assume you’re reading this because you want to integrate jslint into your Rails project and run it on the command-line!

To run jslint as a rake task in your Rails project, you’ll only need a few things:

  • the Java runtime
  • Rhino, the java-based javascript runtime environment
  • jslint itself
  • a rake task to invoke it

So let’s get it set up. First, the java. Drop into a shell on your development system (or build system, wherever you want to run jslint), and make sure you have access to the java runtimes (run java -v, or which java). If not, go get it. Don’t be afraid, it’s easy.

Next you’ll need Rhino, the javascript execution environment. There are many js implementations (spidermonkey/treemonkey, v8, etc), but Rhino is the one that Crockford chose when he wrote the extension to jsunit that loads a file to be parsed. Its a jar file, go get it and put it into your project as vendor/rhino.jar.

Now you need Crockford’s jslint code. There are two parts: one is jslint.js, and the other is the Rhino extension (rhino.js). We will need both of these, and I’ve found it’s easiest when they are combined into one. Concatenate rhino.js to the bottom of jslint.js and save as vendor/jslint.js.

Hey, we’re almost there! Now you just have to add the rake task to your project.

desc "Check the JavaScript source with JSLint - exit with status 1 if any of the files fail."
task :jslint do
  failed_files = []
  classpath = File.join(RAILS_ROOT, "vendor", "rhino.jar")
  jslint_path = File.join(RAILS_ROOT, "vendor", "jslint.js")
  Dir['public/**/*.js'].reject{|path| path =~ /public\/ext\//}.each do |fname|
    cmd = "java -cp #{classpath} org.mozilla.javascript.tools.shell.Main #{jslint_path} #{fname}"
    results = %x{#{cmd}}
    unless results =~ /^jslint: No problems found in/
      puts "#{fname}:"
      puts results
      failed_files << fname
    end
  end
  if failed_files.size > 0
    exit 1
  end
end

Drop this code into an existing Rakefile, or rake task. If you don’t have any rake tasks, then simply save this as lib/tasks/jslint.rake. Rake will find it in your project automatically. Run rake -T to confirm.

A short explanation: it finds all the js files you want to inspect, and runs jslint on them one at a time, printing out failures. Line 6 is the key line - you can change two parts of this to suit your project. First, the list of files to check is created using a Dir glob. My example gets all *.js files under /public recursively (**). Then the second part of that line is used to reject js files you DO NOT want to inspect. Frameworks, 3rd party code, for example (although it can be fun to run jslint on your framework code to see their level of quality). This example excludes the ExtJS installation.

Now youre ready to run

rake jslint

and enjoy the benefits of quality-checking your JavaScript code! And since you’ve just built a rake task that returns 0 or 1, it can be easily integrated into you automated or continuous build process. Heh heh - now the build will fail and everyone will know who doesn’t use triple-effing-equals! (see slide 13 of Naked JavaScript)

Enjoy command-line jslint. And if you develop using TextMate, I highly recommend integrating jslint into that as well.

(I’ve been thinking and talking about this for too long. Inspiration to finally get command-line jslint set up came from reading this stackoverflow earlier today.)