Erst einmal guten Tag, freut mich, dass du meinen Blog gefunden hast. Ehrlich gesagt ist das noch mehr Baustelle, aber eventuell findet sich hier schon etwas Interessantes. Genauer gesagt möchte ich in diesem Post etwas genauer auf die erwähnte Baustelle eingehen.
Ich habe mir ein paar Blogging Platformen oder überhaupt Plattformen zur Erstellung von Webseiten angeschaut, doch entweder waren diese mir zu langsam, benötigten JavaScript, damit sie überhaupt funktionierten oder haben mich beim Installieren wegen ihren Abhängigkeiten abgeschreckt. Außerdem habe ich sehr genaue Vorstellungen, wie das Ergebnis von dem, was ich schreibe aussehen soll. Dementsprechend wäre es die beste Lösung, wenn ich alles von Hand in Html schreibe. Genau das mache ich jetzt auch. Bis auf dass ich nicht jedes Mal den Htmlboilerplatecode schreibe, dafür habe ich mir ein Script geschrieben, dass mir aus einem einfachen Text in einer Datei mit ein paar Tags meine Webseite baut. Effektiv sieht dieser Blogpost so aus:
1[title] 2Backend dieser Webseite oder ich bin faul, mag kein JavaScript und lerne gerade Perl 3[date] 42016-12-19T02:00 5[content] 6<p>Erst einmal guten Tag, freut mich, dass du meinen Blog gefunden hast. Ehrlich 7gesagt ist das noch mehr Baustelle, aber eventuell findet sich hier schon etwas 8Interessantes. Genauer gesagt möchte ich in diesem Post etwas genauer auf die 9erwähnte Baustelle eingehen.</p> 10<p>Ich habe mir ein paar Blogging Platformen oder überhaupt Plattformen zur 11Erstellung von Webseiten angeschaut, doch entweder waren diese mir zu langsam, 12benötigten JavaScript, damit sie überhaupt funktionierten oder haben mich beim 13Installieren wegen ihren Abhängigkeiten abgeschreckt. Außerdem habe ich sehr 14genaue Vorstellungen, wie das Ergebnis von dem, was ich schreibe aussehen soll. 15Dementsprechend wäre es die beste Lösung, wenn ich alles von Hand in Html 16schreibe. Genau das mache ich jetzt auch. Bis auf dass ich nicht jedes Mal den 17Htmlboilerplatecode schreibe, dafür habe ich mir ein Script geschrieben, dass 18mir aus einem einfachen Text in einer Datei mit ein paar Tags meine Webseite 19baut. Effektiv sieht dieser Blogpost so aus:</p> 20 21[code] 22website-backend/blogpost 23 24<p>Die Tags sind dabei relativ selbsterklärend.</p> 25<ul> 26<li>[title] ist der Titel, damit der auch in alle passenden Tags eingebaut 27werden kann und in die Überschrift kommt</li> 28<li>[date] ist das Datum in ISO8601</li> 29<li>[content] ist effektiv Html, das ohne weitere Bearbeitung, bis auf ersetzen 30von Umlauten, ß, etc in die resultierende Datei kopiert wird.</li> 31<li>[code] ist die Außnahme von dieser Regel, wenn dieser Tag auftaucht, wird 32die Codedatei, die in der nächsten Zeile angegeben ist, in den Post 33kopiert.</li> 34</ul> 35 36<p>Das Perlskript, dass das alles macht ist folgendes:</p> 37 38[code] 39website-backend/webcc 40 41<p>Sehen wir mal davon ab, dass ich an diesem Skript Perl gelernt habe und ich 42mir keine Mühe gebe, sauberen Code zu schreiben. Ich hatte auf jeden Fall sehr 43viel Spaß daran und flexibler geht es kaum.</p> 44 45<p>Um die ganze Webseite mit den gesamten Abhängigkeiten und so weiter zu 46kompilieren, habe ich noch ein zweites Skript, dass ich bloß ausführen muss und 47dann die Ordner für Nginx an die richtige Stelle kopieren. Das achtet auch 48darauf, dass alles in der richtigen Reihenfolge erstellt wird (z.B. zuerst der 49Code mit vim gehighlightet wird) und erstellt auch die nach Datum oder Titel 50sortierten Listen.</p> 51<p>Hier das Skript:</p> 52 53[code] 54website-backend/webmake 55 56<p>So, ich versuche jetzt mal, ob das auch funktioniert und mache mich dann mal 57an den CSS Part. Schönen Abend noch!</p>
Die Tags sind dabei relativ selbsterklärend.
-
[title] ist der Titel, damit der auch in alle passenden Tags eingebaut werden kann und in die Überschrift kommt
-
[date] ist das Datum in ISO8601
-
[content] ist effektiv Html, das ohne weitere Bearbeitung, bis auf ersetzen von Umlauten, ß, etc in die resultierende Datei kopiert wird.
-
[code] ist die Außnahme von dieser Regel, wenn dieser Tag auftaucht, wird die Codedatei, die in der nächsten Zeile angegeben ist, in den Post kopiert.
Das Perlskript, dass das alles macht ist folgendes:
1#!/usr/bin/perl -CSD 2use warnings; 3use strict; 4use v5.22; 5 6use File::Path qw(make_path); 7use DateTime::Format::ISO8601; 8use POSIX qw(strftime); 9use HTML::Entities; 10 11my $FH; 12 13# default definitions 14my $domain = "nekodev"; 15my $date_html = ''; 16my $date_str = ''; 17my $title = ''; 18my $outputFile; 19 20# mapping from domains (to navigation current page, output dir, etc) 21my %id_cur_page = ( 22 'nekodev' => '', 23 'blog.nekodev' => '', 24 'code.nekodev' => '' 25); 26 27my %output_dir = ( 28 'nekodev' => '../nekodev', 29 'blog.nekodev' => '../blog.nekodev', 30 'code.nekodev' => '../code.nekodev', 31 32 'code-tmp' => '../code-tmp', 33 '' => '../tmp', 34 'tmpdir' => '../tmp' 35); 36 37 38 39# parse file name 40my $argvSize = 0+@ARGV; 41if ($argvSize > 0) { 42 warn 'Processing: '.$ARGV[0]."\n"; 43 44 die "too many arguments" if $argvSize > 1; 45 46 my ($basename,$fileext) = $ARGV[0] =~ /(.*)\.(.*)/; 47 48 print ' type: '.$fileext."\n"; 49 $domain = "nekodev" if $fileext eq "web"; 50 $domain = "blog.nekodev" if $fileext eq "blog"; 51 $domain = "code.nekodev" if $fileext eq "code"; 52 53 # open output file 54 $outputFile = $output_dir{$domain}.'/'.$basename.'.html'; 55 56 warn $outputFile, "\n"; 57 58 make_path($outputFile =~ /(.*)\//); 59 open($FH, '>', $outputFile) or die "cannot open file $outputFile: $!"; 60 select $FH; 61} 62 63 64# parse file parameters 65$id_cur_page{$domain} = 'id="cur-navpage"'; 66 67while (<<>>) { 68 chomp; 69 my $currentTag = $_; 70 $currentTag eq '[title]' and chomp($title = <<>>); 71 72 if ($currentTag eq '[date]') { 73 chomp($date_str = <<>>); 74 my $date = DateTime::Format::ISO8601->parse_datetime( $date_str ); 75 76 # make sure we have the right format 77 $date_str = $date->iso8601; 78 79 # format nice <time> tag with locale dependent text 80 $date->set_locale('de-DE'); 81 #my $localeDate_str = $date->strftime('%c'); 82 my $localeDate_str = $date->strftime('%A, %d. %B %Y, %H:%M'); 83 $date_html = "<time datetime=$date_str>$localeDate_str</time>"; 84 } 85 86 last if $currentTag eq "[content]"; 87} 88 89 90# write content 91print<<EOF; 92<html> 93 <head> 94 <meta charset="utf-8"/> 95 <title>$title - $domain</title> 96 <link title="dark" rel="stylesheet" type="text/css" href="colors-dark.css"/> 97 <link title="light" rel="alternate stylesheet" type="text/css" href="colors-light.css"/> 98 <link rel="stylesheet" type="text/css" href="stylesheet.css"/> 99 <meta name="viewport" content="width=device-width, initial-scale=1"> 100 </head> 101 <body> 102 <nav id="navbar"> 103 <ul> 104 <li $id_cur_page{'nekodev'} tabindex="1"> 105 <a href="http://nekodev.net/index.html">Home</a> 106 <ul> 107 <li tabindex="2"><a href="http://nekodev.net/projects.html">Projects</a></li> 108 <li tabindex="3"><a href="http://nekodev.net/about.html">About</a></li> 109 </ul> 110 <li $id_cur_page{'blog.nekodev'} tabindex="4"> 111 <a href="http://blog.nekodev.net">Blog</a> 112 <ul> 113 <li tabindex="5"><a href="http://blog.nekodev.net/alpha_index.html">Nach Titel</a></li> 114 <li tabindex="6"><a href="http://blog.nekodev.net/date_index.html">Nach Datum</a></li> 115 </ul> 116 </li> 117 </li> 118 <li $id_cur_page{'code.nekodev'} tabindex="7"> 119 <a href="http://code.nekodev.net">Code</a> 120 <ul> 121 <li tabindex="8"><a href="test.html">Test</a></li> 122 </ul> 123 </li> 124 </ul> 125 </nav> 126 <h1>$title</h1> 127 $date_html 128EOF 129 130while (<<>>) 131{ 132 # insert code when referenced by code tag 133 if ($_ eq "[code]\n") 134 { 135 chomp ( my $codefile = <<>> ); 136 open my $codefh, "<", $output_dir{'code-tmp'}.'/'.$codefile.'.code' or die "cant find code file $codefile: $!"; 137 while ( <$codefh> ne "[content]\n" ) {}; 138 print while <$codefh>; 139 } 140 141 my $encoded = encode_entities($_, '^\n\x20-\x25\x27-\x7e'); 142 print $encoded if defined $encoded; 143} 144 145print<<EOF; 146 </body> 147</html> 148EOF 149 150close $FH if defined $FH; 151 152 153# build blog index 154if ($domain eq 'blog.nekodev' and defined $outputFile) { 155 open my $blogIndexFile, '>>', $output_dir{'tmpdir'}.'/blog_index'; 156 $outputFile =~ s/$output_dir{'blog.nekodev'}\///; 157 print {$blogIndexFile} <<EOF; 158$outputFile 159$title 160$date_str 161EOF 162}
Sehen wir mal davon ab, dass ich an diesem Skript Perl gelernt habe und ich mir keine Mühe gebe, sauberen Code zu schreiben. Ich hatte auf jeden Fall sehr viel Spaß daran und flexibler geht es kaum.
Um die ganze Webseite mit den gesamten Abhängigkeiten und so weiter zu kompilieren, habe ich noch ein zweites Skript, dass ich bloß ausführen muss und dann die Ordner für Nginx an die richtige Stelle kopieren. Das achtet auch darauf, dass alles in der richtigen Reihenfolge erstellt wird (z.B. zuerst der Code mit vim gehighlightet wird) und erstellt auch die nach Datum oder Titel sortierten Listen. Hier das Skript:
1#!/usr/bin/perl -CSD 2use warnings; 3use strict; 4use v5.22; 5 6use File::Path qw(make_path remove_tree); 7use DateTime; 8use DateTime::Format::ISO8601; 9use File::pushd; 10use Text::VimColor; 11 12my %output_dir = ( 13 'nekodev' => '../nekodev', 14 'blog.nekodev' => '../blog.nekodev', 15 'code.nekodev' => '../code.nekodev', 16 '' => '../tmp', 17 'tmpdir' => '../tmp' 18); 19 20my %src_dirs = ( 21 'code-tmp' => 'code-tmp', 22 'blog' => 'blog', 23 'web' => 'web' 24); 25 26 27my $blog_index = $output_dir{'tmpdir'}.'/blog_index'; 28 29sub make { 30 foreach(@_) { 31 system($^X, '-CSD', "../webcc", $_) if (-f $_); 32 #`perl -d webcc $_` if (-f $_); 33 if (-d $_) { 34 print "Processing directory $_\n"; 35 36 my $dirGlob = $_.'/*'; 37 make(glob $dirGlob); 38 } 39 } 40} 41 42sub make_code_highlight { 43 44 foreach(@_) { 45 if (-f $_) { 46 #$highlighter->syntax_mark_file($_); 47 # need to overwrite vim options, as nvim doesn't provide -X flag 48 my @vim_opts = [qw( -RZ -i NONE -u NONE -N -n ), "+set nomodeline"]; 49 my @extra_vim_opts = ['+setg number', '+set printoptions=number:y']; 50 my $highlighter = Text::VimColor->new( 51 file => $_, 52 all_syntax_groups => 1, 53 vim_command => 'nvim', 54 vim_options => @vim_opts, 55 extra_vim_options => @extra_vim_opts 56 ); 57 58 my $modDate = DateTime->from_epoch( epoch => (stat $_)[9])->iso8601(); 59 my $outFileName = $_ =~ s/^code\//code-tmp\//r; 60 $outFileName .= ".code"; 61 my ($dir,$saneFileName) = $_ =~ /(.*)\/(.*)/; 62 make_path($dir); 63 print "outputting file $outFileName\n"; 64 65 open my $out_file, '>', $outFileName or die "Can't open out file $outFileName: $!"; 66 print {$out_file} "[title]\n$saneFileName\n[date]\n$modDate\n[content]\n<pre>\n"; 67 68 $saneFileName =~ s/\./_/g; 69 my $lineNr = 1; 70 foreach(split /^/, $highlighter->html) { 71 my $lineId = 'L'.$lineNr.$saneFileName; 72 print {$out_file} "<span id=\"$lineId\" class=\"synLineNr\">$lineNr </span>".$_; 73 $lineNr++; 74 } 75 print {$out_file} "</pre>\n"; 76 close $out_file; 77 } 78 79 if (-d $_) { 80 print "Processing directory $_\n"; 81 my $dirGlob = $_.'/*'; 82 make_code_highlight(glob $dirGlob); 83 } 84 } 85} 86 87 88# setup tmpdirs 89{ 90 my $dir = pushd($src_dirs{'blog'}); 91 remove_tree($output_dir{'tmpdir'}); 92 make_path($output_dir{'tmpdir'}); 93} 94 95make_code_highlight('code'); 96 97foreach(values %src_dirs) 98{ 99 my $dir = pushd($_); 100 make(glob '*'); 101} 102 103 104#make(@ARGV); 105 106# build blog.nekodex index.html 107{ 108my $dir = pushd('tmp'); 109my %post2title; 110my %post2date; 111 112open (my $FH, '<', $blog_index) or die "can't open blog_index file, no blog post or serious error: $!"; 113while( my $post = <$FH> ) { 114 chomp $post; 115 116 117 chomp( my $title = <$FH>); 118 chomp( my $date = <$FH>); 119 120 if( $date ne '' and $title ne '' ) 121 { 122 $post2title{$post} = $title; 123 $post2date{$post} = $date; 124 } 125} 126close $FH; 127 128# traverse by date 129my $date_index = <<EOF; 130[title] 131Blogposts nach Datum sortiert 132[content] 133EOF 134 135my $lastMonth; 136foreach my $post (sort { $post2date{$a} cmp $post2date{$b} } keys %post2date) { 137 my $date_str = $post2date{$post}; 138 my $date = DateTime::Format::ISO8601->parse_datetime( $date_str ); 139 # format with locale dependent text 140 $date->set_locale('de-DE'); 141 my $localeDate_str = $date->strftime('%A, %d. %B %Y, %H:%M'); 142 143 my $curMonth = $date->strftime('%B %Y'); 144 if (defined $lastMonth) { 145 if ($curMonth ne $lastMonth) { 146 $date_index .= "</ul><li><time datetime=<time datetime=$date_str>$curMonth</time></li><ul>\n"; 147 $lastMonth = $curMonth; 148 } 149 } else { 150 $date_index .= "<ul><li><time datetime=<time datetime=$date_str>$curMonth</time></li><ul>\n"; 151 $lastMonth = $curMonth; 152 } 153 154 my $pattern = $output_dir{'blog.nekodev'}."\/"; 155 my $linkPath = $post; 156 $linkPath =~ s/$pattern//; 157 $date_index .= "<li><a href=\"$linkPath\">$post2title{$post} | <time datetime=$date_str>$localeDate_str</time></a></li>\n"; 158} 159$date_index .= "</ul></ul>\n"; 160 161# We're in tmpdir 162my $tmp_blog_index = 'date_index.blog'; 163 164open (my $date_index_fh, '>', $tmp_blog_index) or die "can't open date_index file: $!"; 165print {$date_index_fh} $date_index; 166close $date_index_fh; 167 168system($^X, '-CSD', "../webcc", $tmp_blog_index); 169 170 171# build alphabeticat index of posts 172my $alphaIndex =<<EOF; 173[title] 174Blogposts alphabetisch sortiert 175[content] 176<ul> 177EOF 178 179foreach my $post (sort { $post2title{$a} cmp $post2title{$b} } keys %post2title) { 180 my $pattern = $output_dir{'blog.nekodev'}."\/"; 181 my $linkPath = $post; 182 $linkPath =~ s/$pattern//; 183 $alphaIndex .= "<li><a href=\"$linkPath\">$post2title{$post}</li>\n"; 184} 185$alphaIndex .= "</ul>\n"; 186 187 188# We're in tmpdir 189my $tmp_alpha_index = 'alpha_index.blog'; 190 191open (my $alpha_index_fh, '>', $tmp_alpha_index) or die "can't open alpha_index file: $!"; 192print {$alpha_index_fh} $alphaIndex; 193close $alpha_index_fh; 194 195system($^X, '-CSD', "../webcc", $tmp_alpha_index); 196}
So, ich versuche jetzt mal, ob das auch funktioniert und mache mich dann mal an den CSS Part. Schönen Abend noch!