Введение
Я уже посвящал несколько постов платформе по ведению блогов Ghost. Должен сказать, что продолжаю использовать именно ее, хотя и испытал за последнее время несколько довольно сильных потрясений. Но об этом расскажу несколько позже, когда все более менее обдумаю и разложу по полочкам. Сейчас же хочу вернуться к теме оформления постов, а именно, к использованию графических изображений.
На эту тему я тоже уже писал ранее, но, как это обычно и бывает, возникают новые потребности, ищутся и, порой, находятся пути их реализации. Если вам интересно, что же это за потребности и как я их реализовал - читайте дальше. Но прежде, хочу предупредить, что web дизайн, все эти CSS, Javascript и прочие прибамбасы не входят в сферу моих профессиональных интересов, я лишь упражняюсь, как любитель. Если бы Ghost
позволил мне обойтись без всех этих премудростей, я был бы только счастлив.
Добавление подписи к рисункам
Первое, что мне захотелось - получить возможность задавать поясняющую подпись под вставленным изображением. На самом деле, можно придумать и реализовать множество вариантов. Например, можно вставить таблицу из двух строк, в одной разместив картинку, во второй - подпись. Можно воспользоваться специальной карточкой для изображений, которые появились в Ghost
в версии 2
, если память мне не изменяет. Можно, наконец, воспользоваться какой-нибудь другой темой, а не Casper
-ом, который является темой по умолчанию. Но... Таблицы добавлять достаточно сложно, специальная карточка сразу отметала использование мобильного клиента[1], ну и заменять тему тоже не хотелось, так как Casper
пактически сразу получает новые фичи и исправления ошибок.
Тег <figure/>
На самом деле, мне очень приглянулось решение, основанное на использовании тегов <figure> и <figcaption>, которые появились в спецификации HTML5. Тег <figure/>
и предназначен для описания как раз таких объектов, как иллюстрации, диаграммы, исходные коды и тому подобное. Ну а <figcaption/>
используется для указания описания элемента <figure/>
, то есть, той самой подписи.
Главное ограничение, если это можно назвать ограничением, заключается в том, что, с идеологической точки зрения, содержимое тега <figure/>
должно быть самодостаточным и не привязанным к конкретному месту в документе. То есть, предполагается, что в тексте есть смысловая ссылка, например, "смотри рисунок 22"
, а где этот рисунок размещен - хоть в самом конце текста, хоть рядом с этой самой ссылкой - не имеет значения, главное, что он должен быть подписан "Рисунок 22"
. А вот если в тексте написано "смотри рисунок ниже"
, то предлагается не использовать тег <figure/>
, а задействовать, например, тег <div/>
.
Code injection
Ну вот, с тем, как описывать рисунки с подписями, я определился. Далее дело за малым - выбрать механизм, как добавлять эти теги в текст. И самый простой способ - руками, по мере написания текста поста. Но у такого метода, наряду с его основным преимуществом (простотой), есть ряд отрицательных моментов. Один из них - что делать с теми постами, которые уже опубликованы? Неужели, все их редактировать? Кроме того, вбивать каждый раз эти HTML
элементы в Markdown
тексте - то ещё удовольствие. И тут на помощь мне пришел великий и могучий Javascript
. Но, для начала, следует упомянуть о такой возможности Ghost
, как Code injection.
Ghost
использует шаблонизатор Handlebars для реализации собственного фреймворка шаблонов. В этом инструменте есть такое понятие, как helper
-ы. Что это такое? Если коротко, то helper
- это предварительно определенная функция, результат выполнения которой будет вставлен в шаблон. Причем, некоторые helper
-ы реализованы, что называется, из коробки и, кроме того, предусмотрен механизм написания и регистрации собственных helper
-ов.
Авторы Ghost
не поленились и написали много собственных helper
-ов. В их числе есть {{ghost_head}} и {{ghost_foot}}, которые можно использовать в собственных темах. Сами разработчики Ghost
задействуют эти helper
-ы в собственной теме Casper
- они добавили их в файл default.hbs: {{ghost_head}}
- непосредственно перед закрывающим тегом </head>
, а {{ghost_foot}}
- непосредственно перед закрывающим тегом </body>
. Выглядит это так:
<html lang="{{@site.lang}}">
<head>
...
<link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}" />
{{!-- This tag outputs SEO meta+structured data and other important settings --}}
{{ghost_head}}
</head>
<body class="{{body_class}}">
...
{{!-- The #block helper will pull in data from the #contentFor other template files. In this case, there's some JavaScript which we only want to use in post.hbs, but it needs to be included down here, after jQuery has already loaded. --}}
{{{block "scripts"}}}
{{!-- Ghost outputs important scripts and data with this tag - it should always be the very last thing before the closing body tag --}}
{{ghost_foot}}
</body>
</html>
Использование этих helper
-ов предоставляет довольно много возможностей, в том числе - добавление дополнительных скриптов и стилей. Естественно, чтобы эти скрипты и стили можно было добавить, необходимо место, в котором их можно было бы задать. И авторы Ghost
предоставли такую возможность в административном интерфейсе, назвав ее Code injection
. На самом деле, вся эта конструкция получилась достаточно удобной, так как позволяет быстро внести дополнения в чужую тему, по сути, не меняя ее[2].
Javascript для формирования тегов <figure/>
Итак, благодаря Code injection
есть возможность в тему добавить некий Javascript
код, который бы что-нибудь этакое бы сделал, после чего волшебным образом у нас все рисунки обрамились бы тегом<figure/>
с подписями в теге <figcaption/>
. Я не очень большой знаток Javascript
, поэтому не стал сам изобретать велосипед, предположив, что кто-то где-то такое уже делал. И предчувствие меня не обмануло: я наткнулся на тему для Ghost
, которую ее автор выложил в открытый доступ, поняв (и приняв), что не имеет достаточно времени для ее развития. И за эту щедрость ему огромное человеческое спасибо.
В этой теме (название ее Chiara) есть именно тот функционал, который мне и требовался. В файле index.js я нашел интересующий меня кусочек кода:
...
// Creates Captions from Alt tags
$(".post-content img").each(function() {
// Let's put a caption if there is one
if($(this).attr("alt"))
$(this).wrap('<figure class="image"></figure>')
.after('<figcaption>'+$(this).attr("alt")+'</figcaption>');
});
...
Давайте попробуем разобраться, что здесь к чему. Автор кода выбирает все теги <img/>
, которые принадлежат элементу с классом post-content
. То есть, изменения коснутся только тех графических изображений, которые включены в текст поста. Другие картинки, например, заглавная картинка поста, не пострадают.
После, уже в теле цикла, для каждого найденного элемента <img/>
производится проверка, определен ли для этого элемента атрибут alt
. То есть, автор решил для себя, что именно атрибут alt
он будет использовать для задания подписи к картинке, и если такого атрибута у конкретного элемента нет, то и модифицировать этот элемент не надо. Что ж, на самом деле, весьма логично.
Ну а дальше следует код с использованием методов библиотеки jQuery, который и выполняет всю работу:
- обрамляет (метод wrap) найденный элемент
<img/>
HTML
кодом<figure class="image"></figure>
, по сути, элементом<figure/>
, задавая ему классimage
- добавляет за найденным элементом (метод after) HTML текст
'<figcaption>'+$(this).attr("alt")+'</figcaption>'
, то есть, добавляет элемент<figcaption/>
, в качестве значения которого указывается значение атрибутаalt
обрабатываемого тега<img/>
Таблица стилей - CSS
Но изменить/добавить нужный HTML
код - это пол дела. Надо еще определить, как этот код будет представлен. А для этого используются таблицы стилей. Если обратиться к первоисточнику, а именно, к теме Chiara
, то в файле main.sass[3] можно найти объявление стиля для следующих элементов <figure/>
и <figcaption/>
:
...
.post-content .post-footer
...
figure
padding: 0 0 modular-scale(1rem, 2, 1.33)
margin: 0
text-align: center
figcaption
padding: modular-scale(1rem, -1, 1.33) 0 0
font-style: italic
color: #aaa
font-size: modular-scale(1rem, 0, 1.33)
...
Как видим, автор темы задает отступы, поля и выравнивание для тега <figure/>
и предлагает использовать курсивный шрифт (italic
), размер которого рассчитывается[4] исходя из размера шрифта корневого элемента html
[5], в качестве цвета использовать #aaa - средне-светлый оттенок серого, ну и отступы (padding) тоже определены относительно шрифта корневого элемента. Использовать этот стиль, или создать собственный - решать вам.
Решение
Теперь соберем все сказанное ранее воедино. В административном интерфейсе блога надо выбрать элемент меню Code injection
и добавить наш стиль и скрипт в соответствующие элементы. Обычно, стили добавляются в helper
{{ghost_head}}
, а скрипты - в helper
{{ghost_foot}}
:
Ниже привожу используемый мною стиль для подписей к графическим изображениям:
<style>
.post .post-content figcaption {
font-weight: normal;
font-style: italic;
font-size: 16px;
color: #555;
outline: 0;
text-align: center;
}
Ну и сам скрипт для вставки нужных HTML
элементов:
<script>
// Creates Captions from Alt tags
$(".post-content img").each(
function() {
// Let's put a caption if there is one
if ($(this).parent().prop("tagName").toLowerCase() !== 'figure' && $(this).attr("alt")) {
$(this).wrap(
'<figure class="image"></figure>'
).after('<figcaption>' + $(this).attr("alt") + '</figcaption>');
}
});
</script>
В скрипте я добавил лишь одну вещь - проверку на то, не "обернут" ли уже тег <img/>
в тег <figure/>
. Если обернут, то я считаю, что, по каким-то причинам, все необходимые действия были сделаны мною вручную, и автоматическая обработка не требуется. Если вам такая проверка не нужна, то просто уберите следующий код: $(this).parent().prop("tagName").toLowerCase() !== 'figure' &&
.
Вот, пожалуй, и все... пока...