Wern Ancheta

Adventures in Web Development.

A Whirlwind Tour of Web Developer Tools: Linting

| Comments

Yo! It’s been a while but I’ve decided to continue this series on A Whirlwind Tour of Web Developer Tools. For those who don’t know, I started this series a year ago but then I got so busy with work and I became an author at Sitepoint. So you can only count the number of in-depth tutorials with your fingers. But I quit my job and now I have a lot of free-time. That is why I no longer have any excuse not to continue what I started.

Ok enough with the life update. Now let’s move on to the main topic of this article. This is part eight of the series on Web Developer Tools where I’m going to walk you through linting. Linting is the process of running a program that will check the quality of code in order to avoid any potential errors. Take for example the following code:

1
2
3
4
5
6
function main(){
  if(x == y){
    return 'Hello, World!'
  }
  return 'Hello';
}

By looking at the code, you can immediately see that x and y hasn’t been defined. The semicolon is also missing from the first return statement. But if add this function to a JavaScript file, you will see that it doesn’t actually cause any errors until you add the code that will call the function. Only then will you realize that x and y hasn’t been defined. But JavaScript doesn’t actually complain if you miss a semicolon or two so the first return statement won’t probably cause any errors. This is because of the automatic semicolon insertion in JavaScript. I know the example that I gave is a bit contrived but you get the point. As developers we sometimes miss the obvious things such as defining a variable or putting a semicolon. That is why there are tools to help us avoid making these kinds of mistakes. Linters are one of those. In the world of web development there are a bunch of tools which can be classified as linters. I’m going to walk you through some of those in this tutorial.

Markup Validation Service

The markup validation service by the World Wide Web Consortium allows developers to check the validity of the HTML code that they’ve written. It uses the doctype defined at the very top of the document as a basis for which specific rules to use for checking the code. You can supply a URL, upload a file or directly input the HTML code that you want to check. Here’s an example:

w3c validator

As you can see from the screenshot, it gives you three types of feedback: info, warning and error. Info gives you general information about the page. Warnings are messages telling you that you can do better. Or something could be improved. In the example above it says that the document uses unicode private use areas. Which is basically another way of saying that undefined unicode characters shouldn’t be used in publicly available documents. Lastly there’s the error. These are messages that tells you to fix something because it might cause problems to the users of your website. In the example above, it’s saying that an alt attribute should always be defined, except in specific conditions. And then it points out to the SVG logo of the website which should probably have an alt assigned to it. This is important because some users might be partially disabled (color-blind, partially blind, etc.) might be using a screenreader to interact with your website. And the value that you have placed in the alt attribute is read out by the screenreader. If there’s nothing there then the user won’t be able to know what he’s currently focusing at.

HTMLHint

HTMLHint is a linter for HTML code. Unlike the markup validation service, this allows you to specify what specific validation rules are to be used to check your HTML code. For example you can specify that all tags should be in lowercase. Or that in every file, an ID can only be used once. Here’s an example:

htmlhint

HTMLHint gives you feedback on which specific line has problems in it. And if you hover over the line number, you will see what the specific error is. In the example above you can see that the errors are:

  • the id a_unique_id has been used twice. It doesn’t matter that the elements used are different as long as an ID is used more than once, it triggers the error on the lines in which the ID is used for the second time.
  • the div with the ID of a_unique_id hasn’t been closed. Note that this doesn’t get triggered on the line where the tag hasn’t been closed. Instead it gets triggered on the nearest closing tag which doesn’t have a pair.

At the bottom part of the website, you can check or uncheck rules depending on what you’d like to apply. There are are a number of rules you can choose from and the naming is pretty self-explanatory so I won’t be delving into that.

CSSLint

CSSLint as the name suggests, is a linter for CSS code. Just like HTMLHint it allows you to specify which validation rules you’d like to apply for the checking of your CSS code. With CSSLint there are mostly warning rules but you can trigger errors as well. Such as when a specific rule is empty, or when using unknown CSS properties, or disallowing duplicate one’s. Warning rules on the other hand requires you to add fallback colors if you’re using hsl, rgba, rgb, or hsla to specify colors. Older browsers might not support those methods of specifying colors so you’ll have to provide a fallback in hexadecimal format. Another example is disallowing units for 0 values. This is mostly for performance benefits. Here’s an example CSS code that I’ve checked with CSSLint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
body {
    font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
    padding: 0;
    margin: 0;
    height: 100%;
    width: 100%;
}

#settings-button {
    float: right;
    margin-top: 20px;
    margin-right: 20px;
}

h1 {
    padding-left: 40px;
    display: inline-block;
}

#message {
    padding: 20px 40px;
    background: #64CF49;
}


#sidebar {
    width: 20%;
    float: left;
    background-color: #67B6DA;
    position: fixed;
    height: 100%;
}

#items-container {
    width: 80%;
    float: left;
    position: relative;
    margin-left: 20%;
    background-color: #F7F7F7;
}

ul li {
    list-style: none;
}

#sidebar h3 {
    border-bottom: 3px solid;
    padding: 0;
    padding-left: 30px;
}

#types li {
    padding: 10px 30px;
}

ul#types {
    padding: 0;
    font-size: 15px;
}

#types li a {
    text-decoration: none;
    color: #575757;
}

#items {
    padding: 0 20px;
}

#items li a {
    text-decoration: none;
    color: #3A3A3A;
    display: inline-block;
}

#items li {
    padding: 20px;
}

#items li:hover {
    background-color: #DFDFDF;
}

.item-info {
    display: inline-block;
    width: 100%;
    font-size: 15px;
    color: #8A8A8A;
    margin-top: 5px;
}

And then it showed me the following feedback:

csslint

As you can see I’ve used a lot of ID’s in this css file so CSSLint is complaining that I shouldn’t use ID’s. This is mainly because CSSLint have this idea that ID’s are completely unique and therefore there’s no room for reuse. CSSLint advocates the use of OOCSS (Object-oriented CSS) whose main principle is the reusability of code by means of using objects.

Another warning is the use of overqualified selectors:

1
2
3
ul#types{
    ...
}

It’s saying that just using #types would suffice.

The last type of warning is the heading should not be qualified warning:

1
2
3
#sidebar h3 {
    ...
}

This is because headings are considered as top-level styles. This means that you shouldn’t define their styles under a specific element. Because their appearance should be consistent throughout the entire website. Note that this is not saying that headings cannot be nested under a specific element. You can do that but when you’re declaring their styles it should be just on its own so that you can ensure that they look the same throughout the whole website.

JSHint

JSHint helps to detect errors and potential problems in your JavaScript code. It checks for undefined variables, the use of eval (we all know that eval is evil right?), unused variables and many others. In the JSHint website you can configure which rules to apply by clicking on the configure link. Here’s an example of how it works:

jshint

As you can see it provides you with some code metrics. It tells you how many functions has been defined, how many variables are not defined and how many are not used.

It also tells you the cyclomatic complexity of the largest functions. In case you’re wondering, cyclomatic complexity is just a fancy term for the complexity of a specific program. You can see that the cyclomatic complexity of the largest function that I’ve defined is 2. And the median (average) complexity of all the functions in the file is 1.5. People generally say that a cyclomatic complexity of 0 to 5 is fine. But if you get around 6 or more then you should consider refactoring your code.

Another warning that you can see in the example is the missing “use strict” statement. This is a way of telling the browser to use strict mode. I haven’t really dived into strict mode yet but the main idea is that adding this literal expression at the very top of each JavaScript file and at the very top of each function makes the browser complain more about your code. Take for example the following code:

1
2
x = "y"; //browser: sweet!
console.log(x);

Without invoking strict mode, the browser would happily execute this piece of code for you. But with strict mode it will complain that you haven’t defined x yet.

1
2
3
"use strict";
x = "y"; //browser: Uncaught ReferenceError: x is not defined
console.log(x);

Command Line Tool

HTMLHint, CSSLint, and JSHint can all be used through the command line. We’re going to take a look at how to do that in this section.

The first thing that you need to do is to install node.js and npm. But we’re not going to go through that here because I previously mentioned it in my article on package managers. Go ahead and check that out if you don’t already have node.js and npm installed.

Once you’ve installed node.js and npm, you can now install htmlhint, csslint, and jshint using npm:

1
npm install -g htmlhint csslint jshint

You can now immediately use them right after the installation is complete:

1
2
3
htmlhint index.html
csslint style.css
jshint main.js

Note that each of these tools already comes with default options. So if you were to execute each of the commands above, you will most likely get a warning or an error if your code is already complex enough. But you can also specify which rules to apply by creating a configuration file inside of your project directory.

For HTMLHint the configuration file that you have to create is .htmlhintrc and it looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
    "tagname-lowercase": true,
    "attr-lowercase": true,
    "tag-pair": true,
    "doctype-first": true,
    "tag-self-close": true,
    "attr-no-duplication": true,
    "attr-value-double-quotes": true,
    "attr-value-not-empty": false,
    "title-require": true,
    "id-unique": true,
    "inline-style-disabled": true,
    "inline-script-disabled": true,
    "doctype-html5": true,
    "alt-require": false
}

You can find the rules that you can specify in this page.

Here’s the HTMLHint cli-tool in action:

htmlhint-cli

And here’s the file that I checked:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>

</head>
<body>
    <div>
        <p id="boom"></p>
        <span id="boom"></span>
        <STRONG></STRONG>
        <strong></strong>
        <span>
        <i data href=fldsfl BOOM="bam!" style="color:red;"><b>dds</b></i>
        <div>
    </div>
</body>
</html>

For CSSLint it’s .csslintrc and it looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
  "adjoining-classes": false,
  "box-sizing": false,
  "box-model": false,
  "compatible-vendor-prefixes": false,
  "floats": false,
  "font-sizes": false,
  "gradients": false,
  "important": false,
  "known-properties": false,
  "outline-none": false,
  "qualified-headings": false,
  "regex-selectors": false,
  "shorthand": false,
  "text-indent": false,
  "unique-headings": false,
  "universal-selector": false,
  "unqualified-attributes": false
}

Note that I’ve pick up that configuration straight from bootstrap’s .csslintrc file. You can find the rules for CSSLint in this page.

Here’s CSSLint’s cli-tool in action:

csslint-cli

Here’s the stylesheet that was checked:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
body {
    font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
    padding: 0;
    margin: 0;
    height: 100%;
    width: 100%;
}

#settings-button {
    float: right;
    margin-top: 20px;
    margin-right: 20px;
}

h1 {
    padding-left: 40px;
    display: inline-block;
}

#message {
    padding: 20px 40px;
    background: #64CF49;
}


#sidebar {
    width: 20%;
    float: left;
    background-color: #67B6DA;
    position: fixed;
    height: 100%;
}

#items-container {
    width: 80%;
    float: left;
    position: relative;
    margin-left: 20%;
    background-color: #F7F7F7;
}

ul li {
    list-style: none;
}

#sidebar h3 {
    border-bottom: 3px solid;
    padding: 0;
    padding-left: 30px;
}

#types li {
    padding: 10px 30px;
}

ul#types {
    padding: 0;
    font-size: 15px;
}

#types li a {
    text-decoration: none;
    color: #575757;
}

#items {
    padding: 0 20px;
}

#items li a {
    text-decoration: none;
    color: #3A3A3A;
    display: inline-block;
}

#items li {
    padding: 20px;
}

#items li:hover {
    background-color: #DFDFDF;
}

.item-info {
    display: inline-block;
    width: 100%;
    font-size: 15px;
    color: #8A8A8A;
    margin-top: 5px;
}

Lastly there’s jshint. Here’s a sample .jshintrc file which I’ve taken from CSSLint. CSSLint is basically written in JavaScript that’s why it has its own .jshintrc file to help the developers in checking their code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
    "camelcase": true,
    "curly": true,
    "eqeqeq": true,
    "es3": true,
    "forin": true,
    "immed": true,
    "indent": 4,
    "latedef": true,
    "newcap": true,
    "noarg": true,
    "noempty": true,
    "nonbsp": true,
    "quotmark": "double",
    "strict": true,
    "undef": true,
    "unused": true
}

You can find a list of options here.

And here is JSHint’s cli tool in action:

jshint-cli

With this script file being checked:

1
2
3
4
5
6
7
"use strict";
x = "y";
console.log(x);

function beam(){
    return x + u;
}

Build Tool Integration

Ok so we have a slight improvement over just copying and pasting the code that we want to check in the HTMLHint, CSSLint, and JSHint website. But wouldn’t it be great if we don’t need to execute the command every time we need to check? And in real-world projects you would most likely have multiple css, JavaScript and HTML files. So executing the commands for each of those files would be too troublesome and time-consuming. That is where build tools comes in. Luckily I’ve already done an article specifically about build tools so if you’re new to it then be sure to check that out. Then you can go back to this article once you have an idea how to use a build tool.

Ok so you’re back. Hopefully you’ve learned all about Grunt and Gulp. In this article we’ll be using Gulp and the Gulp plugins for HTMLHint, CSSLint and JSHint. You can install those with the following command:

1
npm install gulp gulp-htmlhint gulp-csslint gulp-jshint

Optionally you can also install the formatters to make the reports more beautiful.

1
npm install htmlhint-stylish jshint-stylish

Note that there’s also a package called csslint-stylish but it currently doesn’t work with Gulp. If you’re reading this article at a later time be sure to check out that page and see if it already works for Gulp.

The next step is to create a gulpfile.js file in the root of your project directory and then add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var gulp   = require('gulp');

var htmlhint = require("gulp-htmlhint");
var csslint = require('gulp-csslint');
var jshint = require('gulp-jshint');

gulp.task('lint_html', function(){
    gulp.src("*.html")
        .pipe(htmlhint())
        .pipe(htmlhint.reporter("htmlhint-stylish"));
});

gulp.task('lint_css', function(){
  gulp.src('*.css')
    .pipe(csslint())
    .pipe(csslint.reporter());
});

gulp.task('lint_js', function(){
    gulp.src('*.js')
        .pipe(jshint())
        .pipe(jshint.reporter("jshint-stylish"));
});

gulp.task('watch', function() {
    gulp.watch('*.html', ['lint_html']);
    gulp.watch('*.css', ['lint_css']);
    gulp.watch('*.js', ['lint_js']);
});

Like I said earlier, I won’t go deep into this because I’ve already written a whole article on Build Tools. Basically what this file does is to declare all the task that we want to perform with Gulp. We have four tasks in total, one for each linter and one for watching files in a specific directory. The only task that we need to execute is the last one:

1
gulp watch

What this does is to watch all the HTML files and then execute the HTML Linter. The same is true with the other file types. The linter for each specific file type is executed once you save a file. So if you press ctrl + s on your keyboard, the task is immediately executed. What you can do is you can either switch windows (alt + tab) or put the command line window and your text-editor side by side so you get instant feedback on your code.

Text-editor Integration

For the final part we’re going to look at how to integrate the linting tools in the text-editor. I’m a Sublime Text user so I’ll be using it for the examples. But if you’re using another text-editor or IDE be sure to check out if these tools are also available.

The first thing that you need to do is to install the SublimeLinter plugin with Sublime Package Control.

Once installed, determine where HTMLHint, CSSLint, and JSHint are installed in your computer. In Ubuntu you can do something like:

1
2
3
which htmlhint
which csslint
which jshint

That will return the path to the executable file. For me it was /home/wern/.nvm/v4.0.0/bin/csslint for csslint. Note that csslint in that path is the executable file itself. So the path that you actually want is /home/wern/.nvm/v4.0.0/bin. It returned the same path for HTMLHint and JSHint for me so I only need that one path. Once you’ve found it, go ahead and copy that path.

Next open Sublime Text, click on the preferences menu > package settings > SublimeLinter > Settings – User. This opens the user configuration file for SublimeLinter. Add the following into it and then save.

1
{}

Open the file again by going through the same steps above. This time Sublime Text has already added the default configurations in there. What you need to do now is to look for the paths object and under your current operating system at the path to where the HTMLHint, CSSLint and JSHint executables are. Because I’m using Ubuntu I had to put it inside linux object.

1
2
3
4
5
6
7
"paths": {
    "linux": [
        "/home/wern/.nvm/v4.0.0/bin"
    ],
    "osx": [],
    "windows": []
},

Once you’re done, save the file then restart Sublime Text (close it and open again).

Open the Sublime Text console by pressing ctrl + ` then look for something similar to the following:

1
2
3
SublimeLinter: htmlhint activated: /home/wern/.nvm/v4.0.0/bin/htmlhint
SublimeLinter: jshint activated: /home/wern/.nvm/v4.0.0/bin/jshint
SublimeLinter: csslint activated: /home/wern/.nvm/v4.0.0/bin/csslint

This tells you that SublimeLinter has successfully picked up the paths to where the linters are installed. If you’re seeing that then you’re good to go, if not then be sure to check if the path that you’ve supplied really contains the executable code for each of those linters.

Here are some screenshot that shows the linters in action:

htmlhint text editor

csslint text editor

jshint text editor

The yellow dots indicates warnings, while the red dots indicate errors. If you move your cursor over to the line where a dot is, you can see the actual message on the status bar (bottom left corner of the screen). Pretty sweet right?

Conclusion

That’s it! In this article you’ve learned how to use some of the tools that you could use to help you with determining potential problems in your HTML, CSS and JavaScript code. You’ve also learned how to integrate this into your workflow by making use of the command-line tool or the text-editor integration.

Resources

Comments