code prettify

Showing posts with label npm. Show all posts
Showing posts with label npm. Show all posts

Friday, 12 February 2016

Associating git hooks with js syntax check

This is a followup article from my previous post.


Here we will be using git pre-commit to check for syntax error while committing in JavaScript files.

We will need nodejs in our system. Please check https://nodejs.org/en/ for downloading and install steps.

Note: I am using ubuntu 14.04 for this setup.

Steps to add pre-commit JavaScript syntax check with git:

1. Use npm to install jslint package globally in your system.

https://www.npmjs.com/package/jslint

$ npm install -g jslint

This should globally install jslint in your system and can be referenced as below to check syntax error for any js file.

$ jslint sample.js

for (i = 0; i < 10; i++)
{
        sum += i;
}

Sample output from above command:
sample.js
 #1 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 6
 #2 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 13
 #3 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 21
 #4 Unexpected '++'.
    for (i = 0; i < 10; i++) // Line 1, Pos 22
 #5 Expected exactly one space between ')' and '{'.
    { // Line 2, Pos 1
 #6 Use spaces, not tabs.
    sum += i; // Line 3, Pos 1
 #7 Expected 'sum' at column 9, not column 2.
    sum += i; // Line 3, Pos 2
 #8 'i' was used before it was defined.
    sum += i; // Line 3, Pos 9
 #9 Expected '}' at column 5, not column 1.
    } // Line 4, Pos 1

Above info is quite informative and helpful to fix basic syntax errors, missing semi-colons, indentation etc.

Correcting the above errors to below code and running jslint again:

var i, sum = 0;

for (i = 0; i < 10; i = i + 1) {
    sum += i;
}

Output from jslint:

sample.js is OK.

Note: Please also refer rules and standards being followed by jslint for checking here. Makes a nice read. :)

2. Now that jslint is globally available, let us use it and create a pre-commit file.
I found below links which highlight the use of it in a script:

http://stackoverflow.com/questions/15703065/setup-pre-commit-hook-jshint
http://dev.venntro.com/2012/11/maintaining-consistent-javascript-with-jslint/

The only disadvantage I see in the script is that it only highlights passed and failed JavaScript files with names and does not specify the error in each.

So, I made a few changes to the script as below (highlighted in blue):

#!/bin/sh

files=$(git diff --cached --name-only --diff-filter=ACM | grep "\.js$")
if [ "$files" = "" ]; then
    exit 0
fi

pass=true

ERRORS_BUFFER=""

echo -e "\nValidating JavaScript:\n"

for file in ${files}; do
    result=$(jslint ${file} | grep "${file} is OK")
    if [ "$result" != "" ]; then
        echo -e "\t\033[32mJSLint Passed: ${file}\033[0m"
    else
        ERRORS=$(jslint ${file})
        ERRORS_BUFFER="$ERRORS_BUFFER\n$ERRORS"
        echo -e "\t\033[31mJSLint Failed: ${file}\033[0m"
        pass=false
    fi
done

echo -e "\nJavaScript validation complete\n"

if ! $pass; then
    echo -e "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again."
    echo -e $ERRORS_BUFFER
    echo 
    exit 1
else
    echo -e "\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi

3. Save the above script in your git pre-commit file as below:

$ cd /project/directory/
$ vim .git/hooks/pre-commit

Paste the above content and save it. Then give execute permission to it.

$ chmod +x .git/hooks/pre-commit

And we are done and ready :)

Trying a sample case:

I have two js files named sample.js and another.js with below content:

sample.js:

var i = j;

for (key in names) {
    echo names[key];

}

another.js:

var i = []

Lets try to commit them:

$ git commit -m 'Error Commit' sample.js another.js

Below is the pre-commit check output:

Validating JavaScript:

JSLint Failed: sample.js
JSLint Failed: true.js

JavaScript validation complete

COMMIT FAILED: Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again.

 sample.js #1 'j' was used before it was defined. var i = j; // Line 1, Pos 9 #2 'key' was used before it was defined. for (key in names) { // Line 3, Pos 6 #3 Cannot read property 'kind' of undefined // Line 3, Pos 10

 true.js #1 Expected ';' and instead saw '(end)'. var i = [] // Line 1, Pos 11

The output can be formatted a little bit better to place each line error in a new line of its own. But this simple tool is pretty handy for checking js errors while committing :)