]> gitweb.ps.run Git - ps-gitweb/blobdiff - gitweb/gitweb.perl
gitweb patch to display markdown
[ps-gitweb] / gitweb / gitweb.perl
index b5490dfecf2da75a8b875dd614c6a7a2553094f9..ed1dacdf682c115edbaeecf9269e5a7c9b975a2e 100755 (executable)
@@ -18,7 +18,8 @@ use CGI::Carp qw(fatalsToBrowser set_message);
 use Encode;
 use Fcntl ':mode';
 use File::Find qw();
-use File::Basename qw(basename);
+use File::Basename qw(basename dirname);
+use File::Spec;
 use Time::HiRes qw(gettimeofday tv_interval);
 use Digest::MD5 qw(md5_hex);
 
@@ -6662,6 +6663,19 @@ sub git_summary {
                print "\n</div>\n"; # class="readme"
        }
 
+    if (!$prevent_xss) {
+        $file_name = "README.md";
+        my $proj_head_hash = git_get_head_hash($project);
+        my $readme_blob_hash = git_get_hash_by_path($proj_head_hash, "readme.md", "blob");
+        if ($readme_blob_hash) { # if README.md exists
+            print "<div class=\"header\">$file_name</div>\n";
+            print "<div class=\"readme page_body\">"; # TODO find/create a better CSS class than page_body
+            print get_markdown($file_name, $readme_blob_hash);
+            print "</div>";
+        }
+    }
+
        # we need to request one more than 16 (0..15) to check if
        # those 16 are all
        my @commitlist = $head ? parse_commits($head, 17) : ();
@@ -7136,6 +7150,8 @@ sub git_blob {
        my $syntax = guess_file_syntax($highlight, $file_name);
        $fd = run_highlighter($fd, $highlight, $syntax);
 
+       my $ismarkdown = ($file_name =~ /md$/);
+
        git_header_html(undef, $expires);
        my $formats_nav = '';
        if (defined $hash_base && (my %co = parse_commit($hash_base))) {
@@ -7179,7 +7195,11 @@ sub git_blob {
                      esc_attr(href(action=>"blob_plain", hash=>$hash,
                           hash_base=>$hash_base, file_name=>$file_name)) .
                      qq!" />\n!;
-       } else {
+    } elsif ($ismarkdown) {
+        print qq!<div class="readme page_body">\n!;
+        print get_markdown($file_name, $hash);
+        print qq!</div>\n!; #  $cmd_markdownify
+    } else {
                my $nr;
                while (my $line = <$fd>) {
                        chomp $line;
@@ -7196,6 +7216,78 @@ sub git_blob {
        git_footer_html();
 }
 
+sub get_norm_rel_path { # http://www.perlmonks.org/bare/?node_id=11907
+   my $unnormpath = shift;
+   while ($unnormpath =~ m!/\.!) {
+       $unnormpath =~ s!/[^\/]+/\.\.!!;
+       # print "Path is now -+$unnormpath+-\n";
+   }
+   return $unnormpath;
+}
+sub get_markdown {
+   my $tfilename = shift;
+   my $thash = shift;
+   my $rethtmlstr = "";
+   use open ":encoding(utf8)"; # needed to have utf8 survive through the shell pipe
+   my $cmd_markdownify = $GIT . " " . git_cmd() . " cat-file blob " . $thash . " | perl -e 'my \$str = do { local \$/; <STDIN> }; \$str =~ s/<!--.*?--\s*>//gs; print \$str;' | markdown |";
+   open (FOO, $cmd_markdownify) or die_error(500, "Open git-cat-file blob '$thash' failed");
+   while (<FOO>) {
+       if ($_ =~ /(<img[^>]src=")(.*?)"/) {
+           my $origcut = "".$2;
+           my $testcut = "".$2;
+           my $is_anchor = ($testcut =~ /^#/);
+           my $is_absolute = ($testcut =~ /^http/);
+           my $is_relative_up = ($testcut =~ /^\.\./);
+           my $is_local_link = ((!$is_anchor) and (!$is_absolute));
+           my $tdir = dirname($tfilename);
+           my $is_tdir_proper = (($tdir ne "") and ($tdir ne "."));
+           #print "XX: $origcut ($is_anchor, $is_absolute - $is_local_link) ($is_relative_up, $is_tdir_proper, $tdir, $tfilename)\n"; # dbg
+           if ($is_local_link) {
+               if ($is_relative_up) { # normalize
+                   if ($is_tdir_proper) {
+                       # cheat with absolute path here:
+                       my $resolved = get_norm_rel_path( File::Spec->rel2abs ("$origcut", "/$tdir" ) );
+                       $resolved = substr $resolved, 1;
+                       #print "YY: $resolved\n";
+                       $_ =~ s!(<img[^>]src=")(.*?)"!$1?p=$project;a=blob_plain;f=$resolved"!gi;
+                   }
+               } else {
+                   $_ =~ s!(<img[^>]src=")(.*?)"!$1?p=$project;a=blob_plain;f=$2"!gi;
+                   #print "ZZ: $_\n";
+               }
+           }
+       }
+       if ($_ =~ /(<a[^>]href=")(.*?)"/) {
+           my $origcut = "".$2;
+           my $testcut = "".$2;
+           my $is_anchor = ($testcut =~ /^#/);
+           my $is_absolute = ($testcut =~ /^http/);
+           my $is_relative_up = ($testcut =~ /^\.\./);
+           my $is_local_link = ((!$is_anchor) and (!$is_absolute));
+           my $tdir = dirname($tfilename);
+           my $is_tdir_proper = (($tdir ne "") and ($tdir ne "."));
+           #print "XX: $origcut ($is_anchor, $is_absolute - $is_local_link) ($is_relative_up, $is_tdir_proper, $tdir, $tfilename)\n"; # dbg
+           if ($is_local_link) {
+               if ($is_relative_up) { # normalize
+                   if ($is_tdir_proper) {
+                       # cheat with absolute path here:
+                       my $resolved = get_norm_rel_path( File::Spec->rel2abs ("$origcut", "/$tdir" ) );
+                       $resolved = substr $resolved, 1;
+                       #print "YY: $resolved\n";
+                       $_ =~ s!(<a[^>]href=")(.*?)"!$1?p=$project;a=blob;f=$resolved"!gi;
+                   }
+               } else {
+                   $_ =~ s!(<a[^>]href=")(.*?)"!$1?p=$project;a=blob;f=$2"!gi;
+                   #print "ZZ: $_\n";
+               }
+           }
+       }
+       $rethtmlstr .= $_;
+   }
+   close(FOO);
+   return $rethtmlstr;
+}
+
 sub git_tree {
        if (!defined $hash_base) {
                $hash_base = "HEAD";