commit 73c283bf71f247c83024cb0060d046119934e552
parent 7e93628b0e2800455d91acbd650b2a1eda273ee0
Author: torresjrjr <b.torres.edu@gmail.com>
Date: Mon, 25 May 2020 02:05:15 +0100
Add first pdssg and README.md
Diffstat:
A | README.md | | | 79 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | pdssg | | | 196 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 275 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
@@ -0,0 +1,79 @@
+# pdssg - pandoc static site generator
+
+A shell script which generates a static site and Atom feed from Markdown files
+with pandoc.
+
+## Requirements
+
+* sh
+* pandoc
+
+## Installation
+
+Go to one directory above your website source directory, and `git clone` the
+pdssg repo.
+
+```sh
+$ pwd
+/home/user/website
+$ ls
+src
+$ git clone https://github.com/torresjrjr/pdssg
+$ ls
+pdssg src
+```
+
+You should now have an executable is a single shell script `./pdssg/pdssg`.
+
+## Usage
+
+pdssg is a single executable shell script, with an optional `config.sh` script,
+and no command-line flags. It simply generates a site from an exiting `src/`
+directory.
+
+```sh
+$ ./pdssg/pdssg
+```
+
+pdssg's design is modular. It requires a neighboring `src/` directory with the
+site contents (Markdown files to be converted to HTML). Here's an example site.
+
+```
+src/
+|-- index.md
+|-- about.md
+|-- archive.md
+|-- archive/
+| |--- 2020-01-01-new-year.md
+| |--- 2020-02-01-corona-what.md
+| `--- 2020-03-01-stuck-at-home.md
+`-- feed/
+ `--- atom.md
+```
+
+pdssg expects Markdown files to have a YAML frontmatter block, which is an
+initial block of YAML metadata surrounded by a pair of `---`. The frontmatter
+should at least have a `title:` value.
+
+```
+---
+title: My Webpage Title
+author: John Smith
+date: 2020-12-30
+---
+
+contents...
+```
+
+When pdssg is executed, it copies the `src/` directory to `dst/` and converts
+all markdown files (ending in `.md`) to HTML, except for files in the
+sub-directories `ast` (assets), `pub` (public), and `feed` (atom feed).
+
+## Author's notes
+
+This was originally a farily personal script I made to challange myself, and to
+generate my own site. At the request of a friendly blogger, I made it public.
+
+You can contact me at my Telegram: [t.me/torresjrjr](https://t.me/torresjrjr).
+I'll more likely respond there.
+
diff --git a/pdssg b/pdssg
@@ -0,0 +1,196 @@
+#!/usr/bin/sh
+
+main() {
+ echo "### Begin compiling ###"
+
+ # User options
+ source "$(dirname $0)/config.sh"
+ POSTS_DIR="${POSTS_DIR:-./archive}"
+ ATOM_FILE="${ATOM_FILE:-./feed/atom.md}"
+ ATOM_OUT="${ATOM_OUT:-./feed/atom.xml}"
+
+ prepare_dst
+
+ MD_FILES=$(find . -regex '.*\.md' | sed '/^\.\/\(_.*\|ast\|pub\|feed\)/d')
+ CACHE_FILE="./_tmp/posts_metadata.yaml"
+
+ cache_posts_metadata $POSTS_DIR
+ process_files $MD_FILES
+ make_atom_feed
+ clearup_files $MD_FILES
+ finish
+
+ echo "### End compiling ###"
+}
+
+
+# main functions
+
+prepare_dst() {
+ echo "# Preparing ./dst/ directory."
+ echo :: $(pwd)
+
+ [ -d ./src/ ] || {
+ echo "No ./src/ directory. Exiting"
+ exit
+ }
+
+ [ -d ./dst/ ] && {
+ echo "Removing previous ./dst/ build"
+ rm -r ./dst/*
+ }
+
+ echo "Copying from ./src/ to ./dst/"
+ cp -r ./src/* ./dst/
+
+ cd ./dst/
+ echo :: $(pwd)
+}
+
+cache_posts_metadata() {
+ echo "# Preparing post metadata."
+
+ posts_dir=$1
+
+ echo "posts:" > $CACHE_FILE
+
+ for post in $posts_dir/*
+ do
+ echo " -" >> $CACHE_FILE
+
+ post_yaml="$(_get_yaml_block $post)"
+ filename=$(basename $post)
+ slug_attr="slug: ${filename%.md}"
+ yaml_block="$(echo -e "$post_yaml\n$slug_attr" | sed 's/^/ /')"
+
+ echo "$yaml_block" >> $CACHE_FILE
+ done
+
+ cat $CACHE_FILE
+}
+
+process_files() {
+ echo "# Processing Markdown files."
+
+ for md_file in $@
+ do
+ # feedback
+ echo -e "Processing:\t$md_file"
+
+ dirname="$( dirname "$md_file" )"
+ basename="$( basename "$md_file" )"
+ block="$( _get_yaml_block "$md_file" )"
+
+ new_filepath=${md_file%.md}.html
+ #echo -e "Target path:\t$new_filepath"
+
+ bool_toc="$(_get_slug toc "$block")"
+ [ -n "$bool_toc" ] && flag_toc="--toc"
+
+ ### per file logic ###
+ [ "$md_file" == "$POSTS_DIR.md" ] && {
+ flag_metadata_file="--metadata-file=$CACHE_FILE"
+ }
+
+ ### create full HTML page ###
+ pandoc \
+ -f markdown -t html \
+ $md_file -o $new_filepath \
+ --standalone \
+ -M lang:en \
+ --template=./_templates/main.html \
+ -H ./_includes/meta.html \
+ -B ./_includes/header.html \
+ -A ./_includes/footer.html \
+ --email-obfuscation=references \
+ --highlight-style=breezedark \
+ $flag_toc \
+ $flag_metadata_file
+
+
+ ### prepare for next md file
+ # unset pandoc args just in case
+ unset md_file
+ unset new_filepath
+ unset flag_toc
+ unset flag_metadata_file
+
+ # feedback
+ #echo "done $md_file"
+ done
+}
+
+make_atom_feed() {
+ echo "# Making atom feed."
+ echo "Making base feed document"
+
+ pandoc \
+ -f markdown -t html \
+ $ATOM_FILE -o $ATOM_OUT \
+ -M lang:en \
+ --standalone \
+ --template=./_templates/atom.xml \
+ --metadata-file=$CACHE_FILE
+
+ rm -v $ATOM_FILE
+ cat $ATOM_OUT > ./_tmp/atom.xml
+
+ echo "Inserting contents"
+ for post in $POSTS_DIR/*.html
+ do
+ echo -e "Inserting:\t$post"
+
+ sed -n '/<!--CONTENT-->/,$!p' ./_tmp/atom.xml > ./_tmp/before.xml
+ cat "$post" | sed -n '/<article>/,/<\/article>/p' > ./_tmp/content.xml
+ sed -n '1,/<!--CONTENT-->/!p' ./_tmp/atom.xml > ./_tmp/after.xml
+ cat ./_tmp/{before,content,after}.xml > ./_tmp/atom.xml
+ done
+
+ echo "Finishing feed"
+ cat ./_tmp/atom.xml > $ATOM_OUT
+}
+
+clearup_files() {
+ echo "# Clearing up Markdown files."
+
+ rm -v $@
+ rm -rv $( find . -path './_*' -type d )
+}
+
+finish() {
+ echo "# Finished compiling."
+
+ cd ..
+ echo :: $(pwd)
+ echo "Finished"
+}
+
+
+# util functions
+
+_get_yaml_block() {
+ md_file="$1"
+ block="$(sed -n -e '1,/---/p' $md_file | grep -v '\-\-\-')"
+ echo "$block"
+}
+
+_get_slug() {
+ key="$1"
+ block="$2"
+
+ line=$(echo "$block" | grep "^$key\s*:\s*")
+ title=$(echo $line | sed -e "s/^$key\s*:\s*//")
+ slug=$(echo $title | sed -e 's/\s*$//' -e 's/\s\+/-/g')
+ neatslug=$(
+ echo $slug \
+ | tr '[:upper:]' '[:lower:]' \
+ | tr -cd "[:alpha:][:digit:]-"
+ )
+ echo $neatslug
+}
+
+
+# main
+
+main
+