Шаблоны

Шаблоны

Шаблон в Celena — набор .tpl-файлов в каталоге templates/<slug>/. PHP в .tpl запрещён (теги <?php/<?= экранируются как текст) — используются только теги шаблонизатора. Это безопасно, удобно для вёрстки и легко документируется.

При первом обращении .tpl компилируется в PHP и кешируется в storage/cache/tpl/. Инвалидация — автоматически по времени изменения файла.

Синтаксис

Переменные

{title}                <!-- $vars['title'], авто-экранирование -->
{user.name}            <!-- доступ по точке -->
{news.body|raw}        <!-- без экранирования (доверенный HTML) -->

Inline-теги

Тег с параметрами — это вызов обработчика:

{include file="_partials/head.tpl"}
{lang key="hello.world"}
{csrf}                          <!-- скрытое поле -->
{csrf format="meta"}            <!-- <meta name="csrf-token"> для AJAX -->
{icon name="check" size="20"}   <!-- inline SVG-иконка -->
{plugin_assets}                 <!-- CSS/JS активных плагинов -->

В параметрах разрешена интерполяция {var}:

{lang key="greeting" name="{user.name}"}

Условия

[if {user.role}="admin"]
  Привет, начальник.
[else if {user.role}="editor"]
  Привет, редактор.
[else]
  Гость.
[/if]

[if {is_published}]            <!-- truthy-проверка -->
  Опубликовано
[/if]

Операторы: =, !=, >, <, >=, <=. Сравнения >/< — числовые, остальные — строковые. Можно сравнивать две переменные: [if {a}={b}]…[/if].

Циклы

[foreach var="news" as="n"]
  <article>
    <h2><a href="{n.url}">{n.title}</a></h2>
    <small>{n.date} · {n.author}</small>
  </article>
[/foreach]

Служебные переменные внутри цикла:

ПеременнаяЗначение
{_index}0-based номер итерации
{_total}всего элементов
{_first}"1" если первый, иначе ""
{_last}"1" если последний

Если массив пуст — тело не рендерится. Циклы и условия можно вкладывать друг в друга.

Комментарии

{* Этот текст в вывод не попадёт *}

Структура темы

templates/mytheme/
├── theme.json          манифест темы
├── home.tpl            главная
├── page.tpl            обычная страница
├── news_list.tpl       список новостей
├── news_full.tpl       одна новость
├── search.tpl          поиск
├── 404.tpl             ошибка 404
├── _partials/          переиспользуемые куски (head, header, footer)
└── assets/             CSS/JS темы

Переменные, которые ядро передаёт всегда

{site.name}   {site.url}
{page.title}  {page.seo_title}  {page.seo_description}  {page.og_image}
{locale}      {canonical_self}
{account.is_guest}  {account.name}

Защита <script> и <style>

Содержимое <script>/<style> защищено от парсинга блочных тегов (CSS-селекторы вроде [data-x] не примутся за теги). При этом inline-теги {lang …} внутри скриптов работают — чтобы переводить JS-генерируемую разметку.

Async-блоки

Тяжёлую секцию можно догружать отдельным запросом после рендера страницы:

{async block="latest_news" url="/api/blocks/latest_news" placeholder="Загрузка…"}

Параметры: trigger (load/visible/manual), poll (30s/5m), class. После загрузки контейнер получает класс is-loaded.

Запреты

  • <?php, <?= — экранируются как текст.
  • Прямая работа с БД/сессиями/файлами из шаблона — нельзя (только через зарегистрированные теги или async-блоки).
  • Сторонние CDN запрещены (CSP). Все ассеты — в templates/<slug>/assets/.