Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lesshint

Package Overview
Dependencies
Maintainers
1
Versions
91
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lesshint - npm Package Compare versions

Comparing version 0.3.1 to 0.4.0

lib/linters/important_rule.js

10

CHANGELOG.md
# Changelog
## 0.4.0 (2015-05-10)
* **Breaking change:** The `LessHint` class is now called `Lesshint`.
* The following linters have been added:
* `importantRule`
* `stringQuotes`
* `urlFormat`
* `urlQuotes`
* All linters can now be disabled by simply setting the respective property to `false`. No need to set `enabled: false` anymore.
* Some other improvements to the linters.
## 0.3.1 (2015-05-03)

@@ -4,0 +14,0 @@ * When running from the CLI and a line or column is `null`, it's no longer printed.

4

lib/cli.js
'use strict';
var configLoader = require('./config-loader');
var LessHint = require('./lesshint');
var Lesshint = require('./lesshint');
var chalk = require('chalk');

@@ -17,3 +17,3 @@ var exit = require('exit');

module.exports = function (program) {
var lesshint = new LessHint();
var lesshint = new Lesshint();
var exitDefer = Vow.defer();

@@ -20,0 +20,0 @@ var exitPromise = exitDefer.promise();

@@ -37,2 +37,6 @@ {

"importantRule": {
"enabled": true
},
"spaceAfterPropertyColon": {

@@ -53,5 +57,19 @@ "enabled": true,

"stringQuotes": {
"enabled": true,
"style": "single"
},
"trailingSemicolon": {
"enabled": true
},
"urlFormat": {
"enabled": true,
"style": "relative"
},
"urlQuotes": {
"enabled": true
}
}

@@ -7,7 +7,7 @@ 'use strict';

var LessHint = function () {
var Lesshint = function () {
};
LessHint.prototype.checkDirectory = function (path) {
Lesshint.prototype.checkDirectory = function (path) {
return fs.listDir(path).then(function (files) {

@@ -36,3 +36,3 @@ files = files.map(function (file) {

LessHint.prototype.checkFile = function (path) {
Lesshint.prototype.checkFile = function (path) {
return fs.read(path, 'utf8').then(function (data) {

@@ -43,3 +43,3 @@ return this.checkString(data, path);

LessHint.prototype.checkPath = function (path) {
Lesshint.prototype.checkPath = function (path) {
return fs.stat(path).then(function (stats) {

@@ -54,10 +54,10 @@ if (stats.isDirectory()) {

LessHint.prototype.checkString = function (input, path) {
Lesshint.prototype.checkString = function (input, path) {
return linter.lint(input, path, this.config);
};
LessHint.prototype.configure = function (config) {
Lesshint.prototype.configure = function (config) {
this.config = config;
};
module.exports = LessHint;
module.exports = Lesshint;

@@ -17,6 +17,10 @@ 'use strict';

require('./linters/id_selector'),
require('./linters/important_rule'),
require('./linters/space_after_property_colon'),
require('./linters/space_after_property_name'),
require('./linters/space_before_brace'),
require('./linters/trailing_semicolon')
require('./linters/string_quotes'),
require('./linters/trailing_semicolon'),
require('./linters/url_format'),
require('./linters/url_quotes')
];

@@ -23,0 +27,0 @@

@@ -15,3 +15,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.borderZero && !config.borderZero.enabled) {
if (!config.borderZero || (config.borderZero && !config.borderZero.enabled)) {
return null;

@@ -18,0 +18,0 @@ }

@@ -13,3 +13,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.duplicateProperty && !config.duplicateProperty.enabled) {
if (!config.duplicateProperty || (config.duplicateProperty && !config.duplicateProperty.enabled)) {
return null;

@@ -16,0 +16,0 @@ }

@@ -12,3 +12,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.emptyRule && !config.emptyRule.enabled) {
if (!config.emptyRule || (config.emptyRule && !config.emptyRule.enabled)) {
return null;

@@ -15,0 +15,0 @@ }

'use strict';
var clone = require('lodash.clone');
var path = require('path');

@@ -9,7 +8,7 @@

var config = options.config;
var node = clone(options.node, true); // We need to break the object reference since we modify the node below
var node = options.node;
var maybeLine;
// Bail if the linter isn't wanted
if (config.finalNewline && !config.finalNewline.enabled) {
if (!config.finalNewline || (config.finalNewline && !config.finalNewline.enabled)) {
return null;

@@ -23,3 +22,3 @@ }

maybeLine = node.content.pop();
maybeLine = node.content[node.content.length - 1];

@@ -26,0 +25,0 @@ if (maybeLine.type !== 'space' && maybeLine.content !== '\n') {

@@ -18,3 +18,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.hexLength && !config.hexLength.enabled) {
if (!config.hexLength || (config.hexLength && !config.hexLength.enabled)) {
return null;

@@ -21,0 +21,0 @@ }

@@ -14,3 +14,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.hexNotation && !config.hexNotation.enabled) {
if (!config.hexNotation || (config.hexNotation && !config.hexNotation.enabled)) {
return null;

@@ -17,0 +17,0 @@ }

@@ -9,3 +9,2 @@ 'use strict';

var node = options.node;
var message;
var color;

@@ -15,3 +14,3 @@ var value;

// Bail if the linter isn't wanted
if (config.hexValidation && !config.hexValidation.enabled) {
if (!config.hexValidation || (config.hexValidation && !config.hexValidation.enabled)) {
return null;

@@ -35,8 +34,3 @@ }

color = '#' + value.content;
if (!/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(color)) {
message = 'Hexadecimal color "' + color + '" should be either three or six characters long.';
}
if (message) {
return {

@@ -47,3 +41,3 @@ column: value.start.column,

linter: 'hexValidation',
message: message
message: 'Hexadecimal color "' + color + '" should be either three or six characters long.'
};

@@ -50,0 +44,0 @@ }

@@ -13,3 +13,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.idSelector && !config.idSelector.enabled) {
if (!config.idSelector || (config.idSelector && !config.idSelector.enabled)) {
return null;

@@ -24,7 +24,11 @@ }

node.forEach('simpleSelector', function (selector) {
selector.content.forEach(function (selector) {
selector.content.some(function (selector) {
if (selector.type === 'id') {
message = 'Selectors should not use IDs.';
start = selector.start;
return true;
}
return false;
});

@@ -31,0 +35,0 @@ });

@@ -5,3 +5,3 @@ # Available linters

Each linter also accept a `enabled` option to turn if off/on completely.
Each linter also accept a `enabled` option to turn if off/on completely. Another way of disabling a linter is by setting the whole property to `false`.

@@ -16,6 +16,10 @@ * [borderZero](#borderzero)

* [idSelector](#idselector)
* [importantRule](#importantrule)
* [spaceAfterPropertyColon](#spaceafterpropertycolon)
* [spaceAfterPropertyName](#spaceafterpropertyname)
* [spaceBeforeBrace](#spacebeforebrace)
* [stringQuotes](#stringquotes)
* [trailingSemicolon](#trailingsemicolon)
* [urlFormat](#urlformat)
* [urlQuotes](#urlquotes)

@@ -44,4 +48,8 @@ ## borderZero

## duplicateProperty
There shouldn't be any duplicate properties.
There shouldn't be any duplicate properties since this is usually an error, causing unexpected bugs.
However, sometimes, there might be valid reasons such as a fallback for older browsers.
In these cases `lesshint` won't be able to know your intentions and will still report it,
if this is undesired the best option right now is to disable this linter altogether until we have a better solution in place.
### invalid

@@ -80,3 +88,3 @@ ```css

## finalNewline
All files should end with a empty line.
All files should end with a empty line to help create better diffs since the last line will always be untouched and therefore not marked as changed.

@@ -100,3 +108,3 @@ ### invalid

## hexLength
Prefer longhand hex color declarations over short hand ones.
Prefer longhand hex color declarations over short hand ones to be consistent with colors than can't be written using shorthand notation.

@@ -122,3 +130,3 @@ Option | Description

## hexNotation
Hex color declarations should be written in lowercase.
Hex color declarations should be written in lowercase to aid readability.

@@ -162,2 +170,3 @@ Option | Description

Disallow the usage of ID selectors.
ID selectors should be avoided since they introduce unnecessarily specific selectors which can't be easily overridden.

@@ -178,4 +187,22 @@ ### invalid

## importantRule
Disallow the usage of `!important`.
The use of `!important` is often due to a lack of understanding of CSS specificity.
### invalid
```css
#foo {
color: red !important;
}
```
### valid
```css
.foo {
color: red;
}
```
## spaceAfterPropertyColon
Each colon in property declarations should be followed by a space.
Each colon in property declarations should be followed by a space to aid readability.

@@ -222,3 +249,3 @@ Option | Description

## spaceBeforeBrace
A space should be present before opening braces.
A space should be present before opening braces to aid readability.

@@ -251,4 +278,26 @@ Option | Description

## stringQuotes
All strings should use single quotes since they are often easier to type since the `Shift` key doesn't need to be pressed.
Option | Description
---------- | ----------
`style` | `double`, `single` (**default**)
### invalid
```css
.foo {
content: "Hello world";
}
```
### valid
```css
.foo {
content: 'Hello world';
}
```
## trailingSemicolon
All property declarations should end with a semicolon.
Semicolons are optional after the last property in a ruleset but it's a good habit to always add them since one doesn't need to think about it when adding new properties afterwards.

@@ -268,1 +317,44 @@ ### invalid

```
## urlFormat
All URLs should be relative.
Using relative URLs increases portability and is actually recommended by the [CSS spec](http://dev.w3.org/csswg/css-values/#relative-urls).
Option | Description
---------- | ----------
`style` | `absolute`, `relative` (**default**)
### invalid
```css
.foo {
background-image: url('http://example.com/img/image.jpg');
}
```
### valid
```css
.foo {
background-image: url('img/image.jpg');
}
```
## urlQuotes
All URLs should be enclosed in quotes.
Using quotes around URLs allows them to be treated as strings, making escaping of characters easier.
The [CSS spec](http://dev.w3.org/csswg/css-values/#url-value) also recommends the use of quotes.
### invalid
```css
.foo {
background-image: url(img/image.jpg);
}
```
### valid
```css
.foo {
background-image: url('img/image.jpg');
}
```
Most of these rules are based on [@mdo](twitter.com/mdo)s [code guide](http://codeguide.co/#css).
'use strict';
var findIndex = require('lodash.findindex');
var path = require('path');
var findIndex = require('lodash.findindex');

@@ -15,3 +15,3 @@ module.exports = function (options) {

// Bail if the linter isn't wanted
if (config.spaceAfterPropertyColon && !config.spaceAfterPropertyColon.enabled) {
if (!config.spaceAfterPropertyColon || (config.spaceAfterPropertyColon && !config.spaceAfterPropertyColon.enabled)) {
return null;

@@ -18,0 +18,0 @@ }

'use strict';
var findIndex = require('lodash.findindex');
var path = require('path');
var findIndex = require('lodash.findindex');

@@ -15,3 +15,3 @@ module.exports = function (options) {

// Bail if the linter isn't wanted
if (config.spaceAfterPropertyName && !config.spaceAfterPropertyName.enabled) {
if (!config.spaceAfterPropertyName || (config.spaceAfterPropertyName && !config.spaceAfterPropertyName.enabled)) {
return null;

@@ -18,0 +18,0 @@ }

@@ -9,3 +9,3 @@ 'use strict';

var node = options.node;
var selector;
var maybeSpace;
var message;

@@ -15,3 +15,3 @@ var column;

// Bail if the linter isn't wanted
if (config.spaceBeforeBrace && !config.spaceBeforeBrace.enabled) {
if (!config.spaceBeforeBrace || (config.spaceBeforeBrace && !config.spaceBeforeBrace.enabled)) {
return null;

@@ -25,7 +25,8 @@ }

selector = node.content.pop().content.pop();
maybeSpace = node.content[node.content.length - 1];
maybeSpace = maybeSpace.content[maybeSpace.content.length - 1];
switch (config.spaceBeforeBrace.style) {
case 'no_space':
if (selector.type === 'space') {
if (maybeSpace.type === 'space') {
message = 'Opening curly brace should not be preceded by a space or new line.';

@@ -36,9 +37,9 @@ }

case 'one_space':
if (selector.type !== 'space' || (selector.type === 'space' && selector.content !== ' ')) {
if (maybeSpace.type !== 'space' || (maybeSpace.type === 'space' && maybeSpace.content !== ' ')) {
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;
if (maybeSpace.content[0].start) {
column = maybeSpace.content[0].start.column + maybeSpace.content[0].content.length;
} else {
column = selector.start.column + selector.content.length;
column = maybeSpace.start.column + maybeSpace.content.length;
}

@@ -49,3 +50,3 @@ }

case 'new_line':
if (selector.type !== 'space' || (selector.type === 'space' && selector.content !== '\n')) {
if (maybeSpace.type !== 'space' || (maybeSpace.type === 'space' && maybeSpace.content !== '\n')) {
message = 'Opening curly brace should be on it\'s own line.';

@@ -61,5 +62,5 @@ }

return {
column: column || selector.start.column,
column: column || maybeSpace.start.column,
file: filename,
line: selector.start.line,
line: maybeSpace.start.line,
linter: 'spaceBeforeBrace',

@@ -66,0 +67,0 @@ message: message

@@ -15,3 +15,3 @@ 'use strict';

// Bail if the linter isn't wanted
if (config.trailingSemicolon && !config.trailingSemicolon.enabled) {
if (!config.trailingSemicolon || (config.trailingSemicolon && !config.trailingSemicolon.enabled)) {
return null;

@@ -36,3 +36,3 @@ }

if (node.content[checkIndex + 1].type !== 'declarationDelimiter') {
start = node.content.pop().start;
start = node.content[node.content.length - 1].start;

@@ -39,0 +39,0 @@ return {

{
"name": "lesshint",
"description": "A tool to aid you in writing clean and consistent Less.",
"version": "0.3.1",
"version": "0.4.0",
"main": "./lib/lesshint.js",

@@ -24,3 +24,2 @@ "author": {

"gonzales-pe": "^3.0.0-26",
"lodash.clone": "^3.0.1",
"lodash.findindex": "^3.2.0",

@@ -27,0 +26,0 @@ "lodash.flatten": "^3.0.2",

@@ -6,7 +6,7 @@ var assert = require('assert');

var testDir = path.dirname(__dirname) + '/data/files';
var LessHint = require('../../lib/lesshint');
var Lesshint = require('../../lib/lesshint');
describe('checkDirectory', function () {
it('should check all files on all levels of a directory', function () {
var lesshint = new LessHint();
var lesshint = new Lesshint();

@@ -21,3 +21,3 @@ return lesshint.checkDirectory(testDir).then(function (errors) {

it('should check a single file', function () {
var lesshint = new LessHint();
var lesshint = new Lesshint();

@@ -32,3 +32,3 @@ return lesshint.checkFile(testDir + '/file.less').then(function (errors) {

it('should check all files and directories on all levels of a path', function () {
var lesshint = new LessHint();
var lesshint = new Lesshint();

@@ -44,3 +44,3 @@ return lesshint.checkPath(testDir).then(function (errors) {

var string = '.foo{ color: red; }\n';
var lesshint = new LessHint();
var lesshint = new Lesshint();
var errors = lesshint.checkString(string);

@@ -54,3 +54,3 @@

it('should set the config to use', function () {
var lesshint = new LessHint();
var lesshint = new Lesshint();
var expected = {

@@ -57,0 +57,0 @@ spaceAfterPropertyColon: {

@@ -212,3 +212,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { border: none; }';

@@ -231,2 +231,18 @@ var ast;

it('should return null when disabled via shorthand', function () {
var source = '.foo { border: none; }';
var ast;
var options = {
borderZero: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, borderZero({
config: options,
node: ast
}));
});
it('should throw on invalid "style" value', function () {

@@ -233,0 +249,0 @@ var source = '.foo { border: 0; }';

@@ -58,3 +58,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color: red; color: blue; }';

@@ -76,3 +76,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo { color: red; color: blue; }';
var ast;
var options = {
duplicateProperty: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block');
assert.equal(null, duplicateProperty({
config: options,
node: ast
}));
});
});
});

@@ -77,3 +77,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo {}';

@@ -95,3 +95,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo {}';
var ast;
var options = {
emptyRule: false
};
ast = linter.parseAST(source);
ast = ast.first();
assert.equal(null, emptyRule({
config: options,
node: ast
}));
});
});
});

@@ -56,3 +56,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo {}';

@@ -73,3 +73,18 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo {}';
var ast;
var options = {
finalNewline: false
};
ast = linter.parseAST(source);
assert.equal(null, finalNewline({
config: options,
node: ast
}));
});
});
});

@@ -183,3 +183,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color: #abc; }';

@@ -202,2 +202,18 @@ var ast;

it('should return null when disabled via shorthand', function () {
var source = '.foo { color: #abc; }';
var ast;
var options = {
hexLength: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, hexLength({
config: options,
node: ast
}));
});
it('should throw on invalid "style" value', function () {

@@ -204,0 +220,0 @@ var source = '.foo { color: #aabbcc; }';

@@ -143,3 +143,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color: #abc; }';

@@ -162,2 +162,18 @@ var ast;

it('should return null when disabled via shorthand', function () {
var source = '.foo { color: #abc; }';
var ast;
var options = {
hexNotation: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, hexNotation({
config: options,
node: ast
}));
});
it('should throw on invalid "style" value', function () {

@@ -164,0 +180,0 @@ var source = '.foo { color: #aabbcc; }';

@@ -108,3 +108,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color: #AABBC; }';

@@ -126,3 +126,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo { color: #AABBC; }';
var ast;
var options = {
hexValidation: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, hexValidation({
config: options,
node: ast
}));
});
});
});

@@ -58,3 +58,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo #bar {}';

@@ -76,3 +76,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo #bar {}';
var ast;
var options = {
idSelector: false
};
ast = linter.parseAST(source);
ast = ast.first().first('selector');
assert.equal(null, idSelector({
config: options,
node: ast
}));
});
});
});

@@ -195,3 +195,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color:red; }';

@@ -213,3 +213,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo { color:red; }';
var ast;
var options = {
spaceAfterPropertyColon: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, spaceAfterPropertyColon({
config: options,
node: ast
}));
});
});
});

@@ -131,3 +131,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color:red; }';

@@ -149,3 +149,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo { color:red; }';
var ast;
var options = {
spaceAfterPropertyName: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, spaceAfterPropertyName({
config: options,
node: ast
}));
});
});
});

@@ -437,3 +437,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo{ color: red; }';

@@ -455,3 +455,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo{ color: red; }';
var ast;
var options = {
spaceBeforeBrace: false
};
ast = linter.parseAST(source);
ast = ast.first().first('selector');
assert.equal(null, spaceBeforeBrace({
config: options,
node: ast
}));
});
});
});

@@ -111,3 +111,3 @@ var assert = require('assert');

it('should return null run when disabled', function () {
it('should return null when disabled', function () {
var source = '.foo { color: red }';

@@ -129,3 +129,19 @@ var ast;

});
it('should return null when disabled via shorthand', function () {
var source = '.foo { color: red }';
var ast;
var options = {
trailingSemicolon: false
};
ast = linter.parseAST(source);
ast = ast.first().first('block').first('declaration');
assert.equal(null, trailingSemicolon({
config: options,
node: ast
}));
});
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc