Plugins para blog.kippel.org
Hace poco migré todo mi blog antiguo (sigint.in, que en paz descanse) a este nuevo dominio y de pasada hice privado el repositorio con el código del proyecto. Una verdadera pérdida para la comunidad open-source, lo sé. En sí no tenía ninguna gracia: Uso Jekyll con un theme custom -minimalista porque no le sé al frontend- y todo dockerizado y pegado con scotch para que no sea tan tedioso hacer cambios. La única pérdida real (con hartas comillas) son los mini plugins que escribí, que probablemente le podrían servir a alguien para su propio blog. Son bien chicos así que los dejo acá.
Plugin 1: img
Al igual que su nombre, este plugin es fome y corto. De hecho, este es todo el código:
module Jekyll
module Tags
class ImgTag < Liquid::Tag
@@base_asset_path = "/assets/posts"
def initialize(tag_name, img_name, token)
super
@image_name = img_name.strip
end
def render(context)
slug = context.environments.first['page']['slug']
post_year = context.environments.first['page']['date'].year
"#{@@base_asset_path}/#{post_year}/#{slug}/#{@image_name}"
end
end
end
end
Liquid::Template.register_tag('img', Jekyll::Tags::ImgTag)
Básicamente, crea un tag de Liquid, ‘img’, que devuelve la ruta absoluta de un asset para el post en cuestión. Existen muchísimos proyectos parecidos que buscan solucionar la gestión de assets en Jekyll, pero no me convenció ninguno realmente.
Como contexto, antes tenía un solo directorio en donde guardaba los assets para todo el blog, principalmente las imagenes para los posts. Se veía así:
Y para referenciarlas en un post, tenía que escribirlo así:

Si… Por otro lado, con este plugin la estructura cambia a algo así:
. |-- assets | \-- posts | |-- 2023 | | `-- SLUG-1 | | `-- asset-1.png | `-- 2024 | `-- SLUG-2 `-- posts |-- 2023 | `-- 2023-11-09-SLUG-1.md `-- 2024 \-- 2024-05-22-SLUG-2.md
En donde los assets de posts/2023/2023-11-09-SLUG-1.md están en assets/posts/2023/SLUG-1, y pueden referenciarse así:

Es una tontera al final del día, pero tiene esa simpleza que muchos otros proyectos no tienen. Hasta ahora me ha funcionado muy bien y estoy muy cómodo con esta forma de estructurar los archivos.
Plugin 2: asciiart
Este es un poco más entretenido, pero sigue siendo bien simple en principio. El código es un poco más largo, así que lo dejo al final.
Una de las cosas que sí o sí quería que hubiera en mi blog era ASCII Art. El problema es que Jekyll funciona con un sistema de plantillas que genera código HTML estático y estos dibujos dependen mucho de los espacios en blanco, saltos de línea y otros factores. Esto hace bien dificil hacer que queden bien formateados en el sitio y casi imposible moverlos o alinearlos horizontalmente. Este plugin soluciona todo eso con un nuevo bloque de Liquid: ‘asciiart’.
El bloque asciiart recibe dos argumentos opcionales: align y padding. align puede tomar los valores left, center o right y padding toma un número entero.
Por ejemplo:
{% asciiart left %}
|\---/|
| o_o |
\_^_/
{% endasciiart %}
|\---/| | o_o | \_^_/
{% asciiart left, 20 %}
|\---/|
| o_o |
\_^_/
{% endasciiart %}
|\---/| | o_o | \_^_/
{% asciiart center %}
|\---/|
| o_o |
\_^_/
{% endasciiart %}
|\---/| | o_o | \_^_/
{% asciiart right %}
|\---/|
| o_o |
\_^_/
{% endasciiart %}
|\---/| | o_o | \_^_/
También es posible configurar valores por defecto para evitar repetición innecesaria.
{% assign asciiart_padding = 5 %}
{% assign asciiart_align = 'right' %}
{% asciiart %}
|\---/|
| o_o |
\_^_/
{% endasciiart %}
|\---/| | o_o | \_^_/
*Gato sacado de https://www.asciiart.eu/animals/cats
No hay mucho más que decir del plugin. Lo uso literalmente en todas partes y ya no debo andar preocupado de cómo se va a ver el dibujito alineado a la derecha en el navegador de un teléfono.
Este es el código:
module Jekyll
module Tags
class AsciiArtBlock < Liquid::Block
def initialize(tag_name, text, token)
super
# Argument format: (left|right|center), (\d|[a-zA-Z0-9_]+)
align, padding = text.split(',').map(&:strip)
@align = align || ''
@padding = padding
end
def escape_xhtml(text)
# Note: > does not need to be escaped in XML content, but HTML4 spec
# says "should escape" to avoid problems with older user agents
# Note: Characters with restricted/discouraged usage are left unchanged
text.gsub(/[&<>]|[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFF]/) do | match |
case match
when '&' then '&'
when '<' then '<'
when '>' then '>'
else "&#x#{match.ord};"
end
end
end
def normalize_lengths(text)
# Normalize line lengths to maintain picture's shape when right aligned
lines = text.lines.map(&:chomp).map(&:rstrip)
# The first line is usually empty because the picture starts one line
# after the {% asciiart %} block
if lines[0].empty?
lines = lines.drop(1)
end
max_length = lines.map(&:length).max # Longest line
padded_lines = lines.map { |line| line.ljust(max_length) }
padded_lines.join("\n")
end
def apply_padding(text, align, padding)
lines = text.lines.map(&:chomp)
padded_lines = lines.map do |line|
if align == 'left'
line = line.prepend(" " * padding)
elsif align == 'right'
line = line.concat(" " * padding)
end
line
end
padded_lines.join("\n")
end
def get_padding(ctx)
padding_int = Integer(@padding, exception: false)
# Test if argument passed is an integer or a variable in the ctx's
# namespace. Set the padding as 10 otherwise
padding_int || ctx[@padding] || ctx["asciiart_padding"] || 0
end
def get_align(ctx)
if ['left', 'center', 'right'].include?(@align)
return @align
end
ctx[@align] || ctx["asciiart_align"] || 'center'
end
def render(context)
real_padding = get_padding(context)
real_align = get_align(context)
content = escape_xhtml(normalize_lengths(super(context)))
content = apply_padding(content, align=real_align, padding=real_padding)
"<pre class=\"ascii-art-#{real_align}\">#{content}</pre>"
end
end
end
end
Liquid::Template.register_tag('asciiart', Jekyll::Tags::AsciiArtBlock)