Tengo una matriz de términos (Objetos) que contienen term.name, term.id y term.description, por lo que se ve así:
const terms = [{id: 1, name: "First", description: "First Item"}, {id: 2, name: "Second", description: "Second Item"}, {id: 3, name: "Knowledge Base", description: "Test"}, {id: 4, name: "Base", description: "Another Test"}]Y tengo un HTML que se ve así:
<div class="parent"> <p>This is the first text node containing First and Second term name.</p> <div> <h1>Title</h1> <p>Knowledge Base is important. First is also important, base should be good</p> </div> </div>Lo que estoy tratando de lograr es recorrer cada textNode y verificar si alguno de los términos de la matriz está presente en el nodo, si el término está presente, envuelva esa palabra en una etiqueta. Además, si tenemos dos términos, como base de conocimiento y base, simplemente ajuste el término más largo y omita el más corto. Así por ejemplo:
<p>Knowledge Base</p> should look like <p><span>Knowledge Base</span></p>y no como:
<p>Knowledge Base</p> should look like <p><span>Knowledge <span>Base</span></span></p>Aquí está la función para obtener todos los nodos de texto y lo que he hecho hasta ahora:
getAllTextNodes(element) { let node; let nodes = []; let walk = document.createTreeWalker(element,NodeFilter.SHOW_TEXT,null,false); while (node = walk.nextNode()) nodes.push(node); return nodes; } const allNodes = getAllTextNodes(document.querySelector('.parent')); const terms = [{id: 1, name: "First"}, {id: 2, name: "Second"}, {id: 3, name: "Knowledge Base"}, {id: 4, name: "Base"}] Array.from(allNodes).forEach(node => { terms.forEach(term => { if (node.parentNode.textContent.includes(term.name)) { node.parentNode.innerHTML = node.parentNode.innerHTML.replace(term.name, `<span>${term.name}</span>`) } }) }) <div class="parent"> <p>This is the first text node containing First and Second term name.</p> <div> <h1>Title</h1> <p>Knowledge Base is important. First is also important, base should be good</p> </div> </div>