Convert br tags to span tags

Have you ever needed to convert the string immediately before br tags, wrapping it in span tags? Me too, oddly.

I’m sure there’s a regex way to do this but at the time of writing my brain wasn’t willing to entertain the idea, so here’s a very simple way to achieve it using simple string and array functions.

/**
 * Replace linebreaks with span tags
 *
 * Wraps each string immediately before a linebreak in span tags and removes the linebreak.
 *
 * @param string $string        Original string that may have linebreaks (\r\n\
\
)
 * @param string $span_class    Styling class for span tags
 * @return string               HTML string with linebreaks replaced with span tags
 */
function nl2span($string = '', $span_class = 'span') : string {
    // standardise line breaks
    $nl = "\n";
    $string = str_replace(["\r\n", "\r", "
", "
"], $nl, $string );

    // just return the original string if there aren't any linebreaks
    if (!str_contains($string, $nl)) return $string;

    // remove contiguous linebreaks
    $string = preg_replace( "/$nl+/", $nl, $string );

    // convert string to array of parts
    $string_to_array = explode($nl, $string);

    // pop the last part as it will not be wrapped in a span
    $after_nl = array_pop($string_to_array);

    // declare var for spanned elements
    $array_to_string = '';

    // build spanned elements
    foreach ($string_to_array as $index => $part) {
        // create a unique span class for each part
        $unique_span = (int) $index + 1;
        $array_to_string .= sprintf(
            '<span class="%1$s %1$s-%2$s">%3$s</span>',
            $span_class,
            $unique_span,
            $part);
    }

    // cleanup (if you care to)
    unset($nl);
    unset($string);
    unset($string_to_array);

    // append the last part and return
    return $array_to_string . $after_nl;
}

Side note:

str_contains is an Illuminate helper function. If you don’t use this Illuminate, then replace it in the code above with the following code:

// just return the original string if there aren't any linebreaks
$has_breaks = false;
foreach ((array) $string as $needle) {
    if ($needle !== '' && mb_strpos($string, $needle) !== false) {
        $has_breaks = true;
    }
}
if (!$has_breaks) return $string; 

Conclusion

So there it is. If you ever come across the odd occasion where you need to wrap the string immediately before a break tag with span tag, then just drop this into your project’s PHP code and you’re good to go! Or get in touch and we’ll gladly assist.

Reply