Restaure et termine le lot tableur resté non committé. Il n'existait que dans un `git stash` (24 fichiers suivis) et en fichiers non suivis (menus.js, formula.js, color-picker.js, tests, fiches) : la 2.53.3 livrée ne le contenait donc pas. Le stash, créé avant le commit BUG-108, n'a jamais été restauré. #180 Redimensionnement au curseur (en-tête de bord miroité + classe de repaint), grille thémée sur les 15 thèmes et les modes contraste élevé / sépia, menu Fichier au niveau des onglets, barre épinglée pleine largeur. #181 Modèle de saisie Google Sheets : sélection ≠ édition (caret masqué sans quitter contenteditable, double-clic / F2 / première frappe qui remplace, Entrée contextuelle, Échap qui restaure) + inventaire priorisé des écarts. #182 Désélection fiable (clic simple sans dépendre du focus), contours de plage non empilés (sélecteur de classes sans point), couleurs texte/fond sur une plage, clic droit qui préserve la sélection multiple. #183 Panneau de couleurs façon Google Sheets : palette 8 × 10, STANDARD, PERSONNALISÉ, coche selon la luminance, sortie `#rrggbb` (une valeur HSL était rejetée par normHex). #184 Peinture de format complète (toutes propriétés, source sans format = réinitialisation), sélection multi-lignes/colonnes depuis les marges, grille étendue : colonnes A → Z d'emblée, lignes ajoutées PAR BLOCS DE 100 au défilement jusqu'à 1000 — matérialiser 1000 lignes d'un coup = ~26 000 cellules câblées par feuille, ce qui épuisait le tas de la suite JSDOM ; index de cellules `ref → td`, court-circuits formule/styles, marqueur data-wired. #185 Barre de menus : les 10 menus Google Sheets (161 entrées, 125 câblées, 36 annoncées indisponibles), ruban façon Sheets, grille unie 1 px dérivée du thème. #186 « Créer un fichier » propose .xlsx et construit un vrai classeur OPC (openpyxl) au lieu d'une charge utile texte illisible. Corrections trouvées en restaurant et en exerçant le lot : - fuite mémoire : écouteur `click` anonyme posé sur #content-area à chaque rendu, jamais retiré — sa fermeture retenait la grille précédente en entier ; - sorties Markdown / HTML / Imprimer de la barre de menus inertes (`data-xlsx-export` jamais réparti, seul `data-xlsx-action` l'était) ; - collision de classe `.xlsx-structure-menu` entre la barre de menus et le menu Structure de la barre d'outils (toute requête tombait sur un nœud masqué) ; - curseur col/row-resize absent quand le pointeur est sur la table elle-même ; - l'export emportait les lignes et colonnes vides du quadrillage (CSV, Markdown, HTML, impression) ; - clic extérieur avalé par la grâce de 250 ms du menu contextuel (destinée au seul appui long tactile) ; - une entrée indisponible laissait la barre de menus ouverte. Tests : pytest 1595 passés / 2 ignorés ; ruff et mypy 0 erreur ; bandit 0 ; 33 suites frontend vertes (xlsx-viewer 163/163, xlsx-menus 19/19, xlsx-formula 14/14) ; E2E complet 132 passés / 12 ignorés ; E2E xlsx-viewer 19/19.
6.9 KiB
#185 — Tableur : barre de menus Google Sheets, boutons façon Sheets, grille unie
Statut : ✅ livré le 2026-10-08 (v2.54.0) — ouvert le 2026-10-05 | Effort : 1-2 jours | Impact : 🟡 Références : Roadmap · Changelog · #154 · #179 · #180 · #183)
1. Constat
L'éditeur tableur avait un ruban de boutons et trois menus (Structure, Mise en
forme, Export) mais aucune barre de menus : ni Fichier, ni Modifier, ni
Affichage, ni Insertion, ni Format, ni Données, ni Outils, ni Gemini, ni
Extensions, ni Aide. Beaucoup de fonctions existentes n'étaient atteignables que
par un clic droit ou par un bouton à connaître. Le ruban lui-même gardait un
chromer bordersé qui ne ressemblait à rien, et la grille n'était bordée qu'en
bas avec une couleur (--border) quasi identique au fond des cellules : le
quadillage se lisait comme une tache, pas comme une grille.
2. Livré
A1 — Barre de menus (les 10 menus de Google Sheets)
frontend/js/xlsx/menus.js (nouveau) décrit les dix menus, dans l'ordre et avec
les libellés exacts de Google Sheets (Fichier · Modifier · Affichage ·
Insertion · Format · Données · Outils · Gemini · Extensions · Aide), puis
buildMenuBar() produit la barre et ses dix menus déroulants. 161 entrées, dont
125 wirables (67 actions distinctes) et 36 honestement déclarées
indisponibles (elles s'affichent mais répondent « « X » n'est pas disponible
dans ObsiGate »** — jamais un clic muet). Les sections imbriquées (Nombre,
Thème, Alignement, Zoom, Nettoyage…) sont des accordéons comme dans Sheets :
une seule ouverte à la fois par niveau.
Le menu Fichier a quitté la barre d'onglets pour la barre de menus, en
conservant ses identifiants (#xlsx-file-btn, #xlsx-file-menu,
#xlsx-download-btn, #xlsx-csv-btn, [data-xlsx-export]). Seul
Enregistrer reste épinglé à droite de la barre d'onglets.
A2 — Fonctions réellement câblées
- Fichier : Partager, Télécharger (original · CSV · Markdown · HTML),
Imprimer, Renommer (
PATCH /api/file/{vault}), Corbeille (DELETE /api/file/{vault}), Historique des versions (visionneuse de sauvegardes), Détails (vault, chemin, feuilles, cellules, révision, · modifications en attente via/api/healthpour le numéro de version). - Modifier : Annuler, Rétablir, Couper, Copier, Coller, Collage spécial → valeurs uniquement (les formules sont évaluées puis collées comme texte), Supprimer → lignes / colonnes / contenu, Tout sélectionner, Rechercher et remplacer (toutes les feuilles).
- Affichage : Figer (ici / ligne / colonne / libérer), Afficher → barre de formule · grille · en-têtes · tableau de bord, Grouper (déclaré), Feuilles masquées (déclaré), Zoom (50 → 200 %, même état que le ruban), Plein écran.
- Insertion : Lignes (au-dessus / en dessous), Colonnes (à gauche / à droite), Cellules, Lien, Commentaire, Fonction (insère l'appel et place le curseur entre les parenthèses).
- Format : Nombre (6 formats), Thème (liste des 15 thèmes construite à la demande), Gras / Italique / Souligné / Barré, Taille de police, Alignement (horizontal + vertical), Retour à la ligne, Rotation, Couleurs alternées (une écriture par ligne, lots de 50 — plafond du backend), Effacer la mise en forme.
- Données : Trier la plage (croissant / décroissant / réinitialiser), Créer un filtre (sur la valeur de la cellule active), Plages nommées (panneau du tableau de bord), Nettoyage → supprimer les doublons ·trimmer, Diviser le texte en colonnes.
- Outils : Saisie semi-automatique (bascule la liste de fonctions de la barre de formule), Accessibilité (cellules plus grandes, grille plus contrastée).
- Gemini : les six entrées ouvrent le panneau de l'assistant IA.
- Aide : aide intégrée, Mises à jour (version), Raccourcis clavier (liste), Signaler un problème (diagnostic copié dans le presse-papiers).
A3 — Ruban façon Google Sheets
Boutons plats : 30 × 30, sans bordure ni fond au repos, survol discret, état
actif teinté, groupes séparés par des filets verticaux. Les sélecteurs (zoom,
format de nombre, taille de police) suivent le même traitement. Enregistrer
reste le seul pilier plein. Nouveau bouton grille (#xs-grid), piloté par le
menu Affichage et inversement.
A4 — Grille unie et visible
- Chaque cellule est encadrée sur les quatre côtés par la même ligne 1 px (les en-têtes compris : ils se distinguent par leur fond, plus par une bordure plus lourde).
--grid-bordern'est plus--border(1-2 % d'écart avec le fond sur la plupart des thèmes) mais uncolor-mixdu texte vers la surface calculé parthemes.js: une seule valeur pour toute la grille, lisible en sombre comme en clair et dans les modes générés (contraste élevé, sépia).- Les valeurs de repli des 4 blocs
:rootont été remontées en contraste.
3. Tests
tests/frontend/xlsx-menus.test.mjs: i18n amorcé, barre de menus (10 libellés, un déroulant par bouton, accordéon), ** exhaustivité des actions déclarées**, disparition des entrées d'édition en lecture seule, absence de HTML dans les libellés, ids historiques du menu Fichier ; ruban (save, « + », grille).tests/frontend/xlsx-viewer.test.mjs: barre présente au-dessus du ruban, entrée indisponible qui répond (et n'envoie rien), bascules Affichage, Zoom, écriture de structure (Insertion), écriture de style (Format ▸ Nombre), Couleurs alternées (3 lignes → 3 ops), Accessibilité, Raccourcis clavier, classeur en lecture seule, jeton--grid-border.tests/e2e/xlsx-viewer.spec.js: les 10 menus dans le bon ordre et au-dessus du ruban, accordéon Format ▸ Nombre, option indisponible, grille 1 px sur les 4 côtés puis masquée à 0 px.
4. Limites assumées
- Les 36 options Google Sheets qu'ObsiGate n'implémente pas (macros, Apps Script, TCD, graphiques, formulaires,/modules, AppSheet, Looker Studio, training…) sont listées pour rester fidèle à la demande, et annoncées comme indisponibles au clic. Elles ne sont pas masquées : la parité visuelle prime, l'honnêteté prime sur le silence.
- Déplacer lignes/colonnes est déclaré indisponible : leivinguer (supprimer + insérer + réécrire) sur un classeur avec fusions, styles et formules n'est pas sûr en un seul geste.
- Le menu Thème est construit à la demande (import dynamique de
themes.js) : 15 entrées, pas de coût au rendu. - Les couleurs de la grille sont dérivées via
color-mix: un moteur qui ne le supporte pas retombe sur--grid-border(feuille de style).