Switch icons from a webfont to self-hosted SVG masks — the webfont was the actual problem

Self-hosting Font Awesome's font files (previous commit) didn't fix it either: every icon in the picker still failed identically. That rules out CDN/network blocking specifically and points to something in the browser blocking custom webfont loading altogether regardless of origin (common with strict anti-fingerprinting protection, e.g. Brave's font blocking or certain privacy extensions — @font-face loading is a well-known fingerprinting vector).

Replaced the whole mechanism: each of the 258 curated icons is now a real downloaded SVG file (static/icons/*.svg, sourced from Font Awesome 5 Free's official SVG package) displayed via CSS mask-image (.icon-svg in style.css) instead of a font glyph. A masked SVG isn't a font resource at all, so it isn't subject to webfont-blocking — and it still colors via the existing "color" style property (background-color:currentColor) and sizes via font-size (1em), so no change to how the widget's other controls work.

The "Icône" widget now stores just the icon's slug (e.g. "trophy") in a dedicated attribute instead of a full CSS class string, rendered by a new special_render (render_icone.py). Updated the add-gallery and the properties-panel picker modal to use the same mask technique for their previews, and element_add.py to validate the slug against the curated list. Removed the now-unused self-hosted Font Awesome CSS/webfont files and the <link> tags — no font dependency left for icons at all.

Verified end to end (gallery renders with real SVG previews, simulated add creates a correctly-attributed element, the SVG file is actually served, the per-element picker reflects the current icon). Full suite green (89).
This commit is contained in:
william
2026-08-24 20:11:49 +02:00
parent 15cad6c50f
commit 6d80ed6958
270 changed files with 346 additions and 46 deletions
+11 -9
View File
@@ -316,17 +316,19 @@ WIDGETS = {
"controls": BULMA_TABS_CONTROLS,
},
"icone": {
# La classe Font Awesome ("fa-solid fa-xxx") EST le contenu visuel de
# ce widget — posée soit en cliquant/glissant une icône depuis la
# galerie du panneau de propriétés (voir routes/elements/element_add.py,
# qui pré-remplit ce réglage), soit tapée à la main ici pour n'importe
# quelle icône Font Awesome 5 hors de la sélection curatée de la
# galerie (voir fontawesome_icons.py).
"label": "Icône", "icon": "🔤", "tag": "i", "has_content": False,
# Un SVG affiché en silhouette via "mask-image" (voir .icon-svg dans
# style.css et render_icone.py) plutôt qu'une police d'icônes —
# certains navigateurs/extensions bloquent le chargement de polices
# web tierces (protection anti-fingerprinting), ce qui rendait
# invisible toute icône Font Awesome classique quelle que soit sa
# source (CDN ou même hébergée ici). Le nom de l'icône (ex. "star")
# est posé soit en cliquant/glissant depuis la galerie du panneau de
# propriétés (voir routes/elements/element_add.py), soit choisi via
# le sélecteur visuel du réglage "Icône" — jamais tapé à la main.
"label": "Icône", "icon": "🔤", "tag": "i", "has_content": False, "special_render": "icone",
"w": 15, "h": 15, "default_content": "",
"controls": [
c_text("icon_class", "Icône (classe Font Awesome 5)", "attr:class",
default="fa-solid fa-star", placeholder="fa-solid fa-heart", group="Contenu"),
c_text("icon_class", "Icône", "attr:_icon_slug", default="star", group="Contenu"),
c_slider("font-size", "Taille", "style:font-size", min=10, max=160, default=32, group="Texte"),
c_color("color", "Couleur", "style:color", "#e8eaf0", group="Texte"),
],