start underline bold here before italic italic, broken bold again end underline italic bold italic still italic bold
| a | b | c |
| d | e | f |
<p><u>start underline <b>bold here</b> before italic <i>italic, broken <b>bold again</b> end underline</u> italic <b>bold italic</b> still italic </i><b>bold</b></p>
<table>
<tr>
<td>a</td>
<td><u>b</td>
<td>c</td>
</tr>
<tr>
<td>d</td>
<td>e</u></td>
<td>f</td>
</tr>
</table>start underline bold here before italic italic, broken bold again end underline italic bold italic still italic bold
| a | b | c |
| d | e | f |
<p><u>start underline <b>bold here</b> before italic <i>italic, broken <b>bold again</b> end underline</i></u><i> italic </i><b><i>bold italic</i></b><i> still italic </i><b>bold</b></p>
<table>
<tr>
<td>a</td>
<td><u>b</u></td>
<td><u>c</u></td>
</tr>
<tr>
<td><u>d</u></td>
<td><u>e</u></td>
<td>f</td>
</tr>
</table>
<?php
$input = '<p><u>start underline <b>bold here</b> before italic <i>italic, broken <b>bold again</b> end underline</u> italic <b>bold italic</b> still italic </i><b>bold</b></p>
<table>
<tr>
<td>a</td>
<td><u>b</td>
<td>c</td>
</tr>
<tr>
<td>d</td>
<td>e</u></td>
<td>f</td>
</tr>
</table>';
echo '<h1>Original</h1>';
echo $input.'<br/><pre>';
echo htmlentities($input);
echo '</pre>';
$parts = preg_split('!(</?[a-zA-Z]+)!', $input, -1, PREG_SPLIT_DELIM_CAPTURE);
$tags = array();
$isTag = false;
$output = '';
foreach ($parts as $num => $part) {
if ($isTag) {
if ($part[1] == '/') {
$tag = substr($part, 2);
if (false !== array_search($tag, $tags)) {
while (($curTag = array_pop($tags)) && $tag != $curTag) {
$output .= '</'.$curTag.'>';
}
} else {
$curTag = '';
}
if (!$curTag) {
//$pos = strrpos($output, '>');
//$output = substr($output, 0, $pos + 1).'<'.$tag.'>'.substr($output, $pos + 1);
$pos = strrpos($output, '</'.$tag.'>');
$subParts = preg_split('!(</?[^>]*>)!i', substr($output, $pos + strlen($tag) + 3), -1, PREG_SPLIT_DELIM_CAPTURE);
$output = substr($output, 0, $pos + strlen($tag) + 3);
$isSubTag = false;
$maxSub = count($subParts) - 1;
foreach ($subParts as $subNum => $subPart) {
if (!$isSubTag && (strlen(trim($subPart)) || $subNum == $maxSub)) {
$output .= '<'.$tag.'>'.$subPart.($subNum == $maxSub ? '' : '</'.$tag.'>');
} else {
$output .= $subPart;
}
$isSubTag = !$isSubTag;
}
/*$output = substr($output, 0, $pos + strlen($tag) + 4).
preg_replace('!(^/?[^>]*>)!',
'\1<'.$tag.'>',
preg_replace('!(</?[^>]*>)!',
'</'.$tag.'>\1<'.$tag.'>',
substr($output, $pos + strlen($tag) + 4)));*/
}
} else {
$tag = substr($part, 1);
$tags[] = $tag;
}
$output .= $part;
} else {
$output .= $part;
}
$isTag = !$isTag;
}
echo '<h1>Fixed</h1>';
echo $output.'<br/><pre>';
echo htmlentities($output).'</pre><br/><br/>';
highlight_file(__FILE__);
?>