Solution 1 :

You can use indexOf to look for all occurrences of a string in the textContent of the element and use appendChild to add anchor elements.

function addLink(el, text){
  let t = el.textContent;
  el.textContent = '';
  let idx, prev = 0;
  while((idx = t.indexOf(text, prev)) !== -1){
    el.append(t.slice(prev, idx));
    const a = document.createElement('a');
    a.href = '/' + text;
    a.textContent = text;
    prev = idx + text.length;
addLink(document.querySelector('p'), 'ipsum');
<p>Lorem ipsum dolor sit amet</p>

Solution 2 :

You can split apart the text content by a ipsum regular expression, then iterate over each match: for each segment which is not ipsum, insert a text node containing the text for that segment. For ipsum, insert a <span> and assign to its textContent.

const p = document.querySelector('p');
const pattern = new RegExp(/(.*?)(ipsum)/, 'gi');
const matches = p.textContent.split(pattern).filter(Boolean);

p.textContent = '';
for (const match of matches) {
  if (match === 'ipsum') {
    const a = p.appendChild(document.createElement('a'));
    a.textContent = match;
    a.href = '/ipsum';
  } else {
<p>Lorem ipsum dolor sit amet</p>

Problem :

I need to highlight text in an HTML document with JavaScript that will be part of a webextension. The use of .innerHTML would cause a rejection in the review process. See innerHTML Security considerations.

I need to highlight text as a link:

<p>Lorem ipsum dolor sit amet</p>


<p>Lorem <a href="/ipsum">ipsum</a> dolor sit amet</p>

How can I pull this off without using .innerHTML?


Comment posted by Matthew Moran

Can you share what you currently are trying with

Comment posted by Alexander

nothing. I haven’t written this function jet. It’s just an example

Comment posted by Alexander

both anwers are good and they solve the initial problem. Thank you. I was just wondering line breaks (