-
Lucie Bader authoredbdc0eb43
definitions.js 21.25 KiB
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Récupération des définitions (lexiques + Wiktionnaire)
// ─────────────────────────────────────────────────────────────────────────────
window.lexiconMap = new Map();
/**
* Récupère les définitions d'un mot dans les lexiques de l'utilisateur.
* @param {string} word - Le mot dont on veut les définitions.
* @returns {Promise<object[]>} - Un tableau d'objets contenant les définitions.
*/
async function fetchLexiconDefinitions(word) {
try {
log(`🔍 Recherche des définitions de '${word}' dans les lexiques de l'utilisateur...`);
if (!authToken) {
console.warn("Aucun token disponible, impossible de requêter l'API protégée.");
return [];
}
// 1) Récupérer la liste complète des lexiques de l'utilisateur
const lexUrl = `https://babalex.lezinter.net/api/lexicon/search?`;
const lexResponse = await fetch(lexUrl, {
headers: { Authorization: `Bearer ${authToken}` }
});
if (!lexResponse.ok) {
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);
if (!Array.isArray(userLexicons) || userLexicons.length === 0) {
console.warn("⚠️ Aucun lexique trouvé pour cet utilisateur.");
return [];
}
// Mise à jour de lexiconMap avec des libellés uniques (ajout de l'ID)
lexiconMap.clear();
userLexicons.forEach((lex) => {
const lexiconName =
lex.category === "User"
? `Lexique personnel : ${lex.user?.pseudo || "Inconnu"}`
: `Lexique de groupe : ${lex.group?.name || "Inconnu"}`;
lexiconMap.set(lex.id, lexiconName);
});
log("LexiconMap :", lexiconMap);
// 2) Pour chaque lexique, rechercher le mot en ajoutant target_lex
const definitionsPromises = userLexicons.map(async (lex) => {
const searchUrl = `https://babalex.lezinter.net/api/entry/search?graphy=${encodeURIComponent(word)}&language=fr&target_lex=${lex.id}`;
log(`🔎 Appel API pour le lexique ${lex.id} avec l'URL : ${searchUrl}`);
const searchResponse = await fetch(searchUrl, {
headers: { Authorization: `Bearer ${authToken}` }
});
if (!searchResponse.ok) {
console.warn(`⚠️ Erreur pour le lexique ${lex.id} : ${searchResponse.statusText}`);
return { lexiconId: lex.id, entries: [] };
}
const entries = await searchResponse.json();
// Filtrage côté client : ne garder que les entrées dont entry.lexicon.id correspond exactement à lex.id
const filteredEntries = entries.filter(entry => {
if (!entry.lexicon) return false;
return Number(entry.lexicon.id) === Number(lex.id);
});
log(`Pour le lexique ${lex.id} (${lexiconMap.get(lex.id)}), entrées filtrées :`, filteredEntries);
return { lexiconId: lex.id, entries: filteredEntries };
});
const results = await Promise.all(definitionsPromises);
// 3) Parcourir les résultats et extraire les définitions
let allDefinitions = [];
results.forEach(result => {
log(`Pour le lexique ${result.lexiconId}, entrées filtrées :`, result.entries);
const lexiconId = result.lexiconId;
const sourceName = lexiconMap.get(lexiconId) || `Lexique #${lexiconId}`;
result.entries.forEach(entry => {
if (!entry.lexicon || Number(entry.lexicon.id) !== Number(lexiconId)) return;
let items = entry.attributes?.Items;
if (!Array.isArray(items)) {
if (typeof items === 'object' && items !== null) {
items = Object.values(items);
} else {
return;
}
}
items.forEach(item => {
const definitionsArray = item.Sense?.Definitions;
if (!Array.isArray(definitionsArray)) return;
definitionsArray.forEach(defObj => {
if (defObj.Def) {
allDefinitions.push({
source: sourceName,
text: defObj.Def,
lexiconId: lexiconId
});
}
});
});
});
});
log("Résultat final filtré :", allDefinitions);
return allDefinitions;
} catch (error) {
log("Erreur générale lors de la récupération des définitions :", error);
return [];
}
}
/**
* Récupère la définition d'un mot depuis le Wiktionnaire (fr).
* Retourne un tableau d'objets : [{ source: 'Wiktionnaire', text: '...' }]
* @param {string} word - Le mot dont on veut la définition.
* @returns {Promise<object[]>} - Un tableau d'objets contenant la définition.
*/
async function fetchWiktionaryDefinition(word) {
try {
const result = await browser.storage.local.get("accessToken");
authToken = result.accessToken;
if (!authToken) {
log(`🔍 Requête Wiktionnaire pour "${word}"...`);
if (!word || word.trim() === "") {
throw new Error("⚠️ Mot vide, impossible d'envoyer la requête.");
}
const wiktionaryURL = `https://fr.wiktionary.org/w/api.php?action=query&format=json&origin=*&prop=extracts&explaintext=true&redirects=1&titles=${encodeURIComponent(word)}`;
const response = await fetch(wiktionaryURL);
if (!response.ok) {
throw new Error(`❌ Erreur API Wiktionnaire: ${response.statusText}`);
}
const data = await response.json();
log("Réponse API (Wiktionnaire) :", data);
const pages = data.query?.pages;
const page = pages ? Object.values(pages)[0] : null;
const definitionText = page && page.extract
? page.extract.trim()
: "⚠️ Aucune définition trouvée sur le Wiktionnaire.";
log("Définition Wiktionnaire extraite :", definitionText);
return [
{
source: "Wiktionnaire",
text: definitionText
}
];
} else {
log(` Recherche de la définition pour : ${word}`);
// Récupération des données depuis l'API
const apiResponse = await wikiApiResponse(word);
log("Réponse brute de l'API :", apiResponse);
if (!Array.isArray(apiResponse) || apiResponse.length === 0) {
console.warn(`Aucune définition trouvée pour "${word}"`);
return []; // Retourne un tableau vide si aucune définition
}
// Formatage des données
const formattedData = formatDefinitionData(apiResponse);
log("Données formatées :", formattedData);
return [
{
source: "Wiktionnaire",
text: formattedData.definitions.length > 0 ? formattedData.definitions.join(" | ") : "⚠️ Aucune définition disponible."
}
];
}
} catch (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." }];
}
}
/**
* Récupère la définition d'un mot depuis l'API de BaLex (Wiktionnaire).
* @param {string} word - Le mot dont on veut la définition.
* @returns {Promise<object[]>} - Un tableau d'objets contenant la réponse de l'API.
*/
async function wikiApiResponse(word) {
const result = await browser.storage.local.get("accessToken");
authToken = result.accessToken;
// Construire l'URL de l'API avec le mot sélectionné
const wiktionaryApiUrl = `https://babalex.lezinter.net/api/wiktionary/search?graphy=${encodeURIComponent(word)}&language=fr`;
try {
const response = await fetch(wiktionaryApiUrl, {
method: 'GET',
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Erreur lors de la récupération de la définition depuis le Wiktionnaire : ${response.statusText}`);
}
const data = await response.json();
log(`Résultats du Wiktionnaire pour le mot "${word}" :`, data);
return data;
} catch (error) {
log('Erreur lors de la récupération de la définition depuis le Wiktionnaire :', error);
throw error;
}
}
/**
* Formate les données de la réponse de l'API de BaLex (Wiktionnaire).
* @param {object[]} apiResponse - La réponse de l'API de BaLex (Wiktionnaire).
* @returns {object} - Un objet contenant les données formatées.
*/
function formatDefinitionData(apiResponse) {
let formattedData = {
word: apiResponse[0]?.id.split("-").slice(2).join("-") || "",
pronunciations: [],
definitions: [],
examples: [],
translations: {},
};
apiResponse.forEach(entry => {
const wordData = entry[entry.id.split(".").slice(-1)[0]]; // Accéder aux données via la clé dynamique
// Ajout des prononciations
if (wordData.pronunciations) {
formattedData.pronunciations.push(...wordData.pronunciations);
}
// Ajout des définitions
if (wordData.senses) {
for (let senseKey in wordData.senses) {
let sense = wordData.senses[senseKey];
if (sense.Definitions) {
formattedData.definitions.push(...sense.Definitions.map(d => d.definition));
}
if (sense.Examples) {
formattedData.examples.push(...sense.Examples.map(e => e.example));
}
}
}
// Ajout des traductions
if (entry.translations) {
entry.translations.forEach(translation => {
if (!formattedData.translations[translation.lang_name]) {
formattedData.translations[translation.lang_name] = [];
}
formattedData.translations[translation.lang_name].push(translation.sense);
});
}
});
return formattedData;
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Affichage des définitions dans la barre latérale (lexiques + Wiktionnaire)
// ─────────────────────────────────────────────────────────────────────────────
const MAX_LENGTH = 200;
/**
* Affiche les définitions dans la barre latérale.
* @param {object[]} definitions - Les définitions à afficher.
*/
function displayDefinitions(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");
mesLexiquesList.innerHTML = "";
wiktionnaireList.innerHTML = "";
if (noLexiconDefinitionsContainer) noLexiconDefinitionsContainer.style.display = "none";
if (noWiktionaryDefinitionsContainer) noWiktionaryDefinitionsContainer.style.display = "none";
let hasLexiconDefinitions = false;
let hasWiktionaryDefinitions = false;
const lexiconGroups = {};
definitions.forEach(({ source, text }) => {
if (!source || !text) return;
const li = document.createElement("li");
let displayedText = text;
if (text.length > MAX_LENGTH) {
displayedText = text.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(text);
});
li.appendChild(document.createTextNode(displayedText));
li.appendChild(readMoreLink);
} else {
li.textContent = displayedText;
}
// Vérifier la source : Wiktionnaire/Lexiques
if (source === "Wiktionnaire") {
wiktionnaireList.appendChild(li);
hasWiktionaryDefinitions = true;
} else {
if (!lexiconGroups[source]) {
lexiconGroups[source] = [];
}
lexiconGroups[source].push(li);
hasLexiconDefinitions = true;
}
});
Object.entries(lexiconGroups).forEach(([lexiconName, definitionItems]) => {
const lexiconContainer = document.createElement("div");
lexiconContainer.className = "lexicon-section";
const lexiconHeader = document.createElement("div");
lexiconHeader.className = "lexicon-header";
lexiconHeader.textContent = lexiconName;
lexiconHeader.addEventListener("click", () => {
lexiconContent.classList.toggle("hidden");
});
const lexiconContent = document.createElement("ul");
lexiconContent.className = "lexicon-content hidden";
definitionItems.forEach(li => lexiconContent.appendChild(li));
lexiconContainer.appendChild(lexiconHeader);
lexiconContainer.appendChild(lexiconContent);
mesLexiquesList.appendChild(lexiconContainer);
});
if (!hasLexiconDefinitions && noLexiconDefinitionsContainer) {
if (!authToken) {
noLexiconDefinitionsContainer.textContent = "Veuillez vous connecter pour accéder aux définitions de vos lexiques.";
noLexiconDefinitionsContainer.style.textAlign = "center";
noLexiconDefinitionsContainer.style.fontStyle = "italic";
} else {
noLexiconDefinitionsContainer.textContent = "Aucune définition trouvée dans les lexiques.";
}
noLexiconDefinitionsContainer.style.display = "block";
}
if (!hasWiktionaryDefinitions && noWiktionaryDefinitionsContainer) {
noWiktionaryDefinitionsContainer.style.display = "block";
}
const mesLexiquesContainer = document.getElementById("mesLexiquesContainer");
if (mesLexiquesContainer) {
mesLexiquesContainer.style.display = hasLexiconDefinitions ? "block" : "none";
}
const wiktionnaireContainer = document.getElementById("wiktionnaireContainer");
if (wiktionnaireContainer) {
wiktionnaireContainer.style.display = hasWiktionaryDefinitions ? "block" : "none";
}
}
/**
* Récupère en parallèle :
* - les définitions des lexiques de l'utilisateur (fetchLexiconDefinitions)
* - la définition Wiktionnaire (fetchWiktionaryDefinition)
* Puis fusionne les résultats.
*/
async function combineDefinitions(word) {
log(`[combineDefinitions] Récupération des définitions pour "${word}"...`);
const results = await Promise.allSettled([
fetchLexiconDefinitions(word),
fetchWiktionaryDefinition(word)
]);
const lexiconDefinitions =
results[0].status === "fulfilled" ? results[0].value : [];
const wiktionaryDefinitions =
results[1].status === "fulfilled" ? results[1].value : [];
const allDefinitions = [...lexiconDefinitions, ...wiktionaryDefinitions];
log("[combineDefinitions] Résultat fusionné :", allDefinitions);
return allDefinitions;
}
/**
* Récupère et affiche toutes les définitions (lexiques + Wiktionnaire).
* @param {string} word - Le mot dont on veut les définitions.
*/
async function showDefinitions(word) {
log(`[showDefinitions] Recherche + affichage pour "${word}"...`);
const noDefinitionsContainer = document.getElementById("noDefinitionsContainer");
if (noDefinitionsContainer) {
noDefinitionsContainer.textContent = "Chargement des définitions...";
noDefinitionsContainer.style.display = "block";
}
try {
const allDefinitions = await combineDefinitions(word);
log("[showDefinitions] Définitions récupérées :", allDefinitions);
if (!allDefinitions || allDefinitions.length === 0) {
if (noDefinitionsContainer) {
noDefinitionsContainer.textContent = "⚠️ Aucune définition trouvée.";
}
return;
}
displayDefinitions(allDefinitions);
if (noDefinitionsContainer) {
noDefinitionsContainer.style.display = "none";
}
return allDefinitions;
} catch (error) {
log("[showDefinitions] Erreur : ", error);
if (noDefinitionsContainer) {
noDefinitionsContainer.textContent =
"Une erreur est survenue lors de la récupération des définitions.";
noDefinitionsContainer.style.display = "block";
}
return [];
}
}
/**
* Appel direct pour récupérer les définitions d'un mot uniquement via l'API
* (sans Wiktionnaire), puis gérer l'affichage d'erreur ou non.
* @param {string} word - Le mot dont on veut la définition.
*/
async function fetchDefinition(word) {
log(`🔍 Recherche de la définition pour '${word}'...`);
const noDefinitionsContainer = document.getElementById("noDefinitionsContainer");
if (!noDefinitionsContainer) {
log("Élément #noDefinitionsContainer introuvable.");
return;
}
try {
const definition = await fetchLexiconDefinitions(word);
log("Résultat API :", definition);
if (!definition || definition.length === 0) {
console.warn(`⚠️ Aucune définition trouvée pour '${word}'`);
noDefinitionsContainer.style.display = "block";
return;
}
noDefinitionsContainer.style.display = "none";
} catch (error) {
log("Erreur lors de la récupération de la définition :", error);
noDefinitionsContainer.style.display = "block";
}
}
/**
* Affiche les lexiques où le mot sélectionné est présent.
* @param {object[]} lexicons - Les lexiques où le mot est présent.
*/
function displayLexiconResults(lexicons) {
const resultDiv = document.getElementById("lexiconResult");
if (!resultDiv) return;
resultDiv.innerHTML = "";
if (!lexicons || lexicons.length === 0) {
resultDiv.textContent = "Ce mot n'est présent dans aucun lexique.";
return;
}
const title = document.createElement("p");
title.innerHTML = "Ce mot est présent dans le(s) lexique(s) suivant(s) :";
title.style.fontSize = "12px";
resultDiv.appendChild(title);
const ul = document.createElement("ul");
ul.style.paddingLeft = "20px";
lexicons.forEach((lexicon) => {
if (!lexicon) {
console.warn("⚠️ Lexique incorrect :", lexicon);
return;
}
if (!lexicon.id) {
console.warn("ID non défini :", lexicon.id);
return;
}
const lexiconName = lexicon.name || `Lexique #${lexicon.id}`;
const li = document.createElement("li");
li.innerHTML = `<strong>${lexiconName}</strong>`;
ul.appendChild(li);
log(`✅ Lexique ajouté : ${lexiconName} (ID: ${lexicon.id})`);
});
resultDiv.appendChild(ul);
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Gestion de la boîte modale pour afficher la définition complète du Wiktionnaire
// ─────────────────────────────────────────────────────────────────────────────
/**
* Ouvre la boîte modale pour afficher la définition complète du Wiktionnaire.
* @param {string} fullText - La définition complète du mot.
*/
function openDefinitionPopup(fullText) {
const modalOverlay = document.getElementById("modalOverlay");
const modalFullText = document.getElementById("modalFullText");
if (!modalOverlay || !modalFullText) {
log("Modal elements not found!");
return;
}
modalFullText.innerHTML = "<p>" + fullText.replace(/\n/g, "<br>") + "</p>";
modalOverlay.style.display = "flex";
}
/**
* Ferme la boîte modale et nettoie le contenu
* @returns {void}
*/
function closeDefinitionPopup() {
const modalOverlay = document.getElementById("modalOverlay");
const modalFullText = document.getElementById("modalFullText");
if (!modalOverlay || !modalFullText) return;
modalOverlay.style.display = "none";
modalFullText.innerHTML = "";
}
// ─────────────────────────────────────────────────────────────────────────────
// ▌ Exposition des fonctions pour un usage global
// ─────────────────────────────────────────────────────────────────────────────
window.fetchLexiconDefinitions = fetchLexiconDefinitions;
window.fetchWiktionaryDefinition = fetchWiktionaryDefinition;
window.wikiApiResponse = wikiApiResponse;
window.formatDefinitionData = formatDefinitionData;
window.displayDefinitions = displayDefinitions;
window.combineDefinitions = combineDefinitions;
window.showDefinitions = showDefinitions;
window.fetchDefinition = fetchDefinition;
window.displayLexiconResults = displayLexiconResults;
window.openDefinitionPopup = openDefinitionPopup;
window.closeDefinitionPopup = closeDefinitionPopup;