postcss / postcss-bem-linter

A BEM linter for postcss
MIT License
572 stars 35 forks source link

list-sequences doesn’t handle all attribute selectors #105

Open ghost opened 7 years ago

ghost commented 7 years ago

I have selectors that look like this:

.component-name > [data-size~="s:2"] {}

and this:

.component-name > [data-size="s:2"] {}

I would expect the second parts of those selectors to be matched by this:

^(?:\\[.+\\])$

However, since the list-sequences function

  1. splits the string on :
  2. splits the result of (1) on /[\s>+~]/

what gets matched against my regex is either

[data-size

or

[data-size="s

So I’m thinking the splitting needs to avoid matching characters inside attribute selectors.

davidtheclark commented 7 years ago

@rgrjoh Good point! If you'd like to contribute a fix, I suggest using https://github.com/postcss/postcss-selector-parser.

ghost commented 7 years ago

I don’t have time to read up on postcss-selector-parser right now, but I tested a quick hack (which can still go wrong, but should at least handle more situations than the current implementation):

module.exports = function(selector) {
  var withoutPseudos = selector.split(/:+(before|after|link|visited|hover|focus|active)/)[0]; /* Add all possible pseudo-selectors */
  return withoutPseudos
    .split(/[\s>+]|~(?!=)/)
    .filter(function(s) {
      return s !== '';
    });
}

Both splits will incorrectly match the content of attribute selectors, eg. [data-whatever="foo:before"] or [data-whatever="a>b"].

But the best solution would be to do what you suggest and use a parsing library.