]> Sergey Matveev's repositories - public-inbox.git/commitdiff
view: avoid nesting <a> tags from auto-linkification
authorEric Wong <e@80x24.org>
Thu, 20 Aug 2015 02:30:28 +0000 (02:30 +0000)
committerEric Wong <e@80x24.org>
Thu, 20 Aug 2015 02:31:35 +0000 (02:31 +0000)
It is wrong HTML to have <a> tags nested due to auto-linkification.

lib/PublicInbox/View.pm
t/view.t

index 800c1a2e6e0f686b09d492d0d3d2fd467eddf5e8..2ba51182dfcc39f3fe2126885406cc28f8d271f4 100644 (file)
@@ -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;
 }
 
index 463fc0764d9a9e2587e72a038c719a5926d10255..ca456aab86073a09e779515acd7018e1e4c71df4 100644 (file)
--- a/t/view.t
+++ b/t/view.t
@@ -47,7 +47,7 @@ EOF
        like($html, qr!<a\nhref="\.\./m/hello%40!s, "MID link present");
        like($html, qr/hello world\b/, "body present");
        like($html, qr/&gt; keep this inline/, "short quoted text is inline");
-       like($html, qr/<a\nid=[^>]+>&gt; Long and wordy/,
+       like($html, qr/<a\nid=[^>]+><\/a>&gt; Long and wordy/,
                "long quoted text is anchored");
 
        # short page