I’ve been looking for a way to enforce naming conventions for a while. Last night I finally got to testing how this could be done with CSSLint. It turns out this is pretty easy if you know Javascript.

First you have to download the zip file from Github. In it you’ll find a src folder. All the rules are in the … you guessed it, rules folder.

For my first rule, I wanted to check that all class names used dash (-) instead of underscore(_). I started out from one of the other rules, “adjoining classes”.

/*global CSSLint*/
/*
 * Rule: Don't use adjoining classes (.foo.bar).
 */
CSSLint.addRule({

    //rule information
    id: "adjoining-classes",
    name: "Disallow adjoining classes",
    desc: "Don't use adjoining classes.",
    browsers: "IE6",

    //initialization
    init: function(parser, reporter){
        var rule = this;
        parser.addListener("startrule", function(event){
            var selectors = event.selectors,
                selector,
                part,
                modifier,
                classCount,
                i, j, k;

            for (i=0; i < selectors.length; i++){
                selector = selectors[i];
                for (j=0; j < selector.parts.length; j++){
                    part = selector.parts[j];
                    if (part.type == parser.SELECTOR_PART_TYPE){
                        classCount = 0;
                        for (k=0; k < part.modifiers.length; k++){
                            modifier = part.modifiers[k];
                            if (modifier.type == "class"){
                                classCount++;
                            }
                            if (classCount > 1){
                                reporter.report("Don't use adjoining classes.", part.line, part.col, rule);
                            }
                        }
                    }
                }
            }
        });
    }

});

I updated the code to the version below.

/*
 * Rule: test naming conventions: no underscores in classnames
 */
/*global CSSLint*/
CSSLint.addRule({

    //rule information
    id: "namingconventions-nounderscore",
    name: "Disallow classes with underscores",
    desc: "classnames should use dash instead of underscore",
    browsers: "All",

    //initialization
    init: function(parser, reporter){
        var rule = this;

        parser.addListener("startrule", function(event){
            var selectors = event.selectors,
                selector,
                part,
                modifier,
                i, j, k;

            for (i=0; i < selectors.length; i++){
                selector = selectors[i];
                for (j=0; j < selector.parts.length; j++){
                    part = selector.parts[j];
                    if (part.type == parser.SELECTOR_PART_TYPE){
                        for (k=0; k < part.modifiers.length; k++){
                            modifier = part.modifiers[k];
                            if (modifier.type == "class"){
                                if (/[^\.A-Za-z0-9-]/.test(modifier)){
                                    reporter.report("Classnames should follow naming conventions: only alphanumeric and dashes!", modifier.line, modifier.col, rule);
                                }
                            }

                        }
                    }
                }
            }
        });
    }

});

After this you also have to create a file with the same name in the tests folder. After updating the tests to your rule set, you need to build a new version.
Building is done with Ant so, you go to the root of your folder and run Ant.

In my case (I’m using CSSLInt with node.js) I just copied csslint-master/build/npm/lib/csslint-node.js file over the version in /usr/local/lib/node_modules/csslint/lib/. All was working as expected.

I’m curious if JSLint/JSHint can be used this way as well.

Leave a Reply

Your email address will not be published. Required fields are marked *