Skip to content

Commit 9ffc29e

Browse files
Added support for embedded rulesets. Resolves #336.
1 parent ea19b92 commit 9ffc29e

File tree

2 files changed

+83
-21
lines changed

2 files changed

+83
-21
lines changed

src/core/CSSLint.js

+72-21
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
/*global parserlib, Reporter*/
88
var CSSLint = (function(){
99

10-
var rules = [],
11-
formatters = [],
12-
api = new parserlib.util.EventTarget();
13-
10+
var rules = [],
11+
formatters = [],
12+
embeddedRuleset = /\/\*csslint([^\*]*)\*\//,
13+
api = new parserlib.util.EventTarget();
14+
1415
api.version = "@VERSION@";
1516

1617
//-------------------------------------------------------------------------
@@ -34,18 +35,18 @@ var CSSLint = (function(){
3435
api.clearRules = function(){
3536
rules = [];
3637
};
37-
38+
3839
/**
3940
* Returns the rule objects.
4041
* @return An array of rule objects.
4142
* @method getRules
4243
*/
4344
api.getRules = function(){
44-
return [].concat(rules).sort(function(a,b){
45+
return [].concat(rules).sort(function(a,b){
4546
return a.id > b.id ? 1 : 0;
4647
});
4748
};
48-
49+
4950
/**
5051
* Returns a ruleset configuration object with all current rules.
5152
* @return A ruleset object.
@@ -55,11 +56,55 @@ var CSSLint = (function(){
5556
var ruleset = {},
5657
i = 0,
5758
len = rules.length;
58-
59+
5960
while (i < len){
6061
ruleset[rules[i++].id] = 1; //by default, everything is a warning
6162
}
62-
63+
64+
return ruleset;
65+
};
66+
67+
/**
68+
* Returns a ruleset configuration object with all current rules, modified by inline embedded rules.
69+
* @param {String} text A string of css containing embedded rules.
70+
* @return A ruleset object.
71+
* @method getEmbeddedRuleset
72+
*/
73+
api.getEmbeddedRuleset = function(text){
74+
var valueMap,
75+
ruleset = this.getRuleset(),
76+
embedded = text && text.match(embeddedRuleset),
77+
rules = embedded && embedded[1];
78+
79+
if (!rules) {
80+
return ruleset;
81+
}
82+
83+
valueMap = {
84+
'true': 2, // true is error
85+
'false': 0, // false is ignore
86+
'2': 2,
87+
'1': 1,
88+
'0': 0
89+
};
90+
91+
rules.toLowerCase().split(',').forEach(function(rule){
92+
var pair = rule.split(':'),
93+
property = (pair[0] || '').trim(), // normalize properties
94+
value = valueMap[(pair[1] || '').trim()]; // normalize values
95+
96+
if (!ruleset.hasOwnProperty(property)){
97+
return;
98+
}
99+
100+
if (!value) {
101+
delete ruleset[property];
102+
return;
103+
}
104+
105+
ruleset[property] = value;
106+
});
107+
63108
return ruleset;
64109
};
65110

@@ -76,7 +121,7 @@ var CSSLint = (function(){
76121
// formatters.push(formatter);
77122
formatters[formatter.id] = formatter;
78123
};
79-
124+
80125
/**
81126
* Retrieves a formatter for use.
82127
* @param {String} formatId The name of the format to retrieve.
@@ -86,7 +131,7 @@ var CSSLint = (function(){
86131
api.getFormatter = function(formatId){
87132
return formatters[formatId];
88133
};
89-
134+
90135
/**
91136
* Formats the results in a particular format for a single file.
92137
* @param {Object} result The results returned from CSSLint.verify().
@@ -99,16 +144,16 @@ var CSSLint = (function(){
99144
api.format = function(results, filename, formatId, options) {
100145
var formatter = this.getFormatter(formatId),
101146
result = null;
102-
147+
103148
if (formatter){
104149
result = formatter.startFormat();
105150
result += formatter.formatResults(results, filename, options || {});
106151
result += formatter.endFormat();
107152
}
108-
153+
109154
return result;
110155
};
111-
156+
112157
/**
113158
* Indicates if the given format is supported.
114159
* @param {String} formatId The ID of the format to check.
@@ -144,13 +189,18 @@ var CSSLint = (function(){
144189

145190
// normalize line endings
146191
lines = text.replace(/\n\r?/g, "$split$").split('$split$');
147-
192+
193+
// always perfer file-level rulesets
194+
if (embeddedRuleset.test(text)){
195+
ruleset = this.getEmbeddedRuleset(text);
196+
}
197+
148198
if (!ruleset){
149199
ruleset = this.getRuleset();
150200
}
151-
201+
152202
reporter = new Reporter(lines, ruleset);
153-
203+
154204
ruleset.errors = 2; //always report parsing errors as errors
155205
for (i in ruleset){
156206
if(ruleset.hasOwnProperty(i)){
@@ -170,9 +220,10 @@ var CSSLint = (function(){
170220

171221
report = {
172222
messages : reporter.messages,
173-
stats : reporter.stats
223+
stats : reporter.stats,
224+
ruleset : reporter.ruleset
174225
};
175-
226+
176227
//sort by line numbers, rollups at the bottom
177228
report.messages.sort(function (a, b){
178229
if (a.rollup && !b.rollup){
@@ -182,8 +233,8 @@ var CSSLint = (function(){
182233
} else {
183234
return a.line - b.line;
184235
}
185-
});
186-
236+
});
237+
187238
return report;
188239
};
189240

tests/core/CSSLint.js

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@
1515
"@media (max-width:400px) should not cause an error": function(){
1616
var result = CSSLint.verify("@media (max-width:400px) {}", { });
1717
Assert.areEqual(0, result.messages.length);
18+
},
19+
20+
"Embedded ruleset should be honored": function(){
21+
var result = CSSLint.verify(
22+
"/*csslint adjoining-classes:true, box-sizing:false */\n.foo.bar{}",
23+
{ 'text-indent': 2 }
24+
);
25+
26+
Assert.areEqual(2, result.ruleset['adjoining-classes']);
27+
Assert.areEqual(undefined, result.ruleset['box-sizing']);
28+
Assert.areEqual(1, result.ruleset['text-indent']);
1829
}
1930

2031
}));

0 commit comments

Comments
 (0)