stylelint-selector-pattern

A stylelint plugin that allows to check selectors with regular expressions.
git clone https://git.ce9e.org/stylelint-selector-pattern.git

commit
06be400da1dfb9eb9e42494ae0f7c23af6542f42
parent
1e18630d710fcde0b3026466b27de0d6c8982fdc
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2017-02-17 07:40
split code across files

Diffstat

M index.js 86 ++++++++++---------------------------------------------------
A lib/presets.js 22 ++++++++++++++++++++++
A lib/util.js 21 +++++++++++++++++++++
A lib/validate.js 26 ++++++++++++++++++++++++++
M package.json 2 +-

5 files changed, 83 insertions, 74 deletions


diff --git a/index.js b/index.js

@@ -1,29 +1,9 @@
    1     1 var stylelint = require("stylelint");
    2    -1 var resolvedNestedSelector = require('postcss-resolve-nested-selector');
    3     2 var _ = require('lodash');
    4     3 
    5    -1 var presets = {
    6    -1   bem: ["^({block}({element})?({modifier})?({pseudo})?|{utility})$", {
    7    -1     subpatterns: {
    8    -1       block: "\.[a-z][a-z0-9-]+",
    9    -1       modifier: "--[a-z][a-z0-9-]+",
   10    -1       element: "__[a-z][a-z0-9-]+",
   11    -1       utility: "\.u-[a-z][a-z0-9-]+",
   12    -1       pseudo: "::?[a-z-]+"
   13    -1     }
   14    -1   }],
   15    -1   suit: ["^({component}({descendent})?({modifier})?({state})?({pseudo})?|{utility})$", {
   16    -1     subpatterns: {
   17    -1       component: "\.[A-Z][a-zA-Z0-9]+",
   18    -1       modifier: "--[a-z][a-zA-Z0-9]+",
   19    -1       descendent: "-[a-z][a-zA-Z0-9]+",
   20    -1       state: "\.(is|has)-[a-zA-Z0-9]+",
   21    -1       utility: "\.u-[a-z][a-zA-Z0-9]+",
   22    -1       pseudo: "::?[a-z-]+"
   23    -1     }
   24    -1   }],
   25    -1   itcss: ["^\.(o-|c-|u-|t-|s-|is-|has-|_|js-|qa-)[a-z0-9-]+"]
   26    -1 };
   -1     4 var util = require('./lib/util');
   -1     5 var presets = require('./lib/presets');
   -1     6 var validate = require('./lib/validate');
   27     7 
   28     8 var ruleName = "xi/selector-pattern";
   29     9 var messages =  stylelint.utils.ruleMessages(ruleName, {
@@ -32,60 +12,20 @@ var messages =  stylelint.utils.ruleMessages(ruleName, {
   32    12   }
   33    13 });
   34    14 
   35    -1 var createPattern = function(raw, subpatters) {
   36    -1   _.forOwn(subpatters, function(pattern, name) {
   37    -1     var regexp = new RegExp('{' + name + '}', 'g');
   38    -1     raw = raw.replace(regexp, pattern);
   39    -1   });
   40    -1   return new RegExp(raw);
   41    -1 };
   42    -1 
   43    -1 var walkSelectors = function(root, fn) {
   44    -1   root.walkRules(function(rule) {
   45    -1     rule.selectors.forEach(function(_selector) {
   46    -1       var selectors = resolvedNestedSelector(_selector, rule);
   47    -1       selectors.forEach(function(selector) {
   48    -1         fn(selector, rule);
   49    -1       });
   50    -1     });
   51    -1   });
   52    -1 };
   53    -1 
   54    -1 var isPattern = function(input) {
   55    -1   return input && (_.isString(input) || _.isRegExp(input));
   56    -1 };
   57    -1 
   58    -1 var isObject = function(wrapped) {
   59    -1   return function(input) {
   60    -1     return _.isObject(input) && _.every(input, wrapped);
   61    -1   };
   62    -1 };
   63    -1 
   64    -1 module.exports = stylelint.createPlugin(ruleName, function(options_pattern, options) {
   65    -1   if (presets.hasOwnProperty(options_pattern)) {
   66    -1     var args = presets[options_pattern];
   67    -1     options_pattern = args[0];
   68    -1     options = _.defaultsDeep(options, args[1]);
   69    -1   }
   70    -1 
   -1    15 module.exports = stylelint.createPlugin(ruleName, function(optionsPattern, options) {
   71    16   return function(root, result) {
   72    -1     var validOptions = stylelint.utils.validateOptions(result, ruleName, {
   73    -1       actual: options_pattern,
   74    -1       possible: isPattern
   75    -1     }, {
   76    -1       actual: options,
   77    -1       possible: {
   78    -1         filter: isPattern,
   79    -1         subpatterns: isObject(isPattern),
   80    -1       },
   81    -1       optional: true
   82    -1     });
   83    -1     if (!validOptions) return;
   -1    17     if (!validate(result, ruleName, optionsPattern, options)) return;
   -1    18 
   -1    19     if (presets.hasOwnProperty(optionsPattern)) {
   -1    20       var args = presets[optionsPattern];
   -1    21       optionsPattern = args[0];
   -1    22       options = _.defaultsDeep(options, args[1]);
   -1    23     }
   84    24 
   85    25     var filter = new RegExp(options.filter);
   86    -1     var pattern = createPattern(options_pattern, options.subpatterns || {});
   -1    26     var pattern = util.createPattern(optionsPattern, options.subpatterns || {});
   87    27 
   88    -1     walkSelectors(root, function(selector, rule) {
   -1    28     util.walkSelectors(root, function(selector, rule) {
   89    29       if (filter.test(selector) && !pattern.test(selector)) {
   90    30         stylelint.utils.report({
   91    31           ruleName: ruleName,

diff --git a/lib/presets.js b/lib/presets.js

@@ -0,0 +1,22 @@
   -1     1 module.exports = {
   -1     2   bem: ["^({block}({element})?({modifier})?({pseudo})?|{utility})$", {
   -1     3     subpatterns: {
   -1     4       block: "\.[a-z][a-z0-9-]+",
   -1     5       modifier: "--[a-z][a-z0-9-]+",
   -1     6       element: "__[a-z][a-z0-9-]+",
   -1     7       utility: "\.u-[a-z][a-z0-9-]+",
   -1     8       pseudo: "::?[a-z-]+"
   -1     9     }
   -1    10   }],
   -1    11   suit: ["^({component}({descendent})?({modifier})?({state})?({pseudo})?|{utility})$", {
   -1    12     subpatterns: {
   -1    13       component: "\.[A-Z][a-zA-Z0-9]+",
   -1    14       modifier: "--[a-z][a-zA-Z0-9]+",
   -1    15       descendent: "-[a-z][a-zA-Z0-9]+",
   -1    16       state: "\.(is|has)-[a-zA-Z0-9]+",
   -1    17       utility: "\.u-[a-z][a-zA-Z0-9]+",
   -1    18       pseudo: "::?[a-z-]+"
   -1    19     }
   -1    20   }],
   -1    21   itcss: ["^\.(o-|c-|u-|t-|s-|is-|has-|_|js-|qa-)[a-z0-9-]+"]
   -1    22 };

diff --git a/lib/util.js b/lib/util.js

@@ -0,0 +1,21 @@
   -1     1 var resolvedNestedSelector = require('postcss-resolve-nested-selector');
   -1     2 var _ = require('lodash');
   -1     3 
   -1     4 module.exports.createPattern = function(raw, subpatters) {
   -1     5   _.forOwn(subpatters, function(pattern, name) {
   -1     6     var regexp = new RegExp('{' + name + '}', 'g');
   -1     7     raw = raw.replace(regexp, pattern);
   -1     8   });
   -1     9   return new RegExp(raw);
   -1    10 };
   -1    11 
   -1    12 module.exports.walkSelectors = function(root, fn) {
   -1    13   root.walkRules(function(rule) {
   -1    14     rule.selectors.forEach(function(_selector) {
   -1    15       var selectors = resolvedNestedSelector(_selector, rule);
   -1    16       selectors.forEach(function(selector) {
   -1    17         fn(selector, rule);
   -1    18       });
   -1    19     });
   -1    20   });
   -1    21 };

diff --git a/lib/validate.js b/lib/validate.js

@@ -0,0 +1,26 @@
   -1     1 var stylelint = require("stylelint");
   -1     2 var _ = require('lodash');
   -1     3 
   -1     4 var isPattern = function(input) {
   -1     5   return input && (_.isString(input) || _.isRegExp(input));
   -1     6 };
   -1     7 
   -1     8 var isObject = function(wrapped) {
   -1     9   return function(input) {
   -1    10     return _.isObject(input) && _.every(input, wrapped);
   -1    11   };
   -1    12 };
   -1    13 
   -1    14 module.exports = function(result, ruleName, optionsPattern, options) {
   -1    15   return stylelint.utils.validateOptions(result, ruleName, {
   -1    16     actual: optionsPattern,
   -1    17     possible: isPattern
   -1    18   }, {
   -1    19     actual: options,
   -1    20     possible: {
   -1    21       filter: isPattern,
   -1    22       subpatterns: isObject(isPattern),
   -1    23     },
   -1    24     optional: true
   -1    25   });
   -1    26 };

diff --git a/package.json b/package.json

@@ -4,7 +4,7 @@
    4     4   "description": "A stylelint plugin checks selectors with a regular expression",
    5     5   "main": "index.js",
    6     6   "scripts": {
    7    -1     "lint": "jshint index.js",
   -1     7     "lint": "jshint --exclude node_modules ."
    8     8   },
    9     9   "repository": {
   10    10     "type": "git",