Running JSLint with Node

As part of some recent work on an open source project, I’ve been tinkering with node.js. When starting a new javascript project, I like to set up tools like JS Lint early on, since fixing lots of errors later is tedious. I wanted a simple script to run it within node – searching the interwebz revealed a couple of options to run on a single file, so I adapted a couple to do what I wanted.

The result is on github and below – I added just one line to the Crockford script:

exports.JSLINT = JSLINT;

The jslint-runner file sets up options and hooks into node, then loops through all the files in a directory and lints them one by one. It’s not recursive (I didn’t want it to be) but that could be easily added in. The predefinitions include jasmine keywords.


var options = {
    node: true,
    predef: [
            "jasmine",
            "describe",
            "it",
            "expect",
            "beforeEach"
    ]
};

var ANSIColors = {
  pass:    function() { return '\033[32m'; }, // Green
  fail:    function() { return '\033[31m'; }, // Red
  neutral: function() { return '\033[0m';  }  // Normal
};

var stringWithColor = function(str, color) {
    return (color || ANSIColors.neutral()) + str + ANSIColors.neutral();
  }

var fs = require('fs'),
        sys = require('sys'),
        dirName = process.argv[2],
        readFile = function (name) {
            return fs.readFileSync(name).toString();
        },
        print = function (message) {
            sys.puts(message);
        },
        quit = function (code) {
            process.exit(code)
        },
        jslint = require('./jslint');


if (!dirName) {
    print("Usage: jslint.js directory");
    quit(1);
}

fs.readdir(process.cwd() + "/" + dirName, function(err, list) {
    list.forEach(function (file) {
        var fileExtension = file.substr(file.length - 3);
        if (fileExtension === ".js") {
            doLint(dirName + "/" + file);
        }
    });
});

var doLint = function(fileName) {
    var e,i,input;
    input = readFile(fileName);
    if (!input) {
        print(stringWithColor("jslint: Couldn't open file '" + fileName + "'.", ANSIColors.fail()));
        quit(1);
    }
    if (!jslint.JSLINT(input, options)) {
        print(stringWithColor("Problems in " + fileName, ANSIColors.fail()));
        for (i = 0; i < jslint.JSLINT.errors.length; i += 1) {
            e = jslint.JSLINT.errors[i];
            if (e) {
                print('Lint at line ' + e.line + ' character ' +
                        e.character + ': ' + e.reason);
                print((e.evidence || '').replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"));
                print('');
            }
        }
    } else {
        print(stringWithColor("jslint: No problems found in " + fileName, ANSIColors.pass()));
    }
};


Whoops!

In the middle of a busy summer that involved moving out of my flat in London, trying to plan a move to Australia, and taking in an obscene amount of beer and comedy at the Edinburgh Festival, I lost my blog. But it’s coming back, shortly.

Apologies to my (very few) commenters, I don’t think I can restore those. However, I do plan to restore some very old posts from my original Spike the Poodle blog, tales from my very first steps with Scrum, so that might be fun. There, I’ve said it. Now I have to do it.