Gitweb: how to display markdown file in html format automatically like github

前端 未结 4 1946
既然无缘
既然无缘 2021-02-06 01:01

Markdown is important for documentation, it is very nice to see README.md can be automatically show in html format in github like https://github.com/twitter/bootstr

相关标签:
4条回答
  • 2021-02-06 01:29

    Here are my modifications to gitweb.cgi based on the accepted answer, so that:

    • README.md in the project root is displayed (as in accepted answer)
    • Any *.md file is displayed if it is chosen as file from the tree view
    • local links among .md files in a project are preserved (i.e. (my parent)[../parent.md] would refer correctly); should work for images as well

    Note that I'm using sudo apt-get install libtext-markdown-perl on Ubuntu to provide the required markdown executable.

    Here are the modifications as a diff patch:

    --- /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";
    
    0 讨论(0)
  • 2021-02-06 01:33

    Here's something you can stick somewhere under sub git_summary in your gitweb.perl or gitweb.cgi. Note that it depends on an external markdown executable.

    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>";
        }
    }
    

    I don't really know Perl, so this is a dirty hack more than anything else, but it works.

    0 讨论(0)
  • 2021-02-06 01:39

    I use this tampermonkey script in chrome to render README.md files as html, directly in gitweb: https://gist.github.com/nemoo/ee47cd9ad2a5b4fffffdfa Works nicely even if you do not have access to the gitweb server.

    0 讨论(0)
  • 2021-02-06 01:41

    I use following post-receive hook in my remote repositories which are made browsable with 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
    

    That script is run when I push commits from my local work repositories to the remote bare ones. You could use that or something similar depending on your workflow/setup.

    More information about git hooks: http://book.git-scm.com/5_git_hooks.html

    0 讨论(0)
提交回复
热议问题