postcss / postcss-bem-linter

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

Does not work with Sass interpolation #132

Open ruedap opened 6 years ago

ruedap commented 6 years ago

This plugin does not seem to support Sass interpolation.

input.scss:

/** @define ComponentName */
.ComponentName {
  $ComponentName: &;

  &--modifierName {
    color: blue;

    #{$ComponentName} {  // <- Sass interpolation
      &-decendantName {
        color: red;
      }
    }
  }
}

postcss-bem-linter result:

input.scss
 9:7  ✖  Invalid component selector                   plugin/selector-bem-pattern
         ".ComponentName--modifierName
         #{$ComponentName}-decendantName"

output.css

/** @define ComponentName */
.ComponentName--modifierName {
  color: blue;
}
.ComponentName--modifierName .ComponentName-decendantName {
  color: red;
}

postcss-bem-linter result:

No errors

ruedap commented 6 years ago

Might be related to #97, #100 🤔

saulhardman commented 6 years ago

I've come across this issue as well.

For now I'm simply ignoring (the few and far between) instances of selectors that contain Sass string interpolation. Not ideal, nor sustainable, but it's tiding things over until a solution is reached (hopefully in this issue).

Rather than ignoring on a selector-by-selector basis, I put the ignoreSelectors option to use like so:-

bemLinter({
  ignoreSelectors: /\#\{\$[a-z]+(?:-[a-z]+)*\}/,
});

The intended logic of this regex (see example) is to match any string that contains: #{$sass-variable-name}.

Back to the issue at hand:

Is it this plugin's responsibility to process Sass string interpolation and ensure that the resulting selector is in the correct format? (And is that even possible?) Or, is it instead the responsibility of the user to configure the regex to take into account the presence of Sass string interpolation within a selector?

/cc @simonsmith

simonsmith commented 6 years ago

Is it this plugin's responsibility to process Sass string interpolation and ensure that the resulting selector is in the correct format? (And is that even possible?)

A good question and I think it would be outside of the scope of this plugin to compile the Sass and understand how to apply the linting rules to the source file.

The solution I'd be tempted to go with would be to apply the postcss-bem-linter after the Sass transformation has happened. You will get less accurate line numbers in the error console (and no editor support on the source files) but that feels like an acceptable tradeoff for these complex Sass examples.

We support nesting but mainly because that isn't unique to Sass and also exists as an official proposal

guilhermetod commented 4 years ago

If anyone comes after this, I'm using the following for now:


const namePattern = /([a-z0-9]+|#\{\$.*\})((-[a-z0-9]+|#\{\$.*\})+)?/;

componentSelectors: (componentName) => new RegExp(`^\\.(${componentName})(((--|__)(${namePattern.source}))+)?$`)

It's been working so far. If anyone try this in another project and find any error, warn me please.

almogk012 commented 4 years ago

@guilhermetod if i use json format, how can i do it? or you can show your js file?