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

Markdown is important for documentation, it is very nice to see that README.md can be automatically displayed in html format on github, for example https://github.com/twitter/bootstrap/blob/master/README.md

gitweb is written in a perl script, and now there is a plugin for markdown in perl.

I want to check if there is a plugin / solution so that gitweb automatically displays html files for markdown format.

+7
source share
4 answers

Here you can put somewhere under sub git_summary in gitweb.perl or gitweb.cgi . Note that this depends on the external 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>"; } } 

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

+6
source

I use the following post-receive hook in my remote repositories that become viewable 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 

This script runs when I push commits from local work repositories to remote ones. You can use this or something similar depending on your workflow / setup.

More info on git hooks: http://book.git-scm.com/5_git_hooks.html

+11
source

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

  • README.md in the project root is displayed (as in the accepted answer)
  • Any *.md file is displayed if it is selected as a file from the tree view.
  • local links between .md files in the project are saved (ie (my parent)[../parent.md] will be correctly accessed); should work for images too.

Note that I am using sudo apt-get install libtext-markdown-perl in Ubuntu to provide the required markdown .

Here are the changes 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"; 
+1
source

I use this tampermonkey script in chrome to render README.md files as html directly in gitweb: https://gist.github.com/nemoo/ee47cd9ad2a5b4fdddfa Works fine even if you don't have access to the gitweb server.

0
source

All Articles