Files
Forge-Engine/screens/rendering/render_icone.py
T
william 6d80ed6958 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).
2026-08-24 20:11:49 +02:00

25 lines
1.3 KiB
Python

from .visible_attrs import _visible_attrs
from .style_string import _style_string
from .attr_string import _attr_string
from ..widgets.fontawesome_icons import FONTAWESOME_ICONS
def _render_icone(el, meta, slug=None, children_map=None, ctx=None, parent_flex_direction=None):
"""Widget Icône — un SVG affiché en silhouette via "mask-image" (voir
.icon-svg dans style.css), pas une police d'icônes : certains
navigateurs/extensions bloquent le chargement de polices web tierces
(protection anti-fingerprinting), ce qui rendait les icônes Font Awesome
invisibles quelle que soit leur source — un SVG posé en masque n'est
jamais concerné. Se colore via "color" (couleur du texte, déjà un
réglage existant), se dimensionne via "font-size" (le masque fait 1em)."""
raw_attrs = el.get("attributes") or {}
icon_slug = raw_attrs.get("_icon_slug") or "star"
if icon_slug not in FONTAWESOME_ICONS:
icon_slug = "star" # attribut corrompu/vidé : jamais d'icône cassée
attrs = _visible_attrs(el, meta, ctx)
existing_class = attrs.pop("class", "")
attrs["class"] = (existing_class + " icon-svg").strip()
icon_url = f"/static/icons/{icon_slug}.svg"
style = _style_string(el, f" --icon-url:url('{icon_url}');", parent_flex_direction)
return f"<i {_attr_string(attrs, style)}></i>"