-->

Why does sass fail to compile with grunt command e

2019-01-29 11:30发布

问题:

After inheriting a project using Grunt, I am running grunt via terminal, waiting for the 'Watching...' make the change to the scss, and terminal recognizes the change but the compilation fails in the next step of compass:dev. Here is what it's showing inside terminal:

Waiting...
>> File "../sass/inside.scss" changed.

Running "compass:dev" (compass) task
unchanged ../img/common/1x-scb9effd9a6.png
unchanged ../img/common/2x-s7bf9cb0f59.png
    error /Applications/MAMP/htdocs/Repos/wp-content/themes/quindo/_/sass/inside.scss (Line 39 of /Applications/MAMP/htdocs/Repos/wp-content/themes/quindo/_/sass/vendor/retina/_sprite.scss: List index is 2 but list is only 1 item long for `nth')

Compilation failed in 1 files.

A. So I look at line 39 of ...vendor/retina/_sprite.scss which is the @if line of the following function and found that the function contains $index: 2. What would be the purpose of setting it to 2?

@mixin retina-sprite($name, $sprite-name: 0, $hover: false, $active: false) {
  $index: 2;
  $len: length($retina-sprite-names);

  @for $i from $index through $len {
    @if $sprite-name == nth($retina-sprite-names, $i) {
      $index: $i;
    }
  }

  $sprite       : nth($retina-sprite-sprites, $index);
  $sprite-url   : nth($retina-sprite-urls, $index);

  $sprite2x     : nth($retina-sprite-sprites2x, $index);
  $sprite-url2x : nth($retina-sprite-urls2x, $index);

  @include _retina-sprite($name, $sprite, $sprite-url, $sprite2x, $sprite-url2x, $hover, $active);
}

B. To get the scss to change to css, do I simply change the aforementioned 2 to 1? I don't fully understand the effects of the statement.

B2. I tested this theory of changing 2 to 1, and receive errors about the sprite-position() must be a sprite map. Should I simply attempt to run grunt from the development server, wait for 'watching...' then upload the changed .scss file in the thought that the developer was running grunt from the development server rather than locally?

B3. It seems it was built on: https://github.com/novascreen/Retina-mixins-for-Compass/blob/master/src/retina/_retina-sprite.scss

回答1:

As already pointed out, the mixin is attempting to call the 2nd element of a list that only has 1 element in it. This is because this mixin (and its related mixins) were written for an older version of Sass where mixins and functions freely had access to global variables. To remedy this, you'll need to add the !global flag to any instance where the global variable is being referenced.

This is an issue throughout the entire library, it isn't isolated to just the mixin provided by the OP. I've cleaned up the related retina-sprite-add() mixin so that you can see what needs to be changed and carry it over to the rest of the mixins.

The Original:

$retina-sprite-names     : 0;
$retina-sprite-sprites   : 0;
$retina-sprite-urls      : 0;
$retina-sprite-sprites2x : 0;
$retina-sprite-urls2x    : 0;

@mixin retina-sprite-add($name, $path, $path2x) {
  $retina-sprite-spacing: 2px !default;

  $sprite   : sprite-map($path, $spacing: $retina-sprite-spacing);
  $sprite2x : sprite-map($path2x, $spacing: $retina-sprite-spacing);

  $retina-sprite-names     : append($retina-sprite-names, $name);

  $retina-sprite-sprites   : append($retina-sprite-sprites, $sprite);
  $retina-sprite-urls      : append($retina-sprite-urls, sprite-url($sprite));

  $retina-sprite-sprites2x : append($retina-sprite-sprites2x, $sprite2x);
  $retina-sprite-urls2x    : append($retina-sprite-urls2x, sprite-url($sprite2x));
}

Updated for 3.4:

$retina-sprite-names     : 0;
$retina-sprite-sprites   : 0;
$retina-sprite-urls      : 0;
$retina-sprite-sprites2x : 0;
$retina-sprite-urls2x    : 0;

@mixin retina-sprite-add($name, $path, $path2x) {
  $retina-sprite-spacing: 2px !default;

  $sprite   : sprite-map($path, $spacing: $retina-sprite-spacing);
  $sprite2x : sprite-map($path2x, $spacing: $retina-sprite-spacing);

  $retina-sprite-names     : append($retina-sprite-names, $name) !global;

  $retina-sprite-sprites   : append($retina-sprite-sprites, $sprite) !global;
  $retina-sprite-urls      : append($retina-sprite-urls, sprite-url($sprite)) !global;

  $retina-sprite-sprites2x : append($retina-sprite-sprites2x, $sprite2x) !global;
  $retina-sprite-urls2x    : append($retina-sprite-urls2x, sprite-url($sprite2x)) !global;
}

@include retina-sprite-add('foo', 'foo.png', 'foox2.png');
@include retina-sprite-add('bar', 'bar.png', 'barx2.png');

.foo {
  debug: $retina-sprite-names;
}

Should now output:

.foo {
  debug: 0 "foo" "bar";
}

Of course, this also explains why the $index variable starts with the 2nd index.



回答2:

You are trying to access 2nd element of a list that only contains one element hence the compiler throws an error.