Теги
Теги — набор различных встроенных конструкций и операций над шаблоном. Они объявляются с помощью островков кода и определяют поведение шаблона.
Рекомендация
Перед изучением тегов рекомендуется ознакомиться со статьями Типы данных и Конвертация типов.
Команды
Теги команд выполняют какую-либо операцию, но ничего не печатают в результат шаблона.
set
Команда set является операцией присваивания переменной в шаблоне. Она вычислит результат выражения и запишет его в переменную с указанным названием:
{% set five = 2 + 3 %}
В примере выше результат вычисления 2 + 3 (5) будет записан в переменную five.
Команда set также поддерживает составные операторы присваивания, используя основные бинарные операторы для арифметических операций (+, -, *, **, /, //) и объединения строк (~):
{% set value = 2 %}
{% set value += 3 %}
В примере выше результирующее значение переменной будет равно 5.
Название переменной является идентификатором и может содержать только латинские буквы, цифры и нижнее подчеркивание, но не может начинаться с цифры.
set как команда не генерирует контент, она просто объявляет переменную или перезаписывает существующую переменную с этим именем.
global
Переменные, объявленные командой set, имеют локальную область видимости и будут доступны только в шаблоне, в котором они были объявлены. Команда global позволяет объявить переменную глобально.
Это значит, что эта переменная будет доступна в последующих интерпретируемых шаблонах этого сообщения, в макросах и в действии, вызываемом через run. Например, переменная, определенная глобальной в шаблоне сообщения станет сразу доступна в шаблоне панели.
{% global six = 3 + 3 %}
В примере выше результат вычисления 3 + 3 (6) будет записан в переменную six и доступен глобально.
Локальное переопределение
Переменная, объявленная командой set, имеет локальную область видимости, поэтому она может переопределить значение переменной, ранее объявленное командой global с таким же названием. Она не перезапишет значение глобальной переменной, а именно что переопределит его.
Сбросить переопределённое значение set и вернуть переменной её глобальное значение можно, указав этой переменной неопределённое значение, например, названием любой несуществующей переменной:
{% global value = 'global_value' %}
{{ value }}
{# ^ распечатает "global_value" #}
{% set value = 'set_value' %}
{{ value }}
{# ^ распечатает "set_value" #}
{% set value = undefined %}
{# ^ "undefined" может быть название любой несуществующей переменной #}
{{ value }}
{# ^ распечатает "global_value" #}
do
Команда do вычисляет указанное выражение, не печатая ничего в шаблон.
{% do channel.sendMessage('My message!') %}
Данная команда может быть полезна для тихого вызова каких-либо функций или методов у объектов.
require
Команда require является расширением тэга return и выглядит следующим образом:
{% require выражение returning 'Произошла какая-то ошибка' %}
Эта команда вернет ошибку если результат вычисления выражения будет равен:
null;undefined;false;- пустая строка;
0.
Вместо строки можно передать заполненный Embed (но НЕ отправляя его методом send).
Будучи расширением тэга return, данная команда имеет аналогичное поведение в трансформациях и макросах.
use
Команда use включает дополнительную функциональность шаблонного движка или меняет его поведение.
strict
Выполнение шаблона в строгом режиме. Это означает, что шаблонный движок будет возвращать ошибку компиляции в следующих случаях:
- Попытка вывести неопределённую переменную;
- Попытка обратиться к несуществующему свойству объекта;
- Попытка вызвать несуществующую функцию, метод объекта или с некорректно переданными в неё аргументами.
Строгий режим включается следующим образом:
{% use 'strict' %}
run
Команда run используется для запуска указанного Действия с передачей в него параметров (опционально). Эта операция полностью прервёт текущее выполняемое действие.
Внимание
Данный тег работает только в Действиях пользовательских команд для "маршрутизации" одного действия в другое.
Используйте UUID действия для его запуска:
{% run 'aebf9ae8-c62a-4348-b153-a7c0a0173da1' %}
Информация
Вы можете получить этот UUID из самого действия в настройках команды (нажмите иконку "i").
Оба действия должны быть частью одной команды, т.е. действие команды А не может быть запущено из действия команды Б.
Для передачи параметров в запускаемое действие используйте следующий синтаксис:
{% run 'aebf9ae8-c62a-4348-b153-a7c0a0173da1' with { 'param1': 123 } %}
Выражение после with на самом деле просто карта, поэтому можно указать там объявленную ранее переменную карты. Эти параметры будут доступны как часть переменной parameters в запускаемом действии:
{{ parameters.param1 }}
Шаблон выше распечатает 123 в запускаемом действии.
Вы также можете использовать сам parameters в родительском действии для передачи данных в дочернее. Следующий пример сделает абсолютно то же самое, как и предыдущий, просто другим способом:
{% do parameters.store('param1', 123) %}
{% run 'aebf9ae8-c62a-4348-b153-a7c0a0173da1' %}
Внимание
Действия могут запускать друг друга цепочкой до трёх раз. Квоты методов при этом остаются общие для всей цепочки.
Управляющие конструкции
Шаблонный движок JuniperBot реализует базовые управляющие конструкции: условия и циклы
Условия — if/elseif/else
Условие — самая простая управляющая конструкция. Здесь поддерживаются последовательные конструкции elseif, а также распространённую конструкцию else.
{% if (выражение) %}
... Блок вычисляется если "выражение" вычислено как true ...
{% elseif (другоеВыражение) %}
... Блок вычисляется если "другоеВыражение" вычислено как true,
а так же "выражение" вычислено как false ...
{% else %}
... Блок вычисляется если ни одно из
указанных условий не было удовлетворено ...
{% endif %}
Обратите внимание, что вся конструкция if выведет содержимое только первого блока, выражение которого будет вычислено как true согласно правилам Конвертации типов.
С точки зрения области видимости переменных, внутреннее содержимое блока if разделяет контекст с родительским контекстом. Это означает, что условия могут влиять на переменные во внешней области видимости.
{% set variable = "раз" %}
{% if (true) %}
{% set variable = "два" %}
{% endif %}
{{ variable }}
Предыдущий пример генерирует сообщение два, что иллюстрирует как область видимости в условиях разделяет контекст с родительской конструкцией.
{% if (1 != 2) %}
{% return 'Один не равен двум. Внезапно!' %}
{% endif %}
А вот этот текст шаблон не выведет из-за ошибки.
Пример выше демонстрирует, как можно с помощью условия вернуть ошибку.
Циклы — for
Поддерживаются циклы над списками или картами.
{# Пример цикла над списком #}
{% for item in list %}
... Контент с использованием переменной item ...
{% endfor %}
{# Пример цикла над картой #}
{% for key, value in map %}
... Контент с использованием переменных key и value карты ...
{% endfor %}
Область видимости переменных-итераторов (item, key, value в примерах выше) ограничена лишь блоком цикла, даже если их переопределять с помощью команды set.
Переменная loop
Циклы for объявляют дополнительную переменную с идентификатором loop. Она предоставляет доступ к полезным свойствам внутри цикла:
| Свойство | Описание |
|---|---|
length | Размер списка или карты |
index | Номер текущей итерации, начинающийся с 1 |
index0 | Номер текущей итерации, начинающийся с 0 |
revindex | Количество оставшихся итераций до достижения конца списка или карты, заканчивается на 1 |
revindex0 | Количество оставшихся итераций до достижения конца списка или карты, заканчивается на 0 |
first | Свойство, равное true для самой первой итерации |
last | Свойство, равное true для самой последней итерации |
parent | Получение доступа к родительскому контексту |
{% for item in [1, 2, 3] %}
{% if (loop.first) %}
Начало
{% endif %}
{% endfor %}
Предыдущий пример распечатает слово Начало только один раз во время первой итерации.
Переменная loop привязана к контексту цикла for, это значит, что область видимости этой переменной ограничена лишь содержимым блока цикла. Если вне цикла объявлена переменная с названием loop, она не будет перезаписана, но доступ к ней можно будет получить только через родительский контекст, например:
{% set loop = 1 %}
{% for item in [1, 2, 3] %}
{% if (loop.first) %}
{{ loop.parent.loop }}
{% set loop = 2 %}
{% endif %}
{% endfor %}
{{ loop }}
Предыдущий пример распечатает 1 2. Обратите внимание, что присваивание значения переменной loop внутри цикла не перезаписывает loop самого цикла. Эта переменная далее будет доступна уже вне цикла.
Ограничения
- Максимально допустимая вложенность циклов — 2;
- Максимальное количество итераций всех циклов в процессе выполнения одного шаблона — 3000.
Трансформации — transform
Трансформация - разновидность цикла for, используемая для преобразования одного списка в другой. Каждая итерация такого цикла ожидает вызов тега return с указанием нового значения для соответствующего элемента списка:
{% transform item in [1, 2, 3] as newList %}
{% return 'element:' ~ item %}
{% endtransform %}
{{ newList }}
Предыдущий пример преобразует список [1, 2, 3] в ['element:1', 'element:2', 'element:3'] и сохранит в переменную newList.
В случае, если в рамках итерации тег return не был вызван, элемент списка пропускается. Таким образом, используя трансформацию, можно отфильтровать список:
{% transform item in [1, 2, 3] as newList %}
{% if (item != 2) %}
{% return item %}
{% endif %}
{% endtransform %}
{{ newList }}
Предыдущий пример преобразует список [1, 2, 3] в [1, 3], исключая из результата второй элемент согласно установленному условию.
Информация
Трансформации наследуют все особенности работы циклов for, включая переменную loop и доступ к родительскому контексту.
Внимание
Трансформации не могут использовать вложенные списки/карты, такие элементы будут исключены из результата трансформации. Другими словами, нельзя делать списки списков и списки карт.
Кроме этого, трансформации ничего не печатают в шаблон, все островки вывода внутри трансформаций игнорируются.
break/continue
Вы можете прерывать выполнение итераций циклов и трансформаций, используя теги break и continue.
break прерывает текущую и все последующие итерации цикла:
{% for item in [1, 2, 3, 4] %}
start:{{item}}
{% if (item > 2) %}
{% break %}
{% endif %}
end:{{item}}
{% endfor %}
Предыдущий пример распечатает start:1 end:1 start:2 end:2 start:3, поскольку третья и все последующие итерации прерываются условием item > 2.
continue прерывает только текущую итерацию цикла:
{% for item in [1, 2, 3] %}
start:{{item}}
{% if (item == 2) %}
{% continue %}
{% endif %}
end:{{item}}
{% endfor %}
Предыдущий пример распечатает start:1 end:1 start:2 start:3 end:3. Обратите внимание на отсутствие части end:2, так как вторая итерация прерывается выполнением условия item == 2.
return
Тег return прерывает генерацию шаблона и возвращает ошибку. Он также используется в трансформациях и макросах.
{% return 'Произошла какая-то ошибка' %}
Вместо строки можно передать заполненный Embed (но НЕ отправляя его функцией send).
Вы также можете передать null, это предотвратит отправку любого результата шаблона, включая любые ошибки:
{% return null %}
Прочее
macro
Макросы — конструкции, позволяющие минимизировать дублирование однообразного кода шаблона.
Это достигается вынесением переиспользуемой части шаблона в именованную конструкцию macro/endmacro, которая также предоставляет возможность передачи внутрь каких-либо входных данных:
{% macro macroName(firstArgument, secondArgument, ...) %}
... переиспользуемый шаблон ....
{% endmacro %}
Название макроса
Названием макроса должен быть уникальный идентификатор. Макрос с конкретным названием может быть определён только один раз, попытка повторно определить макрос с уже существующим названием приведёт к ошибке исполнения шаблона.
Аргументы макроса
Аргументы макроса — список идентификаторов, представляющие собой входные переменные, которые можно использовать внутри макроса. Список аргументов опционален, Вы можете создать макрос вообще без аргументов. Их передача так же опциональна.
Область видимости
Шаблон макроса имеет доступ к ограниченному числу переменных:
- Переданные в макрос аргументы;
- Переменные, объявленные глобально на момент запуска макроса;
- Переменные, доступные в шаблоне по-умолчанию.
Обычные переменные, объявленные внутри макроса, доступны только в контексте выполнения этого макроса. Глобальные будут ожидаемо доступны во всем шаблоне.
Запуск макроса
Объявленные макросы запускаются аналогично встроенным функциям. Их можно считать своего рода "пользовательскими функциями".
{% macro fullname(firstName, lastName) %}
{{ firstName ~ ' ' ~ lastName }}
{% endmacro %}
{{ fullname('Илон', 'Маск') }}
В данном примере мы создали простейший макрос для получения полного имени из двух входных переменных (имени и фамилии). Результатом вызова макроса является строка, получившаяся в результате обработки шаблона этого макроса с указанными аргументами.
Кроме этого, Вы можете использовать тэг return для случаев, когда макрос должен вернуть значение какой-либо конкретной переменной или выражения, например:
{% macro fullname(firstName, lastName) %}
Блаблабла
{% return firstName ~ ' ' ~ lastName %}
{% endmacro %}
{{ fullname('Илон', 'Маск') }}
Результат выполнения этого шаблона будет аналогичен предыдущему. Обратите внимание на "Блаблабла" в шаблоне макроса. В данном случае этот текст выведен не будет, поскольку макрос использует return для возврата конкретных данных.
Внимание
Макросы не могут запускать другие макросы.
include
Данный тег используется для вставки глобального шаблона в текущий шаблон. Для более подробной информации посетите статью Глобальные шаблоны.
{% include 'my_template' %}
В данном примере мы вставили глобальный шаблон с названием my_template.
Область видимости
По-умолчанию глобальный шаблон выполняется полностью в контексте основного шаблона. Простыми словами, он выполняется буквально если бы вместо тэга include было вставлено содержимое этого шаблона.
Все объявленные в основном шаблоне переменные будут доступны внутри глобального шаблона, а все переменные, объявленные внутри глобального шаблона, станут доступны в основном шаблоне после выполнения тэга include.
Однако, данное поведение можно изменить с помощью дополнительного ключа scoped:
{% include 'my_template' scoped %}
В данном случае глобальный шаблон будет выполнен в собственном контексте. Он не будет иметь доступ к переменным, объявленным в основном шаблоне, а переменные, созданные в процессе выполнения глобального шаблона, не будут доступны в основном шаблоне.
"Внимание"
Глобальные переменные и макросы являются исключением.
Даже в режиме scoped они будут доступны в глобальных шаблонах, и их объявление сделает их доступными в основном шаблоне.
В случае, когда в режиме scoped всё же необходимо передать какие-то данные внутрь глобального шаблона, можно использовать следующую конструкцию:
{% include 'my_template' scoped with { 'param1': 123 } %}
Выражение после with на самом деле просто карта, поэтому можно указать там объявленную ранее переменную карты. Указанные данные будут доступны как обычные переменные внутри глобального шаблона.
В примере выше переменная param1 будет иметь значение 123.
filter
Конструкция фильтра — ещё одна возможность применять функции к указанному контенту. Она использует содержимое указанного тела блока как аргумент для указанной функции.
{% filter lower | capitalize -%}
HELLO WORLD
{%- endfilter %}
Предыдущий пример распечатает сообщение Hello world. Как мы видим, результатом фильтра является выполнение двух функций над телом блока. Сперва фильтр применяет функцию lower к содержимому HELLO WORLD, генерируя hello world, после этого применяет функцию capitalize, генерируя результирующее Hello world.
verbatim
Этот тег полезен для избежания вычисления любого синтаксиса шаблонного движка, то есть оно не будет вычислять содержимое этого блока и распечатает его как есть.
{% verbatim %}
{{ test }}
{% endverbatim %}
Предыдущий пример распечатает сообщение {{ test }}.