PHP wordwrap and non-printing strings

I am writing a class that needs a method and I can’t find a solution that completely passes all the unit tests I wrote, there are small gotchas with each solution.

The method is wrapping text (but with a catch) and has three parameters:

$text (a string that needs to be word wrapped)

$width (the width to wrap)

$markup - an array of markup strings that could be randomly placed inside of $text at various points and will be used to stylize the text later (and hence deleted).

For example, if there is a set of markup strings

[“!!”,”<lime>”]

(they can be anything), and the text

“This is a !!word!!! and this is some <lime>fruit<lime>.”

Wordwrap it to a width of let’s say 25 characters:

1234567890123456789012345
This is a word and this
is some fruit.

That would be the proper wrapping, but in order for wordwrap to work, I have to remove the markup and run PHP's wordwrap (which places \n's into the text string appropriately), then return the markup for later processing.

So, here is the problem, I would much rather use php’s wordwrap function than roll my own, as best practice. Here are the solutions that I have tried so far, but failed the unit tests in small ways:

Replace the $markup strings with ‘\a’ (escape sequence for beep -
using a character that I think would not be used), keep track of
which $markup strings go where in a separate array, run word wrap,
then put the $markup strings back in the now wordwrapped string

Fails because wordwrap counts the \a as one character, thus the more
markup, the worse wordwrap works

Keep an array of the markups and their positions in a separate array and try to rebuild the string

Getting better, but the positions I am storing are relative, meaning as I start to restore the markup values, the string is stretching and the position values aren’t valid

I was starting down the road of keeping two strings, the stripped and original, then marching down each string to rebuild the original, but that seems...ugly. Which leads me to believe that I must be missing something.

Any ideas?

Here is the second solution helper functions for stripping and replacing:

/**
* Takes the text and replaces all markup and store the markup and
* their positions in markupInText for later use
*
* @param $text
* @return string - the text with all the markup switched to /a
*/
public function stripMarkup($text) {

Getting better, but the positions I am storing are relative, meaning
as I start to restore the markup values, the string is stretching and
the position values aren’t valid

If you store them in their absolute positions in the original string, then you can recursively (i.e. after updating new string each time) add them back in their original positions. The only thing you'd have to account for would be the newly added \n characters by wordwrap. Assuming that the original string didn't contain any newline characters, while inserting, you would also count the number of \ns occurrences up to the positions you're inserting in and recalculate rest of the insertion points by adding that number.