document_engine/labels/quiz_config.py (nouveau) : modele de donnees complet, meme convention resolve_X/sanitize_X que game_engine/rendering/quiz_box_config.py cote jeu (aucun import croise) - DEFAULT_QUIZ_CONFIG, sanitize_quiz_config (valide/nettoie chaque question independamment, jamais ne leve, tronque a 2-4 choix, remet correct_index a 0 si hors bornes/non-entier, clampe points >= 0 et timer_seconds dans [5,300]), quiz_total_points. Cote serveur, routes/document/document_element_update.py revalide desormais un quiz avant persistance (seul kind qui en a besoin - les autres n'ont que des attributs scalaires sans structure a garantir) et renvoie les attributs REELLEMENT persistes dans sa reponse, pour que le client ne derive jamais de la verite serveur apres un nettoyage serveur (ex. choix en trop tronque). Cote editeur (static/document/js/document-editor.js), le panneau Proprietes d'un quiz est desormais reel : chronometre optionnel, couleur de theme, liste de questions repetable (ajout/suppression), chacune avec son texte, un nombre de choix ajustable (2-4, les inputs texte suivent), le choix correct via un radio par question, et les points gagnes. Le rendu canevas (render_document_element.py) affiche un resume reel (nombre de questions, total des points, minuteur) au lieu du placeholder generique. Tests : document_engine/labels/quiz_config.py couvert par 13 tests purs (tests/document/test_quiz_config.py, sans Flask - defauts, troncature, validation, cas limites dont bool comme correct_index) + 1 test de route verifiant la sanitization a l'ecriture et le rendu. SKIP=djlint : backlog H021 pre-existant, aucun template touche ici. ruff/mypy --strict/vulture/bandit/import-linter/eslint/stylelint tous verts ; 63 tests cibles (document + onboarding + auth) verifies fraichement + verification manuelle live via le serveur de dev (ajout, sanitization sur choix invalides/en trop, rendu du resume avec minuteur). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2.5 KiB
document_engine/rendering/
Rendu HTML du document — point d'entrée unique utilisé à la fois par le
canevas d'édition et par le Mode Aperçu (même fonction, voir
docs/plan/PLAN.md — "Aperçu réel").
render_document(elements: list[dict[str, Any]]) -> str
Assemble le document entier à partir de la liste à plat renvoyée par
document_engine.list_document_elements : regroupe les éléments par
parent_id, puis rend récursivement les éléments top-niveau dans
l'ordre (une rangée rend elle-même ses propres enfants côte à côte).
- Retour : le HTML complet du document.
- Exceptions : aucune.
render_document_element(el: dict[str, Any], children_by_parent: dict[int | None, list[dict[str, Any]]]) -> str
HTML d'un seul élément — dispatch par dict (table _RENDERERS) selon
el["kind"], plutôt qu'un enchaînement de if (mirroir de l'esprit de
game_engine/scenes/render_scene_object.py). children_by_parent est le
regroupement précalculé par render_document, transmis pour que les
rangées puissent rendre récursivement leurs enfants sans refaire le
regroupement à chaque appel.
- Retour : le HTML de cet élément (et de ses enfants s'il s'agit d'une rangée).
- Exceptions : aucune ; un
kindinconnu produit un blocdocUnknownvisible plutôt qu'une levée d'exception.
Détail des rendus par catégorie (fonctions privées, table de dispatch)
- Rangée (
row) : conteneur flex (gap/align-items/justify-contentréels depuisattributes), enfants rendus récursivement. - Formes (
rectangle/cercle/triangle/trait) :<div>positionné en absolu (x/y/width/height/rotation/z_indexréels) contenant un SVG (rect/circle/polygon/lineselon le type). - Texte (
titre/paragraphe) :<div>stylé selonstyle(préréglage taille/graisse/interligne) etbold/italic/underline/align/color. - Image :
<img>, ou un bloc placeholder sisrcest vide. - Bouton :
<button>avec sonlabelet undata-targetoptionnel. - Quiz : carte résumant la config réelle (nombre de questions, total
des points via
quiz_total_points, minuteur si activé) — sanitizée (sanitize_quiz_config) avant lecture, jamais un rendu direct d'attributesbrut. - Autres mini-jeux (
association/memory/mots/scenario/zones) : carte placeholder portant le libellé du type (voirdocument_engine/labels/element_kind_labels.py) — emplacement réservé, formulaire de contenu dédié hors périmètre de cette passe.