fix(search,excalidraw,e2e): recherche cassee + corruption .excalidraw.md + tests E2E #78
CI / lint (push) Successful in 54s
CI / security (push) Successful in 38s
CI / test (push) Successful in 1m7s
CI / build (push) Successful in 33s
CI / e2e (push) Failing after 10m52s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s

- frontend/js/search.js : onSearchFilter appelee avec (vault, query, results) — renvoyait undefined, cassait le rendu et basculait sur la recherche offline (0 resultat). Regression plugins depuis 30f2df3.
- frontend/excalidraw-editor.html + js/excalidraw-viewer.js : ignorer onChange au montage (plus d'auto-save spurieux qui reecrivait .excalidraw.md en JSON brut) + preservation du format Obsidian frontmatter + compressed-json a la sauvegarde.
- frontend/js/app.js : __OBSIGATE_BOOTED pose apres init() (splash + E2E attendent les handlers lies).
- tests/e2e : goHome/login attendent le boot ; excalidraw.spec.js reecrit avec les selecteurs reels (modal, context menu, canvas.first()).
- ROADMAP : C8 (creation via menu contextuel) marque fait.
- Verifie : 86/86 E2E chromium-desktop, 599 backend, ruff, validate-imports, JSDOM.
This commit is contained in:
2026-09-10 22:51:08 -04:00
parent 4f99d5ce61
commit 0cbbbf260a
8 changed files with 116 additions and 140 deletions
+3 -2
View File
@@ -113,13 +113,14 @@ async function init() {
initAIFab();
}
document.addEventListener("DOMContentLoaded", () => {
document.addEventListener("DOMContentLoaded", async () => {
try {
init();
await init();
Sync.init();
} finally {
// Signale au splash de démarrage (index.html #boot-splash) que l'app est
// initialisée : le splash est retiré et le squelette stylé révélé.
// Set AFTER init() resolves so every handler (search, tabs, …) is bound.
window.__OBSIGATE_BOOTED = true;
if (typeof window.__obsigateBootReady === "function") window.__obsigateBootReady();
}
+13 -2
View File
@@ -114,11 +114,22 @@ export function renderExcalidraw(container, data, vaultName, filePath, opts = {}
*/
async function _saveExcalidrawFile(state, excalidrawData) {
try {
const jsonStr = JSON.stringify(excalidrawData, null, 2);
const isMd = (state.path || '').toLowerCase().endsWith('.excalidraw.md');
let content;
if (isMd && excalidrawData && excalidrawData.compressed) {
// Preserve the Obsidian Excalidraw plugin format: frontmatter +
// compressed-json block. Writing raw JSON here would destroy the
// .excalidraw.md file (the plugin would no longer recognize it).
content = `---\nexcalidraw-plugin: parsed\n---\n\n\`\`\`compressed-json\n${excalidrawData.compressed}\n\`\`\`\n`;
} else {
// Transport-only field must not leak into the pure JSON format.
const { compressed, ...scene } = excalidrawData || {};
content = JSON.stringify(scene, null, 2);
}
await api(`/api/file/${encodeURIComponent(state.vault)}/save?path=${encodeURIComponent(state.path)}&backup=false`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content: jsonStr }),
body: JSON.stringify({ content }),
});
// Toast is handled by the caller or we show a quick one
showToast('Excalidraw saved', 'success');
+1 -1
View File
@@ -804,7 +804,7 @@ export async function performAdvancedSearch(query, vaultFilter, tagFilter, offse
state.advancedSearchTotal = data.total;
state.advancedSearchOffset = ofs;
// Plugin hook: filter search results
data.results = await onSearchFilter(state.vault || "default", data.results);
data.results = await onSearchFilter(state.vault || "default", query, data.results);
renderAdvancedSearchResults(data, query, tagFilter);
} catch (err) {
clearTimeout(timeoutId);