<?php
$string = '<span class="test">Lorem <i>ipsum</i> <b id="the-b">dolor</b> sit amet!</span>' ;
print HtmlTruncate:: truncate ( $string , 10 ) . PHP_EOL;
class HtmlTruncate
{
const READ_STRING = 1 ;
const READ_OPEN_TAG = 2 ;
const READ_CLOSE_TAG = 3 ;
public static function truncate( $string , $length )
{
$left = $length ;
$state = self :: READ_STRING ;
$trunc = '' ;
$tags = 0 ;
for ( $i = 0 ; $i < strlen ( $string ) ; $i ++ ) { $c = $string [ $i ] ;
switch ( $state ) {
case self :: READ_STRING :
if ( $c == '<' ) {
if ( $string [ $i + 1 ] == '/' ) {
$state = self :: READ_CLOSE_TAG ;
} else {
$state = self :: READ_OPEN_TAG ;
$tags += $left ? 0 : 1 ;
}
$i --;
continue ;
} else {
if ( $left ) {
$trunc .= $c ;
} else {
print "skip: " . $c . PHP_EOL;
}
}
break ;
case self :: READ_OPEN_TAG :
if ( $left ) {
$trunc .= $c ;
}
if ( $c == '>' ) {
$state = self :: READ_STRING ;
}
break ;
case self :: READ_CLOSE_TAG :
if ( $left || ! $tags ) {
$trunc .= $c ;
}
if ( $c == '>' ) {
$state = self :: READ_STRING ;
}
break ;
}
}
return $trunc ;
}
}
PD9waHAKJHN0cmluZyA9ICc8c3BhbiBjbGFzcz0idGVzdCI+TG9yZW0gPGk+aXBzdW08L2k+IDxiIGlkPSJ0aGUtYiI+ZG9sb3I8L2I+IHNpdCBhbWV0ITwvc3Bhbj4nOwpwcmludCBIdG1sVHJ1bmNhdGU6OnRydW5jYXRlKCRzdHJpbmcsIDEwKSAuIFBIUF9FT0w7CiAKY2xhc3MgSHRtbFRydW5jYXRlCnsKICAgIGNvbnN0IFJFQURfU1RSSU5HID0gMTsKICAgIGNvbnN0IFJFQURfT1BFTl9UQUcgPSAyOwogICAgY29uc3QgUkVBRF9DTE9TRV9UQUcgPSAzOwogCiAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHRydW5jYXRlKCRzdHJpbmcsICRsZW5ndGgpCiAgICB7CiAKICAgICAgICAkbGVmdCA9ICRsZW5ndGg7CiAgICAgICAgJHN0YXRlID0gc2VsZjo6UkVBRF9TVFJJTkc7CiAgICAgICAgJHRydW5jID0gJyc7CiAgICAgICAgJHRhZ3MgPSAwOwogCiAgICAgICAgZm9yICgkaSA9IDA7ICRpIDwgc3RybGVuKCRzdHJpbmcpOyAkaSsrKSB7CiAgICAgICAgICAgICRjID0gJHN0cmluZ1skaV07CiAKICAgICAgICAgICAgc3dpdGNoICgkc3RhdGUpIHsKICAgICAgICAgICAgICAgIGNhc2Ugc2VsZjo6UkVBRF9TVFJJTkc6CiAgICAgICAgICAgICAgICAgICAgaWYgKCRjID09ICc8JykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoJHN0cmluZ1skaSsxXSA9PSAnLycpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzdGF0ZSA9IHNlbGY6OlJFQURfQ0xPU0VfVEFHOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgJHN0YXRlID0gc2VsZjo6UkVBRF9PUEVOX1RBRzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0YWdzICs9ICRsZWZ0ID8gMCA6IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgJGktLTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCRsZWZ0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdHJ1bmMgLj0gJGM7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludCAic2tpcDogIiAuICRjIC4gUEhQX0VPTDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAkbGVmdCA9IG1heCgkbGVmdC0xLCAwKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAKICAgICAgICAgICAgICAgIGNhc2Ugc2VsZjo6UkVBRF9PUEVOX1RBRzoKICAgICAgICAgICAgICAgICAgICBpZiAoJGxlZnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJHRydW5jIC49ICRjOwogICAgICAgICAgICAgICAgICAgIH0KIAogICAgICAgICAgICAgICAgICAgIGlmICgkYyA9PSAnPicpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJHN0YXRlID0gc2VsZjo6UkVBRF9TVFJJTkc7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogCiAgICAgICAgICAgICAgICBjYXNlIHNlbGY6OlJFQURfQ0xPU0VfVEFHOgogICAgICAgICAgICAgICAgICAgIGlmICgkbGVmdCB8fCAhJHRhZ3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJHRydW5jIC49ICRjOwogICAgICAgICAgICAgICAgICAgIH0KIAogICAgICAgICAgICAgICAgICAgIGlmICgkYyA9PSAnPicpIHsKICAgICAgICAgICAgICAgICAgICAgICAgJHRhZ3MgPSBtYXgoJHRhZ3MtMSwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICRzdGF0ZSA9IHNlbGY6OlJFQURfU1RSSU5HOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KIAogICAgICAgIHJldHVybiAkdHJ1bmM7CiAgICB9Cn0=