Static Site Generator

Documentación

InglésFrancésEspañol

Stapy es un generador de sitios estáticos. Funciona con Python en cualquier sistema operativo sin paquetes adicionales.

Descargar 1.17.10

Esta documentación cubre la versión 1.17.10

¿Una pregunta? Contáctenos!

Requisitos

Requiere Python 3.6 o más nuevo en cualquier sistema operativo.

Demostración

Instalación

Descargue el último lanzamiento de Stapy y descomprima el archivo.

tar.gz

stapy-1.17.10.tar.gz

wget https://www.stapy.net/download/stapy-1.17.10.tar.gz
tar zxvf stapy-1.17.10.tar.gz

zip

stapy-1.17.10.zip

wget https://www.stapy.net/download/stapy-1.17.10.zip
unzip stapy-1.17.10.zip

Serve

Comience a trabajar en el sitio web ejecutando el servidor HTTP.

Unix

python3 stapy.py

Luego navegue a la URL http://127.0.0.1:1985 en su navegador.

Servir desde el host y el puerto personalizados agregando un argumento:

python3 stapy.py 0.0.0.0:8080

Nota: Esto implica modificar la URL base en el archivo source/layout/common.json.

Consejo: Cree un alias para iniciar rápidamente el servidor para su sitio:

alias stapy='python3 /absolute/path/to/stapy.py'

Windows

Haga doble clic en el archivo stapy.py (se requiere Python, se instale fácilmente desde Microsoft Store si es necesario).

Si los archivos py se abren con un editor, haga clic con el botón derecho y seleccione: Abra con... Python 3.x

Luego navegue a la URL http://127.0.0.1:1985 en su navegador.

=^..^= Welcome to Stapy 1.17.9
Serving under http://127.0.0.1:1985

Construir

Cuando el sitio esté listo, construirlo para publicar.

Unix

python3 stapy.py build

Windows

Haga doble clic en el archivo build.py.

Si los archivos py se abren con un editor, haga clic con el botón derecho y seleccione: Abra con... Python 3.x

=^..^= Welcome to Stapy 1.17.9
Build in progress...
[prod] 56 pages generated in 0.1456 seconds
[devel] 56 pages generated in 0.1348 seconds

Entornos

Los archivos estáticos se generan en el directorio web. Este directorio contiene todos los directorios de entorno necesarios (devel, prod...).

Para la producción, agregue un directorio prod en el directorio web. Contendrá todas las páginas y archivos que necesita implementar (HTML, CSS, JS, Imágenes...).

Recursos

Todos los recursos necesarios como JS, CSS o imágenes se copian del directorio source/assets en todos los directorios de entorno (por ejemplo, web/prod).

Ruta

Para una página, el servidor busca un archivo JSON en el directorio source/pages. El nombre del archivo JSON es el mismo que la ruta URL. Ejemplos:

URL Path Json file
/ index.html.json
/hello.html hello.html.json
/hello/world.html hello/world.html.json
/hello/world/ hello/world/index.html.json

Rutas reservadas

Route Result (json)
/_pages List all the pages
/_pages/data List all the pages with the data
/_environments List the environments
/_page/hello.html Get the data of the given path
/_content/content/hello.html Get the content of the given file
/_cache/clear Manually clear Json query data cache

Configuración

El archivo JSON de la página contiene todos los datos necesarios para generar la página:

{
  "template": "template/default.html",
  "enabled": true,

  "content": "content/index.html",

  "meta_title": "Page meta title",
  "meta_description": "Page meta description",
  "title": "Page title"
}

Otras teclas son libres y se usan en la plantilla.

Establezca las variables de entorno con el sufijo de entorno:

{
  "url.local": "http://127.0.0.1:1985/",
  "url.prod": "https://www.example.com/"
}

El sufijo de entorno debe tener el mismo nombre que su directorio de entorno. Para la representación del servidor local, el sufijo siempre es "local".

Una variable puede tener un valor predeterminado:

{
  "my_text": "All environments display this text",
  "my_text.prod": "Except the prod with this"
}

Layout

Se utiliza un archivo llamado html.json en el directorio source/layout para la configuración de página HTML predeterminada. Se fusionará con el archivo JSON de la página. Esto es útil para una configuración global.

layout/html.json

{
  "title": "Default title",
  "template": "template/default.html"
}

pages/index.html.json

{
  "title": "Home title",
  "content": "content/index.html"
}

layout/html.json + pages/index.html.json

{
  "title": "Home title",
  "template": "template/default.html",
  "content": "content/index.html"
}

Puede agregar un archivo de diseño para cualquier extensiones de archivo que necesite:

Un archivo de configuración common.json está disponible para todas las páginas (todas las extensiones).

Finalmente, es posible agregar un archivo de diseño para los subdirectorios de la página:

JSON Weight Required
layout/common.json 1 N
layout/html.json 2 N
layout/blog/common.json 3 N
layout/blog/html.json 4 N
layout/blog/2022/html.json 5 N
pages/blog/2022/my-first-post.html.json 6 Y

Los datos de JSON con mayor peso anularán y extenderán pesos más bajos.

Consejo: Agregar _page/ Antes de la ruta para buscar datos fusionados.

http://127.0.0.1:1985/_page/index.html
http://127.0.0.1:1985/_page/hello.html

Plantilla

El archivo de plantilla es el esqueleto de la página:

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta charset="utf-8">
        <title>{{ meta_title }}</title>
        <meta name="description" content="{{ meta_description }}" />
        <link rel="stylesheet" href="{{ url }}css/style.css" />
    </head>
    <body>
        <header>
            {% block.header %}
        </header>
        <main>
            {% content %}
        </main>
        <footer>
            {% block.footer %}
        </footer>
    </body>
</html>

Expresiones

Nota: Escapar del personaje de Brace para no analizar una expresión:

\{% block.keep.exp %\}

Bloque

Llame a una plantilla de bloque declarada en los datos de la página con {% %} sintaxis.

{
  "block.post": "template/block/post.html"
}
{% block.post %}

Agregue argumentos al bloque:

{% block.post firstname:"John" lastname:"Doe" %}

Los argumentos serán accesibles en la plantilla "block.post" con un $ antes del var:

Hello {{ $firstname }} {{ $lastname }}!

Use datos JSON específicos para el contenido infantil con un separador + (se requieren espacios):

{% block.post + my-first-post.html %}

Los datos json/my-first-post.html.json serán accesibles en la plantilla "block.post" con un $ antes del var:

<a href="{{ url }}{{ $_path }}">{{ $post_title }}</a>

Para bucle los datos JSON con una consulta, use ~ como separador (se requieren espacios):

{% block.post ~ SELECT ITEMS {start}-{end} WHERE {conditions} ORDER BY {key} {dir} %}

Ejemplo:

{% block.post ~ SELECT ITEMS 1-10 WHERE "post" in tags AND published = 1 ORDER BY date desc %}

Esta consulta recupera las páginas 1 a 10, con Post Valor en tags y published establecida en 1, ordenada por date. Las tags, published y date Los vars deben estar presentes en los datos JSON de las páginas:

{
  "date": "2022-01-01",
  "published": 1,
  "tags": ["post"]
}

Los datos json serán accesibles en la plantilla "block.post" con un $ antes del var.

Agregue un separador de bloque opcional con el parámetro delimiter:

{% block.post delimiter:"<br />" ~ SELECT ITEMS 1-10 WHERE "post" in tags AND published = 1 ORDER BY date desc %}

Notas:

El tipo de valor debe ser el mismo que en los datos JSON:

{
  "published": 1
}
{
  "published": "1"
}

Se permiten expresiones multilíneas:

{% block.post
    delimiter:"<br />"
    ~ SELECT ITEMS 1-10 WHERE "post" in tags AND published = 1 ORDER BY date desc
%}

Un bloque llamado en el mismo bloque nunca arroja un error de bucle infinito. Se ignora el bloque infantil.

Variables reservadas

Lista

Variable Descripción Ejemplo
_path Cleaned page path blog/
_full_path Full page path blog/index.html
_env Environment name prod

Ejemplos

{{ url }}{{ _path }}
<!-- https://www.example.com/blog/ -->
{{ url }}{{ _full_path }}
<!-- https://www.example.com/blog/index.html -->
<script type="text/javascript" src="{{ url }}js/init.{{ _env }}.js"></script>
<!-- https://www.example.com/js/init.prod.js -->

Plugins

Un Plugin le permite agregar código personalizado al representar la página.

Method Description Method argument 1 Method argument 2 (dict) Return
file_content_opened Update any file content (html, json, md, css, js...) File content (str or bytes) {path, mode, _stapy} str or bytes
page_data_merged Update the current page json data Page data (dict) {path, _stapy} dict
before_content_parsed Update the page template content before parsing Page content (str) {data, env, path, _stapy} str
after_content_parsed Update the page template content after parsing Page content (str) {data, env, path, _stapy} str
child_content_data Update child data before content generation Child data (dict) {key, env, path, data, _stapy} dict
child_content_query_result Update data result before content generation All child data (list) {key, env, path, data, _stapy} list
custom_http_response Send custom response on a request Response result (tuple or None) {path, request, _stapy} tuple or None
http_request_initialized Execute an action when HTTP request is initialized Current page path {_stapy} None
http_request_sent Execute an action when HTTP request was sent Current page path {_stapy} None
? A free named method called with {: :} syntax Page data (dict) {env, path, _stapy, ?} str

Un Plugin es un script Python llamado gratuito en el directorio plugins, o un script llamado main.py en un subdirectorio:

La tecla _stapy en el argumento 2 contiene StapyFileSystem, StapyJsonQuery, StapyParser, StapyGenerator y StapyPlugins objetos.

Ejemplo

Para convertir Markdown en HTML, agregue un archivo mdtohtml.py en el directorio plugins con el siguiente contenido:

import markdown

def file_content_opened(content: str, args: dict) -> str:
    if args['path'].endswith('.md'):
        return markdown.markdown(content)
    return content
pip3 install markdown

Ahora puede usar la sintaxis de Markdown en el contenido de su página:

Hello World!

[Back to home]({{ url }})

Método personalizado

En cualquier archivo de plantilla, llame a un método con nombre gratuito con colon rizado {: :} sintaxis.

Buscar método en todos los Plugins:

{: my_plugin_method :}

Ejecutar el método solo en el Plugin especificado:

{: custom.my_plugin_method :}

El nombre del Plugin es el nombre del archivo del Plugin sin la extensión .py o el nombre del directorio del Plugin.

custom.my_plugin_method significa mostrar my_plugin_method resultado del script plugins/custom.py o plugins/custom/main.py.

# plugins/custom.py

def my_plugin_method(data: dict, args: dict) -> str:
    return '<strong>Hello World!</strong>'

Agregar argumentos al método:

{: custom.my_plugin_method firstname:"John" lastname:"Doe" :}
# plugins/custom.py

def my_plugin_method(data: dict, args: dict) -> str:
    return '<strong>Hello ' + args['firstname'] + ' ' + args['lastname'] + '</strong>'

Los argumentos del método son opcionales cuando no los necesita:

# plugins/custom.py

def my_plugin_method() -> str:
    return '<strong>Hello World!</strong>'

Métodos protegidos

Todos los métodos que no sean el método del Plugin personalizado deben estar prefijados por un guion bajo. Nunca pueden ser llamados en una plantilla.

# plugins/custom.py

def custom_plugin_method(data: dict, args: dict) -> str:
    return _my_method(data)

def _my_method(data: dict) -> str:
    return '<strong>Hello World!</strong>!'
{: custom_plugin_method :} <!-- OK -->
{: _my_method :} <!-- Forbidden -->

Despliegue

Todos los archivos en su entorno de producción (por ejemplo, web/prod) deben estar expuestos.

Seguimiento de errores

Para cualquier pregunta o informe de errores, agregue un boleto:

Bug Tracking

Temas

Temas para Stapy: