diff --git a/src/background/background.js b/src/background/background.js index be3cfae4fa1afd38331d9898c5264449bc1beee2..2ad660a35280c702f3baba04c7e748145894c6d9 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -53,6 +53,7 @@ browser.storage.onChanged.addListener((changes, area) => { if (!extensionActive) { log("Token ajouté, activation automatique de l'extension."); browser.storage.local.set({ extensionActive: true }); // Met à jour l'état de l'extension + updateExtension(); // Met à jour les fonctionnalités de l'extension // Envoie un message pour mettre à jour l'interface utilisateur browser.runtime.sendMessage({ action: "updateUI", @@ -772,7 +773,7 @@ browser.runtime.onConnect.addListener((port) => { * @returns {Promise<boolean>} - True si le surlignage a été effectué, false sinon. */ async function handleHighlighting(command, lexiconId, tabId) { - 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é @@ -793,4 +794,4 @@ async function handleHighlighting(command, lexiconId, tabId) { log("Erreur lors de la gestion du surlignage:", error); return false; } -} +} \ No newline at end of file diff --git a/src/options/options.html b/src/options/options.html new file mode 100644 index 0000000000000000000000000000000000000000..8b2bfa963d5f5369b8b67464fd9ac95a506d4253 --- /dev/null +++ b/src/options/options.html @@ -0,0 +1,38 @@ +<!-- <!DOCTYPE html> +<html lang="fr"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Paramètres ff2BaLex</title> + <script src="../utils/logger.js"></script> + <style> + body { + font-family: Luciole; + padding: 20px; + background-color: #323046; + color: white; + } + button { + width: 100%; + padding: 10px; + margin-bottom: 10px; + font-size: 15px; + color: #94608a; + font-weight: bold; + border: none; + cursor: pointer; + } + button:hover { + background-color: #94608a; + color: white; + } + </style> +</head> +<body> + <h3>Paramètres BaLex</h3> + <button id="connectBtn">Se connecter</button> + <button id="toggleExtensionBtn">Activer/Désactiver l'extension</button> + <button id="toggleStatsBtn">Activer/Désactiver les statistiques</button> + <script src="options.js"></script> +</body> +</html> --> diff --git a/src/options/options.js b/src/options/options.js new file mode 100644 index 0000000000000000000000000000000000000000..da48f12e80a3aaf985363633861795ef709f6d89 --- /dev/null +++ b/src/options/options.js @@ -0,0 +1,28 @@ +// document.getElementById('connectBtn').addEventListener('click', () => { +// browser.runtime.sendMessage({ action: "openLoginPage" }); +// }); + +// async function disconnectFromLexicalDB() { +// await browser.storage.local.remove("accessToken"); +// log("Token supprimé, déconnexion réussie."); +// alert("Déconnexion réussie."); +// updateContextMenu(); + +// // Envoi d'un message pour mettre à jour l'UI +// browser.runtime.sendMessage({ action: "updateUI" }); +// } + +// document.getElementById("toggleExtensionBtn").addEventListener("click", async () => { +// const { extensionActive } = await browser.storage.local.get("extensionActive"); +// const newState = !extensionActive; +// await browser.storage.local.set({ extensionActive: newState }); +// alert(`Extension ${newState ? "activée" : "désactivée"}.`); +// }); + +// document.getElementById("toggleStatsBtn").addEventListener("click", async () => { +// const { statsActive } = await browser.storage.local.get("statsActive"); +// const newState = !statsActive; +// await browser.storage.local.set({ statsActive: newState }); +// alert(`Statistiques ${newState ? "activées" : "désactivées"}.`); +// }); + diff --git a/src/plugin/displayStats.js b/src/plugin/displayStats.js new file mode 100644 index 0000000000000000000000000000000000000000..cc949856424e2b7c38170150ab2076b9428d1749 --- /dev/null +++ b/src/plugin/displayStats.js @@ -0,0 +1,145 @@ +// stats.js +document.addEventListener("DOMContentLoaded", async () => { + // Fonction pour recalculer et stocker le résumé des statistiques + async function updateStatsSummary() { + console.log("[Stats Page] Mise à jour du résumé des statistiques..."); + + const { + lemmaFrequencies = {}, + trackedLanguages = [], + wordsAdded = {} + } = await browser.storage.local.get([ + "lemmaFrequencies", + "trackedLanguages", + "wordsAdded" + ]); + + let totalWords = 0, totalUniqueWords = 0; + const languages = {}; + + for (const [lang, words] of Object.entries(lemmaFrequencies)) { + if (!trackedLanguages.length || trackedLanguages.includes(lang)) { + let wordCount = 0; + let uniqueWordCount = 0; + for (const count of Object.values(words)) { + wordCount += count; + uniqueWordCount++; + } + languages[lang] = { totalWords: wordCount, uniqueWords: uniqueWordCount }; + totalWords += wordCount; + totalUniqueWords += uniqueWordCount; + } + } + + const summary = { + totalWords, + totalUniqueWords, + languages, + wordsAdded + }; + + console.log("[Stats Page] Résumé des statistiques mis à jour:", summary); + await browser.storage.local.set({ statsSummary: summary }); + return { summary, lemmaFrequencies, trackedLanguages }; + } + + // Générer le HTML du résumé global + function generateSummaryHTML(summary) { + if (summary.totalWords === 0) { + return `<h2>Résumé des statistiques</h2> + <p>Aucune statistique disponible pour le moment.</p>`; + } + return ` + <h2>Résumé des statistiques</h2> + <p>Date : ${new Date().toLocaleDateString()}</p> + <p>Total de mots analysés : ${summary.totalWords}</p> + <p>Total de mots uniques : ${summary.totalUniqueWords}</p> + `; + } + + // Générer le contrôle de tri (placé juste au-dessus des tableaux) + function generateSortControlHTML(currentSortOrder) { + return ` + <div id="sort-container"> + <label for="sort-order">Trier par fréquence : </label> + <select id="sort-order"> + <option value="desc" ${currentSortOrder === "desc" ? "selected" : ""}>Décroissante</option> + <option value="asc" ${currentSortOrder === "asc" ? "selected" : ""}>Croissante</option> + </select> + </div> + `; + } + + // Générer le HTML détaillé pour chaque langue avec le total par langue + function generateDetailedFrequenciesHTML(lemmaFrequencies, trackedLanguages, sortOrder) { + let detailsHTML = `<div id="detailed-frequencies">`; + let hasData = false; + + for (const [lang, words] of Object.entries(lemmaFrequencies)) { + if (!trackedLanguages.length || trackedLanguages.includes(lang)) { + let wordEntries = Object.entries(words); + if (wordEntries.length === 0) { + detailsHTML += `<h4>${lang.toUpperCase()}</h4> + <p>Aucune donnée pour cette langue.</p>`; + } else { + hasData = true; + // Calculer le total pour cette langue + const totalForLang = wordEntries.reduce((acc, curr) => acc + curr[1], 0); + // Trier les mots par fréquence + wordEntries.sort((a, b) => sortOrder === "asc" ? a[1] - b[1] : b[1] - a[1]); + detailsHTML += `<h4>${lang.toUpperCase()} (Total: ${totalForLang} mots)</h4>`; + detailsHTML += `<div class="table-container"> + <table> + <tr> + <th>Mot</th> + <th>Fréquence</th> + </tr>`; + for (const [word, freq] of wordEntries) { + detailsHTML += `<tr> + <td>${word}</td> + <td>${freq}</td> + </tr>`; + } + // // Ligne de récapitulation pour le total de mots de la langue + // detailsHTML += `<tr> + // <td colspan="2" style="text-align:right; font-weight:bold;"> + // AJOUT: Total + // : ${totalForLang} + // </td> + // </tr>`; + detailsHTML += `</table> + </div>`; + } + } + } + + if (!hasData) { + detailsHTML += `<p>Aucune donnée de fréquence à afficher.</p>`; + } + detailsHTML += `</div>`; + return detailsHTML; + } + + const container = document.getElementById("stats-container"); + let currentSortOrder = "desc"; + + const { summary, lemmaFrequencies, trackedLanguages } = await updateStatsSummary(); + container.innerHTML = generateSummaryHTML(summary) + + generateSortControlHTML(currentSortOrder) + + generateDetailedFrequenciesHTML(lemmaFrequencies, trackedLanguages, currentSortOrder); + + // Écouteur pour mettre à jour l'affichage lorsque l'utilisateur change l'ordre de tri + document.getElementById("sort-order").addEventListener("change", async (e) => { + currentSortOrder = e.target.value; + const data = await updateStatsSummary(); + const detailedHTML = generateDetailedFrequenciesHTML(data.lemmaFrequencies, data.trackedLanguages, currentSortOrder); + const detailedContainer = document.getElementById("detailed-frequencies"); + if (detailedContainer) { + detailedContainer.outerHTML = detailedHTML; + } else { + container.innerHTML = generateSummaryHTML(data.summary) + + generateSortControlHTML(currentSortOrder) + + detailedHTML; + } + }); +}); diff --git a/src/plugin/plugin.html b/src/plugin/plugin.html index 8db7d83258925205e7b8227a586ec5781482eff3..ca17e78d592e801a20fe1145af7ac348e654abf3 100644 --- a/src/plugin/plugin.html +++ b/src/plugin/plugin.html @@ -5,7 +5,6 @@ <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Extension BaLex</title> <script src="../utils/logger.js"></script> - <link rel="stylesheet" href="../css/plugin.css"> </head> <body> @@ -71,8 +70,7 @@ <button id="close-notification">OK</button> </div> - <script src="../utils/api.js" defer></script> - <script src="plugin.js" defer></script> - <script src="../utils/stats.js" defer></script> + <script src="../utils/api.js"></script> + <script src="plugin.js"></script> </body> </html> diff --git a/src/plugin/plugin.js b/src/plugin/plugin.js index 8d07f221682df8752de105a995c8a3e6b932da12..4e8a0b7a3d708d54b15261b86d26a8b95b353576 100644 --- a/src/plugin/plugin.js +++ b/src/plugin/plugin.js @@ -1,4 +1,4 @@ -log("plugin.js chargé."); +log("plugin chargé avec succès !"); // fetchExtensionState() : fonction qui se charge de récupérer les valeurs du local storage // updateUI(): utilise les états récupérés par fetchExtensionState pour appeler d'autres fonctions // ex. actualisation du bouton de connexion, bouton activer l'extension, les stats... @@ -9,7 +9,6 @@ log("plugin.js chargé."); // ==================================================================================== // Fonctions utilitaires // ==================================================================================== -let isUpdatingLexicons = false; //Obtenir le token async function getAccessToken() { @@ -137,11 +136,11 @@ async function handleStatsToggle() { browser.runtime.sendMessage({ command: "pyodide-simplemma" }); } - if (isUpdatingLexicons) return; - isUpdatingLexicons = true; - await updateLexiconsDisplay(); - isUpdatingLexicons = false; - await updateExtension(); +// if (isUpdatingLexicons) return; +// isUpdatingLexicons = true; +// await updateLexiconsDisplay(); +// isUpdatingLexicons = false; +// await updateExtension(); } // Activer l'extension @@ -513,66 +512,18 @@ function handleWorkerMessage(event) { }} +// ========================== +// Affichage des statistiques +// ========================== +// Bouton pour ouvrir la page des statistiques +document.getElementById("open-stats")?.addEventListener("click", async () => { + openStatsPage(); +}); +function openStatsPage() { + browser.tabs.create({ + url: browser.runtime.getURL("stats.html") + }); +} - - - - - - - - - - - - - -// // Bouton pour ouvrir la page des statistiques -// document.getElementById("open-stats")?.addEventListener("click", async () => { -// await displayStatsSummary();//résumé dans la console -// window.open("stats.html", "_blank"); -// }); - -// async function displayStatsSummary() { -// console.log("[Popup] Préparation du résumé des statistiques..."); - -// // Récupérer les données stockées -// const { lemmaFrequencies, trackedLanguages, wordsAdded } = await browser.storage.local.get([ -// "lemmaFrequencies", -// "trackedLanguages", -// "wordsAdded" -// ]); - -// // Initialisation du résumé -// let summary = { -// totalWords: 0, // Nombre total de mots analysés -// totalUniqueWords: 0, // Nombre total de mots uniques -// languages: {}, // Nombre de mots analysés par langue -// wordsAdded: wordsAdded || {} // Mots ajoutés classés par langue -// }; - -// if (lemmaFrequencies) { -// Object.entries(lemmaFrequencies).forEach(([lang, words]) => { -// const wordCount = Object.values(words).reduce((sum, count) => sum + count, 0); -// const uniqueWordCount = Object.keys(words).length; - -// // Vérifier si la langue doit être suivie -// if (!trackedLanguages || trackedLanguages.includes(lang)) { -// summary.languages[lang] = { -// totalWords: wordCount, -// uniqueWords: uniqueWordCount -// }; - -// summary.totalWords += wordCount; -// summary.totalUniqueWords += uniqueWordCount; -// } -// }); -// } - -// console.log("[Popup] Résumé des statistiques mis à jour:", summary); - -// // Résumé dans le local storage -// await browser.storage.local.set({ statsSummary: summary }); -// } diff --git a/src/plugin/stats.html b/src/plugin/stats.html new file mode 100644 index 0000000000000000000000000000000000000000..9cbe36c42ed0932f25ce5b80748ab5014ad2cd07 --- /dev/null +++ b/src/plugin/stats.html @@ -0,0 +1,56 @@ +<!-- stats.html --> +<!DOCTYPE html> +<html lang="fr"> +<head> + <meta charset="UTF-8"> + <title>Résumé des statistiques</title> + <script src="displayStats.js"></script> + <style> + /* Style global pour une présentation compacte et lisible */ + body { + font-family: Arial, sans-serif; + margin: 20px; + padding: 0; + } + #stats-container { + max-width: 600px; + margin: 0 auto; + } + /* Contrôle de tri centré et espacé */ + #sort-container { + margin: 20px 0; + text-align: center; + } + /* Tableaux compacts */ + table { + width: 100%; + border-collapse: collapse; + font-size: 0.85em; + margin-bottom: 15px; + } + table, th, td { + border: 1px solid #ddd; + } + th, td { + padding: 6px 8px; + text-align: left; + } + th { + background-color: #ae8bac; + } + h4 { + margin-bottom: 5px; + } + /* Optionnel : encadrer les tableaux dans un conteneur avec défilement si trop de lignes */ + .table-container { + max-height: 300px; + overflow-y: auto; + } + </style> +</head> +<body> + <div id="stats-container"> + <p>Chargement des statistiques…</p> + </div> +</body> +</html> diff --git a/src/utils/definitions.js b/src/utils/definitions.js index 93b9bf42511e692723fc47a67685d82032c0c750..2612c5cd5411d03a08bd428fda24ac1deaa167c2 100644 --- a/src/utils/definitions.js +++ b/src/utils/definitions.js @@ -32,7 +32,7 @@ async function fetchLexiconDefinitions(word) { throw new Error(`⌠Erreur API lors de la récupération des lexiques: ${lexResponse.statusText}`); } const userLexicons = await lexResponse.json(); - log("ðŸ—‚ï¸ Lexiques de l'utilisateur :", userLexicons); + log("Lexiques de l'utilisateur :", userLexicons); if (!Array.isArray(userLexicons) || userLexicons.length === 0) { console.warn("âš ï¸ Aucun lexique trouvé pour cet utilisateur."); @@ -48,7 +48,7 @@ async function fetchLexiconDefinitions(word) { : `Lexique de groupe : ${lex.group?.name || "Inconnu"}`; lexiconMap.set(lex.id, lexiconName); }); - log("📌 LexiconMap :", lexiconMap); + log("LexiconMap :", lexiconMap); // 2) Pour chaque lexique, rechercher le mot en ajoutant target_lex const definitionsPromises = userLexicons.map(async (lex) => { @@ -96,6 +96,8 @@ async function fetchLexiconDefinitions(word) { } } + const balexId = entry.balex_id || null; + items.forEach(item => { const definitionsArray = item.Sense?.Definitions; const pronunciationsArray = item.Sense?.Pronunciations; @@ -112,6 +114,7 @@ async function fetchLexiconDefinitions(word) { allDefinitions.push({ source: sourceName, text: defObj.Def, + balex_id: balexId, pronunciations: pronunciations, lexiconId: lexiconId }); @@ -120,7 +123,7 @@ async function fetchLexiconDefinitions(word) { }); }); }); - log("Résultat final filtré :", allDefinitions); + log("Résultats filtré depuis les lexiques utilisateurs :", allDefinitions); return allDefinitions; } catch (error) { log("⌠Erreur générale lors de la récupération des définitions :", error); @@ -156,16 +159,16 @@ async function fetchWiktionaryDefinition(word) { throw new Error(`⌠Erreur API Wiktionnaire: ${response.statusText}`); } const data = await response.json(); - log("📖 Réponse API (Wiktionnaire) :", data); + log("Réponse API (Wiktionnaire) :", data); const pages = data.query?.pages; const page = pages ? Object.values(pages)[0] : null; formattedData.definitions = page && page.extract ? [page.extract.trim()] - : ["âš ï¸ Aucune définition trouvée sur le Wiktionnaire."]; + : ["Aucune définition trouvée sur le Wiktionnaire."]; - log("🌠Définition Wiktionnaire extraite :", formattedData.definitions); + log("Définition Wiktionnaire extraite :", formattedData.definitions); return [ { @@ -193,13 +196,13 @@ async function fetchWiktionaryDefinition(word) { // Vérification avant retour if (!formattedData.definitions) { - formattedData.definitions = []; // 🔹 Toujours s'assurer que cette clé existe + formattedData.definitions = []; // } if (!formattedData.pronunciations) { - formattedData.pronunciations = []; // 🔹 Toujours s'assurer que cette clé existe + formattedData.pronunciations = []; // } if (!formattedData.definitionsByPOS) { - formattedData.definitionsByPOS = {}; // 🔹 Toujours s'assurer que cette clé existe + formattedData.definitionsByPOS = {}; // } return [ @@ -331,14 +334,15 @@ const MAX_LENGTH = 200; * Affiche les définitions dans la barre latérale. */ function displayDefinitions(definitions) { - log("📖 Affichage des définitions reçues :", definitions); + log("Affichage des définitions reçues :", definitions); if (!Array.isArray(definitions)) return; - const mesLexiquesList = document.getElementById("mesLexiquesList"); const wiktionnaireList = document.getElementById("wiktionnaireList"); const noLexiconDefinitionsContainer = document.getElementById("noLexiconDefinitionsContainer"); const noWiktionaryDefinitionsContainer = document.getElementById("noWiktionaryDefinitionsContainer"); + const balexIdMap = new Map(); // Dictionnaire pour stocker balex_id par lexique + // Nettoyage des listes existantes mesLexiquesList.innerHTML = ""; wiktionnaireList.innerHTML = ""; @@ -351,105 +355,109 @@ function displayDefinitions(definitions) { let hasWiktionaryDefinitions = false; const lexiconGroups = {}; - definitions.forEach(({ source, text, definitionsByPOS }) => { - if (!source || !text) return; - - const definitionContainer = document.createElement("div"); - definitionContainer.classList.add("definition-item"); - - // 🔹 1. **Gestion des définitions des lexiques** - if (!definitionsByPOS) { - // C'est une définition provenant des lexiques utilisateur - const li = document.createElement("li"); - li.textContent = text; - definitionContainer.appendChild(li); - - // Ajout dans le bon groupe - if (!lexiconGroups[source]) { - lexiconGroups[source] = []; - } - lexiconGroups[source].push(definitionContainer); - hasLexiconDefinitions = true; - - } else { - // C'est une définition provenant du Wiktionnaire - log(`Traitement des définitions du Wiktionnaire pour "${source}"`); + definitions.forEach(({ source, text, balex_id, definitionsByPOS }) => { + if (!source || !text) return; + log(`Traitement de ${source}, balex_id:`, balex_id); - // 2. Affichage des prononciations globales si disponibles - const allPronunciations = new Set(); - Object.values(definitionsByPOS).forEach(posData => { - posData.pronunciations.forEach(pron => allPronunciations.add(pron)); - }); - - if (allPronunciations.size > 0) { - const pronDiv = document.createElement("div"); - pronDiv.style.fontWeight = "bold"; - pronDiv.style.color = "#94608a"; - pronDiv.style.marginBottom = "5px"; - pronDiv.textContent = `Prononciations possibles : ${[...allPronunciations].join(", ")}`; - definitionContainer.appendChild(pronDiv); - } - - // 3. Affichage des définitions triées par POS - Object.entries(definitionsByPOS).forEach(([pos, posData]) => { - if (posData.definitions.length === 0) return; // Évite les POS vides - - // Titre du POS - const posTitle = document.createElement("h4"); - posTitle.style.marginTop = "10px"; - posTitle.style.color = "#FFFFFF"; - posTitle.textContent = `${pos.toUpperCase()}`; - definitionContainer.appendChild(posTitle); - - // Prononciations spécifiques au POS - if (posData.pronunciations.length > 0) { - const posPronDiv = document.createElement("div"); - posPronDiv.style.fontStyle = "italic"; - posPronDiv.style.color = "#94608a"; - // posPronDiv.textContent = `${posData.pronunciations.join(", ")}`; - // definitionContainer.appendChild(posPronDiv); - } + const definitionContainer = document.createElement("div"); + definitionContainer.classList.add("definition-item"); - // Liste des définitions - const defList = document.createElement("ul"); - defList.style.margin = "0"; - defList.style.paddingLeft = "20px"; - - posData.definitions.forEach(def => { - const li = document.createElement("li"); - - // 4. Gestion du bouton "Lire la suite" - let displayedText = def.trim(); - if (displayedText.length > MAX_LENGTH) { - const truncatedText = displayedText.slice(0, MAX_LENGTH) + "... "; - const readMoreLink = document.createElement("a"); - readMoreLink.href = "#"; - readMoreLink.textContent = "[Lire la suite]"; - readMoreLink.style.marginLeft = "5px"; - readMoreLink.style.color = "#8d5c70"; - readMoreLink.style.textDecoration = "underline"; - readMoreLink.style.cursor = "pointer"; - readMoreLink.addEventListener("click", (event) => { - event.preventDefault(); - openDefinitionPopup(displayedText); - }); - - li.appendChild(document.createTextNode(truncatedText)); - li.appendChild(readMoreLink); - } else { - li.textContent = displayedText; - } - - defList.appendChild(li); - }); + // Gestion des définitions des lexiques + if (!definitionsByPOS) { + // C'est une définition provenant des lexiques utilisateur + const li = document.createElement("li"); + li.textContent = text; + definitionContainer.appendChild(li); - definitionContainer.appendChild(defList); - }); + // Stocker le premier `balex_id` trouvé pour chaque lexique + if (!balexIdMap.has(source) && balex_id) { + balexIdMap.set(source, balex_id); + } + // Ajout dans le bon groupe + if (!lexiconGroups[source]) { + lexiconGroups[source] = []; + } + lexiconGroups[source].push(definitionContainer); + hasLexiconDefinitions = true; + + } else { + // C'est une définition provenant du Wiktionnaire + log(`Traitement des définitions du Wiktionnaire pour "${source}"`); + + // 2. Affichage des prononciations globales si disponibles + const allPronunciations = new Set(); + Object.values(definitionsByPOS).forEach(posData => { + posData.pronunciations.forEach(pron => allPronunciations.add(pron)); + }); + + if (allPronunciations.size > 0) { + const pronDiv = document.createElement("div"); + pronDiv.style.fontWeight = "bold"; + pronDiv.style.color = "#94608a"; + pronDiv.style.marginBottom = "5px"; + pronDiv.textContent = `Prononciations possibles : ${[...allPronunciations].join(", ")}`; + definitionContainer.appendChild(pronDiv); + } - wiktionnaireList.appendChild(definitionContainer); - hasWiktionaryDefinitions = true; - } - }); + // 3. Affichage des définitions triées par POS + Object.entries(definitionsByPOS).forEach(([pos, posData]) => { + if (posData.definitions.length === 0) return; // Évite les POS vides + + // Titre du POS + const posTitle = document.createElement("h4"); + posTitle.style.marginTop = "10px"; + posTitle.style.color = "#FFFFFF"; + posTitle.textContent = `${pos.toUpperCase()}`; + definitionContainer.appendChild(posTitle); + + // Prononciations spécifiques au POS + if (posData.pronunciations.length > 0) { + const posPronDiv = document.createElement("div"); + posPronDiv.style.fontStyle = "italic"; + posPronDiv.style.color = "#94608a"; + // posPronDiv.textContent = `${posData.pronunciations.join(", ")}`; + // definitionContainer.appendChild(posPronDiv); + } + + const defList = document.createElement("ul"); + defList.style.margin = "0"; + defList.style.paddingLeft = "20px"; + + posData.definitions.forEach(def => { + const li = document.createElement("li"); + + // 4. Gestion du bouton "Lire la suite" + let displayedText = def.trim(); + if (displayedText.length > MAX_LENGTH) { + const truncatedText = displayedText.slice(0, MAX_LENGTH) + "... "; + const readMoreLink = document.createElement("a"); + readMoreLink.href = "#"; + readMoreLink.textContent = "[Lire la suite]"; + readMoreLink.style.marginLeft = "5px"; + readMoreLink.style.color = "#8d5c70"; + readMoreLink.style.textDecoration = "underline"; + readMoreLink.style.cursor = "pointer"; + readMoreLink.addEventListener("click", (event) => { + event.preventDefault(); + openDefinitionPopup(displayedText); + }); + + li.appendChild(document.createTextNode(truncatedText)); + li.appendChild(readMoreLink); + } else { + li.textContent = displayedText; + } + + defList.appendChild(li); + }); + + definitionContainer.appendChild(defList); + }); + + wiktionnaireList.appendChild(definitionContainer); + hasWiktionaryDefinitions = true; + } + }); // 5. Gestion des groupes de lexiques personnels Object.entries(lexiconGroups).forEach(([lexiconName, definitionItems]) => { @@ -466,6 +474,12 @@ function displayDefinitions(definitions) { const lexiconContent = document.createElement("div"); lexiconContent.className = "lexicon-content hidden"; + // Ajout du lien vers le site balex ----------------------------------------------- + const balexButton = createBaLexButton(lexiconName, balexIdMap); + if (balexButton) { + lexiconContent.appendChild(balexButton); + } + definitionItems.forEach(item => lexiconContent.appendChild(item)); lexiconContainer.appendChild(lexiconHeader); @@ -534,7 +548,7 @@ async function combineDefinitions(word) { const allDefinitions = [...lexiconDefinitions, ...wiktionaryDefinitions]; - log("📚 [combineDefinitions] Résultat fusionné :", allDefinitions); + log("[combineDefinitions] Résultat fusionné :", allDefinitions); return allDefinitions; } @@ -648,12 +662,53 @@ function displayLexiconResults(lexicons) { li.innerHTML = `<strong>${lexiconName}</strong>`; ul.appendChild(li); - log(`✅ Lexique ajouté : ${lexiconName} (ID: ${lexicon.id})`); + log(`Lexique ajouté : ${lexiconName} (ID: ${lexicon.id})`); }); resultDiv.appendChild(ul); } +/** + * Crée un bouton permettant d'ouvrir une entrée dans BaLex. + * @param {string} lexiconName - Le nom du lexique. + * @param {Map} balexIdMap - Une Map contenant les balex_id associés aux lexiques. + * @returns {HTMLElement|null} - Un bouton HTML ou null si `balex_id` est manquant. + */ +function createBaLexButton(lexiconName, balexIdMap) { + const balexServ = "babalex.lezinter.net"; + const balex_id = balexIdMap.get(lexiconName) || null; + + log(`ID BaLex trouvé pour "${lexiconName}" :`, balex_id); + + // Vérifie si `balex_id` est valide + if (!balex_id) { + console.warn(`âš ï¸ Aucun balex_id trouvé pour "${lexiconName}". Bouton non créé.`); + return null; + } + + const balexUrl = `https://${balexServ}/entry/${balex_id}/show`; + + // Création du bouton + const balexButton = document.createElement("button"); + balexButton.textContent = "Voir dans BaLex 🔗"; + balexButton.style.marginTop = "5px"; + balexButton.style.display = "block"; + balexButton.style.background = "#3a3739"; + balexButton.style.color = "#fff"; + balexButton.style.border = "none"; + balexButton.style.padding = "5px"; + balexButton.style.margin = "5px"; + balexButton.style.borderRadius = "5px"; + balexButton.style.cursor = "pointer"; + + // Ajout du lien + balexButton.addEventListener("click", () => { + window.open(balexUrl, "_blank"); + }); + + return balexButton; +} + // ───────────────────────────────────────────────────────────────────────────── // â–Œ Utilisation des fonctions dans d'autres scripts // ─────────────────────────────────────────────────────────────────────────────