about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2015-08-20 02:30:28 +0000
committerEric Wong <e@80x24.org>2015-08-20 02:31:35 +0000
commit0ccdf0171d4ee715352feec69a1ed330326dfe1a (patch)
tree92147c7ee4df49d7e1745e71c2d5f3a3225b9aff /lib
parent09b1fc82d53228212805b7e26aa1d4bf381cecd6 (diff)
downloadpublic-inbox-0ccdf0171d4ee715352feec69a1ed330326dfe1a.tar.gz
view: avoid nesting <a> tags from auto-linkification
It is wrong HTML to have <a> tags nested due to auto-linkification.
Diffstat (limited to 'lib')
-rw-r--r--lib/PublicInbox/View.pm110
1 files changed, 61 insertions, 49 deletions
diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm
index 800c1a2e..2ba51182 100644
--- a/lib/PublicInbox/View.pm
+++ b/lib/PublicInbox/View.pm
@@ -207,7 +207,7 @@ sub index_walk {
                 $rv .= add_filename_line($enc->decode($fn));
         }
 
-        my $s = add_text_body_short($enc, $part, $part_nr, $fhref);
+        my $s = add_text_body($enc, $part, $part_nr, $fhref);
 
         # drop the remainder of git patches, they're usually better
         # to review when the full message is viewed
@@ -266,12 +266,7 @@ sub multipart_text_as_html {
                         $rv .= add_filename_line($enc->decode($fn));
                 }
 
-                if (defined $full_pfx) {
-                        $rv .= add_text_body_short($enc, $part, $part_nr,
-                                                $full_pfx);
-                } else {
-                        $rv .= add_text_body_full($enc, $part, $part_nr);
-                }
+                $rv .= add_text_body($enc, $part, $part_nr, $full_pfx);
                 $rv .= "\n" unless $rv =~ /\n\z/s;
                 ++$part_nr;
         });
@@ -294,57 +289,74 @@ my $LINK_RE = qr!\b((?:ftp|https?|nntp)://[@\w\+\&\?\.\%\;/#=-]+)!;
 sub linkify {
         # no newlines added here since it'd break the splitting we do
         # to fold quotes
-        $_[0] =~ s!$LINK_RE!<a href="$1">$1</a>!g;
+        $_[0] =~ s!$LINK_RE!<a\nhref="$1">$1</a>!g;
 }
 
-sub add_text_body_short {
-        my ($enc, $part, $part_nr, $full_pfx) = @_;
-        my $n = 0;
-        my $s = ascii_html($enc->decode($part->body));
-        linkify($s);
-        $s =~ s!^((?:(?:&gt;[^\n]*)\n)+)!
-                my $cur = $1;
-                my @lines = split(/\n/, $cur);
-                if (@lines > MAX_INLINE_QUOTED) {
-                        # show a short snippet of quoted text
-                        $cur = join(' ', @lines);
-                        $cur =~ s/^&gt;\s*//;
-
-                        my @sum = split(/\s+/, $cur);
-                        $cur = '';
-                        do {
-                                my $tmp = shift(@sum);
-                                my $len = length($tmp) + length($cur);
-                                if ($len > MAX_TRUNC_LEN) {
-                                        @sum = ();
-                                } else {
-                                        $cur .= $tmp . ' ';
-                                }
-                        } while (@sum && length($cur) < MAX_TRUNC_LEN);
-                        $cur =~ s/ \z/ .../;
-                        "&gt; &lt;<a\nhref=\"${full_pfx}#q${part_nr}_" . $n++ .
-                                "\">$cur<\/a>&gt;\n";
-                } else {
-                        $cur;
+sub flush_quote {
+        my ($quot, $n, $part_nr, $full_pfx, $final) = @_;
+
+        if ($full_pfx) {
+                if (!$final && scalar(@$quot) <= MAX_INLINE_QUOTED) {
+                        # show quote inline
+                        my $rv = join("\n", map { linkify($_); $_ } @$quot);
+                        @$quot = ();
+                        return $rv . "\n";
                 }
-        !emg;
-        $s;
+
+                # show a short snippet of quoted text and link to full version:
+                @$quot = map { s/^(?:&gt;\s*)+//gm; $_ } @$quot;
+                my $cur = join(' ', @$quot);
+                @$quot = split(/\s+/, $cur);
+                $cur = '';
+                do {
+                        my $tmp = shift(@$quot);
+                        my $len = length($tmp) + length($cur);
+                        if ($len > MAX_TRUNC_LEN) {
+                                @$quot = ();
+                        } else {
+                                $cur .= $tmp . ' ';
+                        }
+                } while (@$quot && length($cur) < MAX_TRUNC_LEN);
+                @$quot = ();
+                $cur =~ s/ \z/ .../s;
+                my $nr = ++$$n;
+                "&gt; [<a\nhref=\"$full_pfx#q${part_nr}_$nr\">$cur</a>]\n";
+        } else {
+                # show everything in the full version with anchor from
+                # short version (see above)
+                my $nr = ++$$n;
+                my $rv = "<a\nid=q${part_nr}_$nr></a>";
+                $rv .= join("\n", map { linkify($_); $_ } @$quot) . "\n";
+                @$quot = ();
+                $rv;
+        }
 }
 
-sub add_text_body_full {
-        my ($enc, $part, $part_nr) = @_;
+sub add_text_body {
+        my ($enc, $part, $part_nr, $full_pfx) = @_;
         my $n = 0;
         my $s = ascii_html($enc->decode($part->body));
-        linkify($s);
-        $s =~ s!^((?:(?:&gt;[^\n]*)\n)+)!
-                my $cur = $1;
-                my @lines = split(/\n/, $cur);
-                if (@lines > MAX_INLINE_QUOTED) {
-                        "<a\nid=q${part_nr}_" . $n++ . ">$cur</a>";
+        my @lines = split(/\n/, $s);
+        $s = '';
+        my $nr = 0;
+        my @quot;
+        while (defined(my $cur = shift @lines)) {
+                if ($cur !~ /^&gt;/) {
+                        # show the previously buffered quote inline
+                        if (scalar @quot) {
+                                $s .= flush_quote(\@quot, \$n, $part_nr,
+                                                  $full_pfx, 0);
+                        }
+
+                        # regular line, OK
+                        linkify($cur);
+                        $s .= $cur;
+                        $s .= "\n";
                 } else {
-                        $cur;
+                        push @quot, $cur;
                 }
-        !emg;
+        }
+        $s .= flush_quote(\@quot, \$n, $part_nr, $full_pfx, 1) if scalar @quot;
         $s;
 }