✨ feat: add multi-language support
This commit is contained in:
parent
e316dc25ab
commit
fa9229377d
@ -1,6 +1,6 @@
|
||||
# tabi
|
||||
|
||||
A fast, lightweight, and modern [Zola](https://getzola.org) theme. It aims to be a personal page and home to blog posts.
|
||||
A fast, lightweight, and modern [Zola](https://getzola.org) theme with multi-language support. It aims to be a personal page and home to blog posts.
|
||||
|
||||
See a live preview [here](https://welpo.github.io/tabi).
|
||||
|
||||
@ -14,6 +14,7 @@ tabi has a perfect score on Google's Lighthouse audit:
|
||||
|
||||
## Features
|
||||
|
||||
- [X] Multi-language support.
|
||||
- [X] Dark and light themes. Defaults to the OS setting, with a switcher in the navigation bar.
|
||||
- [X] Perfect Lighthouse score (Performance, Accessibility, Best Practices and SEO).
|
||||
- [X] [KaTeX](https://katex.org/) support.
|
||||
@ -27,8 +28,6 @@ tabi has a perfect score on Google's Lighthouse audit:
|
||||
- [X] [Custom shortcodes](./templates/shortcodes/).
|
||||
- [X] Customizable secure headers.
|
||||
|
||||
See the project's roadmap [here](https://github.com/users/welpo/projects/1).
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
|
95
config.toml
95
config.toml
@ -1,7 +1,6 @@
|
||||
# Necessary stuff.
|
||||
base_url = "https://welpo.github.io/tabi"
|
||||
title = "~/tabi"
|
||||
description = "tabi is a simple personal site and blogging theme for Zola."
|
||||
description = "tabi is a fast, lightweight, and modern Zola theme with multi-language support, optional JavaScript, and a perfect Lighthouse score."
|
||||
generate_feed = true
|
||||
compile_sass = true
|
||||
minify_html = true
|
||||
@ -15,8 +14,92 @@ external_links_target_blank = true
|
||||
highlight_code = true
|
||||
highlight_theme = "css"
|
||||
|
||||
default_language = "en"
|
||||
|
||||
[languages.es]
|
||||
title = "~/tabi"
|
||||
description = "tabi es un tema de Zola rápido, liviano y moderno con JavaScript opcional y una puntuación perfecta en Lighthouse."
|
||||
generate_feed = true
|
||||
compile_sass = true
|
||||
minify_html = true
|
||||
|
||||
taxonomies = [
|
||||
{name = "tags", feed = true},
|
||||
]
|
||||
|
||||
[languages.ca]
|
||||
title = "~/tabi"
|
||||
description = "tabi és un tema de Zola ràpid, lleuger i modern amb JavaScript opcional i una puntuació perfecta a Lighthouse."
|
||||
generate_feed = true
|
||||
compile_sass = true
|
||||
minify_html = true
|
||||
|
||||
taxonomies = [
|
||||
{name = "tags", feed = true},
|
||||
]
|
||||
|
||||
[languages.es.translations]
|
||||
language_name = "Español"
|
||||
date_locale = "es_ES"
|
||||
# Menu items.
|
||||
blog = "blog"
|
||||
archive = "archivo"
|
||||
tags = "etiquetas"
|
||||
words = "palabras"
|
||||
projects = "proyectos"
|
||||
# Other text.
|
||||
tags_title = "Todas las etiquetas"
|
||||
404_error = "La página que has solicitado parece no existir o aún no se ha traducido a tu idioma. Revisa la URL en busca de errores o"
|
||||
go_home = "regresa a la página de inicio"
|
||||
read_more = "Leer más"
|
||||
all_posts = "Todas las entradas"
|
||||
all_tags = "Todas las etiquetas"
|
||||
min_read = "min de lectura"
|
||||
powered_by = "Impulsado por"
|
||||
and = "y"
|
||||
post = "entrada"
|
||||
posts = "entradas"
|
||||
prev = "Anterior"
|
||||
next = "Siguiente"
|
||||
of = "de"
|
||||
draft = "BORRADOR"
|
||||
table_of_contents = "Tabla de contenido"
|
||||
last_updated_on = "Última actualización el"
|
||||
|
||||
[languages.ca.translations]
|
||||
language_name = "Català"
|
||||
date_locale = "ca_ES"
|
||||
# Menu items.
|
||||
blog = "blog"
|
||||
archive = "arxiu"
|
||||
tags = "etiquetes"
|
||||
words = "paraules"
|
||||
projects = "projectes"
|
||||
# Other text.
|
||||
tags_title = "Totes les etiquetes"
|
||||
404_error = "La pàgina que has sol·licitat sembla que no existeix o encara no s'ha traduït al teu idioma. Comprova l'URL per detectar errors o"
|
||||
go_home = "torna a la pàgina d'inici"
|
||||
read_more = "Llegir més"
|
||||
all_posts = "Totes les entrades"
|
||||
all_tags = "Totes les etiquetes"
|
||||
min_read = "min de lectura"
|
||||
powered_by = "Propulsat per"
|
||||
and = "i"
|
||||
post = "entrada"
|
||||
posts = "entrades"
|
||||
prev = "Anterior"
|
||||
next = "Següent"
|
||||
of = "de"
|
||||
draft = "ESBORRANY"
|
||||
table_of_contents = "Taula de contingut"
|
||||
last_updated_on = "Última actualizació el"
|
||||
|
||||
[extra]
|
||||
|
||||
language_name.ca = "Català"
|
||||
language_name.en = "English"
|
||||
language_name.es = "Español"
|
||||
|
||||
# Enable JavaScript theme toggler for dark/light mode (and automatic switching).
|
||||
# The default setting is the light theme.
|
||||
theme_switcher = true
|
||||
@ -39,10 +122,10 @@ favicon = ""
|
||||
headerImage = ""
|
||||
|
||||
menu = [
|
||||
{ name = "blog", url = "$BASE_URL/blog" },
|
||||
{ name = "archive", url = "$BASE_URL/archive" },
|
||||
{ name = "tags", url = "$BASE_URL/tags" },
|
||||
{ name = "projects", url = "$BASE_URL/projects" },
|
||||
{ name = "blog", url = "blog/" },
|
||||
{ name = "archive", url = "archive/" },
|
||||
{ name = "tags", url = "tags/" },
|
||||
{ name = "projects", url = "projects/" },
|
||||
]
|
||||
|
||||
# The icons available can be found in "social_icons" in the "static" folder
|
||||
|
13
content/_index.ca.md
Normal file
13
content/_index.ca.md
Normal file
@ -0,0 +1,13 @@
|
||||
+++
|
||||
path = "/"
|
||||
title = "Publicacions recents"
|
||||
sort_by = "date"
|
||||
template = "section.html"
|
||||
|
||||
[extra]
|
||||
header = {title = "Hola! Soc tabi~", img = "$BASE_URL/img/main.webp" }
|
||||
section_path = "blog/_index.ca.md"
|
||||
max_posts = 4
|
||||
+++
|
||||
|
||||
tabi és un tema de [Zola](https://getzola.org) ràpid, lleuger i modern. Té com a objectiu ser una pàgina personal i llar d'entrades de blog. Compta amb una puntuació perfecta de Lighthouse, disseny responsive, tema fosc i clar, shortcodes personalitzats i molt més.
|
13
content/_index.es.md
Normal file
13
content/_index.es.md
Normal file
@ -0,0 +1,13 @@
|
||||
+++
|
||||
path = "/"
|
||||
title = "Publicaciones recientes"
|
||||
sort_by = "date"
|
||||
template = "section.html"
|
||||
|
||||
[extra]
|
||||
header = {title = "¡Hola! Soy tabi~", img = "$BASE_URL/img/main.webp" }
|
||||
section_path = "blog/_index.es.md"
|
||||
max_posts = 4
|
||||
+++
|
||||
|
||||
tabi es un tema de [Zola](https://getzola.org) rápido, ligero y moderno. Su objetivo es ser una página personal y hogar para publicaciones de blogs. Cuenta con una puntuación perfecta en Lighthouse, diseño responsive, tema oscuro y claro, shortcodes personalizados y mucho más.
|
4
content/archive/_index.ca.md
Normal file
4
content/archive/_index.ca.md
Normal file
@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Arxiu"
|
||||
template = "archive.html"
|
||||
+++
|
4
content/archive/_index.es.md
Normal file
4
content/archive/_index.es.md
Normal file
@ -0,0 +1,4 @@
|
||||
+++
|
||||
title = "Archivo"
|
||||
template = "archive.html"
|
||||
+++
|
@ -1,5 +1,4 @@
|
||||
+++
|
||||
title = "Archive"
|
||||
path = "archive"
|
||||
template = "archive.html"
|
||||
+++
|
||||
|
8
content/blog/_index.ca.md
Normal file
8
content/blog/_index.ca.md
Normal file
@ -0,0 +1,8 @@
|
||||
+++
|
||||
paginate_by = 5
|
||||
path = "/blog"
|
||||
title = "Blog"
|
||||
sort_by = "date"
|
||||
template = "section.html"
|
||||
insert_anchor_links = "left"
|
||||
+++
|
8
content/blog/_index.es.md
Normal file
8
content/blog/_index.es.md
Normal file
@ -0,0 +1,8 @@
|
||||
+++
|
||||
paginate_by = 5
|
||||
path = "/blog"
|
||||
title = "Blog"
|
||||
sort_by = "date"
|
||||
template = "section.html"
|
||||
insert_anchor_links = "left"
|
||||
+++
|
17
content/blog/almost-no-js.ca.md
Normal file
17
content/blog/almost-no-js.ca.md
Normal file
@ -0,0 +1,17 @@
|
||||
+++
|
||||
title = "Gairebé sense JavaScript"
|
||||
date = 2023-01-06
|
||||
updated = 2023-04-28
|
||||
description = "JavaScript només s'utilitza quan HTML i CSS no són suficients."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalitat"]
|
||||
+++
|
||||
|
||||
# JavaScript?
|
||||
|
||||
Aquest tema gairebé no utilitza JavaScript. Inclou uns ~900 bytes de fitxers `.js` amb la lògica per al canvi de tema clar/fosc, que es pot desactivar establint `theme_switcher = false` al fitxer `config.toml`.
|
||||
|
||||
La funcionalitat de KaTex, que requereix carregar un fitxer JavaScript de 274 KB, es pot activar per a publicacions específiques.
|
||||
|
||||
A part d'això, és un tema ràpid amb HTML i CSS. Tal i com hauria de ser (la major part de) la web :-)
|
17
content/blog/almost-no-js.es.md
Normal file
17
content/blog/almost-no-js.es.md
Normal file
@ -0,0 +1,17 @@
|
||||
+++
|
||||
title = "Casi sin JavaScript"
|
||||
date = 2023-01-06
|
||||
updated = 2023-04-28
|
||||
description = "JavaScript solo se utiliza cuando HTML y CSS no son suficientes."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalidad"]
|
||||
+++
|
||||
|
||||
# ¿JavaScript?
|
||||
|
||||
Este tema casi no utiliza JavaScript. Incluye ~900 bytes de código `.js` con la lógica para el interruptor de modo claro/oscuro, el cual puede ser desactivado configurando `theme_switcher = false` en el archivo `config.toml`.
|
||||
|
||||
El soporte de KaTeX, que requiere cargar un archivo JavaScript de 274 KB, puede ser activado para publicaciones específicas.
|
||||
|
||||
Aparte de esto, es un tema rápido con HTML y CSS. Como debería ser (en su mayoría) la web :-)
|
190
content/blog/custom-font-subset.ca.md
Normal file
190
content/blog/custom-font-subset.ca.md
Normal file
@ -0,0 +1,190 @@
|
||||
+++
|
||||
title = "Optimitza la càrrega amb un subconjunt de font personalitzat"
|
||||
date = 2023-04-29
|
||||
updated = 2023-05-18
|
||||
description = "Aprèn com crear un subconjunt personalitzat que només inclogui els glifs necessaris."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalitat", "tutorial"]
|
||||
+++
|
||||
|
||||
## El problema
|
||||
|
||||
Les fonts personalitzades causen parpelleig de text a Firefox. Per veure un gif i més detalls, mira [aquesta issue](https://github.com/welpo/tabi/issues/75).
|
||||
|
||||
## La solució
|
||||
|
||||
Per solucionar això, tabi carrega un subconjunt de glifs per a l'encapçalament. Donat que això augmenta lleugerament el temps de càrrega inicial, és una bona idea intentar minimitzar la mida d'aquest subconjunt.
|
||||
|
||||
Per defecte, tabi inclou fitxers de subconjunts per a caràcters en anglès i espanyol (amb alguns símbols). Aquests fitxers es carreguen quan la pàgina o el lloc web de Zola està en aquest idioma.
|
||||
|
||||
Per a una optimització addicional, pots crear un subconjunt de fonts personalitzat que només inclogui els caràcters utilitzats en el teu encapçalament.
|
||||
|
||||
## Requisits
|
||||
|
||||
Instal·la aquestes eines:
|
||||
|
||||
- [fonttools](https://github.com/fonttools/fonttools)
|
||||
|
||||
- [brotli](https://github.com/google/brotli)
|
||||
|
||||
Executa `pip install fonttools brotli` per instal·lar totes dues.
|
||||
|
||||
## L'script
|
||||
|
||||
El següent script pren un fitxer `config.toml` i un fitxer de font com a entrada, extreu els caràcters necessaris, crea un subconjunt de la font i genera un fitxer CSS que conté el subconjunt codificat en base64.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [--config|-c CONFIG_FILE] [--font|-f FONT_FILE] [--output|-o OUTPUT_PATH]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --config, -c Path to the config.toml file."
|
||||
echo " --font, -f Path to the font file."
|
||||
echo " --output, -o Output path for the generated subset.css file (default: current directory)"
|
||||
echo " --help, -h Show this help message and exit"
|
||||
}
|
||||
|
||||
# La sortida per defecte és el directori actual.
|
||||
output_path="."
|
||||
|
||||
# Opcions de la línia de comandes.
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--config|-c)
|
||||
config_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
--font|-f)
|
||||
font_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
--output|-o)
|
||||
output_path="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Comprova si s'han proporcionat les opcions -c i -f.
|
||||
if [ -z "$config_file" ]; then
|
||||
echo "Error: --config|-c option is required."
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$font_file" ]; then
|
||||
echo "Error: --font|-f option is required."
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Comprova si els fitxers de configuració i de font existeixen.
|
||||
if [ ! -f "$config_file" ]; then
|
||||
echo "Error: Config file '$config_file' not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$font_file" ]; then
|
||||
echo "Error: Font file '$font_file' not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extreu el títol i els noms del menú del fitxer de configuració.
|
||||
title=$(awk -F' = ' '/^title/{print $2}' "$config_file" | tr -d '"' | grep -v "atom feed")
|
||||
menu_names=$(awk -F' = ' '/^menu/{f=1;next} /socials/{f=0} f && /name/{print $2}' "$config_file" | cut -d',' -f1 | tr -d '"' )
|
||||
language_names=$(awk -F' = ' '/^language_name\./{print $2}' "$config_file" | tr -d '"' )
|
||||
|
||||
# Si el lloc web és multilingüe, obté les traduccions del menú.
|
||||
if [ -n "$language_names" ]; then
|
||||
for menu_name in $menu_names; do
|
||||
# Find the line with the menu name inside a [languages.*.translations] section and get the translated menus.
|
||||
menu_translation=$(awk -F' = ' "/\\[languages.*\\.translations\\]/{f=1;next} /^\\[/ {f=0} f && /$menu_name =/{print \$2}" "$config_file" | tr -d '"' )
|
||||
# Add the found menu value to the translations string
|
||||
menu_names+="$menu_translation"
|
||||
done
|
||||
fi
|
||||
|
||||
# Combina les cadenes extretes.
|
||||
combined="$title$menu_names$language_names"
|
||||
|
||||
# Obté els caràcters únics.
|
||||
unique_chars=$(echo "$combined" | grep -o . | sort -u | tr -d '\n')
|
||||
|
||||
# Crea un fitxer temporal per a subset.woff2.
|
||||
temp_subset=$(mktemp)
|
||||
|
||||
# Executa la comanda pyftsubset amb els caràcters filtrats com a argument --text.
|
||||
pyftsubset "$font_file" \
|
||||
--text="$unique_chars" \
|
||||
--layout-features="" --flavor="woff2" --output-file="$temp_subset" --with-zopfli
|
||||
|
||||
# Codifica en base64 el fitxer temporal subset.woff2 i crea el fitxer CSS.
|
||||
base64_encoded_font=$(base64 -i "$temp_subset")
|
||||
echo "@font-face{font-family:\"Inter Subset\";src:url(data:application/font-woff2;base64,$base64_encoded_font);}" > "$output_path/custom_subset.css"
|
||||
|
||||
# Elimina el fitxer temporal subset.woff2
|
||||
rm "$temp_subset"
|
||||
```
|
||||
|
||||
## Ús
|
||||
|
||||
Guarda l'script a algun lloc com `~/bin/subset_font`. Fes-lo executable amb `chmod +x ~/bin/subset_font`.
|
||||
|
||||
Ara pots executar-lo amb les opcions requerides `--config` i `--font`:
|
||||
|
||||
```
|
||||
~/bin/subset_font --config path/to/config.toml --font path/to/font.woff2
|
||||
```
|
||||
|
||||
De forma predeterminada, això generarà un fitxer `custom_subset.css` al directori actual. Utilitza `-o` o `--output` per especificar una ruta diferent:
|
||||
|
||||
```
|
||||
~/bin/subset_font -c path/to/config.toml -f path/to/font.woff2 -o path/to/output
|
||||
```
|
||||
|
||||
Col·loca aquest fitxer `custom_subset.css` dins del directori `static/` del teu projecte de Zola.
|
||||
|
||||
## Automatització amb un Pre-commit Hook
|
||||
|
||||
És possible que canviïs el títol o les opcions del menú del teu lloc web, la qual cosa faria que el subconjunt personalitzat deixés de ser útil.
|
||||
|
||||
Per automatitzar el procés de creació d'aquest fitxer, pots integrar l'script en un ganxo (hook) pre-commit de Git que s'activi en detectar canvis al fitxer `config.toml`, executi l'script i guardi el fitxer CSS resultant al directori `static/` del teu lloc web.
|
||||
|
||||
1. Crea un fitxer `.git/hooks/pre-commit` al teu projecte de Git, si encara no existeix.
|
||||
|
||||
2. Fes-lo executable amb `chmod +x .git/hooks/pre-commit`.
|
||||
|
||||
3. Afegeix el següent codi al fitxer:
|
||||
|
||||
```bash
|
||||
# Comprova si config.toml s'ha modificat.
|
||||
if git diff --cached --name-only | grep -q "config.toml"; then
|
||||
echo "config.toml modified. Running subset_font…"
|
||||
|
||||
# Executa l'script subset_font.
|
||||
~/bin/subset_font -c config.toml -f static/fonts/Inter4.woff2 -o static/
|
||||
|
||||
# Afegeix el fitxer subset.css generat al commit.
|
||||
git add static/custom_subset.css
|
||||
fi
|
||||
```
|
||||
|
||||
Asegura't de modificar l'script perquè coincideixi amb la ruta on has guardat l'script `subset_font`. Les rutes de configuració i font haurien de funcionar correctament amb la configuració predeterminada de tabi.
|
||||
|
||||
Ara, cada vegada que facis canvis al teu projecte de Git i facis commit, el ganxo pre-commit verificarà les modificacions al fitxer `config.toml` i executarà automàticament l'script `subset_font` per actualitzar el fitxer `custom_subset.css`.
|
||||
|
||||
Per cert, si t'interessa una forma d'actualitzar automàticament la data de les teves publicacions a Zola o comprimir automàticament els teus fitxers PNG, fes un cop d'ull a [aquesta publicació](https://osc.garden/ca/blog/zola-date-git-hook/).
|
||||
|
||||
Si desitges utilitzar tots els scripts alhora (compressió de fitxers PNG, actualització de la data i creació del subconjunt de fonts), combina el seu codi en un sol fitxer `.git/hooks/pre-commit`.
|
191
content/blog/custom-font-subset.es.md
Normal file
191
content/blog/custom-font-subset.es.md
Normal file
@ -0,0 +1,191 @@
|
||||
+++
|
||||
title = "Optimiza la carga con un subconjunto de fuente personalizado"
|
||||
date = 2023-04-29
|
||||
updated = 2023-05-18
|
||||
description = "Aprende cómo crear un subconjunto personalizado que solo incluya los glifos necesarios."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalidad", "tutorial"]
|
||||
+++
|
||||
|
||||
## El problema
|
||||
|
||||
Las fuentes personalizadas causan parpadeo de texto en Firefox. Para ver un gif y más detalles, mira [esta issue](https://github.com/welpo/tabi/issues/75).
|
||||
|
||||
## La solución
|
||||
|
||||
Para solucionar esto, tabi carga un subconjunto de glifos para el encabezado. Dado que esto aumenta ligeramente el tiempo de carga inicial, es una buena idea tratar de minimizar el tamaño de este subconjunto.
|
||||
|
||||
Por defecto, tabi incluye archivos de subconjuntos para caracteres en inglés y español (con algunos símbolos). Estos archivos se cargan cuando la página o el sitio de Zola está en ese idioma.
|
||||
|
||||
Para una optimización adicional, puedes crear un subconjunto de fuentes personalizado que solo incluya los caracteres utilizados en tu encabezado.
|
||||
|
||||
## Requisitos
|
||||
|
||||
Instala estas herramientas:
|
||||
|
||||
- [fonttools](https://github.com/fonttools/fonttools)
|
||||
|
||||
- [brotli](https://github.com/google/brotli)
|
||||
|
||||
Ejecuta `pip install fonttools brotli` para instalar ambas.
|
||||
|
||||
## El script
|
||||
|
||||
El script que sigue toma un archivo `config.toml` y un archivo de fuente como entrada, extrae los caracteres necesarios, crea un subconjunto de la fuente y genera un archivo CSS que contiene el subconjunto codificado en base64.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [--config|-c CONFIG_FILE] [--font|-f FONT_FILE] [--output|-o OUTPUT_PATH]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --config, -c Path to the config.toml file."
|
||||
echo " --font, -f Path to the font file."
|
||||
echo " --output, -o Output path for the generated subset.css file (default: current directory)"
|
||||
echo " --help, -h Show this help message and exit"
|
||||
}
|
||||
|
||||
# La salida predeterminada es el directorio actual.
|
||||
output_path="."
|
||||
|
||||
# Analiza las opciones de la línea de comandos.
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--config|-c)
|
||||
config_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
--font|-f)
|
||||
font_file="$2"
|
||||
shift 2
|
||||
;;
|
||||
--output|-o)
|
||||
output_path="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Comprueba si se proporcionan las opciones -c y -f.
|
||||
if [ -z "$config_file" ]; then
|
||||
echo "Error: --config|-c option is required."
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$font_file" ]; then
|
||||
echo "Error: --font|-f option is required."
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Comprueba si existen los archivos de configuración y de fuentes.
|
||||
if [ ! -f "$config_file" ]; then
|
||||
echo "Error: Config file '$config_file' not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$font_file" ]; then
|
||||
echo "Error: Font file '$font_file' not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extrae el título y los nombres de los menús del archivo de configuración.
|
||||
title=$(awk -F' = ' '/^title/{print $2}' "$config_file" | tr -d '"' | grep -v "atom feed")
|
||||
menu_names=$(awk -F' = ' '/^menu/{f=1;next} /socials/{f=0} f && /name/{print $2}' "$config_file" | cut -d',' -f1 | tr -d '"' )
|
||||
language_names=$(awk -F' = ' '/^language_name\./{print $2}' "$config_file" | tr -d '"' )
|
||||
|
||||
# Si el sitio es multilingüe, obtiene las traducciones de los menús.
|
||||
if [ -n "$language_names" ]; then
|
||||
for menu_name in $menu_names; do
|
||||
# Find the line with the menu name inside a [languages.*.translations] section and get the translated menus.
|
||||
menu_translation=$(awk -F' = ' "/\\[languages.*\\.translations\\]/{f=1;next} /^\\[/ {f=0} f && /$menu_name =/{print \$2}" "$config_file" | tr -d '"' )
|
||||
# Add the found menu value to the translations string
|
||||
menu_names+="$menu_translation"
|
||||
done
|
||||
fi
|
||||
|
||||
# Combina las cadenas extraídas..
|
||||
combined="$title$menu_names$language_names"
|
||||
|
||||
# Obtiene los caracteres únicos.
|
||||
unique_chars=$(echo "$combined" | grep -o . | sort -u | tr -d '\n')
|
||||
|
||||
# Crea un archivo temporal para subset.woff2.
|
||||
temp_subset=$(mktemp)
|
||||
|
||||
# Ejecuta el comando pyftsubset con los caracteres filtrados como argumento --text.
|
||||
pyftsubset "$font_file" \
|
||||
--text="$unique_chars" \
|
||||
--layout-features="" --flavor="woff2" --output-file="$temp_subset" --with-zopfli
|
||||
|
||||
# Codifica en Base64 el archivo temporal subset.woff2 y crea el archivo CSS.
|
||||
base64_encoded_font=$(base64 -i "$temp_subset")
|
||||
echo "@font-face{font-family:\"Inter Subset\";src:url(data:application/font-woff2;base64,$base64_encoded_font);}" > "$output_path/custom_subset.css"
|
||||
|
||||
# Elimina el archivo temporal subset.woff2.
|
||||
rm "$temp_subset"
|
||||
```
|
||||
|
||||
## Uso
|
||||
|
||||
Guarda el script en algún lugar como `~/bin/subset_font`. Hazlo ejecutable con `chmod +x ~/bin/subset_font`.
|
||||
|
||||
Ahora puedes ejecutarlo con las opciones requeridas `--config` y `--font`:
|
||||
|
||||
```
|
||||
~/bin/subset_font --config path/to/config.toml --font path/to/font.woff2
|
||||
```
|
||||
|
||||
De forma predeterminada, esto generará un archivo `custom_subset.css` en el directorio actual. Usa `-o` o `--output` para especificar una ruta diferente:
|
||||
|
||||
```
|
||||
~/bin/subset_font -c path/to/config.toml -f path/to/font.woff2 -o path/to/output
|
||||
```
|
||||
|
||||
Coloca este archivo `custom_subset.css` dentro del directorio `static/`.
|
||||
|
||||
|
||||
## Automatización con un Pre-commit Hook
|
||||
|
||||
Es posible que cambies el título o las opciones del menú de tu sitio, lo que haría que el subconjunto personalizado deje de ser útil.
|
||||
|
||||
Para automatizar el proceso de creación de este archivo, puedes integrar el script en un gancho (hook) pre-commit de Git que se active al detectar cambios en el archivo `config.toml`, ejecute el script y guarde el archivo CSS resultante en el directorio `static/` de tu sitio.
|
||||
|
||||
1. Crea un archivo `.git/hooks/pre-commit` en tu proyecto de Git, si aún no existe.
|
||||
|
||||
2. Hazlo ejecutable con `chmod +x .git/hooks/pre-commit`.
|
||||
|
||||
3. Agrega el siguiente código al archivo:
|
||||
|
||||
```bash
|
||||
# Comprueba si config.toml se ha modificado.
|
||||
if git diff --cached --name-only | grep -q "config.toml"; then
|
||||
echo "config.toml modified. Running subset_font…"
|
||||
|
||||
# Ejecuta el script subset_font.
|
||||
~/bin/subset_font -c config.toml -f static/fonts/Inter4.woff2 -o static/
|
||||
|
||||
# Añadie el subset.css recién generado al commit.
|
||||
git add static/custom_subset.css
|
||||
fi
|
||||
```
|
||||
|
||||
Asegúrate de modificar el script para que coincida con la ruta donde has guardado el script `subset_font`. Las rutas de configuración y fuente deberían funcionar correctamente con la configuración predeterminada de tabi.
|
||||
|
||||
Ahora, cada vez que hagas cambios en tu proyecto de Git y los confirmes, el gancho pre-commit verificará las modificaciones en el archivo `config.toml` y ejecutará automáticamente el script `subset_font` para actualizar el archivo `custom_subset.css`.
|
||||
|
||||
Por cierto, si te interesa una forma de actualizar automáticamente la fecha de tus publicaciones en Zola o comprimir automáticamente tus archivos PNG, echa un vistazo a [esta publicación](https://osc.garden/es/blog/zola-date-git-hook/).
|
||||
|
||||
Si deseas utilizar todos los scripts a la vez (compresión de archivos PNG, actualización de la fecha y creación del subconjunto de fuentes), combina su código en un solo archivo `.git/hooks/pre-commit`.
|
@ -1,7 +1,7 @@
|
||||
+++
|
||||
title = "Optimise loading times with a custom font subset"
|
||||
date = 2023-04-29
|
||||
updated = 2023-05-18
|
||||
updated = 2023-05-22
|
||||
description = "Learn how to create a custom subset that only includes the necessary glyphs."
|
||||
|
||||
[taxonomies]
|
||||
@ -38,12 +38,12 @@ The script below takes a `config.toml` file and a font file as input, extracts t
|
||||
#!/usr/bin/env bash
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [--config | -c CONFIG_FILE] [--font | -f FONT_FILE] [--output | -o OUTPUT_PATH]"
|
||||
echo "Usage: $0 [--config|-c CONFIG_FILE] [--font|-f FONT_FILE] [--output|-o OUTPUT_PATH]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " --config, -c Path to the config.toml file."
|
||||
echo " --font, -f Path to the font file."
|
||||
echo " --output, -o Output path for the generated custom_subset.css file (default: current directory)"
|
||||
echo " --output, -o Output path for the generated subset.css file (default: current directory)"
|
||||
echo " --help, -h Show this help message and exit"
|
||||
}
|
||||
|
||||
@ -102,11 +102,22 @@ if [ ! -f "$font_file" ]; then
|
||||
fi
|
||||
|
||||
# Extract the title and menu names from the config file.
|
||||
title=$(awk -F' = ' '/title/{print $2}' "$config_file" | tr -d '"' | grep -v "atom feed")
|
||||
menu_names=$(awk '/menu/{f=1;next} /^\S/{f=0} f{print}' "$config_file" | awk -F' = ' '/name/{print $2}' | tr -d '"' )
|
||||
title=$(awk -F' = ' '/^title/{print $2}' "$config_file" | tr -d '"' | grep -v "atom feed")
|
||||
menu_names=$(awk -F' = ' '/^menu/{f=1;next} /socials/{f=0} f && /name/{print $2}' "$config_file" | cut -d',' -f1 | tr -d '"' )
|
||||
language_names=$(awk -F' = ' '/^language_name\./{print $2}' "$config_file" | tr -d '"' )
|
||||
|
||||
# If the site is multilingual, get the menu translations.
|
||||
if [ -n "$language_names" ]; then
|
||||
for menu_name in $menu_names; do
|
||||
# Find the line with the menu name inside a [languages.*.translations] section and get the translated menus.
|
||||
menu_translation=$(awk -F' = ' "/\\[languages.*\\.translations\\]/{f=1;next} /^\\[/ {f=0} f && /$menu_name =/{print \$2}" "$config_file" | tr -d '"' )
|
||||
# Add the found menu value to the translations string
|
||||
menu_names+="$menu_translation"
|
||||
done
|
||||
fi
|
||||
|
||||
# Combine the extracted strings.
|
||||
combined="$title$menu_names"
|
||||
combined="$title$menu_names$language_names"
|
||||
|
||||
# Get unique characters.
|
||||
unique_chars=$(echo "$combined" | grep -o . | sort -u | tr -d '\n')
|
||||
@ -114,19 +125,16 @@ unique_chars=$(echo "$combined" | grep -o . | sort -u | tr -d '\n')
|
||||
# Create a temporary file for subset.woff2.
|
||||
temp_subset=$(mktemp)
|
||||
|
||||
# Create the subset.
|
||||
# Run the pyftsubset command with the filtered characters as --text argument.
|
||||
pyftsubset "$font_file" \
|
||||
--text="$unique_chars" \
|
||||
--layout-features="" --flavor="woff2" --output-file="$temp_subset" --with-zopfli
|
||||
|
||||
# Remove trailing slash from output path, if present.
|
||||
output_path=${output_path%/}
|
||||
|
||||
# Base64 encode the temporary subset.woff2 file and create the CSS file.
|
||||
base64_encoded_font=$(base64 -i "$temp_subset")
|
||||
echo "@font-face{font-family:\"Inter Subset\";src:url(data:application/font-woff2;base64,$base64_encoded_font);}" > "$output_path/custom_subset.css"
|
||||
|
||||
# Remove the temporary subset.woff2 file.
|
||||
# Remove the temporary subset.woff2 file
|
||||
rm "$temp_subset"
|
||||
```
|
||||
|
||||
|
60
content/blog/markdown.ca.md
Normal file
60
content/blog/markdown.ca.md
Normal file
@ -0,0 +1,60 @@
|
||||
+++
|
||||
title = "Exemples de Markdown"
|
||||
date = 2023-01-31
|
||||
updated = 2023-04-28
|
||||
description = "Aquesta publicació mostra alguns exemples de format en Markdown, incloent-hi una taula, blocs de codi i etiquetes, citacions, taules i notes a peu de pàgina."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["markdown", "funcionalitat"]
|
||||
|
||||
[extra]
|
||||
katex = true
|
||||
+++
|
||||
|
||||
## $\KaTeX$
|
||||
|
||||
[$\KaTeX$](https://katex.org/) és una llibreria ràpida i fàcil d'usar que permet representar notació matemàtica mitjançant la sintaxi LaTeX.
|
||||
|
||||
Pots utilitzar $\KaTeX$ **en línia** embolcallant l'expressió entre `$` o entre `\\(` i `\\)`.
|
||||
|
||||
Per exemple, `$ \sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n + 1)!} x^{2n + 1} $` es renderitzarà com: $ \sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n + 1)!} x^{2n + 1} $
|
||||
|
||||
Per mostrar l'expressió **en una línia pròpia i centrada**, embolcalla-la amb `$$` o entre `\\[` i `\\]`.
|
||||
|
||||
Per exemple, `\\[ r = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n}(x_i - \bar{x})^2}\sqrt{\sum_{i=1}^{n}(y_i - \bar{y})^2}} \\]` es renderitzarà com: \\[ r = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n}(x_i - \bar{x})^2}\sqrt{\sum_{i=1}^{n}(y_i - \bar{y})^2}} \\]
|
||||
|
||||
Per activar $\KaTeX$ en una publicació, inclou `katex = true` dins de la secció `[extra]` dels metadades de la publicació. Per obtenir un millor rendiment i seguretat, els fitxers JavaScript, CSS i les tipografies s'allotgen localment.
|
||||
|
||||
**Nota**: Després d'activar $\KaTeX$, si vols utilitzar el caràcter \$ sense renderitzar-lo com a expressió matemàtica, escapa'l amb una barra inversa: `\$`.
|
||||
|
||||
## Taula
|
||||
|
||||
Aquí tens un exemple de taula[^1]. Els seus colors canvien en funció del tema actual.
|
||||
|
||||
| Símbol | Element | Nombre atòmic |
|
||||
|---------|---------|---------------|
|
||||
| H | Hidrogen| 1 |
|
||||
| C | Carboni | 6 |
|
||||
| Fe | Ferro | 26 |
|
||||
| Au | Or | 79 |
|
||||
|
||||
## Bloc de codi
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hola, món!") -> ();
|
||||
}
|
||||
```
|
||||
|
||||
## Etiquetes de codi
|
||||
|
||||
Lorem ipsum `dolor` sit amet, `consectetur adipiscing` elit.
|
||||
`Lorem ipsum dolor sit amet, consectetur adipiscing elit.`
|
||||
|
||||
## Quote
|
||||
|
||||
> La vida, perquè sigui vida, s'ha de viure a poc a poc…
|
||||
>
|
||||
> — Mercè Rodoreda, La plaça del Diamant
|
||||
|
||||
[^1]: I aquí tens un exemple de nota a peu de pàgina!
|
60
content/blog/markdown.es.md
Normal file
60
content/blog/markdown.es.md
Normal file
@ -0,0 +1,60 @@
|
||||
+++
|
||||
title = "Ejemplos de Markdown"
|
||||
date = 2023-01-31
|
||||
updated = 2023-04-28
|
||||
description = "Esta publicación muestra algunos ejemplos de formato Markdown, incluyendo una tabla, bloques de código y etiquetas, citas, tablas y notas al pie de página."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["markdown", "funcionalidad"]
|
||||
|
||||
[extra]
|
||||
katex = true
|
||||
+++
|
||||
|
||||
## $\KaTeX$
|
||||
|
||||
[$\KaTeX$](https://katex.org/) es una biblioteca rápida y fácil de usar que permite la representación de notación matemática utilizando sintaxis LaTeX.
|
||||
|
||||
Puedes usar $\KaTeX$ **en línea** al envolver la expresión entre `$` o entre `\\(` y `\\)`.
|
||||
|
||||
Por ejemplo, `$ \sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n + 1)!} x^{2n + 1} $` se mostraría como: $ \sin(x) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n + 1)!} x^{2n + 1} $
|
||||
|
||||
Para mostrar la expresión **en su propia línea y centrada**, envuélvela entre `$$` o entre `\\[` y `\\]`.
|
||||
|
||||
Por ejemplo, `\\[ r = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n}(x_i - \bar{x})^2}\sqrt{\sum_{i=1}^{n}(y_i - \bar{y})^2}} \\]` se mostraría como: \\[ r = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum_{i=1}^{n}(x_i - \bar{x})^2}\sqrt{\sum_{i=1}^{n}(y_i - \bar{y})^2}} \\]
|
||||
|
||||
Para activar $\KaTeX$ en una publicación, incluye `katex = true` dentro de la sección `[extra]` del encabezado de la publicación. Para un mejor rendimiento y seguridad, el JavaScript, CSS y las fuentes se alojan localmente.
|
||||
|
||||
**Nota**: Después de habilitar $\KaTeX$, si deseas usar \$ sin representar una expresión matemática, escápalo con una sola barra invertida: `\$`.
|
||||
|
||||
## Tabla
|
||||
|
||||
Aquí tienes un ejemplo de una tabla[^1]. Los colores cambian dependiendo del tema actual.
|
||||
|
||||
| Símbolo | Elemento | Número atómico |
|
||||
|---------|----------|----------------|
|
||||
| H | Hidrógeno| 1 |
|
||||
| C | Carbono | 6 |
|
||||
| Fe | Hierro | 26 |
|
||||
| Au | Oro | 79 |
|
||||
|
||||
## Bloque de código
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("¡Hola, mundo!") -> ();
|
||||
}
|
||||
```
|
||||
|
||||
## Etiquetas de código
|
||||
|
||||
Lorem ipsum `dolor` sit amet, `consectetur adipiscing` elit.
|
||||
`Lorem ipsum dolor sit amet, consectetur adipiscing elit.`
|
||||
|
||||
## Cita
|
||||
|
||||
> A mí me sobra el cuerpo, Orfeo, me sobra el cuerpo porque me falta alma.
|
||||
>
|
||||
> — Miguel de Unamuno, Niebla
|
||||
|
||||
[^1]: ¡Y aquí tienes un ejemplo de una nota al pie de página!
|
30
content/blog/security.ca.md
Normal file
30
content/blog/security.ca.md
Normal file
@ -0,0 +1,30 @@
|
||||
+++
|
||||
title = "Seguretat per defecte"
|
||||
date = 2023-02-22
|
||||
updated = 2023-04-29
|
||||
description = "tabi té una Política de Seguretat de Contingut (CSP) fàcilment personalitzable amb valors segurs per defecte. Obtingues tranquil·litat i un A+ en l'Observatori de Mozilla."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["seguretat", "funcionalitat"]
|
||||
+++
|
||||
|
||||
La configuració per defecte del tema obté una puntuació A+ a l'[Observatori de Mozilla](https://observatory.mozilla.org).[^1]
|
||||
|
||||
Això s'aconsegueix configurant programàticament les capçaleres de la Política de Seguretat de Contingut (CSP) basant-se en una llista de dominis permesos definida per l'usuari en el fitxer `config.toml`. Aquí tens la configuració per defecte i recomanada (pots eliminar l'última directiva si no vols inserir vídeos de YouTube):
|
||||
|
||||
```
|
||||
[extra]
|
||||
allowed_domains = [
|
||||
{ directive = "font-src", domains = ["'self'", "data:"] },
|
||||
{ directive = "img-src", domains = ["'self'", "https://*", "data:"] },
|
||||
{ directive = "script-src", domains = ["'self'"] },
|
||||
{ directive = "style-src", domains = ["'self'"] },
|
||||
{ directive = "frame-src", domains = ["https://www.youtube-nocookie.com"] },
|
||||
]
|
||||
```
|
||||
|
||||
La llista `allowed_domains` especifica les URLs a les quals el lloc web hauria de poder connectar-se, i cada domini de la llista està associat amb una directiva CSP com `frame-src`, `connect-src` o `script-src`. El fitxer `templates/partials/header.html` genera dinàmicament la capçalera CSP basant-se en aquesta llista.
|
||||
|
||||
Aquesta funcionalitat permet personalitzar fàcilment les capçaleres de seguretat del lloc web per permetre casos d'ús específics, com ara inserir vídeos de YouTube, carregar scripts o tipografies remotes ([no recomanat](https://www.albertovarela.net/blog/2022/11/stop-using-google-fonts/)).
|
||||
|
||||
[^1]: Requereix una configuració adequada del servidor web (p. ex., redirigir el trànsit HTTP a HTTPS).
|
30
content/blog/security.es.md
Normal file
30
content/blog/security.es.md
Normal file
@ -0,0 +1,30 @@
|
||||
+++
|
||||
title = "Seguro por defecto"
|
||||
date = 2023-02-22
|
||||
updated = 2023-04-29
|
||||
description = "tabi tiene una Política de Seguridad de Contenido (CSP) fácilmente personalizable con configuraciones seguras. Obtén tranquilidad y una calificación de A+ en Mozilla Observatory."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["seguridad", "funcionalidad"]
|
||||
+++
|
||||
|
||||
La configuración predeterminada del tema obtiene una calificación de A+ en [Mozilla Observatory](https://observatory.mozilla.org).[^1]
|
||||
|
||||
Esto se logra configurando programáticamente las cabeceras de la Política de Seguridad de Contenido (CSP) en función de una lista de dominios permitidos definida por el usuario en el archivo `config.toml`. Aquí tienes la configuración predeterminada y recomendada (puedes eliminar la última directiva si no deseas insertar videos de YouTube):
|
||||
|
||||
```
|
||||
[extra]
|
||||
allowed_domains = [
|
||||
{ directive = "font-src", domains = ["'self'", "data:"] },
|
||||
{ directive = "img-src", domains = ["'self'", "https://*", "data:"] },
|
||||
{ directive = "script-src", domains = ["'self'"] },
|
||||
{ directive = "style-src", domains = ["'self'"] },
|
||||
{ directive = "frame-src", domains = ["https://www.youtube-nocookie.com"] },
|
||||
]
|
||||
```
|
||||
|
||||
La lista `allowed_domains` especifica las URL a las que el sitio web debería poder conectarse, y cada dominio de la lista se asocia con una directiva CSP como `frame-src`, `connect-src` o `script-src`. El archivo `templates/partials/header.html` genera dinámicamente la cabecera CSP en función de esta lista.
|
||||
|
||||
Esta función permite personalizar fácilmente las cabeceras de seguridad del sitio web para permitir casos de uso específicos, como la incrustación de videos de YouTube, la carga de scripts o fuentes remotas ([no recomendado](https://www.albertovarela.net/blog/2022/11/stop-using-google-fonts/)).
|
||||
|
||||
[^1]: Requiere una configuración adecuada del servidor web (por ejemplo, redirigir el tráfico HTTP a HTTPS).
|
78
content/blog/shortcodes.ca.md
Normal file
78
content/blog/shortcodes.ca.md
Normal file
@ -0,0 +1,78 @@
|
||||
+++
|
||||
title = "Shortcodes personalitzats"
|
||||
date = 2023-02-19
|
||||
updated = 2023-04-16
|
||||
description = "Aquest tema inclou alguns shortcodes personalitzats útils que pots utilitzar per millorar les teves publicacions. Ja sigui per mostrar imatges que s'adapten als temes clar i fosc, o per donar format a una secció de referències amb un aspecte professional, aquests shortcodes personalitzats t'ajudaran."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalitat", "shortcodes"]
|
||||
+++
|
||||
|
||||
## Shortcodes d'imatge
|
||||
|
||||
### Imatges per a temes duals
|
||||
|
||||
Útil si vols utilitzar una imatge diferent pels temes clar i fosc:
|
||||
|
||||
{{ dual_theme_image(light_src="img/paris_day.webp", dark_src="img/paris_night.webp" alt="La Torre Eiffel") }}
|
||||
|
||||
#### Ús
|
||||
```
|
||||
{{/* dual_theme_image(light_src="img/paris_day.webp", dark_src="img/paris_night.webp" alt="La Torre Eiffel") */}}
|
||||
```
|
||||
|
||||
### Imatge invertible
|
||||
|
||||
Útil per a gràfics, dibuixos de línies, diagrames… Inverteix els colors de la imatge. La imatge original s'utilitzarà per al tema clar.
|
||||
|
||||
{{ invertible_image(src="img/graph.webp", alt="Gràfic invertible") }}
|
||||
|
||||
#### Ús
|
||||
|
||||
```
|
||||
{{/* invertible_image(src="img/graph.webp", alt="Gràfic invertible") */}}
|
||||
```
|
||||
|
||||
### Imatge regulable
|
||||
|
||||
Les imatges amb massa brillantor o contrast poden ser molestes en un fons fosc. Aquí tens un exemple d'una fotografia que s'atenua quan s'activa el tema fosc.
|
||||
|
||||
{{ dimmable_image(src="img/desert_by_oskerwyld.webp", alt="Fotografia d'un desert, cel celestial") }}
|
||||
|
||||
#### Usage
|
||||
|
||||
```
|
||||
{{/* dimmable_image(src="img/desert_by_oskerwyld.webp", alt="Fotografia d'un desert, cel celestial") */}}
|
||||
```
|
||||
|
||||
## Referències
|
||||
|
||||
### Sagnat invertit
|
||||
|
||||
Aquest shortcode formata una secció de referència amb un sagnat invertit de la següent manera:
|
||||
|
||||
{% references() %}
|
||||
|
||||
Alderson, E. (2015). Ciberseguretat i justícia social: Una crítica a la hegemonia corporativa en un món digital. *New York Journal of Technology, 11*(2), 24-39. [https://doi.org/10.1007/s10198-022-01497-6](https://doi.org/10.1007/s10198-022-01497-6).
|
||||
|
||||
Funkhouser, M. (2012). Les normes socials d'indecència: Un anàlisi del comportament desviat a la societat contemporània. *Los Angeles Journal of Sociology, 16*(3), 41-58. [https://doi.org/10.1093/jmp/jhx037](https://doi.org/10.1093/jmp/jhx037).
|
||||
|
||||
Schrute, D. (2005). La revolució de l'agricultura de remolatxa: Un anàlisi de la innovació agrícola. *Scranton Agricultural Quarterly, 38*(3), 67-81.
|
||||
|
||||
Steinbrenner, G. (1997). L'anàlisi cost-benefici de George Costanza: Un anàlisi del comportament de presa de riscos en el lloc de treball. *New York Journal of Business, 12*(4), 112-125.
|
||||
|
||||
Winger, J. A. (2010). L'art del debat: Un examen de la retòrica en el model de les Nacions Unides del Greendale Community College. *Colorado Journal of Communication Studies, 19*(2), 73-86. [https://doi.org/10.1093/6seaons/1movie](https://doi.org/10.1093/6seaons/1movie).
|
||||
|
||||
{% end %}
|
||||
|
||||
#### Ús
|
||||
|
||||
```
|
||||
{%/* references() */%}
|
||||
|
||||
Les teves referències van aquí.
|
||||
|
||||
Cada una en una nova línia. Es renderitzarà el Markdown (enllaços, cursiva…).
|
||||
|
||||
{%/* end */%}
|
||||
```
|
79
content/blog/shortcodes.es.md
Normal file
79
content/blog/shortcodes.es.md
Normal file
@ -0,0 +1,79 @@
|
||||
+++
|
||||
title = "Shortcodes personalizados"
|
||||
date = 2023-02-19
|
||||
updated = 2023-05-21
|
||||
description = "Este tema incluye algunos shortcodes personalizados útiles que puedes utilizar para mejorar tus publicaciones. Puedes mostrar imágenes que se adapten a los temas claro y oscuro, dar formato a una sección de referencias con un aspecto profesional, y más."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalidad", "shortcodes"]
|
||||
+++
|
||||
|
||||
## Shortcodes de imágenes
|
||||
|
||||
### Imágenes de doble tema
|
||||
|
||||
Útil si deseas usar una imagen diferente para los temas claro y oscuro:
|
||||
|
||||
{{ dual_theme_image(light_src="img/paris_day.webp", dark_src="img/paris_night.webp" alt="La Torre Eiffel") }}
|
||||
|
||||
#### Uso
|
||||
```
|
||||
{{/* dual_theme_image(light_src="img/paris_day.webp", dark_src="img/paris_night.webp" alt="La Torre Eiffel") */}}
|
||||
```
|
||||
|
||||
### Imagen invertible
|
||||
|
||||
Ideal para gráficos, dibujos lineales, diagramas... Invierte los colores de la imagen. La imagen de origen se utilizará para el tema claro.
|
||||
|
||||
{{ invertible_image(src="img/graph.webp", alt="Gráfico invertible") }}
|
||||
|
||||
#### Uso
|
||||
|
||||
```
|
||||
{{/* invertible_image(src="img/graph.webp", alt="Gráfico invertible") */}}
|
||||
```
|
||||
|
||||
|
||||
### Imagen atenuable
|
||||
|
||||
Las imágenes con demasiado brillo o contraste pueden ser impactantes en un fondo oscuro. Aquí tienes un ejemplo de una fotografía que se atenúa cuando el tema oscuro está activo.
|
||||
|
||||
{{ dimmable_image(src="img/desert_by_oskerwyld.webp", alt="Fotografía de un desierto, cielo celestial") }}
|
||||
|
||||
#### Uso
|
||||
|
||||
```
|
||||
{{/* dimmable_image(src="img/desert_by_oskerwyld.webp", alt="Fotografía de un desierto, cielo celestial") */}}
|
||||
```
|
||||
|
||||
## Referencias
|
||||
|
||||
### Sangría francesa
|
||||
|
||||
Este shortcode formatea una sección de referencias con sangría francesa de la siguiente manera:
|
||||
|
||||
{% references() %}
|
||||
|
||||
Alderson, E. (2015). Ciberseguridad y justicia social: Una crítica a la hegemonía corporativa en un mundo digital. *New York Journal of Technology, 11*(2), 24-39. [https://doi.org/10.1007/s10198-022-01497-6](https://doi.org/10.1007/s10198-022-01497-6).
|
||||
|
||||
Funkhouser, M. (2012). Las normas sociales de indecencia: Un análisis del comportamiento desviado en la sociedad contemporánea. *Los Angeles Journal of Sociology, 16*(3), 41-58. [https://doi.org/10.1093/jmp/jhx037](https://doi.org/10.1093/jmp/jhx037).
|
||||
|
||||
Schrute, D. (2005). La revolución de la agricultura de remolacha: Un análisis de la innovación agrícola. *Scranton Agricultural Quarterly, 38*(3), 67-81.
|
||||
|
||||
Steinbrenner, G. (1997). El análisis costo-beneficio de George Costanza: Un examen del comportamiento de toma de riesgos en el lugar de trabajo. *New York Journal of Business, 12*(4), 112-125.
|
||||
|
||||
Winger, J. A. (2010). El arte del debate: Un examen de la retórica en el modelo de las Naciones Unidas del Greendale Community College. *Colorado Journal of Communication Studies, 19*(2), 73-86. [https://doi.org/10.1093/6seaons/1movie](https://doi.org/10.1093/6seaons/1movie).
|
||||
|
||||
{% end %}
|
||||
|
||||
#### Uso
|
||||
|
||||
```
|
||||
{%/* references() */%}
|
||||
|
||||
Tus referencias van aquí.
|
||||
|
||||
Cada una en una línea nueva. Se renderizará Markdown (enlaces, cursivas…).
|
||||
|
||||
{%/* end */%}
|
||||
```
|
48
content/blog/toc.ca.md
Normal file
48
content/blog/toc.ca.md
Normal file
@ -0,0 +1,48 @@
|
||||
+++
|
||||
title = "Taula de contingut"
|
||||
date = 2022-11-01
|
||||
description = "Una publicació que mostra la taula de contingut opcional."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalitat", "markdown"]
|
||||
|
||||
[extra]
|
||||
toc = true
|
||||
+++
|
||||
|
||||
# Capçalera 1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
## Capçalera 2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
### Capçalera 3.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
### Capçalera 3.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
---
|
||||
|
||||
## Capçalera 2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
### Capçalera 3.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
### Capçalera 3.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Capçalera 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
48
content/blog/toc.es.md
Normal file
48
content/blog/toc.es.md
Normal file
@ -0,0 +1,48 @@
|
||||
+++
|
||||
title = "Tabla de contenido"
|
||||
date = 2022-11-01
|
||||
description = "Una publicación que muestra la tabla de contenido opcional."
|
||||
|
||||
[taxonomies]
|
||||
tags = ["funcionalidad", "markdown"]
|
||||
|
||||
[extra]
|
||||
toc = true
|
||||
+++
|
||||
|
||||
# Encabezado 1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
## Encabezado 2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
### Encabezado 3.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
### Encabezado 3.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
---
|
||||
|
||||
## Encabezado 2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
### Encabezado 3.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
|
||||
### Encabezado 3.2
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
||||
#### Encabezado 4.1
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sed mollis augue, vel efficitur lacus. Pellentesque eu egestas mi. Etiam ultrices lectus sit amet aliquet ullamcorper. Praesent in erat quis est sagittis finibus. Etiam nec sapien in nulla interdum faucibus. Integer iaculis lorem quis arcu lobortis, non malesuada neque vehicula. Aenean nec tellus eu metus bibendum tempus. Sed rutrum urna ut commodo tempor. Vestibulum aliquet elit posuere turpis maximus condimentum. Sed urna libero, ornare eu tellus vitae, laoreet condimentum risus. Aenean elit lectus, mattis quis nibh nec, faucibus rutrum sapien. Sed iaculis consectetur mi, eget posuere turpis finibus et.
|
5
content/projects/_index.ca.md
Normal file
5
content/projects/_index.ca.md
Normal file
@ -0,0 +1,5 @@
|
||||
+++
|
||||
title = "Projectes"
|
||||
sort_by = "weight"
|
||||
template = "cards.html"
|
||||
+++
|
5
content/projects/_index.es.md
Normal file
5
content/projects/_index.es.md
Normal file
@ -0,0 +1,5 @@
|
||||
+++
|
||||
title = "Proyectos"
|
||||
sort_by = "weight"
|
||||
template = "cards.html"
|
||||
+++
|
9
content/projects/chu.ca.md
Normal file
9
content/projects/chu.ca.md
Normal file
@ -0,0 +1,9 @@
|
||||
+++
|
||||
title = "chu"
|
||||
description = "Aplicació Flask per a càrregues de fitxers segures, amb eliminació de metadades, compressió, protecció amb contrasenya i més."
|
||||
weight = 2
|
||||
|
||||
[extra]
|
||||
local_image = "img/chu.webp"
|
||||
link_to = "https://github.com/welpo/chu"
|
||||
+++
|
9
content/projects/chu.es.md
Normal file
9
content/projects/chu.es.md
Normal file
@ -0,0 +1,9 @@
|
||||
+++
|
||||
title = "chu"
|
||||
description = "Aplicación Flask para subir archivos de forma segura, con eliminación de metadatos, compresión, protección con contraseña y más."
|
||||
weight = 2
|
||||
|
||||
[extra]
|
||||
local_image = "img/chu.webp"
|
||||
link_to = "https://github.com/welpo/chu"
|
||||
+++
|
11
content/projects/nani.ca.md
Normal file
11
content/projects/nani.ca.md
Normal file
@ -0,0 +1,11 @@
|
||||
+++
|
||||
title = "nani"
|
||||
description = "Script Bash per crear URL públiques a partir de fitxers o text en servidors remots."
|
||||
weight = 3
|
||||
date = 2015-10-30
|
||||
updated = 2023-02-12
|
||||
|
||||
[extra]
|
||||
local_image = "img/nani.webp"
|
||||
link_to = "https://github.com/welpo/nani"
|
||||
+++
|
11
content/projects/nani.es.md
Normal file
11
content/projects/nani.es.md
Normal file
@ -0,0 +1,11 @@
|
||||
+++
|
||||
title = "nani"
|
||||
description = "Script Bash para crear URL públicas desde archivos o texto en servidores remotos."
|
||||
weight = 3
|
||||
date = 2015-10-30
|
||||
updated = 2023-02-12
|
||||
|
||||
[extra]
|
||||
local_image = "img/nani.webp"
|
||||
link_to = "https://github.com/welpo/nani"
|
||||
+++
|
10
content/projects/spectro.ca.md
Normal file
10
content/projects/spectro.ca.md
Normal file
@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "spectro"
|
||||
description = "Script de Bash per generar espectrogrames, comparar-los, carregar-los a Imgur i proporcionar els corresponents URLs per compartir-los."
|
||||
weight = 4
|
||||
date = 2015-10-29
|
||||
|
||||
[extra]
|
||||
local_image = "img/spectro.webp"
|
||||
link_to = "https://github.com/welpo/spectro"
|
||||
+++
|
10
content/projects/spectro.es.md
Normal file
10
content/projects/spectro.es.md
Normal file
@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "spectro"
|
||||
description = "Script de Bash para generar espectrogramas, compararlos, subirlos a Imgur y proporcionar las correspondientes URLs para compartir."
|
||||
weight = 4
|
||||
date = 2015-10-29
|
||||
|
||||
[extra]
|
||||
local_image = "img/spectro.webp"
|
||||
link_to = "https://github.com/welpo/spectro"
|
||||
+++
|
9
content/projects/tabi.ca.md
Normal file
9
content/projects/tabi.ca.md
Normal file
@ -0,0 +1,9 @@
|
||||
+++
|
||||
title = "tabi"
|
||||
description = "Un tema de Zola ràpid, lleuger i modern amb JavaScript opcional."
|
||||
weight = 1
|
||||
|
||||
[extra]
|
||||
local_image = "img/tabi.webp"
|
||||
link_to = "https://github.com/welpo/tabi"
|
||||
+++
|
9
content/projects/tabi.es.md
Normal file
9
content/projects/tabi.es.md
Normal file
@ -0,0 +1,9 @@
|
||||
+++
|
||||
title = "tabi"
|
||||
description = "Un tema de Zola rápido, ligero y moderno con JavaScript opcional."
|
||||
weight = 1
|
||||
|
||||
[extra]
|
||||
local_image = "img/tabi.webp"
|
||||
link_to = "https://github.com/welpo/tabi"
|
||||
+++
|
Binary file not shown.
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 379 KiB |
@ -196,6 +196,14 @@ p {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.centered-text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.content {
|
||||
max-width: var(--normal-layout-width);
|
||||
|
@ -21,16 +21,6 @@ header {
|
||||
margin: 4rem 0px 1rem 0px;
|
||||
}
|
||||
|
||||
.centered-header {
|
||||
font-family: var(--header-font);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
max-width: var(--max-layout-width);
|
||||
display: flex;
|
||||
@ -107,6 +97,51 @@ header {
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.language-switcher-icon {
|
||||
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 96 960 960'><path d='M480 976q-84 0-157-31.5T196 859q-54-54-85-127.5T80 574q0-84 31-156.5T196 291q54-54 127-84.5T480 176q84 0 157 30.5T764 291q54 54 85 126.5T880 574q0 84-31 157.5T764 859q-54 54-127 85.5T480 976Zm0-58q35-36 58.5-82.5T577 725H384q14 60 37.5 108t58.5 85Zm-85-12q-25-38-43-82t-30-99H172q38 71 88 111.5T395 906Zm171-1q72-23 129.5-69T788 725H639q-13 54-30.5 98T566 905ZM152 665h159q-3-27-3.5-48.5T307 574q0-25 1-44.5t4-43.5H152q-7 24-9.5 43t-2.5 45q0 26 2.5 46.5T152 665Zm221 0h215q4-31 5-50.5t1-40.5q0-20-1-38.5t-5-49.5H373q-4 31-5 49.5t-1 38.5q0 21 1 40.5t5 50.5Zm275 0h160q7-24 9.5-44.5T820 574q0-26-2.5-45t-9.5-43H649q3 35 4 53.5t1 34.5q0 22-1.5 41.5T648 665Zm-10-239h150q-33-69-90.5-115T565 246q25 37 42.5 80T638 426Zm-254 0h194q-11-53-37-102.5T480 236q-32 27-54 71t-42 119Zm-212 0h151q11-54 28-96.5t43-82.5q-75 19-131 64t-91 115Z'/%3E%3C/svg%3E%0A");
|
||||
background: var(--text-color);
|
||||
align-self: center;
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
z-index: 99;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
z-index: 99;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
text-align: center;
|
||||
background: var(--background-color);
|
||||
|
||||
a {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.navbar {
|
||||
max-width: var(--normal-layout-width);
|
||||
@ -129,6 +164,7 @@ header {
|
||||
.navbar {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 149 KiB |
File diff suppressed because one or more lines are too long
@ -1,10 +1,19 @@
|
||||
{% extends "page.html" %}
|
||||
|
||||
{% block main_content %}
|
||||
|
||||
<main class="centered-header">
|
||||
<main class="centered-text">
|
||||
{{ macros_page_header::page_header(title="404")}}
|
||||
<span>not found</span>
|
||||
<div class="subheader">not found</div>
|
||||
|
||||
{# Default English message #}
|
||||
<p>The page you requested doesn't seem to exist or has not been translated to your language yet. Check the URL for errors, or <a href="{{ config.base_url }}">return to the homepage</a>.</p>
|
||||
|
||||
{# Iterate through each language and display the localised 404 message along with a "Go Home" link #}
|
||||
{%- for language_name, language in config.languages -%}
|
||||
{%- if language_name != config.default_language -%}
|
||||
<p>{{ trans(key="404_error", lang=language_name) }} <a href="{{ config.base_url }}/{{ language_name }}/">{{ trans(key="go_home", lang=language_name) }}</a>.</p>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</main>
|
||||
|
||||
{% endblock main_content %}
|
||||
|
@ -4,30 +4,42 @@
|
||||
|
||||
{{ macros_page_header::page_header(title=section.title) }}
|
||||
|
||||
{# Set locale for date #}
|
||||
{%- if lang != config.default_language %}
|
||||
{% set date_locale = trans(key="date_locale" | safe, lang=lang) %}
|
||||
{% else %}
|
||||
{% set date_locale = "en_GB" %}
|
||||
{% endif %}
|
||||
|
||||
<div class="archive">
|
||||
<ul class="list-with-title">
|
||||
{% set section_item = get_section(path="blog/_index.md") %} {% for year, posts in
|
||||
section_item.pages | group_by(attribute="year") %} {% if posts | length > 0
|
||||
%}
|
||||
<li>
|
||||
<h2 class="listing-title">{{ year }}</h2>
|
||||
<ul class="listing">
|
||||
{% for post in posts %}
|
||||
<li class="listing-item">
|
||||
<div class="post-time">
|
||||
<span class="date">
|
||||
{{ post.date | date(format="%d %b") }}
|
||||
</span>
|
||||
</div>
|
||||
<a href="{{ post.permalink }}" title="{{ post.title }}"
|
||||
>{{ post.title }}</a
|
||||
>
|
||||
<ul class="list-with-title">
|
||||
{%- if lang == config.default_language %}
|
||||
{%- set section_item = get_section(path="blog/" ~ "_index.md") %}
|
||||
{%- else %}
|
||||
{%- set section_item = get_section(path="blog/" ~ "_index." ~ lang ~ ".md") %}
|
||||
{%- endif %}
|
||||
|
||||
{% for year, posts in
|
||||
section_item.pages | group_by(attribute="year") %} {% if posts | length > 0
|
||||
%}
|
||||
<li>
|
||||
<h2 class="listing-title">{{ year }}</h2>
|
||||
<ul class="listing">
|
||||
{% for post in posts %}
|
||||
<li class="listing-item">
|
||||
<div class="post-time">
|
||||
<span class="date">
|
||||
{{ post.date | date(format="%d %b", locale=date_locale) }}
|
||||
</span>
|
||||
</div>
|
||||
<a href="{{ post.permalink }}" title="{{ post.title }}"
|
||||
>{{ post.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %} {% endfor %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %} {% endfor %}
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% endblock main_content %}
|
||||
|
@ -10,19 +10,19 @@
|
||||
|
||||
<ul class="meta">
|
||||
{% if page.draft %}
|
||||
<li class="draft-label">DRAFT</li>
|
||||
<li class="draft-label">{%- if lang != config.default_language %} {{ trans(key="draft" | safe, lang=lang) }} {% else %} DRAFT {% endif %}</li>
|
||||
{% endif %}
|
||||
|
||||
{% if page.date %}
|
||||
<li>{{ macros_format_date::format_date(date=page.date, short=true) }} {{ separator }}</li>
|
||||
{% endif %}
|
||||
|
||||
<li title="{{ page.word_count }} words"> {{ page.reading_time }} min read</li>
|
||||
<li title="{{ page.word_count }} {%- if lang != config.default_language %} {{ trans(key="words" | safe, lang=lang) }} {% else %} words {% endif %}"> {{ page.reading_time }}{%- if lang != config.default_language %} {{ trans(key="min_read" | safe, lang=lang) }} {% else %} min read {% endif %}</li>
|
||||
|
||||
{% if page.taxonomies and page.taxonomies.tags %}
|
||||
<li> {{ separator }} Tags: </li>
|
||||
<li> {{ separator }} {%- if lang != config.default_language -%}{{ trans(key="tags" | safe, lang=lang) | capitalize }}{% else %}Tags{%- endif -%}: </li>
|
||||
{% for tag in page.taxonomies.tags %}
|
||||
<li><a href={{ get_taxonomy_url(kind='tags' , name=tag) | safe }}>{{ tag }}</a>
|
||||
<li><a href={{ get_taxonomy_url(kind='tags', name=tag, lang=lang) | safe }}>{{ tag }}</a>
|
||||
{%- if not loop.last -%}
|
||||
,
|
||||
{%- endif -%}
|
||||
@ -31,7 +31,7 @@
|
||||
{% endif %}
|
||||
|
||||
{% if page.updated %}
|
||||
</ul><ul class="meta last-updated"><li>Last updated on {{ macros_format_date::format_date(date=page.updated, short=true) }}</li>
|
||||
</ul><ul class="meta last-updated"><li>{%- if lang != config.default_language %} {{ trans(key="last_updated_on" | safe, lang=lang) }} {% else %} Last updated on {% endif %} {{ macros_format_date::format_date(date=page.updated, short=true) }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
{% if page.extra.toc | default(value=false) %}
|
||||
{% if page.toc %}
|
||||
<div class="toc-container">
|
||||
<h3>Table of Contents</h3>
|
||||
<h3>{%- if lang != config.default_language %} {{ trans(key="table_of_contents" | safe, lang=lang) }} {% else %} Table of Contents {% endif %}</h3>
|
||||
<ul>
|
||||
{% for h1 in page.toc %}
|
||||
<li>
|
||||
|
@ -1,10 +1,15 @@
|
||||
{% macro format_date(date, short) %}
|
||||
|
||||
{% if config.extra.short_date_format and short %}
|
||||
{{ date | date(format=config.extra.short_date_format) }}
|
||||
{% elif config.extra.long_date_format and not short %}
|
||||
{{ date | date(format=config.extra.long_date_format) }}
|
||||
{# Set locale #}
|
||||
{%- if lang != config.default_language %}
|
||||
{% set date_locale = trans(key="date_locale" | safe, lang=lang) %}
|
||||
{% else %}
|
||||
{% set date_locale = "en_GB" %}
|
||||
{% endif %}
|
||||
|
||||
{% if config.extra.long_date_format and not short %}
|
||||
{{ date | date(format=config.extra.long_date_format, locale=date_locale) }}
|
||||
{% elif not config.extra.short_date_format and date_locale == "en_GB" %}
|
||||
{% set day = date | date(format='%-d') | int %}
|
||||
|
||||
{% if day in [11, 12, 13] %}
|
||||
@ -29,6 +34,8 @@
|
||||
{% else %}
|
||||
{{ date | date(format="%B %Y") }}
|
||||
{% endif %}
|
||||
{% elif short %}
|
||||
{{ date | date(format="%d %b %Y", locale=date_locale) }}
|
||||
{% endif %}
|
||||
|
||||
{% endmacro %}
|
||||
|
@ -25,7 +25,7 @@
|
||||
{% if post.taxonomies.tags %}
|
||||
<div class="bloglist-tags">
|
||||
{% for tag in post.taxonomies.tags %}
|
||||
<a class="tag" href="{{ get_taxonomy_url(kind="tags", name=tag) }}">{{ tag }}</a>
|
||||
<a class="tag" href="{{ get_taxonomy_url(kind='tags', name=tag, lang=lang) | safe }}">{{ tag }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -38,14 +38,14 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<a class="readmore" href={{ post.permalink }}>Read more →</a>
|
||||
<a class="readmore" href={{ post.permalink }}>{%- if lang != config.default_language %} {{ trans(key="read_more" | safe, lang=lang) }} {% else %} Read more {% endif %}→</a>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if not loop.last %}
|
||||
{% if loop.index == max %}
|
||||
<div class="all-posts">
|
||||
<a href="{{ get_url(path="/blog/") }}">All posts ⟶</a>
|
||||
<a href="{{ get_url(path="blog", lang=lang) }}/">{%- if lang != config.default_language %} {{ trans(key="all_posts" | safe, lang=lang) }} {% else %} All posts {% endif %}⟶</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -4,25 +4,25 @@
|
||||
<ul class="pagination">
|
||||
{% if paginator.previous %}
|
||||
<li class="page-item page-prev">
|
||||
<a href="{{ paginator.previous }}" class="page-link" aria-label="Previous page">← Prev</a>
|
||||
<a href="{{ paginator.previous }}" class="page-link" aria-label="{%- if lang != config.default_language %} {{ trans(key="prev" | safe, lang=lang) }}{% else %} Prev {%- endif -%}">← {%- if lang != config.default_language %} {{ trans(key="prev" | safe, lang=lang) }}{% else %} Prev {%- endif -%}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item page-prev">
|
||||
<span class="page-link disabled" aria-disabled="true" aria-label="Previous (disabled)">← Prev</span>
|
||||
<span class="page-link disabled" aria-disabled="true" aria-label="{%- if lang != config.default_language %} {{ trans(key="prev" | safe, lang=lang) }}{% else %} Prev {%- endif -%} (disabled)">← {%- if lang != config.default_language %} {{ trans(key="prev" | safe, lang=lang) }}{% else %} Prev {%- endif -%}</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item page-numbers">
|
||||
{{ paginator.current_index }} of {{ paginator.number_pagers }}
|
||||
{{ paginator.current_index }} {%- if lang != config.default_language %} {{ trans(key="of" | safe, lang=lang) }}{% else %} of {%- endif %} {{ paginator.number_pagers }}
|
||||
</li>
|
||||
|
||||
{% if paginator.next %}
|
||||
<li class="page-item page-next">
|
||||
<a href="{{ paginator.next }}" class="page-link" aria-label="Next page">Next →</a>
|
||||
<a href="{{ paginator.next }}" class="page-link" aria-label="{%- if lang != config.default_language %} {{ trans(key="next" | safe, lang=lang) }}{% else %} Next {%- endif -%}">{%- if lang != config.default_language %} {{ trans(key="next" | safe, lang=lang) }}{% else %} Next {%- endif %} →</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item page-next">
|
||||
<span class="page-link disabled" aria-disabled="true" aria-label="Next page (disabled)">Next →</span>
|
||||
<span class="page-link disabled" aria-disabled="true" aria-label="{%- if lang != config.default_language %} {{ trans(key="next" | safe, lang=lang) }}{% else %} Next {%- endif -%} (disabled)">{%- if lang != config.default_language %} {{ trans(key="next" | safe, lang=lang) }}{% else %} Next {%- endif %} →</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
@ -5,7 +5,14 @@
|
||||
{%- set custom_separator = config.extra.separator | default(value="•") -%}
|
||||
{%- set separator = " " ~ custom_separator ~ " " -%}
|
||||
|
||||
{%- if current_path and current_path == "/" -%}
|
||||
{# Get the base path for the current language. #}
|
||||
{%- if lang != config.default_language %}
|
||||
{%- set base_path = "/" ~ lang ~ "/" %}
|
||||
{%- else -%}
|
||||
{%- set base_path = "/" %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if current_path and current_path == base_path -%}
|
||||
{%- set suffix = "" -%}
|
||||
{%- set separator = "" -%}
|
||||
{% elif title %}
|
||||
@ -19,9 +26,13 @@
|
||||
{%- set suffix = term.name -%}
|
||||
{% elif taxonomy.name %}
|
||||
{# List of tags. #}
|
||||
{%- set suffix = taxonomy.name | capitalize -%}
|
||||
{%- if lang != config.default_language -%}
|
||||
{%- set suffix = trans(key=taxonomy.name | safe, lang=lang) | capitalize -%}
|
||||
{% else %}
|
||||
{%- set suffix = taxonomy.name | capitalize -%}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{%- set suffix = "Lost?" %}
|
||||
{%- set suffix = "404" %}
|
||||
{%- endif -%}
|
||||
|
||||
{# Return the final concatenated string. #}
|
||||
|
@ -14,7 +14,7 @@
|
||||
{% endif %}
|
||||
</nav>
|
||||
<div class="credits">
|
||||
<small>Powered by <a href="https://www.getzola.org" target="_blank">Zola</a> & <a href="https://github.com/welpo/tabi" target="_blank">tabi</a></small>
|
||||
<small>{%- if lang != config.default_language %} {{ trans(key="powered_by" | safe, lang=lang) }} {% else %} Powered by {% endif %} <a href="https://www.getzola.org" target="_blank">Zola</a> {%- if lang != config.default_language %} {{ trans(key="and" | safe, lang=lang) }} {% else %} & {% endif %} <a href="https://github.com/welpo/tabi" target="_blank">tabi</a></small>
|
||||
</div>
|
||||
</section>
|
||||
</footer>
|
||||
|
@ -1,17 +1,67 @@
|
||||
<header>
|
||||
<nav class="navbar">
|
||||
<div class="nav-title">
|
||||
<a class="home-title" href={{ config.base_url }}>{{ config.title }}</a>
|
||||
<a class="home-title" href={{ get_url(path="/", lang=lang) }}>{{ config.title }}</a>
|
||||
</div>
|
||||
|
||||
{%- if config.extra.menu %}
|
||||
<div class="nav-navs">
|
||||
<ul>
|
||||
{% for menu in config.extra.menu %}
|
||||
<li>
|
||||
<a class="nav-links no-hover-padding" href={{ menu.url | safe | replace(from="$BASE_URL" , to=config.base_url) }}>{{ menu.name }}</a>
|
||||
{%- if config.extra.menu %}
|
||||
{% for menu in config.extra.menu %}
|
||||
<li>
|
||||
<a class="nav-links no-hover-padding" href={{ get_url(path=menu.url, lang=lang) | safe | replace(from="$BASE_URL", to=config.base_url) }}/>
|
||||
{%- if lang != config.default_language -%}
|
||||
{{ trans(key=menu.name | safe, lang=lang) }}
|
||||
{%- else -%}
|
||||
{{ menu.name | safe }}
|
||||
{%- endif -%}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{%- endif -%}
|
||||
|
||||
{# Language switcher #}
|
||||
{# Display the language switcher only if more than one language is available #}
|
||||
{%- if config.languages | length > 1 %}
|
||||
<li class="language-switcher">
|
||||
<div class="dropdown" type="Button">
|
||||
<div class="language-switcher-icon"></div>
|
||||
|
||||
{# Display the current language first in the dropdown #}
|
||||
<div class="dropdown-content">
|
||||
{%- if lang != config.default_language %}
|
||||
{{ trans(key="language_name" | safe, lang=lang) }}
|
||||
{% else %}
|
||||
{{ config.extra.language_name.en }}
|
||||
{%- endif %}
|
||||
|
||||
{# Loop through all the available languages in the config #}
|
||||
{%- for lcode, language_name in config.extra.language_name -%}
|
||||
{# Skip the current language to avoid linking to the current page #}
|
||||
{%- if lang != lcode -%}
|
||||
{# Check if the language code matches the default language #}
|
||||
{%- if lcode == config.default_language -%}
|
||||
{# If it does, link to the root path (no language code in URL) #}
|
||||
<a type="Button" href="{{ current_url | replace(from=current_path | default(value="") | truncate(length=4, end=""), to="/") }}">{{ language_name }}</a>
|
||||
{%- else -%}
|
||||
{# Check if the current language is the default language #}
|
||||
{%- if lang == config.default_language -%}
|
||||
{# If it is, append the language code to the base URL #}
|
||||
<a type="Button" href="{{ config.base_url }}/{{ lcode }}{{ current_path | default(value="/") | safe }}">{{ language_name }}</a>
|
||||
{%- else -%}
|
||||
{# If it's not, replace the current language code in the URL with the new one #}
|
||||
<a type="Button" href="{{ current_url | replace(from='/' ~ lang ~ '/', to='/' ~ lcode ~ '/') }}"/>{{ language_name }}</a>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{%- endif %}
|
||||
|
||||
{# Theme switcher #}
|
||||
{%- if config.extra.theme_switcher == true -%}
|
||||
<li class="theme-switcher-wrapper">
|
||||
<div class="theme-switcher"></div>
|
||||
|
@ -2,14 +2,26 @@
|
||||
|
||||
{% block main_content %}
|
||||
|
||||
{{ macros_page_header::page_header(title="All tags")}}
|
||||
{%- if lang != config.default_language %}
|
||||
{% set title = trans(key="tags_title" | safe, lang=lang) %}
|
||||
{% else %}
|
||||
{% set title = "All tags" %}
|
||||
{% endif %}
|
||||
|
||||
{{ macros_page_header::page_header(title=title)}}
|
||||
|
||||
<div class="tag-cloud">
|
||||
<ul class="tags">
|
||||
{%- for term in terms -%}
|
||||
<li class="tags-item" id "{{ term.name }}"><a href="{{ term.permalink | safe }}">
|
||||
{{ term.name }}</a>
|
||||
– {{ term.pages | length }} post{{ term.pages | length | pluralize }}
|
||||
– {{ term.pages | length }}{%- if term.pages | length == 1 %}
|
||||
{# Only one post. Singular. #}
|
||||
{%- if lang != config.default_language %} {{ trans(key="post" | safe, lang=lang) }}{% else %} post {%- endif -%}
|
||||
{% elif term.pages | length > 1 %}
|
||||
{# More than one post per tag. Plural. #}
|
||||
{%- if lang != config.default_language %} {{ trans(key="posts" | safe, lang=lang) }}{% else %} posts {%- endif -%}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
<ul class="pagination">
|
||||
<li class="page-item">
|
||||
<a class="all-tags" href="{{ get_url(path="/tags/") }}">← All tags</a>
|
||||
<a class="all-tags" href="{{ get_url(path="tags", lang=lang) }}/">← {%- if lang != config.default_language %} {{ trans(key="all_tags" | safe, lang=lang) }}{% else %} All tags {%- endif -%}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
name = "tabi"
|
||||
description = "A fast, lightweight, and modern Zola theme with optional JavaScript, and a perfect Lighthouse score."
|
||||
description = "A fast, lightweight, and modern Zola theme with multi-language support, optional JavaScript, and a perfect Lighthouse score"
|
||||
license = "MIT"
|
||||
homepage = "https://github.com/welpo/tabi"
|
||||
|
||||
@ -19,6 +19,12 @@ homepage = "https://osc.garden"
|
||||
# be merged with user data, some kind of prefix or nesting is preferable
|
||||
# Use snake_casing to be consistent with the rest of Zola
|
||||
[extra]
|
||||
# Languages of your site.
|
||||
# You'll need to add the language translations for each non-English language.
|
||||
# See the config.toml file for an example.
|
||||
language_name.ca = "Català"
|
||||
language_name.en = "English"
|
||||
language_name.es = "Español"
|
||||
|
||||
# Enable JavaScript theme toggler for dark/light mode (and automatic switching).
|
||||
# The default setting is the light theme.
|
||||
|
Loading…
x
Reference in New Issue
Block a user