From 57de4774c1025bc9a303ed05a402bcefc7ba9d24 Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:37:19 +0100 Subject: [PATCH 1/9] Surlignage 1 lexique --- manifest.json | 4 +- src/background/background.js | 53 +++- src/sidebar/sidebar.html | 10 + src/sidebar/sidebar.js | 229 ++++++++++------- src/utils/api.js | 19 +- src/utils/highlighting.js | 465 +++++++++++++++++++++++++++++++++++ 6 files changed, 678 insertions(+), 102 deletions(-) create mode 100644 src/utils/highlighting.js diff --git a/manifest.json b/manifest.json index 399a0d4..2591e94 100644 --- a/manifest.json +++ b/manifest.json @@ -61,7 +61,9 @@ "src/utils/definitions.js", "src/sidebar/sidebar.js", "src/context_menu/custom_context_menu.js", - "src/utils/stats.js"], + "src/utils/stats.js", + "src/utils/highlighting.js" + ], "css": ["src/context_menu/custom_context_menu.css"], "run_at": "document_idle" }, diff --git a/src/background/background.js b/src/background/background.js index cd3d012..ea71766 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -167,7 +167,7 @@ async function saveToken(token) { } // ───────────────────────────────────────────────────────────────────────────── -// Gestion des messages reçus (depuis popup, etc.) +// Gestion des messages reçus // ───────────────────────────────────────────────────────────────────────────── browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { log("📩 Message reçu dans background.js :", message); @@ -217,6 +217,34 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { } break; } + case "toggleLexiconHighlight": { + const tabs = await browser.tabs.query({active: true, currentWindow: true}); + if (tabs[0]) { + try { + // S'assurer que le script est injecté + await browser.scripting.executeScript({ + target: { tabId: tabs[0].id }, + files: ["src/utils/highlighting.js"] + }); + + // Envoyer le message d'activation + await browser.tabs.sendMessage(tabs[0].id, { + command: message.isActive ? "activate-highlighting" : "deactivate-highlighting", + lexiconId: message.lexiconId + }); + log(`✅ Message de surlignage transmis à l'onglet ${tabs[0].id}`); + } catch (error) { + console.error("⌠Erreur lors de la gestion du surlignage:", error); + } + } + break; + } + + case "register-highlighting-script": { + log("📠Script de surlignage enregistré pour l'onglet", sender.tab.id); + break; + } + default: break; } @@ -543,3 +571,26 @@ function sendStoplistToWorker() { browser.runtime.onStartup.addListener(loadStoplist); browser.runtime.onInstalled.addListener(loadStoplist); +async function handleHighlighting(command, lexiconId, tabId) { + console.log(`🎯 Gestion du surlignage: ${command} pour le lexique ${lexiconId}`); + + try { + // S'assurer que le script est injecté + await browser.scripting.executeScript({ + target: { tabId: tabId }, + files: ["utils/highlighting.js"] + }); + + // Envoyer le message d'activation + const response = await browser.tabs.sendMessage(tabId, { + command: command, + lexiconId: lexiconId + }); + + console.log("✅ Réponse du content script:", response); + return response; + } catch (error) { + console.error("⌠Erreur lors de la gestion du surlignage:", error); + return false; + } +} \ No newline at end of file diff --git a/src/sidebar/sidebar.html b/src/sidebar/sidebar.html index 06f98b5..79f9c09 100644 --- a/src/sidebar/sidebar.html +++ b/src/sidebar/sidebar.html @@ -293,6 +293,16 @@ transform: translateX(-50%) translateY(-5px); } + .lexicon-highlight { + background-color: rgba(255, 255, 0, 0.3); + border-bottom: 1px dashed #666; + transition: background-color 0.3s; + } + + .lexicon-highlight:hover { + background-color: rgba(255, 255, 0, 0.5); + } + .lexicon-section { margin-bottom: 10px; } diff --git a/src/sidebar/sidebar.js b/src/sidebar/sidebar.js index 0b40b78..2c4123b 100644 --- a/src/sidebar/sidebar.js +++ b/src/sidebar/sidebar.js @@ -116,8 +116,8 @@ async function refreshSidebarState() { } /** - * Bascule l’affichage d’un bloc. - * @param {string} blockId - L’ID du conteneur à basculer. + * Bascule l'affichage d'un bloc. + * @param {string} blockId - L'ID du conteneur à basculer. * @param {HTMLElement} btn - Le bouton qui déclenche la bascule, pour mettre à jour son texte. */ function toggleBlock(blockId, btn) { @@ -134,8 +134,8 @@ function toggleBlock(blockId, btn) { } /** - * Ouvre un bloc s’il est fermé et met à jour le bouton de bascule. - * @param {string} blockId - L’ID du conteneur à ouvrir. + * Ouvre un bloc s'il est fermé et met à jour le bouton de bascule. + * @param {string} blockId - L'ID du conteneur à ouvrir. * @param {HTMLElement} [btn] - (Optionnel) Le bouton de bascule à mettre à jour. */ function openBlock(blockId, btn) { @@ -301,12 +301,9 @@ async function displayLexiconsWithCheckbox(lexicons) { let currentState = highlightButton.dataset.active === "true"; let newState = !currentState; try { - await browser.runtime.sendMessage({ - action: "toggleLexiconHighlight", - lexiconId, - isActive: newState, - }); + await toggleLexiconHighlight(lexiconId, newState); highlightButton.dataset.active = newState ? "true" : "false"; + highlightButton.classList.toggle("active", newState); } catch (error) { console.error("Erreur lors du toggle de surlignage pour le lexique", lexiconId, ":", error); } @@ -413,7 +410,7 @@ async function handleAddWordClick() { return; } - // 3) Vérifier si le mot existe déjà dans l’un des lexiques sélectionnés + // 3) Vérifier si le mot existe déjà dans l'un des lexiques sélectionnés let definitions = []; try { definitions = await fetchLexiconDefinitions(selectedWord); @@ -445,7 +442,7 @@ async function handleAddWordClick() { return; } - // 6) Envoi d’une seule requête pour tous les lexiques restants + // 6) Envoi d'une seule requête pour tous les lexiques restants try { log(`📡 Envoi de l'ajout du mot "${selectedWord}" dans les lexiques :`, lexiconsToAdd); const result = await window.AddWord(authToken, selectedWord, lexiconsToAdd, false); @@ -464,9 +461,9 @@ async function handleAddWordClick() { } } catch (error) { - console.error("Erreur lors de l’ajout du mot :", error); + console.error("Erreur lors de l'ajout du mot :", error); if (lexiconResultElement) { - lexiconResultElement.textContent = "Erreur lors de l’ajout : " + error.message; + lexiconResultElement.textContent = "Erreur lors de l'ajout : " + error.message; } } } @@ -476,95 +473,126 @@ async function handleAddWordClick() { // ───────────────────────────────────────────────────────────────────────────── browser.runtime.onMessage.addListener(async (message) => { log("📩 Message reçu dans sidebar.js :", message); - switch (message.action) { - case "refreshUI": - log("🔄 Demande de rafraîchissement de la barre latérale."); - await refreshSidebarState(); - break; - - case "mot_selectionne": - if (message.selectedText) { - log("ðŸ–‹ï¸ Mot sélectionné :", message.selectedText); - const selectedWordElement = document.getElementById("motSelectionne"); - if (selectedWordElement) { - selectedWordElement.textContent = message.selectedText; - } else { - console.warn("âš ï¸ Ã‰lément #motSelectionne introuvable."); + + if (message.action === "refreshUI") { + log("🔄 Demande de rafraîchissement de la barre latérale."); + await refreshSidebarState(); + return; + } + + if (message.command) { + switch (message.command) { + case "activate-highlighting": + const highlightButton = document.querySelector(`[data-lexicon-id="${message.lexiconId}"] .lexique-highlight-toggle`); + if (highlightButton) { + highlightButton.dataset.active = "true"; + highlightButton.classList.add("active"); } - const lexiconResultElement = document.getElementById("lexiconResult"); - if (lexiconResultElement) { - lexiconResultElement.innerHTML = ""; + break; + + case "deactivate-highlighting": + const highlightButtonOff = document.querySelector(`[data-lexicon-id="${message.lexiconId}"] .lexique-highlight-toggle`); + if (highlightButtonOff) { + highlightButtonOff.dataset.active = "false"; + highlightButtonOff.classList.remove("active"); } - openBlock("etatContent"); - } - break; - - case "getDefinition": - if (message.selectedText) { - log("📖 Recherche des définitions pour :", message.selectedText); - openBlock("definitionContent"); - await window.showDefinitions(message.selectedText); - } - break; + break; + + case "mot_selectionne": + if (message.selectedText) { + log("ðŸ–‹ï¸ Mot sélectionné :", message.selectedText); + const selectedWordElement = document.getElementById("motSelectionne"); + if (selectedWordElement) { + selectedWordElement.textContent = message.selectedText; + } else { + console.warn("âš ï¸ Ã‰lément #motSelectionne introuvable."); + } + const lexiconResultElement = document.getElementById("lexiconResult"); + if (lexiconResultElement) { + lexiconResultElement.innerHTML = ""; + } + openBlock("etatContent"); + } + break; - case "showDefinitions": - if (Array.isArray(message.definitions)) { - window.displayDefinitions(message.definitions); - } - break; + case "getDefinition": + if (message.selectedText) { + log("📖 Recherche des définitions pour :", message.selectedText); + openBlock("definitionContent"); + await window.showDefinitions(message.selectedText); + } + break; - case "fetchWiktionaryDefinitionResponse": - if (message.selectedText) { - log(`📖 Réception de la définition du Wiktionnaire pour '${message.selectedText}'`); - window.displayDefinitions(message.definitions); - } - break; + case "showDefinitions": + if (Array.isArray(message.definitions)) { + window.displayDefinitions(message.definitions); + } + break; - case "showLexiconResult": - log("📚 Résultat des lexiques reçus :", message.lexicons); - window.displayLexiconResults(message.lexicons); - break; - - case "addWordResult": - const lexiconResultElement = document.getElementById("lexiconResult"); - if (lexiconResultElement) { - lexiconResultElement.innerHTML = message.lexicons; - } - break; + case "fetchWiktionaryDefinitionResponse": + if (message.selectedText) { + log(`📖 Réception de la définition du Wiktionnaire pour '${message.selectedText}'`); + window.displayDefinitions(message.definitions); + } + break; - case "addToLexicon": - handleAddWordClick(); - break; - - case "openLexiconBlock": - openBlock("menuContent"); - break; + case "showLexiconResult": + log("📚 Résultat des lexiques reçus :", message.lexicons); + window.displayLexiconResults(message.lexicons); + break; - case "toggleAuth": - break; - - case "authStatusChanged": - break; - - case "updateUI": - await refreshSidebarState(); - break; - - case "pyodide-simplemma-ready": - return; - - case "saveToken": - authToken = message.token; - break; + case "addWordResult": + const lexiconResultElement = document.getElementById("lexiconResult"); + if (lexiconResultElement) { + lexiconResultElement.innerHTML = message.lexicons; + } + break; - case "closeSidebarBlocks": - closeBlock("menuContent"); - closeBlock("etatContent"); - closeBlock("definitionContent") - break; + case "addToLexicon": + handleAddWordClick(); + break; + + case "openLexiconBlock": + openBlock("menuContent"); + break; + + case "toggleAuth": + break; + + case "authStatusChanged": + break; + + case "updateUI": + await refreshSidebarState(); + break; + + case "pyodide-simplemma-ready": + return; + + case "saveToken": + authToken = message.token; + break; + + case "closeSidebarBlocks": + closeBlock("menuContent"); + closeBlock("etatContent"); + closeBlock("definitionContent") + break; + + case "register-stats-script": + break; + + case "register-highlighting-script": + log("✅ Script de surlignage enregistré"); + browser.runtime.sendMessage({ + command: "updateAuthToken", + token: authToken + }); + break; - default: - console.warn("âš ï¸ Action inconnue reçue :", message.action); + default: + console.warn("âš ï¸ Action inconnue reçue :", message.command); + } } }); @@ -677,3 +705,18 @@ document.addEventListener("DOMContentLoaded", async () => { } }); }); + +async function toggleLexiconHighlight(lexiconId, isActive) { + try { + await browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { + browser.tabs.sendMessage(tabs[0].id, { + command: isActive ? "activate-highlighting" : "deactivate-highlighting", + lexiconId: lexiconId + }); + }); + + log(`✅ Surlignage ${isActive ? 'activé' : 'désactivé'} pour le lexique ${lexiconId}`); + } catch (error) { + console.error(`⌠Erreur lors du toggle du surlignage pour le lexique ${lexiconId}:`, error); + } +} diff --git a/src/utils/api.js b/src/utils/api.js index 73d7fd0..d725f8d 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -15,7 +15,7 @@ document.addEventListener("mouseup", () => { }); // ───────────────────────────────────────────────────────────────────────────── -// â–Œ Fonction utilitaire pour appeler l’API +// â–Œ Fonction utilitaire pour appeler l'API // ───────────────────────────────────────────────────────────────────────────── /** * Effectue une requête API (GET, POST, etc.) avec ou sans body JSON @@ -54,7 +54,7 @@ async function callApi(url, authToken = null, method = 'GET', data = null) { // ───────────────────────────────────────────────────────────────────────────── /** - * Récupère les lexiques de l’utilisateur, + * Récupère les lexiques de l'utilisateur, * en langue par défaut "fr". * * @param {string} authToken - Le token d'authentification. @@ -67,7 +67,7 @@ async function getLexicons(authToken) { } /** - * Récupère tous les lexiques (catégories) de l’utilisateur + * Récupère tous les lexiques (catégories) de l'utilisateur */ async function getAllCategoriesLexicons(authToken) { const categories = ["User", "Group", "Zero", "New words"]; @@ -118,7 +118,7 @@ async function getAllLexiconWords(authToken) { const lexicons = await getLexicons(authToken); if (!Array.isArray(lexicons) || lexicons.length === 0) { - console.warn("âš ï¸ Aucun lexique retourné par l’API pour ces paramètres."); + console.warn("âš ï¸ Aucun lexique retourné par l'API pour ces paramètres."); return {}; } @@ -127,6 +127,11 @@ async function getAllLexiconWords(authToken) { for (const lexicon of lexicons) { const entries = await getLexiconEntries(authToken, lexicon.id); + // Vérification que entries est bien un tableau + if (!Array.isArray(entries)) { + console.warn(`âš ï¸ Format invalide pour les entrées du lexique ${lexicon.id}:`, entries); + continue; + } const allGraphies = entries.map(entry => entry.graphy); // Création d'un libellé unique pour le lexique @@ -187,13 +192,13 @@ async function getWiktionaryDefinition(word) { */ async function AddWord(authToken, selectedWord, lexiconIds, force = false) { if (!authToken) { - throw new Error("Aucun token d’authentification fourni."); + throw new Error("Aucun token d'authentification fourni."); } if (!selectedWord) { - throw new Error("Aucun mot n’a été spécifié pour l’ajout."); + throw new Error("Aucun mot n'a été spécifié pour l'ajout."); } if (!Array.isArray(lexiconIds) || lexiconIds.length === 0) { - throw new Error("Aucun lexique sélectionné pour l’ajout."); + throw new Error("Aucun lexique sélectionné pour l'ajout."); } const url = "https://babalex.lezinter.net/api/entry/create"; diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js new file mode 100644 index 0000000..97d6225 --- /dev/null +++ b/src/utils/highlighting.js @@ -0,0 +1,465 @@ +// Logs immédiats pour vérifier l'injection +console.log("🔵 DÉBUT DU FICHIER highlighting.js"); +try { + log("✅ highlighting.js chargé"); +} catch (e) { + console.error("⌠Erreur avec la fonction log:", e); +} + +// Vérification de l'existence de l'objet browser +console.log("🔠Vérification de l'environnement:", { + hasBrowser: typeof browser !== 'undefined', + hasChrome: typeof chrome !== 'undefined', + windowLocation: window.location.href +}); + +// Ajout d'un log global pour capturer les erreurs non gérées +window.onerror = function(msg, url, line, col, error) { + console.error("🔴 Erreur globale:", { + message: msg, + url: url, + line: line, + col: col, + error: error + }); + return false; +}; + +// Au début du fichier, récupérons le token du storage local +async function initAuthToken() { + try { + const { accessToken } = await browser.storage.local.get("accessToken"); + if (accessToken) { + window.authToken = accessToken; + log("🔑 Token récupéré depuis le stockage local"); + } else { + log("âš ï¸ Aucun token trouvé dans le stockage local"); + } + } catch (error) { + console.error("⌠Erreur lors de la récupération du token:", error); + } +} + +// Appel immédiat de l'initialisation +initAuthToken(); + +// Gardons aussi l'écoute des mises à jour du token +browser.runtime.onMessage.addListener((message) => { + if (message.command === "updateAuthToken" && message.token) { + window.authToken = message.token; + log("🔑 Token mis à jour via message"); + } +}); + +// Déplacer la déclaration de l'observer au début du fichier, avant son utilisation +let observer = null; + +// Au début du fichier, après la déclaration de observer +document.addEventListener('visibilitychange', async () => { + if (document.visibilityState === 'visible' && highlightingActive) { + log("📄 Page redevenue visible, réinitialisation complète du surlignage"); + // Réinitialiser complètement le surlignage + removeAllHighlights(); + await updateLexiconCache(); + highlightVisibleContent(); + attachMutationObserver(); + } +}); + +// Ajoutons aussi un listener pour le chargement complet de la page +window.addEventListener('load', async () => { + if (highlightingActive) { + log("📄 Page chargée, réinitialisation complète du surlignage"); + // Réinitialiser complètement le surlignage + removeAllHighlights(); + await updateLexiconCache(); + highlightVisibleContent(); + attachMutationObserver(); + } +}); + +(function () { + try { + console.log("🟢 IIFE de highlighting.js démarrée"); + + // Vérification immédiate des objets critiques + console.log("🔠État initial:", { + hasAuthToken: !!window.authToken, + hasGetAllLexiconWords: !!window.getAllLexiconWords, + browserRuntime: !!browser?.runtime, + documentBody: !!document.body + }); + + // Amélioration du log initial pour vérifier si le script s'exécute + console.log("🟢 Début d'exécution du script highlighting.js"); + + // Cache des mots par lexique + let lexiconWordsCache = new Map(); + let highlightingActive = false; + let activeLexiconIds = new Set(); + + // ───────────────────────────────────────────────────────────────────────────── + // Gestion des messages du background + // ───────────────────────────────────────────────────────────────────────────── + log("📡 Enregistrement du listener de messages"); + browser.runtime.onMessage.addListener((message, sender, sendResponse) => { + console.log("📨 Message reçu:", message, "Context:", { + highlightingActive, + activeLexiconIds: Array.from(activeLexiconIds), + hasAuthToken: !!window.authToken, + hasGetAllLexiconWords: !!window.getAllLexiconWords + }); + + if (message.command === "activate-highlighting") { + log(`🎯 Activation du surlignage pour le lexique ${message.lexiconId}`); + // Exécuter startHighlighting de manière synchrone et envoyer la réponse + startHighlighting(message.lexiconId) + .then(result => sendResponse(result)) + .catch(error => { + console.error("Erreur lors de l'activation:", error); + sendResponse(false); + }); + return true; // Indique que nous allons envoyer une réponse asynchrone + } + + if (message.command === "deactivate-highlighting") { + log(`🚫 Désactivation du surlignage pour le lexique ${message.lexiconId}`); + stopHighlighting(message.lexiconId); + sendResponse(true); + return true; + } + + sendResponse(false); + return false; + }); + + log("📡 Enregistrement du script auprès du background"); + browser.runtime.sendMessage({ command: "register-highlighting-script" }); + + // Déplacer la vérification hasRun ici + if (window.hasRun) { + console.log("âš ï¸ highlighting.js déjà chargé, mais listener maintenu"); + return; + } + window.hasRun = true; + log("🚀 Initialisation de highlighting.js"); + + // ───────────────────────────────────────────────────────────────────────────── + // Fonctions principales + // ───────────────────────────────────────────────────────────────────────────── + async function startHighlighting(lexiconId) { + console.log("🎬 startHighlighting appelé avec:", { + lexiconId, + windowContext: { + authToken: !!window.authToken, + getAllLexiconWords: !!window.getAllLexiconWords, + location: window.location.href + } + }); + log(`🎬 Démarrage du surlignage (lexiconId: ${lexiconId})`); + + try { + // Attendre jusqu'à 5 secondes maximum pour le token + let attempts = 0; + while (!window.authToken && attempts < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + attempts++; + } + + if (!window.authToken) { + throw new Error("⌠Pas de token d'authentification disponible après attente"); + } + + if (lexiconId) { + activeLexiconIds.add(lexiconId); + log("📊 Lexiques actifs:", Array.from(activeLexiconIds)); + } + + highlightingActive = true; + + log("🔄 Début de la mise à jour du cache"); + await updateLexiconCache(); + log("✅ Cache mis à jour, début du surlignage"); + highlightVisibleContent(); + attachMutationObserver(); + return true; + } catch (error) { + console.error("⌠Erreur détaillée lors du démarrage du surlignage:", { + error: error.message, + stack: error.stack, + authToken: !!window.authToken, + getAllLexiconWords: typeof window.getAllLexiconWords, + activeLexiconIds: Array.from(activeLexiconIds) + }); + return false; + } + } + + function stopHighlighting(lexiconId) { + log(`🛑 Arrêt du surlignage (lexiconId: ${lexiconId})`); + if (lexiconId) { + activeLexiconIds.delete(lexiconId); + log("📊 Lexiques actifs restants:", Array.from(activeLexiconIds)); + + if (activeLexiconIds.size === 0) { + log("🔄 Plus aucun lexique actif, désactivation complète"); + highlightingActive = false; + removeAllHighlights(); + detachMutationObserver(); + } else { + log("🔄 Rafraîchissement du surlignage pour les lexiques restants"); + removeAllHighlights(); + highlightVisibleContent(); + } + } else { + log("🧹 Désactivation globale du surlignage"); + highlightingActive = false; + activeLexiconIds.clear(); + removeAllHighlights(); + detachMutationObserver(); + } + } + + async function updateLexiconCache() { + console.log("📥 updateLexiconCache - Début avec context:", { + authToken: !!window.authToken, + getAllLexiconWords: !!window.getAllLexiconWords, + activeLexiconIds: Array.from(activeLexiconIds) + }); + try { + if (!window.authToken) { + throw new Error("Pas de token d'authentification"); + } + + // Vérification explicite de getAllLexiconWords + if (typeof window.getAllLexiconWords !== 'function') { + log("âš ï¸ getAllLexiconWords n'est pas une fonction"); + log("Type de getAllLexiconWords:", typeof window.getAllLexiconWords); + log("Contenu de window.getAllLexiconWords:", window.getAllLexiconWords); + throw new Error("getAllLexiconWords n'est pas disponible"); + } + + log("📥 Appel de getAllLexiconWords..."); + const allWords = await window.getAllLexiconWords(window.authToken); + log("📠Réponse de getAllLexiconWords:", allWords); + + if (!allWords || typeof allWords !== 'object') { + throw new Error(`Format de données invalide: ${JSON.stringify(allWords)}`); + } + + lexiconWordsCache.clear(); + + // Vérification de la structure des données + if (Object.keys(allWords).length === 0) { + log("âš ï¸ Aucun lexique reçu de getAllLexiconWords"); + return false; + } + + for (const [lexiconName, words] of Object.entries(allWords)) { + if (!Array.isArray(words)) { + console.warn(`âš ï¸ Format invalide pour le lexique ${lexiconName}:`, words); + continue; + } + + const lexiconId = lexiconName.match(/\[(\d+)\]$/)?.[1]; + if (!lexiconId) { + console.warn(`âš ï¸ Impossible d'extraire l'ID du lexique depuis: ${lexiconName}`); + continue; + } + + log(`📎 Traitement du lexique ${lexiconName} (ID: ${lexiconId})`); + + if (activeLexiconIds.has(Number(lexiconId))) { + lexiconWordsCache.set(lexiconId, new Set(words)); + log(`📖 Lexique ${lexiconId} chargé avec ${words.length} mots`); + } + } + + log("✅ Cache des lexiques mis à jour:", + Object.fromEntries([...lexiconWordsCache.entries()].map(([id, words]) => [id, [...words]]))); + return true; + } catch (error) { + console.error("⌠Erreur dans updateLexiconCache:", { + message: error.message, + stack: error.stack, + authTokenExists: !!window.authToken, + getAllLexiconWordsType: typeof window.getAllLexiconWords, + response: allWords + }); + throw error; + } + } + + // ───────────────────────────────────────────────────────────────────────────── + // Fonctions de surlignage + // ───────────────────────────────────────────────────────────────────────────── + function highlightVisibleContent() { + if (!highlightingActive) { + log("â¸ï¸ Surlignage inactif, sortie"); + return; + } + log("🔠Début du surlignage du contenu visible"); + + const textNodes = []; + const walker = document.createTreeWalker( + document.body, + NodeFilter.SHOW_TEXT, + { + acceptNode: (node) => { + if (node.parentElement?.closest('script, style, .lexicon-highlight')) { + return NodeFilter.FILTER_REJECT; + } + return NodeFilter.FILTER_ACCEPT; + } + } + ); + + let node; + while (node = walker.nextNode()) { + textNodes.push(node); + } + + log(`🔤 ${textNodes.length} nÅ“uds de texte trouvés à traiter`); + textNodes.forEach(processTextNode); + } + + function processTextNode(textNode) { + if (activeLexiconIds.size === 0) { + log("âš ï¸ Aucun lexique actif, sortie du processTextNode"); + return; + } + + const text = textNode.textContent; + log(`🔠Traitement du texte: "${text.substring(0, 50)}..."`); + + let lastIndex = 0; + let fragments = []; + + const allWords = new Set(); + for (const [lexiconId, words] of lexiconWordsCache.entries()) { + // Convertir directement en nombre car lexiconId est déjà l'ID numérique + const numericId = parseInt(lexiconId); + log(`🔄 Vérification du lexique ${lexiconId} (ID: ${numericId})`); + if (activeLexiconIds.has(numericId)) { + log(`✅ Lexique ${lexiconId} actif, ajout de ${words.size} mots`); + words.forEach(word => allWords.add(word)); + } + } + + log(`🔤 Nombre total de mots à rechercher: ${allWords.size}`); + if (allWords.size === 0) { + log("âš ï¸ Aucun mot à rechercher dans les lexiques actifs"); + return; + } + + const wordsPattern = Array.from(allWords) + .sort((a, b) => b.length - a.length) + .map(escapeRegExp) + .join("|"); + + if (!wordsPattern) { + log("âš ï¸ Aucun mot à rechercher, sortie"); + return; + } + + const regex = new RegExp(`\\b(${wordsPattern})\\b`, "gi"); + let match; + let matchCount = 0; + + while ((match = regex.exec(text)) !== null) { + matchCount++; + if (match.index > lastIndex) { + fragments.push(document.createTextNode(text.slice(lastIndex, match.index))); + } + + const span = document.createElement("span"); + span.textContent = match[0]; + span.className = "lexicon-highlight"; + span.style.backgroundColor = "rgba(255, 255, 0, 0.3)"; + span.style.borderBottom = "1px dashed #666"; + fragments.push(span); + + lastIndex = regex.lastIndex; + } + + if (matchCount > 0) { + log(`✨ ${matchCount} correspondances trouvées dans le nÅ“ud`); + } + + if (lastIndex < text.length) { + fragments.push(document.createTextNode(text.slice(lastIndex))); + } + + if (fragments.length > 0) { + const parent = textNode.parentNode; + fragments.forEach(fragment => parent.insertBefore(fragment, textNode)); + parent.removeChild(textNode); + } + } + + function removeAllHighlights() { + log("🧹 Suppression de tous les surlignages"); + const highlights = document.querySelectorAll('.lexicon-highlight'); + log(`📊 ${highlights.length} surlignages à supprimer`); + + highlights.forEach(highlight => { + const text = highlight.textContent; + highlight.replaceWith(text); + }); + } + + // ───────────────────────────────────────────────────────────────────────────── + // Gestion des mutations DOM + // ───────────────────────────────────────────────────────────────────────────── + function attachMutationObserver() { + log("👀 Attachement de l'observateur de mutations"); + observer = new MutationObserver((mutations) => { + log(`🔄 ${mutations.length} mutations DOM détectées`); + mutations.forEach(mutation => { + if (mutation.type === 'childList') { + mutation.addedNodes.forEach(node => { + if (node.nodeType === Node.ELEMENT_NODE) { + highlightVisibleContent(); + } + }); + } + }); + }); + + observer.observe(document.body, { + childList: true, + subtree: true + }); + } + + function detachMutationObserver() { + if (observer) { + log("👋 Détachement de l'observateur de mutations"); + observer.disconnect(); + observer = null; + } + } + + // ───────────────────────────────────────────────────────────────────────────── + // Utilitaires + // ───────────────────────────────────────────────────────────────────────────── + function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } + + function getLexiconIdFromName(lexiconName) { + const match = lexiconName.match(/\[(\d+)\]$/); + const id = match ? parseInt(match[1]) : null; + log(`ðŸ·ï¸ Extraction de l'ID depuis '${lexiconName}': ${id}`); + return id; + } + + // Ajout d'une vérification au démarrage + log("🔠Vérification des dépendances au chargement:", { + authToken: !!window.authToken, + getAllLexiconWords: typeof window.getAllLexiconWords + }); + } catch (error) { + console.error("🔴 Erreur critique dans l'IIFE:", error); + } +})(); -- GitLab From b08bbae3f87eee007976dfdd92d3b340f1169a0a Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:57:14 +0100 Subject: [PATCH 2/9] Correction beugs --- manifest.json | 9 ++++++++ src/sidebar/sidebar.js | 5 +++++ src/utils/highlighting.js | 44 ++++++++++++++++++--------------------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/manifest.json b/manifest.json index 2591e94..d67fa45 100644 --- a/manifest.json +++ b/manifest.json @@ -74,6 +74,15 @@ "src/utils/stats.js" ], "run_at": "document_end" + }, + { + "matches": ["<all_urls>"], + "js": [ + "src/utils/logger.js", + "src/utils/api.js", + "src/utils/highlighting.js" + ], + "run_at": "document_start" } ], diff --git a/src/sidebar/sidebar.js b/src/sidebar/sidebar.js index 2c4123b..5b90964 100644 --- a/src/sidebar/sidebar.js +++ b/src/sidebar/sidebar.js @@ -590,6 +590,11 @@ browser.runtime.onMessage.addListener(async (message) => { }); break; + case "updateAuthToken": + authToken = message.token; + window.authToken = message.token; + break; + default: console.warn("âš ï¸ Action inconnue reçue :", message.command); } diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index 97d6225..4ffd5c9 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -9,7 +9,6 @@ try { // Vérification de l'existence de l'objet browser console.log("🔠Vérification de l'environnement:", { hasBrowser: typeof browser !== 'undefined', - hasChrome: typeof chrome !== 'undefined', windowLocation: window.location.href }); @@ -31,12 +30,16 @@ async function initAuthToken() { const { accessToken } = await browser.storage.local.get("accessToken"); if (accessToken) { window.authToken = accessToken; + authToken = accessToken; log("🔑 Token récupéré depuis le stockage local"); + return true; } else { log("âš ï¸ Aucun token trouvé dans le stockage local"); + return false; } } catch (error) { console.error("⌠Erreur lors de la récupération du token:", error); + return false; } } @@ -47,18 +50,15 @@ initAuthToken(); browser.runtime.onMessage.addListener((message) => { if (message.command === "updateAuthToken" && message.token) { window.authToken = message.token; - log("🔑 Token mis à jour via message"); + authToken = message.token; + log("🔑 Token mis à jour via message:", !!message.token); } }); -// Déplacer la déclaration de l'observer au début du fichier, avant son utilisation -let observer = null; - // Au début du fichier, après la déclaration de observer document.addEventListener('visibilitychange', async () => { - if (document.visibilityState === 'visible' && highlightingActive) { + if (document.visibilityState === 'visible' && window.highlightingActive) { log("📄 Page redevenue visible, réinitialisation complète du surlignage"); - // Réinitialiser complètement le surlignage removeAllHighlights(); await updateLexiconCache(); highlightVisibleContent(); @@ -68,9 +68,8 @@ document.addEventListener('visibilitychange', async () => { // Ajoutons aussi un listener pour le chargement complet de la page window.addEventListener('load', async () => { - if (highlightingActive) { + if (window.highlightingActive) { log("📄 Page chargée, réinitialisation complète du surlignage"); - // Réinitialiser complètement le surlignage removeAllHighlights(); await updateLexiconCache(); highlightVisibleContent(); @@ -80,6 +79,12 @@ window.addEventListener('load', async () => { (function () { try { + // Déplacer la vérification hasRun ici + if (window.hasRun) { + console.log("âš ï¸ highlighting.js déjà chargé, mais listener maintenu"); + return; + } + window.hasRun = true; console.log("🟢 IIFE de highlighting.js démarrée"); // Vérification immédiate des objets critiques @@ -93,10 +98,11 @@ window.addEventListener('load', async () => { // Amélioration du log initial pour vérifier si le script s'exécute console.log("🟢 Début d'exécution du script highlighting.js"); - // Cache des mots par lexique + // Variables globales pour le script let lexiconWordsCache = new Map(); let highlightingActive = false; let activeLexiconIds = new Set(); + let observer = null; // ───────────────────────────────────────────────────────────────────────────── // Gestion des messages du background @@ -136,11 +142,6 @@ window.addEventListener('load', async () => { log("📡 Enregistrement du script auprès du background"); browser.runtime.sendMessage({ command: "register-highlighting-script" }); - // Déplacer la vérification hasRun ici - if (window.hasRun) { - console.log("âš ï¸ highlighting.js déjà chargé, mais listener maintenu"); - return; - } window.hasRun = true; log("🚀 Initialisation de highlighting.js"); @@ -159,15 +160,11 @@ window.addEventListener('load', async () => { log(`🎬 Démarrage du surlignage (lexiconId: ${lexiconId})`); try { - // Attendre jusqu'à 5 secondes maximum pour le token - let attempts = 0; - while (!window.authToken && attempts < 50) { - await new Promise(resolve => setTimeout(resolve, 100)); - attempts++; - } - + // Attendre que le token soit disponible via initAuthToken + await initAuthToken(); + if (!window.authToken) { - throw new Error("⌠Pas de token d'authentification disponible après attente"); + throw new Error("⌠Pas de token d'authentification disponible après initialisation"); } if (lexiconId) { @@ -425,7 +422,6 @@ window.addEventListener('load', async () => { } }); }); - observer.observe(document.body, { childList: true, subtree: true -- GitLab From bd4a9636f97f729bc5c803c4be51ef3796620a97 Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:59:53 +0100 Subject: [PATCH 3/9] Correction temps de traitement surlignage --- src/utils/highlighting.js | 67 +++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index 4ffd5c9..091579a 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -297,13 +297,22 @@ window.addEventListener('load', async () => { } log("🔠Début du surlignage du contenu visible"); + // Ajout d'une limite de traitement par lot + const BATCH_SIZE = 100; + const BATCH_DELAY = 10; // ms entre chaque lot + const textNodes = []; const walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, { acceptNode: (node) => { - if (node.parentElement?.closest('script, style, .lexicon-highlight')) { + // Optimisation des filtres + const parent = node.parentElement; + if (!parent || + parent.closest('script, style, .lexicon-highlight') || + !node.textContent.trim() || + getComputedStyle(parent).display === 'none') { return NodeFilter.FILTER_REJECT; } return NodeFilter.FILTER_ACCEPT; @@ -317,7 +326,24 @@ window.addEventListener('load', async () => { } log(`🔤 ${textNodes.length} nÅ“uds de texte trouvés à traiter`); - textNodes.forEach(processTextNode); + + // Traitement par lots + const processNextBatch = (startIndex) => { + if (!highlightingActive || startIndex >= textNodes.length) { + return; + } + + const endIndex = Math.min(startIndex + BATCH_SIZE, textNodes.length); + const batch = textNodes.slice(startIndex, endIndex); + + batch.forEach(processTextNode); + + if (endIndex < textNodes.length) { + setTimeout(() => processNextBatch(endIndex), BATCH_DELAY); + } + }; + + processNextBatch(0); } function processTextNode(textNode) { @@ -410,18 +436,39 @@ window.addEventListener('load', async () => { // ───────────────────────────────────────────────────────────────────────────── function attachMutationObserver() { log("👀 Attachement de l'observateur de mutations"); + + let debounceTimer = null; + const DEBOUNCE_DELAY = 250; // ms + observer = new MutationObserver((mutations) => { - log(`🔄 ${mutations.length} mutations DOM détectées`); - mutations.forEach(mutation => { - if (mutation.type === 'childList') { - mutation.addedNodes.forEach(node => { - if (node.nodeType === Node.ELEMENT_NODE) { - highlightVisibleContent(); + if (debounceTimer) { + clearTimeout(debounceTimer); + } + + debounceTimer = setTimeout(() => { + log(`🔄 Traitement groupé de ${mutations.length} mutations DOM`); + let shouldHighlight = false; + + for (const mutation of mutations) { + if (mutation.type === 'childList') { + for (const node of mutation.addedNodes) { + if (node.nodeType === Node.ELEMENT_NODE && + !node.closest('.lexicon-highlight') && + node.textContent.trim()) { + shouldHighlight = true; + break; + } } - }); + } + if (shouldHighlight) break; } - }); + + if (shouldHighlight) { + highlightVisibleContent(); + } + }, DEBOUNCE_DELAY); }); + observer.observe(document.body, { childList: true, subtree: true -- GitLab From 2cf8e5f59a9dc9cdc11e6d93624f4df8220b91dd Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 12:20:21 +0100 Subject: [PATCH 4/9] Correction beug bouton surlignage --- src/sidebar/sidebar.html | 2 + src/sidebar/sidebar.js | 43 ++++++++++- src/utils/highlighting.js | 150 ++++++++++++++++++++------------------ 3 files changed, 122 insertions(+), 73 deletions(-) diff --git a/src/sidebar/sidebar.html b/src/sidebar/sidebar.html index 79f9c09..96de998 100644 --- a/src/sidebar/sidebar.html +++ b/src/sidebar/sidebar.html @@ -259,6 +259,8 @@ transition: filter 0.3s ease-in-out; } + /* Ajout de la classe active */ + .lexique-highlight-toggle.active .feutre-icon, .lexique-highlight-toggle[data-active="true"] .feutre-icon { filter: brightness(0) saturate(100%) invert(83%) sepia(89%) saturate(588%) hue-rotate(360deg); } diff --git a/src/sidebar/sidebar.js b/src/sidebar/sidebar.js index 5b90964..c51f264 100644 --- a/src/sidebar/sidebar.js +++ b/src/sidebar/sidebar.js @@ -217,7 +217,7 @@ async function fetchLexicons() { lexiconMap.set(lex.id, lexiconName); }); - displayLexiconsWithCheckbox(lexicons.map((lex) => ({ + await displayLexiconsWithCheckbox(lexicons.map((lex) => ({ lexiconName: lex.category === "User" ? DEBUG @@ -229,6 +229,9 @@ async function fetchLexicons() { lexiconId: lex.id, active: lex.active || false, }))); + + // Restaurer l'état des boutons après l'affichage + await restoreHighlightingState(); } catch (error) { console.error("⌠Erreur lors du chargement des lexiques :", error.message); const lexiquesContainer = document.getElementById("lexiques"); @@ -286,6 +289,9 @@ async function displayLexiconsWithCheckbox(lexicons) { // Conteneur pour le bouton de surlignage (avec tooltip) const highlightButton = document.createElement("button"); highlightButton.className = "tooltip-container lexique-highlight-toggle"; + if (active) { + highlightButton.classList.add('active'); + } highlightButton.dataset.lexiconId = lexiconId; highlightButton.dataset.active = active ? "true" : "false"; const feutreIcon = document.createElement("img"); @@ -296,7 +302,7 @@ async function displayLexiconsWithCheckbox(lexicons) { highlightTooltip.className = "tooltip"; highlightTooltip.textContent = "Activer/Désactiver le surlignage des mots du lexique"; - // Gestion du clic pour activer/désactiver le surlignage + // Mise à jour du gestionnaire d'événements highlightButton.addEventListener("click", async () => { let currentState = highlightButton.dataset.active === "true"; let newState = !currentState; @@ -304,6 +310,11 @@ async function displayLexiconsWithCheckbox(lexicons) { await toggleLexiconHighlight(lexiconId, newState); highlightButton.dataset.active = newState ? "true" : "false"; highlightButton.classList.toggle("active", newState); + + // Sauvegarder l'état dans le storage local + const activeLexicons = Array.from(document.querySelectorAll('.lexique-highlight-toggle[data-active="true"]')) + .map(btn => parseInt(btn.dataset.lexiconId)); + await browser.storage.local.set({ activeLexicons }); } catch (error) { console.error("Erreur lors du toggle de surlignage pour le lexique", lexiconId, ":", error); } @@ -343,6 +354,24 @@ async function displayLexiconsWithCheckbox(lexicons) { }, 100); } +// Ajouter une fonction pour restaurer l'état des boutons au chargement +async function restoreHighlightingState() { + try { + const { activeLexicons } = await browser.storage.local.get("activeLexicons"); + if (activeLexicons && Array.isArray(activeLexicons)) { + const buttons = document.querySelectorAll('.lexique-highlight-toggle'); + buttons.forEach(button => { + const lexiconId = parseInt(button.dataset.lexiconId); + const isActive = activeLexicons.includes(lexiconId); + button.dataset.active = isActive ? "true" : "false"; + button.classList.toggle("active", isActive); + }); + } + } catch (error) { + console.error("Erreur lors de la restauration de l'état des boutons:", error); + } +} + function initModal() { log("initModal appelé"); const modalOverlay = document.getElementById("modalOverlay"); @@ -483,7 +512,7 @@ browser.runtime.onMessage.addListener(async (message) => { if (message.command) { switch (message.command) { case "activate-highlighting": - const highlightButton = document.querySelector(`[data-lexicon-id="${message.lexiconId}"] .lexique-highlight-toggle`); + const highlightButton = document.querySelector(`button[data-lexicon-id="${message.lexiconId}"]`); if (highlightButton) { highlightButton.dataset.active = "true"; highlightButton.classList.add("active"); @@ -491,7 +520,7 @@ browser.runtime.onMessage.addListener(async (message) => { break; case "deactivate-highlighting": - const highlightButtonOff = document.querySelector(`[data-lexicon-id="${message.lexiconId}"] .lexique-highlight-toggle`); + const highlightButtonOff = document.querySelector(`button[data-lexicon-id="${message.lexiconId}"]`); if (highlightButtonOff) { highlightButtonOff.dataset.active = "false"; highlightButtonOff.classList.remove("active"); @@ -713,6 +742,12 @@ document.addEventListener("DOMContentLoaded", async () => { async function toggleLexiconHighlight(lexiconId, isActive) { try { + const button = document.querySelector(`button[data-lexicon-id="${lexiconId}"]`); + if (button) { + button.dataset.active = isActive.toString(); + button.classList.toggle('active', isActive); + } + await browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { browser.tabs.sendMessage(tabs[0].id, { command: isActive ? "activate-highlighting" : "deactivate-highlighting", diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index 091579a..27402c8 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -57,8 +57,8 @@ browser.runtime.onMessage.addListener((message) => { // Au début du fichier, après la déclaration de observer document.addEventListener('visibilitychange', async () => { - if (document.visibilityState === 'visible' && window.highlightingActive) { - log("📄 Page redevenue visible, réinitialisation complète du surlignage"); + if (document.visibilityState === 'visible' && window.highlightingActive && activeLexiconIds.size > 0) { + log("📄 Page redevenue visible, réinitialisation du surlignage"); removeAllHighlights(); await updateLexiconCache(); highlightVisibleContent(); @@ -67,9 +67,9 @@ document.addEventListener('visibilitychange', async () => { }); // Ajoutons aussi un listener pour le chargement complet de la page -window.addEventListener('load', async () => { - if (window.highlightingActive) { - log("📄 Page chargée, réinitialisation complète du surlignage"); +window.addEventListener('pageshow', async () => { + if (window.highlightingActive && activeLexiconIds.size > 0) { + log("📄 Page affichée (pageshow), réinitialisation du surlignage"); removeAllHighlights(); await updateLexiconCache(); highlightVisibleContent(); @@ -77,30 +77,19 @@ window.addEventListener('load', async () => { } }); +// Déplacer checkAndRestoreHighlightingState après la déclaration de startHighlighting (function () { try { - // Déplacer la vérification hasRun ici if (window.hasRun) { - console.log("âš ï¸ highlighting.js déjà chargé, mais listener maintenu"); + console.log("âš ï¸ highlighting.js déjà chargé"); return; } window.hasRun = true; - console.log("🟢 IIFE de highlighting.js démarrée"); - - // Vérification immédiate des objets critiques - console.log("🔠État initial:", { - hasAuthToken: !!window.authToken, - hasGetAllLexiconWords: !!window.getAllLexiconWords, - browserRuntime: !!browser?.runtime, - documentBody: !!document.body - }); - - // Amélioration du log initial pour vérifier si le script s'exécute - console.log("🟢 Début d'exécution du script highlighting.js"); // Variables globales pour le script let lexiconWordsCache = new Map(); let highlightingActive = false; + window.highlightingActive = false; let activeLexiconIds = new Set(); let observer = null; @@ -118,102 +107,103 @@ window.addEventListener('load', async () => { if (message.command === "activate-highlighting") { log(`🎯 Activation du surlignage pour le lexique ${message.lexiconId}`); - // Exécuter startHighlighting de manière synchrone et envoyer la réponse startHighlighting(message.lexiconId) - .then(result => sendResponse(result)) + .then(() => { + window.highlightingActive = true; + sendResponse(true); + }) .catch(error => { - console.error("Erreur lors de l'activation:", error); + console.error("⌠Erreur lors de l'activation:", error); sendResponse(false); }); - return true; // Indique que nous allons envoyer une réponse asynchrone + return true; } if (message.command === "deactivate-highlighting") { log(`🚫 Désactivation du surlignage pour le lexique ${message.lexiconId}`); - stopHighlighting(message.lexiconId); - sendResponse(true); + stopHighlighting(message.lexiconId) + .then(() => { + if (activeLexiconIds.size === 0) { + window.highlightingActive = false; + } + sendResponse(true); + }) + .catch(error => { + console.error("⌠Erreur lors de la désactivation:", error); + sendResponse(false); + }); return true; } - sendResponse(false); return false; }); log("📡 Enregistrement du script auprès du background"); browser.runtime.sendMessage({ command: "register-highlighting-script" }); - window.hasRun = true; log("🚀 Initialisation de highlighting.js"); // ───────────────────────────────────────────────────────────────────────────── // Fonctions principales // ───────────────────────────────────────────────────────────────────────────── async function startHighlighting(lexiconId) { - console.log("🎬 startHighlighting appelé avec:", { - lexiconId, - windowContext: { - authToken: !!window.authToken, - getAllLexiconWords: !!window.getAllLexiconWords, - location: window.location.href - } - }); - log(`🎬 Démarrage du surlignage (lexiconId: ${lexiconId})`); - try { - // Attendre que le token soit disponible via initAuthToken await initAuthToken(); if (!window.authToken) { - throw new Error("⌠Pas de token d'authentification disponible après initialisation"); + throw new Error("⌠Pas de token d'authentification disponible"); } if (lexiconId) { activeLexiconIds.add(lexiconId); - log("📊 Lexiques actifs:", Array.from(activeLexiconIds)); + const activeLexicons = Array.from(activeLexiconIds); + await browser.storage.local.set({ activeLexicons }); + log("📊 Lexiques actifs sauvegardés:", activeLexicons); } + window.highlightingActive = true; highlightingActive = true; - log("🔄 Début de la mise à jour du cache"); await updateLexiconCache(); - log("✅ Cache mis à jour, début du surlignage"); highlightVisibleContent(); attachMutationObserver(); return true; } catch (error) { - console.error("⌠Erreur détaillée lors du démarrage du surlignage:", { - error: error.message, - stack: error.stack, - authToken: !!window.authToken, - getAllLexiconWords: typeof window.getAllLexiconWords, - activeLexiconIds: Array.from(activeLexiconIds) - }); - return false; + console.error("⌠Erreur lors du démarrage du surlignage:", error); + window.highlightingActive = false; + highlightingActive = false; + throw error; } } - function stopHighlighting(lexiconId) { - log(`🛑 Arrêt du surlignage (lexiconId: ${lexiconId})`); - if (lexiconId) { - activeLexiconIds.delete(lexiconId); - log("📊 Lexiques actifs restants:", Array.from(activeLexiconIds)); - - if (activeLexiconIds.size === 0) { - log("🔄 Plus aucun lexique actif, désactivation complète"); + async function stopHighlighting(lexiconId) { + try { + if (lexiconId) { + activeLexiconIds.delete(lexiconId); + const activeLexicons = Array.from(activeLexiconIds); + await browser.storage.local.set({ activeLexicons }); + + if (activeLexiconIds.size === 0) { + window.highlightingActive = false; + highlightingActive = false; + removeAllHighlights(); + detachMutationObserver(); + } else { + removeAllHighlights(); + await updateLexiconCache(); + highlightVisibleContent(); + } + } else { + window.highlightingActive = false; highlightingActive = false; + activeLexiconIds.clear(); removeAllHighlights(); detachMutationObserver(); - } else { - log("🔄 Rafraîchissement du surlignage pour les lexiques restants"); - removeAllHighlights(); - highlightVisibleContent(); } - } else { - log("🧹 Désactivation globale du surlignage"); - highlightingActive = false; - activeLexiconIds.clear(); - removeAllHighlights(); - detachMutationObserver(); + return true; + } catch (error) { + console.error("⌠Erreur lors de l'arrêt du surlignage:", error); + throw error; } } @@ -427,7 +417,8 @@ window.addEventListener('load', async () => { highlights.forEach(highlight => { const text = highlight.textContent; - highlight.replaceWith(text); + const textNode = document.createTextNode(text); + highlight.parentNode.replaceChild(textNode, highlight); }); } @@ -502,6 +493,27 @@ window.addEventListener('load', async () => { authToken: !!window.authToken, getAllLexiconWords: typeof window.getAllLexiconWords }); + + // Puis déclarer checkAndRestoreHighlightingState + async function checkAndRestoreHighlightingState() { + try { + const { activeLexicons } = await browser.storage.local.get("activeLexicons"); + // Ne rien faire si pas de lexiques actifs + if (!activeLexicons || !Array.isArray(activeLexicons) || activeLexicons.length === 0) { + window.highlightingActive = false; + highlightingActive = false; + return; + } + log("🔄 État des lexiques trouvé:", activeLexicons); + } catch (error) { + console.error("⌠Erreur lors de la restauration de l'état:", error); + window.highlightingActive = false; + highlightingActive = false; + } + } + + // Ne pas démarrer automatiquement le surlignage + checkAndRestoreHighlightingState(); } catch (error) { console.error("🔴 Erreur critique dans l'IIFE:", error); } -- GitLab From af1b36535cba6d1a2cf4db0a45eda77d838f3744 Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:10:42 +0100 Subject: [PATCH 5/9] Surlignage actif sur ttes les pages --- src/background/background.js | 4 +-- src/utils/highlighting.js | 54 ++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/background/background.js b/src/background/background.js index ea71766..ddfb4d0 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -45,7 +45,7 @@ browser.storage.onChanged.addListener((changes, area) => { if (!extensionActive) { log("Token ajouté, activation automatique de l'extension."); browser.storage.local.set({ extensionActive: true }); - enableExtensionFeatures(); + updateExtension(); browser.runtime.sendMessage({ action: "updateUI", extensionActive: true, @@ -155,7 +155,7 @@ async function saveToken(token) { const { extensionActive } = await browser.storage.local.get("extensionActive"); if (!extensionActive) { await browser.storage.local.set({ extensionActive: true }); - enableExtensionFeatures(); + updateExtension(); browser.runtime.sendMessage({ action: "updateUI", extensionActive: true, diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index 27402c8..e65a253 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -1,3 +1,6 @@ +window.activeLexiconIds = window.activeLexiconIds || new Set(); + + // Logs immédiats pour vérifier l'injection console.log("🔵 DÉBUT DU FICHIER highlighting.js"); try { @@ -55,28 +58,6 @@ browser.runtime.onMessage.addListener((message) => { } }); -// Au début du fichier, après la déclaration de observer -document.addEventListener('visibilitychange', async () => { - if (document.visibilityState === 'visible' && window.highlightingActive && activeLexiconIds.size > 0) { - log("📄 Page redevenue visible, réinitialisation du surlignage"); - removeAllHighlights(); - await updateLexiconCache(); - highlightVisibleContent(); - attachMutationObserver(); - } -}); - -// Ajoutons aussi un listener pour le chargement complet de la page -window.addEventListener('pageshow', async () => { - if (window.highlightingActive && activeLexiconIds.size > 0) { - log("📄 Page affichée (pageshow), réinitialisation du surlignage"); - removeAllHighlights(); - await updateLexiconCache(); - highlightVisibleContent(); - attachMutationObserver(); - } -}); - // Déplacer checkAndRestoreHighlightingState après la déclaration de startHighlighting (function () { try { @@ -90,9 +71,27 @@ window.addEventListener('pageshow', async () => { let lexiconWordsCache = new Map(); let highlightingActive = false; window.highlightingActive = false; - let activeLexiconIds = new Set(); let observer = null; + document.addEventListener('visibilitychange', async () => { + if (document.visibilityState === 'visible' && window.highlightingActive && activeLexiconIds.size > 0) { + log("📄 Page redevenue visible, réinitialisation du surlignage"); + removeAllHighlights(); + await updateLexiconCache(); + highlightVisibleContent(); + attachMutationObserver(); + } + }); + window.addEventListener('pageshow', async () => { + if (window.highlightingActive && activeLexiconIds.size > 0) { + log("📄 Page affichée (pageshow), réinitialisation du surlignage"); + removeAllHighlights(); + await updateLexiconCache(); + highlightVisibleContent(); + attachMutationObserver(); + } + }); + // ───────────────────────────────────────────────────────────────────────────── // Gestion des messages du background // ───────────────────────────────────────────────────────────────────────────── @@ -213,6 +212,7 @@ window.addEventListener('pageshow', async () => { getAllLexiconWords: !!window.getAllLexiconWords, activeLexiconIds: Array.from(activeLexiconIds) }); + let allWords; try { if (!window.authToken) { throw new Error("Pas de token d'authentification"); @@ -227,7 +227,7 @@ window.addEventListener('pageshow', async () => { } log("📥 Appel de getAllLexiconWords..."); - const allWords = await window.getAllLexiconWords(window.authToken); + allWords = await window.getAllLexiconWords(window.authToken); log("📠Réponse de getAllLexiconWords:", allWords); if (!allWords || typeof allWords !== 'object') { @@ -505,6 +505,11 @@ window.addEventListener('pageshow', async () => { return; } log("🔄 État des lexiques trouvé:", activeLexicons); + + // Restauration de l'état de surlignage + for (const lexiconId of activeLexicons) { + await startHighlighting(lexiconId); + } } catch (error) { console.error("⌠Erreur lors de la restauration de l'état:", error); window.highlightingActive = false; @@ -514,6 +519,7 @@ window.addEventListener('pageshow', async () => { // Ne pas démarrer automatiquement le surlignage checkAndRestoreHighlightingState(); + } catch (error) { console.error("🔴 Erreur critique dans l'IIFE:", error); } -- GitLab From 8944fe28e55ce830ca8158ada1a4254f8e8e300c Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:38:08 +0100 Subject: [PATCH 6/9] Couleurs surlignage selon couleurs lexiques --- src/assets/lexicon_icon.js | 15 +++++++++++- src/background/background.js | 6 ++++- src/sidebar/sidebar.html | 5 ++-- src/sidebar/sidebar.js | 46 +++++++++++++++++++----------------- src/utils/highlighting.js | 25 +++++++++++++++++--- 5 files changed, 67 insertions(+), 30 deletions(-) diff --git a/src/assets/lexicon_icon.js b/src/assets/lexicon_icon.js index 69833f8..ab5eb63 100644 --- a/src/assets/lexicon_icon.js +++ b/src/assets/lexicon_icon.js @@ -147,6 +147,19 @@ async function getColorForLexicon(lexiconId) { const { lexiconColors } = await browser.storage.local.get("lexiconColors"); return (lexiconColors && lexiconColors[String(lexiconId)]) || "#cccccc"; } +/** + * Convertit une couleur hexadécimale en une couleur RGBA. + * @param {string} hex - La couleur en hexadécimal. + * @param {number} opacity - La transparence (0-1). + * @returns {string} La couleur RGBA. + */ +function hexToRgba(hex, opacity) { + const bigint = parseInt(hex.replace('#', ''), 16); + const r = (bigint >> 16) & 255; + const g = (bigint >> 8) & 255; + const b = bigint & 255; + return `rgba(${r}, ${g}, ${b}, ${opacity})`; +} window.updateLexiconColors = updateLexiconColors; window.getColorForLexicon = getColorForLexicon; @@ -155,4 +168,4 @@ window.convertColor = convertColor; window.getOrCreateLexiconColor = getOrCreateLexiconColor; window.createColorCircle = createColorCircle; window.getLexiconsColors = getLexiconsColors; - +window.hexToRgba = hexToRgba; diff --git a/src/background/background.js b/src/background/background.js index ddfb4d0..dd5ac3d 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -68,7 +68,11 @@ async function isUserConnected() { async function refreshAllUI() { log("🔄 Rafraîchissement global de l'UI..."); - browser.runtime.sendMessage({ action: "refreshUI" }); + try { + await browser.runtime.sendMessage({ action: "refreshUI" }); + } catch (error) { + console.warn("Aucun récepteur pour 'refreshUI' :", error); + } } // ───────────────────────────────────────────────────────────────────────────── diff --git a/src/sidebar/sidebar.html b/src/sidebar/sidebar.html index 96de998..6c77670 100644 --- a/src/sidebar/sidebar.html +++ b/src/sidebar/sidebar.html @@ -296,13 +296,12 @@ } .lexicon-highlight { - background-color: rgba(255, 255, 0, 0.3); + background-color: var(--highlight-color, rgba(255, 255, 0, 0.3)); border-bottom: 1px dashed #666; transition: background-color 0.3s; } - .lexicon-highlight:hover { - background-color: rgba(255, 255, 0, 0.5); + background-color: var(--highlight-color-hover, rgba(255, 255, 0, 0.5)); } .lexicon-section { diff --git a/src/sidebar/sidebar.js b/src/sidebar/sidebar.js index c51f264..a6d9a6a 100644 --- a/src/sidebar/sidebar.js +++ b/src/sidebar/sidebar.js @@ -503,28 +503,11 @@ async function handleAddWordClick() { browser.runtime.onMessage.addListener(async (message) => { log("📩 Message reçu dans sidebar.js :", message); - if (message.action === "refreshUI") { - log("🔄 Demande de rafraîchissement de la barre latérale."); - await refreshSidebarState(); - return; - } - - if (message.command) { - switch (message.command) { - case "activate-highlighting": - const highlightButton = document.querySelector(`button[data-lexicon-id="${message.lexiconId}"]`); - if (highlightButton) { - highlightButton.dataset.active = "true"; - highlightButton.classList.add("active"); - } - break; - - case "deactivate-highlighting": - const highlightButtonOff = document.querySelector(`button[data-lexicon-id="${message.lexiconId}"]`); - if (highlightButtonOff) { - highlightButtonOff.dataset.active = "false"; - highlightButtonOff.classList.remove("active"); - } + if (message.action) + switch (message.action) { + case "refreshUI": + log("🔄 Demande de rafraîchissement de la barre latérale."); + await refreshSidebarState(); break; case "mot_selectionne": @@ -607,6 +590,25 @@ browser.runtime.onMessage.addListener(async (message) => { closeBlock("etatContent"); closeBlock("definitionContent") break; + } + + if (message.command) { + switch (message.command) { + case "activate-highlighting": + const highlightButton = document.querySelector(`button[data-lexicon-id="${message.lexiconId}"]`); + if (highlightButton) { + highlightButton.dataset.active = "true"; + highlightButton.classList.add("active"); + } + break; + + case "deactivate-highlighting": + const highlightButtonOff = document.querySelector(`button[data-lexicon-id="${message.lexiconId}"]`); + if (highlightButtonOff) { + highlightButtonOff.dataset.active = "false"; + highlightButtonOff.classList.remove("active"); + } + break; case "register-stats-script": break; diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index e65a253..ac318cd 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -388,10 +388,29 @@ browser.runtime.onMessage.addListener((message) => { const span = document.createElement("span"); span.textContent = match[0]; span.className = "lexicon-highlight"; - span.style.backgroundColor = "rgba(255, 255, 0, 0.3)"; - span.style.borderBottom = "1px dashed #666"; - fragments.push(span); + let currentLexiconId = null; + for (const [id, words] of lexiconWordsCache.entries()) { + if (activeLexiconIds.has(Number(id)) && words.has(match[0])) { + currentLexiconId = id; + break; + } + } + + if (currentLexiconId) { + getColorForLexicon(currentLexiconId).then(hexColor => { + const rgbaColor = hexToRgba(hexColor, 0.3); + const rgbaHoverColor = hexToRgba(hexColor, 0.5); + span.style.setProperty('--highlight-color', rgbaColor); + span.style.setProperty('--highlight-color-hover', rgbaHoverColor); + span.style.backgroundColor = rgbaColor; + }); + } else { + // Optionnel : couleur par défaut + span.style.backgroundColor = "rgba(255, 255, 0, 0.3)"; + } + + fragments.push(span); lastIndex = regex.lastIndex; } -- GitLab From 2e2e8fd7f5d79b0c94669d7832eb4da764847881 Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:26:36 +0100 Subject: [PATCH 7/9] Surlignage multicolore si plusieurs lexiques --- src/sidebar/sidebar.html | 24 +++- src/utils/highlighting.js | 255 ++++++++++++++++++-------------------- 2 files changed, 138 insertions(+), 141 deletions(-) diff --git a/src/sidebar/sidebar.html b/src/sidebar/sidebar.html index 6c77670..7345d94 100644 --- a/src/sidebar/sidebar.html +++ b/src/sidebar/sidebar.html @@ -296,14 +296,30 @@ } .lexicon-highlight { - background-color: var(--highlight-color, rgba(255, 255, 0, 0.3)); - border-bottom: 1px dashed #666; + position: relative; /* Pour positionner le conteneur de bandes en absolu */ + display: inline-block; /* Pour que le span prenne en compte les dimensions */ + padding-bottom: 4px; /* Laisser de l'espace pour les bandes */ + border-bottom: 1px dashed #666; /* Vous pouvez conserver votre bordure si besoin */ transition: background-color 0.3s; + background-color: rgba(255, 255, 0, 0.15); + + } + + .color-bands { + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 3px; /* Ajustez la hauteur des bandes */ + display: flex; /* Pour répartir équitablement les bandes */ } - .lexicon-highlight:hover { - background-color: var(--highlight-color-hover, rgba(255, 255, 0, 0.5)); + + .color-bands div { + flex: 1; /* Chaque bande occupe une part égale */ + height: 100%; } + .lexicon-section { margin-bottom: 10px; } diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index ac318cd..3a98298 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -1,7 +1,7 @@ +// Variables globales window.activeLexiconIds = window.activeLexiconIds || new Set(); - -// Logs immédiats pour vérifier l'injection +// Logs immédiats console.log("🔵 DÉBUT DU FICHIER highlighting.js"); try { log("✅ highlighting.js chargé"); @@ -9,25 +9,19 @@ try { console.error("⌠Erreur avec la fonction log:", e); } -// Vérification de l'existence de l'objet browser +// Vérification de l'environnement console.log("🔠Vérification de l'environnement:", { hasBrowser: typeof browser !== 'undefined', windowLocation: window.location.href }); -// Ajout d'un log global pour capturer les erreurs non gérées +// Gestion globale des erreurs window.onerror = function(msg, url, line, col, error) { - console.error("🔴 Erreur globale:", { - message: msg, - url: url, - line: line, - col: col, - error: error - }); + console.error("🔴 Erreur globale:", { message: msg, url: url, line: line, col: col, error: error }); return false; }; -// Au début du fichier, récupérons le token du storage local +// Fonction d'initialisation du token depuis le stockage local async function initAuthToken() { try { const { accessToken } = await browser.storage.local.get("accessToken"); @@ -45,11 +39,9 @@ async function initAuthToken() { return false; } } - -// Appel immédiat de l'initialisation initAuthToken(); -// Gardons aussi l'écoute des mises à jour du token +// Écoute de mise à jour du token browser.runtime.onMessage.addListener((message) => { if (message.command === "updateAuthToken" && message.token) { window.authToken = message.token; @@ -58,7 +50,6 @@ browser.runtime.onMessage.addListener((message) => { } }); -// Déplacer checkAndRestoreHighlightingState après la déclaration de startHighlighting (function () { try { if (window.hasRun) { @@ -67,12 +58,13 @@ browser.runtime.onMessage.addListener((message) => { } window.hasRun = true; - // Variables globales pour le script + // Variables internes let lexiconWordsCache = new Map(); let highlightingActive = false; window.highlightingActive = false; let observer = null; - + + // Gestion de la visibilité/page show pour réappliquer le surlignage document.addEventListener('visibilitychange', async () => { if (document.visibilityState === 'visible' && window.highlightingActive && activeLexiconIds.size > 0) { log("📄 Page redevenue visible, réinitialisation du surlignage"); @@ -91,11 +83,8 @@ browser.runtime.onMessage.addListener((message) => { attachMutationObserver(); } }); - - // ───────────────────────────────────────────────────────────────────────────── - // Gestion des messages du background - // ───────────────────────────────────────────────────────────────────────────── - log("📡 Enregistrement du listener de messages"); + + // Gestion des messages reçus du background browser.runtime.onMessage.addListener((message, sender, sendResponse) => { console.log("📨 Message reçu:", message, "Context:", { highlightingActive, @@ -136,34 +125,88 @@ browser.runtime.onMessage.addListener((message) => { return false; }); - + log("📡 Enregistrement du script auprès du background"); browser.runtime.sendMessage({ command: "register-highlighting-script" }); - + log("🚀 Initialisation de highlighting.js"); - - // ───────────────────────────────────────────────────────────────────────────── - // Fonctions principales - // ───────────────────────────────────────────────────────────────────────────── + + // Fonction asynchrone pour mettre à jour le style d'un élément surligné en fonction des lexiques qui le concernent + async function updateHighlightStyle(span, lexIds) { + if (!lexIds || lexIds.length === 0) { + span.style.backgroundColor = "rgba(255, 255, 0, 0.25)"; + span.style.backgroundImage = ""; + return; + } + if (lexIds.length === 1) { + const hexColor = await getColorForLexicon(lexIds[0]); + const rgbaColor = hexToRgba(hexColor, 0.25); + span.style.backgroundColor = rgbaColor; + span.style.backgroundImage = ""; + } else { + const hexColors = await Promise.all(lexIds.map(id => getColorForLexicon(id))); + const colors = hexColors.map(hex => hexToRgba(hex, 0.25)); + const n = colors.length; + let stops = []; + for (let i = 0; i < n; i++) { + const start = ((100 * i) / n).toFixed(2) + '%'; + const end = ((100 * (i + 1)) / n).toFixed(2) + '%'; + stops.push(`${colors[i]} ${start}, ${colors[i]} ${end}`); + } + const gradient = `linear-gradient(90deg, ${stops.join(', ')})`; + span.style.backgroundImage = gradient; + + } + } + + // Vérifier si un mot appartient à un lexique (à l'aide de la cache) + function wordIsInLexicon(lexiconId, word) { + const wordsSet = lexiconWordsCache.get(String(lexiconId)); + return wordsSet ? wordsSet.has(word.toLowerCase()) : false; + } + + // Mise à jour incrémentale des éléments déjà surlignés lorsqu'un nouveau lexique est ajouté + async function updateHighlightsForNewLexicon(newLexiconId) { + const spans = document.querySelectorAll('.lexicon-highlight'); + for (let span of spans) { + const word = span.textContent; + if (wordIsInLexicon(newLexiconId, word)) { + let lexIds = []; + try { + lexIds = JSON.parse(span.getAttribute('data-lexicons')); + } catch (e) { + lexIds = []; + } + if (!lexIds.includes(newLexiconId)) { + lexIds.push(newLexiconId); + span.setAttribute('data-lexicons', JSON.stringify(lexIds)); + await updateHighlightStyle(span, lexIds); + } + } + } + } + + // Fonction startHighlighting modifiée pour intégrer la mise à jour incrémentale async function startHighlighting(lexiconId) { try { await initAuthToken(); - if (!window.authToken) { throw new Error("⌠Pas de token d'authentification disponible"); } - if (lexiconId) { - activeLexiconIds.add(lexiconId); - const activeLexicons = Array.from(activeLexiconIds); - await browser.storage.local.set({ activeLexicons }); - log("📊 Lexiques actifs sauvegardés:", activeLexicons); + if (!activeLexiconIds.has(lexiconId)) { + activeLexiconIds.add(lexiconId); + const activeLexicons = Array.from(activeLexiconIds); + await browser.storage.local.set({ activeLexicons }); + log("📊 Lexiques actifs sauvegardés:", activeLexicons); + // Mise à jour de la cache pour inclure le nouveau lexique + await updateLexiconCache(); + // Mise à jour immédiate des éléments surlignés pour intégrer le nouveau lexique + await updateHighlightsForNewLexicon(lexiconId); + } } - window.highlightingActive = true; highlightingActive = true; - - await updateLexiconCache(); highlightVisibleContent(); attachMutationObserver(); return true; @@ -174,14 +217,13 @@ browser.runtime.onMessage.addListener((message) => { throw error; } } - + async function stopHighlighting(lexiconId) { try { if (lexiconId) { activeLexiconIds.delete(lexiconId); const activeLexicons = Array.from(activeLexiconIds); await browser.storage.local.set({ activeLexicons }); - if (activeLexiconIds.size === 0) { window.highlightingActive = false; highlightingActive = false; @@ -205,7 +247,8 @@ browser.runtime.onMessage.addListener((message) => { throw error; } } - + + // Mise à jour du cache des lexiques async function updateLexiconCache() { console.log("📥 updateLexiconCache - Début avec context:", { authToken: !!window.authToken, @@ -217,52 +260,40 @@ browser.runtime.onMessage.addListener((message) => { if (!window.authToken) { throw new Error("Pas de token d'authentification"); } - - // Vérification explicite de getAllLexiconWords if (typeof window.getAllLexiconWords !== 'function') { log("âš ï¸ getAllLexiconWords n'est pas une fonction"); log("Type de getAllLexiconWords:", typeof window.getAllLexiconWords); log("Contenu de window.getAllLexiconWords:", window.getAllLexiconWords); throw new Error("getAllLexiconWords n'est pas disponible"); } - log("📥 Appel de getAllLexiconWords..."); allWords = await window.getAllLexiconWords(window.authToken); log("📠Réponse de getAllLexiconWords:", allWords); - if (!allWords || typeof allWords !== 'object') { throw new Error(`Format de données invalide: ${JSON.stringify(allWords)}`); } - lexiconWordsCache.clear(); - - // Vérification de la structure des données if (Object.keys(allWords).length === 0) { log("âš ï¸ Aucun lexique reçu de getAllLexiconWords"); return false; } - for (const [lexiconName, words] of Object.entries(allWords)) { if (!Array.isArray(words)) { console.warn(`âš ï¸ Format invalide pour le lexique ${lexiconName}:`, words); continue; } - const lexiconId = lexiconName.match(/\[(\d+)\]$/)?.[1]; if (!lexiconId) { console.warn(`âš ï¸ Impossible d'extraire l'ID du lexique depuis: ${lexiconName}`); continue; } - log(`📎 Traitement du lexique ${lexiconName} (ID: ${lexiconId})`); - if (activeLexiconIds.has(Number(lexiconId))) { lexiconWordsCache.set(lexiconId, new Set(words)); log(`📖 Lexique ${lexiconId} chargé avec ${words.length} mots`); } } - - log("✅ Cache des lexiques mis à jour:", + log("✅ Cache des lexiques mis à jour:", Object.fromEntries([...lexiconWordsCache.entries()].map(([id, words]) => [id, [...words]]))); return true; } catch (error) { @@ -276,194 +307,155 @@ browser.runtime.onMessage.addListener((message) => { throw error; } } - - // ───────────────────────────────────────────────────────────────────────────── - // Fonctions de surlignage - // ───────────────────────────────────────────────────────────────────────────── + + // Surlignage du contenu visible function highlightVisibleContent() { if (!highlightingActive) { log("â¸ï¸ Surlignage inactif, sortie"); return; } log("🔠Début du surlignage du contenu visible"); - - // Ajout d'une limite de traitement par lot const BATCH_SIZE = 100; - const BATCH_DELAY = 10; // ms entre chaque lot - + const BATCH_DELAY = 10; // ms const textNodes = []; const walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, { acceptNode: (node) => { - // Optimisation des filtres const parent = node.parentElement; - if (!parent || - parent.closest('script, style, .lexicon-highlight') || - !node.textContent.trim() || - getComputedStyle(parent).display === 'none') { + if (!parent || parent.closest('script, style, .lexicon-highlight') || !node.textContent.trim() || getComputedStyle(parent).display === 'none') { return NodeFilter.FILTER_REJECT; } return NodeFilter.FILTER_ACCEPT; } } ); - let node; while (node = walker.nextNode()) { textNodes.push(node); } - log(`🔤 ${textNodes.length} nÅ“uds de texte trouvés à traiter`); - - // Traitement par lots const processNextBatch = (startIndex) => { if (!highlightingActive || startIndex >= textNodes.length) { return; } - const endIndex = Math.min(startIndex + BATCH_SIZE, textNodes.length); const batch = textNodes.slice(startIndex, endIndex); - batch.forEach(processTextNode); - if (endIndex < textNodes.length) { setTimeout(() => processNextBatch(endIndex), BATCH_DELAY); } }; - processNextBatch(0); } - + + // Traitement d'un nÅ“ud de texte function processTextNode(textNode) { if (activeLexiconIds.size === 0) { log("âš ï¸ Aucun lexique actif, sortie du processTextNode"); return; } - const text = textNode.textContent; log(`🔠Traitement du texte: "${text.substring(0, 50)}..."`); - let lastIndex = 0; let fragments = []; - const allWords = new Set(); + const matchedLexiconIdsMap = new Map(); for (const [lexiconId, words] of lexiconWordsCache.entries()) { - // Convertir directement en nombre car lexiconId est déjà l'ID numérique const numericId = parseInt(lexiconId); log(`🔄 Vérification du lexique ${lexiconId} (ID: ${numericId})`); if (activeLexiconIds.has(numericId)) { log(`✅ Lexique ${lexiconId} actif, ajout de ${words.size} mots`); words.forEach(word => allWords.add(word)); + words.forEach(word => { + const lowerCaseWord = word.toLowerCase(); + if (!matchedLexiconIdsMap.has(lowerCaseWord)) { // Correction ici ! + matchedLexiconIdsMap.set(lowerCaseWord, []); + } + matchedLexiconIdsMap.get(lowerCaseWord).push(lexiconId); + }); } } - log(`🔤 Nombre total de mots à rechercher: ${allWords.size}`); if (allWords.size === 0) { log("âš ï¸ Aucun mot à rechercher dans les lexiques actifs"); return; } - const wordsPattern = Array.from(allWords) .sort((a, b) => b.length - a.length) .map(escapeRegExp) .join("|"); - if (!wordsPattern) { log("âš ï¸ Aucun mot à rechercher, sortie"); return; } - const regex = new RegExp(`\\b(${wordsPattern})\\b`, "gi"); let match; let matchCount = 0; - while ((match = regex.exec(text)) !== null) { matchCount++; if (match.index > lastIndex) { fragments.push(document.createTextNode(text.slice(lastIndex, match.index))); } - const span = document.createElement("span"); span.textContent = match[0]; span.className = "lexicon-highlight"; - - let currentLexiconId = null; - for (const [id, words] of lexiconWordsCache.entries()) { - if (activeLexiconIds.has(Number(id)) && words.has(match[0])) { - currentLexiconId = id; - break; - } - } - - if (currentLexiconId) { - getColorForLexicon(currentLexiconId).then(hexColor => { - const rgbaColor = hexToRgba(hexColor, 0.3); - const rgbaHoverColor = hexToRgba(hexColor, 0.5); - span.style.setProperty('--highlight-color', rgbaColor); - span.style.setProperty('--highlight-color-hover', rgbaHoverColor); - span.style.backgroundColor = rgbaColor; - }); + span.style.display = "inline-block"; + + const matchedLexiconIds = matchedLexiconIdsMap.get(match[0].toLowerCase()) || []; + span.setAttribute('data-lexicons', JSON.stringify(matchedLexiconIds)); + + if (matchedLexiconIds.length === 0) { + span.style.backgroundColor = "rgba(255, 255, 0, 0.25)"; } else { - // Optionnel : couleur par défaut - span.style.backgroundColor = "rgba(255, 255, 0, 0.3)"; + updateHighlightStyle(span, matchedLexiconIds); } - fragments.push(span); lastIndex = regex.lastIndex; } - if (matchCount > 0) { log(`✨ ${matchCount} correspondances trouvées dans le nÅ“ud`); } - if (lastIndex < text.length) { fragments.push(document.createTextNode(text.slice(lastIndex))); } - if (fragments.length > 0) { const parent = textNode.parentNode; fragments.forEach(fragment => parent.insertBefore(fragment, textNode)); parent.removeChild(textNode); } } - + + // Suppression de tous les surlignages function removeAllHighlights() { log("🧹 Suppression de tous les surlignages"); const highlights = document.querySelectorAll('.lexicon-highlight'); log(`📊 ${highlights.length} surlignages à supprimer`); - highlights.forEach(highlight => { const text = highlight.textContent; const textNode = document.createTextNode(text); highlight.parentNode.replaceChild(textNode, highlight); }); } - - // ───────────────────────────────────────────────────────────────────────────── + // Gestion des mutations DOM - // ───────────────────────────────────────────────────────────────────────────── function attachMutationObserver() { log("👀 Attachement de l'observateur de mutations"); - let debounceTimer = null; const DEBOUNCE_DELAY = 250; // ms - observer = new MutationObserver((mutations) => { if (debounceTimer) { clearTimeout(debounceTimer); } - debounceTimer = setTimeout(() => { log(`🔄 Traitement groupé de ${mutations.length} mutations DOM`); let shouldHighlight = false; - for (const mutation of mutations) { if (mutation.type === 'childList') { for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE && - !node.closest('.lexicon-highlight') && + !node.closest('.lexicon-highlight') && node.textContent.trim()) { shouldHighlight = true; break; @@ -472,19 +464,17 @@ browser.runtime.onMessage.addListener((message) => { } if (shouldHighlight) break; } - if (shouldHighlight) { highlightVisibleContent(); } }, DEBOUNCE_DELAY); }); - observer.observe(document.body, { childList: true, subtree: true }); } - + function detachMutationObserver() { if (observer) { log("👋 Détachement de l'observateur de mutations"); @@ -492,40 +482,32 @@ browser.runtime.onMessage.addListener((message) => { observer = null; } } - - // ───────────────────────────────────────────────────────────────────────────── - // Utilitaires - // ───────────────────────────────────────────────────────────────────────────── + function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } - + function getLexiconIdFromName(lexiconName) { const match = lexiconName.match(/\[(\d+)\]$/); const id = match ? parseInt(match[1]) : null; log(`ðŸ·ï¸ Extraction de l'ID depuis '${lexiconName}': ${id}`); return id; } - - // Ajout d'une vérification au démarrage + log("🔠Vérification des dépendances au chargement:", { authToken: !!window.authToken, getAllLexiconWords: typeof window.getAllLexiconWords }); - - // Puis déclarer checkAndRestoreHighlightingState + async function checkAndRestoreHighlightingState() { try { const { activeLexicons } = await browser.storage.local.get("activeLexicons"); - // Ne rien faire si pas de lexiques actifs if (!activeLexicons || !Array.isArray(activeLexicons) || activeLexicons.length === 0) { window.highlightingActive = false; highlightingActive = false; return; } log("🔄 État des lexiques trouvé:", activeLexicons); - - // Restauration de l'état de surlignage for (const lexiconId of activeLexicons) { await startHighlighting(lexiconId); } @@ -535,10 +517,9 @@ browser.runtime.onMessage.addListener((message) => { highlightingActive = false; } } - - // Ne pas démarrer automatiquement le surlignage + checkAndRestoreHighlightingState(); - + } catch (error) { console.error("🔴 Erreur critique dans l'IIFE:", error); } -- GitLab From 5ba80ed9a013dc2b61c37328fa1cbb79ce42f5aa Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:34:00 +0100 Subject: [PATCH 8/9] Taille texte popup instruction connexion --- src/background/background.js | 12 ++++++------ src/utils/highlighting.js | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/background/background.js b/src/background/background.js index dd5ac3d..9b1c26e 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -322,25 +322,25 @@ function showInstructionPopup(details) { popup.style.transform = "translate(-50%, -50%)"; popup.style.backgroundColor = "#a08e9f"; popup.style.color = "#323046"; - popup.style.padding = "20px"; + popup.style.padding = "12px"; popup.style.borderRadius = "10px"; popup.style.boxShadow = "0 2px 10px rgba(0, 0, 0, 0.3)"; popup.style.zIndex = "10000"; popup.style.fontFamily = "Luciole"; - popup.style.fontSize = "14px"; + popup.style.fontSize = "16px"; popup.style.width = "300px"; popup.style.textAlign = "center"; popup.innerHTML = \` - <h5 style="color: #fff; font-weight: bold; margin-top: 0;">🔑 Connexion à l'extension</h5> - <p style="margin: 15px 0;"> - Après avoir renseigné vos identifiants, cliquez sur + <h5 style="color: #fff; font-weight: bold; margin-top: 2px;">Connexion à l'extension</h5> + <p style="margin: 8px 0;"> + Après avoir renseigné vos identifiants, veuillez cliquer sur <strong>"Se connecter avec BaLex"</strong>. </p> <button id="close-popup-btn" style=" width: 100%; margin-top: 15px; - padding: 10px; + padding: 8px; border: none; background-color: #8d5c70; color: #fbfcfc; diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index 3a98298..bc9386d 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -134,18 +134,18 @@ browser.runtime.onMessage.addListener((message) => { // Fonction asynchrone pour mettre à jour le style d'un élément surligné en fonction des lexiques qui le concernent async function updateHighlightStyle(span, lexIds) { if (!lexIds || lexIds.length === 0) { - span.style.backgroundColor = "rgba(255, 255, 0, 0.25)"; + span.style.backgroundColor = "rgba(255, 255, 0, 0.3)"; span.style.backgroundImage = ""; return; } if (lexIds.length === 1) { const hexColor = await getColorForLexicon(lexIds[0]); - const rgbaColor = hexToRgba(hexColor, 0.25); + const rgbaColor = hexToRgba(hexColor, 0.3); span.style.backgroundColor = rgbaColor; span.style.backgroundImage = ""; } else { const hexColors = await Promise.all(lexIds.map(id => getColorForLexicon(id))); - const colors = hexColors.map(hex => hexToRgba(hex, 0.25)); + const colors = hexColors.map(hex => hexToRgba(hex, 0.3)); const n = colors.length; let stops = []; for (let i = 0; i < n; i++) { @@ -407,7 +407,7 @@ browser.runtime.onMessage.addListener((message) => { span.setAttribute('data-lexicons', JSON.stringify(matchedLexiconIds)); if (matchedLexiconIds.length === 0) { - span.style.backgroundColor = "rgba(255, 255, 0, 0.25)"; + span.style.backgroundColor = "rgba(255, 255, 0, 0.3)"; } else { updateHighlightStyle(span, matchedLexiconIds); } -- GitLab From 4c4cecfcb540c275fb333ec5eac6873c20b83588 Mon Sep 17 00:00:00 2001 From: Lucie Bader <167515375+Lucie-Bdr@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:46:19 +0100 Subject: [PATCH 9/9] Correction mode debug/prod --- src/assets/lexicon_icon.js | 6 +-- src/background/background.js | 58 ++++++++++++------------ src/context_menu/browser_context_menu.js | 10 ++-- src/context_menu/custom_context_menu.js | 8 ++-- src/popup/popup.js | 4 +- src/sidebar/sidebar.js | 16 +++---- src/utils/api.js | 8 ++-- src/utils/definitions.js | 16 +++---- src/utils/highlighting.js | 30 ++++++------ src/utils/logger.js | 4 +- src/workers/pyodide_worker.js | 6 +-- 11 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/assets/lexicon_icon.js b/src/assets/lexicon_icon.js index ab5eb63..1247bcf 100644 --- a/src/assets/lexicon_icon.js +++ b/src/assets/lexicon_icon.js @@ -19,7 +19,7 @@ async function getLexiconsColors(authToken) { log("✅ Couleurs des lexiques récupérées :", colors); return colors; } catch (error) { - console.error("⌠Erreur lors de la récupération des couleurs des lexiques :", error); + log("⌠Erreur lors de la récupération des couleurs des lexiques :", error); return {}; } } @@ -87,7 +87,7 @@ async function getOrCreateLexiconColor(lexiconId) { } } } catch (error) { - console.error("Erreur lors de la récupération des couleurs via l'API :", error); + log("Erreur lors de la récupération des couleurs via l'API :", error); } } // Si aucune couleur n'est associée, on la génère et on la sauvegarde @@ -133,7 +133,7 @@ async function updateLexiconColors(authToken) { await browser.storage.local.set({ lexiconColors: colorMapping }); return colorMapping; } catch (error) { - console.error("⌠Erreur lors de la mise à jour des couleurs :", error); + log("⌠Erreur lors de la mise à jour des couleurs :", error); return {}; } } diff --git a/src/background/background.js b/src/background/background.js index 9b1c26e..1f76e0c 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -238,7 +238,7 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { }); log(`✅ Message de surlignage transmis à l'onglet ${tabs[0].id}`); } catch (error) { - console.error("⌠Erreur lors de la gestion du surlignage:", error); + log("⌠Erreur lors de la gestion du surlignage:", error); } } break; @@ -281,14 +281,14 @@ browser.webNavigation.onCompleted.addListener(async (details) => { log("🔠Token détecté :", token); browser.runtime.sendMessage({ action: "saveToken", token }); } else { - console.error("⌠Token introuvable."); + log("⌠Token introuvable."); } return null; })(); ` }); } catch (error) { - console.error("⌠Erreur lors de la récupération du token :", error); + log("⌠Erreur lors de la récupération du token :", error); } } }, { url: [{ hostContains: "prisms.lezinter.net" }] }); @@ -366,48 +366,48 @@ let worker = null; function initWorker() { if (!worker) { - console.log("[Background] Initialisation du WebWorker..."); + log("[Background] Initialisation du WebWorker..."); try { worker = new Worker(browser.runtime.getURL("src/workers/pyodide_worker.js")); // Centralisation de l'écoute des messages et erreurs du Worker worker.addEventListener("message", handleWorkerMessage); worker.addEventListener("error", handleWorkerError); - console.log("[Background] WebWorker initialisé avec succès."); + log("[Background] WebWorker initialisé avec succès."); } catch (error) { - console.error("[Background] Échec de l'initialisation du WebWorker :", error); + log("[Background] Échec de l'initialisation du WebWorker :", error); } } } function handleWorkerError(error) { - console.error("Erreur du WebWorker :", error.message); + log("Erreur du WebWorker :", error.message); } function handleWorkerMessage(event) { const data = event.data; - console.log("[Background] Message du WebWorker :", data); + log("[Background] Message du WebWorker :", data); switch (data.type) { case "pyodide-simplemma": if (data.status === "success") { - console.log("[Background] Pyodide et Simplemma prêts. Mise à jour de l'état."); + log("[Background] Pyodide et Simplemma prêts. Mise à jour de l'état."); browser.storage.local.set({ pyodideSimplemmaReady: true }); checkAndUpdateTracking(); } else if (data.status === "error") { - console.error("[Background] Erreur lors du chargement :", data.message); + log("[Background] Erreur lors du chargement :", data.message); } else if (data.status === "already_loaded") { - console.log("[Background] Pyodide et Simplemma déjà chargés."); + log("[Background] Pyodide et Simplemma déjà chargés."); } break; case "update-frequencies": - console.log("[Background] Mise à jour des fréquences :", data.frequencies); + log("[Background] Mise à jour des fréquences :", data.frequencies); notifyAllTabs({ command: "update-frequencies", frequencies: data.frequencies }); // Si un port stats est connecté, vous pouvez lui transmettre également : // port.postMessage({ command: "update-frequencies", frequencies: data.frequencies }); browser.storage.local.set({ lemmaFrequencies: data.frequencies }); break; case "threshold-exceeded": - console.log("[Background] Mots dépassant le seuil :", data.wordsAboveThreshold); + log("[Background] Mots dépassant le seuil :", data.wordsAboveThreshold); notifyAllTabs({ command: "threshold-exceeded", wordsAboveThreshold: data.wordsAboveThreshold }); break; default: @@ -423,14 +423,14 @@ initWorker(); // Écoute des messages de la popup et transmission au WebWorker // ───────────────────────────────────────────────────────────────────────────── browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { - console.log("[Background] Message reçu :", message); + log("[Background] Message reçu :", message); if (!worker) { initWorker(); } if (message.command === "toggle-stats") { - console.log(`[Background] Statistiques ${message.isActive ? "activées" : "désactivées"}`); + log(`[Background] Statistiques ${message.isActive ? "activées" : "désactivées"}`); const { isActive } = message; await browser.storage.local.set({ isTrackingActive: isActive }); if (!isActive) { @@ -440,7 +440,7 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => { } if (message.command === "pyodide-simplemma") { - console.log("[Background] Demande d'initialisation de Pyodide et Simplemma..."); + log("[Background] Demande d'initialisation de Pyodide et Simplemma..."); worker.postMessage({ command: "pyodide-simplemma" }); } @@ -460,7 +460,7 @@ let storedFrequencies = {}; loadStoredFrequencies().then(frequencies => { storedFrequencies = frequencies; - console.log("[Background] Fréquences initialisées :", storedFrequencies); + log("[Background] Fréquences initialisées :", storedFrequencies); }); // ───────────────────────────────────────────────────────────────────────────── @@ -469,10 +469,10 @@ loadStoredFrequencies().then(frequencies => { async function checkAndUpdateTracking() { const { isTrackingActive, pyodideSimplemmaReady } = await browser.storage.local.get(["isTrackingActive", "pyodideSimplemmaReady"]); if (isTrackingActive && pyodideSimplemmaReady) { - console.log("[Background] Activation du tracking."); + log("[Background] Activation du tracking."); notifyAllTabs({ command: "activate-stats" }); } else { - console.log("[Background] Désactivation du tracking."); + log("[Background] Désactivation du tracking."); notifyAllTabs({ command: "deactivate-stats" }); } } @@ -497,7 +497,7 @@ browser.storage.onChanged.addListener(async (changes, area) => { checkAndUpdateTracking(); } if (area === "local" && (changes.accessToken || changes.threshold || changes.trackedLanguages || changes.autoAdd)) { - console.log("[Background] Mise à jour des préférences détectée."); + log("[Background] Mise à jour des préférences détectée."); const { accessToken, trackedLanguages, threshold, autoAdd } = await browser.storage.local.get([ "accessToken", "trackedLanguages", "threshold", "autoAdd" ]); @@ -517,7 +517,7 @@ browser.storage.onChanged.addListener(async (changes, area) => { // ───────────────────────────────────────────────────────────────────────────── browser.runtime.onMessage.addListener(async (message, sender) => { if (message.command === "register-stats-script") { - console.log("[Background] stats.js s'est enregistré."); + log("[Background] stats.js s'est enregistré."); const { isTrackingActive, pyodideSimplemmaReady } = await browser.storage.local.get(["isTrackingActive", "pyodideSimplemmaReady"]); if (isTrackingActive && pyodideSimplemmaReady) { browser.tabs.sendMessage(sender.tab.id, { command: "activate-stats" }) @@ -530,11 +530,11 @@ browser.runtime.onMessage.addListener(async (message, sender) => { // Connexion entre stats.js et le Worker via un port dédié // ───────────────────────────────────────────────────────────────────────────── browser.runtime.onConnect.addListener((port) => { - console.log("[Background] Connexion établie :", port.name); + log("[Background] Connexion établie :", port.name); if (port.name === "stats-worker-port") { // Redirige les messages de stats.js vers le Worker port.onMessage.addListener((message) => { - console.log("[Background] Message reçu de stats.js :", message); + log("[Background] Message reçu de stats.js :", message); worker.postMessage(message); }); @@ -561,14 +561,14 @@ function loadStoplist() { .then(response => response.text()) .then(text => { stoplistFr = text.split("\n").map(word => word.trim()); - console.log("[Background] Stoplist chargée :", stoplistFr); + log("[Background] Stoplist chargée :", stoplistFr); sendStoplistToWorker(); }) - .catch(error => console.error("[Background] Erreur lors du chargement de la stoplist :", error)); + .catch(error => log("[Background] Erreur lors du chargement de la stoplist :", error)); } function sendStoplistToWorker() { - console.log("[Background] Envoi de la stoplist au Worker..."); + log("[Background] Envoi de la stoplist au Worker..."); worker.postMessage({ command: "update-stoplist", stoplist: stoplistFr }); } @@ -576,7 +576,7 @@ browser.runtime.onStartup.addListener(loadStoplist); browser.runtime.onInstalled.addListener(loadStoplist); async function handleHighlighting(command, lexiconId, tabId) { - console.log(`🎯 Gestion du surlignage: ${command} pour le lexique ${lexiconId}`); + log(`🎯 Gestion du surlignage: ${command} pour le lexique ${lexiconId}`); try { // S'assurer que le script est injecté @@ -591,10 +591,10 @@ async function handleHighlighting(command, lexiconId, tabId) { lexiconId: lexiconId }); - console.log("✅ Réponse du content script:", response); + log("✅ Réponse du content script:", response); return response; } catch (error) { - console.error("⌠Erreur lors de la gestion du surlignage:", error); + log("⌠Erreur lors de la gestion du surlignage:", error); return false; } } \ No newline at end of file diff --git a/src/context_menu/browser_context_menu.js b/src/context_menu/browser_context_menu.js index 9211233..57f5d56 100644 --- a/src/context_menu/browser_context_menu.js +++ b/src/context_menu/browser_context_menu.js @@ -12,7 +12,7 @@ async function loadAuthToken() { authToken = result.accessToken; log("🔑 Token chargé au démarrage :", authToken); } catch (error) { - console.error("⌠Erreur lors de la récupération du token :", error); + log("⌠Erreur lors de la récupération du token :", error); } } @@ -100,7 +100,7 @@ browser.contextMenus.onClicked.addListener(async (info, tab) => { if (typeof actuallyOpenLoginPage === "function") { actuallyOpenLoginPage(); } else { - console.error("La fonction actuallyOpenLoginPage n'est pas accessible."); + log("La fonction actuallyOpenLoginPage n'est pas accessible."); } return; } @@ -146,7 +146,7 @@ browser.contextMenus.onClicked.addListener(async (info, tab) => { break; } - console.error(`⌠Action inconnue : ${info.menuItemId}`); + log(`⌠Action inconnue : ${info.menuItemId}`); }); // ───────────────────────────────────────────────────────────────────────────── @@ -167,7 +167,7 @@ async function getDefinition(selectedText) { definitions: allDefinitions, }); } catch (error) { - console.error("⌠Erreur lors de la recherche combinée des définitions :", error); + log("⌠Erreur lors de la recherche combinée des définitions :", error); } } @@ -201,7 +201,7 @@ async function searchInLexicons(selectedText) { selectedText, }); } catch (error) { - console.error("⌠Erreur lors de la recherche dans les lexiques :", error); + log("⌠Erreur lors de la recherche dans les lexiques :", error); browser.runtime.sendMessage({ action: "showLexiconResult", lexicons: [], diff --git a/src/context_menu/custom_context_menu.js b/src/context_menu/custom_context_menu.js index a4cb929..dc136d9 100644 --- a/src/context_menu/custom_context_menu.js +++ b/src/context_menu/custom_context_menu.js @@ -20,7 +20,7 @@ async function loadAuthToken() { authToken = result.accessToken || null; log("🔑 Token chargé :", authToken); } catch (error) { - console.error("⌠Erreur lors de la récupération du token :", error); + log("⌠Erreur lors de la récupération du token :", error); authToken = null; } } @@ -297,7 +297,7 @@ async function showPicker(event, selectedText) { try { definitions = await fetchLexiconDefinitions(selectedText); } catch (error) { - console.error("Erreur lors de la récupération des définitions :", error); + log("Erreur lors de la récupération des définitions :", error); } const existingLexiconIds = new Set(); if (Array.isArray(definitions)) { @@ -329,7 +329,7 @@ async function showPicker(event, selectedText) { lexicons: successMsg }); } catch (error) { - console.error("⌠Erreur lors de l'ajout du mot :", error); + log("⌠Erreur lors de l'ajout du mot :", error); const errorMsg = `⌠Erreur lors de l'ajout du mot : ${error.message}`; picker.innerHTML = `<p style="color: red;">${errorMsg}</p>`; setTimeout(() => picker.style.display = "none", 3000); @@ -351,7 +351,7 @@ async function showPicker(event, selectedText) { picker.style.top = event.pageY + "px"; picker.style.display = "flex"; } catch (error) { - console.error("⌠Erreur lors de la récupération des lexiques :", error); + log("⌠Erreur lors de la récupération des lexiques :", error); picker.innerHTML = "<p style='color:#333;'>Erreur lors du chargement des lexiques.</p>"; picker.style.display = "block"; } diff --git a/src/popup/popup.js b/src/popup/popup.js index 5f83c88..5a912ed 100644 --- a/src/popup/popup.js +++ b/src/popup/popup.js @@ -16,7 +16,7 @@ async function updateConnectionButton() { const button = document.getElementById("auth-button"); if (!button) { - console.error("⌠Le bouton de connexion n'a pas été trouvé."); + log("⌠Le bouton de connexion n'a pas été trouvé."); return; } @@ -360,7 +360,7 @@ function showNotification(message) { notificationBox.classList.add("hidden"); }, { once: true }); } else { - console.error("⌠Impossible d'afficher la notification : élément manquant."); + log("⌠Impossible d'afficher la notification : élément manquant."); } } diff --git a/src/sidebar/sidebar.js b/src/sidebar/sidebar.js index a6d9a6a..b56fc56 100644 --- a/src/sidebar/sidebar.js +++ b/src/sidebar/sidebar.js @@ -233,7 +233,7 @@ async function fetchLexicons() { // Restaurer l'état des boutons après l'affichage await restoreHighlightingState(); } catch (error) { - console.error("⌠Erreur lors du chargement des lexiques :", error.message); + log("⌠Erreur lors du chargement des lexiques :", error.message); const lexiquesContainer = document.getElementById("lexiques"); if (lexiquesContainer) { lexiquesContainer.textContent = error.message || "Erreur lors du chargement des lexiques."; @@ -316,7 +316,7 @@ async function displayLexiconsWithCheckbox(lexicons) { .map(btn => parseInt(btn.dataset.lexiconId)); await browser.storage.local.set({ activeLexicons }); } catch (error) { - console.error("Erreur lors du toggle de surlignage pour le lexique", lexiconId, ":", error); + log("Erreur lors du toggle de surlignage pour le lexique", lexiconId, ":", error); } }); @@ -368,7 +368,7 @@ async function restoreHighlightingState() { }); } } catch (error) { - console.error("Erreur lors de la restauration de l'état des boutons:", error); + log("Erreur lors de la restauration de l'état des boutons:", error); } } @@ -381,7 +381,7 @@ function initModal() { log("closeModalBtn =", closeModalBtn); if (!modalOverlay || !modalFullText || !closeModalBtn) { - console.error("Les éléments modaux ne sont pas trouvés !"); + log("Les éléments modaux ne sont pas trouvés !"); return; } @@ -444,7 +444,7 @@ async function handleAddWordClick() { try { definitions = await fetchLexiconDefinitions(selectedWord); } catch (error) { - console.error("Erreur lors de la récupération des définitions pour vérification :", error); + log("Erreur lors de la récupération des définitions pour vérification :", error); } const existingLexiconIds = new Set(); @@ -490,7 +490,7 @@ async function handleAddWordClick() { } } catch (error) { - console.error("Erreur lors de l'ajout du mot :", error); + log("Erreur lors de l'ajout du mot :", error); if (lexiconResultElement) { lexiconResultElement.textContent = "Erreur lors de l'ajout : " + error.message; } @@ -664,7 +664,7 @@ document.addEventListener("DOMContentLoaded", async () => { chercherDefButton.style.visibility = "visible"; chercherDefButton.disabled = false; } else { - console.error("⌠ERREUR : Bouton #chercherDef introuvable."); + log("⌠ERREUR : Bouton #chercherDef introuvable."); } // Écouteur pour la case à cocher "toggle-definitions" @@ -759,6 +759,6 @@ async function toggleLexiconHighlight(lexiconId, isActive) { log(`✅ Surlignage ${isActive ? 'activé' : 'désactivé'} pour le lexique ${lexiconId}`); } catch (error) { - console.error(`⌠Erreur lors du toggle du surlignage pour le lexique ${lexiconId}:`, error); + log(`⌠Erreur lors du toggle du surlignage pour le lexique ${lexiconId}:`, error); } } diff --git a/src/utils/api.js b/src/utils/api.js index d725f8d..19d1a12 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -44,7 +44,7 @@ async function callApi(url, authToken = null, method = 'GET', data = null) { } return await response.json(); } catch (error) { - console.error(`🚨 Erreur lors de l'appel API [${url}]:`, error); + log(`🚨 Erreur lors de l'appel API [${url}]:`, error); throw error; } } @@ -91,7 +91,7 @@ async function getAllCategoriesLexicons(authToken) { log("✅ Lexiques récupérés (toutes catégories confondues) :", combined); return combined; } catch (error) { - console.error("⌠Erreur lors de la récupération multi-catégories :", error); + log("⌠Erreur lors de la récupération multi-catégories :", error); return []; } } @@ -146,7 +146,7 @@ async function getAllLexiconWords(authToken) { log("✅ Toutes les graphies récupérées :", allGraphiesByLexicon); return allGraphiesByLexicon; } catch (error) { - console.error("⌠Erreur lors de la récupération des graphies des lexiques :", error); + log("⌠Erreur lors de la récupération des graphies des lexiques :", error); return {}; } } @@ -174,7 +174,7 @@ async function getWiktionaryDefinition(word) { log(`📖 Définition trouvée pour '${word}':`, definition); return [definition]; } catch (error) { - console.error("Erreur lors de la récupération du Wiktionnaire :", error); + log("Erreur lors de la récupération du Wiktionnaire :", error); return ["Erreur : " + error.message]; } } diff --git a/src/utils/definitions.js b/src/utils/definitions.js index 2010727..b59e496 100644 --- a/src/utils/definitions.js +++ b/src/utils/definitions.js @@ -116,7 +116,7 @@ async function fetchLexiconDefinitions(word) { log("Résultat final filtré :", allDefinitions); return allDefinitions; } catch (error) { - console.error("⌠Erreur générale lors de la récupération des définitions :", error); + log("⌠Erreur générale lors de la récupération des définitions :", error); return []; } } @@ -155,7 +155,7 @@ async function fetchLexiconDefinitions(word) { // } // ]; // } catch (error) { -// console.error("⌠Erreur Wiktionnaire :", error); +// log("⌠Erreur Wiktionnaire :", error); // return [ // { // source: "Wiktionnaire", @@ -189,7 +189,7 @@ async function wikiApiResponse(word) { log(`Résultats du Wiktionnaire pour le mot "${word}" :`, data); return data; } catch (error) { - console.error('Erreur lors de la récupération de la définition depuis le Wiktionnaire :', error); + log('Erreur lors de la récupération de la définition depuis le Wiktionnaire :', error); throw error; } } @@ -262,7 +262,7 @@ async function fetchWiktionaryDefinition(word) { } ]; } catch (error) { - console.error("Erreur lors de la récupération de la définition :", error); + log("Erreur lors de la récupération de la définition :", error); return [{ source: "Wiktionnaire", text: "Erreur lors de la récupération sur le Wiktionnaire." }]; } } @@ -387,7 +387,7 @@ function openDefinitionPopup(fullText) { const modalOverlay = document.getElementById("modalOverlay"); const modalFullText = document.getElementById("modalFullText"); if (!modalOverlay || !modalFullText) { - console.error("Modal elements not found!"); + log("Modal elements not found!"); return; } modalFullText.innerHTML = "<p>" + fullText.replace(/\n/g, "<br>") + "</p>"; @@ -467,7 +467,7 @@ async function showDefinitions(word) { return allDefinitions; } catch (error) { - console.error("⌠[showDefinitions] Erreur : ", error); + log("⌠[showDefinitions] Erreur : ", error); if (noDefinitionsContainer) { noDefinitionsContainer.textContent = @@ -487,7 +487,7 @@ async function fetchDefinition(word) { const noDefinitionsContainer = document.getElementById("noDefinitionsContainer"); if (!noDefinitionsContainer) { - console.error("⌠Élément #noDefinitionsContainer introuvable."); + log("⌠Élément #noDefinitionsContainer introuvable."); return; } @@ -503,7 +503,7 @@ async function fetchDefinition(word) { noDefinitionsContainer.style.display = "none"; } catch (error) { - console.error("⌠Erreur lors de la récupération de la définition :", error); + log("⌠Erreur lors de la récupération de la définition :", error); noDefinitionsContainer.style.display = "block"; } } diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index bc9386d..4a673e9 100644 --- a/src/utils/highlighting.js +++ b/src/utils/highlighting.js @@ -2,22 +2,22 @@ window.activeLexiconIds = window.activeLexiconIds || new Set(); // Logs immédiats -console.log("🔵 DÉBUT DU FICHIER highlighting.js"); +log("🔵 DÉBUT DU FICHIER highlighting.js"); try { log("✅ highlighting.js chargé"); } catch (e) { - console.error("⌠Erreur avec la fonction log:", e); + log("⌠Erreur avec la fonction log:", e); } // Vérification de l'environnement -console.log("🔠Vérification de l'environnement:", { +log("🔠Vérification de l'environnement:", { hasBrowser: typeof browser !== 'undefined', windowLocation: window.location.href }); // Gestion globale des erreurs window.onerror = function(msg, url, line, col, error) { - console.error("🔴 Erreur globale:", { message: msg, url: url, line: line, col: col, error: error }); + log("🔴 Erreur globale:", { message: msg, url: url, line: line, col: col, error: error }); return false; }; @@ -35,7 +35,7 @@ async function initAuthToken() { return false; } } catch (error) { - console.error("⌠Erreur lors de la récupération du token:", error); + log("⌠Erreur lors de la récupération du token:", error); return false; } } @@ -53,7 +53,7 @@ browser.runtime.onMessage.addListener((message) => { (function () { try { if (window.hasRun) { - console.log("âš ï¸ highlighting.js déjà chargé"); + log("âš ï¸ highlighting.js déjà chargé"); return; } window.hasRun = true; @@ -86,7 +86,7 @@ browser.runtime.onMessage.addListener((message) => { // Gestion des messages reçus du background browser.runtime.onMessage.addListener((message, sender, sendResponse) => { - console.log("📨 Message reçu:", message, "Context:", { + log("📨 Message reçu:", message, "Context:", { highlightingActive, activeLexiconIds: Array.from(activeLexiconIds), hasAuthToken: !!window.authToken, @@ -101,7 +101,7 @@ browser.runtime.onMessage.addListener((message) => { sendResponse(true); }) .catch(error => { - console.error("⌠Erreur lors de l'activation:", error); + log("⌠Erreur lors de l'activation:", error); sendResponse(false); }); return true; @@ -117,7 +117,7 @@ browser.runtime.onMessage.addListener((message) => { sendResponse(true); }) .catch(error => { - console.error("⌠Erreur lors de la désactivation:", error); + log("⌠Erreur lors de la désactivation:", error); sendResponse(false); }); return true; @@ -211,7 +211,7 @@ browser.runtime.onMessage.addListener((message) => { attachMutationObserver(); return true; } catch (error) { - console.error("⌠Erreur lors du démarrage du surlignage:", error); + log("⌠Erreur lors du démarrage du surlignage:", error); window.highlightingActive = false; highlightingActive = false; throw error; @@ -243,14 +243,14 @@ browser.runtime.onMessage.addListener((message) => { } return true; } catch (error) { - console.error("⌠Erreur lors de l'arrêt du surlignage:", error); + log("⌠Erreur lors de l'arrêt du surlignage:", error); throw error; } } // Mise à jour du cache des lexiques async function updateLexiconCache() { - console.log("📥 updateLexiconCache - Début avec context:", { + log("📥 updateLexiconCache - Début avec context:", { authToken: !!window.authToken, getAllLexiconWords: !!window.getAllLexiconWords, activeLexiconIds: Array.from(activeLexiconIds) @@ -297,7 +297,7 @@ browser.runtime.onMessage.addListener((message) => { Object.fromEntries([...lexiconWordsCache.entries()].map(([id, words]) => [id, [...words]]))); return true; } catch (error) { - console.error("⌠Erreur dans updateLexiconCache:", { + log("⌠Erreur dans updateLexiconCache:", { message: error.message, stack: error.stack, authTokenExists: !!window.authToken, @@ -512,7 +512,7 @@ browser.runtime.onMessage.addListener((message) => { await startHighlighting(lexiconId); } } catch (error) { - console.error("⌠Erreur lors de la restauration de l'état:", error); + log("⌠Erreur lors de la restauration de l'état:", error); window.highlightingActive = false; highlightingActive = false; } @@ -521,6 +521,6 @@ browser.runtime.onMessage.addListener((message) => { checkAndRestoreHighlightingState(); } catch (error) { - console.error("🔴 Erreur critique dans l'IIFE:", error); + log("🔴 Erreur critique dans l'IIFE:", error); } })(); diff --git a/src/utils/logger.js b/src/utils/logger.js index 1455361..9828f27 100644 --- a/src/utils/logger.js +++ b/src/utils/logger.js @@ -5,7 +5,7 @@ (function () { if (typeof window !== 'undefined') { if (typeof window.DEBUG === 'undefined') { - window.DEBUG = true; // ou false en production + window.DEBUG = false; // true en debug } if (!window.log) { function log(...args) { @@ -17,7 +17,7 @@ } } else if (typeof self !== 'undefined') { if (typeof self.DEBUG === 'undefined') { - self.DEBUG = true; + self.DEBUG = false; // true en debug } if (!self.log) { function log(...args) { diff --git a/src/workers/pyodide_worker.js b/src/workers/pyodide_worker.js index 45f9e77..3e8458e 100644 --- a/src/workers/pyodide_worker.js +++ b/src/workers/pyodide_worker.js @@ -37,7 +37,7 @@ self.onmessage = async (event) => { await pyodide.loadPackage("micropip"); pyodideLoaded = true; } catch (err) { - console.error("[Worker] Erreur lors de l'import de pyodide.js :", err); + log("[Worker] Erreur lors de l'import de pyodide.js :", err); self.postMessage({ type: "pyodide-simplemma", status: "error", message: err.toString() }); return; } @@ -77,7 +77,7 @@ await main() // Envoyer confirmation au background script self.postMessage({ type: "pyodide-simplemma", status: "success", message: "Pyodide et Simplemma chargés" }); } catch (error) { - console.error("[Worker] Erreur lors du chargement de Pyodide ou Simplemma :", error); + log("[Worker] Erreur lors du chargement de Pyodide ou Simplemma :", error); self.postMessage({ type: "pyodide-simplemma", status: "error", message: error.toString() }); } } @@ -141,7 +141,7 @@ json.dumps({"lang": detected_lang, "frequencies": freq}, ensure_ascii=False) checkThreshold(detectedLang); } } catch (error) { - console.error("[Worker] Erreur dans l'analyse du texte :", error); + log("[Worker] Erreur dans l'analyse du texte :", error); } } -- GitLab