From bc55a842dbbaefd479aa950bbe6619c4089a5794 Mon Sep 17 00:00:00 2001 From: crvs Date: Tue, 31 Dec 2019 14:08:55 +0100 Subject: [PATCH] version 2 --- README.md | 42 +++++--- blogconfig | 3 + compilesite | 195 ++++++++++++++++++++++++++++++++++++ deploy | 7 ++ deploy.sh | 11 -- indices/index.md | 2 + indices/tag_useless.md | 1 + makeposts.sh | 154 ---------------------------- otherposts/another_post.md | 8 ++ tags/exampletag/tagindex.md | 3 - 10 files changed, 243 insertions(+), 183 deletions(-) create mode 100644 blogconfig create mode 100755 compilesite create mode 100755 deploy delete mode 100755 deploy.sh create mode 100644 indices/index.md create mode 100644 indices/tag_useless.md delete mode 100755 makeposts.sh create mode 100644 otherposts/another_post.md delete mode 100644 tags/exampletag/tagindex.md diff --git a/README.md b/README.md index 7654563..e4d1f59 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,48 @@ -# Staticsite +# Staticsite (Version 2) -This is a simple static html blog generator using only 278 lines (as of this submission) of shell code. +This is a simple static html blog generator using only 320 lines (as of this submission) of shell code. -## Organization +## Differences from Version 1 + +- Posts can now be spread over several folders. +- Configuration takes place in the file blogconfig instead of the script. +- There is no need for the use of INSERTBASEURL anymore since all html files are contained in the same folder. +- Tagindex files are now located at `tag_.html` +- A post called `.md` located in directory `` is located at `_.html` +- The compilation step does not compile posts that have not been changed. -Posts are placed within the `posts` directory and are written in markdown, and have `.md` extension (anything else can be used to effectively save drafts inplace, for example). +## Organization -Each post begins with a metadata section delimited by lines containing nothing but dashes. +Posts are placed within dedicated directories, written in markdown, and have `.md` extension (anything else can be used to effectively save drafts inplace, for example). +Each post begins with a metadata section delimited by lines containing nothing but dashes `---`. The currently supported metadata is: `title:`, `date:`, `modified:`, `tags:`. -The `tags` line is a space-separated list of tags that you may want to place in the file. +- The `tags` line is a space-separated list of tags that you may want to place in the file. +- The lines with `date` and `modified` are recomended to be in format `YYYY-MM-DD` since these can be easily ordered in lexicographic order. +- The `title` line is the title of the post and it gets rendered as a heading at the top of the post. -The script generates a `tagindex.html` page for each tag in a post, which by default only has the tag name as title and lists the posts tagged with that tag. +The directories used by the script are registered at blogconfig in a line marked `postdirs: ` which is a space separated list of directory names (don't use directory names with spaces). -Optionally, by creating the file `tag//tagindex.md` the rendered markdown can be included above the list of posts. +For each post `directory/post.md` the script compiles it to an html file located at `cache/directory_post.md` (notice the `_`), registers each tag `tagname` in the corresponding `cache/tag_tagname.html` file and registers the post at `index.html`. -The main index.html file is created by providing `tag/MAININDEX/tagindex.md`. +To view the output of the site after compilation simply point your browser to `cache/index.html`. + +Tag files can be enriched with an introduction by writing the corresponding `tag_tagname.md` file in the directory `indices`. Similar, a file named `index.md` in the directory `indices` will be rendered into the `index.html` file. ## Dependencies -The script uses mostly standard tools like sed(1) and awk(1) for text manipulation. The only non-standard tool that it makes use of is the lowdown(1) to compile markdown into html. +The `compilesite` script depends on: +- lowdown (for compiling markdown to html) +- sqlite3 (for keeping a searchable database of the post metadata) ## Running -before running you should change the variables `blogname` and `baseurl` at the top of `makeposts.sh` +before running you should change the `blogconfig` file to reflect your options. -After writing all your posts, the whole thing can be compiled by running `./makeposts` and deployed into the default `/var/www/htdocs` by running `./deploy.sh` as root. +After writing all your posts, the whole thing can be compiled by running `./compilesite` and deployed into the default `/var/www/htdocs` by running `./deploy` as root. ## Notes -This was written in openbsd and there may be slight differences in the syntax for sed and awk commands. - -To generate a locally viewable copy simply run `makeposts.sh local` and the resulting webpage saved in the `deploy` directory should be fully functional +This was written in openbsd and there may be slight differences in the syntax for sed(1) and stat(1). If there is a failure with stat(1) the commented lines next to them run in archlinux. diff --git a/blogconfig b/blogconfig new file mode 100644 index 0000000..fdc52ec --- /dev/null +++ b/blogconfig @@ -0,0 +1,3 @@ +blogtitle: my blog title +baseurl: https://my-url.com +postdirs: posts otherposts diff --git a/compilesite b/compilesite new file mode 100755 index 0000000..16d2614 --- /dev/null +++ b/compilesite @@ -0,0 +1,195 @@ +#!/bin/sh + +yell() { echo ": $*" >&2; } +die () { yell "$*"; exit 111; } +try () { "$@" || die "cannot $*" ; } + +blogtitle=`try sed -n 's/blogtitle: *//p' blogconfig` +postdirs=`try sed -n 's/postdirs: *//p' blogconfig` +baseurl=`try sed -n 's/baseurl: *//p' blogconfig` + +mkdir -p cache + +touch cache/dirtytags +dirty=0 + +# open database +sqlite3 cache/posts.db "create table if not exists posts ( title TEXT, prefix TEXT, date TEXT, modified TEXT, tag TEXT)" + +isnewer () { + new=$1 + old=$2 + ####### in open bsd + newstamp=`stat -f "%Sm" -t "%Y%m%d%H%M%S" $new` + #newstamp=`stat -c "%Y" $new` + if [ ! -f $old ]; then + echo "0" + return 0 + fi + + oldstamp=`stat -f "%Sm" -t "%Y%m%d%H%M%S" $old` + #oldstamp=`stat -c "%Y" $old` + if [ $newstamp -ge $oldstamp ]; then + echo "0" + else + echo "1" + fi + return 0 +} + +processheader () { + # add or update post entry(/ies) in database + fileprefix=$1 + header=cache/$fileprefix.head + title=`sed -n 's/^title: *//p' $header` + date=`sed -n 's/^date: *//p' $header` + modified=`sed -n 's/^modified: *//p' $header` + if [ "$modified" = "" ]; then + modified=$date + fi + sqlite3 cache/posts.db "delete from posts where prefix = \"$fileprefix\"" + tags=`sed -n 's/^tags: *//p' $header` + if [ "$tags" = "" ]; then + sqlite3 cache/posts.db "insert into posts values (\"$title\",\"$fileprefix\",\"$date\",\"$modified\",\"\")" + else + for tag in $tags; do + sqlite3 cache/posts.db "insert into posts values (\"$title\",\"$fileprefix\",\"$date\",\"$modified\",\"$tag\")" + done + fi +} + +htmlhead () { + prefix=$1 + title=`sqlite3 cache/posts.db "select distinct title from posts where prefix = \"$prefix\""` + echo "${blogtitle}:${title}" +} + +dateandtags () { + prefix=$1 + date=`sqlite3 cache/posts.db "select distinct date from posts where prefix = \"$prefix\""` + echo "published: ${date}" + modified=`sqlite3 cache/posts.db "select distinct modified from posts where prefix = \"$prefix\""` + if [ ! "$date" = "$modified" ] ; then + echo "last modified: ${modified}" + fi + echo "
" + tags=`sqlite3 cache/posts.db "select distinct tag from posts where prefix = \"$prefix\""` + for tag in $tags; do + echo $tag >> cache/dirtytags + echo "${tag}" + done +} + + +htmlbody () { + prefix=$1 + title=`sqlite3 cache/posts.db "select distinct title from posts where prefix = \"$prefix\""` + echo "

${blogtitle}

" + echo "

${title}

" + dateandtags $prefix + lowdown -e math cache/${prefix}.body +} + + +metadatawarning() { +post=$1 +cat << EOF +WARNING, there may be a problem with processing metadata in $post, please make +sure that there are exactly 2 instances of lines comprising _only_ dashes at +the head of the file, and containing nothing but the metadata in between. +EOF +grep '^--*$' -n -C1 $post +} + +processpost () { + post=$1 + baseurl=$2 + outprefix=`echo $post | sed 's@/@_@g;s/.md$//'` + recompute=`isnewer $post cache/$outprefix.html` + if [ "$recompute" = "0" ]; then + echo processing $post + dirty=1 + sed -n '/^--*$/,/^--*$/p' $post | sed '1d;$d' > cache/$outprefix.head + sed '/^--*$/,/^--*$/d' $post > cache/$outprefix.body + nbars=`sed -n '/^--*$/p' $post | wc -l` + if [ $nbars -ne 2 ]; then + metadatawarning $post >&2 + fi + processheader $outprefix + htmlbody $outprefix > cache/${outprefix}_body.html + htmlhead $outprefix > cache/${outprefix}_head.html + ./html-templater -h cache/${outprefix}_head.html cache/${outprefix}_body.html > cache/${outprefix}.html + # rm cache/${outprefix}_body.html cache/${outprefix}_head.html cache/${outprefix}.head cache/${outprefix}.body + fi +} + +processdir () { + dir=$1 + baseurl=$2 + + # fail if directory doesn't exist + [ -d $dir ] || die "FAILED no such directory \"$dir\"" + + # fail silently if directory doesn't have posts + for post in `ls $dir/*.md 2>/dev/null`; do + processpost $post $baseurl + done +} + +makeindex () { + headfile=cache/index_head.html + bodyfile=cache/index_body.html + printf "${blogtitle}" > $headfile + printf "

%s

\n" $blogtitle > $bodyfile + if [ -f "indices/index.md" ]; then + lowdown -e math indices/index.md | sed "s@INSERTBASEURL@$baseurl@g" >> $bodyfile + fi + echo >> $bodyfile + prefixes=`sqlite3 cache/posts.db "select distinct prefix from posts order by date desc"` + for prefix in $prefixes; do + indexline $prefix >> $bodyfile + done + ./html-templater -h $headfile $bodyfile > cache/index.html + rm $headfile $bodyfile +} + +maketagindex () { + tags=`cat cache/dirtytags | sort | uniq` + for tag in $tags; do + headfile=cache/tag_${tag}_head.html + bodyfile=cache/tag_${tag}_body.html + printf "${blogtitle} - ${tag} (tag)" > $headfile + printf "

%s

\n" $blogtitle > $bodyfile + printf "

%s

\n" $tag >> $bodyfile + if [ -f "indices/tag_${tag}.md" ]; then + lowdown -e math indices/tag_${tag}.md | sed "s@INSERTBASEURL@$baseurl@g" >> $bodyfile + fi + echo >> $bodyfile + prefixes=`sqlite3 cache/posts.db "select distinct prefix from posts where tag = \"$tag\" order by date desc"` + for prefix in $prefixes; do + indexline $prefix >> $bodyfile + done + ./html-templater -h $headfile $bodyfile > cache/tag_${tag}.html + rm $headfile $bodyfile + done +} + +indexline () { + prefix=$1 + title=`sqlite3 cache/posts.db "select distinct title from posts where prefix = \"$prefix\""` + printf "

%s

\n" "$title" + dateandtags $prefix +} + +# process each of the directories +for dir in $postdirs; do + try processdir $dir $baseurl +done + +# reindex +maketagindex +if [ $dirty = 1 ]; then + makeindex +fi + +# vi: et ts=4 sts=4 : diff --git a/deploy b/deploy new file mode 100755 index 0000000..e29053f --- /dev/null +++ b/deploy @@ -0,0 +1,7 @@ +#!/bin/sh + +for file in cache/*.html; +do + filename=${file##cache/} + install -m 500 -o www -g www cache/$filename /var/www/htdocs/$filename +done diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index d6a2844..0000000 --- a/deploy.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -for dir in `du deploy | sed -n -E 's/^[0-9]+[ ]deploy\/*//;/^./p'`; -do - install -m 500 -o www -g www -d /var/www/htdocs/$dir -done - -for file in `du -a deploy | sed -n -E 's/^[0-9]+[ ]deploy\/*//;/.html$/p'`; -do - install -m 500 -o www -g www deploy/$file /var/www/htdocs/$file -done diff --git a/indices/index.md b/indices/index.md new file mode 100644 index 0000000..db86fe3 --- /dev/null +++ b/indices/index.md @@ -0,0 +1,2 @@ +Welcome to my new static website! +Behold how nothing moves! diff --git a/indices/tag_useless.md b/indices/tag_useless.md new file mode 100644 index 0000000..02ce77d --- /dev/null +++ b/indices/tag_useless.md @@ -0,0 +1 @@ +This tag is utterly useless. diff --git a/makeposts.sh b/makeposts.sh deleted file mode 100755 index bee13e8..0000000 --- a/makeposts.sh +++ /dev/null @@ -1,154 +0,0 @@ -#!/bin/sh - -blogname="MY BLOG" -baseurl=https://my_base_url.xyz - -if [ "$1" = "local" ] - then baseurl=file:///`pwd`/deploy -fi - -runmarkdown () { - lowdown -e math $1 | sed "s@INSERTBASEURL@${baseurl}@g" -} - -maketagindex () { - manifest=$1 - tag=$2 - baseurl=$3 - cat $manifest | sort -r | awk -F';' -v T=$tag -v O=$baseurl/posts/ ' - { - if ( $4 == T ) { - printf("

%s

\n",O,$3,$2) - printf("
published: %s
\n",$1) - } - }' -} - -getheader () { - awk ' - BEGIN{ - printing = 0; - printed = 0; - skip = 0; - } - { - if ($0 ~ "^-+$") { - if (printing == 0) { - printing = 1; - } else if( printing == 1) { - printed = 1; - printing = 0; - } - skip = 1; - } - if (printing == 1 && printed == 0 && skip == 0) { - print $0;} - skip=0 - }' $1 -} - - -getbody () { - awk ' - BEGIN{ - printing = 0; - inheader = 0; - skip = 0; - } - { - if ($0 ~ "^-+$") { - if (inheader == 0) { - inheader = 1; - } else if( inheader == 1) { - inbody = 1; - inheader = 0; - } - skip = 1; - } - if (inheader == 0 && inbody == 1 && skip == 0) { - print $0;} - skip=0 - }' $1 -} - -headfile=`mktemp` -bodyfile=`mktemp` - -htmlhead=`mktemp` -htmlbody=`mktemp` - -postmanifest=`mktemp` - -for file in `ls -1 posts/*.md`; -do - file=${file##posts/} - outfile=${file%%.md}.html - - getheader posts/$file > $headfile - getbody posts/$file > $bodyfile - - mkdir -p deploy/posts - - # add the title to head - title=`cat $headfile | sed -n 's/^title: *//p'` - printf "%s: %s" "$blogname" "$title" > $htmlhead - - # add the title to body - echo "" > $htmlbody - printf "
home
\n" "$baseurl" >> $htmlbody - printf "

%s

\n" "$title" >> $htmlbody - - # add date to the body - origdate=`cat $headfile | sed -n 's/^date: *//p'` - modidate=`cat $headfile | sed -n 's/^modified: *//p'` - - printf "%s" '' >> $htmlbody - - runmarkdown $bodyfile >> $htmlbody - - for tag in `cat $headfile | sed -n 's/^tags://p'`; - do - mkdir -p deploy/tags/$tag - printf '' $baseurl $tag >> $htmlbody - echo "$tag " >> $htmlbody - echo ${origdate}\;${title}\;${outfile}\;${tag} >> $postmanifest - done - - ./html-templater -h $htmlhead $htmlbody > deploy/posts/$outfile - echo ${origdate}\;${title}\;${outfile}\;MAININDEX >> $postmanifest -done - -# make the indices using the postmanifest - -tagindexraw=`mktemp` -for tag in `ls deploy/tags`; -do - tagindexfile=deploy/tags/$tag/tagindex.html - echo > $tagindexraw - if [ -f tags/$tag/tagindex.md ]; then - runmarkdown tags/$tag/tagindex.md >> $tagindexraw - fi - printf "
home
\n" "$baseurl" >> $tagindexraw - echo "

Post list:

" >> $tagindexraw - maketagindex $postmanifest $tag $baseurl >> $tagindexraw - ./html-templater -h $htmlhead $tagindexraw > $tagindexfile -done - - -echo > $tagindexraw -if [ -f tags/MAININDEX/tagindex.md ]; then - runmarkdown tags/MAININDEX/tagindex.md >> $tagindexraw -fi -echo "

Post list:

" >> $tagindexraw -maketagindex $postmanifest MAININDEX $baseurl >> $tagindexraw -./html-templater -h $htmlhead $tagindexraw > deploy/index.html - -rm $headfile $bodyfile -rm $htmlhead $htmlbody -rm $tagindexraw -rm $postmanifest -# vim: et ts=4 sts=4 diff --git a/otherposts/another_post.md b/otherposts/another_post.md new file mode 100644 index 0000000..161ef83 --- /dev/null +++ b/otherposts/another_post.md @@ -0,0 +1,8 @@ +--- +title: another post +date: 2019-12-30 +modified: 2019-12-31 +tags: useless +--- + +this post is in another directory diff --git a/tags/exampletag/tagindex.md b/tags/exampletag/tagindex.md deleted file mode 100644 index 75a3aa1..0000000 --- a/tags/exampletag/tagindex.md +++ /dev/null @@ -1,3 +0,0 @@ -# Example tag - -this tag deserves its own little page explaining what it is all about