first commit
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
# Seuls le Dockerfile, le validateur et les sources Zola
|
||||
# sont nécessaires à la construction.
|
||||
*
|
||||
!Dockerfile
|
||||
!scripts/
|
||||
!scripts/check-content.py
|
||||
!scripts/_schema.py
|
||||
!src/
|
||||
!src/**
|
||||
|
||||
# Ne jamais envoyer le site déjà généré
|
||||
src/public/
|
||||
@@ -0,0 +1,6 @@
|
||||
# Site généré par Zola
|
||||
src/public/
|
||||
|
||||
# Caches Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
FROM python:3.13-alpine AS validator
|
||||
|
||||
COPY ./scripts/check-content.py ./scripts/_schema.py /project/scripts/
|
||||
COPY ./src /project/src
|
||||
WORKDIR /project
|
||||
RUN ["python3", "scripts/check-content.py"]
|
||||
|
||||
FROM ghcr.io/getzola/zola:v0.22.1 AS zola
|
||||
|
||||
COPY --from=validator /project/src /project
|
||||
WORKDIR /project
|
||||
RUN ["zola", "build"]
|
||||
|
||||
FROM ghcr.io/static-web-server/static-web-server:2
|
||||
|
||||
ENV SERVER_ROOT=/public
|
||||
COPY --from=zola /project/public /public
|
||||
@@ -0,0 +1,424 @@
|
||||
# Guide de rédaction
|
||||
|
||||
Ce guide décrit la manière d’ajouter et de maintenir les contenus du site **Les Carnets d’Akkadien**.
|
||||
|
||||
Le principe général est le suivant :
|
||||
|
||||
- le front matter TOML contient les données brèves et structurées ;
|
||||
- le corps Markdown contient les explications, tableaux, exemples et commentaires ;
|
||||
- les champs prévus par un modèle restent présents, même lorsqu’ils sont vides ;
|
||||
- les champs vides ne sont pas affichés sur le site.
|
||||
|
||||
## Organisation des contenus
|
||||
|
||||
| Type | Répertoire | Taxonomie |
|
||||
|---|---|---|
|
||||
| Article | `src/content/articles/` | aucune |
|
||||
| Grammaire | `src/content/grammaire/` | `themes` |
|
||||
| Signe | `src/content/signes/` | `lectures` |
|
||||
| Texte | `src/content/textes/` | `genres` |
|
||||
| Vocabulaire | `src/content/vocabulaire/` | `natures` |
|
||||
|
||||
La bibliographie et les mentions légales sont des pages autonomes placées directement dans `src/content/`.
|
||||
|
||||
Chaque section contient un fichier `_index.md` qui définit son titre, sa description, son tri et ses templates. Ces fichiers sont maintenus manuellement ; le générateur crée uniquement des pages de contenu.
|
||||
|
||||
## Conventions générales
|
||||
|
||||
### Période et terminologie
|
||||
|
||||
Le site est principalement consacré au paléo-babylonien. Une forme, une graphie ou une analyse relevant d’une autre période ou d’un autre dialecte est signalée dans la fiche concernée.
|
||||
|
||||
Les champs structurés propres aux fiches utilisent des clés anglaises. Les noms des taxonomies sont en français ; leurs termes suivent la donnée affichée, en français pour les catégories et en translittération pour les lectures.
|
||||
|
||||
### Unicode et translittération
|
||||
|
||||
Tous les fichiers de contenu sont enregistrés en UTF-8 et normalisés en Unicode NFC, y compris leurs noms.
|
||||
|
||||
Les lemmes, lectures et formes akkadiennes conservent leurs diacritiques :
|
||||
|
||||
```text
|
||||
bītum
|
||||
parāsum
|
||||
aš
|
||||
ṭim
|
||||
```
|
||||
|
||||
Dans le corps Markdown, les formes linguistiques sont généralement écrites en *italique*. Le code en ligne est réservé aux commandes, chemins et noms de champs.
|
||||
|
||||
### Noms de fichiers
|
||||
|
||||
Pour les articles, la grammaire, les textes et le vocabulaire, l’identifiant fourni au générateur devient le nom du fichier. Il doit être écrit sous sa forme finale :
|
||||
|
||||
- en minuscules ;
|
||||
- sans espace ni underscore ;
|
||||
- avec seulement des lettres Unicode, des chiffres et des tirets ;
|
||||
- sans double tiret ni tiret final ;
|
||||
- sans extension `.md`.
|
||||
|
||||
Exemples :
|
||||
|
||||
```text
|
||||
src/content/vocabulaire/bītum.md
|
||||
src/content/vocabulaire/parāsum.md
|
||||
src/content/grammaire/forme-liee.md
|
||||
src/content/articles/les-carnets-sont-en-ligne.md
|
||||
```
|
||||
|
||||
Un tiret initial est accepté uniquement pour le vocabulaire, par exemple `-ma.md`.
|
||||
|
||||
Les signes utilisent toujours un numéro MZL sur trois chiffres :
|
||||
|
||||
```text
|
||||
src/content/signes/mzl-001.md
|
||||
src/content/signes/mzl-113.md
|
||||
src/content/signes/mzl-167.md
|
||||
```
|
||||
|
||||
### Front matter commun
|
||||
|
||||
Les pages générées partagent quatre champs communs :
|
||||
|
||||
```toml
|
||||
title = "Titre"
|
||||
date = 2026-08-05T12:30:00+02:00
|
||||
description = ""
|
||||
draft = true
|
||||
```
|
||||
|
||||
Les tables propres à chaque type de contenu viennent ensuite dans le même front matter.
|
||||
|
||||
- `title` est le titre affiché ;
|
||||
- `date` est créée dans le fuseau `Europe/Paris` et doit refléter la date de publication ;
|
||||
- `description` est un résumé court, rédigé manuellement lorsqu’il est utile ;
|
||||
- `draft` détermine si la page est publiée.
|
||||
|
||||
`date` est une valeur temporelle TOML écrite sans guillemets. Le champ facultatif `updated` peut être ajouté après une modification substantielle :
|
||||
|
||||
```toml
|
||||
updated = 2026-08-05
|
||||
```
|
||||
|
||||
Lorsque `description` reste vide :
|
||||
|
||||
- une fiche de vocabulaire affiche une phrase construite à partir de sa nature, de son genre et de son sens ;
|
||||
- une fiche de signe affiche une phrase construite à partir de son titre et de son numéro MZL ;
|
||||
- un article, une note de grammaire ou un texte n’affiche pas de résumé de remplacement.
|
||||
|
||||
La métadescription HTML utilise alors, en dernier recours, la description générale du site.
|
||||
|
||||
### Brouillons et publication
|
||||
|
||||
Un brouillon peut rester incomplet et être affiché localement avec :
|
||||
|
||||
```sh
|
||||
zola --root src serve --drafts
|
||||
```
|
||||
|
||||
Pour publier une fiche :
|
||||
|
||||
1. compléter les données disponibles sans supprimer les champs de son modèle ;
|
||||
2. rédiger le corps Markdown ;
|
||||
3. vérifier la date ;
|
||||
4. passer `draft` à `false` ;
|
||||
5. lancer les contrôles.
|
||||
|
||||
```sh
|
||||
./scripts/check-content.py
|
||||
zola --root src check --drafts --skip-external-links
|
||||
```
|
||||
|
||||
## Générateur de fiches
|
||||
|
||||
La commande générale est :
|
||||
|
||||
```sh
|
||||
./scripts/new-content.py SECTION IDENTIFIANT [--nature NATURE] [--title TITRE]
|
||||
```
|
||||
|
||||
Exemples :
|
||||
|
||||
```sh
|
||||
./scripts/new-content.py vocabulaire šarrum --nature nom
|
||||
./scripts/new-content.py vocabulaire epēšum --nature verbe
|
||||
./scripts/new-content.py vocabulaire --nature particule -- -ma
|
||||
./scripts/new-content.py signes 113 --title BE
|
||||
./scripts/new-content.py grammaire suffixes-pronominaux
|
||||
./scripts/new-content.py textes lettre-au-marchand
|
||||
./scripts/new-content.py articles nouvel-article
|
||||
```
|
||||
|
||||
Pour le vocabulaire, les natures reconnues sont :
|
||||
|
||||
```text
|
||||
nom, adjectif, verbe, pronom, préposition,
|
||||
adverbe, conjonction, particule, numéral
|
||||
```
|
||||
|
||||
Lorsque `--nature` est omise dans un terminal interactif, le générateur propose un menu. Elle est obligatoire dans un contexte non interactif.
|
||||
|
||||
Le générateur normalise l’identifiant et le titre en NFC, prépare tous les champs nécessaires et refuse tout écrasement. Il ne renseigne pas les données linguistiques et ne rédige pas le corps Markdown.
|
||||
|
||||
Pour un article, un texte ou une note de grammaire, le titre est déduit de l’identifiant en remplaçant les tirets par des espaces et en mettant l’initiale en majuscule. Pour le vocabulaire, il reprend l’identifiant. Pour un signe, il reste vide sauf si `--title` est fourni.
|
||||
|
||||
## Taxonomies
|
||||
|
||||
Les taxonomies publiques sont :
|
||||
|
||||
- `natures` pour la nature grammaticale du vocabulaire ;
|
||||
- `lectures` pour les lectures des signes ;
|
||||
- `themes` pour les notions grammaticales ;
|
||||
- `genres` pour les types documentaires des textes.
|
||||
|
||||
Les termes sont écrits sous leur forme destinée à l’affichage :
|
||||
|
||||
```toml
|
||||
natures = ["préposition"]
|
||||
lectures = ["tim", "ṭim"]
|
||||
themes = ["morphologie nominale"]
|
||||
genres = ["lettre"]
|
||||
```
|
||||
|
||||
La graphie doit rester stable. Les diacritiques sont conservés dans les URL : `tim` et `ṭim` correspondent donc à deux lectures distinctes.
|
||||
|
||||
Une fiche de vocabulaire contient exactement une nature. Les autres taxonomies peuvent contenir plusieurs termes lorsque cela est pertinent.
|
||||
|
||||
## Fiches de vocabulaire
|
||||
|
||||
Toutes les fiches lexicales utilisent la même structure générale :
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "lemme"
|
||||
date = 2026-08-05T12:30:00+02:00
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[extra]
|
||||
meaning = ""
|
||||
logograms = []
|
||||
|
||||
[taxonomies]
|
||||
natures = ["nature"]
|
||||
+++
|
||||
```
|
||||
|
||||
`meaning` contient le sens principal ou une courte série de sens. Il doit être renseigné avant publication.
|
||||
|
||||
`logograms` contient les écritures logographiques associées au lemme. Il reste toujours un tableau de chaînes :
|
||||
|
||||
```toml
|
||||
logograms = ["LUGAL"]
|
||||
```
|
||||
|
||||
Chaque nature ajoute les champs suivants, dans l’ordre produit par le générateur :
|
||||
|
||||
| Nature | Champs supplémentaires |
|
||||
|---|---|
|
||||
| Nom | `gender`, `bound`, `plural` |
|
||||
| Adjectif | `bound`, `feminine`, `masculine_plural`, `feminine_plural`, `predicative` |
|
||||
| Verbe | `root`, `stem`, `verb_class`, `vowel_class`, `preterite`, `durative`, `perfect`, `imperative`, `participle`, `verbal_adjective` |
|
||||
| Pronom | `pronoun_type`, `person`, `gender`, `number` |
|
||||
| Préposition | `governs` |
|
||||
| Adverbe | `function` |
|
||||
| Conjonction | `function` |
|
||||
| Particule | `function` |
|
||||
| Numéral | `numeral_type`, `value`, `gender`, `feminine` |
|
||||
|
||||
Tous les champs simples restent des chaînes, même lorsqu’ils sont vides. Une fiche publiée doit contenir exactement les champs de sa nature : un champ manquant, supplémentaire ou mal typé est rejeté par le validateur.
|
||||
|
||||
Pour un verbe, `stem` est obligatoire avant publication. Le titre fournit déjà l’infinitif et ne le répète donc pas dans `[extra]`.
|
||||
|
||||
### Sens des principaux champs
|
||||
|
||||
- `gender` : genre grammatical ;
|
||||
- `bound` : forme liée ;
|
||||
- `plural` : pluriel lexical ;
|
||||
- `predicative` : forme prédicative de référence, affichée comme « Prédicatif (3 m. s.) » ;
|
||||
- `root` : racine, par exemple `p-r-s` ;
|
||||
- `stem` : thème verbal, par exemple `G`, `D`, `Š` ou `N` ;
|
||||
- `verb_class` : classe morphologique, par exemple `fort`, `I-n` ou `III-faible` ;
|
||||
- `vowel_class` : classe vocalique, par exemple `a/u` ;
|
||||
- `pronoun_type` : type de pronom ;
|
||||
- `governs` : cas régi par une préposition ;
|
||||
- `function` : fonction d’un adverbe, d’une conjonction ou d’une particule ;
|
||||
- `numeral_type` : cardinal, ordinal ou autre type de numéral ;
|
||||
- `value` : valeur numérique.
|
||||
|
||||
Le corps Markdown reste libre. Les rubriques suivantes peuvent servir de repères lorsqu’elles sont utiles :
|
||||
|
||||
```markdown
|
||||
## Emploi
|
||||
## Morphologie
|
||||
## Déclinaison
|
||||
## Thèmes dérivés
|
||||
## Occurrences
|
||||
## Voir aussi
|
||||
## Sources
|
||||
```
|
||||
|
||||
Les paradigmes, exceptions, constructions et commentaires détaillés appartiennent au corps plutôt qu’au front matter. Les rubriques vides ne sont pas ajoutées.
|
||||
|
||||
## Fiches de signes
|
||||
|
||||
La commande suivante :
|
||||
|
||||
```sh
|
||||
./scripts/new-content.py signes 113 --title BE
|
||||
```
|
||||
|
||||
produit :
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "BE"
|
||||
date = 2026-08-05T12:30:00+02:00
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[extra]
|
||||
sign = ""
|
||||
mzl = "113"
|
||||
|
||||
[taxonomies]
|
||||
lectures = []
|
||||
+++
|
||||
```
|
||||
|
||||
- le fichier est nommé `mzl-113.md` ;
|
||||
- `title` contient le nom usuel du signe ;
|
||||
- `sign` contient le caractère cunéiforme Unicode ;
|
||||
- `mzl` reprend exactement les trois chiffres du nom de fichier ;
|
||||
- `lectures` contient les lectures translittérées.
|
||||
|
||||
Le nom `mzl-XXX.md` est contrôlé même lorsque la fiche est encore en brouillon. Avant publication, le titre, le glyphe et le numéro MZL doivent être renseignés, et le numéro doit correspondre au nom du fichier.
|
||||
|
||||
Le corps peut accueillir, selon le besoin :
|
||||
|
||||
```markdown
|
||||
## Valeurs syllabiques
|
||||
## Emplois logographiques
|
||||
## Emploi comme déterminatif
|
||||
## Variantes graphiques
|
||||
## Notes
|
||||
```
|
||||
|
||||
Une fiche de signe peut rester sans corps si son front matter suffit.
|
||||
|
||||
## Notes de grammaire
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "Titre de la fiche"
|
||||
date = 2026-08-05T12:30:00+02:00
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
themes = []
|
||||
+++
|
||||
```
|
||||
|
||||
`themes` regroupe les fiches par notion grammaticale. Le corps est organisé librement selon le sujet.
|
||||
|
||||
## Textes étudiés
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "Titre du texte"
|
||||
date = 2026-08-05T12:30:00+02:00
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
genres = []
|
||||
+++
|
||||
```
|
||||
|
||||
`genres` décrit le type documentaire, par exemple `lettre` ou `inscription commémorative`.
|
||||
|
||||
Une structure fréquente est :
|
||||
|
||||
```markdown
|
||||
## Présentation
|
||||
## Translittération
|
||||
## Normalisation
|
||||
## Traduction
|
||||
## Commentaire philologique
|
||||
## Vocabulaire
|
||||
```
|
||||
|
||||
Elle peut être adaptée à chaque texte.
|
||||
|
||||
## Articles
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "Titre de l’article"
|
||||
date = 2026-08-05T12:30:00+02:00
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[extra]
|
||||
banner = ""
|
||||
banner_alt = ""
|
||||
banner_credit = ""
|
||||
+++
|
||||
```
|
||||
|
||||
- `description` est affichée dans la liste des articles, sur la page d’accueil et dans la page elle-même ;
|
||||
- `banner` indique un chemin relatif à `src/static/`, par exemple `images/articles/article.webp` ;
|
||||
- `banner_alt` contient le texte alternatif de l’image ;
|
||||
- `banner_credit` contient une attribution ou une légende facultative.
|
||||
|
||||
Lorsque `banner` reste vide, aucune image ni aucun espace réservé ne sont générés. Lorsqu’une image est ajoutée, son texte alternatif doit décrire utilement son contenu ; une image purement décorative peut utiliser une chaîne vide.
|
||||
|
||||
## Liens internes
|
||||
|
||||
Les liens entre contenus utilisent les chemins internes de Zola :
|
||||
|
||||
```markdown
|
||||
[Voir bītum](@/vocabulaire/bītum.md)
|
||||
[Voir la forme liée](@/grammaire/forme-liee.md)
|
||||
```
|
||||
|
||||
Ils sont ajoutés lorsqu’ils apportent un contexte réel : occurrence dans un texte, exemple grammatical, signe observé ou relation lexicale utile.
|
||||
|
||||
## Ce que contrôle le validateur
|
||||
|
||||
Le validateur vérifie pour tous les fichiers Markdown :
|
||||
|
||||
- l’encodage UTF-8 ;
|
||||
- la normalisation Unicode NFC du contenu et du chemin ;
|
||||
- la présence et la validité du front matter TOML ;
|
||||
- l’appartenance à une section connue lorsque le fichier est placé dans un sous-répertoire de `src/content/`.
|
||||
|
||||
Pour les fichiers `_index.md`, il exige un titre non vide.
|
||||
|
||||
Pour les autres pages, `draft` doit être un booléen. Les brouillons ne sont pas soumis aux contrôles de complétude, à l’exception du nom des fiches de signes.
|
||||
|
||||
Pour toute page publiée, il exige un titre non vide. Une date TOML valide est également obligatoire lorsque la page appartient à une section. Les pages permanentes placées directement dans `src/content/`, comme la bibliographie et les mentions légales, n’ont pas besoin de date.
|
||||
|
||||
Pour une fiche de vocabulaire publiée, il contrôle en plus :
|
||||
|
||||
- une seule nature grammaticale connue ;
|
||||
- la présence exacte des champs prévus pour cette nature ;
|
||||
- des chaînes pour les champs simples ;
|
||||
- un tableau de chaînes non vides pour `logograms` ;
|
||||
- un `meaning` non vide ;
|
||||
- un `stem` non vide pour les verbes.
|
||||
|
||||
Pour une fiche de signe publiée, il contrôle le glyphe, le numéro MZL sur trois chiffres et sa correspondance avec le nom du fichier.
|
||||
|
||||
Zola reste responsable de la construction, des liens internes, des taxonomies et du rendu des templates.
|
||||
|
||||
## Principes de cohérence
|
||||
|
||||
- conserver tous les champs prévus par le modèle, même vides ;
|
||||
- ne renseigner que des informations établies ou utiles ;
|
||||
- garder une graphie stable pour chaque lemme, lecture et terme de taxonomie ;
|
||||
- employer `draft = true` pour un contenu incomplet ou temporairement hors ligne ;
|
||||
- n’ajouter `updated` qu’après une modification substantielle ;
|
||||
- éviter de répéter dans le corps une donnée déjà claire dans le front matter, sauf lorsqu’une explication apporte quelque chose ;
|
||||
- rédiger des descriptions courtes et informatives lorsqu’un résumé spécifique est utile ;
|
||||
- ne pas ajouter de rubriques vides ni de textes d’attente.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Les Carnets d’Akkadien
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,28 @@
|
||||
Les Carnets d’Akkadien — Licence des contenus
|
||||
|
||||
Sauf mention contraire, les contenus originaux publiés dans le répertoire
|
||||
src/content/ et sur le site sont mis à disposition sous le nom
|
||||
Les Carnets d’Akkadien selon les termes de la licence :
|
||||
|
||||
Creative Commons Attribution – Partage dans les mêmes conditions 4.0
|
||||
International (CC BY-SA 4.0)
|
||||
|
||||
Résumé de la licence :
|
||||
https://creativecommons.org/licenses/by-sa/4.0/deed.fr
|
||||
|
||||
Code juridique :
|
||||
https://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
Attribution recommandée :
|
||||
« Les Carnets d’Akkadien — CC BY-SA 4.0 »
|
||||
|
||||
Cette licence ne couvre pas :
|
||||
|
||||
- le code du site, distribué séparément sous licence MIT dans LICENSE-CODE ;
|
||||
- les polices, images, citations, reproductions et autres ressources provenant
|
||||
de tiers, qui restent soumises à leurs propres droits et licences ;
|
||||
- les éléments explicitement accompagnés d’une autre mention de licence.
|
||||
|
||||
La licence CC BY-SA 4.0 autorise le partage et l’adaptation du contenu, y compris
|
||||
à des fins commerciales, sous réserve de créditer Les Carnets d’Akkadien, de signaler les
|
||||
modifications et de diffuser les adaptations sous la même licence.
|
||||
@@ -0,0 +1,217 @@
|
||||
# Les Carnets d’Akkadien
|
||||
|
||||
**Les Carnets d’Akkadien** est un site personnel consacré à l’apprentissage de l’akkadien et de l’écriture cunéiforme. Il réunit des fiches de vocabulaire, des signes, des notes de grammaire, des textes étudiés et des articles de parcours.
|
||||
|
||||
Site public : <https://lescarnetsdakkadien.netig.net>
|
||||
|
||||
Le site est construit avec [Zola](https://www.getzola.org/) à partir de fichiers Markdown. Il ne nécessite ni base de données ni interface d’administration : les contenus restent lisibles et modifiables comme de simples fichiers texte.
|
||||
|
||||
## Contenu du site
|
||||
|
||||
| Section | Contenu | Classement complémentaire |
|
||||
|---|---|---|
|
||||
| `articles` | articles sur l’apprentissage et le projet | — |
|
||||
| `grammaire` | notes consacrées aux notions grammaticales | thèmes |
|
||||
| `signes` | signes cunéiformes classés par numéro MZL | lectures |
|
||||
| `textes` | translittérations, traductions et commentaires | genres |
|
||||
| `vocabulaire` | fiches lexicales adaptées à leur nature grammaticale | natures |
|
||||
|
||||
La page d’accueil présente le dernier article et les trois fiches datées les plus récentes parmi les signes, le vocabulaire, la grammaire et les textes. Des flux Atom et RSS sont également générés.
|
||||
|
||||
Les conventions de rédaction et les champs disponibles sont décrits dans le [guide de rédaction](GUIDE_REDACTION.md).
|
||||
|
||||
## Prérequis
|
||||
|
||||
Pour travailler directement sur le projet :
|
||||
|
||||
- Python 3.11 ou ultérieur ;
|
||||
- Zola 0.22.1 ;
|
||||
- Git, si le dépôt est versionné avec Git.
|
||||
|
||||
Pour le déploiement conteneurisé :
|
||||
|
||||
- Docker Engine ;
|
||||
- Docker Compose.
|
||||
|
||||
Toutes les commandes ci-dessous sont exécutées depuis la racine du dépôt.
|
||||
|
||||
## Développement local
|
||||
|
||||
Valider les contenus :
|
||||
|
||||
```sh
|
||||
./scripts/check-content.py
|
||||
```
|
||||
|
||||
Vérifier la construction Zola, brouillons compris :
|
||||
|
||||
```sh
|
||||
zola --root src check --drafts --skip-external-links
|
||||
```
|
||||
|
||||
`--skip-external-links` évite de dépendre du réseau. Retirer cette option pour contrôler aussi les liens externes.
|
||||
|
||||
Lancer le serveur de développement :
|
||||
|
||||
```sh
|
||||
zola --root src serve
|
||||
```
|
||||
|
||||
Afficher également les brouillons :
|
||||
|
||||
```sh
|
||||
zola --root src serve --drafts
|
||||
```
|
||||
|
||||
Construire le site statique :
|
||||
|
||||
```sh
|
||||
zola --root src build
|
||||
```
|
||||
|
||||
Le résultat est écrit dans `src/public/`, répertoire ignoré par Git.
|
||||
|
||||
## Créer un contenu
|
||||
|
||||
Le générateur crée un brouillon horodaté avec le front matter adapté à la section :
|
||||
|
||||
```sh
|
||||
./scripts/new-content.py vocabulaire šarrum --nature nom
|
||||
```
|
||||
|
||||
Exemples :
|
||||
|
||||
```sh
|
||||
./scripts/new-content.py signes 113 --title BE
|
||||
./scripts/new-content.py grammaire suffixes-pronominaux
|
||||
./scripts/new-content.py textes lettre-au-marchand
|
||||
./scripts/new-content.py articles nouvel-article
|
||||
./scripts/new-content.py vocabulaire --nature particule -- -ma
|
||||
```
|
||||
|
||||
Chaque fichier est créé avec :
|
||||
|
||||
- une date au format TOML dans le fuseau `Europe/Paris` ;
|
||||
- `draft = true` ;
|
||||
- tous les champs prévus par son modèle ;
|
||||
- des chaînes vides ou des listes vides pour les données à compléter.
|
||||
|
||||
Le générateur refuse d’écraser un fichier existant. Son aide complète est disponible avec :
|
||||
|
||||
```sh
|
||||
./scripts/new-content.py --help
|
||||
```
|
||||
|
||||
## Publier un contenu
|
||||
|
||||
Le cycle de rédaction recommandé est simple :
|
||||
|
||||
1. créer le brouillon avec `new-content.py` ;
|
||||
2. compléter le front matter et le corps Markdown ;
|
||||
3. vérifier que `date` correspond à la date de publication souhaitée ;
|
||||
4. remplacer `draft = true` par `draft = false` ;
|
||||
5. lancer le validateur et Zola.
|
||||
|
||||
```sh
|
||||
./scripts/check-content.py
|
||||
zola --root src check --drafts --skip-external-links
|
||||
```
|
||||
|
||||
Le validateur contrôle les invariants qui doivent rester vrais indépendamment du rendu :
|
||||
|
||||
- encodage UTF-8 et normalisation Unicode NFC ;
|
||||
- front matter TOML valide ;
|
||||
- section connue et statut de brouillon valide ;
|
||||
- titre des index et des pages publiées ;
|
||||
- date des pages publiées dans une section ;
|
||||
- nom et numéro MZL des fiches de signes ;
|
||||
- nature, champs et types des fiches de vocabulaire publiées.
|
||||
|
||||
Les brouillons peuvent rester incomplets. Le nom `mzl-XXX.md` d’une fiche de signe reste toutefois contrôlé même en brouillon, car il détermine son identité et son URL future.
|
||||
|
||||
Une erreur renvoie un code de sortie non nul et bloque également la construction Docker.
|
||||
|
||||
## Organisation du dépôt
|
||||
|
||||
```text
|
||||
.
|
||||
├── Dockerfile
|
||||
├── compose.yml
|
||||
├── README.md
|
||||
├── GUIDE_REDACTION.md
|
||||
├── LICENSE-CODE
|
||||
├── LICENSE-CONTENT
|
||||
├── scripts
|
||||
│ ├── _schema.py
|
||||
│ ├── check-content.py
|
||||
│ └── new-content.py
|
||||
└── src
|
||||
├── content
|
||||
├── sass
|
||||
├── static
|
||||
├── templates
|
||||
└── zola.toml
|
||||
```
|
||||
|
||||
- `src/content/` contient les pages Markdown ;
|
||||
- `src/templates/` contient les templates Tera ;
|
||||
- `src/sass/main.scss` contient les styles ;
|
||||
- `src/static/` contient les ressources servies telles quelles ;
|
||||
- `src/zola.toml` contient la configuration de Zola ;
|
||||
- `scripts/new-content.py` crée les brouillons ;
|
||||
- `scripts/check-content.py` valide les contenus ;
|
||||
- `scripts/_schema.py` contient les définitions communes aux deux scripts.
|
||||
|
||||
Les chemins et les taxonomies utilisent la stratégie de slugification `safe` de Zola. Les diacritiques sont donc conservés : des lectures comme `tim` et `ṭim` restent distinctes.
|
||||
|
||||
## Déploiement avec Docker Compose
|
||||
|
||||
L’image est construite en trois étapes : validation des contenus, construction avec Zola 0.22.1, puis service du site statique.
|
||||
|
||||
Vérifier la configuration :
|
||||
|
||||
```sh
|
||||
docker compose config
|
||||
```
|
||||
|
||||
Construire et lancer le service :
|
||||
|
||||
```sh
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Consulter son état et ses journaux :
|
||||
|
||||
```sh
|
||||
docker compose ps
|
||||
docker compose logs --tail=100 zola
|
||||
```
|
||||
|
||||
Le service écoute uniquement sur l’interface locale de l’hôte :
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8002
|
||||
```
|
||||
|
||||
Le domaine public et le certificat TLS sont pris en charge par un proxy inverse placé devant le conteneur.
|
||||
|
||||
Mettre à jour le déploiement :
|
||||
|
||||
```sh
|
||||
git pull --ff-only
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Arrêter le service :
|
||||
|
||||
```sh
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## Licences
|
||||
|
||||
Le code propre au projet est distribué sous licence MIT ; voir [`LICENSE-CODE`](LICENSE-CODE).
|
||||
|
||||
Sauf mention contraire, les contenus originaux de `src/content/` sont publiés sous licence CC BY-SA 4.0 ; voir [`LICENSE-CONTENT`](LICENSE-CONTENT).
|
||||
|
||||
Les polices, photographies et autres ressources tierces restent soumises à leurs propres droits et licences.
|
||||
@@ -0,0 +1,8 @@
|
||||
name: les-carnets-d-akkadien
|
||||
|
||||
services:
|
||||
zola:
|
||||
build: .
|
||||
ports:
|
||||
- "127.0.0.1:8002:80"
|
||||
restart: unless-stopped
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Définitions communes au générateur et au validateur de contenus."""
|
||||
|
||||
SECTION_ALIASES = {
|
||||
"article": "articles",
|
||||
"articles": "articles",
|
||||
"grammaire": "grammaire",
|
||||
"signe": "signes",
|
||||
"signes": "signes",
|
||||
"texte": "textes",
|
||||
"textes": "textes",
|
||||
"vocabulaire": "vocabulaire",
|
||||
}
|
||||
|
||||
VOCABULARY_FIELDS = {
|
||||
"nom": ("meaning", "logograms", "gender", "bound", "plural"),
|
||||
"adjectif": (
|
||||
"meaning",
|
||||
"logograms",
|
||||
"bound",
|
||||
"feminine",
|
||||
"masculine_plural",
|
||||
"feminine_plural",
|
||||
"predicative",
|
||||
),
|
||||
"verbe": (
|
||||
"meaning",
|
||||
"logograms",
|
||||
"root",
|
||||
"stem",
|
||||
"verb_class",
|
||||
"vowel_class",
|
||||
"preterite",
|
||||
"durative",
|
||||
"perfect",
|
||||
"imperative",
|
||||
"participle",
|
||||
"verbal_adjective",
|
||||
),
|
||||
"pronom": (
|
||||
"meaning",
|
||||
"logograms",
|
||||
"pronoun_type",
|
||||
"person",
|
||||
"gender",
|
||||
"number",
|
||||
),
|
||||
"préposition": ("meaning", "logograms", "governs"),
|
||||
"adverbe": ("meaning", "logograms", "function"),
|
||||
"conjonction": ("meaning", "logograms", "function"),
|
||||
"particule": ("meaning", "logograms", "function"),
|
||||
"numéral": (
|
||||
"meaning",
|
||||
"logograms",
|
||||
"numeral_type",
|
||||
"value",
|
||||
"gender",
|
||||
"feminine",
|
||||
),
|
||||
}
|
||||
|
||||
KNOWN_SECTIONS = frozenset(SECTION_ALIASES.values())
|
||||
Executable
+286
@@ -0,0 +1,286 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Vérifie la structure des contenus, le vocabulaire et les signes."""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import tomllib
|
||||
import unicodedata
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from _schema import KNOWN_SECTIONS, VOCABULARY_FIELDS
|
||||
|
||||
ROOT_DIR = Path(__file__).resolve().parent.parent
|
||||
CONTENT_DIR = ROOT_DIR / "src" / "content"
|
||||
|
||||
MZL_FILENAME_RE = re.compile(r"mzl-([0-9]{3})\.md")
|
||||
MZL_VALUE_RE = re.compile(r"[0-9]{3}")
|
||||
|
||||
|
||||
class Validator:
|
||||
def __init__(self) -> None:
|
||||
self.errors = 0
|
||||
|
||||
def error(self, path: Path | None, message: str) -> None:
|
||||
if path is None:
|
||||
label = ""
|
||||
else:
|
||||
label = f"{path.relative_to(ROOT_DIR).as_posix()} : "
|
||||
print(f"ERREUR : {label}{message}", file=sys.stderr)
|
||||
self.errors += 1
|
||||
|
||||
def finish(self) -> int:
|
||||
print(f"\nRésultat : {self.errors} erreur(s).")
|
||||
return 1 if self.errors else 0
|
||||
|
||||
|
||||
def is_non_empty_string(value: Any) -> bool:
|
||||
return isinstance(value, str) and bool(value.strip())
|
||||
|
||||
|
||||
def read_front_matter(path: Path, validator: Validator) -> dict[str, Any] | None:
|
||||
try:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
except UnicodeDecodeError as exc:
|
||||
validator.error(path, f"fichier non valide en UTF-8 ({exc})")
|
||||
return None
|
||||
except OSError as exc:
|
||||
validator.error(path, f"lecture impossible ({exc})")
|
||||
return None
|
||||
|
||||
if not unicodedata.is_normalized("NFC", text):
|
||||
validator.error(path, "contenu non normalisé en Unicode NFC")
|
||||
|
||||
lines = text.splitlines()
|
||||
if not lines or lines[0] != "+++":
|
||||
validator.error(path, "front matter TOML initial absent")
|
||||
return None
|
||||
|
||||
try:
|
||||
closing_index = lines.index("+++", 1)
|
||||
except ValueError:
|
||||
validator.error(path, "délimiteur final +++ absent")
|
||||
return None
|
||||
|
||||
try:
|
||||
return tomllib.loads("\n".join(lines[1:closing_index]))
|
||||
except tomllib.TOMLDecodeError as exc:
|
||||
validator.error(path, f"front matter TOML invalide ({exc})")
|
||||
return None
|
||||
|
||||
|
||||
def require_table(
|
||||
metadata: dict[str, Any],
|
||||
key: str,
|
||||
path: Path,
|
||||
validator: Validator,
|
||||
) -> dict[str, Any] | None:
|
||||
value = metadata.get(key)
|
||||
if not isinstance(value, dict):
|
||||
validator.error(path, f"{key} doit être une table TOML")
|
||||
return None
|
||||
return value
|
||||
|
||||
|
||||
def require_string(
|
||||
metadata: dict[str, Any],
|
||||
key: str,
|
||||
path: Path,
|
||||
validator: Validator,
|
||||
) -> None:
|
||||
if not is_non_empty_string(metadata.get(key)):
|
||||
validator.error(path, f"{key} doit être une chaîne non vide")
|
||||
|
||||
|
||||
def require_date(
|
||||
metadata: dict[str, Any],
|
||||
path: Path,
|
||||
validator: Validator,
|
||||
) -> None:
|
||||
if not isinstance(metadata.get("date"), date):
|
||||
validator.error(path, "date doit être une date TOML valide")
|
||||
|
||||
|
||||
def check_structure(
|
||||
path: Path,
|
||||
metadata: dict[str, Any],
|
||||
validator: Validator,
|
||||
) -> tuple[str, bool] | None:
|
||||
relative_path = path.relative_to(CONTENT_DIR)
|
||||
section = relative_path.parts[0] if len(relative_path.parts) > 1 else ""
|
||||
|
||||
if not unicodedata.is_normalized("NFC", relative_path.as_posix()):
|
||||
validator.error(path, "chemin non normalisé en Unicode NFC")
|
||||
|
||||
if section and section not in KNOWN_SECTIONS:
|
||||
validator.error(path, f"section inconnue « {section} »")
|
||||
|
||||
if path.name == "_index.md":
|
||||
require_string(metadata, "title", path, validator)
|
||||
return None
|
||||
|
||||
draft = metadata.get("draft")
|
||||
if not isinstance(draft, bool):
|
||||
validator.error(path, "draft doit être un booléen")
|
||||
return None
|
||||
|
||||
if draft:
|
||||
return section, True
|
||||
|
||||
require_string(metadata, "title", path, validator)
|
||||
if section:
|
||||
require_date(metadata, path, validator)
|
||||
return section, False
|
||||
|
||||
|
||||
def vocabulary_nature(
|
||||
metadata: dict[str, Any],
|
||||
path: Path,
|
||||
validator: Validator,
|
||||
) -> str | None:
|
||||
taxonomies = require_table(metadata, "taxonomies", path, validator)
|
||||
if taxonomies is None:
|
||||
return None
|
||||
|
||||
natures = taxonomies.get("natures")
|
||||
if not isinstance(natures, list) or len(natures) != 1:
|
||||
validator.error(path, "taxonomies.natures doit contenir exactement une nature")
|
||||
return None
|
||||
|
||||
nature = natures[0]
|
||||
if not isinstance(nature, str):
|
||||
validator.error(path, "taxonomies.natures doit contenir une chaîne")
|
||||
return None
|
||||
|
||||
if nature not in VOCABULARY_FIELDS:
|
||||
validator.error(path, f"nature grammaticale inconnue « {nature} »")
|
||||
return None
|
||||
|
||||
return nature
|
||||
|
||||
|
||||
def check_vocabulary(
|
||||
path: Path,
|
||||
metadata: dict[str, Any],
|
||||
validator: Validator,
|
||||
) -> None:
|
||||
nature = vocabulary_nature(metadata, path, validator)
|
||||
extra = require_table(metadata, "extra", path, validator)
|
||||
if nature is None or extra is None:
|
||||
return
|
||||
|
||||
expected_fields = VOCABULARY_FIELDS[nature]
|
||||
expected_keys = set(expected_fields)
|
||||
actual_keys = set(extra)
|
||||
|
||||
missing_fields = [field for field in expected_fields if field not in actual_keys]
|
||||
if missing_fields:
|
||||
validator.error(
|
||||
path,
|
||||
"champs extra manquants pour "
|
||||
f"la nature « {nature} » : {', '.join(missing_fields)}",
|
||||
)
|
||||
|
||||
unexpected_fields = sorted(actual_keys - expected_keys)
|
||||
if unexpected_fields:
|
||||
validator.error(
|
||||
path,
|
||||
"champs extra inattendus pour "
|
||||
f"la nature « {nature} » : {', '.join(unexpected_fields)}",
|
||||
)
|
||||
|
||||
for field in expected_fields:
|
||||
if field not in extra:
|
||||
continue
|
||||
|
||||
value = extra[field]
|
||||
if field == "logograms":
|
||||
if not isinstance(value, list) or not all(
|
||||
is_non_empty_string(item) for item in value
|
||||
):
|
||||
validator.error(
|
||||
path,
|
||||
"extra.logograms doit être un tableau de chaînes non vides",
|
||||
)
|
||||
elif not isinstance(value, str):
|
||||
validator.error(path, f"extra.{field} doit être une chaîne")
|
||||
|
||||
required_fields = ("meaning", "stem") if nature == "verbe" else ("meaning",)
|
||||
for field in required_fields:
|
||||
value = extra.get(field)
|
||||
if isinstance(value, str) and not value.strip():
|
||||
validator.error(path, f"extra.{field} doit être une chaîne non vide")
|
||||
|
||||
|
||||
def filename_mzl(path: Path, validator: Validator) -> str | None:
|
||||
match = MZL_FILENAME_RE.fullmatch(path.name)
|
||||
if match is None:
|
||||
validator.error(path, "le nom du fichier doit suivre le format mzl-XXX.md")
|
||||
return None
|
||||
|
||||
value = match.group(1)
|
||||
if int(value) == 0:
|
||||
validator.error(path, "le numéro MZL doit être compris entre 001 et 999")
|
||||
return None
|
||||
return value
|
||||
|
||||
|
||||
def check_sign(
|
||||
path: Path,
|
||||
metadata: dict[str, Any],
|
||||
expected_mzl: str | None,
|
||||
validator: Validator,
|
||||
) -> None:
|
||||
extra = require_table(metadata, "extra", path, validator)
|
||||
if extra is None:
|
||||
return
|
||||
|
||||
require_string(extra, "sign", path, validator)
|
||||
|
||||
declared_mzl = extra.get("mzl")
|
||||
if not isinstance(declared_mzl, str) or MZL_VALUE_RE.fullmatch(declared_mzl) is None:
|
||||
validator.error(path, "extra.mzl doit être une chaîne de trois chiffres ASCII")
|
||||
return
|
||||
if int(declared_mzl) == 0:
|
||||
validator.error(path, "extra.mzl doit être compris entre 001 et 999")
|
||||
return
|
||||
if expected_mzl is not None and declared_mzl != expected_mzl:
|
||||
validator.error(
|
||||
path,
|
||||
f'extra.mzl vaut "{declared_mzl}", mais le fichier indique MZL {expected_mzl}',
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
validator = Validator()
|
||||
|
||||
if not CONTENT_DIR.is_dir():
|
||||
validator.error(None, f"répertoire introuvable : {CONTENT_DIR}")
|
||||
return validator.finish()
|
||||
|
||||
print("Vérification des contenus…", flush=True)
|
||||
for path in sorted(CONTENT_DIR.rglob("*.md")):
|
||||
metadata = read_front_matter(path, validator)
|
||||
if metadata is None:
|
||||
continue
|
||||
|
||||
structure = check_structure(path, metadata, validator)
|
||||
if structure is None:
|
||||
continue
|
||||
|
||||
section, is_draft = structure
|
||||
expected_mzl = filename_mzl(path, validator) if section == "signes" else None
|
||||
if is_draft:
|
||||
continue
|
||||
|
||||
if section == "vocabulaire":
|
||||
check_vocabulary(path, metadata, validator)
|
||||
elif section == "signes":
|
||||
check_sign(path, metadata, expected_mzl, validator)
|
||||
|
||||
return validator.finish()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Executable
+268
@@ -0,0 +1,268 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Crée un brouillon Markdown adapté à une section du site."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import unicodedata
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
||||
|
||||
from _schema import SECTION_ALIASES, VOCABULARY_FIELDS
|
||||
|
||||
ROOT_DIR = Path(__file__).resolve().parent.parent
|
||||
CONTENT_DIR = ROOT_DIR / "src" / "content"
|
||||
TIMEZONE_NAME = "Europe/Paris"
|
||||
|
||||
MZL_RE = re.compile(r"(?:mzl-)?([0-9]{1,3})")
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Créer un brouillon Markdown horodaté et prêt à compléter."
|
||||
)
|
||||
parser.add_argument(
|
||||
"section",
|
||||
choices=sorted(SECTION_ALIASES),
|
||||
help="section de destination",
|
||||
)
|
||||
parser.add_argument(
|
||||
"identifiant",
|
||||
help="nom du fichier sans .md ; pour un signe, numéro MZL ou mzl-XXX",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--title",
|
||||
help="titre initial ; déduit de l’identifiant par défaut",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--nature",
|
||||
choices=tuple(VOCABULARY_FIELDS),
|
||||
help="nature grammaticale d’une fiche de vocabulaire",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def normalize(value: str) -> str:
|
||||
return unicodedata.normalize("NFC", value.strip())
|
||||
|
||||
|
||||
def toml_string(value: str) -> str:
|
||||
return json.dumps(value, ensure_ascii=False)
|
||||
|
||||
|
||||
def current_timestamp() -> str:
|
||||
try:
|
||||
timezone = ZoneInfo(TIMEZONE_NAME)
|
||||
except ZoneInfoNotFoundError as exc:
|
||||
raise RuntimeError(
|
||||
f"fuseau {TIMEZONE_NAME} indisponible ; installer les données de fuseaux horaires"
|
||||
) from exc
|
||||
return datetime.now(timezone).isoformat(timespec="seconds")
|
||||
|
||||
|
||||
def validate_identifier(identifier: str, *, allow_leading_hyphen: bool = False) -> str:
|
||||
"""Valide un identifiant déjà écrit sous sa forme de nom de fichier."""
|
||||
value = normalize(identifier)
|
||||
if value.startswith("-") and not allow_leading_hyphen:
|
||||
raise ValueError("seul le vocabulaire accepte un identifiant commençant par un tiret")
|
||||
|
||||
body = value[1:] if value.startswith("-") else value
|
||||
if not body or value in {".", "..", "_index"}:
|
||||
raise ValueError("identifiant de fichier invalide")
|
||||
if value != value.lower():
|
||||
raise ValueError("l’identifiant doit être écrit en minuscules")
|
||||
if value.endswith("-") or "--" in value:
|
||||
raise ValueError(
|
||||
"l’identifiant ne doit pas finir par un tiret ni en contenir deux de suite"
|
||||
)
|
||||
if not all(character.isalnum() or character == "-" for character in body):
|
||||
raise ValueError(
|
||||
"l’identifiant ne doit contenir que des lettres, des chiffres et des tirets"
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
def parse_mzl(identifier: str) -> tuple[str, str]:
|
||||
value = normalize(identifier)
|
||||
match = MZL_RE.fullmatch(value)
|
||||
if match is None:
|
||||
raise ValueError(
|
||||
"un signe doit être identifié par un numéro MZL de un à trois chiffres ASCII"
|
||||
)
|
||||
|
||||
number = int(match.group(1))
|
||||
if not 1 <= number <= 999:
|
||||
raise ValueError("le numéro MZL doit être compris entre 1 et 999")
|
||||
|
||||
mzl = f"{number:03d}"
|
||||
return f"mzl-{mzl}", mzl
|
||||
|
||||
|
||||
def choose_nature(nature: str | None) -> str:
|
||||
if nature:
|
||||
return nature
|
||||
if not sys.stdin.isatty():
|
||||
raise ValueError("--nature est requis pour une fiche de vocabulaire")
|
||||
|
||||
choices = tuple(VOCABULARY_FIELDS)
|
||||
print("Nature grammaticale :")
|
||||
for index, choice in enumerate(choices, start=1):
|
||||
print(f" {index}. {choice}")
|
||||
|
||||
try:
|
||||
answer = input("Choix : ").strip()
|
||||
except (EOFError, KeyboardInterrupt) as exc:
|
||||
raise ValueError("sélection interrompue") from exc
|
||||
|
||||
if not answer.isdigit() or not 1 <= int(answer) <= len(choices):
|
||||
raise ValueError("nature grammaticale invalide")
|
||||
return choices[int(answer) - 1]
|
||||
|
||||
|
||||
def title_from_identifier(identifier: str) -> str:
|
||||
title = identifier.replace("-", " ")
|
||||
return title[:1].upper() + title[1:]
|
||||
|
||||
|
||||
def build_vocabulary(title: str, timestamp: str, nature: str) -> str:
|
||||
fields = "\n".join(
|
||||
f"{field} = []" if field == "logograms" else f'{field} = ""'
|
||||
for field in VOCABULARY_FIELDS[nature]
|
||||
)
|
||||
return f"""+++
|
||||
title = {toml_string(title)}
|
||||
date = {timestamp}
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[extra]
|
||||
{fields}
|
||||
|
||||
[taxonomies]
|
||||
natures = [{toml_string(nature)}]
|
||||
+++
|
||||
"""
|
||||
|
||||
|
||||
def build_sign(title: str, timestamp: str, mzl: str) -> str:
|
||||
return f"""+++
|
||||
title = {toml_string(title)}
|
||||
date = {timestamp}
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[extra]
|
||||
sign = ""
|
||||
mzl = "{mzl}"
|
||||
|
||||
[taxonomies]
|
||||
lectures = []
|
||||
+++
|
||||
"""
|
||||
|
||||
|
||||
def build_page(section: str, title: str, timestamp: str) -> str:
|
||||
if section == "articles":
|
||||
return f"""+++
|
||||
title = {toml_string(title)}
|
||||
date = {timestamp}
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[extra]
|
||||
banner = ""
|
||||
banner_alt = ""
|
||||
banner_credit = ""
|
||||
+++
|
||||
"""
|
||||
|
||||
if section == "grammaire":
|
||||
return f"""+++
|
||||
title = {toml_string(title)}
|
||||
date = {timestamp}
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
themes = []
|
||||
+++
|
||||
"""
|
||||
|
||||
if section == "textes":
|
||||
return f"""+++
|
||||
title = {toml_string(title)}
|
||||
date = {timestamp}
|
||||
description = ""
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
genres = []
|
||||
+++
|
||||
"""
|
||||
|
||||
raise ValueError(f"section non prise en charge : {section}")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
section = SECTION_ALIASES[args.section]
|
||||
|
||||
try:
|
||||
if section != "vocabulaire" and args.nature is not None:
|
||||
raise ValueError("--nature est réservé aux fiches de vocabulaire")
|
||||
|
||||
timestamp = current_timestamp()
|
||||
custom_title = normalize(args.title) if args.title is not None else None
|
||||
|
||||
if section == "signes":
|
||||
filename, mzl = parse_mzl(args.identifiant)
|
||||
title = custom_title if custom_title is not None else ""
|
||||
content = build_sign(title, timestamp, mzl)
|
||||
else:
|
||||
filename = validate_identifier(
|
||||
args.identifiant,
|
||||
allow_leading_hyphen=section == "vocabulaire",
|
||||
)
|
||||
if section == "vocabulaire":
|
||||
nature = choose_nature(args.nature)
|
||||
title = custom_title if custom_title is not None else filename
|
||||
content = build_vocabulary(title, timestamp, nature)
|
||||
else:
|
||||
title = (
|
||||
custom_title
|
||||
if custom_title is not None
|
||||
else title_from_identifier(filename)
|
||||
)
|
||||
content = build_page(section, title, timestamp)
|
||||
except (ValueError, RuntimeError) as exc:
|
||||
print(f"Erreur : {exc}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
destination = CONTENT_DIR / section / f"{filename}.md"
|
||||
try:
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
with destination.open("x", encoding="utf-8") as stream:
|
||||
stream.write(content)
|
||||
except FileExistsError:
|
||||
print(
|
||||
f"Erreur : le fichier existe déjà : {destination.relative_to(ROOT_DIR)}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
except OSError as exc:
|
||||
print(
|
||||
f"Erreur : impossible de créer {destination.relative_to(ROOT_DIR)} ({exc})",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
print(f"Brouillon créé : {destination.relative_to(ROOT_DIR)}")
|
||||
print("Compléter la fiche, passer draft à false, puis lancer :")
|
||||
print(" ./scripts/check-content.py")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "Les Carnets d’Akkadien"
|
||||
description = "Un site consacré à l’apprentissage de la langue akkadienne et de l’écriture cunéiforme."
|
||||
+++
|
||||
|
||||
## Lire l’argile
|
||||
|
||||
Restées enfouies pendant des millénaires, les tablettes cunéiformes ont conservé, dans plusieurs langues, des lettres, des contrats, des récits et d’innombrables traces de la vie quotidienne en Mésopotamie.
|
||||
|
||||
Parmi ces langues, l’akkadien occupe une place majeure.
|
||||
|
||||
L’apprendre, c’est entrer peu à peu dans la lecture de ces textes, retrouver des voix venues du passé et découvrir ce qu’elles ont encore à nous raconter.
|
||||
|
||||
Les Carnets d’Akkadien tiennent le journal de mon apprentissage et de mes découvertes, au fil des signes, des mots et des textes — bonne lecture !
|
||||
@@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "Articles"
|
||||
description = "Réflexions et retours d’expérience sur l’apprentissage de l’akkadien."
|
||||
sort_by = "date"
|
||||
template = "articles.html"
|
||||
page_template = "page.html"
|
||||
|
||||
[extra]
|
||||
back_label = "Retour aux articles"
|
||||
+++
|
||||
@@ -0,0 +1,19 @@
|
||||
+++
|
||||
title = "Les Carnets sont en ligne !"
|
||||
date = 2026-07-29T10:09:28+02:00
|
||||
description = "Ou comment le bazar de mes notes a donné naissance à ce site."
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
banner = "images/articles/le-carnet-est-en-ligne.webp"
|
||||
banner_alt = "Une pile de cahiers et de feuilles aux pages usées"
|
||||
banner_credit = "Photographie : John-Mark Kuznietsov — Pexels"
|
||||
+++
|
||||
|
||||
J’ai commencé à apprendre l’akkadien à la mi-avril avec *A Grammar of Akkadian* de John Huehnergard. Leçon après leçon, me voici arrivé, trois mois plus tard, à la neuvième leçon tant attendue : celle des premiers signes cunéiformes.
|
||||
|
||||
Une nouvelle étape s’ouvre, faite de signes à reconnaître, à mémoriser et à tracer — et de nouvelles notes qui viennent s’ajouter aux feuilles et aux cahiers déjà bien encombrés !
|
||||
|
||||
D’où l’idée de créer *Les Carnets d’Akkadien* : un endroit où rassembler mes notes pour mieux m’y retrouver et pouvoir les consulter où que je sois. Le contenu est encore modeste, mais le site est fonctionnel. Il ne me reste plus qu’à replonger dans mes papiers et à remplir peu à peu les fiches.
|
||||
|
||||
Le site s’enrichira ainsi au fil de mon apprentissage. J’espère qu’avec le temps, ces carnets pourront aussi être utiles à d’autres. L’aventure ne fait que commencer !
|
||||
@@ -0,0 +1,25 @@
|
||||
+++
|
||||
title = "Bibliographie"
|
||||
draft = false
|
||||
description = "Ouvrages de référence utilisés pour l’étude de l’akkadien."
|
||||
+++
|
||||
|
||||
Cette bibliographie rassemble les principaux ouvrages utilisés pour préparer
|
||||
les fiches et les notes du site. Elle n’a pas vocation à être exhaustive.
|
||||
|
||||
## Grammaire
|
||||
|
||||
- **Huehnergard, John.** *A Grammar of Akkadian*. 3e éd.
|
||||
Harvard Semitic Studies 45. Winona Lake (Indiana) : Eisenbrauns, 2011.
|
||||
|
||||
## Signes cunéiformes
|
||||
|
||||
- **Borger, Rykle.** *Mesopotamisches Zeichenlexikon* (**MZL**).
|
||||
2e éd. revue et mise à jour. Alter Orient und Altes Testament 305.
|
||||
Münster : Ugarit-Verlag, 2010.
|
||||
|
||||
## Dictionnaire
|
||||
|
||||
- **Black, Jeremy, Andrew George et Nicholas Postgate (dir.).**
|
||||
*A Concise Dictionary of Akkadian* (**CDA**). 2e éd. corrigée.
|
||||
SANTAG 5. Wiesbaden : Harrassowitz Verlag, 2000.
|
||||
@@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "Grammaire"
|
||||
description = "Notions de grammaire étudiées, avec leurs règles et leurs exemples."
|
||||
sort_by = "title"
|
||||
template = "grammaire.html"
|
||||
page_template = "page.html"
|
||||
|
||||
[extra]
|
||||
back_label = "Retour à la grammaire"
|
||||
+++
|
||||
@@ -0,0 +1,27 @@
|
||||
+++
|
||||
title = "La forme liée"
|
||||
date = 2026-07-28T11:35:06+02:00
|
||||
description = "Fiche d’exemple consacrée à la forme liée du nom akkadien."
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
themes = ["morphologie nominale"]
|
||||
+++
|
||||
|
||||
> Cette fiche factice sert à vérifier la présentation des notes de grammaire.
|
||||
|
||||
## Principe
|
||||
|
||||
La forme liée, ou *status constructus*, est employée lorsqu’un nom est directement
|
||||
suivi de son complément au génitif.
|
||||
|
||||
## Exemple
|
||||
|
||||
| Forme indépendante | Forme liée | Groupe nominal |
|
||||
|---|---|---|
|
||||
| *bītum* | *bīt* | *bīt šarrim* — « la maison du roi » |
|
||||
|
||||
## Remarque
|
||||
|
||||
La formation exacte dépend du type de nom. Cette fiche pourra être remplacée par une
|
||||
note plus complète au fil de l’apprentissage.
|
||||
@@ -0,0 +1,18 @@
|
||||
+++
|
||||
title = "Mentions légales"
|
||||
draft = false
|
||||
description = "Informations légales relatives au site web Les Carnets d’Akkadien."
|
||||
+++
|
||||
|
||||
## Édition
|
||||
|
||||
Les Carnets d’Akkadien est un site personnel édité à titre non professionnel.
|
||||
|
||||
## Hébergement
|
||||
|
||||
Le site est hébergé par :
|
||||
|
||||
**Hetzner Online GmbH**
|
||||
Industriestr. 25
|
||||
91710 Gunzenhausen
|
||||
Allemagne
|
||||
@@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "Signes cunéiformes"
|
||||
description = "Signes étudiés, avec leurs lectures et leurs principaux usages."
|
||||
sort_by = "slug"
|
||||
template = "signes.html"
|
||||
page_template = "signe.html"
|
||||
|
||||
[extra]
|
||||
back_label = "Retour aux signes cunéiformes"
|
||||
+++
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "AŠ"
|
||||
date = 2026-07-28T13:23:24+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒀸"
|
||||
mzl = "001"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["aš", "rum"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "ḪAL"
|
||||
date = 2026-07-30T14:29:32+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒄬"
|
||||
mzl = "003"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["ḫal"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "AN"
|
||||
date = 2026-07-31T14:04:03+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒀭"
|
||||
mzl = "010"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["an"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "BA"
|
||||
date = 2026-07-30T15:48:16+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒁀"
|
||||
mzl = "014"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["ba"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "LA"
|
||||
date = 2026-07-31T12:20:49+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒆷"
|
||||
mzl = "089"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["la"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "MAḪ"
|
||||
date = 2026-07-30T15:00:43+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒈤"
|
||||
mzl = "091"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["maḫ"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "MU"
|
||||
date = 2026-07-31T10:17:36+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒈬"
|
||||
mzl = "098"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["mu"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "NA"
|
||||
date = 2026-07-31T11:36:48+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒈾"
|
||||
mzl = "110"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["na"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "NU"
|
||||
date = 2026-07-31T12:41:08+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒉡"
|
||||
mzl = "112"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["nu"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "BE"
|
||||
date = 2026-07-31T19:43:12+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒁁"
|
||||
mzl = "113"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["be", "bad", "bat", "baṭ", "til"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
+++
|
||||
title = "TIM"
|
||||
date = 2026-07-31T19:25:30+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
sign = "𒁴"
|
||||
mzl = "167"
|
||||
|
||||
[taxonomies]
|
||||
lectures = ["dim", "tim", "ṭim"]
|
||||
+++
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "Textes"
|
||||
description = "Textes étudiés, avec leurs translittérations, traductions et commentaires."
|
||||
sort_by = "title"
|
||||
template = "textes.html"
|
||||
page_template = "texte.html"
|
||||
|
||||
[extra]
|
||||
back_label = "Retour aux textes"
|
||||
+++
|
||||
@@ -0,0 +1,28 @@
|
||||
+++
|
||||
title = "Lettre d’exemple"
|
||||
date = 2026-07-28T18:40:02+02:00
|
||||
description = "Court texte fictif destiné à tester la présentation des translittérations, traductions et commentaires."
|
||||
draft = true
|
||||
|
||||
[taxonomies]
|
||||
genres = ["lettre"]
|
||||
+++
|
||||
|
||||
> Ce texte est un exemple de mise en page et ne correspond pas à une tablette publiée.
|
||||
|
||||
## Translittération
|
||||
|
||||
1. *a-na be-lí-ia*
|
||||
2. *qí-bi-ma*
|
||||
3. *um-ma PN-ma*
|
||||
4. […]
|
||||
|
||||
## Traduction
|
||||
|
||||
À mon seigneur, dis : ainsi parle Untel. […]
|
||||
|
||||
## Commentaire
|
||||
|
||||
Cet exemple reprend la structure conventionnelle d’une lettre paléo-babylonienne :
|
||||
le destinataire est introduit par *ana … qibīma*, puis l’expéditeur par *umma …-ma*.
|
||||
Il sert uniquement à vérifier le rendu des différentes parties d’une fiche de texte.
|
||||
@@ -0,0 +1,26 @@
|
||||
+++
|
||||
title = "-ma"
|
||||
date = 2026-08-03T19:37:21+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "et ; et alors ; puis"
|
||||
logograms = []
|
||||
function = "coordination de propositions logiquement liées"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["particule"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*-ma* est une particule enclitique attachée à une forme verbale finie ou à un autre prédicat. Elle relie normalement deux propositions dont les verbes sont au même mode.
|
||||
|
||||
Les propositions ainsi reliées entretiennent un rapport logique : la première présente souvent les circonstances ou les conditions conduisant à l’action exprimée par la seconde. L’élément principal de l’énoncé se trouve donc généralement dans la seconde proposition, et l’ordre des deux propositions ne peut pas être librement inversé.
|
||||
|
||||
Selon le contexte, *-ma* peut notamment être traduit par « et », « et alors », « puis », « et donc » ou parfois « mais ».
|
||||
|
||||
## Morphologie
|
||||
|
||||
Lorsqu’il est ajouté, *-ma* entraîne l’allongement d’une voyelle finale brève. Un *n* final s’assimile normalement à son *m* ; les consonnes *b* et, plus rarement, *p* peuvent également s’assimiler.
|
||||
@@ -0,0 +1,10 @@
|
||||
+++
|
||||
title = "Vocabulaire"
|
||||
description = "Mots étudiés, avec leurs formes et leurs principaux sens."
|
||||
sort_by = "title"
|
||||
template = "vocabulaire.html"
|
||||
page_template = "mot.html"
|
||||
|
||||
[extra]
|
||||
back_label = "Retour au vocabulaire"
|
||||
+++
|
||||
@@ -0,0 +1,23 @@
|
||||
+++
|
||||
title = "anāku"
|
||||
date = 2026-08-03T09:19:49+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "je ; moi"
|
||||
logograms = []
|
||||
pronoun_type = "personnel indépendant"
|
||||
person = "1re personne"
|
||||
gender = "commun"
|
||||
number = "singulier"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["pronom"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*anāku* est le pronom personnel indépendant de première personne du singulier, commun aux deux genres.
|
||||
|
||||
Il s’emploie comme sujet d’une proposition sans verbe. Dans une proposition verbale, où la personne est déjà indiquée par la forme du verbe, il peut notamment servir à mettre le sujet en relief.
|
||||
@@ -0,0 +1,24 @@
|
||||
+++
|
||||
title = "bītum"
|
||||
date = 2026-07-28T15:32:28+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "maison"
|
||||
logograms = []
|
||||
gender = "masculin"
|
||||
bound = "bīt(i)"
|
||||
plural = "bītātum"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["nom"]
|
||||
+++
|
||||
|
||||
## Déclinaison
|
||||
|
||||
| Cas | Singulier | Pluriel |
|
||||
|---|---|---|
|
||||
| Nominatif | *bītum* | *bītātum* |
|
||||
| Génitif | *bītim* | *bītātim* |
|
||||
| Accusatif | *bītam* | *bītātim* |
|
||||
@@ -0,0 +1,31 @@
|
||||
+++
|
||||
title = "damqum"
|
||||
date = 2026-08-03T19:13:17+02:00
|
||||
updated = 2026-08-05
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "bon, de bonne qualité ; beau ; favorable"
|
||||
logograms = []
|
||||
bound = "damiq"
|
||||
feminine = "damiqtum"
|
||||
masculine_plural = "damqūtum"
|
||||
feminine_plural = "damqātum"
|
||||
predicative = "damiq"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["adjectif"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*damqum* signifie principalement « bon » ou « de bonne qualité ». Selon le contexte, il peut aussi qualifier ce qui est beau, favorable ou approprié.
|
||||
|
||||
Appliqué à une personne, il peut exprimer une qualité positive ou la compétence ; appliqué à une chose ou à une situation, il indique notamment la bonne qualité ou un caractère favorable.
|
||||
|
||||
## Morphologie
|
||||
|
||||
*damqum* est l’adjectif verbal de *damāqum*, « devenir bon, s’améliorer ». Sa base est *damiq-*.
|
||||
|
||||
La forme *damiq* correspond à la forme liée ainsi qu’au prédicatif de troisième personne masculine du singulier.
|
||||
@@ -0,0 +1,23 @@
|
||||
+++
|
||||
title = "ina"
|
||||
date = 2026-08-03T10:58:47+02:00
|
||||
updated = 2026-08-05
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "dans, sur ; parmi ; avec, par ; de, depuis"
|
||||
logograms = []
|
||||
governs = "génitif"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["préposition"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*ina* est une préposition très fréquente. Elle peut exprimer le lieu ou la position, avec les sens « dans » ou « sur », ainsi que l’appartenance à un ensemble, « parmi ».
|
||||
|
||||
Selon le contexte, elle peut également indiquer le moyen ou l’instrument, « avec » ou « par », l’origine ou le point de départ, « de » ou « depuis », ainsi qu’une circonstance temporelle ou causale.
|
||||
|
||||
Le nom ou le groupe nominal qui suit *ina* est au génitif.
|
||||
@@ -0,0 +1,23 @@
|
||||
+++
|
||||
title = "ištēn"
|
||||
date = 2026-08-03T16:43:23+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "un"
|
||||
logograms = []
|
||||
numeral_type = "cardinal"
|
||||
value = "1"
|
||||
gender = "masculin"
|
||||
feminine = "išteat"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["numéral"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*ištēn* est un numéral cardinal. Il s’emploie avec un nom masculin et *išteat* avec un nom féminin.
|
||||
|
||||
Le numéral « un » apparaît presque toujours à l’état absolu et le nom compté reste au singulier.
|
||||
@@ -0,0 +1,29 @@
|
||||
+++
|
||||
title = "narkabtum"
|
||||
date = 2026-07-31T15:46:34+02:00
|
||||
updated = 2026-08-05
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "char, notamment char de guerre"
|
||||
logograms = []
|
||||
gender = "féminin"
|
||||
bound = "narkabti"
|
||||
plural = "narkabātum"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["nom"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*narkabtum* désigne un char. Le mot s’emploie notamment pour le char de guerre, mais peut aussi désigner un véhicule utilisé pour la chasse, les cérémonies ou le culte selon le contexte.
|
||||
|
||||
## Déclinaison
|
||||
|
||||
| Cas | Singulier | Pluriel |
|
||||
|---|---|---|
|
||||
| Nominatif | *narkabtum* | *narkabātum* |
|
||||
| Génitif | *narkabtim* | *narkabātim* |
|
||||
| Accusatif | *narkabtam* | *narkabātim* |
|
||||
@@ -0,0 +1,34 @@
|
||||
+++
|
||||
title = "narûm"
|
||||
date = 2026-08-03T20:00:00+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "stèle"
|
||||
logograms = []
|
||||
gender = "masculin"
|
||||
bound = "naru"
|
||||
plural = "narû"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["nom"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*narûm* désigne une stèle portant une inscription destinée à être rendue publique, notamment un décret ou une inscription royale. À des périodes plus tardives, le terme peut aussi désigner une borne inscrite.
|
||||
|
||||
## Morphologie
|
||||
|
||||
*narûm* est un nom masculin à base finale faible *naru- / narā-*. Sa forme liée est *naru* et son pluriel nominatif *narû*.
|
||||
|
||||
Il s’agit d’un emprunt au sumérien. Le mot ne doit pas être confondu avec *nārum*, nom féminin signifiant « rivière, cours d’eau, canal ».
|
||||
|
||||
## Déclinaison
|
||||
|
||||
| Cas | Singulier | Pluriel |
|
||||
|---|---|---|
|
||||
| Nominatif | *narûm* | *narû* |
|
||||
| Génitif | *narêm* | *narê* |
|
||||
| Accusatif | *narâm* | *narê* |
|
||||
@@ -0,0 +1,40 @@
|
||||
+++
|
||||
title = "nasākum"
|
||||
date = 2026-08-03T19:40:00+02:00
|
||||
updated = 2026-08-05
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "jeter, lancer, projeter ; entasser (du grain)"
|
||||
logograms = []
|
||||
root = "n-s-k"
|
||||
stem = "G"
|
||||
verb_class = "I-n"
|
||||
vowel_class = "u/u"
|
||||
preterite = "issuk"
|
||||
durative = "inassuk"
|
||||
perfect = "ittasuk"
|
||||
imperative = "usuk"
|
||||
participle = "nāsikum"
|
||||
verbal_adjective = "nasikum"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["verbe"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*nasākum* signifie principalement « jeter », « lancer » ou « projeter ». Il peut notamment s’employer pour jeter quelque chose à terre ou dans un lieu, laisser tomber ou déposer une charge, lancer un projectile ou rejeter un objet.
|
||||
|
||||
Le verbe peut aussi signifier « mettre en tas » ou « entasser », en particulier à propos du grain. Avec *ana*, il indique souvent la direction ou la destination de ce qui est jeté. L’expression *kirbānam nasākum*, littéralement « jeter une motte », peut décrire l’érosion d’un terrain.
|
||||
|
||||
## Morphologie
|
||||
|
||||
Verbe I-n de classe vocalique u/u. La première radicale *n* s’assimile dans plusieurs formes : *issuk* au prétérit et *ittasuk* au parfait ; elle demeure visible au duratif *inassuk*.
|
||||
|
||||
Le participe *nāsikum* et l’adjectif verbal *nasikum* se distinguent par la longueur de la première voyelle. Le participe désigne l’auteur de l’action, tandis que l’adjectif verbal exprime l’état résultant.
|
||||
|
||||
## Thèmes dérivés
|
||||
|
||||
Au thème Š, *šussukum* signifie notamment « enlever », « rejeter » ou « annuler ».
|
||||
@@ -0,0 +1,40 @@
|
||||
+++
|
||||
title = "parāsum"
|
||||
date = 2026-08-03T13:12:16+02:00
|
||||
updated = 2026-08-05
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "couper, diviser, séparer ; sélectionner ; décider"
|
||||
logograms = []
|
||||
root = "p-r-s"
|
||||
stem = "G"
|
||||
verb_class = "fort"
|
||||
vowel_class = "a/u"
|
||||
preterite = "iprus"
|
||||
durative = "iparras"
|
||||
perfect = "iptaras"
|
||||
imperative = "purus"
|
||||
participle = "pārisum"
|
||||
verbal_adjective = "parsum"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["verbe"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*parāsum* signifie d’abord « couper », « diviser » ou « séparer ». Selon le contexte, il peut exprimer le fait de détacher une partie d’un ensemble, de sélectionner une personne, un animal ou un bien, de tenir quelqu’un ou quelque chose à l’écart, ou encore d’interrompre ou de bloquer une action.
|
||||
|
||||
Dans les contextes administratifs et juridiques, le verbe signifie « décider », « trancher » ou « rendre une décision ». L’expression *warkatam parāsum* désigne l’examen ou l’établissement des faits d’une affaire ; *purussam parāsum* signifie « prononcer une décision » ou « rendre un verdict ».
|
||||
|
||||
## Morphologie
|
||||
|
||||
Verbe fort au thème G, de classe vocalique a/u. Sa conjugaison est régulière : le duratif *iparras* présente la voyelle *a*, tandis que le prétérit *iprus* présente la voyelle *u* ; le parfait est *iptaras* et l’impératif *purus*.
|
||||
|
||||
Le participe *pārisum* désigne celui qui sépare ou qui décide. L’adjectif verbal *parsum* exprime l’état de ce qui est séparé, divisé ou distinct.
|
||||
|
||||
## Thèmes dérivés
|
||||
|
||||
Au thème D, *purrusum* peut signifier « couper, séparer », « diviser » ou « interrompre », mais aussi « établir les faits » ou « décider » selon le contexte.
|
||||
@@ -0,0 +1,22 @@
|
||||
+++
|
||||
title = "u"
|
||||
date = 2026-08-03T10:06:00+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "et"
|
||||
logograms = []
|
||||
function = "coordination"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["conjonction"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*u* est une conjonction indépendante servant à relier des groupes nominaux ou des propositions.
|
||||
|
||||
Entre deux propositions, *u* coordonne généralement des éléments de même importance. Leur ordre peut normalement être inversé sans modifier leur relation essentielle.
|
||||
|
||||
Selon le contexte, *u* peut aussi être traduit par « et aussi », « de plus » ou parfois « mais ».
|
||||
@@ -0,0 +1,20 @@
|
||||
+++
|
||||
title = "ul"
|
||||
date = 2026-08-03T11:13:23+02:00
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "ne… pas"
|
||||
logograms = []
|
||||
function = "négation d’une proposition principale"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["adverbe"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*ul* est un adverbe négatif servant à nier le prédicat d’une proposition principale. La forme habituelle est *ul* ; *ula* est moins fréquente.
|
||||
|
||||
Dans une proposition verbale, il se place immédiatement avant le verbe. Dans une proposition sans verbe, il précède le noyau du prédicat.
|
||||
@@ -0,0 +1,40 @@
|
||||
+++
|
||||
title = "zakûm"
|
||||
date = 2026-08-03T19:50:00+02:00
|
||||
updated = 2026-08-05
|
||||
description = ""
|
||||
draft = false
|
||||
|
||||
[extra]
|
||||
meaning = "être ou devenir clair, propre ou pur ; être ou devenir libre"
|
||||
logograms = []
|
||||
root = "z-k-w"
|
||||
stem = "G"
|
||||
verb_class = "III-faible (III-u)"
|
||||
vowel_class = "u/u"
|
||||
preterite = "izku"
|
||||
durative = "izakku"
|
||||
perfect = "izzaku"
|
||||
imperative = "zuku"
|
||||
participle = ""
|
||||
verbal_adjective = "zakûm"
|
||||
|
||||
[taxonomies]
|
||||
natures = ["verbe"]
|
||||
+++
|
||||
|
||||
## Emploi
|
||||
|
||||
*zakûm* signifie « être ou devenir clair, propre ou pur ». Il peut notamment s’employer à propos de l’eau, du ciel ou du temps, ainsi que du grain lorsqu’il est nettoyé de son enveloppe.
|
||||
|
||||
Le verbe signifie aussi « être ou devenir libre » d’une revendication, d’une obligation ou d’une charge. Il peut ainsi qualifier une personne, un bien ou une marchandise libre de toute prétention.
|
||||
|
||||
## Morphologie
|
||||
|
||||
Verbe III-faible de type III-u, issu d’une racine historique *z-k-w*. La disparition de la troisième radicale explique les formes terminées par *u*, notamment le prétérit *izku*, le duratif *izakku* et l’impératif *zuku*. Au parfait, l’infixe *-t-* s’assimile au *z* initial, d’où *izzaku*.
|
||||
|
||||
L’infinitif et l’adjectif verbal ont tous deux la forme *zakûm* au nominatif masculin singulier, mais ils reposent sur des bases différentes. L’adjectif verbal a pour base *zaku-* et signifie « clair, propre, pur ; libre ». Aucun participe n’est renseigné dans les références retenues pour cette fiche.
|
||||
|
||||
## Thèmes dérivés
|
||||
|
||||
Au thème D, *zukkûm* signifie notamment « nettoyer, purifier, clarifier ; vanner » et « libérer, dégager d’une obligation ».
|
||||
@@ -0,0 +1,837 @@
|
||||
// Couleurs
|
||||
$paper: #fbf8f0;
|
||||
$paper-soft: #f3eee4;
|
||||
$paper-edge: #e7dfcf;
|
||||
$ink: #28231d;
|
||||
$heading: #3d2c20;
|
||||
$muted: #6c6257;
|
||||
$cuneiform: #5b5046;
|
||||
$accent: #7a3f22;
|
||||
$rule: #d8cdbb;
|
||||
|
||||
// Typographie et mise en page
|
||||
$font-text: Georgia, "Times New Roman", serif;
|
||||
$font-cuneiform: "Assurbanipal", "Noto Sans Cuneiform", "Segoe UI Historic", sans-serif;
|
||||
$font-code: ui-monospace, "Cascadia Code", "Liberation Mono", monospace;
|
||||
$content-width: 50rem;
|
||||
|
||||
// Police cunéiforme
|
||||
@font-face {
|
||||
font-family: "Assurbanipal";
|
||||
src: url("fonts/assurbanipal.woff2") format("woff2");
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
unicode-range: U+12000-123FF, U+12400-1247F;
|
||||
}
|
||||
|
||||
// Base
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
min-height: 100svh;
|
||||
margin: 0;
|
||||
flex-direction: column;
|
||||
color: $ink;
|
||||
background: $paper;
|
||||
font-family: $font-text;
|
||||
font-size: clamp(1.0625rem, 1.02rem + 0.18vw, 1.125rem);
|
||||
line-height: 1.7;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: $ink;
|
||||
background: $paper-edge;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $accent;
|
||||
text-decoration-thickness: 0.08em;
|
||||
text-underline-offset: 0.16em;
|
||||
|
||||
&:hover {
|
||||
text-decoration-thickness: 0.14em;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 3px solid rgba($accent, 0.35);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
[id] {
|
||||
scroll-margin-top: 2rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
// Mise en page générale
|
||||
.container {
|
||||
width: min(100% - 2rem, $content-width);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.skip-link {
|
||||
position: fixed;
|
||||
left: 0.75rem;
|
||||
top: 0.75rem;
|
||||
z-index: 100;
|
||||
padding: 0.65rem 0.95rem;
|
||||
color: $paper;
|
||||
background: $ink;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
transform: translateY(-180%);
|
||||
|
||||
&:focus {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.site-main {
|
||||
padding-block: 2.75rem 4.25rem;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
// En-tête et navigation
|
||||
.site-header {
|
||||
border-bottom: 1px solid $rule;
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
|
||||
&__inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
padding-block: 1.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.site-title {
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
color: $ink;
|
||||
line-height: 1.08;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
|
||||
&__text {
|
||||
font-size: 1.35rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
&__cuneiform {
|
||||
color: $cuneiform;
|
||||
font-family: $font-cuneiform;
|
||||
font-size: 1.52rem;
|
||||
font-synthesis: none;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.1em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&:hover &__cuneiform,
|
||||
&:focus-visible &__cuneiform {
|
||||
color: $accent;
|
||||
}
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
ul {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.25rem 1rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
padding-block: 0.3rem;
|
||||
border-bottom: 2px solid transparent;
|
||||
color: $muted;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
color: $accent;
|
||||
}
|
||||
|
||||
&[aria-current] {
|
||||
border-bottom-color: $accent;
|
||||
color: $ink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titres et contenu courant
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
color: $heading;
|
||||
line-height: 1.22;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: clamp(2.15rem, 5vw, 3rem);
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 2.4rem 0 0;
|
||||
font-size: clamp(1.4rem, 2vw, 1.58rem);
|
||||
letter-spacing: -0.012em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 1.85rem 0 0;
|
||||
font-size: 1.24rem;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
dl,
|
||||
table,
|
||||
pre,
|
||||
blockquote {
|
||||
margin-block: 1rem;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding-left: 1.45rem;
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 0.18rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 1px;
|
||||
margin-block: 2.25rem;
|
||||
border: 0;
|
||||
background: $rule;
|
||||
}
|
||||
|
||||
// En-têtes de page et métadonnées
|
||||
.entry-header {
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1.15rem;
|
||||
border-bottom: 1px solid $rule;
|
||||
|
||||
> :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.entry-description,
|
||||
.section-description {
|
||||
max-width: 72ch;
|
||||
color: $muted;
|
||||
font-size: 1.12rem;
|
||||
line-height: 1.62;
|
||||
}
|
||||
|
||||
.entry-date,
|
||||
.entry-list__meta {
|
||||
color: $muted;
|
||||
font-size: 0.92rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
display: grid;
|
||||
grid-template-columns: max-content minmax(0, 1fr);
|
||||
gap: 0.38rem 1rem;
|
||||
margin-block: 1.3rem 0;
|
||||
|
||||
dt {
|
||||
color: $muted;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Bannière facultative des articles
|
||||
.article-cover {
|
||||
margin: 0 0 1.6rem;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 7;
|
||||
border: 1px solid $paper-edge;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
margin-top: 0.25rem;
|
||||
color: $muted;
|
||||
font-size: 0.8rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
// Listes de contenus
|
||||
.entry-list {
|
||||
margin: 1.25rem 0 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
padding-block: 0.82rem;
|
||||
border-bottom: 1px solid $paper-edge;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
&__meta {
|
||||
margin-top: 0.12rem;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
font-weight: 600;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
color: $accent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Page d’accueil
|
||||
.home-intro {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 13.75rem;
|
||||
gap: 2.25rem;
|
||||
align-items: start;
|
||||
|
||||
&__text > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&__figure {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__image {
|
||||
width: 100%;
|
||||
filter: drop-shadow(0 0.4rem 0.7rem rgba($ink, 0.2));
|
||||
}
|
||||
|
||||
&__caption {
|
||||
margin-top: 0.55rem;
|
||||
color: $muted;
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
|
||||
.home-latest,
|
||||
.home-directory,
|
||||
.home-about {
|
||||
margin-top: 2.4rem;
|
||||
|
||||
> h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.home-latest {
|
||||
&__entry {
|
||||
margin-top: 1.15rem;
|
||||
padding: 1.1rem 1.25rem;
|
||||
border: 1px solid $rule;
|
||||
background: rgba($accent, 0.035);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.entry-date {
|
||||
margin: 0.2rem 0 0;
|
||||
}
|
||||
|
||||
&__description {
|
||||
margin: 0.75rem 0 0;
|
||||
}
|
||||
|
||||
&__link {
|
||||
display: inline-block;
|
||||
margin-top: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.home-directory {
|
||||
&__list {
|
||||
margin: 1.15rem 0 0;
|
||||
padding: 0;
|
||||
border-top: 1px solid $paper-edge;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(8rem, 11rem) minmax(0, 1fr);
|
||||
gap: 1rem;
|
||||
margin: 0;
|
||||
padding-block: 0.82rem;
|
||||
border-bottom: 1px solid $paper-edge;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
color: $muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation secondaire et liens de contexte
|
||||
.section-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
margin-block: 2rem 2.5rem;
|
||||
padding: 1.1rem 1.25rem;
|
||||
border: 1px solid $rule;
|
||||
background: rgba($accent, 0.035);
|
||||
|
||||
h2 {
|
||||
margin: 0 0 0.2rem;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
color: $muted;
|
||||
}
|
||||
|
||||
&__link {
|
||||
flex: 0 0 auto;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.context-link {
|
||||
margin: 0 0 1rem;
|
||||
font-size: 0.95rem;
|
||||
|
||||
a {
|
||||
color: $muted;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
color: $accent;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cunéiforme
|
||||
.cuneiform {
|
||||
display: inline-block;
|
||||
margin-right: 0.25em;
|
||||
font-family: $font-cuneiform;
|
||||
font-synthesis: none;
|
||||
font-size: 1.2em;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
vertical-align: -0.08em;
|
||||
}
|
||||
|
||||
// Tableaux, citations et code
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 0.58rem 0.72rem;
|
||||
border: 1px solid $rule;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
color: $heading;
|
||||
background: rgba($accent, 0.06);
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) {
|
||||
background: rgba($accent, 0.018);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-inline: 0;
|
||||
padding: 0.05rem 0 0.05rem 1rem;
|
||||
border-left: 0.2rem solid $rule;
|
||||
color: $muted;
|
||||
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
> :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0.08em 0.28em;
|
||||
border: 1px solid $paper-edge;
|
||||
background: $paper-soft;
|
||||
font-family: $font-code;
|
||||
font-size: 0.9em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
padding: 1rem 1.1rem;
|
||||
border: 1px solid $paper-edge;
|
||||
background: $paper-soft;
|
||||
line-height: 1.55;
|
||||
tab-size: 4;
|
||||
|
||||
code {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
font-size: 0.88rem;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
}
|
||||
|
||||
// Pied de page
|
||||
.site-footer {
|
||||
padding-block: 1.5rem 2rem;
|
||||
border-top: 1px solid $rule;
|
||||
color: $muted;
|
||||
font-size: 0.9rem;
|
||||
|
||||
&__inner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
|
||||
&__links {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem 2rem;
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
p,
|
||||
&__contact {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__contact {
|
||||
font-style: normal;
|
||||
|
||||
> a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.32rem 0.72rem;
|
||||
border: 1px solid rgba($accent, 0.5);
|
||||
border-radius: 0.3rem;
|
||||
color: $accent;
|
||||
background: rgba($accent, 0.05);
|
||||
font-size: 0.95rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
border-color: $accent;
|
||||
color: $heading;
|
||||
background: rgba($accent, 0.12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// Numéros de ligne générés par la coloration syntaxique de Zola
|
||||
.giallo-l {
|
||||
display: inline-block;
|
||||
min-height: 1lh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.giallo-ln {
|
||||
display: inline-block;
|
||||
min-width: 3ch;
|
||||
margin-right: 0.4em;
|
||||
padding-right: 0.4em;
|
||||
user-select: none;
|
||||
text-align: right;
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
// Petits écrans
|
||||
@media (max-width: 45rem) {
|
||||
.container {
|
||||
width: min(100% - 1.5rem, $content-width);
|
||||
}
|
||||
|
||||
.site-header__inner {
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 0.55rem;
|
||||
padding-block: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.site-title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
width: 100%;
|
||||
|
||||
ul {
|
||||
justify-content: center;
|
||||
gap: 0.1rem 0.85rem;
|
||||
}
|
||||
}
|
||||
|
||||
.site-main {
|
||||
padding-block: 2.15rem 3.25rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(2rem, 10vw, 2.55rem);
|
||||
}
|
||||
|
||||
.section-tools {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.home-intro {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
|
||||
&__figure {
|
||||
width: min(100%, 13.75rem);
|
||||
margin-inline: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.home-directory__list li {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0.1rem;
|
||||
|
||||
dd + dt {
|
||||
margin-top: 0.65rem;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.site-footer__inner {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.site-footer__links {
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
|
||||
nav {
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.site-footer__license {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Impression
|
||||
@media print {
|
||||
@page {
|
||||
margin: 18mm;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
color: #000;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
body {
|
||||
display: block;
|
||||
min-height: auto;
|
||||
font-size: 11pt;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.skip-link,
|
||||
.site-nav,
|
||||
.site-footer,
|
||||
.section-tools,
|
||||
.context-link {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.home-intro__image {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.site-header {
|
||||
border-bottom: 1px solid #999;
|
||||
background: transparent;
|
||||
|
||||
&__inner {
|
||||
display: block;
|
||||
padding-block: 0 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.site-title {
|
||||
align-items: flex-start;
|
||||
color: #000;
|
||||
|
||||
&__cuneiform {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.site-main {
|
||||
padding-block: 1.2rem 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
color: #000;
|
||||
break-after: avoid-page;
|
||||
}
|
||||
|
||||
p,
|
||||
li,
|
||||
blockquote {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
|
||||
.entry-header,
|
||||
.article-cover,
|
||||
.entry-list li,
|
||||
table,
|
||||
blockquote,
|
||||
pre,
|
||||
img {
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
table {
|
||||
display: table;
|
||||
max-width: none;
|
||||
overflow: visible;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #eee;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: visible;
|
||||
border-color: #aaa;
|
||||
background: #fff;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 272 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,9 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Page introuvable · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Page introuvable</h1>
|
||||
<p>La page demandée n’existe pas ou a été déplacée.</p>
|
||||
<p><a href="{{ get_url(path='@/_index.md') | safe }}">Revenir à l’accueil</a></p>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ section.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/section-header.html" %}
|
||||
|
||||
{{ section.content | safe }}
|
||||
|
||||
{% if section.pages %}
|
||||
<h2>Liste des articles</h2>
|
||||
<ul class="entry-list">
|
||||
{% for page in section.pages %}
|
||||
<li>
|
||||
<a href="{{ page.permalink | safe }}">{{ page.title }}</a>
|
||||
{% if page.date or page.description %}
|
||||
<div class="entry-list__meta">
|
||||
{% if page.date %}
|
||||
<time datetime="{{ page.date }}">{{ page.date | date(format="%d/%m/%Y") }}</time>
|
||||
{% endif %}
|
||||
{% if page.date and page.description %} — {% endif %}
|
||||
{% if page.description %}{{ page.description }}{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,122 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ lang }}">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{% if page is defined and page.description %}
|
||||
<meta name="description" content="{{ page.description }}">
|
||||
{% elif section is defined and section.description %}
|
||||
<meta name="description" content="{{ section.description }}">
|
||||
{% elif term is defined %}
|
||||
<meta name="description" content="Contenus associés à « {{ term.name }} » dans {{ config.title }}.">
|
||||
{% elif taxonomy is defined %}
|
||||
<meta name="description" content="Index « {{ taxonomy.name }} » de {{ config.title }}.">
|
||||
{% else %}
|
||||
<meta name="description" content="{{ config.description }}">
|
||||
{% endif %}
|
||||
<meta name="author" content="{{ config.extra.author }}">
|
||||
{% if current_url is defined %}
|
||||
<link rel="canonical" href="{{ current_url | safe }}">
|
||||
{% endif %}
|
||||
<meta property="og:site_name" content="{{ config.title }}">
|
||||
<link rel="alternate" type="application/atom+xml" title="{{ config.title }} — Atom"
|
||||
href="{{ get_url(path='atom.xml', trailing_slash=false) | safe }}">
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ config.title }} — RSS"
|
||||
href="{{ get_url(path='rss.xml', trailing_slash=false) | safe }}">
|
||||
<title>{% block title %}{{ config.title }}{% endblock title %}</title>
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="{{ get_url(path='images/favicon.png') | safe }}">
|
||||
<link rel="stylesheet" href="{{ get_url(path='main.css') | safe }}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% set nav_path = current_path | default(value="") %}
|
||||
|
||||
{% if nav_path == "/" %}
|
||||
<div itemscope itemtype="https://schema.org/WebSite">
|
||||
<link itemprop="url" href="{{ get_url(path='@/_index.md') | safe }}">
|
||||
<meta itemprop="name" content="{{ config.title }}">
|
||||
<meta itemprop="alternateName" content="lescarnetsdakkadien.netig.net">
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<a class="skip-link" href="#contenu">Aller au contenu</a>
|
||||
|
||||
<header class="site-header">
|
||||
<div class="container site-header__inner">
|
||||
<a class="site-title" href="{{ get_url(path='@/_index.md') | safe }}">
|
||||
<span class="site-title__text">{{ config.title }}</span>
|
||||
<span class="site-title__cuneiform" lang="akk-Xsux" aria-hidden="true">𒀝𒅗𒁺𒌑𒌝</span>
|
||||
</a>
|
||||
|
||||
<nav class="site-nav" aria-label="Navigation principale">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ get_url(path='@/signes/_index.md') | safe }}" {% if "/signes/" in nav_path
|
||||
or "/lectures/" in nav_path %} aria-current="location" {% endif %}>Signes</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ get_url(path='@/vocabulaire/_index.md') | safe }}" {% if "/vocabulaire/" in nav_path
|
||||
or "/natures/" in nav_path %} aria-current="location" {% endif %}>Vocabulaire</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ get_url(path='@/grammaire/_index.md') | safe }}" {% if "/grammaire/" in nav_path
|
||||
or "/themes/" in nav_path %} aria-current="location" {% endif %}>Grammaire</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ get_url(path='@/textes/_index.md') | safe }}" {% if "/textes/" in nav_path
|
||||
or "/genres/" in nav_path %} aria-current="location" {% endif %}>Textes</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ get_url(path='@/articles/_index.md') | safe }}" {% if "/articles/" in nav_path %}
|
||||
aria-current="location" {% endif %}>Articles</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="contenu" class="container site-main">
|
||||
{% block content %}{% endblock content %}
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container site-footer__inner">
|
||||
<div class="site-footer__links">
|
||||
<address class="site-footer__contact">
|
||||
<a href="mailto:{{ config.extra.email }}">Me contacter</a>
|
||||
</address>
|
||||
|
||||
<nav aria-label="Liens complémentaires">
|
||||
<a href="{{ get_url(path='@/bibliographie.md') | safe }}">
|
||||
Bibliographie
|
||||
</a>
|
||||
|
||||
<a href="{{ get_url(path='@/mentions-legales.md') | safe }}">
|
||||
Mentions légales
|
||||
</a>
|
||||
|
||||
<a href="{{ get_url(path='atom.xml', trailing_slash=false) | safe }}" type="application/atom+xml">
|
||||
Flux Atom
|
||||
</a>
|
||||
|
||||
<a href="{{ get_url(path='rss.xml', trailing_slash=false) | safe }}" type="application/rss+xml">
|
||||
Flux RSS
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<p class="site-footer__license">
|
||||
<small>
|
||||
Sauf mention contraire, le contenu original du site web
|
||||
{{ config.extra.author }} est placé sous licence
|
||||
<a href="https://creativecommons.org/licenses/by-sa/4.0/deed.fr" rel="license">
|
||||
CC BY-SA 4.0
|
||||
</a>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ section.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/section-header.html" %}
|
||||
|
||||
{{ section.content | safe }}
|
||||
|
||||
{{ macros::taxonomy_nav(
|
||||
kind="themes",
|
||||
heading_id="grammaire-index-title",
|
||||
title="Explorer la grammaire",
|
||||
description="Retrouver les fiches par notion grammaticale.",
|
||||
path="themes",
|
||||
link_label="Par thème grammatical"
|
||||
) }}
|
||||
|
||||
{% if section.pages %}
|
||||
<h2>Liste des fiches</h2>
|
||||
<ul class="entry-list">
|
||||
{% for page in section.pages %}
|
||||
<li>
|
||||
<a href="{{ page.permalink | safe }}">{{ page.title }}</a>
|
||||
{% if page.description %} — {{ page.description }}{% endif %}
|
||||
{% if page.taxonomies.themes %}
|
||||
<div class="entry-list__meta">
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.themes, kind="themes") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>Aucune fiche n’est encore publiée dans cette section.</p>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,134 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% set signes = get_section(path="signes/_index.md") %}
|
||||
{% set vocabulaire = get_section(path="vocabulaire/_index.md") %}
|
||||
{% set grammaire = get_section(path="grammaire/_index.md") %}
|
||||
{% set textes = get_section(path="textes/_index.md") %}
|
||||
{% set articles = get_section(path="articles/_index.md") %}
|
||||
|
||||
{% set recent = signes.pages | concat(with=vocabulaire.pages) %}
|
||||
{% set recent = recent | concat(with=grammaire.pages) %}
|
||||
{% set recent = recent | concat(with=textes.pages) %}
|
||||
{% set recent = recent | filter(attribute="date") | sort(attribute="date") | reverse %}
|
||||
|
||||
{% include "partials/section-header.html" %}
|
||||
|
||||
<section class="home-intro">
|
||||
<div class="home-intro__text">
|
||||
{{ section.content | safe }}
|
||||
</div>
|
||||
|
||||
<figure class="home-intro__figure">
|
||||
<img class="home-intro__image" src="{{ get_url(path='images/DP-12499-013.webp') | safe }}" width="640"
|
||||
height="1120" alt="Tablette cunéiforme portant une lettre privée en akkadien paléo-babylonien"
|
||||
decoding="async">
|
||||
<figcaption class="home-intro__caption">
|
||||
Lettre privée paléo-babylonienne, vers 1632 av. J.-C. —
|
||||
<a href="https://www.metmuseum.org/art/collection/search/321706" target="_blank" rel="noopener noreferrer">
|
||||
The Metropolitan Museum of Art, 86.11.111
|
||||
</a>.
|
||||
</figcaption>
|
||||
</figure>
|
||||
</section>
|
||||
|
||||
{% if articles.pages %}
|
||||
{% set article = articles.pages | first %}
|
||||
|
||||
<section class="home-latest" aria-labelledby="home-latest-title">
|
||||
<h2 id="home-latest-title">Dernier article</h2>
|
||||
|
||||
<article class="home-latest__entry">
|
||||
<h3>
|
||||
<a href="{{ article.permalink | safe }}">{{ article.title }}</a>
|
||||
</h3>
|
||||
|
||||
<p class="entry-date">
|
||||
<time datetime="{{ article.date }}">{{ article.date | date(format="%d/%m/%Y") }}</time>
|
||||
</p>
|
||||
|
||||
{% if article.description %}
|
||||
<p class="home-latest__description">{{ article.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
<a class="home-latest__link" href="{{ article.permalink | safe }}">Lire l’article</a>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% set directory_sections = [
|
||||
signes,
|
||||
vocabulaire,
|
||||
grammaire,
|
||||
textes,
|
||||
articles
|
||||
] %}
|
||||
|
||||
<nav class="home-directory" aria-labelledby="home-directory-title">
|
||||
<h2 id="home-directory-title">Explorer les carnets</h2>
|
||||
|
||||
<ul class="home-directory__list">
|
||||
{% for directory_section in directory_sections %}
|
||||
<li>
|
||||
<a href="{{ directory_section.permalink | safe }}">
|
||||
{{ directory_section.title }}
|
||||
</a>
|
||||
|
||||
{% if directory_section.description %}
|
||||
<p>{{ directory_section.description }}</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{% if recent %}
|
||||
<section aria-labelledby="recent-title">
|
||||
<h2 id="recent-title">Dernières fiches</h2>
|
||||
<ul class="entry-list">
|
||||
{% for item in recent | slice(end=3) %}
|
||||
<li>
|
||||
<a href="{{ item.permalink | safe }}">
|
||||
{% if "/signes/" in item.path %}
|
||||
{% set sign = item.extra | get(key="sign", default="") %}
|
||||
{% if sign %}
|
||||
<span class="cuneiform" lang="und-Xsux" aria-hidden="true">{{ sign }}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if "/vocabulaire/" in item.path %}<span lang="akk-Latn">{{ item.title }}</span>{% else %}{{
|
||||
item.title }}{% endif %}
|
||||
</a>
|
||||
<div class="entry-list__meta">
|
||||
{% if "/signes/" in item.path %}
|
||||
Signe
|
||||
{% elif "/vocabulaire/" in item.path %}
|
||||
Vocabulaire
|
||||
{% elif "/grammaire/" in item.path %}
|
||||
Grammaire
|
||||
{% elif "/textes/" in item.path %}
|
||||
Texte
|
||||
{% endif %}
|
||||
· <time datetime="{{ item.date }}">{{ item.date | date(format="%d/%m/%Y") }}</time>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<section class="home-about" aria-labelledby="home-about-title">
|
||||
<h2 id="home-about-title">À propos de ce site</h2>
|
||||
<p>
|
||||
Ce site évolue au rythme de mon apprentissage et ne prétend pas se substituer à une grammaire ou à un
|
||||
dictionnaire spécialisé. J’apprends pour l’instant le paléo-babylonien : les formes et les analyses présentées
|
||||
ici concernent donc principalement cette période. Les autres périodes ou dialectes seront précisés au fil de mes
|
||||
découvertes. Les principaux ouvrages sur lesquels je m’appuie sont présentés dans la bibliographie.
|
||||
</p>
|
||||
<p>
|
||||
Les fiches peuvent être consultées à l’écran, imprimées ou enregistrées au format PDF.
|
||||
</p>
|
||||
<p>
|
||||
Suggestions, remarques et corrections sont les bienvenues ; un lien de contact est disponible ci-dessous.
|
||||
</p>
|
||||
</section>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,43 @@
|
||||
{% macro taxonomy_links(terms, kind) -%}
|
||||
{%- for term in terms -%}
|
||||
{%- if not loop.first %}, {% endif -%}
|
||||
<a href="{{ get_taxonomy_url(kind=kind, name=term) | safe }}">{{ term }}</a>
|
||||
{%- endfor -%}
|
||||
{%- endmacro taxonomy_links %}
|
||||
|
||||
{% macro taxonomy_nav(kind, heading_id, title, description, path, link_label) %}
|
||||
{% set taxonomy = get_taxonomy(kind=kind, required=false) %}
|
||||
{% if taxonomy and taxonomy.items %}
|
||||
<nav class="section-tools" aria-labelledby="{{ heading_id }}">
|
||||
<div>
|
||||
<h2 id="{{ heading_id }}">{{ title }}</h2>
|
||||
<p>{{ description }}</p>
|
||||
</div>
|
||||
<a class="section-tools__link" href="{{ get_url(path=path, trailing_slash=true) | safe }}">
|
||||
{{ link_label }}
|
||||
</a>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endmacro taxonomy_nav %}
|
||||
|
||||
{% macro metadata_field(extra, key, label, lang="") -%}
|
||||
{%- set value = extra | get(key=key, default="") -%}
|
||||
{%- if value -%}
|
||||
<dt>{{ label }}</dt>
|
||||
<dd{% if lang %} lang="{{ lang }}"{% endif %}>{{ value }}</dd>
|
||||
{%- endif -%}
|
||||
{%- endmacro metadata_field %}
|
||||
|
||||
{% macro metadata_list(extra, key, label, lang="") -%}
|
||||
{%- set values = extra | get(key=key, default="") -%}
|
||||
{%- if values -%}
|
||||
<dt>{{ label }}</dt>
|
||||
<dd{% if lang %} lang="{{ lang }}"{% endif %}>
|
||||
{%- for value in values -%}
|
||||
{%- if not loop.first %}, {% endif -%}
|
||||
{{- value -}}
|
||||
{%- endfor -%}
|
||||
</dd>
|
||||
{%- endif -%}
|
||||
{%- endmacro metadata_list %}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ page.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/back-to-section.html" %}
|
||||
<article>
|
||||
<header class="entry-header">
|
||||
<h1 lang="akk-Latn">{{ page.title }}</h1>
|
||||
|
||||
{% if page.description %}
|
||||
<p class="entry-description">{{ page.description }}</p>
|
||||
{% else %}
|
||||
<p class="entry-description">
|
||||
{% if page.taxonomies.natures %}
|
||||
{% for nature in page.taxonomies.natures %}
|
||||
{% if loop.first %}{{ nature | capitalize }}{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
Mot
|
||||
{% endif %}
|
||||
{% if page.extra.gender %} {{ page.extra.gender }}{% endif %}{% if page.extra.meaning %} signifiant « {{ page.extra.meaning }} »{% endif %}.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% include "partials/entry-dates.html" %}
|
||||
|
||||
<dl class="metadata">
|
||||
<dt>Nature grammaticale</dt>
|
||||
<dd>{{ macros::taxonomy_links(terms=page.taxonomies.natures, kind="natures") }}</dd>
|
||||
|
||||
{# Tera 1.x n’accepte pas les tableaux imbriqués dans un littéral set.
|
||||
Les champs restent donc explicites et leur balisage est factorisé par macro. #}
|
||||
{{ macros::metadata_field(extra=page.extra, key="meaning", label="Sens") }}
|
||||
{{ macros::metadata_list(extra=page.extra, key="logograms", label="Logogrammes", lang="sux-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="gender", label="Genre") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="pronoun_type", label="Type de pronom") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="person", label="Personne") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="number", label="Nombre") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="numeral_type", label="Type de numéral") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="value", label="Valeur") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="governs", label="Cas régi") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="function", label="Fonction") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="bound", label="Forme liée", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="plural", label="Pluriel", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="feminine", label="Féminin", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="masculine_plural", label="Pluriel masculin", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="feminine_plural", label="Pluriel féminin", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="predicative", label="Prédicatif (3 m. s.)", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="root", label="Racine", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="stem", label="Thème") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="verb_class", label="Classe verbale") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="vowel_class", label="Classe vocalique") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="preterite", label="Prétérit", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="durative", label="Duratif", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="perfect", label="Parfait", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="imperative", label="Impératif", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="participle", label="Participe", lang="akk-Latn") }}
|
||||
{{ macros::metadata_field(extra=page.extra, key="verbal_adjective", label="Adjectif verbal", lang="akk-Latn") }}
|
||||
</dl>
|
||||
</header>
|
||||
|
||||
{{ page.content | safe }}
|
||||
</article>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,47 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ page.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/back-to-section.html" %}
|
||||
<article>
|
||||
<header class="entry-header">
|
||||
<h1>{{ page.title }}</h1>
|
||||
|
||||
{% if page.description %}
|
||||
<p class="entry-description">{{ page.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% include "partials/entry-dates.html" %}
|
||||
|
||||
{% if page.taxonomies.themes %}
|
||||
<dl class="metadata">
|
||||
<dt>Thème</dt>
|
||||
<dd>
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.themes, kind="themes") }}
|
||||
</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
{% set banner = page.extra | get(key="banner", default="") %}
|
||||
{% if banner %}
|
||||
{% set banner_alt = page.extra | get(key="banner_alt", default="") %}
|
||||
{% set banner_credit = page.extra | get(key="banner_credit", default="") %}
|
||||
|
||||
<figure class="article-cover">
|
||||
<img
|
||||
src="{{ get_url(path=banner) | safe }}"
|
||||
alt="{{ banner_alt }}"
|
||||
>
|
||||
|
||||
{% if banner_credit %}
|
||||
<figcaption>{{ banner_credit }}</figcaption>
|
||||
{% endif %}
|
||||
</figure>
|
||||
{% endif %}
|
||||
|
||||
{{ page.content | safe }}
|
||||
</article>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% if page.ancestors %}
|
||||
{% set parent_path = page.ancestors | last %}
|
||||
{% set parent = get_section(path=parent_path, metadata_only=true) %}
|
||||
{% set back_label = parent.extra | get(key="back_label", default="") %}
|
||||
|
||||
{% if back_label %}
|
||||
<p class="context-link">
|
||||
<a href="{{ parent.permalink | safe }}">
|
||||
← {{ back_label }}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% if page.date or page.updated %}
|
||||
<p class="entry-date">
|
||||
{% if page.date %}
|
||||
Mis en ligne le
|
||||
<time datetime="{{ page.date }}">{{ page.date | date(format="%d/%m/%Y") }}</time>
|
||||
{% endif %}
|
||||
{% if page.updated %}
|
||||
{% if page.date %} · {% endif %}
|
||||
Mis à jour le
|
||||
<time datetime="{{ page.updated }}">{{ page.updated | date(format="%d/%m/%Y") }}</time>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,6 @@
|
||||
<header class="entry-header">
|
||||
<h1>{{ section.title }}</h1>
|
||||
{% if section.description %}
|
||||
<p class="section-description">{{ section.description }}</p>
|
||||
{% endif %}
|
||||
</header>
|
||||
@@ -0,0 +1,39 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ page.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/back-to-section.html" %}
|
||||
<article>
|
||||
<header class="entry-header">
|
||||
<h1><span class="cuneiform" lang="und-Xsux" aria-hidden="true">{{ page.extra.sign }}</span> {{ page.title }}
|
||||
</h1>
|
||||
|
||||
{% if page.description %}
|
||||
<p class="entry-description">{{ page.description }}</p>
|
||||
{% else %}
|
||||
<p class="entry-description">
|
||||
Signe cunéiforme {{ page.title }}{% if page.extra.mzl %} — MZL {{ page.extra.mzl }}{% endif %}.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% include "partials/entry-dates.html" %}
|
||||
|
||||
<dl class="metadata">
|
||||
<dt>MZL</dt>
|
||||
<dd>{{ page.extra.mzl }}</dd>
|
||||
|
||||
{% if page.taxonomies.lectures %}
|
||||
<dt>Lectures</dt>
|
||||
<dd>
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.lectures, kind="lectures") }}
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
</dl>
|
||||
</header>
|
||||
|
||||
{{ page.content | safe }}
|
||||
</article>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,39 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ section.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/section-header.html" %}
|
||||
|
||||
{{ section.content | safe }}
|
||||
|
||||
{{ macros::taxonomy_nav(
|
||||
kind="lectures",
|
||||
heading_id="signes-index-title",
|
||||
title="Explorer les signes",
|
||||
description="Retrouver les signes par lecture.",
|
||||
path="lectures",
|
||||
link_label="Index des lectures"
|
||||
) }}
|
||||
|
||||
{% if section.pages %}
|
||||
<h2>Liste des signes</h2>
|
||||
<ul class="entry-list">
|
||||
{% for page in section.pages %}
|
||||
<li>
|
||||
<a href="{{ page.permalink | safe }}">
|
||||
<span class="cuneiform" lang="und-Xsux" aria-hidden="true">{{ page.extra.sign }}</span> {{ page.title }}
|
||||
</a>
|
||||
<div class="entry-list__meta">
|
||||
MZL {{ page.extra.mzl }}
|
||||
{% if page.taxonomies.lectures %}
|
||||
·
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.lectures, kind="lectures") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,59 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{% if taxonomy.name == "natures" %}Vocabulaire par nature grammaticale{% elif taxonomy.name == "lectures" %}Index des lectures des signes{% elif taxonomy.name == "genres" %}Textes par type{% elif taxonomy.name == "themes" %}Grammaire par thème{% else %}{{ taxonomy.name | capitalize }}{% endif %} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% set heading = taxonomy.name | capitalize %}
|
||||
{% set description = "Index des entrées de cette taxonomie." %}
|
||||
{% set back_url = get_url(path='@/_index.md') %}
|
||||
{% set back_label = "Retour à l’accueil" %}
|
||||
{% set item_label = "entrée" %}
|
||||
|
||||
{% if taxonomy.name == "natures" %}
|
||||
{% set heading = "Vocabulaire par nature grammaticale" %}
|
||||
{% set description = "Index des fiches lexicales regroupées selon leur nature grammaticale." %}
|
||||
{% set back_url = get_url(path='@/vocabulaire/_index.md') %}
|
||||
{% set back_label = "Retour au vocabulaire" %}
|
||||
{% set item_label = "mot" %}
|
||||
{% elif taxonomy.name == "lectures" %}
|
||||
{% set heading = "Index des lectures des signes" %}
|
||||
{% set description = "Index permettant de retrouver les signes cunéiformes à partir d’une lecture." %}
|
||||
{% set back_url = get_url(path='@/signes/_index.md') %}
|
||||
{% set back_label = "Retour aux signes cunéiformes" %}
|
||||
{% set item_label = "signe" %}
|
||||
{% elif taxonomy.name == "genres" %}
|
||||
{% set heading = "Types de textes" %}
|
||||
{% set description = "Index des textes étudiés regroupés selon leur type documentaire." %}
|
||||
{% set back_url = get_url(path='@/textes/_index.md') %}
|
||||
{% set back_label = "Retour aux textes" %}
|
||||
{% set item_label = "texte" %}
|
||||
{% elif taxonomy.name == "themes" %}
|
||||
{% set heading = "Thèmes grammaticaux" %}
|
||||
{% set description = "Index des fiches de grammaire regroupées selon la notion étudiée." %}
|
||||
{% set back_url = get_url(path='@/grammaire/_index.md') %}
|
||||
{% set back_label = "Retour à la grammaire" %}
|
||||
{% set item_label = "fiche" %}
|
||||
{% endif %}
|
||||
|
||||
<p class="context-link">
|
||||
<a href="{{ back_url | safe }}">← {{ back_label }}</a>
|
||||
</p>
|
||||
|
||||
<header class="entry-header">
|
||||
<h1>{{ heading }}</h1>
|
||||
<p class="section-description">{{ description }}</p>
|
||||
</header>
|
||||
|
||||
{% if terms %}
|
||||
<ul class="entry-list">
|
||||
{% for term in terms %}
|
||||
<li>
|
||||
<a href="{{ term.permalink | safe }}">{{ term.name }}</a>
|
||||
<span class="entry-list__meta">
|
||||
— {{ term.page_count }} {{ item_label }}{% if term.page_count > 1 %}s{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,75 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{% if taxonomy.name == "natures" %}Mots : {{ term.name }}{% elif taxonomy.name == "lectures" %}Lecture « {{ term.name }} »{% elif taxonomy.name == "genres" %}Textes : {{ term.name }}{% elif taxonomy.name == "themes" %}Grammaire : {{ term.name }}{% else %}{{ term.name }}{% endif %} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% set heading = term.name %}
|
||||
{% set description = "Entrées classées dans cet index." %}
|
||||
{% set back_url = get_url(path=taxonomy.name, trailing_slash=true) %}
|
||||
{% set back_label = "Retour à l’index" %}
|
||||
|
||||
{% if taxonomy.name == "natures" %}
|
||||
{% set heading = "Mots : " ~ term.name %}
|
||||
{% set description = "Fiches de vocabulaire classées comme « " ~ term.name ~ " »." %}
|
||||
{% set back_url = get_url(path='natures', trailing_slash=true) %}
|
||||
{% set back_label = "Toutes les natures grammaticales" %}
|
||||
{% elif taxonomy.name == "lectures" %}
|
||||
{% set heading = "Lecture « " ~ term.name ~ " »" %}
|
||||
{% set description = "Signes cunéiformes pouvant recevoir la lecture « " ~ term.name ~ " »." %}
|
||||
{% set back_url = get_url(path='lectures', trailing_slash=true) %}
|
||||
{% set back_label = "Toutes les lectures" %}
|
||||
{% elif taxonomy.name == "genres" %}
|
||||
{% set heading = "Textes : " ~ term.name %}
|
||||
{% set description = "Textes classés dans le type « " ~ term.name ~ " »." %}
|
||||
{% set back_url = get_url(path='genres', trailing_slash=true) %}
|
||||
{% set back_label = "Tous les types de textes" %}
|
||||
{% elif taxonomy.name == "themes" %}
|
||||
{% set heading = "Thème : " ~ term.name %}
|
||||
{% set description = "Fiches de grammaire classées dans le thème « " ~ term.name ~ " »." %}
|
||||
{% set back_url = get_url(path='themes', trailing_slash=true) %}
|
||||
{% set back_label = "Tous les thèmes grammaticaux" %}
|
||||
{% endif %}
|
||||
|
||||
<p class="context-link">
|
||||
<a href="{{ back_url | safe }}">← {{ back_label }}</a>
|
||||
</p>
|
||||
|
||||
<header class="entry-header">
|
||||
<h1>{{ heading }}</h1>
|
||||
<p class="section-description">{{ description }}</p>
|
||||
</header>
|
||||
|
||||
{% if term.pages %}
|
||||
{% if taxonomy.name == "lectures" %}
|
||||
{% set taxonomy_pages = term.pages | sort(attribute="slug") %}
|
||||
{% else %}
|
||||
{% set taxonomy_pages = term.pages | sort(attribute="title") %}
|
||||
{% endif %}
|
||||
|
||||
<ul class="entry-list">
|
||||
{% for page in taxonomy_pages %}
|
||||
<li>
|
||||
{% if taxonomy.name == "lectures" %}
|
||||
<a href="{{ page.permalink | safe }}">
|
||||
<span class="cuneiform" lang="und-Xsux" aria-hidden="true">{{ page.extra.sign }}</span> {{ page.title }}
|
||||
</a>
|
||||
<div class="entry-list__meta">MZL {{ page.extra.mzl }}</div>
|
||||
{% elif taxonomy.name == "natures" %}
|
||||
<a href="{{ page.permalink | safe }}"><span lang="akk-Latn">{{ page.title }}</span></a>
|
||||
{% if page.extra.meaning %} — {{ page.extra.meaning }}{% endif %}
|
||||
{% if page.extra.gender %}
|
||||
<div class="entry-list__meta">{{ page.extra.gender }}</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{{ page.permalink | safe }}">{{ page.title }}</a>
|
||||
{% if page.description %}
|
||||
<div class="entry-list__meta">{{ page.description }}</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>Aucune fiche n’est encore associée à cette entrée.</p>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ page.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/back-to-section.html" %}
|
||||
<article>
|
||||
<header class="entry-header">
|
||||
<h1>{{ page.title }}</h1>
|
||||
|
||||
{% if page.description %}
|
||||
<p class="entry-description">{{ page.description }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% include "partials/entry-dates.html" %}
|
||||
|
||||
{% if page.taxonomies.genres %}
|
||||
<dl class="metadata">
|
||||
<dt>Type de texte</dt>
|
||||
<dd>
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.genres, kind="genres") }}
|
||||
</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
{{ page.content | safe }}
|
||||
</article>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ section.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/section-header.html" %}
|
||||
|
||||
{{ section.content | safe }}
|
||||
|
||||
{{ macros::taxonomy_nav(
|
||||
kind="genres",
|
||||
heading_id="textes-index-title",
|
||||
title="Explorer les textes",
|
||||
description="Retrouver les textes par type documentaire.",
|
||||
path="genres",
|
||||
link_label="Par type de texte"
|
||||
) }}
|
||||
|
||||
{% if section.pages %}
|
||||
<h2>Liste des textes</h2>
|
||||
<ul class="entry-list">
|
||||
{% for page in section.pages %}
|
||||
<li>
|
||||
<a href="{{ page.permalink | safe }}">{{ page.title }}</a>
|
||||
{% if page.description %} — {{ page.description }}{% endif %}
|
||||
{% if page.taxonomies.genres %}
|
||||
<div class="entry-list__meta">
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.genres, kind="genres") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>Aucun texte n’est encore publié dans cette section.</p>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,35 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "macros.html" as macros %}
|
||||
|
||||
{% block title %}{{ section.title }} · {{ config.title }}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
{% include "partials/section-header.html" %}
|
||||
|
||||
{{ section.content | safe }}
|
||||
|
||||
{{ macros::taxonomy_nav(
|
||||
kind="natures",
|
||||
heading_id="vocabulaire-index-title",
|
||||
title="Explorer le vocabulaire",
|
||||
description="Retrouver les mots par nature grammaticale.",
|
||||
path="natures",
|
||||
link_label="Par nature grammaticale"
|
||||
) }}
|
||||
|
||||
{% if section.pages %}
|
||||
<h2>Liste des mots</h2>
|
||||
<ul class="entry-list">
|
||||
{% for page in section.pages %}
|
||||
<li>
|
||||
<a href="{{ page.permalink | safe }}"><span lang="akk-Latn">{{ page.title }}</span></a>
|
||||
{% if page.extra.meaning %} — {{ page.extra.meaning }}{% endif %}
|
||||
<div class="entry-list__meta">
|
||||
{{ macros::taxonomy_links(terms=page.taxonomies.natures, kind="natures") }}
|
||||
{% if page.extra.gender %} · {{ page.extra.gender }}{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,32 @@
|
||||
base_url = "https://lescarnetsdakkadien.netig.net"
|
||||
title = "Les Carnets d’Akkadien"
|
||||
description = "Un site consacré à l’apprentissage de la langue akkadienne et de l’écriture cunéiforme."
|
||||
default_language = "fr"
|
||||
|
||||
compile_sass = true
|
||||
build_search_index = false
|
||||
|
||||
generate_feeds = true
|
||||
feed_filenames = ["atom.xml", "rss.xml"]
|
||||
|
||||
taxonomies = [
|
||||
{ name = "natures" },
|
||||
{ name = "lectures" },
|
||||
{ name = "themes" },
|
||||
{ name = "genres" },
|
||||
]
|
||||
|
||||
[markdown]
|
||||
|
||||
[markdown.highlighting]
|
||||
theme = "github-light"
|
||||
|
||||
[slugify]
|
||||
# Conserver les diacritiques dans les termes de taxonomie afin de
|
||||
# distinguer des lectures comme « tim » et « ṭim ».
|
||||
taxonomies = "safe"
|
||||
paths = "safe"
|
||||
|
||||
[extra]
|
||||
author = "Les Carnets d’Akkadien"
|
||||
email = "julien.deb@netig.net"
|
||||
Reference in New Issue
Block a user