bemlinter.js
Advanced tools
Comparing version 0.2.0 to 0.4.0
{ | ||
"name": "bemlinter.js", | ||
"version": "0.2.0", | ||
"version": "0.4.0", | ||
"description": "BEM linter", | ||
@@ -38,3 +38,3 @@ "main": "index.js", | ||
"engines": { | ||
"node": ">=5.0.0" | ||
"node": ">=6" | ||
}, | ||
@@ -41,0 +41,0 @@ "devDependencies": { |
@@ -1,2 +0,2 @@ | ||
bemlinter.js | ||
bemlinter.js [![Build Status](https://travis-ci.org/tzi/bemlinter.js.svg?branch=master)](https://travis-ci.org/tzi/bemlinter.js) | ||
====== | ||
@@ -16,3 +16,3 @@ | ||
```sh | ||
npm i bemlinter --save | ||
npm i bemlinter.js --save | ||
``` | ||
@@ -48,9 +48,12 @@ | ||
{ | ||
// Define the sources file | ||
// Define the paths of your source files | ||
"sources": [ | ||
"a/path/to/your/scss/*.scss", | ||
"a/path/to/a/specific/scss/main.scss", | ||
"!an/exclude/path/of/scss/*.scss" | ||
"a/path/to/a/specific/scss/main.scss | ||
], | ||
// Define the sources file that are not a component yet, so the linter will be kind ;) | ||
// Define the paths of some exclude source files | ||
"excludePath": [ | ||
"an/exclude/path/of/scss/*.scss" | ||
], | ||
// Define the names of some component that are not isolated yet, so the linter will be kind ;) | ||
"excludeComponent": [ | ||
@@ -60,3 +63,7 @@ "messed-up-component", | ||
"old-component" | ||
] | ||
], | ||
// Optionally disable some check | ||
"options": { | ||
"checkLowerCase": false | ||
} | ||
} | ||
@@ -63,0 +70,0 @@ ``` |
@@ -15,7 +15,15 @@ const _ = require('lodash'); | ||
function eachWrapper(wrapper, fn) { | ||
for (let n of wrapper.nodes) { fn(n) } | ||
} | ||
// Logs | ||
const logs = []; | ||
let _logs = []; | ||
let _defaultOptions = { | ||
checkLowerCase: true | ||
}; | ||
let _options = {}; | ||
function addLog(type, message, filePath, blockName, wrapper) { | ||
logs.push({ | ||
_logs.push({ | ||
type, | ||
@@ -48,9 +56,3 @@ message, | ||
function getBlockNameFromClass(className) { | ||
if (className.indexOf('__') != -1) { | ||
return className.slice(0, className.indexOf('__')); | ||
} | ||
if (className.indexOf('--') != -1) { | ||
return className.slice(0, className.indexOf('--')); | ||
} | ||
return className; | ||
return className.split('__')[0].split('--')[0]; | ||
} | ||
@@ -76,3 +78,3 @@ | ||
function checkInternalClassName($, filePath, blockName) { | ||
return $('class').find('identifier').reduce((fileLogs, wrapper) => { | ||
eachWrapper($('class').find('identifier'), wrapper => { | ||
const className = wrapper.node.value; | ||
@@ -82,9 +84,7 @@ if (!isBlockName(className, blockName)) { | ||
} | ||
return fileLogs; | ||
}, []); | ||
}); | ||
} | ||
function checkExternalClassName($, filePath, blockList, authorizedBlockName) { | ||
return $('class').find('identifier').reduce((fileLogs, wrapper) => { | ||
eachWrapper($('class').find('identifier'), wrapper => { | ||
const className = wrapper.node.value; | ||
@@ -99,7 +99,29 @@ if (isBlockNameOneOf(className, blockList, authorizedBlockName)) { | ||
} | ||
return fileLogs; | ||
}, []); | ||
}); | ||
} | ||
function checkBemSyntaxClassName($, filePath, blockName) { | ||
eachWrapper($('class').find('identifier'), wrapper => { | ||
const className = wrapper.node.value; | ||
if (_options.checkLowerCase && className !== className.toLowerCase()) { | ||
addError(`".${className}" should be in lower case.`, filePath, blockName, wrapper); | ||
} | ||
if (/___/.test(className)) { | ||
addError(`".${className}" element should have only 2 underscores.`, filePath, blockName, wrapper); | ||
} | ||
if (/---/.test(className)) { | ||
addError(`".${className}" modifier should have only 2 dashes.`, filePath, blockName, wrapper); | ||
} | ||
if (/--[^-]+--/.test(className)) { | ||
addError(`".${className}" should have a single modifier.`, filePath, blockName, wrapper); | ||
} | ||
if (/__[^-]+__/.test(className)) { | ||
addError(`".${className}" should have a single depth of element.`, filePath, blockName, wrapper); | ||
} | ||
if (/--[^-]+__/.test(className)) { | ||
addError(`".${className}" represents an element of a modifier, it should be cut in 2 classes.`, filePath, blockName, wrapper); | ||
} | ||
}); | ||
} | ||
// Main | ||
@@ -113,3 +135,4 @@ function bemLintFile(filePath, blockList) { | ||
const $ = createQueryAst(ast); | ||
checkBemSyntaxClassName($, filePath, blockName); | ||
if (blockList.indexOf(blockName) !== -1) { | ||
@@ -128,3 +151,5 @@ checkInternalClassName($, filePath, blockName); | ||
module.exports = (sources, excludeComponent = []) => { | ||
module.exports = (sources, excludeComponent = [], options) => { | ||
_logs = []; | ||
_options = _.merge(_defaultOptions, options); | ||
const blockList = globby.sync(sources, { | ||
@@ -138,3 +163,3 @@ ignore: excludeComponent | ||
return _.mapValues( | ||
groupByAndOmit(_.flatten(logs), 'blockName'), | ||
groupByAndOmit(_.flatten(_logs), 'blockName'), | ||
blockLog => groupByAndOmit(blockLog, 'type') | ||
@@ -141,0 +166,0 @@ ); |
@@ -41,3 +41,4 @@ #!/usr/bin/env node | ||
sources: argv._, | ||
excludeComponent: [] | ||
excludeComponent: [], | ||
options: {} | ||
}; | ||
@@ -52,5 +53,11 @@ | ||
.then(config => { | ||
config.excludeComponent = config.excludeComponent.map(path => `**/${path}.scss`); | ||
config.excludePath = config.excludePath.map(filePath => `!${path.resolve(filePath)}`); | ||
config.sources = config.sources | ||
.map(filePath => path.resolve(filePath)) | ||
.concat(config.excludePath) | ||
; | ||
config.excludeComponent = config.excludeComponent.map(component => `**/${component}.scss`); | ||
resolve(config); | ||
}) | ||
.catch(console.error); | ||
; | ||
@@ -64,3 +71,3 @@ }) | ||
return bemlinter(config.sources, config.excludeComponent) | ||
return bemlinter(config.sources, config.excludeComponent, config.options); | ||
}) | ||
@@ -67,0 +74,0 @@ .then(logs => { |
TODO | ||
====== | ||
Multi-file tests | ||
------ | ||
* [ ] Create a test for a tolerated dependency (warning) | ||
* [ ] Create a test for a block style in another stylesheet (error) | ||
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
60454
246
86
0