Merge branch 'main' into main

This commit is contained in:
Blaine Traudt 2024-09-24 10:44:38 -05:00 committed by GitHub
commit 5495c25073
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 1317 additions and 424 deletions

1
.github/CODEOWNERS vendored
View file

@ -1 +1,2 @@
* @welpo
i18n/ar.toml @TheAwiteb

74
.github/workflows/upgrade-deps.yml vendored Normal file
View file

@ -0,0 +1,74 @@
name: Dependency upgrade
on:
workflow_dispatch:
inputs:
dependency:
description: 'Dependency to upgrade'
required: true
type: choice
options:
- all
- mermaid
- katex
schedule:
- cron: '32 4 * * *'
jobs:
upgrade-dependency:
name: Upgrade dependency
runs-on: ubuntu-22.04
permissions:
contents: write
pull-requests: write
strategy:
matrix:
dependency: ${{ github.event_name == 'schedule' && fromJson('["mermaid", "katex"]') || fromJson(format('["{0}"]', github.event.inputs.dependency)) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
run: |
sudo apt-get update
sudo apt-get install -y jq npm curl git
npm install uglify-js -g
uglifyjs --version
- name: Configure GPG key
run: |
echo -n ${{ secrets.GPG_PRIVATE_KEY }} | base64 --decode | gpg --import
- name: Configure Git
run: |
git config --global user.signingkey 33EACFE956484C3940BFEEDCE4EC28F8DFB57474
git config --global commit.gpgsign true
git config --global user.name "welpo"
git config --global user.email "welpo@users.noreply.github.com"
- name: Create and switch to new branch
run: |
git checkout -b deps/upgrade-${{ matrix.dependency }}
- name: Run upgrade script
shell: bash
run: |
if [[ "${{ matrix.dependency }}" == "all" ]]; then
bash scripts/upgrade-deps --all
else
bash scripts/upgrade-deps --${{ matrix.dependency }}
fi
- name: Push changes and create PR
shell: bash
run: |
if git diff --quiet HEAD origin/main; then
echo "No changes to push for ${{ matrix.dependency }}"
exit 0
fi
git push -u origin deps/upgrade-${{ matrix.dependency }}
gh pr create --fill --base main --head deps/upgrade-${{ matrix.dependency }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -4,6 +4,82 @@ Welcome to the changelog for tabi. This document aims to provide a comprehensive
We use Semantic Versioning (SemVer) for our version numbers, formatted as MAJOR.MINOR.PATCH. Major version changes involve significant (breaking) changes, minor versions introduce features and improvements in a backward compatible manner, and patch versions are for bug fixes and minor tweaks.
## [2.16.0](https://github.com/welpo/tabi/compare/v2.15.0..v2.16.0) - 2024-09-22
### ✨ Features
- *(remote_text shortcode)* Support line ranges ([#399](https://github.com/welpo/tabi/issues/399)) ([008b976](https://github.com/welpo/tabi/commit/008b976e06e0b93e021e2ca641eda42521e58f98)) by [@welpo](https://github.com/welpo)
- *(remote_text shortcode)* Support relative paths ([#398](https://github.com/welpo/tabi/issues/398)) by [@welpo](https://github.com/welpo)
## [2.15.0](https://github.com/welpo/tabi/compare/v2.14.0..v2.15.0) - 2024-09-20
### ✨ Features
- *(feed)* Make "Visit website" link context-aware ([#394](https://github.com/welpo/tabi/issues/394)) by [@welpo](https://github.com/welpo)
- *(search)* Hide "clear search" icon if input is empty ([#388](https://github.com/welpo/tabi/issues/388)) by [@welpo](https://github.com/welpo)
### 🐛 Bug fixes
- *(feed)* Resolve Atom feed validation issues ([#393](https://github.com/welpo/tabi/issues/393)) by [@welpo](https://github.com/welpo)
- Allow pages within pages ([#385](https://github.com/welpo/tabi/issues/385)) by [@welpo](https://github.com/welpo)
- Improve dark mode and OS theme handling ([#380](https://github.com/welpo/tabi/issues/380)) by [@welpo](https://github.com/welpo)
### 💄 Styling
- Improve RTL styling consistency ([#381](https://github.com/welpo/tabi/issues/381)) by [@welpo](https://github.com/welpo)
### 🔧 Miscellaneous tasks
- *(README)* Add Ponderosa Games to showcase ([#395](https://github.com/welpo/tabi/issues/395)) by [@JVimes](https://github.com/JVimes)
- *(deps)* Avoid masking return values ([1b11f4b](https://github.com/welpo/tabi/commit/1b11f4b321d0ae52179d88cc3ecd1b72ef2b37ae)) by [@welpo](https://github.com/welpo)
- *(deps)* Check local deps version to early exit ([b5cbad4](https://github.com/welpo/tabi/commit/b5cbad422bc14f44a620bcbb87449f2425c16af6)) by [@welpo](https://github.com/welpo)
- Set [@TheAwiteb](https://github.com/TheAwiteb) as owner of Arabic translation ([edb0873](https://github.com/welpo/tabi/commit/edb087392f2989b4f08122c81fa3e51d17fbb6b8)) by [@welpo](https://github.com/welpo)
### 👥 New contributors
🫶 [@JVimes](https://github.com/JVimes) made their first contribution in [#395](https://github.com/welpo/tabi/pull/395)
## [2.14.0](https://github.com/welpo/tabi/compare/v2.13.0..v2.14.0) - 2024-09-08
### ✨ Features
- *(i18n)* Add Odia language ([#372](https://github.com/welpo/tabi/issues/372)) by [@soumendrak](https://github.com/soumendrak)
- *(i18n)* Add Estonian language ([#365](https://github.com/welpo/tabi/issues/365)) by [@NippleOfAnApe](https://github.com/NippleOfAnApe)
- Add Mermaid diagram support ([#370](https://github.com/welpo/tabi/issues/370)) by [@welpo](https://github.com/welpo)
### 🐛 Bug fixes
- *(RTL)* Fix blockquote style ([#368](https://github.com/welpo/tabi/issues/368)) by [@TheAwiteb](https://github.com/TheAwiteb) and [@welpo](https://github.com/welpo)
- Reduce main page header/list sizes ([#375](https://github.com/welpo/tabi/issues/375)) by [@welpo](https://github.com/welpo)
- Add missing quotes to HTML attributes ([#367](https://github.com/welpo/tabi/issues/367)) by [@DataTriny](https://github.com/DataTriny)
### 💄 Styling
- Use note admonition for TL;DR ([b9bf4b2](https://github.com/welpo/tabi/commit/b9bf4b2fd67c71647c0d2a1bd77dee8cb9e0ec49)) by [@welpo](https://github.com/welpo)
### 📝 Documentation
- *(mastering tabi)* Clarify prev/next links requirements ([6219b92](https://github.com/welpo/tabi/commit/6219b9200cfd544b999b064fabfa0ca37d4815d8)) by [@welpo](https://github.com/welpo)
### ♻️ Refactor
- *(footer)* Lazy load social icons ([9e7b845](https://github.com/welpo/tabi/commit/9e7b845e544758792831da520379e04089909b78)) by [@welpo](https://github.com/welpo)
### 🔧 Miscellaneous tasks
- *(deps)* Add KaTeX to dependency upgrade script ([001ec8f](https://github.com/welpo/tabi/commit/001ec8fc9a9524efbe4c3c04669fb64be4ed8efd)) by [@welpo](https://github.com/welpo)
- *(deps)* Add script to upgrade mermaid ([d73c4bd](https://github.com/welpo/tabi/commit/d73c4bde5a12d434a595be877f4452fa0c20ae30)) by [@welpo](https://github.com/welpo)
- *(release)* Ensure script is ran from default branch ([82f7a98](https://github.com/welpo/tabi/commit/82f7a984d54046a4f884461b3c5f52ac830661bf)) by [@welpo](https://github.com/welpo)
- Add funding information ([8d22a42](https://github.com/welpo/tabi/commit/8d22a42e3fd5d909eaf90f7132e818b9c45f7b07)) by [@welpo](https://github.com/welpo)
### 👥 New contributors
🫶 [@soumendrak](https://github.com/soumendrak) made their first contribution in [#372](https://github.com/welpo/tabi/pull/372)
🫶 [@DataTriny](https://github.com/DataTriny) made their first contribution in [#367](https://github.com/welpo/tabi/pull/367)
🫶 [@NippleOfAnApe](https://github.com/NippleOfAnApe) made their first contribution in [#365](https://github.com/welpo/tabi/pull/365)
## [2.13.0](https://github.com/welpo/tabi/compare/v2.12.0..v2.13.0) - 2024-07-24
### ✨ Features
@ -31,8 +107,8 @@ We use Semantic Versioning (SemVer) for our version numbers, formatted as MAJOR.
### 🔧 Miscellaneous tasks
- *(release)* Add error handling function ([9585843](https://github.com/welpo/tabi/commit/9585843b14131843775e41df67fe9cc60c95a2ea))
- *(release)* Ensure local repository is in good state ([617a940](https://github.com/welpo/tabi/commit/617a940cf823917bc86df5f05350236c40560dc0))
- *(release)* Add error handling function ([9585843](https://github.com/welpo/tabi/commit/9585843b14131843775e41df67fe9cc60c95a2ea)) by [@welpo](https://github.com/welpo)
- *(release)* Ensure local repository is in good state ([617a940](https://github.com/welpo/tabi/commit/617a940cf823917bc86df5f05350236c40560dc0)) by [@welpo](https://github.com/welpo)
### 👥 New contributors
@ -331,6 +407,10 @@ We use Semantic Versioning (SemVer) for our version numbers, formatted as MAJOR.
- *(README)* Add CSS code block setup in required config ([c9d6b62](https://github.com/welpo/tabi/commit/c9d6b629078f70f4392818a17a4a7ac6b11c0480)) by [@welpo](https://github.com/welpo)
### 👥 New contributors
🫶 [@andwati](https://github.com/andwati) made their first contribution in [#257](https://github.com/welpo/tabi/pull/257)
## [2.0.0](https://github.com/welpo/tabi/compare/v1.0.0..v2.0.0) - 2024-01-15
### 💥 BREAKING CHANGES 💥
@ -916,10 +996,18 @@ We use Semantic Versioning (SemVer) for our version numbers, formatted as MAJOR.
🫶 [@donovanglover](https://github.com/donovanglover) made their first contribution in [#205](https://github.com/welpo/tabi/pull/205)
🫶 [@nyadiia](https://github.com/nyadiia) made their first contribution in [#195](https://github.com/welpo/tabi/pull/195)
🫶 [@Almost-Senseless-Coder](https://github.com/Almost-Senseless-Coder) made their first contribution in [#192](https://github.com/welpo/tabi/pull/192)
🫶 [@Jieiku](https://github.com/Jieiku) made their first contribution in [#173](https://github.com/welpo/tabi/pull/173)
🫶 [@sandman](https://github.com/sandman) made their first contribution in [#170](https://github.com/welpo/tabi/pull/170)
🫶 [@SeaDve](https://github.com/SeaDve) made their first contribution in [#165](https://github.com/welpo/tabi/pull/165)
🫶 [@stevenroose](https://github.com/stevenroose) made their first contribution in [#124](https://github.com/welpo/tabi/pull/124)
🫶 [@serginogal](https://github.com/serginogal) made their first contribution
<!-- generated by git-cliff -->

View file

@ -180,6 +180,8 @@ git pull
| [mikufan.page](https://mikufan.page) | [Nadia](https://github.com/nyadiia) | Personal blog | [Source](https://github.com/nyadiia/mikufan.page) |
| [tim-boettcher.online](https://tim-boettcher.online/) | [Tim Böttcher](https://codeberg.org/Tim-Boettcher/) | Insights and ramblings of a deafblind programmer | [Source](https://codeberg.org/Tim-Boettcher/tim-boettcher-online/) |
| [www.richtman.au](https://www.richtman.au) | [Ariel Richtman](https://github.com/arichtman) | Personal tech blog | [Source](https://github.com/arichtman/www.richtman.au) |
| [Ponderosa Games](https://ponderosagames.com/) | John Burak ([JVimes](https://github.com/jvimes)) | A friendly indie game company | &mdash; |
Using tabi? Feel free to create a PR and add your site to this list.

View file

@ -1,7 +1,7 @@
+++
title = "Personalitza el color de tabi i el tema per defecte"
date = 2023-08-09
updated = 2023-11-24
updated = 2024-09-12
description = "Aprèn a personalitzar tabi fent servir skins i establint un tema per defecte, aconseguint un aspecte únic."
[taxonomies]
@ -169,12 +169,33 @@ Pots guardar la teva nova skin en qualsevol d'aquests dos directoris:
Crea un nou arxiu `.scss` (per exemple, `la_teva_skin.scss`) a la ubicació que prefereixis. Aquest arxiu ha de contenir aquestes dues variables (aquesta és la skin predeterminada, "teal"):
```scss
// This defines theme-specific variables.
@mixin theme-variables($theme) {
@if $theme =='light' {
// Light theme colours.
--primary-color: #087e96; // Contrast ratio: 4.73:1
}
@else if $theme == 'dark' {
// Dark theme colours.
--primary-color: #91e0ee; // Contrast ratio: 11.06:1
}
}
// Apply light theme variables by default.
:root {
--primary-color: #087e96;
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #91e0ee;
@include theme-variables('dark');
}
// Apply dark theme variables when user's system prefers dark mode
// and the theme is not explicitly set to light.
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}
```

View file

@ -1,7 +1,7 @@
+++
title = "Personaliza el color de tabi y el tema predeterminado"
date = 2023-08-09
updated = 2023-11-24
updated = 2024-09-12
description = "Aprende a personalizar tabi usando skins y estableciendo un tema predeterminado, haciendo que tu sitio sea único."
[taxonomies]
@ -171,12 +171,34 @@ Puedes guardar tu nueva skin en cualquiera de estos dos directorios:
Crea un nuevo archivo `.scss` (por ejemplo, `tu_skin.scss`) en la ubicación que prefieras. Este archivo debe contener estas dos variables (esta es la skin predeterminada, "teal"):
```scss
:root {
--primary-color: #087e96;
// This defines theme-specific variables.
@mixin theme-variables($theme) {
@if $theme =='light' {
// Light theme colours.
--primary-color: #087e96; // Contrast ratio: 4.73:1
}
@else if $theme == 'dark' {
// Dark theme colours.
--primary-color: #91e0ee; // Contrast ratio: 11.06:1
}
}
// Apply light theme variables by default.
:root {
@include theme-variables('light');
}
// Apply dark theme variables when dark theme is explicitly set.
[data-theme='dark'] {
--primary-color: #91e0ee;
@include theme-variables('dark');
}
// Apply dark theme variables when user's system prefers dark mode
// and the theme is not explicitly set to light.
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}
```

View file

@ -1,7 +1,7 @@
+++
title = "Customise tabi with skins and a default theme"
date = 2023-08-09
updated = 2023-11-24
updated = 2024-09-12
description = "Learn how to customise tabi using skins and setting a default theme, making your site uniquely yours."
[taxonomies]
@ -180,12 +180,34 @@ You can save your new skin it in either of these two directories:
Create a new `.scss` file (for example, `your_skin.scss`) in your preferred location. This file needs to have these two variables (this is the default skin, "teal"):
```scss
:root {
--primary-color: #087e96;
// This defines theme-specific variables.
@mixin theme-variables($theme) {
@if $theme =='light' {
// Light theme colours.
--primary-color: #087e96; // Contrast ratio: 4.73:1
}
@else if $theme == 'dark' {
// Dark theme colours.
--primary-color: #91e0ee; // Contrast ratio: 11.06:1
}
}
// Apply light theme variables by default.
:root {
@include theme-variables('light');
}
// Apply dark theme variables when dark theme is explicitly set.
[data-theme='dark'] {
--primary-color: #91e0ee;
@include theme-variables('dark');
}
// Apply dark theme variables when user's system prefers dark mode
// and the theme is not explicitly set to light.
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}
```

View file

@ -1,7 +1,7 @@
+++
title = "Domina la configuració de tabi: guia completa"
date = 2023-09-18
updated = 2024-08-28
updated = 2024-09-17
description = "Descobreix les múltiples maneres en què pots personalitzar tabi."
[taxonomies]
@ -25,11 +25,12 @@ tabi té una jerarquia que permet personalitzar el teu lloc a diferents nivells.
1. **Configuracions globals**: Aquestes són les configuracions que s'apliquen a tot el teu lloc. Es configuren a `config.toml`.
2. **Configuracions de secció**: Aquestes són les configuracions que s'apliquen a una secció del teu lloc (per exemple, `/blog` o `/projects`). Es configuren a la metainformació de l'arxiu `_index.md` de la secció.
3. **Configuracions de pàgina**: Aquestes són les configuracions que s'apliquen a una sola pàgina. Es configuren a la metainformació de la pàgina.
3. **Configuració de la pàgina «pare»**: Per a pàgines anidades (pàgines dins de pàgines), aquestes són les configuracions de la pàgina que les conté.
4. **Configuracions de pàgina**: Aquestes són les configuracions que s'apliquen a una sola pàgina. Es configuren a la metainformació de la pàgina.
En tots els casos, les opcions de tabi es configuren a la secció `[extra]`.
Per a les configuracions que segueixen aquesta jerarquia, el valor establert a una pàgina reemplaça el valor d'una secció, que al seu torn reemplaça el valor global. En resum: com més específica sigui la configuració, més prioritat tindrà, o `pàgina > secció > config.toml`.
Per a les configuracions que segueixen aquesta jerarquia, el valor establert a una pàgina reemplaça el valor d'una secció, que al seu torn reemplaça el valor global. En resum: com més específica sigui la configuració, més prioritat tindrà, o `pàgina > pàgina pare/secció > config.toml`.
---

View file

@ -1,7 +1,7 @@
+++
title = "Domina la configuración de tabi: guía completa"
date = 2023-09-18
updated = 2024-08-28
updated = 2024-09-17
description = "Descubre las múltiples maneras en que puedes personalizar tabi."
[taxonomies]
@ -25,11 +25,12 @@ tabi tiene una jerarquía que te permite personalizar tu sitio en diferentes niv
1. **Configuraciones globales**: Estas son las configuraciones que se aplican a todo tu sitio. Se establecen en `config.toml`.
2. **Configuraciones de sección**: Estas son las configuraciones que se aplican a una sección de tu sitio (por ejemplo, `/blog` o `/projects`). Se establecen en la metainformación del archivo `_index.md` de la sección.
3. **Configuraciones de página**: Estas son las configuraciones que se aplican a una sola página. Se establecen en la metainformación de la página.
3. **Configuración de la página «padre»**: Para páginas anidadas (páginas dentro de páginas), estas son las configuraciones de la página que las contiene.
4. **Configuraciones de página**: Estas son las configuraciones que se aplican a una sola página. Se establecen en la metainformación de la página.
En todos los casos, las opciones de tabi se establecen en la sección `[extra]`.
Para las configuraciones que siguen esta jerarquía, el valor establecido en una página reemplaza el valor de una sección, que a su vez reemplaza el valor global. En resumen: cuanto más específica sea la configuración, mayor prioridad tendrá, o `página > sección > config.toml`.
Para las configuraciones que siguen esta jerarquía, el valor establecido en una página reemplaza el valor de una sección, que a su vez reemplaza el valor global. En resumen: cuanto más específica sea la configuración, mayor prioridad tendrá, o `página > página padre/sección > config.toml`.
---

View file

@ -1,7 +1,7 @@
+++
title = "Mastering tabi Settings: A Comprehensive Guide"
date = 2023-09-18
updated = 2024-08-28
updated = 2024-09-17
description = "Discover the many ways you can customise your tabi site."
[taxonomies]
@ -25,11 +25,12 @@ tabi has a hierarchy that allows you to customise your site at different levels.
1. **Global settings**: These are the settings that apply to your entire site. They are set in `config.toml`.
2. **Section settings**: These are the settings that apply to a section of your site (e.g.`/blog` or `/projects`). They are set in the front matter of the `_index.md` file of the section.
3. **Page settings**: These are the settings that apply to a single page. They are set in the front matter of the page.
3. **Parent page settings**: For nested pages (pages within pages), these are the settings from the parent page.
4. **Page settings**: These are the settings that apply to a single page. They are set in the front matter of the page.
In all cases, tabi's settings are set in the `[extra]` section.
For settings which follow this hierarchy, the value set on a page overrides the value for a section, which overrides the global value. In short: the more specific the setting, the higher priority it has, or `page > section > config.toml`.
For settings which follow this hierarchy, the value set on a page overrides the value for a section, which overrides the global value. In short: the more specific the setting, the higher priority it has, or `page > parent page/section > config.toml`.
---

View file

@ -1,7 +1,7 @@
+++
title = "Shortcodes personalitzats"
date = 2023-02-19
updated = 2024-08-28
updated = 2024-09-22
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]
@ -207,10 +207,18 @@ dist/
Afegeix text des d'una URL remota o un arxiu local.
El shortcode accepta tres paràmetres:
- `src`: L'URL d'origen o ruta del fitxer (obligatori)
- `start`: Primera línia a mostrar (opcional, comença a 1)
- `end`: Número de l'última línia (opcional, per defecte és 0, l'última línia)
{{ admonition(type="info", text="`start` i `end` són inclusius. `start=3, end=3` mostrarà només la tercera línia.") }}
**Important**:
- **Arxius remots VS arxius locals**: Si `src` comença amb "http", es tractarà com un arxiu remot. D'altra banda, s'assumeix que és una ruta d'arxiu local.
- **Accés a arxius**: Atès que utilitza la funció [`load_data`](https://www.getzola.org/documentation/templates/overview/#load-data) de Zola, els arxius locals han d'estar dins del directori de Zola —vegeu la [lògica de cerca d'arxius](https://www.getzola.org/documentation/templates/overview/#file-searching-logic).
- **Accés a arxius**: Atès que utilitza la funció [`load_data`](https://www.getzola.org/documentation/templates/overview/#load-data) de Zola, els arxius locals han d'estar dins del directori de Zola —vegeu la [lògica de cerca d'arxius](https://www.getzola.org/documentation/templates/overview/#file-searching-logic). Desde [tabi 2.16.0](https://github.com/welpo/tabi/releases/tag/v2.16.0), el shortcode admet també rutes relatives.
- **Formateig de blocs de codi**: Per mostrar el text com un bloc de codi, has d'afegir manualment les tanques de codi Markdown (cometes inverses) i, opcionalment, especificar el llenguatge de programació per al ressaltat sintàctic.
#### Ús
@ -229,6 +237,12 @@ Mostra el text d'un arxiu local:
{{/* remote_text(src="ruta/a/arxiu.txt") */}}
```
Mostreu només les línies 3 a 5 d'un arxiu local:
```
{{/* remote_text(src="ruta/a/arxiu.txt", start=3, end=5) */}}
```
### Advertències
Destaca informació amb aquests shortcodes. Hi ha cinc tipus (`type`): `note`, `tip`, `info`, `warning`, i `danger`.

View file

@ -1,7 +1,7 @@
+++
title = "Shortcodes personalizados"
date = 2023-02-19
updated = 2024-08-28
updated = 2024-09-22
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]
@ -208,10 +208,18 @@ dist/
Añade texto desde una URL remota o un archivo local.
El shortcode acepta tres parámetros:
- `src`: La URL de origen o ruta del archivo (obligatorio)
- `start`: Primera línea a mostrar (opcional, empieza en 1)
- `end`: Número de la última línea (opcional, por defecto es 0, la última línea)
{{ admonition(type="info", text="`start` y `end` son inclusivos. `start=3, end=3` mostrará solo la tercera línea.") }}
**Importante**:
- **Archivos remotos VS archivos locales**: Si `src` empieza con "http", se tratará como un archivo remoto. De lo contrario, se asume que es una ruta de archivo local.
- **Acceso a archivos**: Dado que utiliza la función [`load_data`](https://www.getzola.org/documentation/templates/overview/#load-data) de Zola, los archivos locales deben estar dentro del directorio de Zola —ver la [lógica de búsqueda de archivos](https://www.getzola.org/documentation/templates/overview/#file-searching-logic).
- **Acceso a archivos**: Dado que utiliza la función [`load_data`](https://www.getzola.org/documentation/templates/overview/#load-data) de Zola, los archivos locales deben estar dentro del directorio de Zola —ver la [lógica de búsqueda de archivos](https://www.getzola.org/documentation/templates/overview/#file-searching-logic). Desde [tabi 2.16.0](https://github.com/welpo/tabi/releases/tag/v2.16.0), el shortcode admite también rutas relativas.
- **Formateo de bloques de código**: Para mostrar el texto como un bloque de código, debes añadir manualmente las cercas de código Markdown (comillas invertidas) y, opcionalmente, especificar el lenguaje de programación para el resaltado sintáctico.
#### Uso
@ -230,6 +238,12 @@ Visualización de texto de un archivo local:
{{/* remote_text(src="ruta/a/archivo.txt") */}}
```
Mostar sólo las líneas 3 a 5 de un archivo remoto:
```
{{/* remote_text(src="https://example.com/script.py", start=3, end=5) */}}
```
### Advertencias
Destaca información con estos shortcodes. Hay cinco tipos (`type`): `note`, `tip`, `info`, `warning`, y `danger`.

View file

@ -1,7 +1,7 @@
+++
title = "Custom shortcodes"
date = 2023-02-19
updated = 2024-08-28
updated = 2024-09-22
description = "This theme includes some useful custom shortcodes that you can use to enhance your posts. Whether you want to display images that adapt to light and dark themes, or format a professional-looking reference section, these custom shortcodes have got you covered."
[taxonomies]
@ -207,10 +207,18 @@ dist/
Embed text from a remote URL or a local file. To display the path or URL on the code block, see the [show source or path shortcode](#show-source-or-path).
The shortcode accepts three parameters:
- `src`: The source URL or file path (required)
- `start`: First line to display (optional, starts at 1)
- `end`: The ending line number (optional, defaults to 0, meaning the last line)
{{ admonition(type="info", text="`start` and `end` are inclusive. `start=3, end=3` will display only the third line.") }}
**Important**:
- **Remote VS local files**: If `src` starts with "http", it will be treated as a remote file. Otherwise, it assumes a local file path.
- **Files access**: As it uses Zola's [`load_data`](https://www.getzola.org/documentation/templates/overview/#load-data), local files must be inside the Zola directory—see [File searching logic](https://www.getzola.org/documentation/templates/overview/#file-searching-logic).
- **Files access**: As it uses Zola's [`load_data`](https://www.getzola.org/documentation/templates/overview/#load-data), local files must be inside the Zola directory—see [File searching logic](https://www.getzola.org/documentation/templates/overview/#file-searching-logic). As of [tabi 2.16.0](https://github.com/welpo/tabi/releases/tag/v2.16.0), the shortcode supports both relative and absolute paths.
- **Code block formatting**: To display the text as a code block, you must manually add the Markdown code fences (backticks) and, optionally, specify the programming language for syntax highlighting.
#### Usage
@ -229,6 +237,12 @@ Displaying text from a local file:
{{/* remote_text(src="path/to/file.txt") */}}
```
Display lines 3 to 7 (both inclusive) of a local file:
```
{{/* remote_text(src="path/to/file.txt", start=3, end=7) */}}
```
### Admonitions
Bring attention to information with these admonition shortcodes. They come in five `type`s: `note`, `tip`, `info`, `warning`, and `danger`.

View file

@ -138,8 +138,8 @@ html {
body {
display: flex;
flex-direction: column;
margin: 0 5vmin;
padding: 0;
margin-inline: 5vmin;
margin-block: 0;
min-height: 100vh;
}
@ -147,7 +147,7 @@ body {
word-wrap: break-word;
margin: 0 auto;
margin-top: 6vmin;
margin-bottom: 4rem;
margin-block-end: 4rem;
width: 100%;
max-width: var(--max-layout-width);
}
@ -174,18 +174,18 @@ article {
}
.full-width {
margin-right: -$base-margin;
margin-left: -$base-margin;
margin-inline-start: -$base-margin;
margin-inline-end: -$base-margin;
max-width: calc(100% + 2*$base-margin);
}
li {
p:not(:last-child) {
margin-bottom: 0;
margin-block-end: 0;
}
p + :last-child {
margin-bottom: var(--paragraph-spacing);
margin-block-end: var(--paragraph-spacing);
}
}
}
@ -210,62 +210,44 @@ h3,
h4,
h5,
h6 {
display: block;
position: relative;
margin: 0;
}
h1 {
display: block;
margin-top: 0.67em;
margin-right: 0;
margin-bottom: 0em;
margin-left: 0;
font-weight: 550;
font-size: 1.62rem;
}
h2 {
display: block;
margin-top: 0.5em;
margin-right: 0;
margin-bottom: 0em;
margin-left: 0;
font-weight: 550;
font-size: 1.4rem;
}
h3 {
display: block;
margin-top: 0.3em;
margin-right: 0;
margin-bottom: 0em;
margin-left: 0;
font-weight: 550;
font-size: 1.2rem;
}
h4 {
display: block;
margin-top: 0.83em;
margin-right: 0;
margin-bottom: 0em;
margin-left: 0;
font-weight: 550;
font-size: 1rem;
}
h5 {
display: block;
margin-top: 0.83em;
margin-right: 0;
margin-bottom: 0em;
margin-left: 0;
font-weight: normal;
font-size: 1rem;
}
p {
margin-top: 0.4rem;
margin-bottom: var(--paragraph-spacing);
margin-block-end: var(--paragraph-spacing);
font-size: 1em;
line-height: 2rem;
}
@ -294,7 +276,7 @@ video {
}
.subheader {
margin-bottom: 2rem;
margin-block-end: 2rem;
}
.mobile-only {
@ -312,8 +294,8 @@ video {
article .full-width {
display: block;
margin-right: 0;
margin-left: 0;
margin-inline-start: 0;
margin-inline-end: 0;
max-width: none;
overflow-x: auto;
}
@ -334,7 +316,8 @@ video {
}
body {
margin: 0 16px;
margin-inline: 16px;
margin-block: 0;
}
}

View file

@ -1,51 +1,26 @@
.admonition {
display: flex;
align-items: flex-start;
margin: 1em 0;
border-left: 6px solid;
border-radius: 10px;
padding: 0.8rem;
color: var(--text-color-high-contrast);
font-family: var(--sans-serif-font);
@mixin admonition-type($type) {
border-color: var(--admonition-#{$type}-border);
background-color: var(--admonition-#{$type}-bg);
p {
margin-bottom: 0;
margin-left: -1.75rem;
font-family: inherit;
code {
background-color: var(--admonition-#{$type}-code);
}
a:hover {
color: var(--hover-color) !important;
a {
border-bottom: 1px solid var(--admonition-#{$type}-border);
color: var(--admonition-#{$type}-border);
code {
color: var(--text-color-high-contrast) !important;
&:hover {
background-color: var(--admonition-#{$type}-border);
color: var(--hover-color);
}
}
}
.admonition-content {
flex: 1;
strong {
font-weight: 580;
.admonition-icon {
background-color: var(--admonition-#{$type}-border);
}
}
.admonition-icon {
display: flex;
align-items: center;
margin: 0.3rem;
background-size: contain;
background-repeat: no-repeat;
aspect-ratio: 1/1;
width: 1.5rem;
}
.admonition-title {
opacity: 0.92;
font-weight: bold;
font-size: 0.82rem;
}
:root {
/* Note */
--admonition-note-border: #5b6167;
@ -73,7 +48,7 @@
--admonition-danger-code: #fcc1c5;
}
[data-theme='dark'] {
@mixin dark-theme-variables {
/* Note */
--admonition-note-border: #d0d1d4;
--admonition-note-bg: #3d3e40;
@ -100,95 +75,62 @@
--admonition-danger-code: #8c2e00;
}
.admonition.note {
border-color: var(--admonition-note-border);
background-color: var(--admonition-note-bg);
[data-theme='dark'] {
@include dark-theme-variables;
}
code {
background-color: var(--admonition-note-code) !important;
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include dark-theme-variables;
}
}
.admonition {
display: flex;
align-items: flex-start;
margin-block: 1em;
border-radius: 10px;
border-inline-start: 6px solid;
padding: 0.8rem;
color: var(--text-color-high-contrast);
font-family: var(--sans-serif-font);
p {
margin-inline-start: -1.75rem;
margin-block-end: 0;
font-family: inherit;
}
a {
border-bottom: 1px solid var(--admonition-note-border);
color: var(--admonition-note-border);
&:hover {
background-color: var(--admonition-note-border);
code {
color: inherit;
}
}
}
.admonition.tip {
border-color: var(--admonition-tip-border);
background-color: var(--admonition-tip-bg);
code {
background-color: var(--admonition-tip-code) !important;
}
a {
border-bottom: 1px solid var(--admonition-tip-border);
color: var(--admonition-tip-border);
&:hover {
background-color: var(--admonition-tip-border);
}
.admonition-content {
flex: 1;
strong {
font-weight: 580;
}
}
.admonition.info {
border-color: var(--admonition-info-border);
background-color: var(--admonition-info-bg);
code {
background-color: var(--admonition-info-code) !important;
}
a {
border-bottom: 1px solid var(--admonition-info-border);
color: var(--admonition-info-border);
&:hover {
background-color: var(--admonition-info-border);
}
}
.admonition-icon {
display: flex;
align-items: center;
margin: 0.3rem;
background-size: contain;
background-repeat: no-repeat;
aspect-ratio: 1/1;
width: 1.5rem;
}
.admonition.warning {
border-color: var(--admonition-warning-border);
background-color: var(--admonition-warning-bg);
code {
background-color: var(--admonition-warning-code) !important;
}
a {
border-bottom: 1px solid var(--admonition-warning-border);
color: var(--admonition-warning-border);
&:hover {
background-color: var(--admonition-warning-border);
}
}
.admonition-title {
opacity: 0.92;
font-weight: bold;
font-size: 0.82rem;
}
.admonition.danger {
border-color: var(--admonition-danger-border);
background-color: var(--admonition-danger-bg);
code {
background-color: var(--admonition-danger-code) !important;
}
a {
border-bottom: 1px solid var(--admonition-danger-border);
color: var(--admonition-danger-border);
&:hover {
background-color: var(--admonition-danger-border);
}
}
}
.admonition-icon-note {
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960' %3E%3Cpath d='M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z'/%3E%3C/svg%3E");
@ -210,23 +152,8 @@
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960' %3E%3Cpath d='M239.256-400q0 58.091 27.975 108.995t76.13 81.237q-5.616-8.513-8.487-18.398-2.872-9.885-2.872-19.167 1.333-26.436 12.153-50.307 10.821-23.872 31.41-43.461L480-443.921l105.819 102.82q18.923 19.311 29.885 43.321 10.961 24.011 12.294 50.447 0 9.282-2.872 19.167-2.871 9.885-7.82 18.398 47.488-30.333 75.796-81.237Q721.41-341.909 721.41-400q0-47.622-19.258-93.169-19.259-45.547-53.998-82.549-19.951 13.41-42.202 19.859Q583.7-549.41 561-549.41q-62.448 0-105.108-38.039-42.661-38.038-51.225-98.628v-9.744q-39.385 31.949-69.898 67.68-30.513 35.73-51.987 74.166t-32.5 77.464Q239.256-437.483 239.256-400ZM480-349.539l-57.436 56.436q-12.154 11.821-17.731 26.029-5.577 14.208-5.577 29.074 0 32.769 23.498 55.757 23.497 22.987 57.246 22.987 33.432 0 57.421-22.906 23.989-22.906 23.989-55.561 0-16.162-6.116-30.162-6.116-13.999-17.454-25.154l-57.84-56.5Zm-11.002-469.022V-708q0 38.637 26.832 64.819 26.831 26.183 65.17 26.183 15.609 0 30.818-5.923 15.208-5.923 28.131-17.718l22.615-24.102q67.564 44.128 106.999 114.917 39.435 70.79 39.435 150.156 0 128.206-89.846 218.103Q609.307-91.668 480-91.668q-129.027 0-218.68-89.652-89.652-89.653-89.652-218.68 0-119.178 79.371-232.447t217.959-186.114Z'/%3E%3C/svg%3E");
}
/* Admonition type styles */
.admonition.note .admonition-icon {
background-color: var(--admonition-note-border);
}
.admonition.tip .admonition-icon {
background-color: var(--admonition-tip-border);
}
.admonition.info .admonition-icon {
background-color: var(--admonition-info-border);
}
.admonition.warning .admonition-icon {
background-color: var(--admonition-warning-border);
}
.admonition.danger .admonition-icon {
background-color: var(--admonition-danger-border);
}
.admonition.note { @include admonition-type('note'); }
.admonition.tip { @include admonition-type('tip'); }
.admonition.info { @include admonition-type('info'); }
.admonition.warning { @include admonition-type('warning'); }
.admonition.danger { @include admonition-type('danger'); }

View file

@ -1,21 +1,22 @@
.archive {
margin-top: 4vmin;
margin-block-start: 4vmin;
.listing-title {
margin-bottom: 1rem;
margin-block-end: 1rem;
font-size: 1.5rem;
}
.listing-item {
display: flex;
gap: 1rem;
margin-bottom: 0.5rem;
padding: 0.2rem 1rem;
margin-block-end: 0.5rem;
padding-inline: 1rem;
padding-block: 0.2rem;
.post-time {
padding-left: 1vmin;
min-width: 5rem;
text-align: left;
padding-inline-start: 1vmin;
min-inline-size: 5rem;
text-align: start;
.date {
color: var(--meta-color);

View file

@ -4,7 +4,7 @@
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 24px;
margin-top: 4vmin;
padding: 12px 0;
padding-block: 12px;
.card {
box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
@ -22,7 +22,9 @@
}
.card-info {
padding: 0 24px 24px;
padding-inline: 24px;
padding-block-start: 0;
padding-block-end: 24px;
text-align: center;
}

View file

@ -1,7 +1,8 @@
code {
border-radius: 5px;
background-color: var(--bg-1);
padding: 0.1em 0.2em;
padding-inline: 0.2em;
padding-block: 0.1em;
font-size: 0.9rem;
font-family: var(--code-font);
@ -17,7 +18,7 @@ code {
border-collapse: collapse;
border-spacing: 0rem;
width: 100%;
text-align: left;
text-align: start;
td,
th,
@ -29,7 +30,7 @@ code {
tbody td:first-child {
width: 2rem;
user-select: none;
text-align: left;
text-align: start;
}
tbody tr:nth-child(even) {
@ -46,7 +47,9 @@ pre {
display: block;
position: relative;
border-radius: 5px;
padding: 2.4rem 1rem 1rem;
padding-inline: 1rem;
padding-block-start: 2.4rem;
padding-block-end: 1rem;
overflow: hidden;
overflow-x: auto;
line-height: 1.4;
@ -66,16 +69,16 @@ pre {
display: block;
position: absolute;
top: 0;
left: 0;
inset-inline-start: 0;
background-color: var(--primary-color);
padding: 0.3rem;
padding-left: 1rem;
padding-inline-start: 1rem;
width: calc(100% - 1.3rem);
height: 0.9rem;
content: attr(data-lang);
color: var(--hover-color);
font-size: 0.65rem;
text-align: left;
text-align: start;
text-transform: uppercase;
}
@ -83,15 +86,15 @@ pre {
display: block;
position: absolute;
top: 0;
right: 1.3rem;
inset-inline-end: 1.3rem;
padding-top: 0.3rem;
padding-right: 1.3rem;
padding-inline-end: 1.3rem;
max-width: calc(100% - 14em);
height: 0.9rem;
overflow: hidden;
color: var(--hover-color);
font-size: 0.65rem;
text-align: right;
text-align: end;
text-overflow: ellipsis;
white-space: nowrap;
}
@ -102,10 +105,10 @@ pre {
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960' %3E%3Cpath d='M217.002-67.694q-37.732 0-64.02-26.288-26.287-26.287-26.287-64.019V-707.69h77.999v549.689q0 4.615 3.846 8.462 3.846 3.846 8.462 3.846h451.689v77.999H217.002Zm175.999-175.999q-37.733 0-64.02-26.287T302.694-334v-463.383q0-37.732 26.287-64.02 26.287-26.287 64.02-26.287h365.383q37.732 0 64.019 26.287 26.288 26.288 26.288 64.02V-334q0 37.733-26.288 64.02-26.287 26.287-64.019 26.287H393.001Zm0-77.998h365.383q4.615 0 8.462-3.847 3.846-3.846 3.846-8.462v-463.383q0-4.616-3.846-8.462-3.847-3.846-8.462-3.846H393.001q-4.616 0-8.462 3.846-3.847 3.846-3.847 8.462V-334q0 4.616 3.847 8.462 3.846 3.847 8.462 3.847Zm-12.309 0v-488V-321.691Z'/%3E%3C/svg%3E");
position: absolute;
top: 0.3rem;
right: 0.7rem;
align-self: center;
z-index: 1;
cursor: pointer;
inset-inline-end: 0.7rem;
background: var(--hover-color);
background-size: contain;
width: 0.9rem;

View file

@ -23,7 +23,8 @@
margin: 0.5em auto;
border: none;
background: none;
padding: 0.5em 1em;
padding-block: 0.5em;
padding-inline: 1em;
color: inherit;
font-size: 0.95rem;
font-family: var(--sans-serif-font);

View file

@ -1,6 +1,6 @@
footer {
margin-top: auto;
margin-bottom: 1.4rem;
margin-block-end: 1.4rem;
color: var(--meta-color);
font-size: 0.88rem;
font-family: var(--post-font-family);
@ -66,7 +66,7 @@ footer nav {
}
}
[data-theme="dark"] {
@mixin dark-theme-social {
.social {
&:hover {
& > img {
@ -79,3 +79,13 @@ footer nav {
}
}
}
[data-theme="dark"] {
@include dark-theme-social;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
@include dark-theme-social;
}
}

View file

@ -4,8 +4,8 @@
justify-content: center;
align-items: center;
opacity: 0;
margin-left: -2rem;
padding-right: 0.3rem;
margin-inline-start: -2rem;
padding-inline-end: 0.3rem;
width: 1.9rem;
height: 100%;
user-select: none;
@ -15,11 +15,6 @@
}
}
:dir(rtl) .header-anchor {
margin-right: -2rem;
padding-left: 0.3rem;
}
.link-icon {
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14.78 3.653a3.936 3.936 0 1 1 5.567 5.567l-3.627 3.627a3.936 3.936 0 0 1-5.88-.353.75.75 0 0 0-1.18.928 5.436 5.436 0 0 0 8.12.486l3.628-3.628a5.436 5.436 0 1 0-7.688-7.688l-3 3a.75.75 0 0 0 1.06 1.061l3-3Z'%3E%3C/path%3E%3Cpath d='M7.28 11.153a3.936 3.936 0 0 1 5.88.353.75.75 0 0 0 1.18-.928 5.436 5.436 0 0 0-8.12-.486L2.592 13.72a5.436 5.436 0 1 0 7.688 7.688l3-3a.75.75 0 1 0-1.06-1.06l-3 3a3.936 3.936 0 0 1-5.567-5.568l3.627-3.627Z'%3E%3C/path%3E%3C/svg%3E");
align-self: center;

View file

@ -4,7 +4,7 @@ header {
}
.page-header {
margin: 4rem 0px 1rem 0px;
margin-block: 4rem 1rem;
font-size: 3em;
line-height: 100%;
font-family: var(--header-font);
@ -17,7 +17,7 @@ header {
justify-content: space-between;
align-items: center;
margin: 0 auto;
padding: 1em 0;
padding-block: 1em;
max-width: var(--max-layout-width);
}
@ -48,7 +48,7 @@ header {
}
.home-title {
margin-left: -0.12rem;
margin-inline-start: -0.12rem;
border: none;
padding: 0.12rem;
color: var(--primary-color);
@ -85,8 +85,8 @@ header {
display: flex;
justify-content: center;
align-items: center;
margin-right: 0.5rem;
margin-left: 0.5rem;
margin-inline-start: 0.5rem;
margin-inline-end: 0.5rem;
.language-switcher-icon {
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='1.8' d='M1 12a11 11 90 0 0 22 0 11 11 90 0 0-22 0m1-4h20M2 16h20M11 1a21 21 90 0 0 0 22m2-22a21 21 90 0 1 0 22'/%3E%3C/svg%3E%0A");
@ -129,8 +129,8 @@ header {
transform: translateX(-50%);
z-index: 1;
background: var(--background-color);
padding-right: 0.5rem;
padding-left: 0.5rem;
padding-inline-start: 0.5rem;
padding-inline-end: 0.5rem;
text-align: center;
white-space: nowrap;

View file

@ -7,11 +7,11 @@
@media only screen and (max-width: 600px) {
display: block;
margin-bottom: 2rem;
margin-block-end: 2rem;
}
#home-banner-text {
margin-bottom: 1.5rem;
margin-block-end: 1.5rem;
color: var(--primary-color);
font-size: 1.875rem;
line-height: 3rem;
@ -22,12 +22,12 @@
#home-banner-header {
margin: 0;
margin-bottom: 1rem;
margin-block-end: 1rem;
font-weight: 550;
font-size: 2.8rem;
@media only screen and (max-width: 600px) {
margin-bottom: 0;
margin-block-end: 0;
font-size: 2.2rem;
}
}
@ -53,7 +53,7 @@
#image-container-home {
position: relative;
padding-left: 2rem;
padding-inline-start: 2rem;
min-width: 11rem;
min-height: 11rem;
overflow: hidden;
@ -68,7 +68,7 @@
}
@media only screen and (max-width: 600px) {
padding-left: 0;
padding-inline-start: 0;
}
}
}

View file

@ -27,7 +27,7 @@ img.inline {
figure h4 {
margin: 0;
margin-bottom: 1em;
margin-block-end: 1em;
font-size: 1rem;
}

View file

@ -1,7 +1,8 @@
.draft-label {
margin-right: 0.3rem;
margin-inline-end: 0.3rem;
background-color: var(--primary-color);
padding: 2px 4px;
padding-inline: 4px;
padding-block: 2px;
color: var(--hover-color);
}
@ -16,9 +17,9 @@
iframe {
display: block;
margin-right: 15%;
margin-bottom: 3vmin;
margin-left: 15%;
margin-inline-start: 15%;
margin-inline-end: 15%;
margin-block-end: 3vmin;
border: none;
aspect-ratio: 16/9;
width: 100vmin;
@ -30,7 +31,7 @@ ul {
}
.toc-container {
margin-bottom: 4vmin;
margin-block-end: 4vmin;
}
.padding-top {
@ -81,13 +82,13 @@ a:hover {
a:not(.no-hover-padding):hover::after {
display: inline-block;
position: absolute;
top: 0;
right: -0.15em;
bottom: 0;
left: -0.15em;
z-index: -1;
inset-block-end: 0;
inset-block-start: 0;
inset-inline-end: -0.15em;
inset-inline-start: -0.15em;
background-color: var(--primary-color);
max-width: 105%; // This fixes multi-line links (see #225)
max-inline-size: 105%; // This fixes multi-line links (see #225)
content: "";
}
@ -111,10 +112,10 @@ hr {
}
.footnote-definition {
margin-bottom: 0.6rem;
margin-block-end: 0.6rem;
sup {
margin-right: 0.15rem;
margin-inline-end: 0.15rem;
font-size: 0.75rem;
font-family: var(--serif-font);
}
@ -125,7 +126,7 @@ hr {
}
.footnote-backlink {
margin-left: 0.2rem;
margin-inline-start: 0.2rem;
font-size: 0.8rem;
}
@ -134,16 +135,16 @@ hr {
}
.references p {
margin-left: 2.4rem;
margin-inline-start: 2.4rem;
text-indent: -2.4rem;
}
.info-box {
margin-top: 1rem;
margin-bottom: 1rem;
margin-block-end: 1rem;
border: 1px solid var(--primary-color);
border-left-width: 0.3rem;
border-radius: 10px;
border-inline-start-width: 0.3rem;
padding: 1rem;
text-align: center;
}
@ -187,18 +188,18 @@ details summary {
.article-navigation {
display: flex;
margin-top: 2rem;
border-top: var(--divider-color) solid 0.5px;
padding-top: 2rem;
margin-block-start: 2rem;
border-block-start: var(--divider-color) solid 0.5px;
padding-block-start: 2rem;
div:first-child {
flex: 1;
text-align: left;
text-align: start;
}
div:last-child {
flex: 1;
text-align: right;
text-align: end;
}
div p {
@ -218,25 +219,15 @@ details summary {
}
}
:dir(rtl) .article-navigation {
div:first-child {
text-align: right;
}
div:last-child {
text-align: left;
}
}
:dir(rtl) .arrow {
display: inline-block;
transform: rotate(180deg);
transform: scaleX(-1);
}
// This for the arrows that point to a corner, (e.g. '', '', '', '')
:dir(rtl) .arrow-corner {
display: inline-block;
transform: rotate(270deg);
transform: rotate(-90deg);
}
.mermaid p {

View file

@ -7,10 +7,10 @@
display: flex;
align-items: flex-start;
background-color: var(--navbar-color);
padding: 2.5rem 0;
padding-block: 2.5rem;
.bloglist-meta {
margin-right: 0.7rem;
margin-inline-end: 0.7rem;
padding: 0;
width: 13.5rem;
color: var(--meta-color);
@ -32,7 +32,7 @@
.tag {
display: inline-block;
margin-right: 0.7rem;
margin-inline-end: 0.7rem;
font-weight: 400;
font-size: 0.75rem;
text-transform: uppercase;
@ -89,15 +89,15 @@
.bloglist-row {
flex-direction: column;
align-items: flex-start;
padding: 2rem 0;
padding-block: 2rem;
.bloglist-meta {
margin-bottom: 0;
margin-block-end: 0;
width: 100%;
li {
display: inline;
margin-right: 0.3rem;
margin-inline-end: 0.3rem;
}
}

View file

@ -64,20 +64,20 @@
right: 0;
bottom: 100%;
z-index: 2;
margin-bottom: $padding-vertical;
margin-block-end: $padding-vertical;
box-shadow: rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px;
border: 1px solid var(--divider-color);
border-radius: 5px;
background-color: var(--background-color);
padding-right: $padding-horizontal;
padding-inline-end: $padding-horizontal;
max-height: 70vh;
overflow-y: auto;
font-size: 0.8rem;
text-align: left;
text-align: start;
white-space: nowrap; // Prevents wrapping, allowing content to define width.
ul {
padding-left: $padding-horizontal;
padding-inline-start: $padding-horizontal;
list-style: none;
}
}

View file

@ -2,7 +2,7 @@ $icon-size: 1.3rem;
#searchModal {
background: color-mix(in srgb, var(--primary-color) 5%, transparent);
text-align: left;
text-align: start;
#searchContainer {
padding: 1rem;
@ -18,7 +18,7 @@ $icon-size: 1.3rem;
.search-icon {
position: absolute;
left: 1rem;
inset-inline-start: 1rem;
width: $icon-size;
height: $icon-size;
@ -28,10 +28,11 @@ $icon-size: 1.3rem;
}
.close-icon {
display: none;
position: absolute;
right: $icon-size;
margin-right: 0.5rem;
margin-left: 1rem;
margin-inline-start: 1rem;
margin-inline-end: 0.5rem;
width: $icon-size;
height: $icon-size;
}
@ -41,7 +42,8 @@ $icon-size: 1.3rem;
border: 1px solid var(--divider-color);
border-radius: 20px;
background-color: var(--input-background-color);
padding: 0.75rem 1rem 0.75rem 3rem;
padding-inline: 3rem 1rem;
padding-block: 0.75rem;
width: calc(100% - 2rem);
color: var(--text-color);
font-size: 1rem;
@ -82,7 +84,8 @@ $icon-size: 1.3rem;
> div {
cursor: pointer;
padding: 0.5rem 1rem;
padding-inline: 1rem;
padding-block: 0.5rem;
&[aria-selected="true"] {
background-color: var(--primary-color);
@ -113,8 +116,8 @@ $icon-size: 1.3rem;
display: block;
position: relative;
align-self: center;
margin-right: 0.5rem;
margin-left: 1rem;
margin-inline-start: 1rem;
margin-inline-end: 0.5rem;
width: $icon-size;
height: $icon-size;
}

View file

@ -11,7 +11,8 @@ table {
th,
td {
border: 1px solid var(--bg-1);
padding: 6px 13px;
padding-inline: 13px;
padding-block: 6px;
font-size: large;
}

View file

@ -8,7 +8,7 @@
}
.tags-item {
margin-bottom: 1rem;
margin-block-end: 1rem;
}
}

View file

@ -3,7 +3,7 @@
position: relative;
align-self: center;
cursor: pointer;
margin-left: 0.5rem;
margin-inline-start: 0.5rem;
background: var(--text-color);
width: 1rem;
height: 1rem;
@ -19,13 +19,13 @@
.theme-resetter {
-webkit-mask: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" %3E%3Cpath d="M295.87-193.869v-78.001h291.152q43.63 0 72.369-33.424 28.739-33.423 28.739-79.271t-28.739-79.391Q630.652-497.5 587.022-497.5H343.913l87.478 87.478-55.652 55.153L193.869-536.5l181.87-181.631 55.652 55.653-87.478 86.978h243.109q75.435 0 127.272 56.522 51.837 56.521 51.837 134.174 0 77.652-51.837 134.293-51.837 56.642-127.272 56.642H295.87Z"/%3E%3C/svg%3E');
position: absolute;
top: -0.6rem;
right: -0.6rem;
visibility: hidden;
opacity: 0;
transition: opacity 0.3s ease, visibility 0.3s ease;
transition-delay: 0.5s;
cursor: pointer;
inset-block-start: -0.6rem;
inset-inline-end: -0.6rem;
background: var(--text-color);
width: 0.8rem;
height: 0.8rem;

View file

@ -21,7 +21,7 @@ body > div:last-child > div:last-child[style]:not([class]):not([id]) > p[style]:
}
body > div:last-child > div:last-child[style]:not([class]):not([id]) > pre[style]:last-child {
margin-bottom: 0;
margin-block-end: 0;
background-color: var(--admonition-danger-code);
padding: 10px;
overflow-x: auto;

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #3271E7; // Contrast ratio: 4.51:1
}
@else if $theme == 'dark' {
--primary-color: #6cacff; // Contrast ratio: 7.05:1
}
}
:root {
--primary-color: #3271E7; // Contrast ratio: 4.51:1
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #6cacff; // Contrast ratio: 7.05:1
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,9 +1,24 @@
// Evangelion Unit-02.
:root {
--primary-color: #d12e36; // Contrast ratio: 5.05:1
@mixin theme-variables($theme) {
@if $theme =='light' {
// Evangelion Unit-02.
--primary-color: #d12e36; // Contrast ratio: 5.05:1
}
@else if $theme == 'dark' {
// Evangelion Unit-01.
--primary-color: #c09bd9; // Contrast ratio: 7.01:1
}
}
// Evangelion Unit-01.
[data-theme='dark'] {
--primary-color: #c09bd9; // Contrast
:root {
@include theme-variables('light');
}
[data-theme='dark'] {
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #1460bd; // Contrast ratio: 6.1:1
}
@else if $theme == 'dark' {
--primary-color: #e6c212; // Contrast ratio: 9.48:1
}
}
:root {
--primary-color: #1460bd; // Contrast ratio: 6.1:1
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #e6c212; // Contrast ratio: 9.48:1
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #9055d8; // Contrast ratio: 4.69:1
}
@else if $theme == 'dark' {
--primary-color: #cba2e8; // Contrast ratio: 7.74:1
}
}
:root {
--primary-color: #9055d8; // Contrast ratio: 4.69:1
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #cba2e8; // Contrast ratio: 7.74:1
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -2,11 +2,25 @@
// and might not be suitable for users with certain types of visual impairment.
// Furthermore, low contrast will affect your Google Lighthouse rating.
// For more information on web accessibility: https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #f56a00; // Contrast ratio: 3.02:1. Not very accessible.
}
@else if $theme == 'dark' {
--primary-color: #ec984f; // Contrast ratio: 7.19:1. Accessible.
}
}
:root {
--primary-color: #f56a00; // Contrast ratio: 3.02:1. Not very accessible.
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #ec984f; // Contrast ratio: 7.19:1. Accessible.
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -2,11 +2,25 @@
// and might not be suitable for users with certain types of visual impairment.
// Furthermore, low contrast will affect your Google Lighthouse rating.
// For more information on web accessibility: https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #ffa057; // Contrast ratio: 2.01:1. Not very accessible.
}
@else if $theme == 'dark' {
--primary-color: #ffab7f; // Contrast ratio: 8.93:1. Accessible.
}
}
:root {
--primary-color: #ffa057; // Contrast ratio: 2.01:1. Not very accessible.
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #ffab7f; // Contrast ratio: 8.93:1. Accessible.
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -2,11 +2,25 @@
// and might not be suitable for users with certain types of visual impairment.
// Furthermore, low contrast will affect your Google Lighthouse rating.
// For more information on web accessibility: https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #ee59d2; // Contrast ratio: 3:1. Not very accessible.
}
@else if $theme == 'dark' {
--primary-color: #f49ee9; // Contrast ratio: 9.87:1. Accessible.
}
}
:root {
--primary-color: #ee59d2; // Contrast ratio: 3:1. Not very accessible.
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #f49ee9; // Contrast ratio: 9.87:1. Accessible.
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #00804d; // Contrast ratio: 5:1
}
@else if $theme == 'dark' {
--primary-color: #00b86e; // Contrast ratio: 6.34:1
}
}
:root {
--primary-color: #00804d; // Contrast ratio: 5:1
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #00b86e; // Contrast ratio: 6.34:1
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #727272; // Contrast ratio: 4.81:1
}
@else if $theme == 'dark' {
--primary-color: #b3b3b3; // Contrast ratio: 7.86:1
}
}
:root {
--primary-color: #727272; // Contrast ratio: 4.81:1
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #b3b3b3; // Contrast ratio: 7.86:1
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #ca4963; // Contrast ratio: 4.52:1.
}
@else if $theme == 'dark' {
--primary-color: #ea535f; // Contrast ratio: 4.63:1.
}
}
:root {
--primary-color: #ca4963; // Contrast ratio: 4.52:1.
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #ea535f; // Contrast ratio: 4.63:1.
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,7 +1,22 @@
@mixin theme-variables($theme) {
@if $theme =='light' {
--primary-color: #D33C5C; // Contrast ratio: 4.61:1
}
@else if $theme == 'dark' {
--primary-color: #fabed2; // Contrast ratio: 10.48:1
}
}
:root {
--primary-color: #D33C5C; // Contrast ratio: 4.61:1
@include theme-variables('light');
}
[data-theme='dark'] {
--primary-color: #fabed2; // Contrast ratio: 10.48:1
@include theme-variables('dark');
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

View file

@ -1,12 +1,33 @@
// This file is never loaded; it's serves as reference for the default skin (in main.scss).
// When creating your own skin, you can use https://webaim.org/resources/contrastchecker/
// to verify the accessibility and readability of your colourscheme.
// The light background is #fff and the dark background is #1f1f1f.
// The default light background is #fff and the dark background is #1f1f1f.
// This defines theme-specific variables.
@mixin theme-variables($theme) {
@if $theme =='light' {
// Light theme colours.
--primary-color: #087e96; // Contrast ratio: 4.73:1
}
@else if $theme == 'dark' {
// Dark theme colours.
--primary-color: #91e0ee; // Contrast ratio: 11.06:1
}
}
// Apply light theme variables by default.
:root {
--primary-color: #087e96; // Contrast ratio: 4.73:1
@include theme-variables('light');
}
// Apply dark theme variables when dark theme is explicitly set.
[data-theme='dark'] {
--primary-color: #91e0ee; // Contrast ratio: 11.06:1
@include theme-variables('dark');
}
// Apply dark theme variables when user's system prefers dark mode
// and the theme is not explicitly set to light.
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
@include theme-variables('dark');
}
}

392
scripts/upgrade-deps Executable file
View file

@ -0,0 +1,392 @@
#!/usr/bin/env bash
set -eu
MERMAID_DIR="static/js"
MERMAID_FILE="mermaid.min.js"
MERMAID_PATH="${MERMAID_DIR}/${MERMAID_FILE}"
KATEX_JS_DIR="static/js"
KATEX_CSS_DIR="static"
KATEX_FONTS_DIR="static/fonts/KaTeX"
KATEX_JS_FILE="katex.min.js"
KATEX_CSS_FILE="katex.min.css"
KATEX_JS_PATH="${KATEX_JS_DIR}/${KATEX_JS_FILE}"
KATEX_CSS_PATH="${KATEX_CSS_DIR}/${KATEX_CSS_FILE}"
UGLIFY_ITERATIONS=5
CURL_RETRIES=3
cleanup() {
rm -rf "$TEMP_DIR"
}
exit_with_message() {
echo "$1" >&2
exit 1
}
print_usage() {
echo "Usage: $0 [options]"
echo "Options:"
echo " --mermaid Upgrade Mermaid.js"
echo " --katex Upgrade KaTeX"
echo " --all Upgrade all dependencies (default)"
echo " --help Display this help message"
}
check_dependency() {
if ! command -v "$1" &> /dev/null; then
exit_with_message "$1 is required but not installed."
fi
}
curl_with_retry() {
local url="$1"
local output="$2"
local retries="$CURL_RETRIES"
local wait_time=5
while [ $retries -gt 0 ]; do
if curl -L "$url" -o "$output"; then
return 0
else
echo "Curl failed. Retrying in $wait_time seconds…"
sleep $wait_time
retries=$((retries - 1))
wait_time=$((wait_time * 2))
fi
done
echo "Failed to download after $CURL_RETRIES attempts." >&2
return 1
}
get_latest_version_jsdelivr() {
local package="$1"
local temp_file="${TEMP_DIR}/jsdelivr_response.json"
if curl_with_retry "https://data.jsdelivr.com/v1/package/npm/${package}" "$temp_file"; then
jq -r '.tags.latest' "$temp_file"
else
return 1
fi
}
get_latest_version_github() {
local repo="$1"
local temp_file="${TEMP_DIR}/github_response.json"
if curl_with_retry "https://api.github.com/repos/${repo}/releases/latest" "$temp_file"; then
jq -r '.tag_name' "$temp_file" | sed -E 's/^v?//'
else
return 1
fi
}
get_local_mermaid_version() {
sed -n 's/.*bpt="\([^"]*\)".*/\1/p' "$MERMAID_PATH" | head -n 1
}
get_local_katex_version() {
sed -n 's/.*version:"\([^"]*\)".*/\1/p' "$KATEX_JS_PATH" | head -n 1
}
compare_md5() {
local new_file="$1"
local current_file="$2"
local new_md5
new_md5=$(md5sum "$new_file" | awk '{ print $1 }')
if [ -f "$current_file" ]; then
local current_md5
current_md5=$(md5sum "$current_file" | awk '{ print $1 }')
if [ "$new_md5" = "$current_md5" ]; then
echo "same"
else
echo "different"
fi
else
echo "new"
fi
}
uglify_file() {
local file="$1"
local iterations="$2"
for i in $(seq 1 "$iterations"); do
echo "Running UglifyJS iteration $i"
uglifyjs --compress --mangle -- "$file" > "${file}.tmp"
mv "${file}.tmp" "$file"
done
}
generate_commit_message() {
local template="$1"
local version="$2"
echo "${template//\{VERSION\}/${version}}"
}
safe_file_manipulation() {
local file="$1"
local manipulation_command="$2"
local temp_file="${file}.tmp"
awk "${manipulation_command}" "$file" > "$temp_file"
mv "$temp_file" "$file"
}
append_autorender_extension() {
local file="$1"
# Auto-render Extension (https://katex.org/docs/autorender) with a slight modification to add `$` inline delimiters.
local extension_code='
,function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},$={};function r(e){var _=$[e];if(void 0!==_)return _.exports;var n=$[e]={exports:{}};return t[e](n,n.exports,r),n.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var $ in t)r.o(t,$)&&!r.o(e,$)&&Object.defineProperty(e,$,{enumerable:!0,get:t[$]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var _,n,a,i,o,s,l,h,m={};return r.d(m,{default:function(){return h}}),_=r(771),n=r.n(_),a=function(e,t,$){for(var r=$,_=0,n=e.length;r<t.length;){var a=t[r];if(_<=0&&t.slice(r,r+n)===e)return r;"\\"===a?r++:"{"===a?_++:"}"===a&&_--,r++}return -1},i=/^\\begin{/,o=function(e,t){for(var $,r=[],_=RegExp("("+t.map(function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")}).join("|")+")");-1!==($=e.search(_));){$>0&&(r.push({type:"text",data:e.slice(0,$)}),e=e.slice($));var n=t.findIndex(function(t){return e.startsWith(t.left)});if(-1===($=a(t[n].right,e,t[n].left.length)))break;var o=e.slice(0,$+t[n].right.length),s=i.test(o)?o:e.slice(t[n].left.length,$);r.push({type:"math",data:s,rawData:o,display:t[n].display}),e=e.slice($+t[n].right.length)}return""!==e&&r.push({type:"text",data:e}),r},s=function(e,t){var $=o(e,t.delimiters);if(1===$.length&&"text"===$[0].type)return null;for(var r=document.createDocumentFragment(),_=0;_<$.length;_++)if("text"===$[_].type)r.appendChild(document.createTextNode($[_].data));else{var a=document.createElement("span"),i=$[_].data;t.displayMode=$[_].display;try{t.preProcess&&(i=t.preProcess(i)),n().render(i,a,t)}catch(s){if(!(s instanceof n().ParseError))throw s;t.errorCallback("KaTeX auto-render: Failed to parse `"+$[_].data+"` with ",s),r.appendChild(document.createTextNode($[_].rawData));continue}r.appendChild(a)}return r},l=function e(t,$){for(var r=0;r<t.childNodes.length;r++){var _=t.childNodes[r];if(3===_.nodeType){for(var n=_.textContent,a=_.nextSibling,i=0;a&&a.nodeType===Node.TEXT_NODE;)n+=a.textContent,a=a.nextSibling,i++;var o=s(n,$);if(o){for(var l=0;l<i;l++)_.nextSibling.remove();r+=o.childNodes.length-1,t.replaceChild(o,_)}else r+=i}else 1===_.nodeType&&function(){var t=" "+_.className+" ";-1===$.ignoredTags.indexOf(_.nodeName.toLowerCase())&&$.ignoredClasses.every(function(e){return -1===t.indexOf(" "+e+" ")})&&e(_,$)}()}},h=function(e,t){if(!e)throw Error("No element provided to render");var $={};for(var r in t)t.hasOwnProperty(r)&&($[r]=t[r]);$.delimiters=$.delimiters||[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],$.ignoredTags=$.ignoredTags||["script","noscript","style","textarea","pre","code","option"],$.ignoredClasses=$.ignoredClasses||[],$.errorCallback=$.errorCallback||console.error,$.macros=$.macros||{},l(e,$)},m=m.default}()}),document.addEventListener("DOMContentLoaded",function(){renderMathInElement(document.body)})
'
safe_file_manipulation "$file" '{gsub(/;$/,""); print $0}'
echo "$extension_code" >> "$file"
echo ";" >> "$file"
}
modify_katex_css() {
local file="$1"
safe_file_manipulation "$file" '{gsub(/url\(fonts\/KaTeX/, "url(fonts/KaTeX/KaTeX"); print $0}'
}
upgrade_mermaid() {
echo
echo "Starting Mermaid.js update…"
if [ ! -d "$MERMAID_DIR" ]; then
exit_with_message "Directory ${MERMAID_DIR} does not exist. Are you running this script from the root of the repository?"
fi
local commit_msg_template
commit_msg_template=$(cat << EOM
⬆️ chore(deps): upgrade mermaid to v{VERSION}
Changelog: https://github.com/mermaid-js/mermaid/releases/tag/mermaid%40{VERSION}
Source: https://cdn.jsdelivr.net/npm/mermaid@{VERSION}/dist/mermaid.min.js
EOM
)
local latest_version
latest_version=$(get_latest_version_jsdelivr "mermaid" || get_latest_version_github "mermaid-js/mermaid")
if [ -z "$latest_version" ]; then
exit_with_message "Unable to determine the latest Mermaid.js version."
fi
local local_version
local_version=$(get_local_mermaid_version)
echo "Latest Mermaid.js version: ${latest_version}"
echo "Local Mermaid.js version: ${local_version}"
if [ "$latest_version" = "$local_version" ]; then
echo "Mermaid.js is already up to date. Skipping update."
return 0
fi
local download_url
download_url="https://cdn.jsdelivr.net/npm/mermaid@${latest_version}/dist/mermaid.min.js"
if ! curl_with_retry "${download_url}" "${TEMP_DIR}/${MERMAID_FILE}"; then
exit_with_message "Failed to download Mermaid.js"
fi
uglify_file "${TEMP_DIR}/${MERMAID_FILE}" "$UGLIFY_ITERATIONS"
local comparison_result
comparison_result=$(compare_md5 "${TEMP_DIR}/${MERMAID_FILE}" "${MERMAID_PATH}")
case "$comparison_result" in
"same")
echo "Mermaid: New version is the same as current version. No update needed."
return 0
;;
"different")
echo "Mermaid: New version differs from current version. Proceeding with update."
mv "${TEMP_DIR}/${MERMAID_FILE}" "${MERMAID_PATH}"
;;
"new")
echo "Mermaid: Creating new file: ${MERMAID_PATH}"
mv "${TEMP_DIR}/${MERMAID_FILE}" "${MERMAID_PATH}"
;;
esac
echo "Mermaid.js updated and minified successfully!"
echo "Preparing to commit changes…"
git add "${MERMAID_PATH}"
local commit_msg
commit_msg=$(generate_commit_message "$commit_msg_template" "$latest_version")
git commit -m "${commit_msg}"
echo "Most recent commit:"
git log -1
}
upgrade_katex() {
echo
echo "Starting KaTeX update…"
if [ ! -d "$KATEX_JS_DIR" ] || [ ! -d "$KATEX_CSS_DIR" ]; then
exit_with_message "KaTeX directories do not exist. Are you running this script from the root of the repository?"
fi
local commit_msg_template
commit_msg_template=$(cat << EOM
⬆️ chore(deps): upgrade KaTeX to v{VERSION}
Changelog: https://github.com/KaTeX/KaTeX/releases/tag/v{VERSION}
Source: https://github.com/KaTeX/KaTeX/releases/download/v{VERSION}/katex.tar.gz
EOM
)
local latest_version
latest_version=$(get_latest_version_github "KaTeX/KaTeX")
local local_version
local_version=$(get_local_katex_version)
if [ -z "$local_version" ]; then
exit_with_message "Unable to determine the local KaTeX version."
fi
echo "Latest KaTeX version: ${latest_version}"
echo "Local KaTeX version: ${local_version}"
if [ "$latest_version" = "$local_version" ]; then
echo "KaTeX is already up to date. Skipping update."
return 0
fi
local download_url="https://github.com/KaTeX/KaTeX/releases/download/v${latest_version}/katex.tar.gz"
if ! curl_with_retry "${download_url}" "${TEMP_DIR}/katex.tar.gz"; then
exit_with_message "Failed to download KaTeX"
fi
tar -xzf "${TEMP_DIR}/katex.tar.gz" -C "${TEMP_DIR}"
# JS.
cp "${TEMP_DIR}/katex/katex.min.js" "${TEMP_DIR}/${KATEX_JS_FILE}"
append_autorender_extension "${TEMP_DIR}/${KATEX_JS_FILE}"
uglify_file "${TEMP_DIR}/${KATEX_JS_FILE}" "$UGLIFY_ITERATIONS"
local js_comparison_result
js_comparison_result=$(compare_md5 "${TEMP_DIR}/${KATEX_JS_FILE}" "${KATEX_JS_PATH}")
# CSS.
cp "${TEMP_DIR}/katex/katex.min.css" "${TEMP_DIR}/${KATEX_CSS_FILE}"
modify_katex_css "${TEMP_DIR}/${KATEX_CSS_FILE}"
local css_comparison_result
css_comparison_result=$(compare_md5 "${TEMP_DIR}/${KATEX_CSS_FILE}" "${KATEX_CSS_PATH}")
if [ "$js_comparison_result" = "same" ] && [ "$css_comparison_result" = "same" ]; then
echo "KaTeX: New version is the same as current version. No update needed."
return 0
fi
local changes_made
changes_made=false
if [ "$js_comparison_result" != "same" ]; then
echo "KaTeX JS: New version differs from current version. Proceeding with update."
mv "${TEMP_DIR}/${KATEX_JS_FILE}" "${KATEX_JS_PATH}"
changes_made=true
fi
if [ "$css_comparison_result" != "same" ]; then
echo "KaTeX CSS: New version differs from current version. Proceeding with update."
mv "${TEMP_DIR}/${KATEX_CSS_FILE}" "${KATEX_CSS_PATH}"
changes_made=true
fi
rm -rf "${KATEX_FONTS_DIR}"
mkdir -p "${KATEX_FONTS_DIR}"
cp -r "${TEMP_DIR}/katex/fonts"/* "${KATEX_FONTS_DIR}/"
if [ "$changes_made" = false ]; then
echo "No changes detected in KaTeX files. Skipping commit."
return 0
fi
echo "KaTeX updated successfully!"
echo "Preparing to commit changes…"
git add "${KATEX_JS_PATH}" "${KATEX_CSS_PATH}" "${KATEX_FONTS_DIR}"
local commit_msg
commit_msg=$(generate_commit_message "$commit_msg_template" "$latest_version")
git commit -m "${commit_msg}"
echo "Most recent commit:"
git log -1
}
main() {
local upgrade_mermaid=false
local upgrade_katex=false
# No args = default to upgrading all dependencies.
if [ $# -eq 0 ]; then
upgrade_mermaid=true
upgrade_katex=true
else
while [[ $# -gt 0 ]]; do
case $1 in
--mermaid)
upgrade_mermaid=true
shift
;;
--katex)
upgrade_katex=true
shift
;;
--all)
upgrade_mermaid=true
upgrade_katex=true
shift
;;
--help)
print_usage
exit 0
;;
*)
echo "Unknown option: $1"
print_usage
exit 1
;;
esac
done
fi
check_dependency "jq"
check_dependency "uglifyjs"
check_dependency "curl"
check_dependency "git"
check_dependency "sed"
check_dependency "awk"
check_dependency "md5sum"
check_dependency "tar"
TEMP_DIR=$(mktemp -d)
trap cleanup EXIT
if ! git diff --cached --quiet; then
exit_with_message "There are staged changes. Unstage them before running this script."
fi
echo "Updating local repository…"
git fetch origin
current_branch=$(git rev-parse --abbrev-ref HEAD)
echo "Current branch: $current_branch"
# Check if the branch exists on the remote
if git ls-remote --exit-code --heads origin "$current_branch" >/dev/null 2>&1; then
# Branch exists on remote, compare with local.
local_commit=$(git rev-parse HEAD)
remote_commit=$(git rev-parse origin/"$current_branch")
if [ "$local_commit" = "$remote_commit" ]; then
echo "Branch is up to date with origin/$current_branch"
elif git merge-base --is-ancestor "$remote_commit" "$local_commit"; then
echo "Local branch is ahead of origin/$current_branch"
else
exit_with_message "Your local branch is behind origin/$current_branch. Pull the latest changes before running this script."
fi
else
echo "Branch $current_branch does not exist on remote. Assuming it's a new branch."
fi
echo "Local repository is ready."
if [ "$upgrade_mermaid" = true ]; then
upgrade_mermaid
fi
if [ "$upgrade_katex" = true ]; then
upgrade_katex
fi
}
main "$@"

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom" xmlns:base="http://purl.org/atompub/base/1.0/" xmlns:str="https://github.com/welpo/tabi">
xmlns:atom="http://www.w3.org/2005/Atom" xmlns:tabi="https://github.com/welpo/tabi">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<xsl:attribute name="data-theme">
<xsl:value-of select="/atom:feed/str:translations/str:default_theme"/>
<xsl:value-of select="/atom:feed/tabi:metadata/tabi:default_theme"/>
</xsl:attribute>
<head>
<title>
@ -24,13 +24,13 @@
<div class="info-box">
<!-- This block replaces the text "About Feeds" with a hyperlink in the translated string -->
<xsl:choose>
<xsl:when test="contains(/atom:feed/str:translations/str:about_feeds, 'About Feeds')">
<xsl:value-of select="substring-before(/atom:feed/str:translations/str:about_feeds, 'About Feeds')"/>
<xsl:when test="contains(/atom:feed/tabi:metadata/tabi:about_feeds, 'About Feeds')">
<xsl:value-of select="substring-before(/atom:feed/tabi:metadata/tabi:about_feeds, 'About Feeds')"/>
<a href="https://aboutfeeds.com/" target="_blank">About Feeds</a>
<xsl:value-of select="substring-after(/atom:feed/str:translations/str:about_feeds, 'About Feeds')"/>
<xsl:value-of select="substring-after(/atom:feed/tabi:metadata/tabi:about_feeds, 'About Feeds')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="/atom:feed/str:translations/str:about_feeds"/>
<xsl:value-of select="/atom:feed/tabi:metadata/tabi:about_feeds"/>
</xsl:otherwise>
</xsl:choose>
</div>
@ -43,16 +43,21 @@
</p>
<a class="readmore">
<xsl:attribute name="href">
<xsl:value-of select="/atom:feed/@xml:base"/>
<xsl:value-of select="/atom:feed/atom:link[@rel='alternate']/@href"/>
</xsl:attribute>
<xsl:value-of select="/atom:feed/str:translations/str:visit_the_site" />&#160;<span class="arrow"></span>
<xsl:value-of select="/atom:feed/tabi:metadata/tabi:visit_the_site" />
<xsl:if test="/atom:feed/tabi:metadata/tabi:current_section != /atom:feed/atom:title">
<xsl:text>: </xsl:text>
<xsl:value-of select="/atom:feed/tabi:metadata/tabi:current_section" />
</xsl:if>
<span class="arrow"></span>
</a>
<p></p>
</section>
<div class="padding-top listing-title bottom-divider">
<h1><xsl:value-of select="/atom:feed/str:translations/str:recent_posts" /></h1>
<h1><xsl:value-of select="/atom:feed/tabi:metadata/tabi:recent_posts" /></h1>
</div>
<xsl:variable name="post_listing_date" select="/atom:feed/atom:post_listing_date"/>
<xsl:variable name="post_listing_date" select="/atom:feed/tabi:metadata/tabi:post_listing_date"/>
<div class="bloglist-container">
<xsl:for-each select="/atom:feed/atom:entry">
<section class="bloglist-row bottom-divider">
@ -68,13 +73,13 @@
<xsl:if test="$show_date and $show_updated">
<li class="mobile-only">
<xsl:value-of select="/atom:feed/str:translations/str:separator"/>
<xsl:value-of select="/atom:feed/tabi:metadata/tabi:separator"/>
</li>
</xsl:if>
<xsl:if test="$show_updated">
<li class="date">
<xsl:variable name="update_string" select="/atom:feed/str:translations/str:last_updated_on"/>
<xsl:variable name="update_string" select="/atom:feed/tabi:metadata/tabi:last_updated_on"/>
<xsl:variable name="update_date" select="substring(atom:updated, 0, 11)"/>
<xsl:value-of select="substring-before($update_string, '$DATE')"/>
<xsl:value-of select="$update_date"/>

View file

@ -27,8 +27,8 @@ h4.isso-thread-heading {
}
.isso-feedlink {
float: right;
padding-left: 1em;
float: inline-end;
padding-inline-start: 1em;
}
.isso-feedlink a {
@ -52,13 +52,13 @@ h4.isso-thread-heading {
.isso-comment:not(:first-of-type),
.isso-follow-up .isso-comment {
margin-bottom: 0.5em;
margin-block-end: 0.5em;
border-top: 1px solid var(--divider-color);
}
.isso-avatar {
display: block;
float: left;
float: inline-start;
margin: 0.95em 0.95em 0;
}
@ -77,7 +77,7 @@ h4.isso-thread-heading {
}
.isso-follow-up {
padding-left: calc(7% + 20px);
padding-inline-start: calc(7% + 20px);
}
.isso-comment-footer {
@ -94,7 +94,7 @@ h4.isso-thread-heading {
/* Only for comment header, spacer between up-/downvote should have no padding */
.isso-comment-header .isso-spacer {
padding: 0 6px;
padding-inline: 6px;
}
.isso-spacer,
@ -113,7 +113,7 @@ h4.isso-thread-heading {
}
.isso-note {
float: right;
float: inline-end;
}
.isso-author {
@ -146,7 +146,7 @@ h4.isso-thread-heading {
}
.isso-text p:last-child {
margin-bottom: 0.2em;
margin-block-end: 0.2em;
}
.isso-text h1,
@ -228,7 +228,7 @@ h4.isso-thread-heading {
position: relative;
bottom: 1px;
vertical-align: middle;
margin-left: 0;
margin-inline-end: 0;
}
.isso-notification-section {
@ -257,7 +257,7 @@ h4.isso-thread-heading {
}
.isso-input-wrapper {
margin-right: 0.5em;
margin-inline-end: 0.5em;
}
.isso-input-wrapper input,
@ -289,7 +289,8 @@ h4.isso-thread-heading {
border: none;
border-radius: 5px;
background-color: var(--primary-color);
padding: 0.6em 1em;
padding-inline: 1em;
padding-block: 0.6em;
color: var(--background-color);
font-size: 0.8rem;
}

2
static/isso.min.css vendored
View file

@ -1 +1 @@
.isso-avatar svg,.isso-preview,.isso-textarea{border:1px solid var(--divider-color);width:100%}#isso-thread *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#isso-thread{margin:0 auto;padding:0;width:100%;color:var(--text-color);font-size:.9em;font-family:var(--sans-serif-font)}h4.isso-thread-heading{padding-bottom:.2em;color:var(--text-color);font-size:1.2rem}.isso-feedlink,.isso-note{float:right}.isso-feedlink a{vertical-align:bottom;font-size:.8em}.isso-comment{margin:0 auto;max-width:68em}.isso-preview .isso-comment{margin:0;padding-top:0}.isso-comment:not(:first-of-type),.isso-follow-up .isso-comment{margin-bottom:.5em;border-top:1px solid var(--divider-color)}.isso-avatar{display:block;float:left;margin:.95em .95em 0}.isso-avatar svg{border-radius:3px;max-width:48px;height:100%;max-height:48px}.isso-text-wrapper{display:block;padding:.3em}.isso-follow-up{padding-left:calc(7% + 20px)}.isso-comment-header{font-size:.85em}.isso-comment-header a{text-decoration:none}.isso-comment-header .isso-spacer{padding:0 6px}.isso-note,.isso-parent,.isso-permalink,.isso-spacer{color:var(--meta-color);font-weight:400;text-shadow:none}.isso-note:hover,.isso-parent:hover,.isso-permalink:hover{color:var(--hover-color)}.isso-author{color:var(--text-color);font-weight:500}.isso-page-author-suffix{color:var(--text-color-high-contrast);font-weight:700}.isso-input-wrapper input,.isso-preview,.isso-textarea{background-color:var(--bg-2);color:var(--text-color);font-family:var(--sans-serif-font)}.isso-is-page-author>.isso-text-wrapper{background-color:var(--bg-1)}.isso-preview,.isso-textarea{padding:10px;font-size:.8em}.isso-comment-footer,.isso-comment-footer .isso-votes{color:var(--meta-color)}.isso-text p{margin-top:-.4em}.isso-text p:last-child{margin-bottom:.2em}.isso-text h1,.isso-text h2,.isso-text h3,.isso-text h4,.isso-text h5,.isso-text h6{font-weight:700;font-size:130%}.isso-comment-footer{clear:left;font-size:.8em}.isso-comment-footer a,.isso-feedlink{margin:.4em;padding:.1em;font-weight:700;text-decoration:none}.isso-downvote svg,.isso-upvote svg{position:relative;top:.2em}.isso-downvote:hover svg,.isso-upvote:hover svg{fill:var(--hover-color)}.isso-comment .isso-postbox{margin-top:.8em}.isso-comment.isso-no-votes>*>.isso-comment-footer .isso-votes,.isso-post-action input[name=edit],.isso-postbox.isso-preview-mode>.isso-form-wrapper .isso-textarea,.isso-postbox.isso-preview-mode>.isso-form-wrapper input[name=preview],.isso-preview{display:none}.isso-postbox{clear:right;margin:0 auto 2em}.isso-form-wrapper{display:flex;flex-direction:column}.isso-preview,.isso-textarea{margin-top:.2em;border-radius:5px}.isso-textarea{outline:0;width:100%;resize:none}.isso-form-wrapper input[type=checkbox]{position:relative;bottom:1px;vertical-align:middle;margin-left:0}.isso-notification-section{display:none;padding-top:.3em;padding-bottom:10px;font-size:.9em}.isso-auth-section{display:flex;flex-direction:row}.isso-input-wrapper,.isso-post-action{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;margin:0 auto;max-width:35%;font-size:.8em;font-family:var(--sans-serif-font);text-align:center}.isso-input-wrapper{margin-right:.5em}.isso-input-wrapper input,.isso-post-action input{margin-top:auto}.isso-input-wrapper label{display:inline-block;margin-top:auto;height:auto;line-height:1.4em}.isso-input-wrapper input{border:1px solid var(--divider-color);border-radius:5px;padding:.3em;width:100%;line-height:1.2em}.isso-post-action input{cursor:pointer;margin:.1em;border:none;border-radius:5px;background-color:var(--primary-color);padding:.6em 1em;color:var(--background-color);font-size:.8rem}.isso-post-action{display:block;align-self:flex-end;margin:0 auto}.isso-post-action>input:hover{opacity:.8}.isso-postbox.isso-preview-mode>.isso-form-wrapper .isso-preview{display:block}.isso-postbox.isso-preview-mode>.isso-form-wrapper input[name=edit]{display:inline}.isso-preview{background:repeating-linear-gradient(-45deg,var(--bg-0),var(--bg-0) 10px,var(--bg-2) 10px,var(--bg-2) 20px);background-color:var(--bg-0)}.isso-target{animation:5s ease-out isso-target-fade}@keyframes isso-target-fade{0%{background-color:var(--divider-color)}}@media screen and (max-width:600px){.isso-auth-section{flex-direction:column;text-align:center}.isso-input-wrapper{display:block;margin:0 0 .4em;max-width:100%}.isso-input-wrapper input{width:100%}.isso-post-action{margin:.4em auto;width:60%}}
.isso-avatar svg,.isso-preview,.isso-textarea{border:1px solid var(--divider-color);width:100%}#isso-thread *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#isso-thread{margin:0 auto;padding:0;width:100%;color:var(--text-color);font-size:.9em;font-family:var(--sans-serif-font)}h4.isso-thread-heading{padding-bottom:.2em;color:var(--text-color);font-size:1.2rem}.isso-feedlink,.isso-note{float:right}.isso-feedlink a{vertical-align:bottom;font-size:.8em}.isso-comment{margin:0 auto;max-width:68em}.isso-preview .isso-comment{margin:0;padding-top:0}.isso-comment:not(:first-of-type),.isso-follow-up .isso-comment{margin-bottom:.5em;border-top:1px solid var(--divider-color)}.isso-avatar{display:block;float:left;margin:.95em .95em 0}.isso-avatar svg{border-radius:3px;max-width:48px;height:100%;max-height:48px}.isso-text-wrapper{display:block;padding:.3em}.isso-follow-up{padding-inline-start:calc(7% + 20px)}.isso-comment-header{font-size:.85em}.isso-comment-header a{text-decoration:none}.isso-comment-header .isso-spacer{padding:0 6px}.isso-note,.isso-parent,.isso-permalink,.isso-spacer{color:var(--meta-color);font-weight:400;text-shadow:none}.isso-note:hover,.isso-parent:hover,.isso-permalink:hover{color:var(--hover-color)}.isso-author{color:var(--text-color);font-weight:500}.isso-page-author-suffix{color:var(--text-color-high-contrast);font-weight:700}.isso-input-wrapper input,.isso-preview,.isso-textarea{background-color:var(--bg-2);color:var(--text-color);font-family:var(--sans-serif-font)}.isso-is-page-author>.isso-text-wrapper{background-color:var(--bg-1)}.isso-preview,.isso-textarea{padding:10px;font-size:.8em}.isso-comment-footer,.isso-comment-footer .isso-votes{color:var(--meta-color)}.isso-text p{margin-top:-.4em}.isso-text p:last-child{margin-bottom:.2em}.isso-text h1,.isso-text h2,.isso-text h3,.isso-text h4,.isso-text h5,.isso-text h6{font-weight:700;font-size:130%}.isso-comment-footer{clear:left;font-size:.8em}.isso-comment-footer a,.isso-feedlink{margin:.4em;padding:.1em;font-weight:700;text-decoration:none}.isso-downvote svg,.isso-upvote svg{position:relative;top:.2em}.isso-downvote:hover svg,.isso-upvote:hover svg{fill:var(--hover-color)}.isso-comment .isso-postbox{margin-top:.8em}.isso-comment.isso-no-votes>*>.isso-comment-footer .isso-votes,.isso-post-action input[name=edit],.isso-postbox.isso-preview-mode>.isso-form-wrapper .isso-textarea,.isso-postbox.isso-preview-mode>.isso-form-wrapper input[name=preview],.isso-preview{display:none}.isso-postbox{clear:right;margin:0 auto 2em}.isso-form-wrapper{display:flex;flex-direction:column}.isso-preview,.isso-textarea{margin-top:.2em;border-radius:5px}.isso-textarea{outline:0;width:100%;resize:none}.isso-form-wrapper input[type=checkbox]{position:relative;bottom:1px;vertical-align:middle;margin-inline-end:0}.isso-notification-section{display:none;padding-top:.3em;padding-bottom:10px;font-size:.9em}.isso-auth-section{display:flex;flex-direction:row}.isso-input-wrapper,.isso-post-action{display:flex;flex-direction:column;justify-content:flex-end;align-items:center;margin:0 auto;max-width:35%;font-size:.8em;font-family:var(--sans-serif-font);text-align:center}.isso-input-wrapper{margin-inline-end:.5em}.isso-input-wrapper input,.isso-post-action input{margin-top:auto}.isso-input-wrapper label{display:inline-block;margin-top:auto;height:auto;line-height:1.4em}.isso-input-wrapper input{border:1px solid var(--divider-color);border-radius:5px;padding:.3em;width:100%;line-height:1.2em}.isso-post-action input{cursor:pointer;margin:.1em;border:none;border-radius:5px;background-color:var(--primary-color);padding:.6em 1em;color:var(--background-color);font-size:.8rem}.isso-post-action{display:block;align-self:flex-end;margin:0 auto}.isso-post-action>input:hover{opacity:.8}.isso-postbox.isso-preview-mode>.isso-form-wrapper .isso-preview{display:block}.isso-postbox.isso-preview-mode>.isso-form-wrapper input[name=edit]{display:inline}.isso-preview{background:repeating-linear-gradient(-45deg,var(--bg-0),var(--bg-0) 10px,var(--bg-2) 10px,var(--bg-2) 20px);background-color:var(--bg-0)}.isso-target{animation:5s ease-out isso-target-fade}@keyframes isso-target-fade{0%{background-color:var(--divider-color)}}@media screen and (max-width:600px){.isso-auth-section{flex-direction:column;text-align:center}.isso-input-wrapper{display:block;margin:0 0 .4em;max-width:100%}.isso-input-wrapper input{width:100%}.isso-post-action{margin:.4em auto;width:60%}}

File diff suppressed because one or more lines are too long

View file

@ -2675,6 +2675,7 @@ window.onload = function () {
results.innerHTML = '';
resultsContainer.style.display = 'none';
searchInput.removeAttribute('aria-activedescendant');
clearSearchButton.style.display = 'none';
}
// Close modal when clicking/tapping outside.
@ -2941,10 +2942,13 @@ window.onload = function () {
searchInput.addEventListener(
'input',
async function () {
const searchTerm = this.value.trim();
const searchInput = this.value;
const searchTerm = searchInput.trim();
const searchIndex = await searchIndexPromise;
results.innerHTML = '';
// Use the raw input so the "clear" button appears even if there's only spaces.
clearSearchButton.style.display = searchInput.length > 0 ? 'block' : 'none';
resultsContainer.style.display = searchTerm.length > 0 ? 'block' : 'none';
// Perform the search and store the results.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -7,27 +7,39 @@
{%- endif -%}
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="{{ get_url(path='/feed_style.xsl', trailing_slash=false) | safe }}" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:base="http://purl.org/atompub/base/1.0/" xml:lang="{{ lang }}" xml:base="{{ config.base_url }}">
<str:translations xmlns:str="https://github.com/welpo/tabi">
<str:separator>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="{{ lang }}">
<tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
<tabi:separator>
{{ config.extra.separator | default(value="•") }}
</str:separator>
<str:about_feeds>
</tabi:separator>
<tabi:about_feeds>
{{- macros_translate::translate(key="about_feeds", default="This is a web feed, also known as an Atom feed. Subscribe by copying the URL from the address bar into your newsreader", language_strings=language_strings) -}}
</str:about_feeds>
<str:visit_the_site>
</tabi:about_feeds>
<tabi:visit_the_site>
{{- macros_translate::translate(key="visit_the_site", default="Visit website", language_strings=language_strings) -}}
</str:visit_the_site>
<str:recent_posts>
</tabi:visit_the_site>
<tabi:recent_posts>
{{- macros_translate::translate(key="recent_posts", default="Recent posts", language_strings=language_strings) -}}
</str:recent_posts>
<str:last_updated_on>
</tabi:recent_posts>
<tabi:last_updated_on>
{{- macros_translate::translate(key="last_updated_on", default="Updated on $DATE", language_strings=language_strings) -}}
</str:last_updated_on>
<str:default_theme>
</tabi:last_updated_on>
<tabi:default_theme>
{{- config.extra.default_theme | default(value="") -}}
</str:default_theme>
</str:translations>
</tabi:default_theme>
<tabi:post_listing_date>
{{- config.extra.post_listing_date | default(value="date") -}}
</tabi:post_listing_date>
<tabi:current_section>
{%- if term -%}
{{ term.name }}
{%- elif section.title -%}
{{ section.title }}
{%- else -%}
{{ config.title }}
{%- endif -%}
</tabi:current_section>
</tabi:metadata>
{#- Load extra CSS (skin) if set in config.toml -#}
{%- if config.extra.skin -%}
@ -43,14 +55,15 @@
<subtitle>{{ config.description }}</subtitle>
{%- endif %}
<link href="{{ feed_url | safe }}" rel="self" type="application/atom+xml"/>
<post_listing_date>{{ config.extra.post_listing_date | default(value="date") }}</post_listing_date>
<link href="
{%- if section -%}
{%- if term -%}
{{ term.permalink | escape_xml | safe }}
{%- elif section -%}
{{ section.permalink | escape_xml | safe }}
{%- else -%}
{{ get_url(path="/", lang=lang) | escape_xml | safe }}
{%- endif -%}
"/>
" rel="alternate" type="text/html"/>
<generator uri="https://www.getzola.org/">Zola</generator>
<updated>{{ last_updated | date(format="%+") }}</updated>
<id>{{ feed_url | safe }}</id>

View file

@ -14,9 +14,38 @@ Parameters:
{%- if section -%}
{%- set current_section = section -%}
{%- elif page -%}
{%- set current_section = "" -%}
{#- Retrieve last ancestor to determine current section, if applicable -#}
{%- set last_ancestor = page.ancestors | slice(start=-1) %}
{%- set current_section = get_section(path=last_ancestor.0, metadata_only=true) %}
{%- if page.ancestors | length > 0 -%}
{%- set last_ancestor = page.ancestors | slice(start=-1) -%}
{%- set_global current_section = get_section(path=last_ancestor.0, metadata_only=true) -%}
{%- else -%}
{#- We're likely in a nested page. Try to find the parent page or nearest section. -#}
{%- set components = page.components -%}
{%- for i in range(start=1, end=components | length) -%}
{%- if lang == config.default_language -%}
{%- set potential_path = components | slice(end=components | length - i) | join(sep="/") -%}
{%- set potential_page = potential_path ~ "/index.md" -%}
{%- set potential_section = potential_path ~ "/_index.md" -%}
{%- else -%}
{%- set potential_path = components | slice(start=1, end=components | length - i) | join(sep="/") -%}
{%- set potential_page = potential_path ~ "/index." ~ lang ~ ".md" -%}
{%- set potential_section = potential_path ~ "/_index." ~ lang ~ ".md" -%}
{%- endif -%}
{#- Check for parent page first. -#}
{%- set page_data = load_data(path=potential_page, required=false) -%}
{%- if page_data -%}
{%- set_global current_section = get_page(path=potential_page) -%}
{%- break -%}
{%- endif -%}
{#- No parent page, check for section. -#}
{%- set section_data = load_data(path=potential_section, required=false) -%}
{%- if section_data -%}
{%- set_global current_section = get_section(path=potential_section, metadata_only=true) -%}
{%- break -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{%- set priority_order = [

View file

@ -12,48 +12,94 @@
{%- endif -%}
{# Debugging #}
{# {% set last_ancestor = page.ancestors | slice(start=-1) %}
{% set current_section = get_section(path=last_ancestor.0) %}
{# <div><pre>
Page path: {{ page.path }}
Page components: {{ page.components | join(sep=", ") }}
Page ancestors: {{ page.ancestors | join(sep=", ") }}
Current language: {{ lang }}
Default language: {{ config.default_language }}
Current section: {% if current_section %}{{ current_section.path }}{% else %}None{% endif %}
Page extra: {{ page.extra | json_encode() }}
{% if section -%}
{%- set current_section = section -%}
{%- elif page -%}
{%- set current_section = "" -%}
{%- if page.ancestors | length > 0 -%}
{%- set last_ancestor = page.ancestors | slice(start=-1) -%}
{%- set_global current_section = get_section(path=last_ancestor.0, metadata_only=true) -%}
{%- else -%}
{%- set components = page.components -%}
{%- for i in range(start=1, end=components | length) -%}
{%- if lang == config.default_language -%}
{%- set potential_path = components | slice(end=components | length - i) | join(sep="/") -%}
{%- set potential_page = potential_path ~ "/index.md" -%}
{%- set potential_section = potential_path ~ "/_index.md" -%}
{%- else -%}
{%- set potential_path = components | slice(start=1, end=components | length - i) | join(sep="/") -%}
{%- set potential_page = potential_path ~ "/index." ~ lang ~ ".md" -%}
{%- set potential_section = potential_path ~ "/_index." ~ lang ~ ".md" -%}
{%- endif -%}
Checking parent page: {{ potential_page }}
{%- set page_data = load_data(path=potential_page, required=false) -%}
{%- if page_data -%}
{%- set_global current_section = get_page(path=potential_page) %}
Parent page found: {{ current_section.path }}
{%- break -%}
{%- endif -%}
Checking section: {{ potential_section }}
{%- set section_data = load_data(path=potential_section, required=false) -%}
{%- if section_data -%}
{%- set_global current_section = get_section(path=potential_section, metadata_only=true) -%}
Section found: {{ current_section.path }}
{%- break -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endif %}
Found nearest parent/section: {% if current_section %}{{ current_section.path }}{% else %}None{% endif %}
Current section extra: {% if current_section %}{{ current_section.extra | json_encode() }}{% else %}None{% endif %}
</pre></div>
{% set settings_to_test = [
"footnote_backlinks",
"add_src_to_code_block",
"copy_button",
"katex",
"quick_navigation_buttons",
"show_reading_time",
"show_date",
"show_author",
"show_remote_changes",
"toc",
"show_previous_next_article_links",
"invert_previous_next_article_links",
"previous_next_article_links_full_width",
"enable_csp",
] %}
{% set settings_to_test = [
"footnote_backlinks",
"add_src_to_code_block",
"copy_button",
"katex",
"quick_navigation_buttons",
"show_reading_time",
"show_date",
"show_author",
"show_remote_changes",
"toc",
"show_previous_next_article_links",
"invert_previous_next_article_links",
"previous_next_article_links_full_width",
"enable_csp",
] %}
<table>
<thead>
<tr>
<th>setting</th>
<th>page</th>
<th>section</th>
<th>config</th>
<th>macro output</th>
</tr>
</thead>
<tbody>
{% for setting in settings_to_test %}
<table>
<thead>
<tr>
<td><code>{{ setting }}</code></td>
<td>{{ page.extra[setting] | default(value="⬛") }}</td>
<td>{{ current_section.extra[setting] | default(value="⬛") }}</td>
<td>{{ config.extra[setting] | default(value="⬛") }}</td>
<td>{{ macros_settings::evaluate_setting_priority(setting=setting, page=page) }}</td>
<th>setting</th>
<th>page</th>
<th>section</th>
<th>config</th>
<th>macro output</th>
</tr>
{% endfor %}
</tbody>
</table> #}
</thead>
<tbody>
{% for setting in settings_to_test %}
<tr>
<td><code>{{ setting }}</code></td>
<td>{{ page.extra[setting] | default(value="⬛") }}</td>
<td>{{ current_section.extra[setting] | default(value="⬛") }}</td>
<td>{{ config.extra[setting] | default(value="⬛") }}</td>
<td>{{ macros_settings::evaluate_setting_priority(setting=setting, page=page) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> #}
{# {{ __tera_context }} #}
{# End debugging #}
@ -134,9 +180,14 @@
</ul>
{% if page.extra.tldr %}
<div class="tldr">
<h3>TL;DR:</h3>
<p>{{ page.extra.tldr }}</p>
<div class="admonition note">
<div class="admonition-icon admonition-icon-note"></div>
<div class="admonition-content">
<strong class="admonition-title">
<span title="Too long; didn't read (summary)">TL;DR</span>
</strong>
<p>{{ page.extra.tldr | markdown | safe }}</p>
</div>
</div>
{% endif %}

View file

@ -21,7 +21,7 @@
<div
title="{{ reset_str }}"
class="theme-resetter"
class="theme-resetter arrow"
tabindex="0"
role="button"
aria-hidden="true"

View file

@ -1,7 +1,30 @@
{%- set start = start | default(value=1) -%}
{%- set end = end | default(value=0) -%}
{#- load_data uses different arguments based on whether it's a remote or local file -#}
{%- if src is starting_with("http") -%}
{%- set response = load_data(url=src, format="plain") -%}
{%- else -%}
{%- set response = load_data(path=src, format="plain") -%}
{#- Try to load the file from a relative path -#}
{%- set colocated_path = page.colocated_path | default(value="") -%}
{%- set relative_path = colocated_path ~ src -%}
{%- set response = load_data(path=relative_path, format="plain", required=false) -%}
{#- If relative path fails, try absolute path -#}
{%- if not response -%}
{%- set response = load_data(path=src, format="plain") -%}
{%- endif -%}
{%- endif -%}
{{- response | trim_end | safe -}}
{%- set lines = response | trim_end | split(pat="\n") -%}
{%- if start > 0 -%}
{%- set start = start - 1 -%}
{%- endif -%}
{%- if end == 0 or end > lines | length -%}
{%- set end = lines | length -%}
{%- endif -%}
{%- set lines = lines | slice(start=start, end=end) -%}
{{- lines | join(sep="\n") | safe -}}