Search code examples
htmlgulphtmllint

Prevent gulp-htmllint from skipping invalid html files


I'm using gulp-htmllint to check files with html fragments. However, to my surprise, it skips files with invalid markup. I'd love to get "as good as possible" linting, but at the very least I want it to fail / report an error on invalid html.

Here's a repro. First the gulpfile.js (requires appropriate npm install commands beforehand):

var gulp = require("gulp"),
    gutil = require('gulp-util'),
    htmllint = require("gulp-htmllint"), 
    path = require('path');

gulp.task("default", [], function() {
    return gulp.src("src/*.html")
        .pipe(htmllint({}, reporter));
});

function reporter(filepath, issues) {
    var filename = path.basename(filepath);
    if (issues.length > 0) {
        issues.forEach(function (issue) {
            gutil.log(gutil.colors.cyan('[lintHtml] ') + gutil.colors.white(filename + ' [' + issue.line + ',' + issue.column + ']: ') + gutil.colors.red('(' + issue.code + ') ' + issue.msg));
        });
        process.exitCode = 1;
    }
}

The reporter is based off the example on the package's home page.

With this src/fragment.html file:

<span style="color: red;">Test 1.</span>
<span style="color: green;">Test 2.</span>

I'll nicely get:

[08:04:06] Using gulpfile ~\myapp\gulpfile.js
[08:04:06] Starting 'default'...
[08:04:06] [lintHtml] fragment.html [1,6]: (E001) the `style` attribute is banned
[08:04:06] [lintHtml] fragment.html [2,6]: (E001) the `style` attribute is banned
[08:04:06] Finished 'default' after 38 ms

But, if I make the html file invalid like so:

<span style="color: red;"Test 1.</span>
<span style="color: green;">Test 2.</span>

I get:

[08:05:06] Using gulpfile ~\myapp\gulpfile.js
[08:05:06] Starting 'default'...
[08:05:06] Finished 'default' after 25 ms

As if there's nothing wrong.

How do I get the process to report errors and fail when my fragment has such a problem?

PS. I ended up cross-posting to Github as an issue too.


Solution

  • There's no way to do this without changes to gulp-htmllint itself. If you look at the source you see that it only provides a success handler to the htmllint promise:

    lint.then(function(issues) {
        issues.forEach(function(issue) {
            issue.msg = issue.msg || htmllint.messages.renderIssue(issue);
        });
        reporter(file.path, issues);
    });
    

    To output cases where the linting process fails because of invalid html, it would have to provide a reject handler as well:

    lint.then(function(issues) {
        issues.forEach(function(issue) {
            issue.msg = issue.msg || htmllint.messages.renderIssue(issue);
        });
        reporter(file.path, issues);
    }).catch(function(error) {
        //do something useful here
        console.log(file.path + ': ' + error.toString());
    });
    

    That means you have two options: