Audit complet de mise en forme — Liste à puces/numérotée (4e élément)
Implémente toutes les options manquantes identifiées pour les listes :
typographie complète, style/position/couleur/taille de puce (validés
selon le kind), puce personnalisée en SVG pour les listes à puces,
padding uniforme par élément (nouveau, il n'y en avait aucun), espacement
entre éléments réglable, et tous les attributs de boîte partagés sur la
liste entière. Bordure/fond/padding par élément individuel et sous-listes
imbriquées volontairement différés (portée actée avec l'utilisateur
avant implémentation : transformeraient le stockage des éléments en
objets structurés, chantier bien plus lourd).
Trois ajouts transversaux bénéficiant à plusieurs éléments : sections
"Contenu"/"Conteneur" dans tous les panneaux de propriétés, alignement
vertical du contenu dans son bloc (Titre/Paragraphe/Liste/Image
légendée), et une option pour retirer un thème appliqué ("Aucun modèle"
dans la modale, avec une nouvelle fonction db.remove_document_theme).
Quatre bugs réels trouvés et corrigés en chaîne pendant la validation
avec le thème "Sécurité incendie" : un badge de thème s'affichait
au-dessus du texte au lieu d'à côté ; le correctif a d'abord fait
disparaître les puces/numéros natifs de TOUTES les listes (bug plus
grave que celui corrigé) ; puis un marqueur natif redondant apparaissait
à côté du badge du thème ; puis une règle CSS site-large de spécificité
supérieure empêchait silencieusement ce dernier correctif. Chaque étape
vérifiée par navigateur automatisé sur un support jetable.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
8f879f6321
commit
4db1269348
@@ -298,7 +298,163 @@ sinon d'un état neutre. Bénéficie automatiquement à TOUS les éléments
|
||||
qui utilisent déjà ce module (Titre/Paragraphe/Image/Bouton), aucune
|
||||
modification nécessaire ailleurs.
|
||||
|
||||
### 4. Liste à puces / numérotée — à faire
|
||||
### 4. Liste à puces / numérotée — ✅ audité et validé (commité)
|
||||
|
||||
**Portée actée avec l'utilisateur avant implémentation** (question
|
||||
posée explicitement, deux catégories du tableau impliquaient de
|
||||
transformer `items` — une simple liste de chaînes — en objets
|
||||
structurés) : style sur la LISTE ENTIÈRE uniquement, jamais par élément
|
||||
individuel ni de sous-listes imbriquées (chantier bien plus lourd,
|
||||
différé à une demande séparée si besoin). Seule exception actée : un
|
||||
padding UNIFORME appliqué à chaque élément (`item_padding`), pas encore
|
||||
réglable individuellement.
|
||||
|
||||
Implémenté : gras/italique/souligné, police (liste déroulante web-safe,
|
||||
`FORGE_DOC_FONT_FAMILY_OPTIONS` réutilisé), taille de police, hauteur de
|
||||
ligne, couleur du texte, style de puce (`list_style_type`, options
|
||||
propres à chaque kind — disque/cercle/carré/aucune pour puces,
|
||||
1-2-3/01-02-03/i-ii-iii/I-II-III/a-b-c/A-B-C/aucune pour numérotée),
|
||||
position de la puce (intérieure/extérieure), couleur et taille de puce
|
||||
indépendantes du texte, puce personnalisée (icône SVG, liste à puces
|
||||
uniquement — encodée en URI de données pour `list-style-image`),
|
||||
espacement intérieur par élément (`item_padding`, **"6px" par défaut,
|
||||
retour utilisateur explicite : "il faut un padding de base par élément
|
||||
de liste car y en a pas aujourd'hui"** — n'existait pas du tout avant),
|
||||
espacement entre éléments réglable (`item_spacing`), tous les attributs
|
||||
de boîte partagés sur la liste entière (padding/margin/fond/bordure/
|
||||
ombre/opacité/position du bloc).
|
||||
|
||||
Mécanisme technique notable : `marker_color`/`marker_size`/
|
||||
`item_padding`/`item_spacing` ne peuvent pas passer par un style inline
|
||||
classique sur le `<ul>`/`<ol>` (impossible de cibler le `::marker` ou le
|
||||
padding des `<li>` enfants depuis le style de leur parent) — résolu via
|
||||
des propriétés personnalisées CSS (`--doc-marker-color` etc.), posées
|
||||
en inline sur le conteneur et consommées par une règle CSS dédiée
|
||||
(`.docList li`/`.docList li::marker`) qui en hérite. Même technique déjà
|
||||
utilisée pour la position du bloc des éléments enveloppés (Image).
|
||||
|
||||
Volontairement laissé de côté (portée actée ci-dessus) : style/bordure/
|
||||
fond par élément individuel, sous-listes imbriquées — nécessiteraient
|
||||
de transformer `items` (liste de chaînes) en objets structurés, refonte
|
||||
du panneau et du stockage. Comme les autres éléments : responsive par
|
||||
taille d'écran.
|
||||
|
||||
**Existant retroactivement inchangé** : une liste déjà créée avant ce
|
||||
commit garde ses anciens attributs (juste `items`) — `item_padding`
|
||||
n'apparaît en style inline QUE pour les nouvelles listes ; ouvrir le
|
||||
panneau Propriétés d'une ancienne liste et toucher un réglage la fait
|
||||
bénéficier des nouveaux défauts au passage.
|
||||
|
||||
**Bug réel corrigé pendant le test (retour utilisateur : "si j'enlève
|
||||
les puces ou que les puces se mettent à l'intérieur, il reste un
|
||||
espace devant la liste, cet espace doit être supprimé")** : le
|
||||
`padding-left:1.4em` par défaut (réservé pour une puce EXTÉRIEURE)
|
||||
n'a plus lieu d'être dès que `list_style_type="none"` ou
|
||||
`list_style_position="inside"` — `_render_list` ajoute alors
|
||||
automatiquement `padding-left:0;`, prioritaire sur le CSS mais toujours
|
||||
cédant la place à un `padding` uniforme réglé explicitement par
|
||||
ailleurs (attributs de boîte partagés).
|
||||
|
||||
**Deux ajouts transversaux pendant le test, bénéficiant à plusieurs
|
||||
éléments à la fois :**
|
||||
|
||||
1. **Sections "Contenu"/"Conteneur" dans le panneau Propriétés (retour
|
||||
utilisateur : "il faut distinguer par des sections la propriété qui
|
||||
touche au conteneur de celles qui touchent à l'élément qu'il
|
||||
contient sinon c'est pas compréhensible")** : un sous-titre visuel
|
||||
(bordure du dessus) sépare maintenant, dans CHAQUE panneau qui
|
||||
utilise `box_style.py` (Titre/Paragraphe, Image, Bouton, Liste), les
|
||||
champs propres au CONTENU (texte, icône, puces...) de ceux qui
|
||||
touchent au CONTENEUR (padding/margin/fond/bordure/ombre/opacité/
|
||||
position du bloc/alignement du contenu — voir point 2). Le sous-titre
|
||||
"Conteneur" est posé UNE SEULE FOIS, à l'intérieur de
|
||||
`forgeDocRenderBoxFieldsHtml` (le module déjà partagé), jamais dupliqué
|
||||
à chaque appelant.
|
||||
2. **Alignement vertical du CONTENU dans son bloc (retour utilisateur :
|
||||
"je peux augmenter la hauteur d'un conteneur mais pas l'alignement
|
||||
vertical à l'intérieur, pour les listes et il faut aussi vérifier
|
||||
pour les autres")** : nouvel attribut partagé `content_align`
|
||||
(`"top"` par défaut, `"center"`/`"bottom"`) posé dans `BOX_DEFAULTS`,
|
||||
rendu via `render_content_align(a)` — volontairement PAS fusionné
|
||||
dans `render_box_style` (l'alignement du contenu dépend de l'axe
|
||||
interne du conteneur : `justify-content` convient à un conteneur en
|
||||
COLONNE — Titre/Paragraphe/Liste, rendus `display:flex;
|
||||
flex-direction:column;` pour l'occasion, et la figure d'une image
|
||||
légendée, déjà flex-colonne — mais serait FAUX pour le Bouton, une
|
||||
RANGÉE icône+texte qui gère déjà son axe vertical via `align-items`,
|
||||
déjà correct sans réglage). Contrôle exclu explicitement du panneau
|
||||
Bouton (`includeContentAlign: false`) pour ne jamais afficher un
|
||||
réglage sans effet.
|
||||
|
||||
**Bug réel corrigé, puis CORRIGÉ UNE SECONDE FOIS après un retour de
|
||||
régression (capture à l'appui, thème "Sécurité incendie")** :
|
||||
|
||||
1. *Premier symptôme* ("dans les liste numéroté [...] la position des
|
||||
élément à l'intérieur de base est verticale au lieu d'être
|
||||
horizontale") : ce thème remplace la puce native d'une liste par un
|
||||
badge (`::before`, voir `static/document/themes/
|
||||
securite-incendie.css`), pensé pour s'afficher À CÔTÉ du texte.
|
||||
Corrigé une première fois en posant `display:flex` sur `.docList li`
|
||||
(`static/document/document-editor.css`).
|
||||
2. *Régression introduite par ce premier correctif* ("quand j'enlève le
|
||||
thème [...] on voit plus les puces ou les numéros") : `display:flex`
|
||||
posé DIRECTEMENT sur le `<li>` remplace entièrement son
|
||||
`display:list-item` natif — ça supprime le marqueur natif (puce/
|
||||
numéro) pour TOUTE liste, avec ou sans thème (l'affirmation inverse
|
||||
dans le premier correctif était FAUSSE, corrigée après une
|
||||
vérification en conditions réelles, navigateur automatisé). **Corrigé
|
||||
en ciblant le `::before` LUI-MÊME** (`display:inline-block;
|
||||
vertical-align:middle; margin-right:10px;`), jamais son parent : le
|
||||
`<li>` garde son `display:list-item` natif (donc son marqueur), et le
|
||||
badge s'aligne quand même à côté du texte qui le suit dans le flux
|
||||
normal.
|
||||
3. *Redondance restante* : une fois le marqueur natif restauré, les
|
||||
listes du thème affichaient À LA FOIS leur badge personnalisé ET le
|
||||
marqueur natif (disc/decimal) en double — le thème ne les avait
|
||||
jamais explicitement désactivés (aucun `list-style:none` dans
|
||||
`securite-incendie.css`, il comptait implicitement sur le marqueur
|
||||
natif pour disparaître tout seul). Corrigé en ajoutant ce reset —
|
||||
avec le sélecteur d'élément (`ul.docList[...]`/`ol.docList[...]`),
|
||||
jamais seulement les classes/attributs : `static/style.css` (site
|
||||
large) porte une règle `.content ol:not([type]) {
|
||||
list-style-type: decimal; }` d'une spécificité légèrement supérieure
|
||||
qui l'emportait sinon silencieusement.
|
||||
4. *Dernière régression du même correctif* : le badge numéroté du thème
|
||||
posait lui-même `display:flex` (pour centrer son chiffre) — une
|
||||
valeur qui BLOCKIFIE le `::before` (le repousse hors du flux en
|
||||
ligne, au-dessus du texte), défaisant le point 1 pour ce cas précis.
|
||||
Corrigé en `display:inline-flex` (garde le badge en ligne tout en
|
||||
centrant quand même le chiffre à l'intérieur).
|
||||
|
||||
Chaque étape vérifiée par un navigateur automatisé (Playwright) contre
|
||||
le serveur local, sur un support jetable créé puis supprimé pour
|
||||
l'occasion — thème appliqué et retiré successivement, capture d'écran
|
||||
et styles calculés (`getComputedStyle`) inspectés à chaque fois, pas
|
||||
seulement supposés corrects.
|
||||
|
||||
**Audit final** : chaque ligne du tableau d'audit initial pour l'élément
|
||||
Liste est couverte —
|
||||
**Typo** (police/taille/gras/italique/souligné/couleur/interligne) ✅,
|
||||
**Puces/numéros** (style de puce validé par kind, image de puce
|
||||
personnalisée pour les puces, position intérieure/extérieure, couleur/
|
||||
taille de puce indépendantes du texte via propriétés personnalisées
|
||||
CSS) ✅,
|
||||
**Boîte** (padding/margin sur la liste entière via `box_style.py`,
|
||||
padding UNIFORME par élément — `item_padding`, avec un vrai défaut non
|
||||
vide comme demandé —, espacement entre éléments réglable —
|
||||
`item_spacing` —, indentation couverte par le padding partagé) ✅,
|
||||
**Bordure/fond** sur la liste entière ✅.
|
||||
Volontairement différés, portée actée explicitement AVANT
|
||||
implémentation avec l'utilisateur (question posée, réponse : liste
|
||||
entière seulement) : bordure/fond/padding/margin **par élément
|
||||
individuel** (au-delà du padding uniforme) et **listes imbriquées** —
|
||||
transformeraient `items` (liste de chaînes) en objets structurés, un
|
||||
chantier bien plus lourd que le reste du tableau, à traiter séparément
|
||||
si demandé. Comme les autres éléments : responsive par taille d'écran.
|
||||
245 tests passent, ruff/mypy --strict/bandit/vulture/import-linter/
|
||||
eslint/stylelint tous clean. Rien d'oublié constaté à cette relecture.
|
||||
Validé par l'utilisateur (y compris les 4 bugs de thème trouvés et
|
||||
corrigés pendant la validation), prêt à committer.
|
||||
|
||||
### 5. Étiquette (badge) — à compléter
|
||||
|
||||
@@ -349,3 +505,41 @@ distinct de `.is-active`/`.is-dragging`. Pas de test automatisé
|
||||
possible côté client (aucune suite de tests n'existe pour
|
||||
`document-editor.js`), vérification manuelle uniquement — le mécanisme
|
||||
serveur sous-jacent, lui, reste couvert par les tests existants.
|
||||
|
||||
## Fonctionnalité hors tableau : retirer le thème appliqué
|
||||
|
||||
Retour utilisateur du 26/09/2026 : après avoir choisi un thème puis
|
||||
vidé toutes les pages, le thème restait appliqué — question légitime
|
||||
("c'est voulu ?"), réponse : OUI pour la séparation contenu/thème (déjà
|
||||
le cas), mais il manquait un moyen de retirer un thème une fois choisi.
|
||||
Ajout demandé : "dans la modale de choix des modèles, ajoute-en un qui
|
||||
s'appelle Aucun modèle, si l'utilisateur le choisit ça enlève tout
|
||||
modèle de style choisi pour revenir à un document de base".
|
||||
|
||||
- **Nouvelle fonction bas niveau** `db.remove_document_theme(slug)`
|
||||
(`db/supports/remove_document_theme.py`) — supprime la LIGNE `_meta`
|
||||
plutôt que d'y stocker une chaîne vide, pour que `get_document_theme`
|
||||
continue de renvoyer `None` (son contrat documenté : "aucun thème
|
||||
n'a jamais été appliqué"), jamais une chaîne vide qui le violerait
|
||||
silencieusement pour tout appelant qui compare à `None` (dont le test
|
||||
déjà existant `test_new_support_has_no_theme_by_default`).
|
||||
- **Route** `/document/<slug>/theme/apply` : `theme_id` vide retire
|
||||
désormais le thème et s'arrête là — `mode` n'a alors aucun sens
|
||||
(aucun contenu de démonstration pour "aucun modèle") et est ignoré,
|
||||
jamais validé ni utilisé dans ce cas.
|
||||
- **Modale "Utiliser un modèle"** : nouvelle carte "Aucun modèle"
|
||||
toujours en tête de liste (même catalogue vide), id sentinelle `""`
|
||||
— distincte de `null` (qui reste réservé à "rien n'a encore été
|
||||
cliqué dans la modale", `forgeDocSelectedTemplateId` à l'ouverture).
|
||||
La sélectionner remplace l'aperçu (rien à prévisualiser, "aucun
|
||||
modèle" n'a pas de contenu de démonstration) par un message explicite
|
||||
et un unique bouton "Retirer le modèle" (jamais les deux boutons
|
||||
"contenu actuel/du modèle", qui supposent un vrai thème choisi) —
|
||||
confirmation native avant l'action (changement visuel notable, même
|
||||
si le contenu n'est jamais touché).
|
||||
- Testé : `db/supports/remove_document_theme.py` (2 tests bas niveau,
|
||||
`tests/document/test_support_lifecycle.py`) + la route (2 tests,
|
||||
`tests/document/test_document_routes.py` — retire vraiment le thème,
|
||||
laisse le contenu intact, ignore `mode`). Le déclenchement côté
|
||||
client (clic sur la carte/le bouton) reste manuel faute de suite de
|
||||
tests JS, comme le reste de l'éditeur.
|
||||
|
||||
Reference in New Issue
Block a user