Skip to content

Instantly share code, notes, and snippets.

@drFabio
Last active August 29, 2015 13:56
Show Gist options
  • Save drFabio/9128225 to your computer and use it in GitHub Desktop.
Save drFabio/9128225 to your computer and use it in GitHub Desktop.
HTML PHP Truncator using tidy. IT counts the texts chars to N chars, if the word didn't end yet it ends, and it closes the html tags that it's left open
echo '<pre>';
$subject='<p>Lorem</p>
<pre class="brush:js;auto-links:false;toolbar:false" contenteditable="false"> //$(\'textarea[name=html]\').editor();
tinymce.init({selector:\'textarea[name=html]\',
plugins: [ // plugins list
"preview sh4tinymce wordcount"
],
toolbar: "undo redo | sh4tinymce | preview" // toolbar list
});</pre>
<p> Ipsum dolor sit amet</p>';
$hTruncator=new HtmlTruncator($subject,'<a href="#"> More ... </a>');
echo htmlspecialchars($hTruncator->truncateHtml(10));
<?php
/**
* Truncate an html to at Least N characters, close the remaining tags, and end the world in which it stopped.
* Optionally preserve syntaxHighlighter code
* @author Fabio Oliveira Costa <[email protected]>
*/
class HtmlTruncator{
protected $_tidy;
protected $_alwaysShowSyntaxHighlighter;
protected $_moreSufix;
/**
*
* @param string $raw the raw HTML we want to truncate
* @param int $maxLength the max length of simple text we want
* @param string $moreSufix the sufix for more if any
*/
public function __construct($raw,$moreSufix='',$alwaysShowSyntaxHighlighter=true){
$this->_tidy=tidy_parse_string($raw)->body();
$this->_moreSufix=$moreSufix;
$this->_alwaysShowSyntaxHighlighter=$alwaysShowSyntaxHighlighter;
}
/**
* Make a left tag
* @param tidyNode $tidy [description]
* @return string
*/
protected static function _makeLeftTag(tidyNode $tidy){
if($tidy->isText()){
return '';
}
$atrs='';
if(!empty($tidy->attribute)){
foreach ($tidy->attribute as $k => $v) {
$atrs.=' '.$k.'="'.$v.'"';
}
}
return '<'.$tidy->name.$atrs.'>';
}
protected static function _makeRightTag(tidyNode $tidy){
if($tidy->isText()){
return '';
}
return '</'.$tidy->name.'>';
}
/**
* Truncate the html that this HtmlTruncator represent to more or less length characters
* @param int $length
* @return string the truncated html
*/
public function truncateHtml($length){
$finished=false;
$counting=0;
$excerpt='';
$ret= $this->_truncateHtml($this->_tidy,$length,$finished,$counting,$excerpt);
if($finished){
return $ret.$this->_moreSufix;
}
else{
return $ret;
}
}
/**
* Check whether this node is the syntax highlighter node
* @param tidyNode $tidy [description]
* @return boolean [description]
*/
protected static function _isSyntaxHighlighter(tidyNode $tidy){
if($tidy->name==='pre'){
if(array_key_exists('class', $tidy->attribute) && strrpos($tidy->attribute['class'], 'brush')!==false){
return true;
}
}
return false;
}
protected function _truncateHtml(tidyNode $tidy,$length,&$finished,&$counting) {
if(empty($tidy)){
return '';
}
$excerpt='';
if($this->_alwaysShowSyntaxHighlighter && static::_isSyntaxHighlighter($tidy)){
return static::_makeLeftTag($tidy).$tidy->value.static::_makeRightTag($tidy);
}
else if($tidy->hasChildren()){
foreach($tidy->child as $c){
$excerpt.=$this->_truncateHtml($c,$length,$finished,$counting);
if($finished){
break;
}
}
if($tidy->name==='body'){
return $excerpt;
}
return static::_makeLeftTag($tidy).$excerpt.static::_makeRightTag($tidy);
}
else{
if($tidy->isText()){
$text=$tidy->value;
$size=strlen($text);
if($counting+$size>=$length){
//First space after the minimum chars
$lastSpace=strpos($text,' ',$length-$counting);
if($lastSpace!==false){
$text=substr($text, 0,$lastSpace);
}
$size=$lastSpace;
$finished=true;
}
$counting+=$size;
return $text;
}
return static::_makeLeftTag($tidy).static::_makeRightTag($tidy);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment