Skip to content

Commit f844802

Browse files
committed
Merge pull request #502 from dmi3y/cliconfig
Allow config file path to be passed through the CLI
2 parents ea36ad5 + 0a23182 commit f844802

File tree

4 files changed

+243
-19
lines changed

4 files changed

+243
-19
lines changed

src/cli/common.js

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function cli(api){
1717
"warnings" : { "format" : "<rule[,rule]+>", "description" : "Indicate which rules to include as warnings."},
1818
"ignore" : { "format" : "<rule[,rule]+>", "description" : "Indicate which rules to ignore completely."},
1919
"exclude-list": { "format" : "<file|dir[,file|dir]+>", "description" : "Indicate which files/directories to exclude from being linted."},
20+
"config" : { "format" : "<file>", "description" : "Reads csslint options from specified file."},
2021
"version" : { "format" : "", "description" : "Outputs the current version number."}
2122
};
2223

@@ -251,8 +252,9 @@ function cli(api){
251252
}
252253

253254

254-
function processArguments(args, options) {
255+
function processArguments(args, extend) {
255256
var arg = args.shift(),
257+
options = extend || {},
256258
argName,
257259
parts,
258260
files = [];
@@ -294,9 +296,16 @@ function cli(api){
294296
}
295297
}
296298

297-
function readConfigFile(options) {
298-
var data = api.readFile(api.getFullPath(".csslintrc")),
299-
json;
299+
function readConfigFile(config) {
300+
var csslintrc = config || ".csslintrc",
301+
data = api.readFile(api.getFullPath(csslintrc));
302+
return data;
303+
}
304+
305+
function readConfigData(config) {
306+
var data = readConfigFile(config),
307+
json,
308+
options = {};
300309
if (data) {
301310
if (data.charAt(0) === "{") {
302311
try {
@@ -309,45 +318,52 @@ function cli(api){
309318
}
310319
} catch(e) {}
311320
}
312-
options = processArguments(data.split(/[\s\n\r]+/m), options);
321+
options = processArguments(data.split(/[\s\n\r]+/m));
313322
}
314323

315324
return options;
316325
}
317326

318-
319-
320327
//-----------------------------------------------------------------------------
321328
// Process command line
322329
//-----------------------------------------------------------------------------
323330

324331
var args = api.args,
325332
argCount = args.length,
326-
options = {};
333+
options,
334+
rcOptions,
335+
cliOptions;
327336

328-
// first look for config file .csslintrc
329-
options = readConfigFile(options);
337+
// Preprocess command line arguments
338+
cliOptions = processArguments(args);
330339

331-
// Command line arguments override config file
332-
options = processArguments(args, options);
333-
334-
if (options.help || argCount === 0){
340+
if (cliOptions.help || argCount === 0){
335341
outputHelp();
336342
api.quit(0);
337343
}
338344

339-
// Validate options
340-
validateOptions(options);
341-
342-
if (options.version){
345+
if (cliOptions.version){
343346
api.print("v" + CSSLint.version);
344347
api.quit(0);
345348
}
346349

347-
if (options["list-rules"]){
350+
if (cliOptions["list-rules"]){
348351
printRules();
349352
api.quit(0);
350353
}
351354

355+
// Look for config file
356+
rcOptions = readConfigData(cliOptions.config);
357+
358+
// Command line arguments override config file
359+
options = CSSLint.Util.mix(rcOptions, cliOptions);
360+
361+
// hot fix for CSSLint.Util.mix current behavior
362+
// https://github.com/CSSLint/csslint/issues/501
363+
options = rcOptions;
364+
365+
// Validate options
366+
validateOptions(options);
367+
352368
api.quit(processFiles(options.files,options));
353369
}

tests/cli/assets/apiStub.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*jshint node:true*/
2+
"use strict";
3+
var
4+
stub = {
5+
logbook: function (log) {
6+
this.logs.push(log);
7+
},
8+
readLogs: function () {
9+
return this.logs.slice();
10+
},
11+
12+
getFullPath: function (path) {
13+
return path;
14+
},
15+
getFiles: function (dir) {
16+
var
17+
filesobj = this.fakedFs[dir],
18+
fileix,
19+
out = [];
20+
for (fileix in filesobj) {
21+
if ( filesobj.hasOwnProperty(fileix) && /\.css$/.test(fileix) ) {
22+
out.push(dir + "/" + fileix);
23+
}
24+
}
25+
return out;
26+
},
27+
readFile: function (path) {
28+
var
29+
spath = path.split("/"),
30+
spathLen = spath.length,
31+
i,
32+
out = this.fakedFs;
33+
34+
for (i = 0; i < spathLen; i += 1) {
35+
out = out[spath[i]];
36+
}
37+
38+
return out;
39+
},
40+
isDirectory: function (checkit) {
41+
var
42+
result = this.fakedFs[checkit];
43+
return typeof result === "object";
44+
},
45+
print: function (msg) {
46+
this.logbook(msg);
47+
},
48+
quit: function (signal) {
49+
this.logbook(signal);
50+
}
51+
};
52+
53+
module.exports = function (setup) {
54+
var
55+
api,
56+
setix;
57+
58+
api = Object.create(stub);
59+
60+
for (setix in setup) {
61+
if (setup.hasOwnProperty(setix)) {
62+
api[setix] = setup[setix];
63+
}
64+
}
65+
66+
api.logs = [];
67+
return api;
68+
};

tests/cli/assets/data.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*jshint node:true*/
2+
module.exports = {
3+
"suites": {
4+
"config csslintrc override": {
5+
"args": [
6+
"--config=.rc1",
7+
"dir"
8+
],
9+
"expecting": [
10+
"csslint: No errors in dir/a.css.",
11+
"csslint: No errors in dir/b.css.",
12+
0
13+
]
14+
},
15+
"straight linting": {
16+
"args": [
17+
"dir"
18+
],
19+
"expecting": [
20+
"csslint: There is 1 problem in dir/a.css.",
21+
"csslint: There is 1 problem in dir/b.css.",
22+
0
23+
]
24+
},
25+
"mix of cli options": {
26+
"args": [
27+
"--config=.rc1",
28+
"--ignore=important",
29+
"dir"
30+
],
31+
"expecting": [
32+
"csslint: No errors in dir/a.css.",
33+
"csslint: There is 1 problem in dir/b.css.",
34+
0
35+
]
36+
},
37+
"more mixes of cli options": {
38+
"args": [
39+
"--config=.rc1",
40+
"--errors=important",
41+
"dir"
42+
],
43+
"expecting": [
44+
"csslint: There is 1 problem in dir/a.css.",
45+
"csslint: No errors in dir/b.css.",
46+
1
47+
]
48+
},
49+
"version": {
50+
"args": [
51+
"--version"
52+
],
53+
"expecting": [
54+
"v@VERSION@",
55+
0
56+
]
57+
}
58+
},
59+
60+
"fakedFs": {
61+
".rc1": "--ignore=important,ids",
62+
"dir": {
63+
"a.css": ".a {color: red!important;}",
64+
"b.css": "#a {color: red;}"
65+
},
66+
}
67+
};

tests/cli/cli-common.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*jshint loopfunc:true, node:true */
2+
"use strict";
3+
function include(path, sandbox) {
4+
var
5+
vm = require("vm"),
6+
fs = require("fs"),
7+
file;
8+
9+
file = fs.readFileSync(path);
10+
vm.runInNewContext(file, sandbox);
11+
}
12+
13+
14+
15+
(function(){
16+
17+
var Assert = YUITest.Assert,
18+
suite = new YUITest.TestSuite("General Tests for CLI"),
19+
apiStub = require("./tests/cli/assets/apiStub.js"),
20+
data = require("./tests/cli/assets/data.js"),
21+
suites = data.suites,
22+
suiteix,
23+
sandbox = {
24+
CSSLint: CSSLint
25+
};
26+
27+
include(__dirname + "/src/cli/common.js", sandbox); /* expose sandbox.cli */
28+
29+
for (suiteix in suites) {
30+
if (suites.hasOwnProperty(suiteix)) {
31+
(function (suiteix) {
32+
33+
suite.add(new YUITest.TestCase({
34+
35+
name: "Test " + suiteix,
36+
37+
"Outcome logs should match expected": function (){
38+
var
39+
it = suites[suiteix],
40+
expecting = it.expecting,
41+
expectingLen = expecting.length,
42+
outcome,
43+
api,
44+
exp,
45+
out,
46+
i = 0;
47+
48+
data.args = it.args.slice();
49+
api = apiStub(data);
50+
sandbox.cli(api);
51+
outcome = api.readLogs();
52+
53+
for (i; i < expectingLen; i += 1) {
54+
exp = expecting[i];
55+
out = outcome[i];
56+
57+
if ( typeof out === "string") {
58+
out = /^.*/.exec(out.trim())[0];
59+
}
60+
if ( exp !== out ) {
61+
Assert.fail("Expecting: " + exp + " Got: " + out);
62+
}
63+
}
64+
Assert.pass();
65+
66+
}
67+
}));
68+
})(suiteix);
69+
}
70+
}
71+
72+
YUITest.TestRunner.add(suite);
73+
})();

0 commit comments

Comments
 (0)