Compare commits

2 Commits
Author SHA1 Message Date
ArtemiaandClaude Opus 5.5 503aa66dc0 Polices libres Noto Sans / Noto Sans Mono, vérifiées et installées par l'assistant
Segoe UI et Consolas (polices Microsoft, non redistribuables) provoquaient des avertissements Typst sous Linux et macOS. Le gabarit utilise désormais Noto Sans et Noto Sans Mono. L'assistant vérifie leur présence (quarto typst fonts) et sinon les installe : paquets système sous Linux, ou téléchargement depuis le dépôt officiel Noto dans le dossier de polices de l'utilisateur (Windows, macOS, et secours Linux).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:00:53 +02:00
ArtemiaandClaude Opus 5.5 5b312f7459 Assistant : installe Quarto sous Arch Linux via l'AUR (yay ou paru)
Quarto n'est pas dans les dépôts officiels d'Arch. Si pacman ne connaît pas le paquet, l'assistant utilise yay (ou paru) pour installer quarto-cli-bin (binaire officiel, à jour), sans sudo puisque ces outils l'appellent eux-mêmes. Sans assistant AUR, il explique la marche à suivre.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:48:17 +02:00
3 changed files with 111 additions and 7 deletions
+5 -2
View File
@@ -33,7 +33,8 @@ correspondant à votre système :
Une fenêtre s'ouvre et vous guide :
1. elle vérifie que **Python** et **Quarto** sont installés, et propose de les installer automatiquement sinon ;
1. elle vérifie que **Python**, **Quarto** et les polices **Noto Sans / Noto Sans Mono** sont installés,
et propose de les installer automatiquement sinon (sous Linux, les polices sont généralement déjà présentes) ;
2. elle prépare l'environnement Python des schémas (dossier `.venv`, une seule fois) ;
3. elle vous demande le **format** (PDF, LibreOffice .odt ou site web HTML) et les **supports** à produire
(tous, ou un seul module) ;
@@ -54,7 +55,9 @@ _output/ PDF générés (non versionnés)
## Produire les PDF
Prérequis : [Quarto](https://quarto.org/docs/get-started/) (inclut Pandoc et Typst).
Prérequis : [Quarto](https://quarto.org/docs/get-started/) (inclut Pandoc et Typst) et les polices libres
[Noto Sans et Noto Sans Mono](https://notofonts.github.io/) (paquets `noto-fonts` sous Arch,
`fonts-noto-core fonts-noto-mono` sous Debian/Ubuntu).
```
quarto render # tous les supports
+2 -2
View File
@@ -17,9 +17,9 @@ format:
margin:
x: 2cm
y: 2.2cm
mainfont: "Segoe UI"
mainfont: "Noto Sans"
fontsize: 10pt
codefont: "Consolas"
codefont: "Noto Sans Mono"
toc: false
highlight-style: modele/code.theme
include-in-header: modele/entete.typ
+104 -3
View File
@@ -126,6 +126,8 @@ def installer_quarto():
paquet = telecharger_quarto(f"linux-{arch}.deb")
print(" Votre mot de passe peut être demandé (installation système).")
subprocess.run(["sudo", "apt-get", "install", "-y", str(paquet)])
elif SYSTEME == "Linux" and shutil.which("pacman"):
return installer_quarto_arch()
else:
return False
except Exception as erreur: # réseau indisponible, fichier introuvable…
@@ -134,8 +136,30 @@ def installer_quarto():
return True
def installer_quarto_arch():
"""Arch Linux et dérivées : dépôts officiels si le paquet y existe, sinon AUR via yay (ou paru)."""
for nom in ("quarto-cli", "quarto"):
if subprocess.run(["pacman", "-Si", nom], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL).returncode == 0:
print(" Votre mot de passe peut être demandé (installation système).")
subprocess.run(["sudo", "pacman", "-S", "--needed", nom])
return True
paquet_aur = "quarto-cli-bin" # binaire officiel empaqueté, à jour (quarto-cli compile depuis les sources)
for assistant_aur in ("yay", "paru"):
if shutil.which(assistant_aur):
print(f" Quarto n'est disponible que dans l'AUR : installation de « {paquet_aur} » avec {assistant_aur}.")
print(" Validez les questions posées ; votre mot de passe sera demandé à la fin.")
# Jamais avec sudo : yay et paru s'exécutent en utilisateur normal et appellent sudo eux-mêmes.
subprocess.run([assistant_aur, "-S", "--needed", paquet_aur])
return True
print(" Sous Arch, Quarto n'est disponible que dans l'AUR (paquet « quarto-cli-bin »),")
print(" et aucun assistant AUR (yay ou paru) n'a été trouvé sur cet ordinateur.")
print(" Installez yay (https://github.com/Jguer/yay) puis relancez, ou installez le paquet à la main.")
return False
def verifier_quarto():
titre("1/3 Quarto (outil de mise en page)")
titre("1/4 Quarto (outil de mise en page)")
quarto = trouver_quarto()
if quarto:
print(f" Quarto est installé : {quarto}")
@@ -155,6 +179,82 @@ def verifier_quarto():
return quarto
# --- Polices -----------------------------------------------------------------------
DEPOT_NOTO = "https://github.com/notofonts/notofonts.github.io/raw/main/fonts"
POLICES = { # famille attendue par _quarto.yml -> fichiers à installer si elle manque
"Noto Sans": [f"NotoSans/hinted/ttf/NotoSans-{s}.ttf" for s in
("Regular", "Italic", "SemiBold", "SemiBoldItalic", "Bold", "BoldItalic")],
"Noto Sans Mono": [f"NotoSansMono/hinted/ttf/NotoSansMono-{s}.ttf" for s in ("Regular", "Bold")],
}
PAQUETS_POLICES = { # gestionnaire Linux -> commande d'installation des deux familles
"apt-get": ["sudo", "apt-get", "install", "-y", "fonts-noto-core", "fonts-noto-mono"],
"pacman": ["sudo", "pacman", "-S", "--needed", "noto-fonts"],
"dnf": ["sudo", "dnf", "install", "-y", "google-noto-sans-fonts", "google-noto-sans-mono-fonts"],
"zypper": ["sudo", "zypper", "install", "-y", "noto-sans-fonts", "noto-sans-mono-fonts"],
}
def polices_manquantes(quarto):
"""Familles absentes, d'après la liste des polices réellement visibles par Typst."""
resultat = subprocess.run([quarto, "typst", "fonts"], capture_output=True, text=True,
encoding="utf-8", errors="replace")
sortie = resultat.stdout + resultat.stderr # Quarto écrit la liste sur la sortie d'erreur
familles = {ligne.strip() for ligne in sortie.splitlines()}
return [f for f in POLICES if f not in familles]
def dossier_polices_utilisateur():
if SYSTEME == "Windows":
return Path(os.environ["LOCALAPPDATA"]) / "Microsoft/Windows/Fonts"
if SYSTEME == "Darwin":
return Path.home() / "Library/Fonts"
return Path.home() / ".local/share/fonts"
def telecharger_polices(familles):
"""Installe les polices pour l'utilisateur courant (aucun droit administrateur nécessaire)."""
dossier = dossier_polices_utilisateur()
dossier.mkdir(parents=True, exist_ok=True)
for famille in familles:
for chemin in POLICES[famille]:
cible = dossier / Path(chemin).name
print(f" Téléchargement de {cible.name}...")
urllib.request.urlretrieve(f"{DEPOT_NOTO}/{chemin}", cible)
if SYSTEME == "Windows": # déclarer la police pour l'utilisateur (comme « Installer » dans l'Explorateur)
import winreg
with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows NT\CurrentVersion\Fonts", 0,
winreg.KEY_SET_VALUE) as cle:
winreg.SetValueEx(cle, f"{cible.stem} (TrueType)", 0, winreg.REG_SZ, str(cible))
if SYSTEME == "Linux" and shutil.which("fc-cache"):
subprocess.run(["fc-cache", "-f", str(dossier)], stdout=subprocess.DEVNULL)
def verifier_polices(quarto):
titre("2/4 Polices (Noto Sans et Noto Sans Mono)")
manquantes = polices_manquantes(quarto)
if not manquantes:
print(" Les polices sont installées.")
return
print(f" Polices manquantes : {', '.join(manquantes)}.")
print(" Sans elles, les documents seraient produits avec une police de remplacement.")
if not oui_non(" Les installer maintenant ?"):
return
gestionnaire = next((g for g in PAQUETS_POLICES if SYSTEME == "Linux" and shutil.which(g)), None)
try:
if gestionnaire:
print(" Votre mot de passe peut être demandé (installation système).")
subprocess.run(PAQUETS_POLICES[gestionnaire])
if not gestionnaire or polices_manquantes(quarto):
telecharger_polices(polices_manquantes(quarto))
except Exception as erreur:
print(f" L'installation des polices a échoué : {erreur}")
reste = polices_manquantes(quarto)
print(" Polices installées." if not reste else
f" Toujours introuvables : {', '.join(reste)} (les documents seront produits quand même).")
# --- Environnement Python des schémas ----------------------------------------------
def python_du_venv():
@@ -162,7 +262,7 @@ def python_du_venv():
def preparer_venv():
titre("2/3 Environnement Python (schémas)")
titre("3/4 Environnement Python (schémas)")
empreinte = hashlib.sha256(EXIGENCES.read_bytes()).hexdigest()
temoin = VENV / ".empreinte-requirements"
if python_du_venv().exists() and temoin.exists() and temoin.read_text().strip() == empreinte:
@@ -207,7 +307,7 @@ def ouvrir_dossier(dossier):
def generer(quarto, venv_ok):
titre("3/3 Génération des documents")
titre("4/4 Génération des documents")
i_format = choisir("Quel format ?", [f[0] for f in FORMATS])
libelle, cible, extension = FORMATS[i_format]
supports = lister_supports()
@@ -244,6 +344,7 @@ def main():
print("Python 3.9 ou plus récent est nécessaire.")
raise SystemExit(1)
quarto = verifier_quarto()
verifier_polices(quarto)
venv_ok = preparer_venv()
while True:
generer(quarto, venv_ok)