Pelican blog with Python Markdown
Pelican es un generador de microblogs estáticos en HTML/Python. Permite utilizar Markdown, RTF, y algunos otros formatos de texto para su contenido. La versión 4.8.0 es muy robusta e incluye scripts para subir el código a cualquier proveedor de nube y desplegar cambios, así como un servidor de desarrollo y un catálogo amplio de extensiones y temas.
Armé el blog inicialmente según [pelican-hosting-on-appengine.html](http://www.craigjperry. com/pelican-hosting-on-appengine.html), pero me demoré un poco, y ahora en lugar de Google AppEngine lo despliego mediante Netlify.
Reto: Github Emojis en Pelican
No se pueden utilizar emojis directamente en Pelican (es decir, con Python Markdown), pero existen varios plugins para lo mismo, y varios repositorios de los códigos Unicode en la web. Python también maneja Unicode directamente ¡¡lo cual es genial!!
>>> n = "\N{FIRE}"
>>> n
'🔥'
>>> u = "\U0001F637"
>>> u
'😷'
Pero en este caso quiero los emojis de Github especificamente, porque son más bonitos.
Método
Conseguí los png del API GitHub con requests, y copiaremos a https://bytefish. de/blog/markdown_emoji_extension salvo que tenemos emojis disponibles en el enlace mencionado, en mi opinión mejores que Unicode estándar y las demás ofertas en internet.
Markdown Extension
Python Markdown incluye la posiblidad de modificar el archivo .md antes y durante el análisis léxico, e inclusive después de generado el HTML. Para esto se utilizan una variedad de Processors y Handlers que mayormente vienen con el módulo.
Estos cubren la mayoría de necesidades como ser HTML tags, imágenes, símbolos comunes, etc. Primero, Pelican se configura con un archivo Python sencillo que pasa las opciones deseadas. He desarrollado la
clase GheEmoji que permite bajar los datos de Github: { shortname: image_url}
from github_emojis import GheEmoji
MARKDOWN = {
'extensions' : [GheEmoji.load_from_github()], # ...
}
Markdown requiere una expresión regular o regex para encontrar cada shortname por ejemplo
\:robot\: =>
![]()
Permitiremos +1 y tags con _
EMOJI_RE = r'(:)((?:[\+\-])?[_0-9a-zA-Z]*?):'
Inline Processor
Siguiendo el manual de Markdown, creamos una clase para extender Markdown.Extension. Inicialmente, usamos ImageInlinePattern para crear nuestro HTML tag img a partir del shortname del emoji Github. Posteriormente con la versión 3.4.1 actual, se recomienda utilizar InlineProcessor
Previous extension with InlinePattern
from markdown.extensions import Extension
class GheEmoji(Extension):
pattern = EmojiInlinePattern(EMOJI_RE, self.getConfig('emoji'))
md.inlinePatterns.add('emoji', pattern, '>not_strong')
class EmojiInlinePattern(Pattern):
def __init__(self, pattern, emoji):
super(EmojiInlinePattern, self).__init__(pattern)
self.emoji = emoji
def handleMatch(self, m):
tag = m.group(3)
url = self.emoji.get(tag, '')
d. Markdown nos brinda un objeto Match dónde el grupo 1 es reservado, el 2 es nuestro primer ``` : ``` y el tag el 3.
Latest Python Markdown with InlineProcessor
Aqui utilizamos la misma regex, con una lógica algo diferente. InlineProcessor permite más control sobre el resultado y gestionar espacios o carácteres especiales. Además, aproveché el XML Etree para añadir el CSS class correspondiente que convierte a los emoji en inline_block del tamaño del texto.
class EmojiInlineProcessor(InlineProcessor):
def __init__(self, pattern, emoji):
super(EmojiInlineProcessor, self).__init__(pattern)
self.emoji = emoji
def handleMatch(self, m, data):
tag = m.group(2)
url = self.emoji.get(tag, '')
if not url:
return None, None, None
div = etree.Element("div")
div.attrib["class"] = "ghe_emoji"
el = etree.SubElement(div, "img")
el.attrib["class"] = "ghe_emoji"
el.set("src", url)
el.set("title", tag)
el.set("alt", tag)
return div, m.start(0), m.end(0)
Python Setup
setup(
name='python_markdown_gh_emoji',
version='0.9',
packages=find_packages(),
py_modules=['python_markdown_gh_emoji'],
install_requires=['markdown>=3.0'],
python_requires='>3.7',
url='https://github.com/edamsoft-sre/github_emojis',
license="OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
author='EDAM',
author_email='eric.arellano@hey.com',
description='Markdown extension to provide Github emoji (in Pelican)',
classifiers=[
"Programming Language :: Python :: 3.8",
"License :: GNU General Public License v3 or later (GPLv3+)",
"Operating System :: OS Independent"]
)
Test/usage
txt = """
line 1
:fight:
line 2
line 3
"""
result = markdown.markdown(txt, extensions=[GheEmoji.load_from_github()])
assert result == """<p>line 1
line 2 <img alt="smiley" src="https://github.githubassets.com/images/icons/emoji/unicode/1f603.png?v8" title="smiley" />
line 3 <img alt="metal" src="https://github.githubassets.com/images/icons/emoji/unicode/1f918.png?v8" title="metal" /></p>"""
# plus_one = """
# :+1: the plus sign
# """
#
# thumbs_up = markdown.markdown(plus_one, extensions=[GheEmoji.load_from_github()])
# print(thumbs_up)
Desplegar el blog con módulo emoji en Netlify.
Netlify nos permite ejecutar cualquier comando Linux, que generalmente será alguna herramienta para builds y en este
caso es pelican content. La idea es replicar el entorno de desarrollo y correr python3 setup.py install && pelican content.
Para desarrollar este “feature” y no romper el sitio en vivo, creo un despliego mediante git branch, es decir configuramos Netlify para hacer un branch deploy.

Y zás, está este blog emojiado
![]()
En CICD con Netlify hablare más sobre estrategias de despliegue.