estoy pegando a continuación una clase PHP que escribí hace un tiempo largo , pero yo sé que funciona. no es exactamente lo que buscas, ya que se trata de palabras en lugar de un recuento de personajes, pero creo que es bastante cercano y que a alguien le puede resultar útil.
class HtmlWordManipulator
{
var $stack = array();
function truncate($text, $num=50)
{
if (preg_match_all('/\s+/', $text, $junk) <= $num) return $text;
$text = preg_replace_callback('/(<\/?[^>]+\s+[^>]*>)/','_truncateProtect', $text);
$words = 0;
$out = array();
$text = str_replace('<',' <',str_replace('>','> ',$text));
$toks = preg_split('/\s+/', $text);
foreach ($toks as $tok)
{
if (preg_match_all('/<(\/?[^\x01>]+)([^>]*)>/',$tok,$matches,PREG_SET_ORDER))
foreach ($matches as $tag) $this->_recordTag($tag[1], $tag[2]);
$out[] = trim($tok);
if (! preg_match('/^(<[^>]+>)+$/', $tok))
{
if (!strpos($tok,'=') && !strpos($tok,'<') && strlen(trim(strip_tags($tok))) > 0)
{
++$words;
}
else
{
/*
echo '<hr />';
echo htmlentities('failed: '.$tok).'<br /)>';
echo htmlentities('has equals: '.strpos($tok,'=')).'<br />';
echo htmlentities('has greater than: '.strpos($tok,'<')).'<br />';
echo htmlentities('strip tags: '.strip_tags($tok)).'<br />';
echo str_word_count($text);
*/
}
}
if ($words > $num) break;
}
$truncate = $this->_truncateRestore(implode(' ', $out));
return $truncate;
}
function restoreTags($text)
{
foreach ($this->stack as $tag) $text .= "</$tag>";
return $text;
}
private function _truncateProtect($match)
{
return preg_replace('/\s/', "\x01", $match[0]);
}
private function _truncateRestore($strings)
{
return preg_replace('/\x01/', ' ', $strings);
}
private function _recordTag($tag, $args)
{
// XHTML
if (strlen($args) and $args[strlen($args) - 1] == '/') return;
else if ($tag[0] == '/')
{
$tag = substr($tag, 1);
for ($i=count($this->stack) -1; $i >= 0; $i--) {
if ($this->stack[$i] == $tag) {
array_splice($this->stack, $i, 1);
return;
}
}
return;
}
else if (in_array($tag, array('p', 'li', 'ul', 'ol', 'div', 'span', 'a')))
$this->stack[] = $tag;
else return;
}
}
truncado es lo que quiere, y se le pasa el html y el número de palabras que desea que recorta a. ignora html mientras cuenta las palabras, pero luego vuelve a envolver todo en html, incluso al cerrar las etiquetas finales debido al truncamiento.
por favor no me juzguen sobre la falta total de principios oop. Era joven y estúpido.
edición:
por lo que resulta el uso es de la misma familia:
$content = $manipulator->restoreTags($manipulator->truncate($myHtml,$numOfWords));
estúpida decisión de diseño. Sin embargo, me permitió inyectar html dentro de las etiquetas sin cerrar.
¿Desea que el texto se cuente sin html, pero luego se devuelve envuelto en el html original? –
sí. Quiero que se devuelva envuelto en html para que pueda mostrarlo en una página. – Vin
He agregado un poco de Pseudo a mi respuesta anterior, espero que pueda apuntar en la dirección correcta. Realmente lo siento, no tengo tiempo para trabajar en hacer las cosas bien, pero cruzar los dedos te hará superar el obstáculo. ¡Publica tu respuesta si encuentras la solución! Me encantaría ver –