Gitweb:如何像github一样自动以html格式显示markdown文件

时间:2011-11-30 05:44:13

标签: perl markdown gitweb

Markdown对于文档很重要,很高兴看到README.md可以在github中以html格式自动显示,如https://github.com/twitter/bootstrap/blob/master/README.md

gitweb是用perl脚本编写的,而且perl中有markdown插件。

我想检查是否有插件/解决方案让gitweb自动显示标记格式的html文件。

4 个答案:

答案 0 :(得分:11)

我在我的远程存储库中使用了以下post-receive hook,这些存储库可以使用gitweb进行浏览。

#!/bin/sh
#
# Post-receive hook script which generates README.html to git-dir from
# README.md found at the head of master branch in repository.
#
# Gitweb can read the README.html and embed it to the project summary page.

git cat-file blob HEAD:README.md | markdown > $GIT_DIR/README.html

当我将提交从本地工作存储库推送到远程裸工具库时,运行该脚本。根据您的工作流程/设置,您可以使用它或类似的东西。

有关git hooks的更多信息:http://book.git-scm.com/5_git_hooks.html

答案 1 :(得分:7)

您可以在sub git_summarygitweb.perl gitweb.cgi下的某些地方贴上某些内容。请注意,它取决于外部markdown可执行文件。

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\">readme</div>\n";
        print "<div class=\"readme page_body\">"; # TODO find/create a better CSS class than page_body                                                                                                  

        my $cmd_markdownify = $GIT . " " . git_cmd() . " cat-file blob " . $readme_blob_hash . " | markdown |";
        open FOO, $cmd_markdownify or die_error(500, "Open git-cat-file blob '$hash' failed");
        while (<FOO>) {
            print $_;
        }
        close(FOO);

        print "</div>";
    }
}

我真的不知道Perl,所以这是一个肮脏的黑客,但它确实有效。

答案 2 :(得分:2)

以下是我根据接受的答案对gitweb.cgi的修改,以便:

    显示项目根目录中的
  • README.md(如接受的答案)
  • 如果从树视图中选择文件
  • ,则会显示任何*.md文件
  • 保留项目中.md文件之间的本地链接(即(my parent)[../parent.md]将正确引用);也适用于图像

请注意,我在Ubuntu上使用sudo apt-get install libtext-markdown-perl来提供所需的markdown可执行文件。

以下是diff补丁的修改:

--- /usr/share/gitweb/gitweb.cgi.orig   2016-04-13 10:28:03.268872899 +0200
+++ /usr/share/gitweb/gitweb.cgi    2016-04-13 10:39:02.344875516 +0200
@@ -16,8 +16,9 @@
 use Encode;
 use Fcntl ':mode';
 use File::Find qw();
-use File::Basename qw(basename);
+use File::Basename qw(basename dirname);
 use Time::HiRes qw(gettimeofday tv_interval);
+use File::Spec; # hack
 binmode STDOUT, ':utf8';

 our $t0 = [ gettimeofday() ];
@@ -6585,6 +6586,20 @@
        print "\n</div>\n"; # class="readme"
    }

+   # hack
+   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) : ();
@@ -7059,6 +7074,9 @@
    $fd = run_highlighter($fd, $highlight, $syntax)
        if $syntax;

+   # hack
+   my $ismarkdown = ($file_name =~ /md$/);
+
    git_header_html(undef, $expires);
    my $formats_nav = '';
    if (defined $hash_base && (my %co = parse_commit($hash_base))) {
@@ -7102,6 +7120,10 @@
              href(action=>"blob_plain", hash=>$hash,
                   hash_base=>$hash_base, file_name=>$file_name) .
              qq!" />\n!;
+   } 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>) {
@@ -7119,6 +7141,79 @@
    git_footer_html();
 }

+# hack
+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";

答案 3 :(得分:0)

我在chrome中使用这个tampermonkey脚本直接在gitweb中将README.md文件呈现为html: https://gist.github.com/nemoo/ee47cd9ad2a5b4fdddfa即使您无法访问gitweb服务器也能很好地工作。