gitweb: Highlight matched part of shortened project description
Previous commit make gitweb use esc_html_match_hl() to mark match in the _whole_ description of a project when searching projects. This commit makes gitweb highlight match in _shortened_ description, based on match in whole description, using esc_html_match_hl_chopped() subroutine. If match is in removed (chopped) part, even partially, then trailing "... " is highlighted. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jakub Narebski committed
Feb 27, 2012 at 02:55 UTC
e607b79fb14f2196f7ea46d2115f21c548972e78
1 file changed
+47
-5
gitweb/gitweb.perl
+47
-5
@@ -1742,20 +1742,61 @@ sub esc_html_hl_regions {
1742
return $out;
1743
}
1744
1745
-# highlight match (if any), and escape HTML
1746
-sub esc_html_match_hl {
1745
+# return positions of beginning and end of each match
1746
+sub matchpos_list {
1747
my ($str, $regexp) = @_;
1748
- return esc_html($str) unless defined $regexp;
1748
+ return unless (defined $str && defined $regexp);
1749
1750
my @matches;
1751
while ($str =~ /$regexp/g) {
1752
push @matches, [$-[0], $+[0]];
1753
}
1754
+ return @matches;
1755
+}
1756
+
1757
+# highlight match (if any), and escape HTML
1758
+sub esc_html_match_hl {
1759
+ my ($str, $regexp) = @_;
1760
+ return esc_html($str) unless defined $regexp;
1761
+
1762
+ my @matches = matchpos_list($str, $regexp);
1763
return esc_html($str) unless @matches;
1764
1765
return esc_html_hl_regions($str, 'match', @matches);
1766
}
1767
1768
+
1769
+# highlight match (if any) of shortened string, and escape HTML
1770
+sub esc_html_match_hl_chopped {
1771
+ my ($str, $chopped, $regexp) = @_;
1772
+ return esc_html_match_hl($str, $regexp) unless defined $chopped;
1773
+
1774
+ my @matches = matchpos_list($str, $regexp);
1775
+ return esc_html($chopped) unless @matches;
1776
+
1777
+ # filter matches so that we mark chopped string
1778
+ my $tail = "... "; # see chop_str
1779
+ unless ($chopped =~ s/\Q$tail\E$//) {
1780
+ $tail = '';
1781
+ }
1782
+ my $chop_len = length($chopped);
1783
+ my $tail_len = length($tail);
1784
+ my @filtered;
1785
+
1786
+ for my $m (@matches) {
1787
+ if ($m->[0] > $chop_len) {
1788
+ push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0);
1789
+ last;
1790
+ } elsif ($m->[1] > $chop_len) {
1791
+ push @filtered, [ $m->[0], $chop_len + $tail_len ];
1792
+ last;
1793
+ }
1794
+ push @filtered, $m;
1795
+ }
1796
+
1797
+ return esc_html_hl_regions($chopped . $tail, 'match', @filtered);
1798
+}
1799
+
1800
## ----------------------------------------------------------------------
1801
## functions returning short strings
1802
@@ -5405,9 +5446,10 @@ sub git_project_list_rows {
5446
"</td>\n" .
5447
"<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
5448
-class => "list",
5408
- $search_regexp ? () : -title => $pr->{'descr_long'}},
5449
+ -title => $pr->{'descr_long'}},
5450
$search_regexp
5410
- ? esc_html_match_hl($pr->{'descr_long'}, $search_regexp)
5451
+ ? esc_html_match_hl_chopped($pr->{'descr_long'},
5452
+ $pr->{'descr'}, $search_regexp)
5453
: esc_html($pr->{'descr'})) .
5454
"</td>\n" .
5455
"<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";