postcss-bem-linter
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -0,4 +1,11 @@ | ||
=== 1.1.0 (September 18, 2015) | ||
* Support selective overriding of a chosen preset's patterns. | ||
* Support `ignoreSelectors` pattern. | ||
* Support ignoring utility selectors with a preceding comment. | ||
* Add helpful error messages when user configuration is lacking patterns. | ||
=== 1.0.1 (August 30, 2015) | ||
* Use PostCSS's improved warning API to provide more precise locations | ||
* Use PostCSS's improved warning API to provide more precise locations. | ||
@@ -45,1 +52,2 @@ === 1.0.0 (August 26, 2015) | ||
* Initial release. Ported from rework-suit-conformance. | ||
e1iv |
21
index.js
@@ -46,5 +46,23 @@ var postcss = require('postcss'); | ||
if (range.defined === UTILITIES_IDENT) { | ||
validateUtilities(rule, config.patterns.utilitySelectors, result); | ||
if (!config.patterns.utilitySelectors) { | ||
throw new Error( | ||
'You tried to `@define utilities` but have not provided ' + | ||
'a `utilitySelectors` pattern' | ||
); | ||
} | ||
validateUtilities({ | ||
rule: rule, | ||
utilityPattern: config.patterns.utilitySelectors, | ||
ignorePattern: config.patterns.ignoreSelectors, | ||
result: result, | ||
}); | ||
return; | ||
} | ||
if (!config.patterns.componentSelectors) { | ||
throw new Error( | ||
'You tried to `@define` a component but have not provided ' + | ||
'a `componentSelectors` pattern' | ||
); | ||
} | ||
validateCustomProperties(rule, range.defined, result); | ||
@@ -57,2 +75,3 @@ validateSelectors({ | ||
selectorPatternOptions: config.presetOptions, | ||
ignorePattern: config.patterns.ignoreSelectors, | ||
result: result, | ||
@@ -59,0 +78,0 @@ }); |
@@ -11,2 +11,3 @@ var presetPatterns = require('./preset-patterns'); | ||
* @param {Object|Function} [primaryOptions.componentSelectors] | ||
* @param {RegExp} [primaryOptions.ignoreSelectors] | ||
* @param {String} [primaryOptions.preset] - The same as passing a string for `primaryOptions` | ||
@@ -24,2 +25,16 @@ * @param {Object} [primaryOptions.presetOptions] - Options that are can be used by | ||
patterns = presetPatterns[patterns.preset]; | ||
// Enable overriding of preset patterns | ||
if (primaryOptions.utilitySelectors) { | ||
patterns.utilitySelectors = primaryOptions.utilitySelectors; | ||
} | ||
if (primaryOptions.componentName) { | ||
patterns.componentName = primaryOptions.componentName; | ||
} | ||
if (primaryOptions.componentSelectors) { | ||
patterns.componentSelectors = primaryOptions.componentSelectors; | ||
} | ||
if (primaryOptions.ignoreSelectors) { | ||
patterns.ignoreSelectors = primaryOptions.ignoreSelectors; | ||
} | ||
} | ||
@@ -26,0 +41,0 @@ |
var listSequences = require('./list-sequences'); | ||
var shouldIgnoreRule = require('./should-ignore-rule'); | ||
var IGNORE_COMMENT = 'postcss-bem-linter: ignore'; | ||
/** | ||
@@ -12,2 +11,3 @@ * @param {Object} config | ||
* @param {Object} config.selectorPatternOptions | ||
* @param {RegExp} config.ignorePattern | ||
* @param {Result} config.result - PostCSS Result, for registering warnings | ||
@@ -17,47 +17,35 @@ */ | ||
if (config.rule.parent && config.rule.parent.name === 'keyframes') return; | ||
if (shouldIgnoreRule(config.rule)) return; | ||
var prev = config.rule.prev(); | ||
if ( | ||
prev | ||
&& prev.type === 'comment' | ||
&& prev.text === IGNORE_COMMENT | ||
) return; | ||
var initialPattern = (config.selectorPattern.initial) | ||
? config.selectorPattern.initial(config.componentName, config.selectorPatternOptions) | ||
: config.selectorPattern(config.componentName, config.selectorPatternOptions); | ||
var combinedPattern = (config.selectorPattern.combined) | ||
? config.selectorPattern.combined(config.componentName, config.selectorPatternOptions) | ||
: initialPattern; | ||
var selectors = config.rule.selectors; | ||
selectors.forEach(function(selector) { | ||
if (isValid(selector)) return; | ||
config.result.warn( | ||
'Invalid component selector "' + selector + '"', | ||
{ | ||
node: config.rule, | ||
word: selector, | ||
} | ||
); | ||
}); | ||
function isValid(selector) { | ||
// Don't bother with :root | ||
if (selector === ':root') return true; | ||
if (selector === ':root') return; | ||
var initialPattern = (config.selectorPattern.initial) ? | ||
config.selectorPattern.initial(config.componentName, config.selectorPatternOptions) : | ||
config.selectorPattern(config.componentName, config.selectorPatternOptions); | ||
var combinedPattern = (config.selectorPattern.combined) ? | ||
config.selectorPattern.combined(config.componentName, config.selectorPatternOptions) : | ||
initialPattern; | ||
var sequences = listSequences(selector); | ||
var allSequences = listSequences(selector); | ||
var sequence; | ||
for (var i = 0, l = allSequences.length; i < l; i++) { | ||
if (config.weakMode && i !== 0) return; | ||
sequence = allSequences[i]; | ||
if (config.ignorePattern && config.ignorePattern.test(sequence)) continue; | ||
if (i === 0 && initialPattern.test(sequence)) continue; | ||
if (i !== 0 && combinedPattern.test(sequence)) continue; | ||
// Not valid if an initialPattern does not begin the selector | ||
if (!initialPattern.test(sequences[0])) return false; | ||
// Unless in weak mode, not valid if combined simple selectors do not match the | ||
// combinedPattern | ||
if (config.weakMode) return true; | ||
return sequences.slice(1).every(function(combinedSequence) { | ||
return initialPattern.test(combinedSequence) | ||
|| combinedPattern.test(combinedSequence); | ||
}); | ||
} | ||
config.result.warn( | ||
'Invalid component selector "' + selector + '"', | ||
{ | ||
node: config.rule, | ||
word: selector, | ||
} | ||
); | ||
return; | ||
} | ||
}); | ||
} |
var listSequences = require('./list-sequences'); | ||
var shouldIgnoreRule = require('./should-ignore-rule'); | ||
/** | ||
* @param {Rule} rule - PostCSS Rule | ||
* @param {RegExp} pattern | ||
* @param {Result} result - PostCSS Result, for registering warnings | ||
* @param {Object} config | ||
* @param {Rule} config.rule - PostCSS Rule | ||
* @param {RegExp} config.utilityPattern | ||
* @param {RegExp} config.ignorePattern | ||
* @param {Result} config.result - PostCSS Result, for registering warnings | ||
*/ | ||
module.exports = function(rule, pattern, result) { | ||
rule.selectors.forEach(function(selector) { | ||
if (isValid(selector, pattern)) return; | ||
result.warn( | ||
'Invalid utility selector "' + selector + '"', | ||
{ | ||
node: rule, | ||
word: selector, | ||
} | ||
); | ||
}); | ||
} | ||
module.exports = function(config) { | ||
if (shouldIgnoreRule(config.rule)) return; | ||
function isValid(selector, pattern) { | ||
var sequences = listSequences(selector); | ||
return sequences.every(function(sequence) { | ||
return pattern.test(sequence); | ||
config.rule.selectors.forEach(function(selector) { | ||
var allSequences = listSequences(selector); | ||
var sequence; | ||
for (var i = 0, l = allSequences.length; i < l; i++) { | ||
sequence = allSequences[i]; | ||
if (config.ignorePattern && config.ignorePattern.test(sequence)) continue; | ||
if (config.utilityPattern.test(sequence)) continue; | ||
config.result.warn( | ||
'Invalid utility selector "' + selector + '"', | ||
{ | ||
node: config.rule, | ||
word: selector, | ||
} | ||
); | ||
return; | ||
} | ||
}); | ||
} |
{ | ||
"name": "postcss-bem-linter", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "A BEM linter for postcss", | ||
@@ -5,0 +5,0 @@ "files": [ |
@@ -97,8 +97,22 @@ # postcss-bem-linter | ||
- In weak mode, *any* combined sequences are accepted. | ||
- `utilitySelectors`: A regular expression describing valid utility selectors. This will be use | ||
- `utilitySelectors`: A regular expression describing valid utility selector sequences. This will be used | ||
if the stylesheet defines a group of utilities, as explained below. | ||
- `ignoreSelectors`: A regular expression describing selector sequences to ignore. You can use this to | ||
systematically ignore selectors matching this pattern, instead of having to add a | ||
`/* postcss-bem-linter: ignore */` comment above each one (see below). | ||
So you might call the plugin in any of the following ways: | ||
*You can also choose a preset to start with and override specific patterns.* | ||
For example, if you want to use SUIT's `componentSelectors` pattern but write your own `utilitySelectors` pattern, | ||
you can do that with a config object like this: | ||
```js | ||
{ | ||
preset: 'suit', | ||
utilitySelectors: /\.fancyUtilities-[a-z]+/ | ||
} | ||
``` | ||
Given all of the above, you might call the plugin in any of the following ways: | ||
```js | ||
// use 'suit' conventions | ||
@@ -138,2 +152,10 @@ bemLinter(); | ||
}); | ||
// start with the `bem` preset but include a special `componentName` pattern | ||
// and `ignoreSelectors` pattern to ignore Modernizr-injected `no-*` classes | ||
bemLinter({ | ||
preset: 'bem', | ||
componentName: /cmpnt_[a-zA-Z]+/, | ||
ignoreSelectors: /\.no-.+/ | ||
}) | ||
``` | ||
@@ -246,3 +268,8 @@ | ||
If you need to ignore a specific selector but do not want to ignore the entire stylesheet | ||
or end the enforcement of a definition, | ||
or end the enforcement of a definition, there are two ways to accomplish this: | ||
As describe above, you can include an `ignoreSelectors` regular expression in your configuration. | ||
This is the best approach if you want to systematically ignore all selectors matching a pattern (e.g. all Modernizr classes). | ||
If you just want to ignore a single, isolated selector, though, | ||
you can do so by *preceding the selector* with this comment: `/* postcss-bem-linter: ignore */`. | ||
@@ -263,3 +290,3 @@ | ||
*This will cause the linter to ignore **only** the very next selector.* | ||
*The comment will cause the linter to ignore **only** the very next selector.* | ||
@@ -266,0 +293,0 @@ ### Testing CSS files |
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
25261
12
313
330