Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82f6b4a791 | ||
|
|
7e1f5d6852 |
+19
-1
@@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
|
||||
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
> **En cours de développement** : les changements à venir sont listés dans la section
|
||||
> [Unreleased](#unreleased). La dernière version livrée est **2.12.0**.
|
||||
> [Unreleased](#unreleased). La dernière version livrée est **2.12.2**.
|
||||
|
||||
---
|
||||
|
||||
@@ -14,6 +14,24 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
---
|
||||
|
||||
## [2.12.2] — 2026-09-18
|
||||
|
||||
### Corrigé
|
||||
|
||||
- **BUG-066 — Configuration : icônes manquantes dans la table des matières** :
|
||||
les entrées « Fichiers cachés » et « Partages publics » du sommaire de la page de
|
||||
configuration n'affichaient pas d'icône (les titres de section, eux, en avaient une).
|
||||
Les libellés i18n `config.section_hidden` (🗂️) et `config.section_shares` (📤) sont
|
||||
alignés sur leurs titres de section, en FR **et** EN. Test de non-régression ajouté
|
||||
dans `tests/frontend/unit.test.mjs` (toutes les entrées du sommaire doivent porter une
|
||||
icône dans les deux langues).
|
||||
|
||||
---
|
||||
|
||||
## [2.12.1] — 2026-09-18
|
||||
|
||||
---
|
||||
|
||||
## [2.12.0] — 2026-09-18
|
||||
|
||||
### Ajouté
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@
|
||||
|
||||
**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://www.docker.com/)
|
||||
[](https://www.python.org/)
|
||||
@@ -926,8 +926,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l
|
||||
|
||||
## 📝 Changelog
|
||||
|
||||
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.12.0).
|
||||
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.12.2).
|
||||
|
||||
---
|
||||
|
||||
*Projet : ObsiGate | Version : 2.12.0 | Dernière mise à jour : Juin 2026*
|
||||
*Projet : ObsiGate | Version : 2.12.2 | Dernière mise à jour : Juin 2026*
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface.
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://www.docker.com/)
|
||||
[](https://www.python.org/)
|
||||
@@ -1095,8 +1095,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE)
|
||||
|
||||
## 📝 Changelog
|
||||
|
||||
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.12.0).
|
||||
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.12.2).
|
||||
|
||||
---
|
||||
|
||||
*Project: ObsiGate | Version: 2.12.0 | Last updated: May 2026*
|
||||
*Project: ObsiGate | Version: 2.12.2 | Last updated: May 2026*
|
||||
|
||||
Generated
+1
-1
@@ -2626,7 +2626,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "obsigate-desktop"
|
||||
version = "2.12.0"
|
||||
version = "2.12.2"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "obsigate-desktop"
|
||||
version = "2.12.0"
|
||||
version = "2.12.2"
|
||||
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
|
||||
authors = ["Bruno Charest"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
|
||||
"productName": "ObsiGate",
|
||||
"version": "2.12.0",
|
||||
"version": "2.12.2",
|
||||
"identifier": "com.obsigate.desktop",
|
||||
"build": {
|
||||
"frontendDist": "../frontend",
|
||||
|
||||
@@ -174,6 +174,7 @@ Avant de corriger quoi que ce soit, un agent IA doit :
|
||||
| *BUG-063* | [🟡 IMPORTANT] Viewer PDF : la table des matières s'affiche mais ne navigue pas | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/viewer.js`, `tests/frontend/pdf-viewer.test.mjs`, `tests/e2e/pdf-viewer.spec.js` (fixture `test_vault/sample-pdf-toc.pdf`) | Ouvrir un PDF avec signets, puis cliquer une entrée de la TOC | Deux causes : (1) `contentWindow.location.hash='page=N'` n'atteint pas le document (lecteur PDF natif dans une fenêtre `about:blank`) ; (2) un simple changement de fragment sur `iframe.src` est une navigation same-document **ignorée** par le lecteur natif. `navigatePdfToPage()` (liens `data-page` + listeners, plus d'`onclick` inline) recharge réellement l'iframe via un paramètre de query qui change (`&_pdfpage=<ts>#page=N`). Test E2E : `src` finit par `&_pdfpage=<n>#page=3`. Vérifié en Chrome *headful* : page 1 → page 8 → page 1 (captures identiques au retour) | Le fragment seul ne suffisait pas : Chrome applique `#page=N` au **chargement**, pas lors d'un changement de fragment |
|
||||
| *BUG-064* | [🟡 IMPORTANT] Éditeur Excalidraw : le diagramme ne s'affiche jamais (canvas vide), pour tout fichier `.excalidraw` / `.excalidraw.md` | 🟢 corrigé | P1 | 📱 frontend + ⚙️ backend | IA | `frontend/excalidraw-editor.html`, `backend/main.py`, `tests/frontend/excalidraw-viewer.test.mjs`, `tests/test_security_hardening.py`, `tests/e2e/excalidraw.spec.js`, `test_vault/diagram-app-export.excalidraw` | Ouvrir un `.excalidraw` (ou `.excalidraw.md`) dans ObsiGate | Deux causes : (1) la feuille de style d'Excalidraw n'était jamais chargée → éditeur non stylisé + `.excalidraw` sans hauteur fixe → boucle de resize jusqu'au plafond `2^25` (33 554 432 px) → scène blanche. Correctif : `<link>` CSS depuis esm.sh + `style-src` CSP autorisant `https://esm.sh`. (2) `appState.collaborators` objet JSON → `collaborators.forEach is not a function` ; `sanitizeAppState()` reconvertit en `Map` et écarte `width/height/offsetLeft/offsetTop`. | Vérifié navigateur : hauteur canvas 525 px (avant 33 554 432), dessin affiché, UI stylisée, 0 erreur. E2E + tests statiques CSP/CSS ajoutés. |
|
||||
| *BUG-065* | [🟡 IMPORTANT] Éditeur Excalidraw : l'auto-save recharge la page en pleine édition | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/excalidraw-viewer.js`, `frontend/js/utils.js`, `frontend/excalidraw-editor.html`, `tests/frontend/excalidraw-viewer.test.mjs` | Ouvrir un `.excalidraw` puis modifier un élément : au bout de 2 s la vue se recharge | Chaque modification déclenchait un `PUT save` 2 s plus tard → SSE `index_updated` → `reloadExternalWrite` → `openFile` → **recréation de l'iframe** (refresh visible). Auto-save supprimée : sauvegarde explicite (bouton 💾 / Ctrl+S). `reloadExternalWrite` ignore le fichier si un iframe Excalidraw est ouvert (`iframe[data-excalidraw-vault/path]`). Le badge « Modified » ne réagit plus aux changements d'`appState` (resize/zoom) mais à la signature des éléments. | Vérifié Playwright : plus de refresh, badge stable après bascule plein écran. Test statique (absence de `requestSave`/`saveTimer`). |
|
||||
| *BUG-066* | [🔵 MINEUR] Configuration : icônes manquantes dans la table des matières (« Fichiers cachés », « Partages publics ») | 🟢 corrigé | P3 | 📱 frontend | IA | `frontend/locales/{fr,en}.json` | Ouvrir Configuration → observer le sommaire : les entrées « Fichiers cachés » et « Partages publics » n'ont pas d'icône | `config.section_hidden` → « 🗂️ Fichiers cachés » / « 🗂️ Hidden files », `config.section_shares` → « 📤 Partages publics » (EN avait déjà l'icône). Test : `tests/frontend/unit.test.mjs` (+1 : toutes les entrées du sommaire portent une icône FR/EN) | Les libellés du sommaire utilisent des clés i18n distinctes des titres de section (`auto.f8ba6127`, `config.section_partages-publics`) qui, elles, avaient l'icône |
|
||||
| | | | | | | | | | | |
|
||||
|
||||
### TODOs techniques (améliorations / nouvelles tâches)
|
||||
@@ -244,6 +245,7 @@ Avant de corriger quoi que ce soit, un agent IA doit :
|
||||
| 2026-09-17 | BUG-064 (complément) | Correction | `frontend/style.css`, `tests/frontend/excalidraw-viewer.test.mjs`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md` | **BUG-064 (complément)** : quand la barre de navigation gauche est masquée, le viewer Excalidraw restait borné à la colonne de lecture centrée de 1200 px. La règle `.sidebar.hidden ~ .content-wrapper .content-area { max-width: 1200px }` s'appliquait au viewer comme aux notes. Ajout de `.content-area:has(iframe[src*="excalidraw-editor.html"])` en `max-width: none; margin: 0` (même traitement que les viewers PDF/image, BUG-062). Vérifié Playwright (viewport 1400 px) : contenu 1115 → 1400 px, iframe 1035 → 1320 px, `max-width` calculé `none`. Test statique ajouté (`excalidraw-viewer.test.mjs` 9/9). | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
| 2026-09-17 | BUG-065, #78 (complément) | Correction + feature | `frontend/js/excalidraw-viewer.js`, `frontend/js/utils.js`, `frontend/excalidraw-editor.html`, `tests/frontend/excalidraw-viewer.test.mjs`, `docs/features/excalidraw.md`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md` | **BUG-065** : l'auto-save Excalidraw (débounce 2 s) déclenchait `PUT save` → SSE `index_updated` → `reloadExternalWrite` → `openFile` → recréation de l'iframe = refresh visible pendant le dessin. Auto-save retirée (`excalidraw-viewer.js` : plus de `requestSave`/`saveTimer`), sauvegarde explicite (bouton 💾 / Ctrl+S) ; `reloadExternalWrite` (utils.js) court-circuite le re-rendu si un iframe Excalidraw est ouvert sur ce fichier (attributs `data-excalidraw-vault`/`data-excalidraw-path`) ; le badge « Modified » suit désormais une signature des éléments (`id:versionNonce`) au lieu de tout `onChange` — resize/zoom/plein écran ne marquent plus le fichier modifié. **#78 (complément)** : bouton **plein écran** `#btn-fullscreen` dans la barre d'outils de l'éditeur (`requestFullscreen` sur le document de l'iframe) + iframe créée avec `allow="fullscreen" allowfullscreen`. Vérifié Playwright : bascule plein écran OK (`document.fullscreenElement` true→false), badge non modifié après bascule ; tests statiques `excalidraw-viewer.test.mjs` 12/12, validate-imports 38 modules, unit 9/9. | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
| 2026-09-17 | #78 (complément) | UI | `frontend/excalidraw-editor.html`, `docs/features/excalidraw.md`, `CHANGELOG.md` | **#78 (complément)** : la barre d'outils de l'éditeur Excalidraw passe en **colonne d'icônes** (34×34 px, SVG seuls), **collée au bord droit** (`right: 0` ; `top: 45%` ; empilement vertical), avec `title`/`aria-label`. L'icône du bouton Save est remplacée par une coche pendant 1,2 s après une sauvegarde réussie. Badge « Modifié » réduit à une pastille. Vérifié Playwright : bord droit au bord de l'iframe, haut 45 %, 4 boutons empilés ; bascule plein écran OK, cycle d'icône Save + `PUT save` observés. | 🟢 livré (en attente vérif utilisateur) |
|
||||
| 2026-09-18 | BUG-066 | Correction | `frontend/locales/fr.json`, `frontend/locales/en.json`, `tests/frontend/unit.test.mjs`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md` | **BUG-066** : la table des matières de la page de configuration n'affichait aucune icône pour « Fichiers cachés » et « Partages publics ». Les libellés du sommaire proviennent de clés i18n (`config.section_hidden`, `config.section_shares`) distinctes des titres de section qui, eux, portaient déjà l'icône. Alignement : 🗂️ / 📤 en FR **et** EN. Test de non-régression : `unit.test.mjs` vérifie que **toutes** les entrées `.help-nav-link` du sommaire portent une icône dans les deux langues (17/17). Vérifié : `unit.test.mjs` 10/10, `validate-imports` 38 modules. | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# ObsiGate — Roadmap
|
||||
|
||||
> **Version :** 2.12.0 | **Dernière mise à jour :** 2026-09-18
|
||||
> **Version :** 2.12.2 | **Dernière mise à jour :** 2026-09-18
|
||||
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
|
||||
> vers les fonctionnalités livrées.
|
||||
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
|
||||
|
||||
@@ -496,7 +496,7 @@
|
||||
"config.section_fonctionnalites": "Features",
|
||||
"config.section_format-du-payload": "Format du payload",
|
||||
"config.section_gestion-des-onglets": "📑 Gestion des onglets",
|
||||
"config.section_hidden": "Hidden files",
|
||||
"config.section_hidden": "🗂️ Hidden files",
|
||||
"config.section_historique-recent-redemarrage-non-requis": "📋 Recent History\n No restart required",
|
||||
"config.section_indicateurs-visuels": "Indicateurs visuels",
|
||||
"config.section_intelligence-artificielle-dans-l-editeur": "🤖 AI in the Editor",
|
||||
|
||||
@@ -496,7 +496,7 @@
|
||||
"config.section_fonctionnalites": "Fonctionnalités",
|
||||
"config.section_format-du-payload": "Format du payload",
|
||||
"config.section_gestion-des-onglets": "📑 Gestion des onglets",
|
||||
"config.section_hidden": "Fichiers cachés",
|
||||
"config.section_hidden": "🗂️ Fichiers cachés",
|
||||
"config.section_historique-recent-redemarrage-non-requis": "📋 Historique récent\n Redémarrage non requis",
|
||||
"config.section_indicateurs-visuels": "Indicateurs visuels",
|
||||
"config.section_intelligence-artificielle-dans-l-editeur": "🤖 Intelligence Artificielle dans l'Éditeur",
|
||||
@@ -539,7 +539,7 @@
|
||||
"config.section_securite-signature-hmac-sha256": "Sécurité : signature HMAC-SHA256",
|
||||
"config.section_selection-de-vault": "Sélection de vault",
|
||||
"config.section_server": "Serveur",
|
||||
"config.section_shares": "Partages publics",
|
||||
"config.section_shares": "📤 Partages publics",
|
||||
"config.section_sidebar-barre-laterale": "Sidebar (barre latérale)",
|
||||
"config.section_synchronisation-automatique": "Synchronisation automatique",
|
||||
"config.section_tag-cloud": "Tag cloud",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "obsigate",
|
||||
"version": "2.12.0",
|
||||
"version": "2.12.2",
|
||||
"description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.",
|
||||
"main": "patch.js",
|
||||
"directories": {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"elements": [
|
||||
{
|
||||
"id": "app-rect-1",
|
||||
"type": "rectangle",
|
||||
"x": 100,
|
||||
"y": 100,
|
||||
"width": 300,
|
||||
"height": 150,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": "a0",
|
||||
"roundness": { "type": 3 },
|
||||
"seed": 975148614,
|
||||
"version": 73,
|
||||
"versionNonce": 1826427930,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 1789695570496,
|
||||
"created": 1789695569357,
|
||||
"link": null,
|
||||
"locked": false
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"showWelcomeScreen": false,
|
||||
"theme": "dark",
|
||||
"collaborators": {},
|
||||
"currentChartType": "bar",
|
||||
"currentItemBackgroundColor": "transparent",
|
||||
"currentItemEndArrowhead": "arrow",
|
||||
"currentItemFillStyle": "solid",
|
||||
"currentItemFontFamily": 5,
|
||||
"currentItemFontSize": 20,
|
||||
"currentItemOpacity": 100,
|
||||
"currentItemRoughness": 1,
|
||||
"currentItemStartArrowhead": null,
|
||||
"currentItemStrokeColor": "#1e1e1e",
|
||||
"currentItemRoundness": "round",
|
||||
"currentItemArrowType": "round",
|
||||
"currentItemStrokeStyle": "solid",
|
||||
"currentItemStrokeWidth": 2,
|
||||
"currentItemTextAlign": "left",
|
||||
"cursorButton": "up",
|
||||
"activeTool": {
|
||||
"type": "selection",
|
||||
"customType": null,
|
||||
"locked": false,
|
||||
"lastActiveTool": null
|
||||
},
|
||||
"penMode": false,
|
||||
"penDetected": false,
|
||||
"errorMessage": null,
|
||||
"exportBackground": true,
|
||||
"exportScale": 1,
|
||||
"exportEmbedScene": false,
|
||||
"exportWithDarkMode": false,
|
||||
"gridSize": 20,
|
||||
"gridStep": 5,
|
||||
"gridModeEnabled": false,
|
||||
"isBindingEnabled": true,
|
||||
"isLoading": false,
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"name": "App Export Fixture",
|
||||
"previousSelectedElementIds": {},
|
||||
"scrollX": 0,
|
||||
"scrollY": 0,
|
||||
"selectedElementIds": {},
|
||||
"selectedGroupIds": {},
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"zenModeEnabled": false,
|
||||
"zoom": { "value": 1 },
|
||||
"viewModeEnabled": false
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -189,6 +189,38 @@ function testAdminModuleSyntax() {
|
||||
console.log(' ✓ admin.js parses without syntax errors');
|
||||
}
|
||||
|
||||
// ── Test config TOC icons ─────────────────────────────────────────────────
|
||||
const FRONTEND_DIR = join(__dirname, '../../frontend');
|
||||
const INDEX_HTML = join(FRONTEND_DIR, 'index.html');
|
||||
const ICON_RE = /^\p{Extended_Pictographic}/u;
|
||||
|
||||
function testConfigTocIcons() {
|
||||
const html = readFileSync(INDEX_HTML, 'utf-8');
|
||||
const keys = [
|
||||
...html.matchAll(
|
||||
/<a\s+href="#cfg-[^"]*"\s+class="help-nav-link"\s+data-i18n="([^"]+)"/g,
|
||||
),
|
||||
].map((m) => m[1]);
|
||||
assert.ok(keys.length > 0, 'config TOC links found in index.html');
|
||||
|
||||
for (const lang of ['fr', 'en']) {
|
||||
const locale = JSON.parse(
|
||||
readFileSync(join(FRONTEND_DIR, 'locales', `${lang}.json`), 'utf-8'),
|
||||
);
|
||||
for (const key of keys) {
|
||||
const value = locale[key];
|
||||
assert.ok(value, `${lang}: missing TOC label for ${key}`);
|
||||
assert.ok(
|
||||
ICON_RE.test(value),
|
||||
`${lang}: TOC label for ${key} has no icon ("${value}")`,
|
||||
);
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
` ✓ config TOC labels (${keys.length}) all carry an icon in FR and EN`,
|
||||
);
|
||||
}
|
||||
|
||||
// ── Test ai-fab.js (FAB — Floating Action Button) ─────────────────────────
|
||||
const AIFAB_PATH = join(JS_DIR, 'ai-fab.js');
|
||||
|
||||
@@ -222,6 +254,7 @@ async function main() {
|
||||
['admin module syntax', testAdminModuleSyntax],
|
||||
['ai-fab module exists', testAIFabModuleExists],
|
||||
['ai-fab module exports', testAIFabModuleExports],
|
||||
['config TOC icons', testConfigTocIcons],
|
||||
];
|
||||
|
||||
for (const [name, fn] of tests) {
|
||||
|
||||
Reference in New Issue
Block a user