Shields.io — это «сервис для создания лаконичных, последовательных и разборчивых бейджей в формате SVG и растровом формате, которые можно легко включить в ридми GitHub или любую другую веб-страницу».
Их сервис принимает параметры запроса к конечной точке API для создания бейджа / щита. Например:
https://img.shields.io/static/v1?label=Find%20me%20on&message=GitHub&color=181717&style=flat&logo=github
становится:
Я планировал использовать это в своем личном блоге, но понял одну проблему: это сложно поддерживать.
Хотя содержимое этих щитов можно редко менять, было бы неплохо иметь поддерживаемый способ размещения щита в моем блоге.
Поскольку я использую Jekyll, я могу определить пользовательский «жидкий тег». Точно так же, как мы можем встраивать материалы из совместимых сервисов с помощью тегов liquid здесь, на DEV.to, например, {% github repo %}
и {% embed website %}
, мы можем сделать пользовательский тег, скажем, {% shields_io payload %}
, для отображения щита.
Как работает тег Liquid на Jekyll?
Тег Liquid на Jekyll имеет следующий формат:
{% tag_name [tag_argument] %}
Он имеет имя тега и один необязательный аргумент.
Видите, в чем проблема? В качестве аргумента принимается не более одного значения. Shields.io принимает гораздо больше, и размещение здесь параметра запроса ничего не решает.
Однако надежда еще есть; давайте посмотрим на код, который мы будем писать.
module Jekyll
class CustomTag < Liquid::Tag
def initialize(tag_name, arg, parse_context)
super
# @type [String]
@arg = arg
end
def render(_context)
"The argument is #{@arg}" # return the render result here
end
end
end
Аргумент arg
— это аргумент, передаваемый из тега. Это строка. Таким образом, мы можем что-то сделать с вводом.
Если вернуться к исходной задаче, то мы пытаемся передать набор пар ключ-значение в конечную точку API.
Поэтому я решил передать сюда полезную нагрузку в формате JSON; ее можно приукрасить для наших целей, а Ruby поддерживает десериализацию JSON из коробки.
Как превратить его в URL
Поскольку Ruby может превратить входной JSON в хэш, мы можем выполнить итерации по этому хэшу и построить параметр запроса.
Идея заключается в том, чтобы десериализовать JSON и сохранить его в переменной:
def initialize(tag_name, input, parse_context)
super
# @type [Hash]
@config = JSON.load(input.strip)
end
И сконструировать параметр запроса. Я также решил включить href
и alt
для других целей в полезную нагрузку JSON, но они не имеют отношения к запросу. Поэтому я извлекаю их значения и удаляю из входного хэша, прежде чем превратить остаток в параметр запроса.
def render(_context)
href = @config[:href]
alt = @config[:alt]
@config.delete(:href)
@config.delete(:alt)
shield_tag = <<HTML
<img src="https://img.shields.io/static/v1?#{hash_to_query}"
HTML
if alt != nil
shield_tag += " alt="#{alt}" />"
else
shield_tag += " />"
end
if href != nil
<<HTML
<a href="#{href}">
#{shield_tag}
</a>
HTML
else
shield_tag
end
end
private
def hash_to_query
@config.to_a.map { |k, v|
"#{k}=#{v}"
}.join '&'
end
Результат
Вот мое творение — скопируйте последние два файла и запустите локальный сервер!