Главный шаблон сайта на тегах
Рамка каждой страницы без PHP: обычная разметка и теги шапки, меню, содержимого, колонки и подвала.
Главный шаблон — рамка каждой страницы: шапка, меню, место для содержимого, боковая колонка и подвал. Положите файл layouts/main.tpl.html в views/ своей темы (themes/ИМЯ/views/layouts/main.tpl.html), и страница строится по нему. Файла нет или он сломан — работает обычный вид, сайт не ломается. Голова страницы, скрипты движка и кнопка «наверх» остаются от движка: стили и шрифты подключайте через theme.json и assets.
Готовый образец: шапка, меню, колонка, подвал
<header class="site-head"><div class="wrap">
<a class="brand" href="{home}"><span class="brand-name">{site_name}</span></a>
{languages} {search}
[if:user.logged]<a href="{user.url}">{user.name}</a> {logout_button}[else]<a href="{user.login_url}">Войти</a>[/if]
</div><div class="wrap"><nav class="nav">[each:menu]<a href="{item.url}">{item.title}</a>[/each]</nav></div></header>
<main id="content" class="wrap has-side">
<div>{content}</div>
<aside class="side-col region region--side">{region:sidebar}</aside>
</main>
<footer class="site-foot"><div class="wrap">© {year} {site_name}</div></footer>Классы site-head, wrap, brand, nav, has-side, side-col, site-foot — готовые классы общего оформления движка: с ними образец сразу выглядит как часть сайта и подстраивается под цвета темы.
На телефоне. Колонка уходит под содержимое, поиск раскрывается под шапкой. Меню разделов в строке образца на телефоне не показывается; поставьте в шапку тег {menu_toggle} вместо строки nav — на телефоне появится кнопка «Меню», по нажатию откроется меню с разделами, на компьютере меню стоит в строке шапки.
Что выводят теги
| Тег | Что выводит |
|---|---|
{site_name} | название сайта из «Настройки → Общие» |
{home} | адрес главной |
{year} | текущий год |
{locale} | код языка страницы |
{canonical} | основной адрес этой страницы |
{theme} | адрес папки файлов темы (assets), например {theme}/img/logo.svg |
{content} | содержимое страницы (запись, магазин, форум…) в контейнере движка: не вылезает за ширину экрана, годится для кабинета, форума и форм |
{content_raw} | то же без обёртки и без ограничения ширины: только для своих полностраничных раскладок; для кабинета, форума и форм берите {content} |
{languages} | выбор языка (готовый блок) |
{search} | строка поиска (готовый блок) |
{login} | блок «Войти / Регистрация» или имя вошедшего (готовый) |
{poll} | текущий опрос сайта |
{logout_button} | кнопка «Выйти» с ключом защиты |
{menu_toggle} | кнопка «Меню» и меню разделов, которое на телефоне открывается кнопкой |
{user_menu} | меню участника: профиль, сообщения, панель, выход |
{region:header} {region:before_content} {region:sidebar} {region:after_content} {region:footer} {region:head_actions} | блоки модулей, поставленные в это место темы |
[each:menu]…[/each] | пункты меню сайта; внутри {item.title}, {item.url}, {item.active} |
Про вошедшего посетителя
| Тег | Что выводит |
|---|---|
[if:user.logged]…[else]…[/if] | разный текст гостю и вошедшему |
{user.name} {user.url} | имя и адрес профиля |
{user.avatar} | адрес аватара; пусто, если аватара нет |
{user.role} | название роли |
{user.pm_unread} | число непрочитанных личных сообщений; пусто, если модуль выключен |
{user.favorites_count} | число закладок |
{user.pm_url} {user.favorites_url} | адреса сообщений и закладок |
{user.admin_url}, [if:user.can_admin]…[/if] | адрес панели и условие «в панель пускают» |
{user.login_url} {user.register_url} {user.forgot_url} | адреса входа, регистрации, восстановления |
{user.field:имя} | своё поле профиля вошедшего (поле заводит владелец); гостю, выключенному и несуществующему полю — пусто; значение экранируется |
Где мы и кто пришёл
Считаются только те теги, на которые файл ссылается: страница без них ничего не тратит.
| Тег | Что выводит |
|---|---|
{page.title} {page.description} | название и описание этой страницы (как в голове страницы) |
{page.route}, [if:page.home] | имя маршрута страницы и условие «это главная», например [if:page.route=news.show]…[/if] |
{page.path} | адрес страницы без домена |
[if:module.имя] | модуль включён (любое имя из папки modules), например [if:module.shop]…[/if] |
{category.title} {category.url} {category.key} | текущая рубрика, если модуль её назвал |
[each:crumbs] {item.title} {item.url} [if:item.last] | хлебные крошки: «Главная» + цепочка модуля (или пункт меню этой страницы); последний пункт помечен last |
{visitor.country} | код страны посетителя («UA»); из заголовка CDN или локальной базы адресов; пусто, если неизвестна |
[if:visitor.mobile] [if:visitor.tablet] [if:visitor.desktop] {visitor.device} | тип устройства по строке браузера |
{propose_url} | ссылка «Предложить запись»; пусто, если модуль или настройка выключены |
{social_login} | готовые кнопки «Войти через …» (только включённые сети; ключей приложения на странице нет); пусто, если сетей нет |
[if:social.google] {social.google.url} {social.google.title} | вход через конкретную сеть (google, github, yandex, vk): включена ли, адрес начала входа и название — кнопку можно поставить в свою разметку |
[if:social.any] | включена ли хоть одна сеть |
{social_profile} | блок «Привязанные сервисы» для кабинета: привязать и отвязать по паролю; гостю пусто |
Рубрику и цепочку разделов называет модуль: кладёт в общие данные вида ключ pageContext (category с title, url, key и crumbs — список с title и url) или добавляет их фильтром theme.page_context. Адрес берётся только свой — от корня.
Условия и повторы
[if:имя]…[/if] — показать, если значение есть; [ifnot:имя]…[/ifnot] — если нет; [if:имя=значение]…[else]…[/if] — сравнение; [each:список]…[/each] — повтор по списку с {item}, {item.ключ}, {index}. Значения из данных страницы доступны по имени; у каждого вида свои.
Безопасность
PHP, include и вызов функций в файле тегов не работают; разметка очищается по белому списку (без тегов script, style, iframe, обработчиков событий и data-*); адреса только http(s)://, путь от корня и #; к ссылкам из шаблона движок добавляет rel="noopener". Значения экранируются. Пределы: 20000 знаков, 400 тегов, вложенность 6, повторов 60.