Liquid

Материал из Insales Wiki
Версия от 10:25, 24 октября 2014; A.kachalova (обсуждение | вклад) (split(input, segmenter = ' ') – разбить строку на подстроки по разделителю)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

О языке Liquid

Для управление дизайном в InSales используется язык шаблонов Liquid.

Это простой в освоении и достаточно мощный язык. Он был разработан компанией jadedPixel в рамках проекта shopify.com и сейчас является open source проектом.

Более подробная информация о нём, а также полная документация на английском языке находится на сайте: http://www.liquidmarkup.org/.

Более подробная инструкция http://wiki.github.com/tobi/liquid/liquid-for-designers. Справочник: http://liquid.rubyforge.org/.

Введение

В языке Liquid есть два основных вида конструкций: Вывод данных (Output) и Теги (Tag).

  • Вывод данных заключается в {{ двойные фигурные скобки }}
  • Теги заключаются в {% фигурные скобки с процентом %}

Блоки вывода данных всегда заменяются на то, на что они ссылаются. Если в шаблон передаётся информация о товаре через переменную product, то конструкция

{{ product.title }}

выведет его имя.

Теги управляют логикой шаблонов. При их помощи вы можете организовывать циклы и логику ветвления.

Вывод данных

Пример вывода данных:

 Привет, {{ name }}!
Привет, {{ user.name }}!
Привет, {{ 'Имярек' }}!


Фильтры

Для преобразования выходных данных можно использовать фильтры. Фильтры это обычные функции.

Первый аргумент пишется слева от имени фильтра и отделяется от него символом "|" (труба).

Результатом работы фильтра является преобразованный элемент, который подставляется в это место текста.

Исходные данные, например значения переменных, которые являлись аргументом фильтра, сохраняют своё прежнее значение.

 Привет, {{ name | upcase }}!
 В слове 'магазин' {{ 'магазин' | length }} букв
 {{ product.price | money }} 


Результат выполнения фильтра может быть первым аргументом для следующего фильтра, находящегося справа от него, если таковой имеется.

 {{ array | sort | last }} 

Если у фильтра больше одного аргумента, то остальные аргументы перечисляются справа от имени фильтра после символа ":" (двоеточие) через запятую:

 {{ 'Яндекс' | link_to: 'http://yandex.ru' }} => <a href="http://yandex.ru" title="">Яндекс</a> 
 {{ 'Яндекс' | link_to: 'http://yandex.ru', 'ссылка на яндекс' }} => <a href="http://yandex.ru" title="ссылка на яндекс">Яндекс</a> 

Список стандартных фильтров Liquid

Далее словом input обозначается первый аргумент фильтра; тот, что записывается слева от названия фильтра, словом array - массив; словом text - текстовая последовательность символов.

capitalize(input) – преобразовать первую букву строки в заглавную

Фильтр используется для преобразования первой буквы строки в заглавную

Пример:

@   {{ 'string' | capitalize }} #=> String @

escape(input) - преобразовать ссылку в esc-последовательность

Фильтр используется для преобразовывания специальных и национальных символов в URL представление (percent-encoding: пробел в %20, например) в тексте ссылки. Это необходимо, согласно стандарта RFC1738 - Uniform Resource Locators (URL).

Пример:

@   {{ link.title | escape }}  @
{{ http://wiki.insales.ru/Оглавление | escape }} #=> http://wiki.insales.ru/%D0%9E%D0%B3%D0%BB%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5

append(input, ' ') - добавить символы к концу строки

Фильтр используется для добавления указанных символов к концу указанной строки.

Пример:

@   {{ 'sales' | append: '.jpg' }} #=> sales.jpg @

prepend(input, ' ') - добавить символы к началу строки

Фильтр используется для добавления указанных символов к началу указанной строки.

size(input) – вернуть размер массива или строки

Возвращает размер массива или строки.

Пример:

@   {{ 'this is an 30 character string' | size }} #=> 30 @

sort(input, property = z) – отсортировать массив

Фильтр используется для сортировки массива. Второй параметр - необязательный.

Пример: {% assign characteristics_sort = property.characteristics | sort: 'title' %}


   {% for property in collection.properties %}
      <p><b>{{property.title}}:</b>
      {% assign characteristics_sort = property.characteristics | sort: 'title' %}
      {% for characteristic in characteristics_sort %}
         <span>{{characteristic.title}} </span>
      {% endfor %}
      </p>
   {% endfor %}

Отсортирует значения параметров по названию.

join(input, segmenter = ' ') – соединить элементы массива в строку

Фильтр объединяет массив в строку, используя как разделитель элементов указанную последовательность символов.

Пример:

@   {{ product.tags | join: ', ' }} #=> wooden, deepsnow, season2006 @

split(input, segmenter = ' ') – разбить строку на подстроки по разделителю

Разбивает строку на массив подстрок по указанному разделителю

Пример:

@   {% assign string = 'wooden, deepsnow, season2006' %}
@   {% assign array = string | split: ', '%}
@   {{array[0]}} #=> wooden

downcase(input) – преобразовать строку к нижнему регистру

Фильтр преобразовывает строку к нижнему регистру.

Пример:

@   {{ 'StRiNg' | downcase }} #=> string @

upcase(input) – преобразовать строку к верхнему регистру

Фильтр преобразовывает строку к верхнему регистру.

Пример:

@   {{ 'StRiNg' | upcase }} #=> STRING @

strip_html(text) – вырезать html-теги

Этот фильтр изымает из указанного текста все HTML-теги. Очень эффективен в сочетании с truncate.

strip_newlines(input) – вырезать NL

Фильтр изымает из указанной последовательности символов служебный символ "Новая строка" (символ, обозначаемый NL, \n, имеющий код 0ah).

truncate(input, characters = x) – обрезать строку до x символов

Фильтр укорачивает строки до указанного количества символов удалением конца строки.

В случае, если обрабатываемый текст содержит HTML-теги, можно сперва применить фильтр strip_html(см. выше).

truncatewords(input, words = y) - обрезать строку до y слов

Фильтр укорачивает строку до указанного количества символов удалением конца строки.

date(input, format) - преобразовать формат даты к нужному

Фильтр преобразует формат даты в указанный (все даты - григорианского календаря)

%a - Сокращённое обозначение дня недели

%A - Полное обозначение дня недели

%b - Сокращённое обозначение названия месяца

%B - Полное обозначение названия месяца

%c - Предпочтительное местное представление даты и времени

%d - День месяца (01..31)

%H - Час суток, 24-часовое представление (00..23)

%I - Час суток, 12-часовое представление (01..12)

%j - Номер дня года (001..366) 

%m - Номер месяца года (01..12) 

%M - Номер минуты часа (00..59)

%p - Указатель времени суток (``AM''  or  ``PM'') ''после полудня'' или ''до полудня'' соответственно

%S - Секунда минуты (00..60)

%U - Неделя текущего года, начиная с первого воскресенья года как первого дня первой недели (00..53)

%W - Неделя текущего года, начиная с первого понедельника года как первого дня первой недели (00..53)

%w - Номер дня недели (Воскресенью соответствует 0, 0..6)

%x - Предпочтительное представление только даты, без указания времени

%X - Предпочтительное представление только времени, без указания даты

%y - Номер года двузначный (00..99)

%Y - Номер года четырёхзначный

%Z - Имя временной зоны

%% - Обозначает символ ``%''


{{ 'now' | date: "%Y" }}

выведет текущий год в четырёхзначном формате (другие параметры текущей даты, выводятся аналогично)

first(array) – вернуть первый элемент массива

Фильтр возвращает первый элемент из массива

Пример:


{{ product.images | first }}

last(array) – вернуть последний элемент массива

Фильтр возвращает элемент из массива

Пример:


{{ product.images | last }}

newline_to_br(input) – дополнить символ "NL" тегом конца строки

Фильтр добавляет тег конца строки <br /> перед каждым служебным символом "Новая строка" (символ, обозначаемый NL, \n, имеющий код 0ah).

replace(input, substring, replacement) - заменить все

Фильтр заменяет все вхождения в input последовательности substring на последовательность replacement

Пример:

{{ product.description | replace: 'super', 'mega' }}

replace_first(input, substring, replacement) - заменить первый

Фильтр заменяет первое вхождение в input последовательности substring на последовательность replacement

Пример:

{{ product.description | replace_first: 'super', 'mega' }}

remove(input, substring) - удалить все

Фильтр удаляет из input все вхождения последовательности substring

Пример:

{{ product.description | remove: 'way too expensive'}}

remove_first(input, substring) - удалить первый

Фильтр удаляет из input первое вхождение последовательности substring

Пример:

{{ product.description | remove_first: 'remove-me'}}

plus(input, operand) - сложить

Фильтр возвращает результат сложения input и operand. Если это строки, то они приводятся к формату "целое" перед сложением.

Пример:

Showing {{ paginate.current_offset }}-{{ paginate.current_offset | plus: paginate.page_size }} items

minus(input, operand) - вычесть

Фильтр возвращает результат вычитания operand из input. Если это строки, то они приводятся к формату "целое" перед вычитанием.

Пример:

{{ product.price | minus: 10 | money }}

round(input, operand) - округлить

Фильтр возвращает результат округления operand до input знаков после разделителя.

Пример:

{{ product.price | round: 2 | money }}

times(input, operand) - умножить

Фильтр возвращает результат умножеия input и operand.

Пример:

{{ 5 | times:4 }} #=> 20
{{ '5' | times:'4' }} #=> 20

Для обычных строк операция не работает:

{{ 'foo' | times:4 }} #=> 0 а не 'foofoofoofoo'

divided_by(input, operand) - разделить

Фильтр возвращает результат деления input на operand.

Пример:

{{ 10 | divided_by:2 }} #=> 5

Список специфических фильтров в системе InSales

В ПО InSales дополнительно к стандартным реализовано несколько специфических фильтров.

asset_url

Фильтр формирует полный путь до ассета темы

{{ 'reset.css' | asset_url }}

global_asset_url

Фильтр формирует полный путь до глобального ассета (файлы, доступные для всех магазинов)

{{ 'shadowbox/shadowbox.js' | global_asset_url }}

file_url

Фильтр формирует полный путь до файла из раздела Сайт->Файлы

{{ 'image.png' | file_url }}

money

Фильтр выводит сумму денег

{{product.sale_price | money}}



locale_url

Фильтр преобразует URL с учетом текущего языка (нужно только в мультиязычных магазинах)

  {{'/page/about' | locale_url}}

Выражения сравнения

При сравнении доступны следующие операторы:

==равенство
!=неравенство
<>неравенство
<меньше
>больше
>=больше либо равно
<=меньше либо равно
containsстрока слева содержит строку справа
andлогическое и
orлогическое и

Для вызова фильтров при сравнении надо использовать ".", а не "|"'. Так можно использовать только фильтры с одним аргументом.

 {% if array.size > 10 %}   - правильно
 {% if array | size > 10 %} - неправильно

Обратите внимание на отсутствие оператора отрицания; если вам нужно отрицание, надо либо преобразовать условие, либо использовать else, а основную ветку оставить пустой.

  {% if product.title contains 'asus' %}
  {% else %}
     ...
  {% end %}

При сравнении объектов разного типа, например, чисел со строками, всегда возвращается false.

  {% if products.size == 0 %}    - правильно
  {% if products.size == '0'  %} - неправильно

При обращении к несуществующим методам тоже возвращается false.

  {% if products.size == 0 %}    - правильно
  {% if products.empty %}        - не вернет ошибку, но будет всегда возвращать false 

Список значений, которые при приведении к Boolean становятся false в языке Liquid, совпадает с языком ruby, который сильно отличается от аналогичного списка в PHP.

False

  • false
  • nil


True - все остальное

  • “”
  • 0
  • “0”
  • “false”

Теги

Теги используются для добавления логики в шаблон.

Комментарии

Комментарий должен начинаться с "{% comment %}" и заканчиваться "{% endcomment %}". Все что заключено между этими тегами будет игнорироваться и не попадёт на конечную страницу. Комментарии могут быть как однострочными так и многострочными.

{% comment %} закомментированный текст {% endcomment %}

Определение переменных

При помощи тега assign вы можете определять и менять значения своих переменныx, которые потом будут использованы наравне с имеющимися переменными.

  {% assign name = 'свежая' %}
  {% for product in collection.products %}{% if product.description contains name %}
     <p>Свежая!</p>
  {% endif %}{% endfor %}

Вы можете использовать фильтры внутри тега assign

 {% assign name =  product.title | upcase %}

Для объединения нескольких переменных в одну строку, которая становится значением новой переменной, удобно использовать тег capture. При этом содержимое тегов попадает в переменную с указанным именем (в примере select_id), а не в итоговый текст.

  {% capture select_id %}option-{{ option.id }}{% endcapture %}

  <label for="{{ select_id }}">Цвет:</label>
  <select name="options[{{ option.id }}][]]" id="{{ select_id }}">
    <option value="black">Черный</option>
    <option value="yellow">Жёлтый</option>
    <option value="white">Белый</option>
  </select>


Также переменные можно использовать в объявление других. Примеры

  {% assign colhandle = 'action' %}
  {{collection[colhandle].title}} \\ Выдаст Название категории с пермалинком заданным в переменной colhandle

Ещё один пример посложнее. Вывод массива(в данном случае названий товара категории с пермалинком frontpage) в обратном порядке

  {% for product in collections.frontpage.products%}
    {% assign current = forloop.length| minus: forloop.index %}
    <p>{{collections.frontpage.products[current].title }}  </p>
  {% endfor %}

Условия If / Else / Elsif / Unless

Оператор позволяет проверить условие и, в зависимости от результата, выполнить ту или иную ветку. Оператор Unless, в отличии от оператора If, удобен, если надо проверить отрицание условия, так как в Liquid нет оператора отрицания.

{% if user %}
  Привет, {{ user.name }}
{% endif %}

{% if user.name == 'Вася' %}
  Привет, Вася!
{% endif %}

{% if product.title contains 'колбаса' %} 
  Это колбаса
{% endif %}

{% unless product.title contains 'колбаса' %} 
  Это не колбаса
{% endunless %}

{% if product.description == null %}
   В разработке
{% endif %}

Конструкция Case

Если у вас несколько проверок на равенство, то удобно использовать Case.

{% case condition %} 
{% when 1 %} 
hit 1 
{% when 2 %} 

hit 2 
{% else %} 
elseblock 
{% endcase %} 


{% case template %}
	
{% when 'index' %}
     // {{ page.title }}
{% when 'product' %}
     // {{ product.title }}
{% else %}
     // {{ title }}
{% endcase %}

Чередование Cycle

Часто есть необходимость чередовать цвета, для таких задач в Liquid есть тег cycle. Например,

{% cycle 'odd', 'even' %}<br /> 
{% cycle 'odd', 'even' %}<br /> 
{% cycle 'odd', 'even' %}<br /> 
{% cycle 'odd', 'even' %}

вернёт:

odd
even
odd
even

Если не указано имя группы, то предполагается, что все вызовы относятся к одной и той же группе.

Если вы хотите указывать к какой из групп относится вызов, то вы можете задать имя его группы. Например,

{% cycle 'group 1': 'odd', 'even' %}<br /> 
{% cycle 'group 1': 'odd', 'even' %}<br /> 
{% cycle 'group 2': 'one', 'two', 'three' %}<br /> 
{% cycle 'group 2': 'one', 'two', 'three' %} 

вернёт:

odd
even
one
two

Цикл For

Цикл применяется для обхода массивов

{% for item in array %} 
  {{ item }}
{% endfor %}

При обходе массива доступны дополнительные переменные:

 forloop.length      # => количество элементов в массиве
 forloop.index       # => номер текущей итерации 
 forloop.index0      # => номер текущей итерации (считая от нуля) 
 forloop.rindex      # => сколько элементов осталось
 forloop.rindex0     # => сколько элементов осталось (считая от нуля)
 forloop.first       # => первая итерация?
 forloop.last        # => последняя итерация?

Можно задавать сдвиг и максимальное число элементов для обхода:

limit позволяет ограничить число обходимых элементов. offset позволяет начать обход с n-ого элемента.

  # Если array = [1,2,3,4,5,6] ...
  {% for item in array limit:2 offset:1 %} 
    {{ item }}
  {% endfor %}
  # вернёт 2,3

Вместо обхода значений существующего массива, можно задать диапазон чисел, которые надо обойти. Диапазон можно прописать в коде или задать переменной:

  # Если item.quantity = 4 ...
  {% for i in (1..item.quantity) %}
    {{ i }}
  {% endfor %}
  # вернёт 1,2,3,4

Таблицы

Используя Liquid, можно создавать таблицы (аналогично с циклом for), при этом нужно применить тег table, обрамляющий инструкцию tablerow:

  {% tablerow item in items cols: 2 limit: 6 %}
    {{ item }}
  {% endtablerow %}

На каждой итерации цикла есть возможность определить, является ли ячейка таблицы первой или последней в ряду или же прямо узнать номер ячейки по значению дополнительных переменных, доступных при обходе таблицы:

  tablerowloop.length       # => количество элементов в массиве
  tablerowloop.index        # => номер текущей итерации 
  tablerowloop.index0       # => номер текущей итерации (считая с нуля) 
  tablerowloop.rindex       # => сколько элементов осталось
  tablerowloop.rindex0      # => сколько элементов осталось (считая  с нуля)
  tablerowloop.first        # => первый элемент?
  tablerowloop.last         # => последний элемент? 
  tablerowloop.col          # => номер колонки в текущей строчке
  tablerowloop.col0         # => номер колонки в текущей строчке (считая с нуля)
  tablerowloop.col_first    # => первая колонка?
  tablerowloop.col_last     # => последняя колонка?

Include

Тег include позволяет вставлять сниппеты шаблона в произвольные места лайаута, шаблонов и других сниппетов.

Использование:

   {% include 'foobar' %}

Этот код сгенерирует сниппет с именем foobar со всеми переменными в подставленном шаблоне на месте тега. Можно указать имя переменной в необязательном параметра with, эта переменная будет использована в качестве основного объекта в сниппете, по умолчанию имя объекта совпадает с именем сниппета:

   {% include 'foo' with 'bar' %}

В качестве объекта нельзя указывать массив.

Примеры:

Сниппет price:

  цена:   '{{ price }}'
  вес: '{{ weight }}'

1. Подставляем в шаблон:

{% assign weight = '2.0' %}
{% include 'price' %}

Результат:

 цена: ''
 вес: '2.0'

2. Подставляем в шаблон:

{% assign weight = '2.0' %}
{% include 'price' %}
{% include 'price' with '100.0' %}
{% include 'price' with '200.0' %}
{% assign weight = '10.0' %}
{% include 'price' with '300.0' %}

Результат:

 цена: ''
 вес: '2.0'
 цена: '100.0'
 вес: '2.0'
 цена: '200.0'
 вес: '2.0'
 цена: '300.0'
 вес: '10.0'