jekyll-is-images
Сначала коротко про jekyll-is-images. По сравнению с состоянием на прошлый пост в основном
произошло много мелких правок мелких багов, из относительно существенного — довел до ума работу галерей в режиме слайд-шоу (впрочем, и там
есть куда расти). А третью цифру я поднял при смене зависимости с is-kramdown-hooked
на jekyll-is-hookdown, о котором и поговорим далее. Это повлияло на то, что следует указывать
в _config.yml — вместо input: ISKram в подразделе kramdown следует указывать markdown: Hookdown в корне конфига. А подраздел
kramdown остается полностью рабочим, и там можно указывать любой input, например — GFM1 (что я и собираюсь сделать на сайте
в ближайшее время).
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 %}. ↩