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
+22 -2
View File
@@ -184,14 +184,34 @@ body.builderBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden; d
.widgetGrid{ display:grid; grid-template-columns:1fr 1fr; gap:8px; }
/* Galerie d'icônes Font Awesome (panneau de propriétés) — voir
/* Icônes (widget Icône + galerie du panneau de propriétés) — SVG posé en
silhouette via "mask-image" plutôt qu'une police d'icônes (@font-face) :
se colore avec "color"/"background-color" comme du texte, MAIS ne dépend
d'aucun fichier de police externe — certains navigateurs/extensions
bloquent le chargement de polices web tierces (protection anti-
fingerprinting), ce qui rendait toutes les icônes Font Awesome invisibles
quelle que soit leur source (CDN ou même hébergées ici). Un simple SVG
affiché en masque n'est jamais concerné par ce blocage. Voir
render_icone.py (widget) et fontawesome_icons.py (liste + chemin des
fichiers, statiques dans static/icons/). */
.icon-svg{
display:inline-block; width:1em; height:1em; flex:0 0 auto;
background-color:currentColor;
-webkit-mask-image:var(--icon-url); mask-image:var(--icon-url);
-webkit-mask-size:contain; mask-size:contain;
-webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
-webkit-mask-position:center; mask-position:center;
}
/* Galerie d'icônes (panneau de propriétés) — voir
fontawesome_icons.py et addIconElement()/filterIconGallery() plus bas. */
.iconGallery{ display:grid; grid-template-columns:repeat(6, 1fr); gap:6px; max-height:220px; overflow-y:auto; margin-top:8px; }
.iconGalleryTile{
aspect-ratio:1; display:flex; align-items:center; justify-content:center;
background:var(--panel2); border:1px solid var(--border); border-radius:6px;
color:var(--text); cursor:grab; font-size:15px; padding:0;
color:var(--text); cursor:grab; padding:0;
}
.iconGalleryTile .icon-svg{ width:16px; height:16px; }
.iconGalleryTile:hover{ border-color:var(--accent); color:var(--accent); }
.iconGalleryTile.dragging{ opacity:0.4; }
.iconGalleryTile.iconHidden{ display:none; }