Export Web/SCORM : inline les icônes en data: URI (CORS Firefox/file://)
Le chemin relatif ("icons/x.svg") était enfin correct, mais Firefox
bloque encore par CORS TOUT chemin de fichier pour mask-image sous
file:// — chaque ressource file:// y est une origine opaque distincte,
indépendamment du chemin (troisième rapport du même utilisateur). Seule
une data: URI (aucune requête réseau séparée) contourne le problème.
_build_icon_data_uris (build_scorm_package.py) encode chaque icône
RÉELLEMENT posée dans le jeu (élément direct ou niché dans un élément de
jeu réutilisable) en base64, ajouté au payload sous
gameData.icon_data_uris ; forgeRenderIcone (JS) le consulte pour toute
régénération après une action, avec repli sur l'ancien chemin relatif
si jamais une icône n'a pas été pré-encodée.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b60fe63a54
commit
82d00b3800
+23
-22
@@ -50,25 +50,26 @@ def test_export_scorm_index_html_is_offline_and_self_contained(client, game):
|
||||
assert "let gameData = " in html
|
||||
|
||||
|
||||
def test_export_scorm_icon_widget_uses_a_relative_url(client, game):
|
||||
"""Régression signalée par un utilisateur : render_icone.py construit
|
||||
son URL en dur avec un préfixe "/static/..." (correct EN LIGNE, où il
|
||||
part de la racine du serveur Flask) — jamais réécrit par le refactor
|
||||
asset_url de templates/play.html (celui-ci ne touche que les <script>/
|
||||
<link> du template, pas le rendered_html déjà bake dans le payload).
|
||||
|
||||
Cette URL, posée en style INLINE (--icon-url), est CONSOMMÉE par
|
||||
`mask-image: var(--icon-url)` dans static/style.css (voir .icon-svg) —
|
||||
une URL relative dans une propriété personnalisée CSS se résout par
|
||||
rapport à LA FEUILLE DE STYLE où le var() est utilisé, pas où elle est
|
||||
définie (piège CSS connu) : un premier correctif ("static/icons/x.svg")
|
||||
redevenait donc "static/static/icons/x.svg" une fois résolu depuis
|
||||
static/style.css (CORS bloqué sur ce chemin doublé — deuxième rapport
|
||||
du même utilisateur) — seul "icons/x.svg" (sans "static/") est correct
|
||||
une fois résolu depuis static/style.css. Voir aussi le miroir JS
|
||||
(forgeRenderIcone, static/js/play/offline/render-special-widgets.js),
|
||||
qui régénère ce même widget après une action, et devait être corrigé
|
||||
séparément."""
|
||||
def test_export_scorm_icon_widget_is_inlined_as_a_data_uri(client, game):
|
||||
"""Régression signalée par un utilisateur (trois fois de suite) :
|
||||
render_icone.py construit son URL en dur avec un préfixe "/static/..."
|
||||
(correct EN LIGNE, où il part de la racine du serveur Flask). Cette
|
||||
URL, posée en style INLINE (--icon-url), est CONSOMMÉE par `mask-image:
|
||||
var(--icon-url)` dans static/style.css (voir .icon-svg) :
|
||||
- un premier correctif ("static/icons/x.svg") ignorait qu'une URL
|
||||
relative dans une propriété personnalisée CSS se résout par rapport
|
||||
à LA FEUILLE DE STYLE où le var() est utilisé (static/style.css),
|
||||
pas où elle est définie (piège CSS connu) — devenait donc
|
||||
"static/static/icons/x.svg" ;
|
||||
- un second correctif ("icons/x.svg", sans "static/") réglait bien CE
|
||||
chemin, mais Firefox bloque encore par CORS TOUT chemin de fichier
|
||||
pour mask-image sous file:// (chaque ressource file:// y est une
|
||||
origine opaque distincte, indépendamment du chemin).
|
||||
Seule une data: URI (aucune requête réseau séparée) contourne
|
||||
entièrement le problème — voir _build_icon_data_uris
|
||||
(publish/build_scorm_package.py) et son miroir JS (forgeRenderIcone,
|
||||
static/js/play/offline/render-special-widgets.js, qui régénère ce
|
||||
même widget après une action et devait être corrigé séparément)."""
|
||||
import re
|
||||
resp = client.post(f"/game/{game}/screens/new", data={"name": "Accueil"}, follow_redirects=False)
|
||||
screen_id = int(re.search(r"/screens/(\d+)/edit", resp.headers["Location"]).group(1))
|
||||
@@ -79,9 +80,9 @@ def test_export_scorm_icon_widget_uses_a_relative_url(client, game):
|
||||
import io
|
||||
with zipfile.ZipFile(io.BytesIO(resp.data)) as zf:
|
||||
html = zf.read("index.html").decode("utf-8")
|
||||
assert "icons/star.svg" in html
|
||||
assert "static/icons/star.svg" not in html
|
||||
assert "/static/icons/star.svg" not in html
|
||||
assert "--icon-url:url('data:image/svg+xml;base64," in html
|
||||
assert "icons/star.svg" not in html
|
||||
assert '"icon_data_uris": {"star":' in html
|
||||
|
||||
|
||||
def test_export_scorm_databound_text_resolves_a_relation_field(client, game):
|
||||
|
||||
Reference in New Issue
Block a user