Documentación
Stapy es un generador de sitios estáticos. Funciona con Python en cualquier sistema operativo sin paquetes adicionales.
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
- Tema de Stapy predeterminada en vivo
- Editor de Stapy (solo lea)
- Sitio construido y alojado en SourceHut Pages
Instalación
Descargue el último lanzamiento de Stapy y descomprima el archivo.
tar.gz
wget https://www.stapy.net/download/stapy-1.17.10.tar.gz
tar zxvf stapy-1.17.10.tar.gz
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"
}
- template define el archivo de esqueleto HTML. Si lo falta será una plantilla en blanco con solo el bloque "content".
- enabled determina si la página debe aparecer y generarse durante la compilación. Si falta la clave, se supone que el valor es true.
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:
- layout/xml.json
- layout/txt.json
- ...
Un archivo de configuración common.json
está disponible para todas las páginas (todas las extensiones).
- layout/common.json
Finalmente, es posible agregar un archivo de diseño para los subdirectorios de la página:
- layout/blog/html.json
- layout/blog/2022/html.json
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
- Todas las variables encerradas en aparatos ortopédicos dobles {{ }} se reemplazarán con el valor declarado en el archivo JSON para el var.
- Todas las variables encerradas en el porcentaje de aparato ortopédico rizado {% %} se reemplazarán con el contenido del archivo declarado en el archivo JSON para el var.
- Todos los nombres de métodos encerrados en colon rizado {: :} se reemplazarán con la retorno del método en un Plugin.
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 (int) es True
- published = "1" (str) es False
{
"published": "1"
}
- published = 1 (int) es False
- published = "1" (str) es True
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:
- plugins/helloworld.py
- plugins/helloworld/main.py
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.
- En un alojamiento clásico, puede enviar el contenido de directorio
web/prod
por SFTP. - En una herramienta de implementación automatizada como Netlify, Cloudflare Pages o Vercel, debe crear un repositorio en GitHub y presionar los archivos (solo push el contenido
web/prod
o todos los archivos de Stapy y configurar la herramienta para implementar el entorno de producción directorio). - Con GitHub Pages, puede usar acciones de GitHub para construir e implementar el sitio web (Push los archivos de Stapy sin el directorio
web
y agregar pasos en el flujo de trabajo para crearweb/prod
y construir el sitio).
Seguimiento de errores
Para cualquier pregunta o informe de errores, agregue un boleto:
Temas
Temas para Stapy: