Search code examples
csssassdart-sass

Sass stuck on compiling @extend property inside loop but works with node-sass


following code is using by css-star-rating library.

@for $i from $minRatingValue through $maxNumOfStars {
    &.value-#{$i}.half {

      .star-container {
        @if ($i < $maxNumOfStars) {
          .star:nth-child(#{$i+1}) {
            @extend .half;
          }
        }
      }

    }
  }

with following values for variables

$minRatingValue: 1 !default;
$maxNumOfStars: 6 !default;

Source: https://github.com/BioPhoton/css-star-rating/blob/master/src/scss/_modifiers.scss#L163

This part of code compile correctly using node-sass but not working as soon as i try to compile this with newer version of sass (https://www.npmjs.com/package/sass). The compiler just stuck on and no error/warning is displayed. Any idea on how i can fix this?

I already tried the !optional flag but this doesnt affect the behavior.


Solution

  • The problem comes from your @extend. Somehow, it seems that Node Sass and Dart Sass don't process it the same way. For example, with $maxNumOfStars: 3, the extended selector compiles as:

    Node Sass

    .half,
    .rating.value-1.half .star-container .star:nth-child(2),
    .rating.value-2.half .star-container .star:nth-child(3)
    

    Dart Sass

    .half,
    .rating.value-2.half .star-container .star:nth-child(3),
    .rating.value-1.half .star-container .rating.value-2.star:nth-child(2) .star-container .star:nth-child(3),
    .rating.value-2.half .star-container .rating.value-1.star:nth-child(3) .star-container .star:nth-child(2),
    .rating.value-1.half .star-container .star:nth-child(2)
    

    The more loops you add, the more longer the selector is, which is probably what makes your compiler crash. The problem seems to be that the extended selector .half is also used on one of the parent &.value-#{$i}.half.

    Though, I don't know if it is the intended behavior or a bug.

    Depending on what selector you want in the end, you might need to rename some classes or use a placeholder selector to fix the issue:

    %half {
        // Code to extend
    }
    
    .half {
       @extend %half;
       ...
    }
    
    .rating {
        @for $i from $minRatingValue through $maxNumOfStars {
            &.value-#{$i} {
                .star-container {
                    @if ($i < $maxNumOfStars) {
                        .star:nth-child(#{$i+1}) {
                             @extend %half;
                        }
                    }
                }
            }
        }
    }