diff options
| author | patrick-scho | 2025-11-29 13:58:52 +0100 |
|---|---|---|
| committer | patrick-scho | 2025-11-29 13:58:52 +0100 |
| commit | 62cb152784d956cc22c356cfe3df61e712fbe196 (patch) | |
| tree | ad8a02835a2bb574efe6531e831a8e0e99cd7e72 /gitweb/gitweb.perl | |
| parent | 12047d230075bac819e179eb8814c97fd18da8b4 (diff) | |
| download | ps-gitweb-62cb152784d956cc22c356cfe3df61e712fbe196.tar.gz ps-gitweb-62cb152784d956cc22c356cfe3df61e712fbe196.zip | |
gitweb patch to display markdown
https://stackoverflow.com/a/36593115
https://gist.github.com/johnlane/b0eb78dc97694d3a42d8dedcc6a5d095
Diffstat (limited to 'gitweb/gitweb.perl')
| -rwxr-xr-x | gitweb/gitweb.perl | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b5490df..ed1dacd 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -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"; |
