my %is_approved_element = map { $_ => 1 } qw(a b big blockquote br center cite code dd div dl dt em font hr i img i ol p pre samp small span strong sub sup table td th tr tt u ul); my %is_block_element = map { $_ => 1 } qw(blockquote center div dl ol pre table ul); my %is_raw_element = map { $_ => 1 } qw(dl ol pre table ul); my %is_empty_element = map { $_ => 1} qw(br img hr); sub render_text { my $str = shift; my $no_margin = shift; my $buf; my @tag_stack; my $raw; my $nl; my $in_p; $str =~ s/&(?!\#?[a-zA-Z0-9]+;)/&/g; $str =~ s{([^<>]+)} {sprintf(qq|%s|, $script_name, user_id($1), $1)}gei; while ($str) { my $out; my $need_p = !$in_p && !$raw; if ($str =~ s/^([^<>\n]+)//) { $out = $1; for ($out) { my $in_a = grep { $_ eq 'a' } @tag_stack; unless ($in_a) { s{((?:http|https|ftp|mailto):\S+[a-zA-Z0-9/])} {$1}g; } } } elsif ($str =~ s/^//) { my $close = $1; my $name = lc $2; my $attributes = $3; if ($is_approved_element{$name}) { if ($is_block_element{$name}) { # A

tag produced by \n\n should go after a

tag, # not before it. $need_p = 0; if ($close && $in_p) { $buf .= '

'; $in_p = 0; } if ($is_raw_element{$name}) { if ($close) { $raw--; } else { $raw++; } } } if ($close) { # Catch a pending \n so it doesn't get translated to
. if ($nl) { $out .= "\n"; $nl = 0; } if ($tag_stack[0] eq $name) { $out .= ""; shift(@tag_stack); } } else { $out .= "<$name$attributes>"; unless ($is_empty_element{$name}) { unshift(@tag_stack, $name); $str =~ s/^(\n+)//; $out .= $1; } } } else { $out = "<$close$name$attributes>"; } } else { $out = '<'; } } elsif ($str =~ s/^>//) { $out = '>'; } elsif ($str =~ s/^(\n{2,})//) { if ($in_p) { $buf .= '

'; $in_p = 0; } $buf .= $1; } elsif ($str =~ s/^\n//) { if ($raw) { $buf .= "\n"; } else { $nl = 1; } } if ($out) { if ($nl) { $buf .= "
\n"; $nl = 0; } if ($need_p) { $buf .= '

'; $in_p = 1; } $buf .= $out; } } for my $name (@tag_stack) { $buf .= ""; } if ($in_p) { $buf .= '

'; } if ($no_margin) { my $first_p = index($buf, '

'); my $last_p = rindex($buf, '

'); if ($first_p == $last_p) { substr($buf, $first_p + 2, 0) = q| style="margin: 0"|; } else { if ($last_p >= 0) { substr($buf, $last_p + 2, 0) = q| style="margin-bottom: 0"|; } if ($first_p >= 0) { substr($buf, $first_p + 2, 0) = q| style="margin-top: 0"|; } } } return $buf; }