diff --git a/src/cli/common.js b/src/cli/common.js index c86c80b7..bd004d7d 100644 --- a/src/cli/common.js +++ b/src/cli/common.js @@ -59,7 +59,7 @@ function cli(api){ if (ignore) { ruleset = CSSLint.getRuleset(); ignore.split(",").forEach(function(value){ - delete ruleset[value]; + ruleset[value] = 0; }); } diff --git a/src/core/CSSLint.js b/src/core/CSSLint.js index 56e49ead..6fd28279 100644 --- a/src/core/CSSLint.js +++ b/src/core/CSSLint.js @@ -7,10 +7,11 @@ /*global parserlib, Reporter*/ var CSSLint = (function(){ - var rules = [], - formatters = [], - api = new parserlib.util.EventTarget(); - + var rules = [], + formatters = [], + embeddedRuleset = /\/\*csslint([^\*]*)\*\//, + api = new parserlib.util.EventTarget(); + api.version = "@VERSION@"; //------------------------------------------------------------------------- @@ -34,18 +35,18 @@ var CSSLint = (function(){ api.clearRules = function(){ rules = []; }; - + /** * Returns the rule objects. * @return An array of rule objects. * @method getRules */ api.getRules = function(){ - return [].concat(rules).sort(function(a,b){ + return [].concat(rules).sort(function(a,b){ return a.id > b.id ? 1 : 0; }); }; - + /** * Returns a ruleset configuration object with all current rules. * @return A ruleset object. @@ -55,14 +56,49 @@ var CSSLint = (function(){ var ruleset = {}, i = 0, len = rules.length; - + while (i < len){ ruleset[rules[i++].id] = 1; //by default, everything is a warning } - + return ruleset; }; + /** + * Returns a ruleset object based on embedded rules. + * @param {String} text A string of css containing embedded rules. + * @param {Object} ruleset A ruleset object to modify. + * @return {Object} A ruleset object. + * @method getEmbeddedRuleset + */ + function applyEmbeddedRuleset(text, ruleset){ + var valueMap, + embedded = text && text.match(embeddedRuleset), + rules = embedded && embedded[1]; + + if (rules) { + valueMap = { + "true": 2, // true is error + "": 1, // blank is warning + "false": 0, // false is ignore + + "2": 2, // explicit error + "1": 1, // explicit warning + "0": 0 // explicit ignore + }; + + rules.toLowerCase().split(",").forEach(function(rule){ + var pair = rule.split(":"), + property = pair[0] || "", + value = pair[1] || ""; + + ruleset[property.trim()] = valueMap[value.trim()]; + }); + } + + return ruleset; + } + //------------------------------------------------------------------------- // Formatters //------------------------------------------------------------------------- @@ -76,7 +112,7 @@ var CSSLint = (function(){ // formatters.push(formatter); formatters[formatter.id] = formatter; }; - + /** * Retrieves a formatter for use. * @param {String} formatId The name of the format to retrieve. @@ -86,7 +122,7 @@ var CSSLint = (function(){ api.getFormatter = function(formatId){ return formatters[formatId]; }; - + /** * Formats the results in a particular format for a single file. * @param {Object} result The results returned from CSSLint.verify(). @@ -99,16 +135,16 @@ var CSSLint = (function(){ api.format = function(results, filename, formatId, options) { var formatter = this.getFormatter(formatId), result = null; - + if (formatter){ result = formatter.startFormat(); result += formatter.formatResults(results, filename, options || {}); result += formatter.endFormat(); } - + return result; }; - + /** * Indicates if the given format is supported. * @param {String} formatId The ID of the format to check. @@ -144,16 +180,20 @@ var CSSLint = (function(){ // normalize line endings lines = text.replace(/\n\r?/g, "$split$").split('$split$'); - + if (!ruleset){ ruleset = this.getRuleset(); } - + + if (embeddedRuleset.test(text)){ + ruleset = applyEmbeddedRuleset(text, ruleset); + } + reporter = new Reporter(lines, ruleset); - + ruleset.errors = 2; //always report parsing errors as errors for (i in ruleset){ - if(ruleset.hasOwnProperty(i)){ + if(ruleset.hasOwnProperty(i) && ruleset[i]){ if (rules[i]){ rules[i].init(parser, reporter); } @@ -170,9 +210,10 @@ var CSSLint = (function(){ report = { messages : reporter.messages, - stats : reporter.stats + stats : reporter.stats, + ruleset : reporter.ruleset }; - + //sort by line numbers, rollups at the bottom report.messages.sort(function (a, b){ if (a.rollup && !b.rollup){ @@ -182,8 +223,8 @@ var CSSLint = (function(){ } else { return a.line - b.line; } - }); - + }); + return report; }; diff --git a/tests/core/CSSLint.js b/tests/core/CSSLint.js index 7486dc0f..08166fb0 100644 --- a/tests/core/CSSLint.js +++ b/tests/core/CSSLint.js @@ -15,6 +15,17 @@ "@media (max-width:400px) should not cause an error": function(){ var result = CSSLint.verify("@media (max-width:400px) {}", { }); Assert.areEqual(0, result.messages.length); + }, + + "Embedded ruleset should be honored": function(){ + var result = CSSLint.verify("/*csslint bogus, adjoining-classes:true, box-sizing:false */\n.foo.bar{}", { + 'text-indent': 1, + 'box-sizing': 1 + }); + + Assert.areEqual(2, result.ruleset['adjoining-classes']); + Assert.areEqual(1, result.ruleset['text-indent']); + Assert.areEqual(0, result.ruleset['box-sizing']); } }));