Proposal: wrap combine mode
Introduction
The main idea of this library is to split a match into portions when it crosses element boundaries.
Note: I will refer to only the
inputandoutputas a shorthand for calling the following function:function wrap(input) { var el = document.createElement('div'); el.innerHTML = input; findAndReplaceDOMText(el, { find: /\w+/g, wrap: 'w' }); var output = el.innerHTML; return output; }
As expected, the following code splits the matched word b1b2 among two <w> elements:
input: a b1<i>b2 c</i> <i>d e</i> output: <w>a</w> <w>b1</w><i><w>b2</w> <w>c</w></i> <i><w>d</w> <w>e</w></i>
However, if the entire match corresponds to properly-nested HTML, then it is possible to just use a single element to wrap the match. So instead of the following:
input: a b1<i>b2</i> <i>c d</i> output: <w>a</w> <w>b1</w><i><w>b2</w></i> <i><w>c</w> <w>d</w></i>
the two portions b1 and b2 could be combined as such:
output: <w>a</w> <w>b1<i>b2</i></w> <i><w>c</w> <w>d</w></i>
Proposal
I think it could be useful to add this behavior in a new option called wrapCombineMode.
| wrapCombineMode | behavior |
|---|---|
separate |
Original behavior. Each leaf (portion) of a match gets wrapped. |
combine |
If the entire match encompasses balanced HTML, it is wrapped. Otherwise, fall back to separate. |
split |
Force the entire match to be wrapped as a unit. (If the entire match encompasses balanced HTML, it is wrapped. Otherwise, split up elements that cross the edges of the match.) |
Here are some test cases (spaced out for legibility):
Basic balanced
input: <i>aa</i>a a<i>aa</i> a<i>a</i>a separate: <i><w>aa</w></i><w>a</w> <w>a</w><i><w>aa</w></i> <w>a</w><i><w>a</w></i><w>a</w> combine: <w><i>aa</i>a</w> <w>a<i>aa</i></w> <w>a<i>a</i>a</w> split: <w><i>aa</i>a</w> <w>a<i>aa</i></w> <w>a<i>a</i>a</w>
Complex balanced
input: a<i><i>a</i></i>a <i>a<i>a</i></i>a <i>a</i>a<i>a</i> separate: <w>a</w><i><i><w>a</w></i></i><w>a</w> <i><w>a</w><i><w>a</w></i></i><w>a</w> <i><w>a</w></i><w>a</w><i><w>a</w></i> combine: <w>a<i><i>a</i></i>a</w> <w><i>a<i>a</i></i>a</w> <w><i>a</i>a<i>a</i></w> split: <w>a<i><i>a</i></i>a</w> <w><i>a<i>a</i></i>a</w> <w><i>a</i>a<i>a</i></w>
Unbalanced
input: aa<i>a a</i>a<i>a a</i>aa separate: <w>aa</w><i><w>a</w> <w>a</w></i><w>a</w><i><w>a</w> <w>a</w></i><w>aa</w> combine: <w>aa</w><i><w>a</w> <w>a</w></i><w>a</w><i><w>a</w> <w>a</w></i><w>aa</w> split: <w>aa<i>a</i></w> <w><i>a</i>a<i>a</i></w> <w><i>a</i>aa</w>
Thanks for writing this up. 👍 Seems like a good idea! I'm pondering a slight re-write of the lib (the code is getting a bit difficult to maintain), and this definitely seems like a feature worth putting in (especially the 'combine' mode). Not sure of timeline, but shall update this ticket when the time comes.
FWIW, I had ported my code to Fibrio so I could use it easily on the server. The author of that project also refactored the code, so it might be helpful to look at.
@hftf @padolsey Any progress on this feature. It would be an amazing feature.
I noticed back in 2012 that @padolsey mentioned it as 1 of 2 solutions to solve the problem in https://j11y.io/javascript/replacing-text-in-the-dom-solved/
@hftf Are you aware of any forks that implement this feature?
@pjebs I am not aware of any, no. In my opinion, this is the main feature I would expect to bring the project up to a 1.0 milestone.
I have created a $30 USD bounty for anyone who can solve this:
https://thehonestscoop.com/docs/gutter/bounty/
Do you think this may be relevant: https://github.com/bfred-it/zip-text-nodes (in some way)?
Would love this too!