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>