PlainTextPre
This patch is at http://issues.bestpractical.com/Ticket/Display.html?id=8374. It was tested with 3.6.1 and I believe it will work as-is with 3.6.3.
Many of the messages our RT instance handles contain space- and tab-based formatting in plain text. The way RT displays them (as HTML with <br> used to preserve line breaks) causes this formatting to be lost. Eg, this text:
left side right side --------- ---------- item one value one item two value two
won't look right on the web page with a standard RT setup.
I couldn't figure out a clean way to change this via an overlay or callback. One problem is the <br>s get added after the callback returns. Another is that you want to use one <pre> for the whole message body (because it introduces vertical space the way a <p> does), but ShowMessageStanza is called for each blob of text Text::Quoted extracts. Additionally the standard ShowMessageStanza adds newlines around the <div>s, and these cause blank lines inside <pre>.
There might be a way to do have space- and tab-based formatting work based on "white-space: pre;" style instead of <pre>, but this didn't line things up correctly when I tried it. I am no HTML expert.
Here's the solution I came up with. It adds a new config variable, $RT::PlainTextPre, which allows you to tell the system to use <pre> on plain text message bodies.
--- etc/RT_Config.pm.in.~1~ 2006-10-25 23:18:11.000000000 -0400 +++ etc/RT_Config.pm.in 2007-05-10 15:34:04.000000000 -0400 @@ -463,6 +463,13 @@ Set($ShowTransactionImages, 1); +# Normally plain text attachments are displayed as HTML with line +# breaks preserved. This causes space- and tab-based formatting not +# to be displayed correctly. By setting $PlainTextPre they'll be +# displayed using <pre> instead so such formatting works, but they'll +# use a monospaced font. + +Set($PlainTextPre, 0); # $HomepageComponents is an arrayref of allowed components on a user's # customized homepage ("RT at a glance"). --- html/Ticket/Elements/ShowMessageStanza.~1~ 2006-06-19 18:44:04.000000000 -0400 +++ html/Ticket/Elements/ShowMessageStanza 2007-05-10 14:52:13.000000000 -0400 @@ -1,3 +1,4 @@ +%# $Id: PlainTextPre,v 1.1 2007/05/10 20:30:13 www-data Exp www-data $ %# BEGIN BPS TAGGED BLOCK {{{ %# %# COPYRIGHT: @@ -43,35 +44,73 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} -% if (ref($Message)) { -<div class="message-stanza-depth-<% $Depth %>"> <%perl> -foreach my $stanza (@$Message) { - if ( ref $stanza eq "ARRAY" ) { - $m->comp( 'ShowMessageStanza', - Depth => $Depth + 1, - Transaction => $Transaction, - Message => $stanza ); - } - elsif ( ref $stanza eq "HASH" ) { - my $content = $stanza->{raw}; - RT::Interface::Web::EscapeUTF8(\$content); - $m->comp('/Elements/Callback', content => \$content, %ARGS); - $content =~ s{$}{<br />}mg - if defined $content; +# This component is called to display plain text attachments. At the +# top level it's passed the data structure returned by Text::Quoted, +# then it uses itself recursively to display it. +# +# By default the messages are displayed as simple escapped HTML. Line +# breaks are preserved by adding <br>. +# +# If you set $RT::PlainTextPre then the messages are displayed inside a +# <pre> section. This allows space- and tab-based formatting to work, +# at the cost of using a monospaced font. +# +# There might be a way to do have space- and tab-based formatting work +# based on "white-space: pre;" style instead of <pre>, but this didn't +# line things up correctly when I tried it. I am no HTML expert. + +# Because the output might be inside <pre> this code has to be careful +# not to introduce extra newlines. + +# An oddity of Text::Quoted is that it strips the trailing newline from +# each returned strings. The strings can be multi-line, they'll always +# be missing the newline at the end. + +if (ref($Message)) { + my ($pon, $poff) = ($RT::PlainTextPre && $Depth == 0) + ? ('<pre>', '</pre>') + : ('', ''); + $m->out($pon); + $m->out(qq(<div class="message-stanza-depth-$Depth">)); + foreach my $stanza (@$Message) { + if ( ref $stanza eq "ARRAY" ) { + $m->comp( 'ShowMessageStanza', + Depth => $Depth + 1, + Transaction => $Transaction, + Message => $stanza ); + } + elsif ( ref $stanza eq "HASH" ) { + my $content = $stanza->{raw}; + RT::Interface::Web::EscapeUTF8(\$content); + $m->comp('/Elements/Callback', content => \$content, %ARGS); + # I put the trailing \n back here, after the callback, + # because the callback was historically called without it + # attached. + $content .= "\n"; + $content =~ s{\n}{<br />\n}mg + if !$RT::PlainTextPre; + $m->out($content); + } + } + $m->out('</div>'); + $m->out($poff); +} else { + my $content = $Message; + RT::Interface::Web::EscapeUTF8(\$content); + $m->comp('/Elements/Callback', content => \$content, %ARGS); + $content .= "\n" + if $content !~ /\n$/; + if ($RT::PlainTextPre) { + $content = "<pre>$content</pre>"; + } + else { + $content =~ s{\n}{<br />\n}mg; + } + $m->out($content); +} </%perl> -<%$content |n%> -% } -% } # end foreach -</div> -% } else { -% my $content = $Message; -% RT::Interface::Web::EscapeUTF8(\$content); -% $m->comp('/Elements/Callback', content => \$content, %ARGS); -% $content =~ s{$}{<br />}mg; -<%$content |n%> -% } <%INIT> use URI::URL; </%INIT>