diff --git a/.gitignore b/.gitignore index c310d0c..e689032 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,11 @@ -site/\n.obsidian/\n__pycache__/ +site/ +__pycache__/ + +# Assets binaires — générés par scripts/build-assets.py +# Hébergés sur https://static.alpinux.org/logo/ +docs/assets/*.png +docs/assets/*.ico +docs/assets/images/ + +# Obsidian (local uniquement) +.obsidian/ diff --git a/docs/assets/alpinux-logo.svg b/docs/assets/alpinux-logo.svg new file mode 100644 index 0000000..8c1fd3d --- /dev/null +++ b/docs/assets/alpinux-logo.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Alpinux + + diff --git a/home/index.html b/home/index.html new file mode 100644 index 0000000..0e04d47 --- /dev/null +++ b/home/index.html @@ -0,0 +1,297 @@ + + + + + + + + Alpinux — Le LUG de Savoie + + + + + + + + + + + +
+
+ Logo Alpinux +
+
+ Alpinux +
+
le LUG de Savoie
+
+
+

+ Association loi 1901 dédiée à Linux et aux logiciels libres en Savoie. + Réunions tous les 1er et 3e jeudis du mois à la Dynamo Chambéry. +

+
+ + + +
+ +

Prochains événements

+
+
+
1er & 3e jeudis
+
Réunion mensuelle
+
📍 Dynamo Chambéry — 18h00
+
+
+
Voir le calendrier
+
Install Party & ateliers
+ +
+
+ +

Nos services

+
+ +
📖
+
Wiki
+
Guides, tutoriels et présentations
+
+ +
🔐
+
Portail membres
+
Espace adhérent, Nextcloud, Dolibarr
+
+ +
🐧
+
Install Party
+
Événements & inscriptions
+
+ +
💻
+
Gitea
+
Dépôts de code de l'association
+
+ +
🎮
+
Jeux & quiz
+
Mini-jeux et questionnaires interactifs
+
+
+ +
+ + + + + diff --git a/mkdocs.yml b/mkdocs.yml index 2e8603c..a97be46 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -23,7 +23,7 @@ theme: - search.suggest - content.code.copy - content.code.select - logo: assets/alpinux-logo.png + logo: assets/alpinux-logo.svg font: text: Roboto code: Roboto Mono @@ -48,6 +48,9 @@ markdown_extensions: - toc: permalink: true - footnotes + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg extra: social: diff --git a/overrides/main.html b/overrides/main.html index ca0e9a4..e1aaa88 100644 --- a/overrides/main.html +++ b/overrides/main.html @@ -5,3 +5,10 @@ Alpinux {% endblock %} + +{% block extrahead %} + + + + +{% endblock %} diff --git a/overrides/partials/logo.html b/overrides/partials/logo.html new file mode 100644 index 0000000..98a1aa8 --- /dev/null +++ b/overrides/partials/logo.html @@ -0,0 +1,3 @@ +Alpinux diff --git a/scripts/build-assets.py b/scripts/build-assets.py new file mode 100644 index 0000000..f34e973 --- /dev/null +++ b/scripts/build-assets.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +""" +Génère les assets binaires (logo PNG + favicons) depuis la source SVG. +Dépendances : Pillow, chromium + +Usage : + python3 scripts/build-assets.py [--out /chemin/de/sortie] + +Les fichiers générés sont ensuite uploadés sur static.alpinux.org/logo/ +""" + +import argparse +import subprocess +import tempfile +import os +from pathlib import Path + +from PIL import Image, ImageDraw, ImageFont + +REPO = Path(__file__).resolve().parent.parent +SVG = REPO / "docs/assets/alpinux-logo.svg" +FONT_R = "/usr/share/fonts/truetype/msttcorefonts/arial.ttf" +FONT_B = "/usr/share/fonts/truetype/msttcorefonts/arialbd.ttf" +COLOR = (15, 78, 143) # #0f4e8f + + +def render_shapes(svg_path: Path, width: int, height: int) -> Image.Image: + """Render SVG shapes via chromium headless (no text).""" + html = f""" + + + + +""" + with tempfile.NamedTemporaryFile(suffix=".html", mode="w", delete=False) as f: + f.write(html) + tmp_html = f.name + out_png = tmp_html.replace(".html", ".png") + subprocess.run([ + "chromium", "--headless", "--disable-gpu", "--no-sandbox", + f"--screenshot={out_png}", f"--window-size={width},{height}", + f"file://{tmp_html}" + ], capture_output=True) + img = Image.open(out_png).convert("RGBA") + os.unlink(tmp_html) + os.unlink(out_png) + return img + + +def add_text(canvas: Image.Image) -> Image.Image: + """Composite Alpinux text with correct weights onto the canvas.""" + draw = ImageDraw.Draw(canvas) + size = 30 + f_reg = ImageFont.truetype(FONT_R, size) + f_bld = ImageFont.truetype(FONT_B, size) + parts = [("A", False), ("l", True), ("p", False), ("inux", True)] + + widths = [] + for char, bold in parts: + f = f_bld if bold else f_reg + bb = f.getbbox(char) + widths.append(bb[2] - bb[0]) + + total_w = sum(widths) + x = (canvas.width - total_w) // 2 + y = 164 + (36 - size) // 2 + 1 + + for (char, bold), w in zip(parts, widths): + f = f_bld if bold else f_reg + bb = f.getbbox(char) + draw.text((x - bb[0], y - bb[1]), char, font=f, fill=COLOR) + x += w + + return canvas + + +def build_logo(out_dir: Path): + """Build 200×200 logo PNG.""" + shapes = render_shapes(SVG, 200, 164) + canvas = Image.new("RGBA", (200, 200), (255, 255, 255, 255)) + canvas.paste(shapes, (0, 0)) + canvas = add_text(canvas) + path = out_dir / "alpinux-logo.png" + canvas.convert("RGB").save(path) + print(f" {path} (200×200)") + + # 512px high-res version + shapes512 = render_shapes(SVG, 512, 421) + canvas512 = Image.new("RGBA", (512, 512), (255, 255, 255, 255)) + canvas512.paste(shapes512, (0, 0)) + # Scale text proportionally + draw = ImageDraw.Draw(canvas512) + size = 77 + f_reg = ImageFont.truetype(FONT_R, size) + f_bld = ImageFont.truetype(FONT_B, size) + parts = [("A", False), ("l", True), ("p", False), ("inux", True)] + widths = [f_bld.getbbox(c)[2]-f_bld.getbbox(c)[0] if b else f_reg.getbbox(c)[2]-f_reg.getbbox(c)[0] for c,b in parts] + total_w = sum(widths) + x = (512 - total_w) // 2 + y = 421 + (91 - size) // 2 + 2 + for (char, bold), w in zip(parts, widths): + f = f_bld if bold else f_reg + bb = f.getbbox(char) + draw.text((x - bb[0], y - bb[1]), char, font=f, fill=COLOR) + x += w + path512 = out_dir / "alpinux-logo-512.png" + canvas512.convert("RGB").save(path512) + print(f" {path512} (512×512)") + + +def build_favicons(out_dir: Path): + """Build favicon PNG set + .ico from the icon portion of the SVG.""" + icon_src = render_shapes(SVG, 200, 164).crop((0, 0, 164, 164)) + + sizes = { + "favicon-16.png": 16, + "favicon-32.png": 32, + "favicon.png": 48, + "favicon-96.png": 96, + "favicon-192.png": 192, + } + imgs = {} + for name, sz in sizes.items(): + img = icon_src.resize((sz, sz), Image.LANCZOS) + bg = Image.new("RGBA", (sz, sz), (255, 255, 255, 255)) + bg.paste(img, (0, 0)) + p = out_dir / name + bg.save(p) + imgs[sz] = bg + print(f" {p} ({sz}×{sz})") + + ico = out_dir / "favicon.ico" + imgs[16].save(ico, format="ICO", sizes=[(16,16),(32,32),(48,48)], + append_images=[imgs[32], imgs[48]]) + print(f" {ico} (multi-size: 16+32+48)") + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--out", default="/tmp/alpinux-static-assets", + help="Répertoire de sortie (défaut: /tmp/alpinux-static-assets)") + args = parser.parse_args() + + out_dir = Path(args.out) + out_dir.mkdir(parents=True, exist_ok=True) + + print("Génération des assets Alpinux...") + build_logo(out_dir) + build_favicons(out_dir) + print(f"\nFichiers dans : {out_dir}") + print("À uploader sur : static.alpinux.org/logo/") + + +if __name__ == "__main__": + main() diff --git a/scripts/static.alpinux.org.vhost.conf b/scripts/static.alpinux.org.vhost.conf new file mode 100644 index 0000000..9f76113 --- /dev/null +++ b/scripts/static.alpinux.org.vhost.conf @@ -0,0 +1,37 @@ +# Apache vhost pour static.alpinux.org +# À créer via ISPConfig : Sites > Ajouter un site web +# Domaine : static.alpinux.org | DocumentRoot : /var/www/clients/clientX/webY/web +# Activer SSL Let's Encrypt dans ISPConfig +# +# Ou, si créé manuellement, coller ce fichier dans /etc/apache2/sites-enabled/ + + + ServerName static.alpinux.org + Redirect permanent / https://static.alpinux.org/ + + + + ServerName static.alpinux.org + DocumentRoot /var/www/clients/client1/web-static/web + + # En-têtes CORS — permet au wiki et à la page d'accueil de charger les assets + Header always set Access-Control-Allow-Origin "*" + Header always set Cache-Control "public, max-age=31536000, immutable" + + # Pas d'exécution PHP + php_admin_flag engine Off + + + Options -Indexes +FollowSymLinks + AllowOverride None + Require all granted + + + # Logs + ErrorLog /var/log/apache2/static.alpinux.org-error.log + CustomLog /var/log/apache2/static.alpinux.org-access.log combined + + SSLEngine on + SSLCertificateFile /etc/letsencrypt/live/static.alpinux.org/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/static.alpinux.org/privkey.pem +