Hola, como soy así de mí mismo, ya me he puesto con un nuevo librojuego. Este está destinado a publicarse como un sitio web. Mi primera intención era hacerlo con Flask, un módulo de Python que te permite generar sitios webs dinámicos, como si fuera PHP o Ruby on Rails.
Solo que a mitad del asunto me di cuenta que no necesitaba un sitio dinámico para nada. Un estático iba a ser suficiente y llevar menos recursos y complicaciones.
Pues bien, resulta que Flask usa Jinja2, un sistema de plantillas, para crear los documentos html. En esencia: donde pongas en la plantilla "{{ nombre-pj }}" en el documento final aparecerá el valor de la variable nombre, por ejemplo "Garzonillo el Magnífico".
Así que, saliéndome de Flask me puse a construir mi propio sistema, que fui simplificando hasta dejarlo en justo lo necesario para mis necesidades. Quizás sean también las tuyas.
El motor
Un sencillísimo programita en python tal que así:
from jinja2 import Environment, PackageLoader, select_autoescape, FileSystemLoader
from cap1 import s1
from fragmentos import fragmentos
env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template("layout.html")
for seccion in s1:
to_write = template.render(y=seccion)
with open("out/" + seccion["filename"]+".html", "w") as tf:
tf.write(to_write)
Sí, solo eso. Ahora perdonad si me pongo a detallarlo todo puntito por puntito. Siempre puede venir alguna persona que esté poco o ducha en python.
Importaciones
Primera línea: Importa lo necesario del módulo de plantillas Jinja2
Segunda: Importa un objeto con el contenido de los documentos que quiero generar. (En este caso se refiere al "primer capítulo" del librojuego, ya se verá.
Tercera: Importo otro modulillo mío que solo contiene fragmentos de texto. (También se verá luego, es una naderí).
"dice" a jinja que me cargue la plantilla "layout.hml" y la cargue en la variable 'template'.
A trabajar
for seccion in s1:
to_write = template.render(y=seccion)
with open("out/" + seccion["filename"]+".html", "w") as tf:
tf.write(to_write)
Que viene a significar. Para cada 'seccion', que es un elemento de 's1' (el objeto que importamos antes), a) genera un documento pasando a la plantilla 'template' los datos de la 'seccion' y b) luego grábala en un nuevo archivo, en la carpeta 'out' y con el nombre de archivo que está en sección.
Las secciones
Aquí uso un archivo llamado cap1.py, que está en la misma carpeta del script principal.
Te pongo abajo solo dos secciones del librojuego, porque tampoco tiene sentido ponerlo todo. Vale, las primeras variables solo están ahí por ahorrarme comillas luego (menos trabajo, más claridad y un archivo algo más pequeño).
El protagonista es 's1'. Una lista o array de objetos, que tienen como 'campos' obligatorios: filename (nombre de archivo) y texto. Los campos opcionales son titulo, imagen-arriba e imagen-abajo, que me imagino imaginaréis su utilidad.
Esos campos son los que pasarán a jinja para que me los sustituya donde yo quiero.
Fíjate que aquí importo y uso fragmentos, los veremos a continuación.
No dices nada. Hasta disimulas, mirando al suelo,
como si no pasara nada. Pasan dos minutos muy lentos
hasta que ves a diez caballeros cabalgar a toda velocidad
contra los recién llegados. A vosotros os hacen esperar,
rodeados por los soldados que van a pie. Pronto, te temes,
los caballeros volverán
con nuevos prisioneros.
""",
},
{
filename:"1ocultas",
texto:"""
Te metes entre las altas espigas, avanzas
encorvado y después te arrastras hasta alcanzar
el sitio que te parece más oscuro. Oculto aquí
esperas pasar desapercibido.
Pero lo cierto es que los caballeros te están
buscando. Vieron, más o menos, dónde te escondías
y vas a tener que tener mucha suerte para que
pasen de largo.
""" + fragmentos["instr_prueba"] +
"""
Si sumaste nueve o más, todo irá bien.
Pero si sacaste ocho o menos, seguramente Fortuna, la diosa,
te haya concedido una aventura.
""",
},
]
Fragmentos
Esto viene en un archivo llamado fragmentos.py y, de nuevo, te saco solo un pedacito del mismo. Es, literalmente, esto:
fragmentos = {
"instr_prueba":"""
""",
"fin":"
Un fin
\n
…salvo que vuelvas a imaginar
"
}
Con esto puedo añadir al texto de cualquier sección el contenido de 'fragmentos["fin"]' y así, si quiero cambiar "Un fin", por "Fin", por ejemplo, solo lo tengo que hacer en ese punto.
La plantilla
Esta plantilla está diseñada para una página web. En este caso las páginas webs del librojuego. Es sencilla, pero ni que decir tiene que un texto para gemini, gemtext, sería aún más sencillo.
Creo que se entiende bastante bien. En cualquier caso jinja tiene una documentación bastante buena, por no hablar de tutoriales por todas partes.
Nota 1: como lo estoy generando desde la seguridad relativa de mi ordenador personal, en local, no he puesto algunas medidas de seguridad que serían necesarias si el contenido lo generaría el servidor, en remoto. Si lo necesitas mira la documentación de flask y/o jinja.
Nota 2: No, no estoy usando "imagen-abajo" todavía. La quité al simplificar la página, pero es probable que la vuelva a poner, porque no todas las imágenes quedan bien en el mismo sitio.
Nota 3: No, no me gusta indentar nada salvo que no tenga más remedio.
El Rey de los Trasgrines
El Rey de los Trasgrines
{%- if y['imagen-arriba'] %}
{% endif %}
{%- if y['titulo'] %}
{{y['titulo'] }}
{% endif %}
{{ y['texto'] }}
Conclusión
Bueno, pues eso es todo, la verdad. El código completo a día de hoy, y los archivos html generados, los tenéis en el archivo ori.zip, más abajo. Creo que es muy fácil adaptarlo para, por ejemplo, generar una cápsula gemini completa, o un sitio gopher, o ---Capitán Obvio--- un sitio web.
¡Ojo! He quitado una imagen por razones de copyright. Vamos, cuando tenga la cosa más avanzada, si todo va bien, etc, hablaré con el ilustrador y ya, si llegamos a un acuerdo...