Разделить каждое слово, присутствующее в различных тегах веб-страницы - PullRequest
0 голосов
/ 30 сентября 2019

по этой ссылке я опубликовал похожий вопрос, но теперь мне нужно улучшить функцию, которую я хочу. Пожалуйста, прочитайте, чтобы понять: Как разбить каждое слово на

(html) с учетом других элементов внутри

. Первое решение для пользователя великолепно и хорошо работает, если я рассматриваю только теги <p>, но теперь я должен рассмотреть все следующие теги, которые могут быть на веб-странице:span, p, h1, h2, h3, h4, h5, h6, em, strong, q, abbr, acronym, address, li, dd, dt, a, td, th, caption, legend, label, option. Я всегда должен разбивать каждое отдельное слово внутри тега и помещать вокруг него тег <span> (es: <h2> ...<span> word </span>...</h2>, но теперь возникает сложность:некоторые теги могут быть одни или внутри других тегов (например, тег <a> может быть снаружи или внутри тега <p>, и многие другие теги из списка выше с тем же использованием). Таким образом, предлагаемое решение не является оптимальным, поскольку вставьте два разных тега <span> вокруг одного и того же слова, один из-за <p> и один из-за <a> при запуске кода. Я объясню это более сложным примером и различными элементами тега:

Изобретенная часть html-страницы:

<a> Text of lorem ipum </a>
<h2> Lorem <span>ipsum</span> dolor <em>sit</em> amet, <a>consectetur</a> adipiscing <strong>elit</strong> </h2>

Предлагаемое решение делает:

тег без посторонних, работает корректно

<a>                            
   <span>Text<span>    
   <span>of<span>
   <span>lorem<span>
   <span>ipum<span>
</a>

тег скто-то внутри, плохо работает

<h2>                                       
   <span><span><span> Lorem </span></span></span>        //3times
   <span(original)><span><span><span> ipsum </span></span></span></span(original)>  //3times + original one
   <span><span><span> dolor </span></span></span>               //3times
   <em><span><span><span> sit </span></span></span></em>        //3times
   <span><span><span> amet </span></span></span>                //3times
   <a><span><span><span><span> consectetur </span></span></span></span></a>     //4times
   <span><span><span>adipiscing</span></span></span>                //3times
   <strong><span><span><span>elit</span></span></span></strong>      //3times
</h2>

Работает рекурсивно, поэтому создает разные для разных встречаемых тегов, но я хочу добиться результата:

<a>                            
   <span>Text<span>    
   <span>of<span>
   <span>lorem<span>
   <span>ipum<span>
</a>

<h2> 
   <span>Lorem</span>       
   <span(original)><span>ipsum</span></span(original)> 
   <span>dolor</span>              
   <em><span>sit</span></em>      
   <span>amet</span>               
   <a><span>consectetur</span></a>    
   <span>adipiscing</span>             
   <strong><span>elit</span></strong>  
</h2>

Не знаюзнать, как редактировать приведенный ниже код, чтобы избежать копирования <span> во время рекурсии или в случае, если она уже существует.

Код решения, используемого до сих пор (для улучшения):

const span = document.createElement('span');
span.className = 'foo';
span.appendChild(document.createTextNode(''));

for (const p of document.getElementsByTagName('p')) { //I've tried to change in document.querySelectorAll('p,h1,h2,h3,h4,h5,h6,em,strong,q,abbr,acronym,address,li,dd,dt,a,td,th,caption,legend,label,option') 
    const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
    const textNodes = [];
    for (let n; (n = walker.nextNode());) {
        if (n.nodeValue.trim()) {
            textNodes.push(n);
        }
    }
    for (const n of textNodes) {
        const fragment = document.createDocumentFragment();
        for (const s of n.nodeValue.split(/(\s+)/)) {
            if (s.trim()) {
                span.firstChild.nodeValue = s;
                fragment.appendChild(span.cloneNode(true));
            } else {
                fragment.appendChild(document.createTextNode(s));
            }
        }
        n.parentNode.replaceChild(fragment, n);
    }
}

Спасибо за помощь!

1 Ответ

0 голосов
/ 30 сентября 2019

Вы можете получить внешние элементы (я использовал outerElement, чтобы заставить работать фрагмент, но вы можете использовать нужный тег) innerHTML и разбить его на слова. Затем, используя Array.map(), вы можете обернуть их тегами <span>.

const documentChildren = document.getElementById('outerElement').children;

for (let node of documentChildren) {

  node.innerHTML = node.innerText.match(/\S+/g).map(text => `<span>${text}</span>`).join('');

}
span{
  display: block; // only to show spans separate
}
<div id="outerElement">
  <a> Text of lorem ipum </a>
  <h2>
    Lorem
    <span>ipsum</span> dolor <em>sit</em> amet, <a>consectetur</a> adipiscing <strong>elit</strong> </h2>
</div>

Надеюсь, я понимаю ваш вопрос, и это поможет вам.

...