Comparing version 0.1.5 to 0.2.0
# Changelog | ||
## 0.2.0 (2015-04-27) | ||
* Added the following linters: | ||
* `borderZero` | ||
* `hexLength` | ||
* `hexNotation` | ||
* `hexValidation` | ||
* `spaceAfterPropertyName` | ||
* `lesshint` will now exit with proper status codes. E.g. `1` when there's a lint error in a checked file, thus failing builds etc. | ||
* Made some improvements to CLI output, added colors and made it easier to read. | ||
* Fixed an issue where the `spaceBeforeBrace` linter would report the wrong column when `style` is `one_space` ([`#4`](https://github.com/jwilsson/lesshint/issues/4)). | ||
## 0.1.5 (2015-04-24) | ||
@@ -4,0 +15,0 @@ * The default options are now always loaded, regardless if `lesshint` is running from the CLI or another module. |
@@ -5,13 +5,28 @@ 'use strict'; | ||
var LessHint = require('./lesshint'); | ||
var chalk = require('chalk'); | ||
var exit = require('exit'); | ||
var Vow = require('vow'); | ||
var EXIT_CODES = { | ||
OK: 0, | ||
WARNING: 1, | ||
NOINPUT: 66, | ||
CONFIG: 78 | ||
}; | ||
module.exports = function (program) { | ||
var lesshint = new LessHint(); | ||
var exitDefer = Vow.defer(); | ||
var exitPromise = exitDefer.promise(); | ||
var promises = []; | ||
var config; | ||
exitPromise.always(function (status) { | ||
exit(status.valueOf()); | ||
}); | ||
if (!program.args.length) { | ||
console.error('No files to lint were passed. See lesshint -h'); | ||
return; | ||
exitDefer.reject(EXIT_CODES.NOINPUT); | ||
} | ||
@@ -24,3 +39,3 @@ | ||
return; | ||
exitDefer.reject(EXIT_CODES.CONFIG); | ||
} | ||
@@ -34,12 +49,23 @@ | ||
if (!errors.length) { | ||
exitDefer.resolve(EXIT_CODES.OK); | ||
return; | ||
} | ||
errors.forEach(function (error) { | ||
console.log( | ||
'%s %s:%d %s', | ||
error.linter, | ||
error.file, | ||
error.line, | ||
'%s: %s, %s, %s: %s', | ||
chalk.cyan(error.file), | ||
chalk.magenta('line ' + error.line), | ||
chalk.magenta('col ' + error.column), | ||
chalk.green(error.linter), | ||
error.message | ||
); | ||
}); | ||
exitDefer.reject(EXIT_CODES.WARNING); | ||
}); | ||
return exitPromise; | ||
}; |
{ | ||
"borderZero": { | ||
"enabled": true, | ||
"style": "zero" | ||
}, | ||
"hexLength": { | ||
"enabled": true, | ||
"style": "long" | ||
}, | ||
"hexNotation": { | ||
"enabled": true, | ||
"style": "lowercase" | ||
}, | ||
"hexValidation": { | ||
"enabled": true | ||
}, | ||
"spaceAfterPropertyColon": { | ||
@@ -7,2 +26,7 @@ "enabled": true, | ||
"spaceAfterPropertyName": { | ||
"enabled": true, | ||
"style": "no_space" | ||
}, | ||
"spaceBeforeBrace": { | ||
@@ -9,0 +33,0 @@ "enabled": true, |
@@ -8,3 +8,8 @@ 'use strict'; | ||
var linters = [ | ||
require('./linters/border_zero'), | ||
require('./linters/hex_length'), | ||
require('./linters/hex_notation'), | ||
require('./linters/hex_validation'), | ||
require('./linters/space_after_property_colon'), | ||
require('./linters/space_after_property_name'), | ||
require('./linters/space_before_brace') | ||
@@ -11,0 +16,0 @@ ]; |
@@ -7,2 +7,90 @@ # Available linters | ||
* [borderZero](#borderzero) | ||
* [hexLength](#hexlength) | ||
* [hexNotation](#hexnotation) | ||
* [hexValidation](#hexvalidation) | ||
* [spaceAfterPropertyColon](#spaceafterpropertycolon) | ||
* [spaceAfterPropertyName](#spaceafterpropertyname) | ||
* [spaceBeforeBrace](#spacebeforebrace) | ||
## borderZero | ||
Prefer `0` over `none` in border declarations. | ||
Option | Description | ||
---------- | ---------- | ||
`style` | `none`, `zero` (**default**) | ||
### none | ||
```css | ||
.foo { | ||
border: none; | ||
} | ||
``` | ||
### zero | ||
```css | ||
.foo { | ||
border: 0; | ||
} | ||
``` | ||
## hexLength | ||
Prefer longhand hex color declarations over short hand ones. | ||
Option | Description | ||
---------- | ---------- | ||
`style` | `long` (**default**), `short` | ||
### long | ||
```css | ||
.foo { | ||
color: #000000; | ||
} | ||
``` | ||
### short | ||
```css | ||
.foo { | ||
color: #000; | ||
} | ||
``` | ||
## hexNotation | ||
Hex color declarations should be written in lowercase. | ||
Option | Description | ||
---------- | ---------- | ||
`style` | `lowercase` (**default**), `uppercase` | ||
### lowercase | ||
```css | ||
.foo { | ||
color: #abcdef; | ||
} | ||
``` | ||
### uppercase | ||
```css | ||
.foo { | ||
color: #ABCDEF; | ||
} | ||
``` | ||
## hexValidation | ||
Check if hex color declarations are valid. | ||
### invalid | ||
```css | ||
.foo { | ||
color: #ab; | ||
} | ||
``` | ||
### valid | ||
```css | ||
.foo { | ||
color: #abc; | ||
} | ||
``` | ||
## spaceAfterPropertyColon | ||
@@ -29,2 +117,23 @@ Each colon in property declarations should be followed by a space. | ||
## spaceAfterPropertyName | ||
The colon in property declarations shouldn't be preceded by any space. | ||
Option | Description | ||
---------- | ---------- | ||
`style` | `no_space` (**default**), `one_space` | ||
### no_space | ||
```css | ||
.foo { | ||
margin: 0; | ||
} | ||
``` | ||
### one_space | ||
```css | ||
.foo { | ||
margin : 0; | ||
} | ||
``` | ||
## spaceBeforeBrace | ||
@@ -51,3 +160,3 @@ A space should be present before opening braces. | ||
## new_line | ||
### new_line | ||
```css | ||
@@ -54,0 +163,0 @@ .foo |
@@ -42,3 +42,3 @@ 'use strict'; | ||
if (maybeSpace.type === 'space') { | ||
message = 'Colon after property shouldn\'t be followed by any spaces.'; | ||
message = 'Colon after property name should not be followed by any spaces.'; | ||
} | ||
@@ -49,3 +49,3 @@ | ||
if (maybeSpace.type !== 'space' || (maybeSpace.type === 'space' && maybeSpace.content !== ' ')) { | ||
message = 'Colon after property should be followed by one space.'; | ||
message = 'Colon after property name should be followed by one space.'; | ||
} | ||
@@ -52,0 +52,0 @@ |
@@ -11,2 +11,3 @@ 'use strict'; | ||
var message; | ||
var column; | ||
@@ -35,2 +36,8 @@ // Bail if the linter isn't wanted | ||
message = 'Opening curly brace should be preceded by one space.'; | ||
if (selector.content[0].start) { | ||
column = selector.content[0].start.column + selector.content[0].content.length; | ||
} else { | ||
column = selector.start.column + selector.content.length; | ||
} | ||
} | ||
@@ -51,3 +58,3 @@ | ||
return { | ||
column: selector.start.column, | ||
column: column || selector.start.column, | ||
file: filename, | ||
@@ -54,0 +61,0 @@ line: selector.start.line, |
{ | ||
"name": "lesshint", | ||
"description": "A tool to aid you in writing clean and consistent Less.", | ||
"version": "0.1.5", | ||
"version": "0.2.0", | ||
"main": "./lib/lesshint.js", | ||
@@ -20,4 +20,7 @@ "author": { | ||
"dependencies": { | ||
"chalk": "^1.0.0", | ||
"commander": "^2.8.0", | ||
"exit": "^0.1.2", | ||
"gonzales-pe": "^3.0.0-26", | ||
"lodash.find": "^3.2.0", | ||
"lodash.findindex": "^3.2.0", | ||
@@ -35,2 +38,3 @@ "lodash.merge": "^3.2.0", | ||
"mock-fs": "^2.5.0", | ||
"rewire": "^2.3.1", | ||
"sinon": "^1.14.1" | ||
@@ -37,0 +41,0 @@ }, |
var assert = require('assert'); | ||
var rewire = require('rewire'); | ||
var sinon = require('sinon'); | ||
var path = require('path'); | ||
var sinon = require('sinon'); | ||
describe('cli', function () { | ||
var cli = require('../../lib/cli'); | ||
var cli = rewire('../../lib/cli'); | ||
beforeEach(function() { | ||
sinon.stub(process.stderr, 'write'); | ||
cli.__set__('exit', function () {}); | ||
}); | ||
@@ -19,5 +22,7 @@ | ||
it('should print error on invalid config file', function () { | ||
var result; | ||
sinon.spy(console, 'error'); | ||
cli({ | ||
result = cli({ | ||
args: ['test.less'], | ||
@@ -27,17 +32,74 @@ config: path.resolve(process.cwd() + '/test/data/config/invalid.json') | ||
// We can't really be sure of the JSON.parse() error message, so we'll just check that the beginning is correct | ||
assert(console.error.getCall(0).args[0].indexOf('Something\'s wrong with the config file. Error: ') === 0); | ||
console.error.restore(); | ||
return result.fail(function () { | ||
// We can't really be sure of the JSON.parse() error message, so we'll just check that the beginning is correct | ||
assert(console.error.getCall(0).args[0].indexOf('Something\'s wrong with the config file. Error: ') === 0); | ||
console.error.restore(); | ||
}); | ||
}); | ||
it('should print error when no files are passed', function () { | ||
var result; | ||
sinon.spy(console, 'error'); | ||
cli({ | ||
result = cli({ | ||
args: [] | ||
}); | ||
assert(console.error.getCall(0).args[0] === 'No files to lint were passed. See lesshint -h'); | ||
console.error.restore(); | ||
return result.fail(function () { | ||
assert(console.error.getCall(0).args[0] === 'No files to lint were passed. See lesshint -h'); | ||
console.error.restore(); | ||
}); | ||
}); | ||
it('should exit with a non-zero status code when lint errors were found', function () { | ||
var result; | ||
result = cli({ | ||
args: [path.dirname(__dirname) + '/data/files/file.less'], | ||
config: path.resolve(process.cwd() + '/lib/config/defaults.json') | ||
}); | ||
return result.fail(function (status) { | ||
assert.ok(status === 1); | ||
}); | ||
}); | ||
it('should exit with a non-zero status code when no files were passed', function () { | ||
var result; | ||
result = cli({ | ||
args: [] | ||
}); | ||
return result.fail(function (status) { | ||
assert.ok(status === 66); | ||
}); | ||
}); | ||
it('should exit with a non-zero status code when invalid config file is used', function () { | ||
var result; | ||
result = cli({ | ||
args: ['test.less'], | ||
config: path.resolve(process.cwd() + '/test/data/config/invalid.json') | ||
}); | ||
return result.fail(function (status) { | ||
assert.ok(status === 78); | ||
}); | ||
}); | ||
it('should exit with a zero status code when everything is alright', function () { | ||
var result; | ||
result = cli({ | ||
args: [path.dirname(__dirname) + '/data/files/ok.less'], | ||
config: path.resolve(process.cwd() + '/test/data/config/invalid.json') | ||
}); | ||
return result.fail(function (status) { | ||
assert.ok(status === 78); | ||
}); | ||
}); | ||
}); |
@@ -25,3 +25,3 @@ var assert = require('assert'); | ||
assert.equal(2, actual.length); | ||
assert.ok(actual.length === 2); | ||
}); | ||
@@ -28,0 +28,0 @@ }); |
@@ -38,3 +38,3 @@ var assert = require('assert'); | ||
linter: 'spaceAfterPropertyColon', | ||
message: 'Colon after property should be followed by one space.' | ||
message: 'Colon after property name should be followed by one space.' | ||
}; | ||
@@ -71,3 +71,3 @@ | ||
linter: 'spaceAfterPropertyColon', | ||
message: 'Colon after property should be followed by one space.' | ||
message: 'Colon after property name should be followed by one space.' | ||
}; | ||
@@ -94,3 +94,3 @@ | ||
it('shouldn\'t allow any space when style is "no_space"', function () { | ||
it('should not allow any space when style is "no_space"', function () { | ||
var source = '.foo { color:red; }'; | ||
@@ -125,3 +125,3 @@ var ast; | ||
linter: 'spaceAfterPropertyColon', | ||
message: 'Colon after property shouldn\'t be followed by any spaces.' | ||
message: 'Colon after property name should not be followed by any spaces.' | ||
}; | ||
@@ -158,3 +158,3 @@ | ||
linter: 'spaceAfterPropertyColon', | ||
message: 'Colon after property shouldn\'t be followed by any spaces.' | ||
message: 'Colon after property name should not be followed by any spaces.' | ||
}; | ||
@@ -161,0 +161,0 @@ |
@@ -178,3 +178,3 @@ var assert = require('assert'); | ||
var expected = { | ||
column: 1, | ||
column: 5, | ||
file: 'test.less', | ||
@@ -230,3 +230,3 @@ line: 1, | ||
var expected = { | ||
column: 7, | ||
column: 11, | ||
file: 'test.less', | ||
@@ -262,3 +262,3 @@ line: 1, | ||
var expected = { | ||
column: 5, | ||
column: 7, | ||
file: 'test.less', | ||
@@ -294,3 +294,3 @@ line: 1, | ||
var expected = { | ||
column: 11, | ||
column: 13, | ||
file: 'test.less', | ||
@@ -297,0 +297,0 @@ line: 1, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83451
42
2103
11
6
+ Addedchalk@^1.0.0
+ Addedexit@^0.1.2
+ Addedlodash.find@^3.2.0
+ Addedansi-regex@2.1.1(transitive)
+ Addedansi-styles@2.2.1(transitive)
+ Addedchalk@1.1.3(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedexit@0.1.2(transitive)
+ Addedhas-ansi@2.0.0(transitive)
+ Addedlodash._baseeach@3.0.4(transitive)
+ Addedlodash._basefind@3.0.0(transitive)
+ Addedlodash.find@3.2.1(transitive)
+ Addedstrip-ansi@3.0.1(transitive)
+ Addedsupports-color@2.0.0(transitive)