Статьи

Взлом компонента маршрутизации в Jekyll

Изначально я собирался озаглавить эту статью. Взлом компонента маршрутизации в Jekyll, когда он размещен на страницах GitHub с Markdown, Liquid и YAML . Очевидно, это немного долго, поэтому мне пришлось сократить его. В любом случае, суть не меняется: у Джекилла нет какого-то роутера, и я думаю, что нашел не столь ужасное решение, чтобы имитировать его.

Но обо всем по порядку: я исходил из опыта Symfony , поэтому под маршрутизатором я подразумеваю компонент, который отображает URL-адреса на имена — так называемые маршруты — так что вы можете смело менять URL-адрес без необходимости сканировать свою кодовую базу, чтобы обновить все ссылки, ведущие к устаревшим место расположения.

Зачем нам такая вещь?

В настоящее время я усердно работаю над документами для SassDoc v2 (на момент написания статьи еще не выпущен). У нас довольно много контента; более 20 страниц разбиты на 4 разных раздела, содержащих множество примеров кода и перекрестных ссылок.

Пару раз во время переписывания я хотел изменить URL. Проблема в том, что когда я меняю URL, мне нужно обновить все ссылки на этот URL, если я не хочу, чтобы они были сломаны. Просматривать более 20 страниц, чтобы убедиться, что все URL-адреса в порядке, далеко от идеала…

Вот почему нам нужен компонент маршрутизации. Затем мы будем ссылаться на URL-адреса по имени, а не по их пути, что позволит нам изменить путь, сохраняя при этом правильное имя.

Как это работает?

Итак, что нам нужно, чтобы эта работа? Если вы используете Jekyll, но не ограничены безопасным режимом (что, к сожалению, имеет место при использовании GitHub Pages для хостинга), вы можете найти / собрать плагин Ruby для этого. Это было бы наилучшим решением, поскольку обычно это что-то, что обрабатывается серверным языком.

Теперь, если вы размещаете свой сайт на страницах GitHub, что чаще всего встречается в Jekyll, вы не можете использовать плагины и расширять ядро ​​Jekyll с помощью пользовательского кода Ruby, и в итоге вы получаете решение с помощью доступных средств: Liquid и Markdown. ,

Основная идея заключается в том, чтобы иметь файл, содержащий все наши маршруты, сопоставленные с реальными URL. К счастью, Jekyll позволяет нам определять пользовательские глобальные переменные с помощью файлов YAML / JSON / CSV, хранящихся в папке _datasite.data.<filename> Таким образом, мы можем получить доступ к этим URL-адресам непосредственно на наших страницах от их имени.

Чтобы добавить немного синтаксического сахара сверху, мы создадим ссылки на Markdown, которые позволят использовать более удобный синтаксис, но давайте не будем слишком быстро идти слишком быстро.

Создание роутера

Задача маршрутизатора состоит в том, чтобы выставлять маршруты (или имена ), сопоставленные с URL-адресами (один к одному). Можно создать файлы YAML / JSON / CSV в папке _dataroutes.yml

 home: "/"
about: "/about-us/"
faq: "/frequently-asked-questions/"
repository: "https://github.com/user/repository"

Вы, возможно, заметили, что мы, конечно, не ограничены внутренними ссылками. Мы можем полностью определить маршруты для внешних URL-адресов, чтобы не вводить их снова и снова, если они будут появляться регулярно. В том же духе мы остановились на 4 маршрутах для нашего примера, но маршрутизатор может содержать сотни маршрутов.

Поскольку файл находится в _datasite.data.<filename>.<key> Допустим, у нас есть страница, содержащая следующий код:

 ---
layout: default
title: "About us"
---

<!-- Content about us -->

Go to our [GitHub repository]({{ site.data.routes.repository }}).
Or read the section dedicated to [Frequently Asked Questions]({{ site.data.routes.faq }}).

Как видите, мы больше не ссылаемся на URL, а вместо этого на маршруты. Это не волшебство, оно только сообщает Jekyll доступ к глобальным переменным, хранящимся по указанному пути (например, site.data.routes.faq

Теперь, если хранилище больше не размещено на GitHub или URL страницы «О нас» теперь /about/ Обновляя маршрутизатор, мы заставляем его работать, не возвращаясь на наши страницы, чтобы обновить наши ссылки.

Добавление синтаксического сахара

На данный момент у нас есть функциональный маршрутизатор, позволяющий нам изменять любой URL без необходимости сканировать наш сайт для исправления неработающих ссылок. Так что вы можете сказать, что это уже довольно круто. Однако вводить site.data.routes.faq Конечно, мы могли бы сделать его немного элегантнее!

Да и нет. Сначала я подумал о создании небольшой функции route()site.data.routes.<key> Проблема в том, что мы запускаем Jekyll в безопасном режиме, поэтому мы не можем расширить его с помощью кода Ruby. Неудачно.

Затем я подумал о функции Markdown, которой никогда не пользовался: ссылки-ссылки . Вот как ссылка представлена ​​в Markdown:

 [I am a link](http://link.url/)

Вы также можете установить ссылку, чтобы перейти к ссылке — которая, кстати, совершенно невидима, определена в любом месте страницы, например:

 [I am a link][id_reference]

​[id_reference]: http://link.url

Примечание: скобки заменяются скобками при использовании ссылки, а не URL.

Это может позволить вам определять все ваши ссылки в одном месте (например, внизу), а не по всему документу. Должен сказать, что я не очень часто использовал эту функцию, но в этом случае она пригодится.

Идея состоит в том, чтобы автоматически генерировать ссылки на ссылки с нашего маршрутизатора, чтобы мы могли использовать наши маршруты в качестве ссылки в любом файле. Оказывается, на удивление легко сделать это в Liquid:

 # _includes/route.html
{% for route in site.data.routes %}
[{{ route[0] }}]: {{ route[1] }}
{% endfor %}

Добавив цикл for в любое место на странице, он дает указание Jekyll обработать его как код Liquid, который затем будет обрабатываться как ссылки Markdown. Так, например, и возвращаясь к нашему предыдущему примеру, мы могли бы сделать:

 ---
layout: default
title: "About us"
---

<!-- Content about us -->

Go to our [GitHub repository][repository].
Or read the section dedicated to [Frequently Asked Questions][faq].

{% for route in site.data.routes %}
[{{ route[0] }}]: {{ route[1] }}
{% endfor %}

Теперь мы говорим, верно? Единственная проблема состоит в том, чтобы включить этот цикл на любой странице. Сначала я думал добавить его в макет, чтобы он автоматически добавлялся на любую страницу с использованием соответствующего макета. Проблема в том, что макеты не обрабатываются как Markdown в Jekyll, поэтому ссылки на самом деле видны внизу DOM. Хуже того, они не могут быть использованы на наших страницах, так как они не были обработаны как Markdown … Жаль.

Однако мы все еще можем сделать что-то, чтобы сделать это немного лучше. Мы можем поместить этот цикл в частичное представление Liquid и включать частичное в каждую страницу, а не вставлять его в копию. Скажем, мы создаем routes.html_includes

 {% for route in site.data.routes %}
[{{ route[0] }}]: {{ route[1] }}
{% endfor %}

А потом, на нашей странице:

 ---
layout: default
title: "About us"
---
{% include routes.html %}

<!-- Content about us -->

Go to our [GitHub repository][repository].
Or read the section dedicated to [Frequently Asked Questions][faq].

Примечание: вы можете включить частичное в любом месте страницы, а не только сверху. Вы могли бы полностью поместить это как самую последнюю строку файла.

Последние мысли

Вот и все, мы взломали небольшой компонент маршрутизации в безопасном режиме Jekyll. Каковы недостатки этого? Есть несколько второстепенных:

  • Это работает в Markdown; если у вас есть ссылка в простом HTML, вы должны вернуться к {{ site.data.routes.<key> }}
  • Вы не можете добавить привязку к ссылке; если вам нужно, вернитесь к {{ site.data.routes.<key> }}#anchor
  • Вы должны включить частичку HTML во все страницы, что может быть утомительно (даже если вы считаете это расширением основного вопроса YAML, который вам все равно придется писать).

Помимо этих недостатков, все хорошо и блестяще. Как вы думаете?