From 7e6aaed022ed3894a1c4e313cff958e5e045b8b3 Mon Sep 17 00:00:00 2001 From: bolbol Date: Wed, 8 Jul 2026 13:25:09 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20cause=20racine=20mode=20template=20nyor?= =?UTF-8?q?a-doc-api=20(runs=20rPr=20>=20styles)=20+=20correctif=20restyle?= =?UTF-8?q?=20opt-in=20propos=C3=A9=20+=20footer=20d=C3=A9j=C3=A0=20d?= =?UTF-8?q?=C3=A9ploy=C3=A9=2004/07?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...a-doc-api-template-restyle-cause-racine.md | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 common/nyora-doc-api-template-restyle-cause-racine.md diff --git a/common/nyora-doc-api-template-restyle-cause-racine.md b/common/nyora-doc-api-template-restyle-cause-racine.md new file mode 100644 index 0000000..05369e3 --- /dev/null +++ b/common/nyora-doc-api-template-restyle-cause-racine.md @@ -0,0 +1,39 @@ +# nyora-doc-api — Mode template : cause racine du non-restyle des runs + correctif proposé + +**Date** : 08/07/2026 · **Statut** : cause racine prouvée en prod, correctif conçu, NON implémenté (attente GO) + +## Contexte de la session +Objectif initial : rebuilder le correctif footer DOCX. **Constat : déjà déployé le 04/07** (image buildée 08:03 UTC, commit 3c0d20ff, code container == disque == Gitea, vérifié par `docker exec cat | diff`). Voir `common/nyora-doc-api-rebuild-footer-docx.md`. Session réorientée sur la limite connue du mode template. + +## Vérification prod du footer (08/07, re-validée) +Mode data, titre long 140+ caractères + tableau totaux : footer1.xml contient liseré or B8862A, « · NYORA · », tagline, © 2026, champs PAGE/NUMPAGES. Corps intact, format FR `1 234 567,891` OK. **Aucune régression du correctif footer sur le mode data.** + +## Cause racine — DOCX template (`generate_docx`, services.py:11) +1. `docxtpl.render()` remplace les tags Jinja **en héritant du rPr du run porteur du tag** (police/taille/couleur directes du template). +2. `apply_docx_theme(doc)` (formatting.py:139) ne modifie que les **définitions de styles** (Normal, Heading 1–4) + marges. Il ne touche jamais les runs. +3. Précédence OOXML : **formatage direct de run (rPr) > style de paragraphe > défauts**. Or Word écrit un rPr explicite dès que l'auteur choisit une police → dans un template réel, quasi tous les runs portent un rPr → le thème appliqué au style est invisible. + +**Preuve empirique (08/07)** : template avec run Comic Sans MS 22pt rouge `{{name}}` → sortie : styles.xml bien rethémé Calibri, MAIS document.xml conserve Comic Sans/sz=44/FF0000. CQFD. + +Angles morts supplémentaires : styles custom du template non couverts (seuls Normal/Heading 1–4 sont réécrits), headers/footers du template jamais parcourus, `font.name` de python-docx ne règle que `rFonts@ascii,hAnsi` (pas `cs` → texte arabe non restylé). + +## Cause racine — PPTX template (`generate_pptx`, services.py:362) +Architectural : la branche template (`_replace_in_slide` → `validate_pptx_layout` → `save` → `return`) **sort avant toute lecture du thème**. `_replace_in_textframe` concentre le texte dans `runs[0]` qui garde son rPr d'origine. Aucun restyle n'est même tenté. + +## Correctif proposé (design, à faire exécuter — brief prêt) +Option opt-in `options.restyle: "none" (défaut) | "full"` — défaut à `none` pour ne jamais détruire une mise en page de template voulue. + +**DOCX (`restyle=full`)** : après `render()`, itérer TOUS les paragraphes (body + cellules de tables + header/footer de chaque section) ; pour chaque run : forcer `rFonts` ascii/hAnsi/**cs**/eastAsia (Calibri corps, Arial si style Heading 1–2), taille selon catégorie du style du paragraphe (mapping Typography), couleur charte ; **préserver bold/italic** (emphase sémantique de l'auteur). Générateur `_iter_all_paragraphs(doc)` ~15 lignes. + +**PPTX (`restyle=full`)** : ne PAS restyler tout le deck (destructeur). Marquer dans `_replace_in_textframe` les paragraphes où une substitution a eu lieu et ne restyler que ceux-là (font family + couleur thème, taille conservée). + +Estimation : ~60 lignes services.py + ~25 lignes formatting.py. Test de non-régression : le template Comic Sans ci-dessus avec restyle=none (inchangé) puis restyle=full (Calibri 11 navy). + +## Leçon transverse (ajoutée à PROTOCOL-INFRA des 3 instances) +`/app` est **cuit dans l'image** (COPY du Dockerfile), pas bind-mounté. Avant tout rebuild « parce qu'un fix n'est pas actif » : vérifier d'abord `docker exec cat | diff - ` + date de build image (`docker images --format '{{.CreatedAt}}'`). Ici, le rebuild demandé était déjà fait — 10 min économisées, zéro interruption de service. + +## Rappel usage pour les agents Hermes +Tant que `restyle=full` n'est pas implémenté : **mode data pour tout document devant porter la charte** (Nyora ou tt). Le mode template ne sert qu'à remplir un document dont on veut garder le design d'origine. + +## Point d'attention branding (décision Nabil requise) +Le footer « · NYORA · » est ajouté à TOUT DOCX mode data, y compris pour des documents Zone Sud (le thème `tt` n'existe que pour XLSX/PPTX, pas DOCX). Un document officiel Direction Zone Sud portera donc le branding Nyora. Proposition : `options.theme=tt` sur DOCX → footer neutre (pagination seule) + éventuel thème navy/cyan. À trancher avant implémentation.