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

postcss-bem-linter

Package Overview
Dependencies
Maintainers
2
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

postcss-bem-linter - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

5

CHANGELOG.md

@@ -1,3 +0,6 @@

=== HEAD
=== 0.5.0 (August 5, 2015)
* Add alternate signature for designating preset and preset options.
* Remove checks that `:root` rules only contain custom-properties, and that the `:root` selector is not grouped or combined with other selectors. Outsourcing these checks to [stylelint](https://github.com/stylelint/stylelint).
=== 0.4.0 (June 23, 2015)

@@ -4,0 +7,0 @@

103

index.js

@@ -1,7 +0,1 @@

'use strict';
/**
* Module dependencies
*/
var postcss = require('postcss');

@@ -11,3 +5,2 @@ var validateCustomProperties = require('./lib/validate-properties');

var validateSelectors = require('./lib/validate-selectors');
var validateRules = require('./lib/validate-rules');
var presetPatterns = require('./lib/preset-patterns');

@@ -19,57 +12,61 @@

/**
* Check patterns or setup defaults. If the input CSS does not have a
* Set things up and call the validators.
*
* If the input CSS does not have a
* directive defining a component name according to the specified pattern,
* do nothing -- or warn, if the directive is there but the name does not match.
* Then call all of the validators.
*
* @param {Object} [patterns = 'suit']
* @param {RegExp} [patterns.componentName]
* @param {RegExp} [patterns.utilitySelectors]
* @param {Object|Function} [patterns.componentSelectors]
* @param {Object} [opts] - Options that are can be used by
* @param {Object|String} [primaryOptions = 'suit']
* @param {RegExp} [primaryOptions.componentName]
* @param {RegExp} [primaryOptions.utilitySelectors]
* @param {Object|Function} [primaryOptions.componentSelectors]
* @param {String} [primaryOptions.preset] - The same as passing a string for `primaryOptions`
* @param {Object} [primaryOptions.presetOptions] - Options that are can be used by
* a pattern (e.g. `namespace`)
* @param {Object} [secondaryOptions] - The same as `primaryOptions.presetOptions`
*/
module.exports = postcss.plugin(
'postcss-bem-linter',
function (patterns, opts) {
patterns = patterns || 'suit';
if (typeof patterns === 'string') {
patterns = presetPatterns[patterns];
}
var componentNamePattern = patterns.componentName || /[-_a-zA-Z0-9]+/;
module.exports = postcss.plugin('postcss-bem-linter', function(primaryOptions, secondaryOptions) {
var patterns = primaryOptions || 'suit';
if (typeof patterns === 'string') {
patterns = presetPatterns[patterns];
} else if (patterns.preset) {
patterns = presetPatterns[patterns.preset];
}
return function (styles, result) {
return new Promise(function (resolve) {
var firstNode = styles.nodes[0];
if (!firstNode || firstNode.type !== 'comment') { resolve(); }
var presetOptions = secondaryOptions || {};
if (primaryOptions && primaryOptions.presetOptions) {
presetOptions = primaryOptions.presetOptions;
}
var initialComment = firstNode.text;
if (!initialComment || !initialComment.match(RE_DIRECTIVE)) {
resolve();
}
var componentNamePattern = patterns.componentName || /[-_a-zA-Z0-9]+/;
var defined = initialComment.match(RE_DIRECTIVE)[1].trim();
var isUtilities = defined === UTILITIES_IDENT;
if (!isUtilities && !defined.match(componentNamePattern)) {
result.warn(
'Invalid component name in definition /*' + initialComment + '*/',
{ node: firstNode }
);
}
return function(root, result) {
var firstNode = root.nodes[0];
if (!firstNode || firstNode.type !== 'comment') return;
var weakMode = initialComment.match(RE_DIRECTIVE)[2] === 'weak';
var initialComment = firstNode.text;
if (!initialComment || !initialComment.match(RE_DIRECTIVE)) return;
validateRules(styles, result);
if (isUtilities) {
validateUtilities(styles, patterns.utilitySelectors, result);
} else {
validateSelectors(
styles, defined, weakMode, patterns.componentSelectors, opts, result
);
}
validateCustomProperties(styles, defined, result);
resolve();
});
};
}
);
var defined = initialComment.match(RE_DIRECTIVE)[1].trim();
var isUtilities = defined === UTILITIES_IDENT;
if (!isUtilities && !defined.match(componentNamePattern)) {
result.warn(
'Invalid component name in definition /*' + initialComment + '*/',
{ node: firstNode }
);
}
var weakMode = initialComment.match(RE_DIRECTIVE)[2] === 'weak';
if (isUtilities) {
validateUtilities(root, patterns.utilitySelectors, result);
return;
}
validateSelectors(
root, defined, weakMode, patterns.componentSelectors, presetOptions, result
);
validateCustomProperties(root, defined, result);
console.log(result.messages)
};
});

@@ -1,16 +0,4 @@

'use strict';
/**
* Module dependencies
*/
var listSequences = require('./listSequences');
/**
* Module exports
*/
module.exports = isValidSelector;
/**
* A SelectorPattern defines acceptable patterns for selector sequences

@@ -48,14 +36,14 @@ * in component stylesheets.

* SelectorPattern, as described above
* @param {Object} [opts] - Options to pass to the pattern functions
* @param {Object} [presetOptions] - Options to pass to the pattern functions
* @returns {Boolean}
*/
function isValidSelector(selector, componentName, weakMode, pattern, opts) {
module.exports = function(selector, componentName, weakMode, pattern, presetOptions) {
// Don't bother with :root
if (selector === ':root') { return true; }
if (selector === ':root') return true;
var initialPattern = (pattern.initial) ?
pattern.initial(componentName, opts) :
pattern(componentName, opts);
pattern.initial(componentName, presetOptions) :
pattern(componentName, presetOptions);
var combinedPattern = (pattern.combined) ?
pattern.combined(componentName, opts) :
pattern.combined(componentName, presetOptions) :
initialPattern;

@@ -65,12 +53,12 @@ var sequences = listSequences(selector);

// Error if an acceptable initialPattern does not begin the selector
if (!initialPattern.test(sequences[0])) { return false; }
if (!initialPattern.test(sequences[0])) return false;
// Unless in weak mode, error if combined simple selectors do not match the
// combinedPattern
if (weakMode) { return true; }
if (weakMode) return true;
return sequences.slice(1).every(function (combinedSequence) {
return initialPattern.test(combinedSequence) ||
combinedPattern.test(combinedSequence);
return sequences.slice(1).every(function(combinedSequence) {
return initialPattern.test(combinedSequence)
|| combinedPattern.test(combinedSequence);
});
}

@@ -1,16 +0,4 @@

'use strict';
/**
* Module dependencies
*/
var listSequences = require('./listSequences');
/**
* Module exports
*/
module.exports = isValidUtility;
/**
* @param {String} selector

@@ -20,7 +8,7 @@ * @param {RegExp} pattern

*/
function isValidUtility(selector, pattern) {
module.exports = function(selector, pattern) {
var sequences = listSequences(selector);
return sequences.every(function (sequence) {
return sequences.every(function(sequence) {
return pattern.test(sequence);
});
}

@@ -1,3 +0,1 @@

module.exports = listSequences;
/**

@@ -7,3 +5,3 @@ * Extract an array of selector sequences from a selector string ---

*
* CSS combinators are whitespace, >, +, ~
* CSS combinators are " ", >, +, ~
* (cf. http://www.w3.org/TR/css3-selectors/#selector-syntax)

@@ -17,11 +15,11 @@ *

*/
function listSequences(selector) {
module.exports = function(selector) {
return selector
.split(/[\s>+~]/)
.filter(function (s) {
.filter(function(s) {
return s !== '';
})
.map(function (s) {
.map(function(s) {
return s.split(':')[0];
});
}

@@ -1,7 +0,1 @@

'use strict';
/**
* Module exports
*/
module.exports = {

@@ -11,8 +5,8 @@ suit: {

componentSelectors: suitSelector,
utilitySelectors: /^\.u(?:-[a-z][a-zA-Z0-9]+)+$/
utilitySelectors: /^\.u(?:-[a-z][a-zA-Z0-9]+)+$/,
},
bem: {
componentName: /[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*/,
componentSelectors: bemSelector
}
componentSelectors: bemSelector,
},
};

@@ -22,8 +16,8 @@

* @param {String} componentName
* @param {Object} [opts]
* @param {String} [opts.namespace]
* @param {Object} [presetOptions]
* @param {String} [presetOptions.namespace]
* @returns {RegExp}
*/
function suitSelector(componentName, opts) {
var ns = (opts && opts.namespace) ? opts.namespace + '-' : '';
function suitSelector(componentName, presetOptions) {
var ns = (presetOptions && presetOptions.namespace) ? presetOptions.namespace + '-' : '';
var OPTIONAL_PART = '(?:-[a-zA-Z0-9]+)?';

@@ -30,0 +24,0 @@ var OPTIONAL_MODIFIER = '(?:--[a-zA-Z0-9]+)?';

@@ -1,16 +0,2 @@

'use strict';
/**
* Module dependencies
*/
var isValidRule = require('./is-valid-rule');
/**
* Module exports
*/
module.exports = validateCustomProperties;
/**
* @param {Object} styles

@@ -20,18 +6,12 @@ * @param {String} componentName

*/
function validateCustomProperties(styles, componentName, result) {
styles.eachRule(function (rule) {
if (!isValidRule(rule) || rule.selectors[0] !== ':root') { return; }
module.exports = function(styles, componentName, result) {
styles.eachRule(function(rule) {
if (rule.selectors[0] !== ':root') return;
rule.eachDecl(function (declaration, i) {
rule.eachDecl(function(declaration, i) {
var property = declaration.prop;
if (property.indexOf('--') !== 0) {
if (property.indexOf(componentName + '-') !== 2) {
result.warn(
'Invalid custom property name "' + property + '": ' +
'`:root` rules must only contain custom properties',
{ node: declaration }
);
} else if (property.indexOf(componentName + '-') !== 2) {
result.warn(
'Invalid custom property name "' + property + '": ' +
'a component\'s custom properties must start with the ' +

@@ -38,0 +18,0 @@ 'component name',

@@ -1,7 +0,1 @@

'use strict';
/**
* Module dependencies
*/
var isValid = require('./is-valid-selector');

@@ -11,8 +5,2 @@ var IGNORE_COMMENT = 'postcss-bem-linter: ignore';

/**
* Module exports
*/
module.exports = validateSelectors;
/**
* @param {Object} styles

@@ -22,20 +10,21 @@ * @param {String} componentName

* @param {Object} pattern
* @param {Object} opts
* @param {Object} presetOptions
* @param {Result} result - PostCSS Result, for registering warnings
*/
function validateSelectors(
styles, componentName, weakMode, pattern, opts, result
) {
styles.eachRule(function (rule) {
if (rule.parent && rule.parent.name === 'keyframes') { return; }
module.exports = function(styles, componentName, weakMode, pattern, presetOptions, result) {
styles.eachRule(function(rule) {
if (rule.parent && rule.parent.name === 'keyframes') return;
var prev = rule.prev();
if (prev && prev.type === 'comment'
&& prev.text === IGNORE_COMMENT) { return; }
if (
prev
&& prev.type === 'comment'
&& prev.text === IGNORE_COMMENT
) return;
var selectors = rule.selectors;
selectors.forEach(function (selector) {
selectors.forEach(function(selector) {
// selectors must start with the componentName class, or be `:root`
if (!isValid(selector, componentName, weakMode, pattern, opts)) {
if (!isValid(selector, componentName, weakMode, pattern, presetOptions)) {
result.warn(

@@ -42,0 +31,0 @@ 'Invalid component selector "' + selector + '"',

@@ -1,16 +0,4 @@

'use strict';
/**
* Module dependencies
*/
var isValid = require('./is-valid-utility');
/**
* Module exports
*/
module.exports = validateSelectors;
/**
* @param {Object} styles

@@ -20,5 +8,5 @@ * @param {RegExp} pattern

*/
function validateSelectors(styles, pattern, result) {
styles.eachRule(function (rule) {
rule.selectors.forEach(function (selector) {
module.exports = function(styles, pattern, result) {
styles.eachRule(function(rule) {
rule.selectors.forEach(function(selector) {
if (!isValid(selector, pattern)) {

@@ -25,0 +13,0 @@ result.warn(

{
"name": "postcss-bem-linter",
"version": "0.4.0",
"version": "0.5.0",
"description": "A BEM linter for postcss",

@@ -13,3 +13,3 @@ "files": [

"devDependencies": {
"eslint": "0.23.0",
"eslint": "1.0.0",
"mocha": "2.2.5"

@@ -25,3 +25,3 @@ },

"type": "git",
"url": "git://github.com/necolas/postcss-bem-linter.git"
"url": "git://github.com/postcss/postcss-bem-linter.git"
},

@@ -28,0 +28,0 @@ "keywords": [

@@ -14,3 +14,3 @@ # postcss-bem-linter

With this plugin, you can check the validity of stylesheets against a set of BEM-style conventions.
**With this plugin, you can check the validity of selectors against a set of BEM-style conventions.**
You can use preset patterns (SUIT and BEM, currently) or insert your own. The plugin will register

@@ -25,3 +25,3 @@ warnings if it finds CSS that does not follow the specified conventions.

This plugin registers warnings via PostCSS. Therefore, you'll want to use it with a PostCSS runner that prints warnings (e.g. [`gulp-postcss`](https://github.com/postcss/gulp-postcss)) or another PostCSS plugin that prints warnings (e.g. [`postcss-log-warnings`](https://github.com/davidtheclark/postcss-log-warnings)).
This plugin registers warnings via PostCSS. Therefore, you'll want to use it with a PostCSS runner that prints warnings (e.g. [`gulp-postcss`](https://github.com/postcss/gulp-postcss)) or another PostCSS plugin that prints warnings (e.g. [`postcss-reporter`](https://github.com/postcss/postcss-reporter)).

@@ -34,4 +34,2 @@ ## Conformance tests

* Only allow custom-property names that *begin* with the defined `ComponentName`.
* The `:root` selector can only contain custom-properties.
* The `:root` cannot be combined with other selectors.

@@ -43,2 +41,4 @@ **Weak mode**:

*Prior to 0.5.0, this plugin checked two other details: that `:root` rules only contain custom-properties; and that the `:root` selector is not grouped or combined with other selectors. These checks can now be performed by [stylelint](https://github.com/stylelint/stylelint). So from 0.5.0 onwards, this plugin leaves that business to stylelint to focus on its more unique task.*
## Use

@@ -59,11 +59,8 @@

Also note that *pseudo-classes and pseudo-elements must be at the end of sequences, and
will be ignored*. Instead of `.Component:first-child.is-open` you should use
`.Component.is-open:first-child`. The former will trigger a warning.
Also note that *pseudo-classes and pseudo-elements will be ignored if they occur at the end of the sequence*.
Instead of `.Component:first-child.is-open`, you should use `.Component.is-open:first-child`.
The former will trigger a warning unless you've written a silly complicated regular expression.
#### Preset Patterns
You can use a preset pattern by passing a string as the `pattern`, and, if needed, an `options` object,
as in `bemLinter('suit', { namespace: 'twt' })`. Options are pattern-specific.
The following preset patterns are available:

@@ -77,2 +74,7 @@

You can use a preset pattern and its options in two ways:
- pass the preset's name as the first argument, and, if needed, an `options` object as the second,
e.g. `bemLinter('suit', { namespace: 'twt' })`.
- pass an object as the first and only argument, with the preset's name as the `preset` property and, if need, `presetOptions`, e.g. `bemLinter({ preset: 'suit', presetOptions { namespace: 'twt' })`.
**`'suit'` is the default pattern**; so if you do not pass any `pattern` argument,

@@ -83,3 +85,3 @@ SUIT conventions will be enforced.

You can define a custom pattern by passing an object with the following properties:
You can define a custom pattern by passing as your first and only argument an object with the following properties:

@@ -108,2 +110,3 @@ - `componentName` (optional): A regular expression describing valid component names.

bemLinter('suit', { namespace: 'twt' });
bemLinter({ preset: 'suit', presetOptions: { namespace: 'twt' }});

@@ -213,3 +216,3 @@ // use 'bem' conventions

conformance failures, which you can print to the console using
[`postcss-log-warnings`](https://github.com/davidtheclark/postcss-log-warnings) or relying
[`postcss-reporter`](https://github.com/postcss/postcss-reporter) or relying
on a PostCSS runner (such as [`gulp-postcss`](https://github.com/postcss/gulp-postcss)).

@@ -220,9 +223,9 @@

var bemLinter = require('postcss-bem-linter');
var logWarnings = require('postcss-log-warnings');
var reporter = require('postcss-reporter');
files.forEach(function (file) {
files.forEach(function(file) {
var css = fs.readFileSync(file, 'utf-8');
postcss()
.use(bemLinter())
.use(logWarnings())
.use(reporter())
.process(css)

@@ -229,0 +232,0 @@ .then(function(result) { .. });

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