You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
3.5 KiB
172 lines
3.5 KiB
#! /usr/bin/env perl |
|
use strict; |
|
use warnings; |
|
use Text::Markdown qw(markdown); |
|
use FindBin qw($Bin); |
|
|
|
my $title = "no title"; |
|
my $body = "no body"; |
|
|
|
# 解析 GET 参数 |
|
my $query = $ENV{QUERY_STRING}; |
|
my %query = map {$1 => $2 if /(\w+)=(\S+)/} split('&', $query); |
|
|
|
my $mdpath = $query{p}; |
|
response() unless $mdpath; |
|
|
|
$mdpath = "$Bin/$mdpath.md"; |
|
response() unless -r $mdpath; |
|
|
|
my $mdfile = prefile($mdpath); |
|
my $text = join("", @{$mdfile->{content}}); |
|
# my $text = join("\n", @{$mdfile->{content}}); |
|
# <pre> will add anthor empty line |
|
|
|
$title = $mdfile->{title} if $mdfile->{title}; |
|
$body = markdown($text, {tab_width => 2}); |
|
fixlink(); |
|
# postbody(); |
|
response(); |
|
|
|
# read markdown file, save some information with hash |
|
# Text::Markdown fail to handle code block such as |
|
# ```perl |
|
# any code snippet |
|
# ``` |
|
sub prefile |
|
{ |
|
my ($filename) = @_; |
|
my $filemark = {content => [], title => '', tags => [], }; |
|
my $codeblok = 0; |
|
|
|
open(my $fh, '<', $filename) or die "cannot open $filename $!"; |
|
# local $/ = undef; $text = <$fh>; |
|
while (<$fh>) { |
|
# chomp; |
|
# title line |
|
if ($. == 1) { |
|
push(@{$filemark->{content}}, $_); |
|
(my $title = $_ ) =~ s/^[#\s]+//; |
|
$filemark->{title} = $title; |
|
next; |
|
} |
|
# tag line |
|
elsif ($. == 2){ |
|
my @tags = /`([^`]+)`/g; |
|
if (@tags) { |
|
push(@{$filemark->{tags}}, @tags); |
|
next; |
|
} |
|
} |
|
|
|
# begin/end code block ```perl |
|
if (/^\s*```(\S*)\s*$/) { |
|
my $line = $_; |
|
if (!$codeblok) { |
|
$line = qq{<pre><code class="language-$1">}; |
|
$codeblok = 1; |
|
} |
|
else { |
|
$line = qq{</code></pre>\n}; |
|
$codeblok = 0; |
|
} |
|
push(@{$filemark->{content}}, $line); |
|
} |
|
else { |
|
push(@{$filemark->{content}}, $_); |
|
} |
|
} |
|
close($fh); |
|
|
|
return $filemark; |
|
} |
|
|
|
# 回应输出 |
|
sub response |
|
{ |
|
print "Content-type:text/html\n\n"; |
|
print <<EndOfHTML; |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<meta name="viewport" content="width=device-width" /> |
|
<link rel="stylesheet" type="text/css" href="/css/main.css"> |
|
<link rel="stylesheet" type="text/css" href="/css/markdown.css"> |
|
<title> $title </title> |
|
</head> |
|
<body> |
|
$body |
|
</body> |
|
</html> |
|
EndOfHTML |
|
} |
|
|
|
sub debug_query |
|
{ |
|
$body = ""; |
|
while (my ($key, $value) = each %query) { |
|
$body .= "$key => $value<br/>"; |
|
} |
|
} |
|
|
|
sub postbody |
|
{ |
|
$body .= qq{<hr>\n}; |
|
for my $tag (@{$mdfile->{tags}}) { |
|
$body .= qq{<code>$tag</code> }; |
|
} |
|
} |
|
|
|
# fix links from/to home content and prev/next pages |
|
sub fixlink |
|
{ |
|
my $base = $ENV{SCRIPT_NAME}; |
|
my $subname = $query{p}; |
|
if ($subname =~ /^content$/) { |
|
$body =~ s/href="(.+)\.md"/href="$base?p=$1"/g; |
|
} |
|
else { |
|
my ($prev, $next) = findprenext($subname); |
|
my @foot = (); |
|
|
|
push(@foot, "<hr/>"); |
|
$prev ? push(@foot, qq{<a href="$base?p=$prev">Prev</a>}) |
|
: push(@foot, qq{<a>First</a>}); |
|
push(@foot, qq{<a href="$base?p=content">| Home |</a>}); |
|
$next ? push(@foot, qq{<a href="$base?p=$next">Next</a>}) |
|
: push(@foot, qq{<a>Last</a>}); |
|
|
|
$body .= sprintf(qq{\n<div class="foot-link"> %s \n</div>\n}, join("\n", @foot)); |
|
} |
|
} |
|
|
|
# read content.md, find the prev/next page |
|
sub findprenext |
|
{ |
|
my $curname = shift; |
|
my ($prev, $next) = ('', ''); |
|
|
|
my $tocname = "$Bin/content.md"; |
|
return ($prev, $next) unless -f $tocname; |
|
|
|
open(my $fh, '<', $tocname) or die "cannot open $tocname $!"; |
|
my ($prev_may, $cur_may); |
|
while (<$fh>) { |
|
chomp; |
|
next unless /\((\S+)\.md\)/; |
|
$prev_may = $cur_may; |
|
$cur_may = $1; |
|
if ($cur_may eq $curname) { |
|
$prev = $prev_may; |
|
next; |
|
} |
|
if ($prev_may eq $curname) { |
|
$next = $cur_may; |
|
last; |
|
} |
|
} |
|
close($fh); |
|
|
|
return ($prev, $next); |
|
}
|
|
|