en RU

jekyll-is-hookdown

GitHub License Gem Version Ruby Coverage

Плагин для Jekyll, позволяющий подменить markdown-парсер на кастомный — унаследованный от стандартного Kramdown и дополняющий его дополнительным хуком для перехвата внутреннего AST-представления.

Подключение

Вообще, гем предназначен для использования другими плагинами и должен быть указан в зависимостях именно в них, а не в Gemfile сайта. Однако, в Jekyll есть возможность писать плагины в подкаталоге _plugins — чтобы там использовать данный хук, потребуется подключить данный гем именно как плагин:

В Gemfile:

group :jekyll_plugins do
    . . .
  gem 'jekyll-is-hookdown', '~> 0.8'
end

Или, если вы не используете Bundler, установить гем командой:

gem install jekyll-is-hookdown

В _config.yml:

plugins:
    . . .
  - jekyll-is-hookdown

markdown: Hookdown

Последняя строчка включает работу плагина. При этом, поскольку конвертер унаследован от стандартного Kramdown, будут работать все расширения и настройки в подразделе конфигурации kramdown (собственной секции hookdown плагин не предусматривает), например:

kramdown:
  input: GFM
  hard_wrap: false

Зависимости

  • Ruby >= 3.4

  • Jekyll ~> 4.4

  • Kramdown ~> 2.5

Использование

Основной хук внедрен в общую систему хуков Jekyll как событие :post_parse. Он доступен для объектов :pages, :documents и :posts (нужно заметить, что :documents включает в себя :posts). В обработчик передается объект документа/страницы и объект класса Kramdown::Document.

Jekyll::Hooks::register [ :pages, :documents ], :post_parse do |page, document|
  # Какие-то действия с документом...
end

Поскольку чаще всего нужно обрабатывать не весь документ, а определенные теги/элементы, предусмотрен и другой хук, не приводимый к стандартным, он регистрируется иначе. В обработчик передается объект документа/страницы и объект класса Kramdown::Element.

JekyllIS::Hookdown::register_element_hook [ :pages, :documents ], :a, :img do |page, element|
  case element.type
  when :a
    # Тут что-то делаем...
  when :img
    # И тут что-то делаем...
  end
end

При этом значение, возвращаемое обработчиком, важно и трактуется следующим образом:

  • nil — не приводит к дополнительным действиям.

  • Kramdown::Element — заменяет текущий элемент в AST-дереве.

  • :delete — удаляет текущий элемент из AST-дерева.

  • Прочие значения трактуются как ошибочные.

Замена и удаление корневого элемента (document.root) не поддерживается.

Рекомендация

Если вы пишете свой плагин с использованием этого хука, крайне желательно убедиться, что он активирован, то есть в конфиге выбран соответствующий кастомный конвертер. Можно, конечно, непосредственно проверять значение в _config.yml, но лучше использовать специальный метод:

if JekyllIS::Hookdown::enabled?
  # Устанавливаем свои хуки здесь...
end

Проверка этого условия будет работать даже до инициализации сайта.

Пример

Выставим всем внешним ссылкам target="_blank":

if JekyllIS::Hookdown::enabled?
  JekyllIS::Hookdown::register_element_hook [ :pages, :documents ], :a do |_, element|
    href = element.attr['href']
    target = element.attr['target']
    if href && !target && (href.start_with?('https://') || href.start_with?('http://'))
      element.attr['target'] = '_blank'
    end
    nil
  end
end

Лицензия

Плагин опубликован под GNU Lesser General Public License v3.0. Это означает, что вы можете свободно им пользоваться без каких-то ограничений, пока подтягиваете его по зависимостям. Если же вы захотите взять код и втянуть его в свой проект, или выпустить форк данного плагина, результат должен быть опубликован так же под LGPLv3.

Статус

Текущая версия — 0.8.x. Это следует трактовать как публичную альфа-версию.

Однако, в силу принципиального ограничения функциональности — плагин чисто инфраструктурный и не должен делать ничего лишнего, скорее всего чего-то нового в нем уже не появится. Так что по мере доработки автотестов и документации он будет плавно переходить в стадию бета-версии (0.9.x) и затем релиза (1.0) без каких-либо сущностных изменений в коде.