Shields.io is a "service for concise, consistent, and legible badges in SVG and raster format, which can easily be included in GitHub readmes or any other web page."
Their service takes query parameters to their API endpoint to generate a badge / shield. For example:
https://img.shields.io/static/v1?label=Find%20me%20on&message=GitHub&color=181717&style=flat&logo=github
becomes:
I was planning to use this in my personal blog, when I realized a problem; it is hard to maintain.
While it may be rare to change the content of those shields, it would be nice to have a maintainable way to put a shield on my blog.
Since I use Jekyll, I can define a custom 'Liquid tag.' Just like we can embed stuff from compatible services with liquid tags here in DEV.to, e.g., {% github repo %}
and {% embed website %}
, we can make a custom tag, say, {% shields_io payload %}
, to display a shield.
How does Liquid tag on Jekyll work?
The Liquid tag on Jekyll takes the following format:
{% tag_name [tag_argument] %}
It has a tag name, and one optional argument.
See the problem here? There is at most one value accepted as an argument. Shields.io takes way more than that, and putting query parameter here does not solve anything.
There is still hope, though; let's take a look at the code we'll be writing.
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
The arg
argument is the argument passed from the tag. It's a string. So we can do something with the input.
And looking back at the original problem, we are trying to pass a set of key-value pairs to an API endpoint.
So, I decided to pass a JSON payload here; it can be prettified for our purposes, and Ruby supports JSON deserialization out of the box.
How to turn it into the URL
Since Ruby can turn the input JSON into a hash, we can iterate on this hash and construct the query parameter.
So the idea is to deserialize the JSON and store it in a variable:
def initialize(tag_name, input, parse_context)
super
# @type [Hash]
@config = JSON.load(input.strip)
end
And construct the query parameter. I also decided to include href
and alt
for other purposes into the JSON payload, but they are not relevant for the request. So I extract their values and remove it from the input hash before turning the rest into the query parameter.
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
Result
Here is my creation - copy the last two files and run a local server!
Shields.IO is a web service to create a 'badge' you may find in a README in many GitHub repositories.
All you need to craft is a URL, and the service will interpret your request.
https://img.shields.io/static/v1?label=Find%20me%20on&message=GitHub&color=181717&style=flat&logo=github
There is one issue with this approach; the URL is too long to handle for human.
I wrote these files to create a Liquid tag for Jekyll that makes it easier to create those shields.
Copy custom-tags.rb
into $SOURCE_DIR/_plugins
directory, where $SOURCE_DIR
is .
(your Jekyll project root) by default
and may change if you have source
key in your _config.yml
.
A restart of bundle exec jekyll serve
is required should you be running one already.
The syntax is:
{% shields_io <JSON here> %}
The idea is to pass a JSON object consisting of query parameters.
{
"href": "https://www.github.com/clpsplug",
"label": "Find me on",
"message": "GitHub",
"color": "181717",
"style": "flat",
"logo": "github",
"alt": "GitHub"
}
key | required? | content |
---|---|---|
href | NO | A URL. Specifying this key will turn the shield into a clickable link |
label | NO | The leftside text of the shield. If left, it will be "static" |
message | YES | The rightside text of the shield. |
color | NO | The color of the right side (some styles may ignore this value.) This can be color name (see Shields.io for supported names) or hex color code. Hex color codes must not contain # . If left, 'inactive' is used. |
style | NO | The shield style, see Shields.io for valid values. If left, 'plastic' is used. |
logo | NO | Service name or Simple Icons icon name; display on the left of the leftside text. |
alt | NO, but strongly recommended | The alternative text for the image. This should be specified for accessibility reasons and when the service fails for any reason. |
- JSON payload should be passed without being surrounded by quotes; quotes will break them.
- Liquid tags can span across multiple lines, so it is safe to prettify your JSON.
MIT
--- | |
layout: your_layout | |
--- | |
<p> | |
{% shields_io { | |
"href": "https://www.github.com/clpsplug", | |
"label": "Find me on", | |
"message": "GitHub", | |
"color": "181717", | |
"style": "flat", | |
"logo": "github", | |
"alt": "GitHub" | |
} %} | |
</p> |
Top comments (0)