Почему sass не скомпилируется с командой grunt, ошибка индекса равна 2, но список состоит только из 1 элемента для `nth'?

После наследования проекта с использованием Grunt я запускаю grunt через терминал, ожидая, пока «Наблюдение...» внесет изменение в scss, и терминал распознает изменение, но на следующем этапе компаса: dev компиляция завершается неудачно. Вот что он показывает внутри терминала:

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.

О. Итак, я смотрю на строку 39 файла ...vendor/retina/_sprite.scss, которая является строкой @if следующей функции, и обнаружил, что функция содержит $index: 2. Какова цель установки значения 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. Чтобы изменить scss на css, мне просто изменить вышеупомянутые 2 на 1? Я не совсем понимаю последствия этого заявления.

БИ 2. Я проверил эту теорию изменения 2 на 1, и получаю ошибки о том, что sprite-position() должна быть картой спрайтов. Должен ли я просто попытаться запустить grunt с сервера разработки, дождаться «просмотра...», а затем загрузить измененный файл .scss, думая, что разработчик запускал grunt с сервера разработки, а не локально?

Б3. Кажется, он был построен на: https://github.com/novascreen/Retina-mixins-for-Compass/blob/master/src/retina/_retina-sprite.scss


person beta208    schedule 29.10.2014    source источник
comment
Этот миксин создан третьей стороной? Если это так, вы хотите подать отчет об ошибке. Ошибка связана с использованием nth() в следующей строке. Он пытается выбрать 2-й элемент списка, который содержит только 1 элемент. Однако я не вижу причин, по которым они хотели бы начать со 2-го элемента, поэтому изменение его на 1 может вызвать нежелательные побочные эффекты.   -  person cimmanon    schedule 29.10.2014
comment
Он создан третьей стороной, похоже, я могу отправить им электронное письмо.   -  person beta208    schedule 29.10.2014
comment
Если бы я угадал, я бы сказал, что этот миксин был написан для Sass 3.2 или, возможно, 3.3. Здесь нет указаний на то, что должно быть $retina-sprite-names, поэтому я предполагаю, что они пытаются получить доступ к переменной, которая существует вне области действия этого миксина (т.е. глобальной). Область видимости изменена в Sass 3.4, поэтому глобальные переменные не видны в миксинах, если они не указаны явно.   -  person cimmanon    schedule 29.10.2014
comment
Я думаю, вы правы, он был добавлен около 4 месяцев назад и мог быть переработанным кодом на тот момент. Недавно я загрузил свои локальные файлы, что вы порекомендуете мне сделать? Можно ли запустить grunt на сервере разработки, дождаться просмотра... затем загрузить отредактированный scss и скомпилировать его там? Однако $retina-sprite-names : 0;   -  person beta208    schedule 29.10.2014
comment
Посмотрите, поможет ли это вам выбрать правильный путь: sassmeister.com/gist/d7239fdaba9bcebad2be. У меня нет доступа ко всем переменным/примесям, необходимым для всего этого, поэтому я закомментировал их (они должны работать, если вы их раскомментируете). Если это сработает, я опубликую ответ, хотя я подозреваю, что это лучше решить с помощью сопоставлений, а не списков.   -  person cimmanon    schedule 29.10.2014
comment
Я вижу, куда вы идете, но, похоже, это не решает проблему. Я нашел, на чем он был построен: github.com/novascreen/Retina-mixins-for-Compass/blob/master/src/   -  person beta208    schedule 29.10.2014


Ответы (2)


Как уже было сказано, миксин пытается вызвать второй элемент списка, в котором есть только один элемент. Это связано с тем, что этот миксин (и связанные с ним миксины) был написан для более старой версии Sass, где миксины и функции имели свободный доступ к глобальным переменным. Чтобы исправить это, вам нужно добавить флаг !global к любому экземпляру, где есть ссылка на глобальную переменную.

Это проблема во всей библиотеке, она не изолирована только от миксина, предоставленного OP. Я очистил связанный миксин retina-sprite-add(), чтобы вы могли видеть, что нужно изменить, и перенести это на остальные миксины.

Оригинал:

$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));
}

Обновлено для 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;
}

Теперь должно выводиться:

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

Конечно, это также объясняет, почему переменная $index начинается со 2-го индекса.

person cimmanon    schedule 29.10.2014
comment
Я люблю тебя, чимманон. Вы решили мою недельную проблему. Большая вам пятерка. - person beta208; 30.10.2014
comment
Для любого другого, кто сталкивается с этим, просто замените функцию @mixin retina-sprite-add на ее выше (остановитесь на скобке перед @include). - person beta208; 30.10.2014

Вы пытаетесь получить доступ ко второму элементу списка, который содержит только один элемент, поэтому компилятор выдает ошибку.

person Lucky Soni    schedule 29.10.2014
comment
Поскольку я на тестовом сервере, мне просто изменить его на 1? - person beta208; 29.10.2014
comment
Хотя это и объясняет ошибку, это не объясняет, почему возникла ошибка. - person cimmanon; 29.10.2014
comment
Трудно комментировать, так как у меня нет полного кода передо мной. что такое $retina-sprite-names, $retina-sprite-sprites и т. д.? - person Lucky Soni; 29.10.2014
comment
Изменил его на единицу, и теперь он дает мне знать: первый аргумент для sprite-position() должен быть картой спрайтов. Первый аргумент: @import compass/utilities/sprites Но я не могу найти этот файл. - person beta208; 29.10.2014