From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id C05F52141C for ; Fri, 1 Feb 2019 08:55:09 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 3/4] view: diffstat anchors for multi-message/attachment views Date: Fri, 1 Feb 2019 08:55:07 +0000 Message-Id: <20190201085508.24003-4-e@80x24.org> In-Reply-To: <20190201085508.24003-1-e@80x24.org> References: <20190201085508.24003-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: diffstat <-> ^diff anchors work within the same attachment or message while in HTML views which display multiple messages. --- Documentation/design_www.txt | 5 ++++- lib/PublicInbox/View.pm | 33 ++++++++++++++++++++------------ lib/PublicInbox/ViewDiff.pm | 31 +++++++++++++++--------------- lib/PublicInbox/WwwAtomStream.pm | 2 +- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/Documentation/design_www.txt b/Documentation/design_www.txt index c7d7fcb..cd715b2 100644 --- a/Documentation/design_www.txt +++ b/Documentation/design_www.txt @@ -6,12 +6,15 @@ URL and anchor naming /$INBOX/new.atom -> Atom feed #### Optional, relies on Search::Xapian -/$INBOX/$MESSAGE_ID/t/ -> HTML content of thread +/$INBOX/$MESSAGE_ID/t/ -> HTML content of thread (nested) +/$INBOX/$MESSAGE_ID/T/ -> HTML content of thread (flat) anchors: #u location of $MESSAGE_ID in URL #m per-message links, where is of the Message-ID of each message (stable) #s relative numeric position of message in thread (unstable) + #i<...> diffstat location for patch emails + #Z?<...> per-file diff header location for patch emails /$INBOX/$MESSAGE_ID/t.atom -> Atom feed for thread /$INBOX/$MESSAGE_ID/t.mbox.gz -> gzipped mbox of thread diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index ca9b955..8c81253 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -37,7 +37,7 @@ sub msg_html { if ($nr == 1) { # $more cannot be true w/o $smsg being defined: my $upfx = $more ? '../'.mid_escape($smsg->mid).'/' : ''; - $tip . multipart_text_as_html($mime, $upfx, $ibx) . + $tip . multipart_text_as_html($mime, $upfx, $ctx) . '
' } elsif ($more && @$more) { ++$end; @@ -90,7 +90,7 @@ sub msg_html_more { my $mime = $smsg->{mime}; my $upfx = '../' . mid_escape($smsg->mid) . '/'; _msg_html_prepare($mime->header_obj, $ctx, $more, $nr) . - multipart_text_as_html($mime, $upfx, $ibx) . + multipart_text_as_html($mime, $upfx, $ctx) . '
' } else { ''; @@ -262,7 +262,7 @@ sub index_entry { # scan through all parts, looking for displayable text my $ibx = $ctx->{-inbox}; - msg_iter($mime, sub { $rv .= add_text_body($mhref, $ibx, $_[0]) }); + msg_iter($mime, sub { $rv .= add_text_body($mhref, $ctx, $_[0]) }); # add the footer $rv .= "\n^ ". @@ -490,11 +490,11 @@ sub thread_html { } sub multipart_text_as_html { - my ($mime, $upfx, $ibx) = @_; + my ($mime, $upfx, $ctx) = @_; my $rv = ""; # scan through all parts, looking for displayable text - msg_iter($mime, sub { $rv .= add_text_body($upfx, $ibx, $_[0]) }); + msg_iter($mime, sub { $rv .= add_text_body($upfx, $ctx, $_[0]) }); $rv; } @@ -547,10 +547,11 @@ sub attach_link ($$$$;$) { } sub add_text_body { - my ($upfx, $ibx, $p) = @_; + my ($upfx, $ctx, $p) = @_; + my $ibx = $ctx->{-inbox}; my $obfs_ibx = $ibx->{obfuscate} ? $ibx : undef; # $p - from msg_iter: [ Email::MIME, depth, @idx ] - my ($part, $depth) = @$p; # attachment @idx is unused + my ($part, $depth, @idx) = @$p; my $ct = $part->content_type || 'text/plain'; my $fn = $part->filename; my ($s, $err) = msg_part_text($part, $ct); @@ -561,9 +562,16 @@ sub add_text_body { # link generation in diffs with the extra '%0D' $s =~ s/\r\n/\n/sg; - my ($diff, $spfx); + # always support diff-highlighting, but we can't linkify hunk + # headers for solver unless some coderepo are configured: + my $diff; if ($s =~ /^(?:diff|---|\+{3}) /ms) { - $diff = []; + # diffstat anchors do not link across attachments or messages: + $idx[0] = $upfx . $idx[0] if $upfx ne ''; + $ctx->{-apfx} = join('/', @idx); + $ctx->{-anchors} = {}; # attr => filename + $ctx->{-diff} = $diff = []; + my $spfx; if ($ibx->{-repo_objs}) { my $n_slash = $upfx =~ tr!/!/!; if ($n_slash == 0) { @@ -574,6 +582,7 @@ sub add_text_body { $spfx = '../../'; } } + $ctx->{-spfx} = $spfx; }; my @lines = split(/^/m, $s); @@ -598,18 +607,18 @@ sub add_text_body { $s .= $l->linkify_2(ascii_html($cur)); } } else { - flush_diff(\$s, $spfx, $l, $diff) if $diff && @$diff; + flush_diff(\$s, $ctx, $l) if $diff && @$diff; push @quot, $cur; } } if (@quot) { # ugh, top posted flush_quote(\$s, $l, \@quot); - flush_diff(\$s, $spfx, $l, $diff) if $diff && @$diff; + flush_diff(\$s, $ctx, $l) if $diff && @$diff; obfuscate_addrs($obfs_ibx, $s) if $obfs_ibx; $s; } else { - flush_diff(\$s, $spfx, $l, $diff) if $diff && @$diff; + flush_diff(\$s, $ctx, $l) if $diff && @$diff; obfuscate_addrs($obfs_ibx, $s) if $obfs_ibx; if ($s =~ /\n\z/s) { # common, last line ends with a newline $s; diff --git a/lib/PublicInbox/ViewDiff.pm b/lib/PublicInbox/ViewDiff.pm index 38cb5a1..2074e12 100644 --- a/lib/PublicInbox/ViewDiff.pm +++ b/lib/PublicInbox/ViewDiff.pm @@ -76,10 +76,10 @@ sub to_state ($$$) { } sub anchor0 ($$$$$) { - my ($dst, $anchors, $linkify, $fn, $rest) = @_; - if (my $attr = to_attr($fn)) { - $anchors->{$attr} = 1; - $$dst .= " " . + my ($dst, $ctx, $linkify, $fn, $rest) = @_; + if (my $attr = to_attr($ctx->{-apfx}.$fn)) { + $ctx->{-anchors}->{$attr} = 1; + $$dst .= " " . ascii_html($fn) . ''. to_html($linkify, $rest); return 1; @@ -88,33 +88,33 @@ sub anchor0 ($$$$$) { } sub anchor1 ($$$$$) { - my ($dst, $anchors, $linkify, $pb, $s) = @_; - my $attr = to_attr($pb) or return; + my ($dst, $ctx, $linkify, $pb, $s) = @_; + my $attr = to_attr($ctx->{-apfx}.$pb) or return; my $line = to_html($linkify, $s); - if (delete $anchors->{$attr} && $line =~ s/^diff //) { - $$dst .= "diff ".$line; + if (delete $ctx->{-anchors}->{$attr} && $line =~ s/^diff //) { + $$dst .= "diff ".$line; return 1; } undef } -sub flush_diff ($$$$) { - my ($dst, $spfx, $linkify, $diff) = @_; +sub flush_diff ($$$) { + my ($dst, $ctx, $linkify) = @_; + my $diff = $ctx->{-diff}; + my $spfx = $ctx->{-spfx}; my $state = DSTATE_INIT; my $dctx = { Q => '' }; # {}, keys: oid_a, oid_b, path_a, path_b - my $anchors = {}; # attr => filename foreach my $s (@$diff) { if ($s =~ /^---$/) { to_state($dst, $state, DSTATE_STAT); - $$dst .= "" . $s . ''; + $$dst .= $s; } elsif ($s =~ /^ /) { # works for common cases, but not weird/long filenames if ($state == DSTATE_STAT && $s =~ /^ (\S+)(\s+\|.*\z)/s) { - anchor0($dst, $anchors, $linkify, $1, $2) - and next; + anchor0($dst, $ctx, $linkify, $1, $2) and next; } elsif ($state2class[$state]) { to_state($dst, $state, DSTATE_CTX); } @@ -136,8 +136,7 @@ sub flush_diff ($$$$) { $dctx->{Q} .= "&a=".uri_escape_utf8($pa, UNSAFE); } - anchor1($dst, $anchors, $linkify, $pb, $s) - and next; + anchor1($dst, $ctx, $linkify, $pb, $s) and next; } $$dst .= to_html($linkify, $s); } elsif ($s =~ s/^(index $OID_NULL\.\.)($OID_BLOB)\b//o) { diff --git a/lib/PublicInbox/WwwAtomStream.pm b/lib/PublicInbox/WwwAtomStream.pm index 712c3dc..6d3a936 100644 --- a/lib/PublicInbox/WwwAtomStream.pm +++ b/lib/PublicInbox/WwwAtomStream.pm @@ -137,7 +137,7 @@ sub feed_entry { qq{} . qq{} . qq() . - PublicInbox::View::multipart_text_as_html($mime, $href) . + PublicInbox::View::multipart_text_as_html($mime, $href, $ctx) . ''; } -- EW