diff --git a/src/utils/highlighting.js b/src/utils/highlighting.js index 4ffd5c91f25db834be3adf927f07354af57b4f5e..091579a9dd05cbd1efab5df32e1b71aaf9b73ea2 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