HTMLRewriter dynamic text replacement on all elements

Yes, .replace() only replaces that individual chunk of text. To deal with the split-chunk problem you’ll need to both buffer and remove the text chunks as you see them, until you see text.lastInTextNode === true. At that point, run the replacement code on the entire buffer, replace the last text chunk, and reset the buffer. (This is essentially the same as what @sandro suggested.)

Something like this should do the trick:

let handler = {
  text(text) {
    buffer += text.text

    if (text.lastInTextNode) {
      // We're done with this text node -- search and replace and reset.
      text.replace(buffer.replace(pattern, replacement))
      buffer = ''
    } else {
      // This wasn't the last text chunk, and we don't know if this chunk
      // will participate in a match. We must remove it so the client
      // doesn't see it.
      text.remove()
    }
  }
}

let response = new HTMLRewriter()
    .on("*", handler)
    .transform(response)

Something to keep in mind is that this will be defeated by opening elements:

<p>some.domain.to<strong>replace</strong></p>

This situation would be much more difficult to handle generically.

Harris

4 Likes