Comparing version 2.0.3 to 2.1.0
# Changelog | ||
## 2.1.0 (2016-09-02) | ||
* Added `maxCharPerLine` linter. ([af69e95](https://github.com/lesshint/lesshint/commit/af69e9545ac8fc89ff508064741d77e21e29c926)) | ||
* Added `newlineAfterBlock` linter. ([05d48e1](https://github.com/lesshint/lesshint/commit/05d48e1500a4b0e95b3cceee3d5b137c116a472e)) | ||
* Fixed an issue where `stringQuotes` wouldn't check at-rules. ([aaf1d84](https://github.com/lesshint/lesshint/commit/aaf1d847cc34c20b48903bc65d03202ebfdf90fc)) | ||
* Fixed an issue where `spaceBetweenParens` would report the wrong line. ([fa6ff41](https://github.com/lesshint/lesshint/commit/fa6ff41917744af62e418dfb8489901dfcfde37c)) | ||
* Added tests for failing linter plugins. ([02aeef0](https://github.com/lesshint/lesshint/commit/02aeef0c06f9f2f43f0b885b2b845ba928b41835)) | ||
* Added some examples on how to use `lesshint` from custom code. ([0a87b24](https://github.com/lesshint/lesshint/commit/0a87b24a41e5c4f111493a54aa04d2256f1908b9)) | ||
## 2.0.3 (2016-08-09) | ||
@@ -3,0 +11,0 @@ * Fixed an issue where `importPath` wouldn't handle [Less import options](http://lesscss.org/features/#import-options). ([dc099ee](https://github.com/lesshint/lesshint/commit/dc099eeb8bc11db07e487b01fd3f15245eb1bccc)) |
@@ -44,2 +44,7 @@ { | ||
"maxCharPerLine" : { | ||
"enabled": true, | ||
"limit" : 100 | ||
}, | ||
"hexLength": { | ||
@@ -75,2 +80,6 @@ "enabled": true, | ||
"newlineAfterBlock": { | ||
"enabled": true | ||
}, | ||
"propertyOrdering": { | ||
@@ -77,0 +86,0 @@ "enabled": true, |
@@ -11,2 +11,3 @@ 'use strict'; | ||
require('./linters/attribute_quotes'), | ||
require('./linters/newline_after_block'), | ||
require('./linters/border_zero'), | ||
@@ -43,3 +44,4 @@ require('./linters/comment'), | ||
require('./linters/url_quotes'), | ||
require('./linters/zero_unit') | ||
require('./linters/zero_unit'), | ||
require('./linters/max_char_per_line') | ||
]; | ||
@@ -46,0 +48,0 @@ |
@@ -17,2 +17,4 @@ # Available linters | ||
* [importPath](#importpath) | ||
* [maxCharPerLine](#maxcharperline) | ||
* [newlineAfterBlock](#newlineafterblock) | ||
* [propertyOrdering](#propertyordering) | ||
@@ -355,2 +357,47 @@ * [propertyUnits](#propertyunits) | ||
## maxCharPerLine | ||
Lines shouldn't exceed the defined length. | ||
Option | Description | ||
--------- | ---------- | ||
`limit` | `100` | ||
### invalid | ||
```less | ||
.foo { | ||
color: red; // A really long comment that's more than 100 chars... | ||
} | ||
``` | ||
### valid | ||
```less | ||
.foo { | ||
color: red; // A short comment that's less than 100 chars | ||
} | ||
``` | ||
## newlineAfterBlock | ||
All blocks should be followed by a new line. | ||
### invalid | ||
```less | ||
.foo { | ||
color: red; | ||
} | ||
.bar { | ||
color: blue; | ||
} | ||
``` | ||
### valid | ||
```less | ||
.foo { | ||
color: red; | ||
} | ||
.bar { | ||
color: blue; | ||
} | ||
``` | ||
## propertyOrdering | ||
@@ -357,0 +404,0 @@ Make sure properties are sorted in a particular order. |
@@ -58,3 +58,3 @@ 'use strict'; | ||
column: column + child.source.start.column, | ||
line: child.source.start.line, | ||
line: node.source.start.line, | ||
message: util.format(self.message.opening, ' not', 'followed', 'any') | ||
@@ -67,3 +67,3 @@ }); | ||
column: column + prev.source.end.column, | ||
line: prev.source.end.line, | ||
line: node.source.start.line, | ||
message: util.format(self.message.closing, ' not', 'preceded', 'any') | ||
@@ -78,3 +78,3 @@ }); | ||
column: column + child.source.start.column, | ||
line: child.source.start.line, | ||
line: node.source.start.line, | ||
message: util.format(self.message.opening, '', 'followed', 'one') | ||
@@ -87,3 +87,3 @@ }); | ||
column: column + prev.source.end.column, | ||
line: prev.source.end.line, | ||
line: node.source.start.line, | ||
message: util.format(self.message.closing, '', 'preceded', 'one') | ||
@@ -90,0 +90,0 @@ }); |
@@ -9,3 +9,3 @@ 'use strict'; | ||
name: 'stringQuotes', | ||
nodeTypes: ['decl', 'rule'], | ||
nodeTypes: ['atrule', 'decl', 'rule'], | ||
message: 'Strings should use %s quotes.', | ||
@@ -16,2 +16,3 @@ | ||
var self = this; | ||
var column; | ||
var ast; | ||
@@ -27,7 +28,25 @@ var quotes = { | ||
if (node.type === 'decl') { | ||
if (node.type === 'atrule') { | ||
/** | ||
* Hopefully node.ruleWithoutBody will be implemented on AtRule nodes | ||
* in the future: https://github.com/webschik/postcss-less/issues/55 | ||
*/ | ||
if (node.nodes) { | ||
return; | ||
} | ||
if (!quotes[config.style].test(node.params)) { | ||
column = (node.raws.afterName ? node.raws.afterName.length : 0) + | ||
node.source.start.column + | ||
node.name.length + 1; | ||
results.push({ | ||
column: column, | ||
line: node.source.start.line, | ||
message: util.format(self.message, config.style) | ||
}); | ||
} | ||
} else if (node.type === 'decl') { | ||
ast = valuesParser(node.value).parse(); | ||
ast.first.walk(function (decl) { | ||
var column; | ||
if (decl.type !== 'string') { | ||
@@ -54,4 +73,2 @@ return; | ||
selectors.walkAttributes(function (selector) { | ||
var column; | ||
if (selector.quoted && !quotes[config.style].test(selector.value)) { | ||
@@ -58,0 +75,0 @@ column = node.source.start.column + selector.source.start.column |
{ | ||
"name": "lesshint", | ||
"description": "A tool to aid you in writing clean and consistent Less.", | ||
"version": "2.0.3", | ||
"version": "2.1.0", | ||
"main": "./lib/lesshint.js", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -48,2 +48,16 @@ # lesshint | ||
### Setting custom configuration path | ||
```js | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var LessHint = require('lesshint'); | ||
var lesshint = new LessHint(); | ||
var lesshintConfigPath = path.resolve('my-custom-path/.lesshintrc'); | ||
var lesshintConfig = JSON.parse(fs.readFileSync(lesshintConfigurePath, 'utf8')); | ||
lesshint.configure(lesshintConfiguration); | ||
``` | ||
### Inline configuration | ||
@@ -121,2 +135,3 @@ It's also possible to configure rules using inline comments in your `.less` files. For example: | ||
## Custom linters | ||
@@ -226,9 +241,8 @@ Since `2.0.0` it's possible to create your own linters when needed for something team/project specfic or something that's out of scope for `lesshint`. | ||
```js | ||
var Lesshint = require('lesshint'); | ||
var lesshint = new Lesshint(); | ||
var reporter = lesshint.getReporter('my-super-awesome-reporter'); | ||
var errors = lesshint.checkFile('file.less'); | ||
reporter.report(errors); | ||
var defaultReporter = lesshint.getReporter(); //Or pass path to your custom reporter in getReporter | ||
var promise = lesshint.checkFile('my-less-file.less'); | ||
promise.then(function(result){ | ||
defaultReporter.report(result); | ||
}) | ||
``` | ||
@@ -266,1 +280,3 @@ | ||
Take a look at the [default reporter](https://github.com/lesshint/lesshint/blob/master/lib/reporters/default.js) for more information. | ||
@@ -194,2 +194,36 @@ /*eslint no-console: 0*/ | ||
it('should fail loading linters if a command-line linter errors', function () { | ||
var result; | ||
sinon.spy(console, 'log'); | ||
result = cli({ | ||
args: [path.dirname(__dirname) + '/data/files/file.less'], | ||
config: path.resolve(process.cwd() + '/test/data/config/linters.json'), | ||
linters: ['../test/plugins/failingLinter'] | ||
}); | ||
return result.fail(function (status) { | ||
console.log.restore(); | ||
expect(status).to.equal(70); | ||
}); | ||
}); | ||
it('should fail loading linters if a config file linter errors', function () { | ||
var result; | ||
sinon.spy(console, 'log'); | ||
result = cli({ | ||
args: [path.dirname(__dirname) + '/data/files/file.less'], | ||
config: path.resolve(process.cwd() + '/test/data/config/linters-failing.json'), | ||
linters: ['../test/plugins/sampleLinter'] | ||
}); | ||
return result.fail(function (status) { | ||
console.log.restore(); | ||
expect(status).to.equal(78); | ||
}); | ||
}); | ||
it('should exit without errors when passed a built-in reporter name', function () { | ||
@@ -196,0 +230,0 @@ var result; |
@@ -252,2 +252,79 @@ 'use strict'; | ||
it('should not allow double quotes in @-rules when "style" is "single"', function () { | ||
var source = '@import "foo.less";'; | ||
var expected = [{ | ||
column: 9, | ||
line: 1, | ||
message: 'Strings should use single quotes.' | ||
}]; | ||
var options = { | ||
style: 'single' | ||
}; | ||
return spec.parse(source, function (ast) { | ||
var result = spec.linter.lint(options, ast.root.first); | ||
expect(result).to.deep.equal(expected); | ||
}); | ||
}); | ||
it('should not allow single quotes in @-rules when "style" is "double"', function () { | ||
var source = "@import 'foo.less';"; | ||
var expected = [{ | ||
column: 9, | ||
line: 1, | ||
message: 'Strings should use double quotes.' | ||
}]; | ||
var options = { | ||
style: 'double' | ||
}; | ||
return spec.parse(source, function (ast) { | ||
var result = spec.linter.lint(options, ast.root.first); | ||
expect(result).to.deep.equal(expected); | ||
}); | ||
}); | ||
it('should allow single quotes in @-rules when "style" is "single"', function () { | ||
var source = "@import 'foo.less';"; | ||
var options = { | ||
style: 'single' | ||
}; | ||
return spec.parse(source, function (ast) { | ||
var result = spec.linter.lint(options, ast.root.first); | ||
expect(result).to.deep.undefined; | ||
}); | ||
}); | ||
it('should allow double quotes in @-rules when "style" is "double"', function () { | ||
var source = '@import "foo.less";'; | ||
var options = { | ||
style: 'double' | ||
}; | ||
return spec.parse(source, function (ast) { | ||
var result = spec.linter.lint(options, ast.root.first); | ||
expect(result).to.deep.undefined; | ||
}); | ||
}); | ||
it('should not check irrelevant @-rules', function () { | ||
var source = '@media (screen) {}'; | ||
var options = { | ||
style: 'double' | ||
}; | ||
return spec.parse(source, function (ast) { | ||
var result = spec.linter.lint(options, ast.root.first); | ||
expect(result).to.deep.undefined; | ||
}); | ||
}); | ||
it('should throw on invalid "style" value', function () { | ||
@@ -254,0 +331,0 @@ var source = ".foo { content: 'Hello world' }"; |
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
388583
117
8348
279