[ic] Filter tag and html - Patch for Interpolate.pm
Sandy Thomson
sandy at scotwebshops.com
Thu Mar 24 10:38:41 EST 2005
Hi,
We were using the character limit thing on the filter tag, and were
getting frustrated that it treated html entites as > 1 characters, and
if there were html tags in the string, it didnt close the tags.
Examples:
[filter 20.]The sheep the sheep theyre gaining on me![/filter] = 'The
sheep the sheep ...'
[filter 20.]The sheep <strong>the sheep theyre gaining on me![/filter] =
'The sheep <strong>th ...'
[filter 20.]The sheep the she  theyre gaining on me![/filter] = 'The
sheep the she&nb...'
Basically this can leave bad html code that will not validate.
After a morning of programming, I have made this code correctly close
open html tags (ignores self closed tags) and treat html entites as one
character.
Examples:
[filter 20.]The sheep the sheep theyre gaining on me![/filter] = 'The
sheep the sheep …'
[filter 20.]The sheep <strong>the sheep theyre gaining on
me</strong>![/filter] = 'The sheep <strong>the sheep </strong>…'
[filter 20.]The sheep <strong>the she  theyre gaining on
me</strong>![/filter] = 'The sheep <strong>the sheep
</strong>…'
[filter 20.]The <p />sheep <strong>the she  theyre gaining on
me</strong>![/filter] = 'The <p />sheep <strong>the sheep
</strong>…'
Nested html tags should work ok too.
As my Interpolate.pm is already hacked to bits, I actually cant provide
a patch so here is the code.
Look for: sub filter_value {
And then a few if statements down substitute:
if (/^(\d+)(\.?)$/) {
substr($value, $1) = $2 ? '...' : ''
if length($value) > $1;
next;
}
For this:
if (/^(\d+)(\.?)$/) {
if(length($value) > $1){
my @tagstoclose;
my $charcount=0;
my $charlimit=$1;
my $original_val=$value;
my $tempval;
$value='';
while($original_val=~/<(.*?)>/){
$tempval.=$`;
$original_val=$';
$value.=$`;
my $matched=$1;
$tempval=~s/&\w*;/./g;
$charcount=length($tempval);
if($charcount>=$charlimit){
last;
}
if($matched=~/^\//){
if(length($tempval)<$charlimit){
pop @tagstoclose;
$value.="<".$matched.">";
}
}else{
$value.="<".$matched.">";
$matched=~/^(\w*)/;
my $tag=$1;
push @tagstoclose, $tag
if($matched!~/\/$/);
}
}
if($charcount>$charlimit){
#chop down value
print "chopping val by
".-($charcount-$charlimit)." chars \n";
print $value."\n";
my $html_entity=0;
for(my $i=0,my
$j=0;$j<($charcount-$charlimit);$i++){
my $char= substr
$value,-1,1;
my
$temp_val=substr $value,0,-1;
$value=$temp_val;
if ($char eq ';'){
$html_entity=1;
}
}
if($html_entity==1 && $char eq '&'){
$html_entity=0;
}
if(!$html_entity){
$j++;
}
}
print $value."\n";
}elsif($charcount<$charlimit){
#add some original_val to the value
if(length($original_val)>=($charlimit-$charcount)){
my $html_entity=0;
for(my $i=0,my
$j=0;$j<($charlimit-$charcount);$i++){
my $char=substr
$original_val,$i,1;
if ($char eq '&'){
$html_entity=1;
}
$value.=$char;
if($html_entity==1 && $char eq ';'){
$html_entity=0;
}
if(!$html_entity){
$j++;
}
}
}else{
$value.=$original_val;
}
}
while(my $opentag=pop @tagstoclose){
$value.="</".$opentag.">";
}
$value.="…";
}
next;
}
Not saying this is optimal code at all, but hope it is of use. The other
if statement (without the ...) could be changed for the above as well,
but you will want to omit the $value.="…";
Sandy.
More information about the interchange-users
mailing list