Estoy tratando de encontrar el código JavaScript correcto para una extensión de navegador que reemplaza la palabra "invierno" con la palabra "verano" en el texto de una página web.
Primer intento
Basado en esta publicación de blog , mi primer intento fue
function wordFilter() { let target = "winter"; let replace = "summer"; var html = document.querySelector('html'); var walker = document.createTreeWalker(html, NodeFilter.SHOW_TEXT); var node; while (node = walker.nextNode()) { node.nodeValue = node.nodeValue.replace(target, replace); } } wordFilter()Esto casi funciona. Reemplaza "invierno" con "verano", pero la palabra "invierno" aún aparece en la pantalla durante unos segundos antes de que se reemplace. Quiero que el filtro funcione desde el principio.
Como mínimo, este intento muestra que la configuración general de mi extensión y los permisos son correctos, por lo que cualquier otra falla debe ser un problema de código.
Segundo intento
Mi segundo intento se basó en esta respuesta a una publicación de StackOverflow. Es una publicación complicada, pero la sección " Enumeración ingenua de nodos agregados " es la más cercana a lo que quiero. El código de la función onMutation() busca elementos <h1> que contengan el texto de destino; solo como prueba de concepto, simplifiqué esa parte del código para aplicarla a todos los Elementos que son descendientes de un Elemento agregado. Si la carga DOM inicial califica como un conjunto de Mutaciones (que todavía no tengo claro, pero por el contexto parece ser el comportamiento esperado), entonces esto debería capturar cada Elemento y cada fragmento de texto en la página.
El código:
var observer = new MutationObserver(onMutation); observer.observe(document, { childList: true, // report added/removed nodes subtree: true, // observe any descendant elements }); function onMutation(mutations, observer) { for (var i = 0, len = mutations.length; i < len; i++) { var added = mutations[i].addedNodes; for (var j = 0, node; (node = added[j]); j++) { replaceText(node); } } } function replaceText(el) { let target_string = "winter"; let replacement_string = "summer"; const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT); for (let node; (node = walker.nextNode());) { const text = node.nodeValue; const newText = text.replace(target_string, replacement_string); if (text !== newText) { node.nodeValue = newText; } } }Esto no funciona en absoluto . Ninguna instancia de la palabra "invierno" se reemplaza con nada en ningún momento bajo ninguna condición.
Ahora estoy perdido. ¿Cómo reemplazo texto en una página web sin que aparezca el texto original antes del reemplazo?
Puedo confirmar que la selección de enfoques de wOxxOm , vinculada en mi publicación, funciona bien, incluido el que intenté usar.
El problema en este caso es el momento en que el navegador inserta el código.
manifest.json permite una clave "content_scripts" "run_at" para especificar cuándo el navegador debe cargar scripts de contenido (más en MDN ). El valor predeterminado es "document_idle" , que parece significar "siempre que tengas la oportunidad".
Con este valor predeterminado, el navegador cargaba la página y luego esperaba hasta que tenía un momento de inactividad para cargar el script de extensión para comenzar a buscar Mutaciones. Por lo tanto, MutationObserver pasó por alto todas las mutaciones iniciales y el script pareció no funcionar. (Aparte: ahora confío en que la carga inicial de cada elemento DOM cuenta como una mutación en el DOM).
Al especificar "run_at": "document_start" en manifest.json así:
"content_scripts": [ { "js": ["filename.js"], "run_at": "document_start" } ]el navegador ejecuta la secuencia de comandos para buscar mutaciones tan pronto como comienza a cargar el DOM, por lo que se detectan las mutaciones iniciales y el texto se cambia antes de cargar para que el "invierno" original nunca aparezca en la página antes de cambiarse a " el verano".
Un agradecimiento especial a @Jason Goemaat por la pista.