0

so I have a fairly decent sized code base which is using less (many files). I want to convert the css to use BEM (actually a variant of BEM) and I would love to find a gulp way to lint the less files including naming conventions.

Is there any way to do this?

So basically I would like all the default css lint stuff and additionally define naming conventions that may not be broken.

E.g. classes need to start with c-, u- or o-, other classes are not permitted.

Lukas Oppermann
  • 2,918
  • 6
  • 47
  • 62
  • I'd rather think this is a problem, I am not asking which tool is best for it, I am wondering how to solve this problem of validating my syntax using gulp. I don't see how answers will be opinionated, since its a "how to" question. – Lukas Oppermann Mar 12 '15 at 16:00
  • Is this a one time solution to convert your existing LESS to be BEM compliant or do you want Gulp to go through your LESS/CSS and confirm it's BEM compliant? – allejo Mar 12 '15 at 18:25
  • I want it to confirm it, not one time, but all the time, while developing. Also to help remind others to stick to the rules. :) – Lukas Oppermann Mar 12 '15 at 20:33
  • can't you use https://github.com/necolas/postcss-bem-linter? – Bass Jobsen Mar 12 '15 at 21:34

1 Answers1

2

If postprocessors like https://github.com/necolas/postcss-bem-linter won't work for you for some reason. You can write your own, or possible create a Less Plugin. Less plugin can be visitors or postprocess, which can be used by you.

E.g. classes need to start with c-, u- or o-, other classes are not permitted.

Example of a visitor plugin that checks the above requirement:

 <!DOCTYPE html>
 <html>
 <head>
 <title>BEM Validation</title>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link type="text/css" href="bem.less" rel="stylesheet/less">
<script>
var ValidateBEM = function(less) {
    this._visitor = new less.visitors.Visitor(this);
};
ValidateBEM.prototype = {
    isReplacing: true,
    run: function (root) {
    return this._visitor.visit(root);
    },
    visitRuleset: function (rulesetNode, visitArgs) {
        console.log(visitArgs);
        if(rulesetNode.selectors) {

        for (var i = 0; i < rulesetNode.selectors.length; i++) {

            if(rulesetNode.selectors[i].elements[0].value.match(/^\./)){


                if(!rulesetNode.selectors[i].elements[0].value.match(/^\.[cuo]-/))
                {
                console.log(rulesetNode.selectors[i].elements[0]);
                throw { type: 'BEM Validation',
                message: "class names should start with c-, u- or o-",
                filename: rulesetNode.selectors[i].elements[0].currentFileInfo.filename,
                index: rulesetNode.selectors[i].elements[0].index };
                }   

            }   
        }

        }   

        return rulesetNode;
    }
};

var ValidateBEMPlugin = {
    install: function(less, pluginManager) {
        pluginManager.addVisitor(new ValidateBEM(less));
    }
}; 

less = { 
    env: "development",
    plugins: [ValidateBEMPlugin]
};
</script> 
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/2.4.0/less.min.js"></script>

</head> 
<body>
<header>
    <h1>header</h1>
</header>




</body>
</html>

When bem.less contains the following class:

.class {
t:test;
}

in above will result in the error like that shown beneath:

enter image description here

Grunt-contrib-less allows you to use Less Plugin too:

less: {
  production: {
    options: {
      paths: ["assets/css"],
      plugins: [
        new (require('less-plugin-bem'))({browsers: ["last 2 versions"]}),
      ] }
}
}

The plugin used above only works in browser, see How to exend the Less compiler with a custom function leveraging a plugin how to create a CLI version.

Community
  • 1
  • 1
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224