jekyll-is-images
Сначала коротко про jekyll-is-images. По сравнению с состоянием на прошлый пост в основном
произошло много мелких правок мелких багов, из относительно существенного — довел до ума работу галерей в режиме слайд-шоу (впрочем, и там
есть куда расти). А третью цифру я поднял при смене зависимости с is-kramdown-hooked
на jekyll-is-hookdown, о котором и поговорим далее. Это повлияло на то, что следует указывать
в _config.yml — вместо input: ISKram в подразделе kramdown следует указывать markdown: Hookdown в корне конфига. А подраздел
kramdown остается полностью рабочим, и там можно указывать любой input, например — GFM 1 (что я и собираюсь сделать на сайте
в ближайшее время).
jekyll-is-hookdown
Итак, что же это такое? Это специальный гем, который «хакает» процесс обработки markdown в Jekyll, добавляя хук на тот момент, когда
страница уже распарсена во внутреннее AST-представление и еще не преобразована во что-то другое. Зачем это надо? Чтобы не делать лишней
работы по парсингу исходного markdown или финального HTML.
Поскольку я планирую этот подход использовать не только в jekyll-is-images,
вполне логично было вынести этот механизм в отдельный гем. Более того, подобный хак плохо дублируется, и втыкать его в каждый функциональный
плагин по отдельности потребует много хитрых оберток и постоянного разруливания конфликтов…
В общем, главный недостаток такого подхода в том, что он по сути формирует экосистему, несовместимую с другими экосистемами, использующими
тот же хак… Поэтому я планирую отдельно пройтись по jekyll-is-images и четко разделить возможности, требующие хака, т.е. переинтерпретацию
стандартного markdown-синтаксиса, и тот же функционал в liquid-тегах, хака соответственно не требующий.
Небольшое историческое отступление
Сначала я запихнул хук внутрь собственно Kramdown через кастомный парсер — в геме is-kramdown-hooked.
Причем это решение не требовало зависимости от Jekyll, но — обратная сторона медали — и не особо-то интегрировалось с системой хуков в Jekyll.
Кроме того, использование кастомного парсера не позволяло использовать другие кастомные парсеры…
А еще в процессе работы я понял, что
нужный мне момент вполне доступен и извне Kramdown — это момент между созданием Kramdown::Document и вызовом его to_html (или to_latex, etc).
Принцип работы
Во-первых, определен кастомный конвертер в Jekyll. Естественно, он просто унаследован от стандартного, и всего один метод переопределен.
В _config.yml требуется указать markdown: Hookdown чтобы использовать этот конвертер вместо стандартного.
Во-вторых, и это уже чистый хак (или грязный…) к стандартному набору хуков Jekyll добавлено событие:post_parse для страниц, документов
и постов. Тут на самом деле довольно интересно: почему-то Jekyll легко позволяет расширять систему хуков в разрезе объектов, но не дает этого
делать в разрезе событий… Приходится хакать, благо в Ruby это сделать легко, но проблема тут, конечно, в том, что хак полагается на внутреннюю
структуру, а не интерфейс.
Зато теперь можно писать:
Jekyll:: Hooks:: register [:pages,:documents],:post_parse do | page, document |
# Тут что-то делаем с document (это Kramdown::Document)
end
И в-третьих, уже в порядке дополнительного расширения имеется хук на элементы по типам. Он уже вешается не через стандартный механизм, поскольку
у стандартного параметров не хватает.
JekyllIS:: Hookdown:: register_element_hook [:pages,:documents],:img do | page, element |
# Делаем что-то с element (Kramdown::Element)
end
При этом важно, что ваш обработчик возвращает:
Kramdown::Element — заменит элемент, на котором был вызван хук, в дереве документа.
nil — не приведет к изменениям в документе (если вы сами внутри обработчика не модифицировали дочерние элементы данного).
:delete — удалит элемент, на котором вызван хук из дерева документа.
Любые другие значения трактуются как ошибочные.
Использование
Думаю, уже понятно, что данный гем используется из других плагинов — расположенных в каталоге _plugins или в отдельных гемах — неважно.
При этом чтобы он работал, нужно включить кастомный конвертер в _config.yml, что делается конечным пользователем, а не разработчиком
плагина… Зато разработчик плагина может это проверить посредством JekyllIS::Hookdown::enabled?, что крайне рекомендуется делать, чтобы
конечный пользователь не получил неожиданных и непонятных для него ошибок.
Что дальше?
По jekyll-is-hookdown я не вижу направлений для расширения функциональности без потери логики. Буду писать документацию и править баги, если
вдруг появятся.
По jekyll-is-images планов полно, приглашаю в Issues.
is-kramdown-hooked отправится в архив.
GitHub Flavored Markdown. Конкретно мне это нужно для того, чтобы использовать ``` (тройной бэктик) для блоков кода вместо окружения {% highlight %}. ↩