Учебник по темам⚓︎
Часто лучший способ узнать что-то новое — это использовать пример, а затем попытаться построить свое собственное творение из него. Мы собираемся использовать эту же методологию для создания новой темы Grav.
Quark⚓︎
Grav поставляется с чистой и современной темой под названием Quark, которая использует фреймворк Spectre.css.
Spectre.css — лёгкий, отзывчивый и современный CSS-фреймворк для более быстрой и расширяемой разработки.
Spectre предоставляет базовые стили для типографии и элементов, гибкую систему быстрой разметки, чистые CSS-компоненты и утилиты с передовой практикой кодирования и последовательным языком проектирования.
Однако, часто лучше начинать с чего-то ещё более простого.
Pure.css⚓︎
Ради этого учебника мы создадим тему, использующую популярный фреймворк Pure.css, разработанный Yahoo!
Pure — маленький, быстрый и отзывчивый CSS-фреймворк, который содержит основы для разработки вашего сайта без накладных расходов как у более крупных фреймворков, таких как Bootstrap или Foundation. Он содержит несколько модулей, которые могут быть использованы независимо друг от друга, но полный пакет занимает 4 Кб в сжатом и упакованном виде!
Вы можете прочитать обо всех возможностях Pure на сайте проекта Pure.css.
Кроме того, вы должны прочитать статью Important Theme Updates в блоге Grav, которая описывает некоторые ключевые изменения в Grav-темах, чтобы обеспечить лучшую поддержку плагинов в будущем.
Шаг 1 - Установка плагина DevTools⚓︎
Предыдущие версии данного руководства требовали создания базовой темы по умолчанию. Весь этот процесс можно пропустить благодаря нашему новому плагину DevTools.
Первым шагом в создании новой темы является установка плагина DevTools. Это можно сделать двумя способами.
Установка через консольное приложение GPM⚓︎
- Перейдите в командной строке в корень вашей установки Grav и введите следующую команду:
Установка через плагин Admin⚓︎
- После входа в систему просто перейдите к разделу Плагины в боковой панели.
- Нажмите кнопку Добавить в правом верхнем углу.
- Найдите DevTools в списке и нажмите кнопку Установить.
Шаг 2 - Создание базовой темы⚓︎
Для этого следующего шага вам действительно нужно быть в командной строке, так как DevTools предоставляет пару CLI-команд для того, чтобы сделать процесс создания новой темы намного проще!
Из корневой части вашей установки Grav введите следующую команду (в консоли Open Server не забудьте добавить php
в начале команды):
В ходе этого процесса вам будет задано несколько вопросов, которые необходимы для создания новой темы:
Мы собираемся использовать pure-blank для создания новой темы, но вы можете создать простой шаблон, наследующий от другой базовой темы.
bin/plugin devtools new-theme
Enter Theme Name: MyTheme
Enter Theme Description: My New Theme
Enter Developer Name: Acme Corp
Enter Developer Email: contact@acme.co
Please choose a template type
[pure-blank ] Basic Theme using Pure.css
[inheritance] Inherit from another theme
[copy ] Copy another theme
> pure-blank
SUCCESS theme mytheme -> Created Successfully
Path: /www/user/themes/my-theme
DevTools сообщает, где был создан этот новый шаблон. Созданный шаблон полностью функционален, но в то же время очень прост. Вы захотите изменить его в соответствии с вашими потребностями.
Чтобы увидеть вашу новую тему в действии, вам нужно будет изменить тему по умолчанию с quark
на my-theme
, так что отредактируйте ваш user/config/system.yaml
таким образом:
Перезагрузите ваш сайт в браузере, и вы увидите, что тема теперь изменилась.
Шаг 3 - Основы темы⚓︎
Теперь мы создали новую базовую тему, которую можно изменять и развивать, давайте разберем её и рассмотрим составляющие. Если вы заглянете в папку user/themes/my-theme
, вы увидите:
.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── blueprints.yaml
├── css
│ └── custom.css
├── fonts
├── images
│ └── logo.png
├── js
├── my-theme.php
├── my-theme.yaml
├── screenshot.jpg
├── templates
│ ├── default.html.twig
│ ├── error.html.twig
│ └── partials
│ ├── base.html.twig
│ └── navigation.html.twig
└── thumbnail.jpg
Это примерная структура, но потребуется ещё несколько вещей.
Необходимые элементы для работы⚓︎
Эти элементы имеют решающее значение, и ваша тема не будет работать надежно, если вы не включите их в свою тему.
blueprints.yaml
- файл конфигурации, используемый Grav для получения информации о вашей теме. Он также может определить форму, отображаемую при просмотре деталей темы. Эта форма позволит вам сохранить настройки темы. Подробнее в главе Формы.
my-theme.php
- этот файл будет назван в соответствии с вашей темой, но может быть использован для размещения любой нужной логики. Вы можете использовать любой хук событий плагинов за исключениемonPluginsInitialized()
, однако есть хукonThemeInitialized()
, который можно использовать в качестве альтернативы.my-theme.yaml
- это конфигурация, используемая плагином для установки опций темы.templates/
- это папка, которая содержит шаблоны Twig для отображения ваших страниц.
Требуемые элементы для выпуска⚓︎
Эти пункты необходимы, если вы хотите выпустить свою тему через GPM.
CHANGELOG.md
- файл, который соответствует формату списка изменений Grav для отображения изменений в релизах.LICENSE
- файл лицензии. Чаще всего это MIT, если только у вас нет особой потребности в чем-то другом.README.md
- содержит любую документацию по теме. Например, как установить, настроить и использовать.screenshot.jpg
- скриншот темы, размером 1009px x 1009px.thumbnail.jpg
- скриншот темы, размером 300px x 300px.
Шаг 4 - Базовый шаблон⚓︎
Как вы знаете из предыдущей главы, каждый элемент контента в Grav имеет определенное имя файла, например default.md
, который указывает Grav искать шаблон Twig для рендеринга с именем default.html.twig
. Можно поместить всё, что вам нужно для отображения страницы в этом одном файле, и он будет работать нормально. Однако есть лучшее решение.
Используя тег Twig Extends, вы можете определить базовый макет с помощью определённых блоков. Это позволяет любому шаблону Twig расширять базовый шаблон и предоставляет определения для любого блока, определенного в базе. Итак, посмотрите на файл templates/default.html.twig
и изучите его содержимое:
В действительности здесь происходят две вещи.
Во-первых, этот шаблон расширяет другой шаблон, расположенный в partials/base.html.twig
.
Вам не нужно включать templates/
в шаблоны Twig, поскольку Twig уже ищет templates/
в качестве корневого уровня для любого шаблона.
Во-вторых, блок content
переопределяется из базового шаблона, и содержимое страницы выводится вместо него.
Для единообразия рекомендуется использовать папку templates/partials
для хранения шаблонов Twig, которые представляют либо небольшие фрагменты HTML, либо являются общими. Мы также используем templates/modular
для модульных шаблонов и templates/forms
для любых форм. Вы можете создать любые подпапки, которые вам нравятся, если вы предпочитаете организовывать свои шаблоны по-другому.
Если вы посмотрите на templates/partials/base.html.twig
, вы увидите основную часть HTML-макета:
{% set theme_config = attribute(config.themes, config.system.pages.theme) %}
<!DOCTYPE html>
<html lang="{{ grav.language.getActive ?: theme_config.default_lang }}">
<head>
{% block head %}
<meta charset="utf-8" />
<title>{% if header.title %}{{ header.title|e('html') }} | {% endif %}{{ site.title|e('html') }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% include 'partials/metadata.html.twig' %}
<link rel="icon" type="image/png" href="{{ url('theme://images/logo.png') }}" />
<link rel="canonical" href="{{ page.url(true, true) }}" />
{% endblock head %}
{% block stylesheets %}
{% do assets.addCss('https://unpkg.com/purecss@1.0.0/build/pure-min.css', 100) %}
{% do assets.addCss('https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css', 99) %}
{% do assets.addCss('theme://css/custom.css', 98) %}
{% endblock %}
{% block javascripts %}
{% do assets.addJs('jquery', 100) %}
{% endblock %}
{% block assets deferred %}
{{ assets.css()|raw }}
{{ assets.js()|raw }}
{% endblock %}
</head>
<body id="top" class="{{ page.header.body_classes }}">
{% block header %}
<div class="header">
<div class="wrapper padding">
<a class="logo left" href="{{ base_url == '' ? '/' : base_url }}">
<i class="fa fa-rebel"></i>
{{ config.site.title }}
</a>
{% block header_navigation %}
<nav class="main-nav">
{% include 'partials/navigation.html.twig' %}
</nav>
{% endblock %}
</div>
</div>
{% endblock %}
{% block body %}
<section id="body">
<div class="wrapper padding">
{% block content %}{% endblock %}
</div>
</section>
{% endblock %}
{% block footer %}
<div class="footer text-center">
<div class="wrapper padding">
<p><a href="https://getgrav.org">Grav</a> was <i class="fa fa-code"></i> with <i class="fa fa-heart"></i> by <a href="https://www.rockettheme.com">RocketTheme</a>.</p>
</div>
</div>
{% endblock %}
{% block bottom %}
{{ assets.js('bottom')|raw }}
{% endblock %}
</body>
Если переменная безопасна для рендеринга и содержит HTML, всегда используйте фильтр |raw
, чтобы шаблон работал с включенным экранированием (autoescape
).
Очень важно включить параметр autoescape
в конфигурации системы или не забыть экранировать каждую переменную в файлах шаблонов, чтобы защитить сайт от XSS-атак.
Шаг 5 - Погружение в детали⚓︎
Пожалуйста, прочитайте код в файле base.html.twig
, для лучшего понимания происходящего. Есть несколько ключевых моментов, которые следует отметить:
-
Переменная
theme_config
устанавливается с конфигурацией темы. Потому что Twig плохо работает с тире, чтобы извлекать переменные с тире (напримерconfig.themes.my-theme
), мы используем Twig-функциюattribute()
для динамического получения данныхmy-theme
изconfig.themes
. -
Элемент
<html lang=...
установлен на основе активного языка Grav, если он включен, иначе он используетdefault_lang
, как установлено вtheme_config
. -
Синтаксис '{% block head %}{% endblock head %}' определяет область в базовом шаблоне Twig. Обратите внимание, что использование
head
в теге{% endblock head %}
не требуется, но используется здесь для удобства чтения. В этот блок мы помещаем вещи, которые обычно находятся в HTML-теге<head>
. -
Тег
<title>
динамически устанавливается на основе переменнойtitle
страницы, установленной в заголовке файла.header.title
- это метод быстрого доступа, но он эквивалентенpage.header.title
. -
После установки пары стандартных метатегов появляется ссылка для включения
partials/metadata.html.twig
. Этот файл содержит цикл, который перебирает метаданные страницы. Фактически это объединение метаданных изsite.yaml
и любых переопределений, специфичных для страницы. -
Запись
<link rel="icon"...
устанавливается путем указания на изображение, зависящее от темы. В этом случае оно находится в каталоге тем под именемimages/logo.png
. Синтаксис для этого -{{url ('theme: //images/logo.png')}}
. -
Запись
<link rel="canonical"...
устанавливает канонический URL-адрес для страницы, который всегда устанавливается на полный URL-адрес страницы через{{ page.url(true, true) }}
. -
Теперь мы определяем блок под названием
stylesheets
, и здесь мы используем менеджер активов для добавления нескольких активов. Первый загружает каркасPure.css
. Второй загружает FontAwesome для предоставления полезных иконок. Последняя запись указывает на файлcustom.css
в папке темыcss/
. Здесь есть несколько полезных стилей, чтобы вы могли начать, но вы можете добавить больше здесь. Также вы можете добавить другие записи CSS-файлов по мере необходимости. -
Вызов
{{ assets.css()|raw }}
- это то, что запускает шаблон для отображения всех тегов ссылок на CSS. -
Блок
javascripts
, как и блокstylesheets
- хорошее место для размещения ваших JavaScript-файлов. В этом примере мы добавляем только библиотекуjquery
, которая уже связана с Grav, так что вам не нужно указывать путь к ней. -
{{ assets.js()|raw }}
выведет все теги JavaScript. -
Тэг
<body>
имеет атрибут класса, который будет выводить всё, что вы установили в переменнойbody_classes
фронтматтера страницы. -
В блоке
header
есть несколько вещей, которые выводят HTML-заголовок страницы. Важно отметить, что логотип имеет гиперссылку наbase_url
с логикой:{{base_url == '? '/': base_url}}
. Это сделано для того, чтобы гарантировать, что если нет подкаталога, ссылка будет просто/
. -
Название сайта выводится в качестве логотипа в этой теме примера с
{{config.site.title}}
, но вы можете просто заменить его тегом<img>
на логотип, если хотите. -
Тег
<nav>
на самом деле содержит ссылку наpartials/navigation.HTML.twig
, который содержит логику для циклического перебора любых видимых страниц и отображения их в виде меню. По умолчанию он поддерживает выпадающие меню для вложенных страниц, но это можно отключить с помощью конфигурации темы. Загляните в этот навигационный файл, чтобы получить представление о том, как генерируется меню. -
Использование
{% block content%} {% endblock%}
предоставляет заполнитель, который позволяет нам предоставлять контент из шаблона, расширяющего этот шаблон. Помните, что мы переопределили это вdefault.html.twig
для вывода содержимого страницы. -
Блок
footer
содержит простой нижний колонтитул, вы можете легко изменить его для своих нужд. -
Подобно блоку содержимого,
{% block bottom%} {% endblock%}
предназначен в качестве заполнителя для шаблонов для добавления пользовательских кодов инициализации JavaScript или аналитических кодов. В этом примере мы выводим любой код JavaScript, который был добавлен в группу активовbottom
. Подробнее об этом читайте в документации менеджер активов.
Шаг 6 - CSS-файлы темы⚓︎
Вы могли заметить, что в файле partials/base.html.twig
мы сделали ссылку на настраиваемую тему CSS через менеджер активов: do assets.add('theme://css/custom.css', 98)
. Этот файл будет содержать любой настраиваемый CSS, который нам нужен для заполнения пробелов, не предусмотренных платформой Pure.css. Поскольку Pure - это очень минималистичный фреймворк, он предоставляет самое необходимое, но почти не имеет стилей.
- В папке
user/themes/my-theme/css
просмотрите файлcustom.css
:
/* Core Styles */
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-size: 1rem;
line-height: 1.7;
color: #606d6e;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: #454b4d;
}
a {
color: #1f8cd6;
text-decoration: none;
}
a:hover {
color: #175e91;
}
pre {
background: #f0f0f0;
margin: 1rem 0;
border-radius: 2px;
}
blockquote {
border-left: 10px solid #eee;
margin: 0;
padding: 0 2rem;
}
/* Utility Classes */
.wrapper {
margin: 0 3rem;
}
.padding {
padding: 3rem 1rem;
}
.left {
float: left;
}
.right {
float: right;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-left {
text-align: left;
}
/* Content Styling */
.header .padding {
padding: 1rem 0;
}
.header {
background-color: #1f8dd6;
color: #eee;
}
.header a {
color: #fff;
}
.header .logo {
font-size: 1.7rem;
text-transform: uppercase;
}
.footer {
background-color: #eee;
}
/* Menu Settings */
.main-nav ul {
text-align: center;
letter-spacing: -1em;
margin: 0;
padding: 0;
}
.main-nav ul li {
display: inline-block;
letter-spacing: normal;
}
.main-nav ul li a {
position: relative;
display: block;
line-height: 45px;
color: #fff;
padding: 0 20px;
white-space: nowrap;
}
.main-nav > ul > li > a {
border-radius: 2px;
}
/*Active dropdown nav item */
.main-nav ul li:hover > a {
background-color: #175e91;
}
/* Selected Dropdown nav item */
.main-nav ul li.selected > a {
background-color: #fff;
color: #175e91;
}
/* Dropdown CSS */
.main-nav ul li {
position: relative;
}
.main-nav ul li ul {
position: absolute;
background-color: #1f8dd6;
min-width: 100%;
text-align: left;
z-index: 999;
display: none;
}
.main-nav ul li ul li {
display: block;
}
/* Dropdown CSS */
.main-nav ul li ul ul {
left: 100%;
top: 0;
}
/* Active on Hover */
.main-nav li:hover > ul {
display: block;
}
/* Child Indicator */
.main-nav .has-children > a {
padding-right: 30px;
}
.main-nav .has-children > a:after {
font-family: FontAwesome;
content: '\f107';
position: absolute;
display: inline-block;
right: 8px;
top: 0;
}
.main-nav .has-children .has-children > a:after {
content: '\f105';
}
Это довольно стандартный CSS-файл, который задает некоторые основные поля, шрифты, цвета и служебные классы. Для отрисовки раскрывающегося меню требуются некоторые базовые стили содержимого и более обширные стили. Не стесняйтесь изменять этот файл по своему усмотрению или даже добавлять новые файлы CSS (просто убедитесь, что вы добавили ссылку в блоке head
, следуя примеру с custom.css
).
Шаг 7 - Тестирование⚓︎
Чтобы увидеть свою тему в действии, откройте браузер и укажите в нем свой сайт Grav. Вы должны увидеть что-то вроде этого:
Поздравляем, вы создали свою первую тему!