Cuando tus palabras devienen en escaparate
En el anterior artículo explicamos cómo presentar nuestras palabras en la web. Y la WWW primigenia tuvo su fuste en exponer trocitos de conocimiento así como enlazar a otros, rompiendo así la linealidad del texto, y dio paso a las webs personales que encontrábamos en espacios como Lycos o Geocities donde expresábamos nuestras aficiones y aflicciones. Muchas de esas páginas se generaban a mano o en editores WYSIWYG, como Composer, Frontpage o Macromedia Dreamweaver.
También se iban generando autómatas en lenguajes como CGI, ASP o PHP, incluso por la consola de comandos de UNIX. Eran soluciones personalizadas y un tanto rústicas al lado de soluciones actuales como Hugo, pero superaban el problema de copipegar los mismos elementos de diseño. Hoy sería impensable montar una web que se precie sin un generador de contenido como Deno o un framework, que se encargue tanto del diseño web como de lo que hay detrás, como lo pueda ser Django. Para estas líneas estoy escribiendo en Markdown, que es un flujo más natural y así me ahorro poner cientos de etiquetas HTML a mano.
Pero ahí queda, hoy es un fichero nuevo en formato Markdown, mañana otro. Tenemos un cúmulo, presumiblemente en nuestra carpeta personal, así que empezaremos por la generalización con Markdown, un formato de texto plano con el fin de crear contenido de manera legible priorizando lo que se va a decir y posponiendo la estética luego, al final, sin caer en la maraña de HTML.
También veremos la importancia de una organización mínima en nuestros proyectos, especialmente si vamos a escalar. El propósito en este escrito será el ver cómo nuestros pensamientos desarrollados en Markdown pueden acabar siendo una página web, siendo nuestro escaparate al mundo.
Puede ser una reflexión suelta que hayas desarrollado y la guardes en tu carpeta personal. Puede ser otra. Y no falta mucho para que se haya creado un sindiós de ficheros de texto sueltos. ¿Cuál es cuál? -te preguntarás-. Lo sensato será crear un fichero aparte y una mínima estructura de carpetas. Podemos pensar en que dentro de nuestra carpeta tendremos nuestros escritos en Markdown. Creamos una carpeta llamada posts
para la versión en HTML de nuestros escritos.
En cualquier *NIX podríamos hacerlo de esta guisa, mkdir -p proyecto/{posts/{images,css},drafts,ideas}
y ya tendríamos un esqueleto montado, como lo podemos ver abajo:
El asunto de las nomenclaturas también importa. Personalmente no soy partidario de usar espacios en archivos, luego hay que escapar cuando tengo que procesar algunos comandos con ellos y es una brasa. Digamos que es más fácil hacer un less crecimiento_web.md
para ver rápidamente sus contenidos que hacer un less 'crecimiento web.md'
o peor aún, less crecimiento\ web.md
. Para autocompletar con TAB también es más ágil. Nombres sencillos de recordar, breves y adaptados al medio en el que estamos, mi camino. Otros pueden tener el hábito de poner espacios en los archivos, como si siguiesen con la mentalidad de escribir en el archivero, y les será más natural.
Una buena organización en nuestro proyecto también nos ayudará a prever necesidades futuras de crecimiento, como conectarlo a un repositorio en Github. Y también otro recordatorio. ¿Terminal? ¿Consola de comandos? Te suenan, ¿verdad? En caso afirmativo, adelante, y mucho mejor si lo has usado. En caso contrario, deja este escrito y adquiere ciertos fundamentos. A la hora de desplegar tu página web vas a usar bastantes comandos, es incluso preferible si usas aliases para sintetizar en una palabra largas retahilas de comandos que repetiremos.
Imaginemos que queremos crear un archivo con estos parámetros de entrada y empezar a escribir alegremente.
---
title: '¿Cómo crecer tu web?'
subtitle: 'Cuando tus palabras devienen en escaparate'
author: 'Robledo'
lang: es-ES
header-includes:
<meta name="keywords" content="html,markdown,pandoc,hugo" />
<meta name="description" content="Cuando tus palabras devienen en escaparate" />
---
¿Cómo empezaríamos? printf
nos da una pista, véase printf 'Hello\nworld\n' > ~/gueb/articulo.md
, pero no es tan generalizable. Tendríamos que escribir cada vez, así que podemos ir a mayores. Abrimos VS Code. Abrimos la carpeta de nuestro proyecto a través de File → Open Folder
, y ésta es otra. Como parte del crecimiento web, se trata de empezar a pensar en proyectos, que a su vez también pueden tener subproyectos.
CTRL + Shift + P
nos permite acceder a la paleta de comandos. Elegimos la opción Snippets: Configure User Snippets
y se nos ofrecerá una lista como la siguiente:
Como observaremos, tendremos opciones. Tiraremos por un fichero de snippets para nuestra carpeta y tendremos una interfaz, podremos poner como ejemplo este trocito de código que hemos generado.
{
"Create Markdown": {
"prefix": "markpostGenerator",
"body": [
"---",
"title: $1",
"subtitle: $2",
"author: 'Robledo'",
"date: \"$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE\"",
"lang: es-ES",
"header-includes:",
" <meta name=\"keywords\" content=\"html,markdown,pandoc,hugo\" />",
" <meta name=\"description\" content=$2 />",
"---",
"",
"# Hi, Seaworld"
],
"description": "Create Markdown"
}
}
Con CTRL + Space
en una nueva pestaña podremos elegir markpostGenerator y ya tendremos una plantilla lista para nuestros ficheros Markdown. En este caso a golpe de TAB especifico el título y el subtítulo. Incluso la fecha se genera dinámicamente, lo cual nos viene de perlas. ¡Y a escribir! Lo que tendremos es un artículo como el que estoy escribiendo ahora y que lo transformaré a algún formato como HTML o PDF a través de un conversor de documentos como Pandoc, lo abro en un editor de texto como el ya mentado VS Code o Notepad++ o lo abro en alguna aplicación para notas como Obsidian, Simplenote o Logseq.
Markdown simplemente facilita mucho el desarrollar nuestros pensamientos con poco ruido y tiene múltiples posibilidades para publicar, desarrollar o automatizar. Pasemos a Pandoc y observaremos cómo nuestro documento ahora toma forma.
Los sitios estáticos a partir de cierta escala, es decir, cuando pasamos del puro frontispicio empiezan a ser una brasa y ahí es cuando es bueno ser autómatas y eficientes. En la güeb encontramos andanadas de generadores de sitios estáticos, desde Pandoc para nuestros documentos en Markdown, y que podemos extender a través de Makefiles, como hemos hecho con la sección de artículos de la página matriz. Podemos automatizar combinando comandos, como en este caso.
filename=$(ls -1t *.md | head -1 |sed -e 's/\.md$//'); pandoc -s --css template.css --mathjax --toc --toc-depth=4 ./"${filename}".md -o ./"${filename}".html && curl -F "articles/$_=@$_" "https://[user]:[password]@neocities.org/api/upload" && mv ./"${filename}".html ./posts/
¿Qué hace? En primer lugar detecto cuál es el último archivo en Markdown que he guardado, pongamos este artículo, y con sed
elimino la extensión y me quedo con el nombre de archivo. Luego, tras guardar la variable como filename
, llamo a Pandoc y menciono una hoja de estilos en CSS para que mi escrito sea presentable y legible. También incluyo MathJax para incorporar notación matemática al texto si terciase, así como una tabla de contenidos. Incluso puedo especificar su profundidad. A la izquierda, elijo el archivo Markdown a convertir, en este caso en mi directorio. Y a la derecha, el output, en otro directorio y con formato HTML. Si he ejecutado bien la conversión, con &&
en la consola de comandos pasaré a otro caso. En este caso usaré la API de Neocities para llamar al archivo que he generado y así subirlo. Es bastante conveniente. Escribo. Guardo. Ejecuto el comando, veo cómo se transforma y se publica. Como podemos ver, Pandoc es un buen puzzle con muchísimas opciones. Por ejemplo, he especificado también la opción -s
para generar un fichero HTML completo, con su cabecera, para cada artículo.
Como vimos en el apartado anterior, incorporamos parámetros amigables para el SEO en la cabecera de nuestro artículo, describiendo lo que deseemos.
---
title: 'Pandoc y Neocities'
header-includes:
<meta name="keywords" content="Foo,Bar" />
<meta name="description" content="My description" />
---
Con dichos parámetros tendremos también vista previa en numerosas redes sociales, como el caso de Telegram.
Pero incluso este enfoque es una brasa. Imagínate, copipegar el comando cada vez que queramos subir algo. ¿Y si tenemos otro autómata en mente? Instalamos la extensión Terminal Snippets
¿Cómo generalizamos? Supongamos que tenemos nuestros ficheros Markdown en una carpeta. Los transformamos en formato HTML, en una carpeta aparte que podríamos llamar posts
.
En primer lugar, pondré el código que he utilizado aproximadamente para generar el índice de esta página web.
import pandas as pd
from jinja2 import Template, Environment, FileSystemLoader
import requests
from bs4 import BeautifulSoup
import os
= 'roble.do'
project = f"{os.environ['HOME']}/{project}/posts/"
folder = "NEOCITIES_API_KEY"
api_key = [f"{folder}{file}" for file in os.listdir(folder) if file.endswith(".html")]
pages
# extract title from several html pages
= []
titles for page in pages:
with open(page) as page:
= page.read()
html = BeautifulSoup(html, 'lxml')
soup 'title').text)
titles.append(soup.find(
= [page.replace(folder, 'articles/') for page in pages] # in local is /posts/, we replace for /articles/
neocities_pages = dict(zip(titles, neocities_pages))
articulos
= {"Bitácora en Prose.sh": "https://robledo.prose.sh/", "INSIGHTS: libérate de distracciones al escribir": "insights", "(En construcción): DIËRESIS, un curso de Javascript eminentemente práctico": "curso/index", "Frontend alternativo para Anna's Archive": "annas_frontend"}
obras
= Environment(loader=FileSystemLoader("./"))
environment = environment.get_template("template.html")
template
with open('index.html', 'w', encoding="utf-8") as output:
= template.render(obras=obras, uris=articulos)
content
output.write(content)
# Upload to Neocities
with open('index.html', 'rb') as web:
"https://neocities.org/api/upload", files={'index.html': web}, headers={'Authorization':f'Bearer {api_key}'}) requests.post(
Como podemos ver, primero mencionaremos el directorio donde estará nuestro proyecto, así filtramos todos los artículos en formato HTML que hemos escrito. Para evitar un diccionario Python que implique actualizar cada dos por tres el script, he decidido poner las obras, mis obras web más allá de los artículos, en formato JSON. Sólo lo tengo que tocar y guardar.
Continuaremos en el próximo paso extendiendo aún más nuestras capacidades con un generador ya establecido de sitios estáticos.