Visualización de ficheros markdown desde GitWeb

Los usuarios de GitHub están acostumbrados a escribir un fichero README.md en la raíz del repositorio que se visualiza desde la web proporcionando información del proyecto.

La extensión .md del proyecto indica que el mismo está escrito con el lenguaje de marcación Markdown (para más detalles, consultar esta guía rápida sobre uso del lenguaje Markdown).

Dado que tengo mi propio servicio de repositorios Git, quería incorporarle mi propio procesador de ficheros markdown e integrarlo con la consulta vía GitWeb. Por suerte, encontré este hack de Stack Overflow que me dió todas las pistas para conseguirlo.

Partiendo de la instalación de GitWeb de este tutorial, comenzamos instalando el intérprete de markdown de Perl:

# apt-get install libtext-markdown-perl

Luego se realizan los siguientes cambios en el script /usr/share/gitweb/gitweb.cgi:

# diff gitweb.cgi gitweb.cgi.orig 
19,20c19
< use File::Basename qw(basename dirname);
< use File::Spec;
---
> use File::Basename qw(basename);
6611,6622d6609
<       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>";
<               }
<       }
< 
7096,7097d7082
<       my $ismarkdown = ($file_name =~ /md$/);
< 
7141,7144d7125
<       } elsif ($ismarkdown) {
<               print qq!<div class="readme page_body">\n!;
<               print get_markdown($file_name, $hash);
<               print qq!</div>\n!; # $cmd_markdownify
7160,7232d7140
< }
< 
< 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; 

Estos cambios visualizan en html el contenido del fichero README.md que se encuentre en la raíz del proyecto y lo visualiza dentro de la página de sumario del proyecto de GitWeb.

Adicionalmente permite que, al explorar los ficheros que componen un proyecto, si se hace click sobre un fichero que tenga la extensión .md, el contenido en markdown de este será visualizado en html.

José Administrator
Apasionado por el software, la electrónica y la fotografía.
follow me

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *