diff options
| author | Paul Buetow <git@mx.buetow.org> | 2021-05-21 05:18:10 +0100 |
|---|---|---|
| committer | Paul Buetow <git@mx.buetow.org> | 2021-05-21 05:18:10 +0100 |
| commit | 85df071aa1a5aa73328fdc5969d3ca0ed9df2c08 (patch) | |
| tree | ec8c11c9e1ad5dfa02c15e57212b239b75e52c87 | |
| parent | 9dbd7f008192fd506bf642944232334fad0ed55c (diff) | |
add readme
| -rw-r--r-- | LICENSE | 24 | ||||
| -rw-r--r-- | README.md | 108 | ||||
| -rw-r--r-- | buetow.org.conf | 9 | ||||
| -rwxr-xr-x | buetow.org.sh | 107 | ||||
| -rw-r--r-- | footer.html.part | 2 | ||||
| -rw-r--r-- | header.html.part | 50 | ||||
| -rw-r--r-- | packages/assert.source.sh | 59 | ||||
| -rw-r--r-- | packages/atomfeed.source.sh | 128 | ||||
| -rw-r--r-- | packages/gemfeed.source.sh | 54 | ||||
| -rw-r--r-- | packages/generate.source.sh | 160 | ||||
| -rw-r--r-- | packages/git.source.sh | 50 | ||||
| -rw-r--r-- | packages/html.source.sh | 162 | ||||
| -rw-r--r-- | packages/log.source.sh | 30 | ||||
| -rw-r--r-- | packages/md.source.sh | 63 |
14 files changed, 2 insertions, 1004 deletions
diff --git a/LICENSE b/LICENSE deleted file mode 100644 index fdddb29a..00000000 --- a/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to <https://unlicense.org> @@ -1,110 +1,6 @@ The buetow.org internet site ============================ -This is the source code of my personal internet site and blog engine. All content is written in Gemini Gemtext format, but the script `buetow.org.sh` generates multiple other static output formats from it. You can reach the site(s)... +This repository contains the static files of my internet site. [gemini://buetow.org](gemini://buetow.org) and [https://buetow.org](https://buetow.org). -* Via Gemini/Gemtext: [gemini://buetow.org](gemini://buetow.org) (You need a Gemini client for this) -* Via "normal" HTML: [https://buetow.org](https://buetow.org) (Actually it's XHTML Transitional 1.0) -* Via [Gemini Webproxy](https://portal.mozz.us/gemini/buetow.org) -* Via [GitHub Markdown](https://github.com/snonux/buetow.org/blob/content-md/index.md) -* Via [GitHub Page](https://snonux.github.io/buetow.org) (from Markdown) - -Have a look at the `content-*` branches of this buetow.org Git project for source samples. - -## Software I use to maintain this site - -* Text editor: [Vim](https://www.vim.org) -* Gemini server: [a-h/gemini](https://github.com/a-h/gemini) -* Bash -* ShellCheck (if you want to run the tests) -* Web server: [Apache HTTPD](https://httpd.apache.org) (for "normal" HTML site) -* Obviously, I am also using GitHub for source code and GitHub Page hosting. - -# Getting started - -## Requirements - -These are the requirements of the `buetow.org.sh` static site generator script: - -* GNU Bash 5.x or higher -* ShellCheck installed -* GNU Sed -* GNU Date -* Git - -The script was tested on a recent Fedora Linux. For *BSD or macOS you would need to install GNU Sed, GNU Date, and a newer version of Bash. - -## Usage - -So you want such a pretty internet site too? - -To get started, just clone this repo (master branch) and run `./buetow.org.sh`. You will will be prompted with further instructions. - -You will notice soon, that all site content is located in `../buetow.org-content/` (you can configure the `BASE_CONTENT_DIR` in `buetow.org.conf`). There is one sub-directory per output format, e.g.: - -``` -../buetow.org-content/gemtext -../buetow.org-content/html -../buetow.org-content/md -../buetow.org-content/meta -``` - -### Alternative config file path - -If you don't want to mess with `buetow.org.conf`, you can use an alternative config file path in `~/.config/buetow.org.conf`, which takes precedence if it exists. Another way is to set the `CONFIG_FILE_PATH` environment variable, e.g.: - -``` -export CONFIG_FILE_PATH=~/.config/my-site.geek.conf -./buetow.org.sh --generate -``` - -### What is what - -Whereas, you only want to directly edit/add/remove content in the `gemtext` folder. The `buetow.org.sh` then will take the Gemtext and update all other formats accordingly. Summary of what is what: - -* `gemtext`: The Gemini Gemtext markup files of the internet site. -* `html`: The XHTML version of it. -* `md`: The Markdown version of it. -* `meta`: Some meta data of all Gemtext blog posts. It's used by `buetow.org.sh` internally for Atom feed generation. - -### Special HTML configuration - -You will find the `./header.html.part` and `./footer.html.part` files, they are minimal template files for the HTML generation. - -### Special Markdown configuraiton - -`buetow.org.sh` will never touch the `../buetow.org-content/md/_config.yml` file (if it exists). That's a special configuration file for GitHub Pages. - -## Store all formats in Git - -I personally have for each directory in `../buetow.org-content/` a separate Git repository configured. So whenever something has changed it will be updated/added/removed to version control. The following will run the generator and commit everything to Git: - -``` -USE_GIT=yes ./buetow.org --generate -``` - -And the following will additionally perform a `git pull` and `git push` afterwards; - -``` -USE_GIT=yes GIT_PUSH=yes ./buetow.org --generate -``` - -You could add the `USE_GIT` and `GIT_PUSH` options to the `buetow.org.conf` config file too. - -## Publishing a blog post - -All what needs to be done is to create a new file in `./gemtext/gemfeed/YYYY-MM-DD-article-title-dash-separated.gmi`, whereas `YYYY-MM-DD` defines the publishing date of the blog post. - -A subsequent `./buetow.org.sh --generate` will then detect the new post and link it from `$BASE_CONTENT_DIR/gemtext/gemfeed/index.gmi`, link it from the main index `$BASE_CONTENT_DIR/gemtext/index.gmi`, and also add it to the Atom feed at `$BASE_CONTENT_DIR/gemtext/gemfeed/atom.xml`. The first level 1 Gemtext title (e.g. `# Title`) will be the displayed link name. `YYYY-MM-DD` will be the publishing date. There are various other settings, such as Author - they come from the `buetow.org.conf` configuration file. - -Once all of that is done, the `buetow.org.sh` script will convert the new post (plus all the indices and the Atom feed) to the other formats too (e.g. HTML, Markdown). - -You can also have a look at `$BASE_CONTENT_DIR/meta/gemfeed`. There is a meta file for each blog post stored. These meta files are required for the generation of the Atom feed. You can edit these meta files manually and run `./buetow.org.sh --generate` or `./buetow.org.sh --feed` again, in case you want to change some of the Atom feed content. - -## Finito - -After running `./buetow.org --genreate` you will have all static files ready to be published. But before you do that you could preview the content with `firefox ../buetow.org-content/html/index.html` or `glow ../buetow.org-content/md/index.md` (you get the idea). - -Have also a look at the generated `atom.xml` files. They make sense (at least) for Gemtext and HTML. - -Now it is up to you to setup a Gemini server for the Gemtext, a Webserver for the HTML and/or a GitHub page for the Markdowns. +You can find more about my internet site and the static content generator at [snonux/gemtexter](https://github.com/snonux/gemtexter). diff --git a/buetow.org.conf b/buetow.org.conf deleted file mode 100644 index effeaef6..00000000 --- a/buetow.org.conf +++ /dev/null @@ -1,9 +0,0 @@ -declare -xr DOMAIN=buetow.org -declare -xr SUBTITLE='Having fun with computers!' -declare -xr AUTHOR='Paul Buetow' -declare -xr EMAIL='comments@mx.buetow.org' -declare -xr IMAGE_PATTERN='\.(jpg|png|gif)$' -declare -xr ATOM_MAX_ENTRIES=42 -declare -xr CONTENT_BASE_DIR=../buetow.org-content -declare -xr HTML_HEADER=./header.html.part -declare -xr HTML_FOOTER=./header.html.part diff --git a/buetow.org.sh b/buetow.org.sh deleted file mode 100755 index 29eadbd0..00000000 --- a/buetow.org.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bash -# -# The buetow.org.sh static site generator -# by Paul Buetow 2021 - -declare -r ARG="$1"; shift -declare DATE=date -declare SED=sed -declare GREP=grep -which gdate &>/dev/null && DATE=gdate -which gsed &>/dev/null && SED=gsed -which ggrep &>/dev/null && GREP=ggrep -readonly DATE -readonly SED -readonly GREP - -set -e - -if [[ -n "$CONFIG_FILE_PATH" ]]; then - source "$CONFIG_FILE_PATH" -elif [[ -f ~/.config/buetow.org.conf ]]; then - source ~/.config/buetow.org.conf -else - source ./buetow.org.conf -fi - -source ./packages/assert.source.sh -source ./packages/git.source.sh -source ./packages/atomfeed.source.sh -source ./packages/gemfeed.source.sh -source ./packages/generate.source.sh -source ./packages/html.source.sh -source ./packages/log.source.sh -source ./packages/md.source.sh - -help () { - cat <<HELPHERE -$0's possible arguments: - --feed Generates Gemtext Atom feed and Gemfeed. - --generate Generates all known output formats (html, md, ...). - If USE_GIT=yes set, all files will be commited to git too. - If GIT_PUSH=yes is set, all content will be pushed to origin. - --test Only runs some shellcheck and unit tests. - --help Prints this retty text. -Example: - USE_GIT=yes GIT_PUSH=yes $0 --generate -HELPHERE -} - -setup () { - if [ ! -d "$CONTENT_BASE_DIR" ]; then - cat <<END -The content base directory, does not exist. Run the following to create it, it -also adds some sample Gemtext content: - - mkdir -p $CONTENT_BASE_DIR/{meta,md,html} - git clone --branch content-gemtext https://github.com/snonux/buetow.org $CONTENT_BASE_DIR/gemtext - rm -Rf $CONTENT_BASE_DIR/gemtext/.git - -Once done, you are ready to edit the files in $CONTENT_BASE_DIR/gemtext. Every -time you want to generate other formats from Gemtext (e.g. HTML, Markdown), run - $0 --generate -again. - -For a list of other available arguments run - $0 --help - -Pro tip: You could make all the directories in $CONTENT_BASE_DIR separate git -repositories or branches. You can then run - USE_GIT=yes $0 --generate -so that all static files are commited to the content repositories too. -END - exit 1 - fi -} - -main () { - local -r arg="$1"; shift - - setup - - case $arg in - --test) - LOG_VERBOSE=yes - assert::shellcheck - html::test - md::test - ;; - --feed) - gemfeed::generate - atomfeed::generate - ;; - --generate) - gemfeed::generate - atomfeed::generate - generate::fromgmi html md - ;; - --help|*) - help - ;; - esac - - return 0 -} - -main "$ARG" -exit $? diff --git a/footer.html.part b/footer.html.part deleted file mode 100644 index 308b1d01..00000000 --- a/footer.html.part +++ /dev/null @@ -1,2 +0,0 @@ -</body> -</html> diff --git a/header.html.part b/header.html.part deleted file mode 100644 index d499e512..00000000 --- a/header.html.part +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<title>%%TITLE%%</title> -<link rel="shortcut icon" type="image/gif" href="/favicon.ico" /> -<style type="text/css"> -body { - margin: auto; - max-width: 900px; - background-color: #FFFFEF; - border: 1px dashed #880000; - border-radius: 8px; - padding: 5px; -} -img { - display:block; - max-width: 80%; -} -a.textlink:before { - content: " ⇒ "; - padding-left: 2px; -} -a.textlink { - text-decoration: none; - color: #FF0000; -} -a.textlink:hover { - text-decoration: underline; -} -i { - color: #48AAAD; -} -pre { - background-color: #F1F8E9; - border: 1px dashed #BB0000; - border-radius: 8px; - padding: 5px; - font-family: "Lucida Console", "Courier New", monospace; -} -h1 { - text-align: center; - color: #880000; -} -h2, h3 { - color: #BB0000; -} -</style> -</head> -<body> diff --git a/packages/assert.source.sh b/packages/assert.source.sh deleted file mode 100644 index d53a728e..00000000 --- a/packages/assert.source.sh +++ /dev/null @@ -1,59 +0,0 @@ -# Unit test for whether 2 given strings equal. -assert::equals () { - local -r result="$1"; shift - local -r expected="$1"; shift - local -r callee=${FUNCNAME[1]} - - if [[ "$result" != "$expected" ]]; then - cat <<ERROR | log::pipe ERROR -In $callee expected - '$expected' -But got - '$result' -ERROR - exit 2 - fi - - log VERBOSE "Result in $callee as expected: '$expected'" -} - -# Unit test for whether a given string is not empty. -assert::not_empty () { - local -r name="$1"; shift - local -r content="$1"; shift - local -r callee=${FUNCNAME[1]} - - if [ -z "$content" ]; then - log ERROR "In $callee expected '$name' not to be empty!" - exit 2 - fi - - log VERBOSE "Result in $callee as expected not empty" -} - -# Unit test for whether a given string matches a regex. -assert::matches () { - local -r name="$1"; shift - local -r content="$1"; shift - local -r regex="$1"; shift - local -r callee=${FUNCNAME[1]} - - if ! $GREP -q -E "$regex" <<< "$content"; then - log ERROR "In $callee expected '$name' to match '$regex'" - exit 2 - fi - - log VERBOSE "Matching in $callee as expected" -} - -# Checks if all the Bash scripts here are good. -assert::shellcheck () { - set -e - shellcheck \ - --norc \ - --external-sources \ - --check-sourced \ - --exclude=SC2155,SC2010,SC2154,SC1090,SC2012 \ - ./"$0" - set +e -} diff --git a/packages/atomfeed.source.sh b/packages/atomfeed.source.sh deleted file mode 100644 index e1ee4064..00000000 --- a/packages/atomfeed.source.sh +++ /dev/null @@ -1,128 +0,0 @@ -# Retrieve meta data of a given blog post. Generate new meta info if not yet exists. -atomfeed::meta () { - local -r gmi_file_path="$1"; shift - local -r meta_file=$($SED 's|gemtext|meta|; s|.gmi$|.meta|;' <<< "$gmi_file_path") - - log VERBOSE "Generating meta info for post $gmi_file_path" - - local is_draft=no - if $GREP -E -q '\.draft\.meta$' <<< "$meta_file"; then - is_draft=yes - fi - - local -r meta_dir=$(dirname "$meta_file") - if [[ ! -d "$meta_dir" ]]; then - mkdir -p "$meta_dir" - fi - - if [ ! -f "$meta_file" ]; then - # Extract first heading as post title. - local title=$($SED -n '/^# / { s/# //; p; q; }' "$gmi_file_path" | tr '"' "'") - # Extract first paragraph from Gemtext - local summary=$($SED -n '/^[A-Z]/ { p; q; }' "$gmi_file_path" | tr '"' "'") - # Extract the date from the file name. - local filename_date=$(basename "$gmi_file_path" | cut -d- -f1,2,3) - local date=$($DATE --iso-8601=seconds --date "$filename_date $($DATE +%H:%M:%S)") - - cat <<META | tee "$meta_file" -local meta_date="$date" -local meta_author="$AUTHOR" -local meta_email="$EMAIL" -local meta_title="$title" -local meta_summary="$summary. .....to read on please visit my site." -META - if [[ $is_draft == no ]]; then - git::add meta "$meta_file" - fi - return - fi - - cat "$meta_file" - if [[ $is_draft == yes ]]; then - rm "$meta_file" - fi -} - -# Retrieve the core content as XHTML of the blog post. -atomfeed::content () { - local -r gmi_file_path="$1"; shift - log VERBOSE "Retrieving feed content from $gmi_file_path" - - # sed: Remove all before the first header - # sed: Make HTML links absolute, Atom relative URLs feature seems a mess - # across different Atom clients. - html::fromgmi < <($SED '/Go back to the main site/d' "$gmi_file_path") | - $SED " - s|href=\"\./|href=\"https://$DOMAIN/gemfeed/|g; - s|src=\"\./|src=\"https://$DOMAIN/gemfeed/|g; - " -} - -# Generate an atom.xml feed file. -atomfeed::generate () { - local -r gemfeed_dir="$CONTENT_BASE_DIR/gemtext/gemfeed" - local -r atom_file="$gemfeed_dir/atom.xml" - local -r now=$($DATE --iso-8601=seconds) - log INFO "Generating Atom feed to $atom_file" - - assert::not_empty now "$now" - - cat <<ATOMHEADER > "$atom_file.tmp" -<?xml version="1.0" encoding="utf-8"?> -<feed xmlns="http://www.w3.org/2005/Atom"> - <updated>$now</updated> - <title>$DOMAIN feed</title> - <subtitle>$SUBTITLE</subtitle> - <link href="gemini://$DOMAIN/gemfeed/atom.xml" rel="self" /> - <link href="gemini://$DOMAIN/" /> - <id>gemini://$DOMAIN/</id> -ATOMHEADER - - while read -r gmi_file; do - # Load cached meta information about the post. - source <(atomfeed::meta "$gemfeed_dir/$gmi_file") - - # Get HTML content for the feed - local content="$(atomfeed::content "$gemfeed_dir/$gmi_file")" - - assert::not_empty meta_title "$meta_title" - assert::not_empty meta_date "$meta_date" - assert::not_empty meta_author "$meta_author" - assert::not_empty meta_email "$meta_email" - assert::not_empty meta_summary "$meta_summary" - assert::not_empty content "$content" - - cat <<ATOMENTRY >> "$atom_file.tmp" - <entry> - <title>$meta_title</title> - <link href="gemini://$DOMAIN/gemfeed/$gmi_file" /> - <id>gemini://$DOMAIN/gemfeed/$gmi_file</id> - <updated>$meta_date</updated> - <author> - <name>$meta_author</name> - <email>$meta_email</email> - </author> - <summary>$meta_summary</summary> - <content type="xhtml"> - <div xmlns="http://www.w3.org/1999/xhtml"> - $content - </div> - </content> - </entry> -ATOMENTRY - done < <(gemfeed::get_posts | head -n $ATOM_MAX_ENTRIES) - - cat <<ATOMFOOTER >> "$atom_file.tmp" -</feed> -ATOMFOOTER - - # Delete the 3rd line of the atom feeds (global feed update timestamp) - if ! diff -u <($SED 3d "$atom_file") <($SED 3d "$atom_file.tmp"); then - log INFO 'Feed got something new!' - mv "$atom_file.tmp" "$atom_file" - git::add gemtext "$atom_file" - else - log INFO 'Nothing really new in the feed' - rm "$atom_file.tmp" - fi -} diff --git a/packages/gemfeed.source.sh b/packages/gemfeed.source.sh deleted file mode 100644 index c842bb13..00000000 --- a/packages/gemfeed.source.sh +++ /dev/null @@ -1,54 +0,0 @@ -# Filter out blog posts from other files in the gemfeed dir. -gemfeed::get_posts () { - local -r gemfeed_dir="$CONTENT_BASE_DIR/gemtext/gemfeed" - local -r gmi_pattern='^[0-9]{4}-[0-9]{2}-[0-9]{2}-.*\.gmi$' - local -r draft_pattern='\.draft\.gmi$' - - ls "$gemfeed_dir" | - $GREP -E "$gmi_pattern" | - $GREP -E -v "$draft_pattern" | - sort -r -} - -# Add the links from gemfeed/index.gmi to the main index site. -gemfeed::updatemainindex () { - local -r index_gmi="$CONTENT_BASE_DIR/gemtext/index.gmi" - local -r gemfeed_dir="$CONTENT_BASE_DIR/gemtext/gemfeed" - - log VERBOSE "Updating $index_gmi with posts from $gemfeed_dir" - - # Remove old gemfeeds from main index - $SED '/^=> .\/gemfeed\/[0-9].* - .*/d;' "$index_gmi" > "$index_gmi.tmp" - # Add current gemfeeds to main index - $SED -n '/^=> / { s| ./| ./gemfeed/|; p; }' "$gemfeed_dir/index.gmi" >> "$index_gmi.tmp" - - mv "$index_gmi.tmp" "$index_gmi" - git::add gemtext "$index_gmi" -} - -# Generate a index.gmi in the ./gemfeed subdir. -gemfeed::generate () { - local -r gemfeed_dir="$CONTENT_BASE_DIR/gemtext/gemfeed" - log INFO "Generating Gemfeed index for $gemfeed_dir" - -cat <<GEMFEED > "$gemfeed_dir/index.gmi.tmp" -# $DOMAIN's Gemfeed - -## $SUBTITLE - -GEMFEED - - gemfeed::get_posts | while read -r gmi_file; do - # Extract first heading as post title. - local title=$($SED -n '/^# / { s/# //; p; q; }' "$gemfeed_dir/$gmi_file" | tr '"' "'") - # Extract the date from the file name. - local filename_date=$(basename "$gemfeed_dir/$gmi_file" | cut -d- -f1,2,3) - - echo "=> ./$gmi_file $filename_date - $title" >> "$gemfeed_dir/index.gmi.tmp" - done - - mv "$gemfeed_dir/index.gmi.tmp" "$gemfeed_dir/index.gmi" - git::add gemtext "$gemfeed_dir/index.gmi" - - gemfeed::updatemainindex -} diff --git a/packages/generate.source.sh b/packages/generate.source.sh deleted file mode 100644 index 98cd2154..00000000 --- a/packages/generate.source.sh +++ /dev/null @@ -1,160 +0,0 @@ -# Generate a HTML or Markdown link from given Gemtext link. -generate::make_link () { - local -r what="$1"; shift - local -r line="${1/=> }"; shift - local link - local descr - - while read -r token; do - if [ -z "$link" ]; then - link="$token" - elif [ -z "$descr" ]; then - descr="$token" - else - descr="$descr $token" - fi - done < <(echo "$line" | tr ' ' '\n') - - if $GREP -E -q "$IMAGE_PATTERN" <<< "$link"; then - if [[ "$what" == md ]]; then - md::make_img "$link" "$descr" - else - html::make_img "$link" "$(html::encode "$descr")" - fi - return - fi - - if [[ "$what" == md ]]; then - md::make_link "$link" "$descr" - else - html::make_link "$link" "$(html::encode "$descr")" - fi -} - -# Add other docs (e.g. images, videos) from Gemtext to output format. -generate::fromgmi_add_docs () { - local -r src="$1"; shift - local -r format="$1"; shift - local -r dest=${src/gemtext/$format} - local -r dest_dir=$(dirname "$dest") - - if [[ ! -d "$dest_dir" ]]; then - mkdir -p "$dest_dir" - fi - cp "$src" "$dest" - git::add "$format" "$dest" -} - -# Remove docs from output format which aren't present in Gemtext anymore. -generate::fromgmi_cleanup_docs () { - local -r src="$1"; shift - local -r format="$1"; shift - local dest=${src/.$format/.gmi} - dest=${dest/$format/gemtext} - - if [[ ! -f "$dest" ]]; then - git::rm "$format" "$src" - fi -} - -# Convert the Gemtext Atom feed to a HTML Atom feed. -generate::convert_gmi_atom_to_html_atom () { - local -r format="$1"; shift - if [[ "$format" != html ]]; then - return - fi - - log INFO 'Converting Gemtext Atom feed to HTML Atom feed' - - $SED 's|.gmi|.html|g; s|gemini://|https://|g' \ - < $CONTENT_BASE_DIR/gemtext/gemfeed/atom.xml \ - > $CONTENT_BASE_DIR/html/gemfeed/atom.xml - - git::add "$format" "$CONTENT_BASE_DIR/html/gemfeed/atom.xml" -} - -# Internal helper function for generate::fromgmi -generate::_fromgmi () { - local -r src="$1"; shift - local -r format="$1"; shift - local dest=${src/gemtext/$format} - dest=${dest/.gmi/.$format} - local dest_dir=$(dirname "$dest") - - if [[ ! -d "$dest_dir" ]]; then - mkdir -p "$dest_dir" - fi - - if [[ "$format" == html ]]; then - cat "$HTML_HEADER" > "$dest.tmp" - html::fromgmi < "$src" >> "$dest.tmp" - cat "$HTML_FOOTER" >> "$dest.tmp" - - elif [[ "$format" == md ]]; then - md::fromgmi < "$src" >> "$dest.tmp" - fi - - local title=$($SED -n '/^# / { s/# //; p; q; }' "$src" | tr '"' "'") - if [[ -z "$title" ]]; then - title=$SUBTITLE - fi - $SED -i "s|%%TITLE%%|$title|g" "$dest.tmp" - mv "$dest.tmp" "$dest" - - git::add "$format" "$dest" -} - -# Generate a given output format from a Gemtext file. -generate::fromgmi () { - local -i num_gmi_files=0 - local -i num_doc_files=0 - - log INFO "Generating $* from Gemtext" - - while read -r src; do - num_gmi_files=$(( num_gmi_files + 1 )) - for format in "$@"; do - generate::_fromgmi "$src" "$format" - done - done < <(find "$CONTENT_BASE_DIR/gemtext" -type f -name \*.gmi) - - log INFO "Converted $num_gmi_files Gemtext files" - - # Add non-.gmi files to html dir. - log VERBOSE "Adding other docs to $*" - - while read -r src; do - num_doc_files=$(( num_doc_files + 1 )) - for format in "$@"; do - generate::fromgmi_add_docs "$src" "$format" - done - done < <(find "$CONTENT_BASE_DIR/gemtext" -type f | $GREP -E -v '(\.git.*|\.gmi|atom.xml|\.tmp)$') - - log INFO "Added $num_doc_files other documents to each of $*" - - # Add atom feed for HTML - for format in "$@"; do - generate::convert_gmi_atom_to_html_atom "$format" - done - - # Remove obsolete files from ./html/. - # Note: The _config.yml is the config file for GitHub pages (md format). - for format in "$@"; do - find "$CONTENT_BASE_DIR/$format" -type f | - $GREP -E -v '(\.git.*|_config.yml)$'| - while read -r src; do - generate::fromgmi_cleanup_docs "$src" "$format" - done - done - - if [[ -z "$GIT_COMMIT_MESSAGE" ]]; then - GIT_COMMIT_MESSAGE='Publishing new version' - fi - git::commit gemtext "$GIT_COMMIT_MESSAGE" - git::commit meta "$GIT_COMMIT_MESSAGE" - - for format in "$@"; do - git::commit "$format" "$GIT_COMMIT_MESSAGE" - log INFO "$format can be found in $CONTENT_BASE_DIR/$format now" - done -} diff --git a/packages/git.source.sh b/packages/git.source.sh deleted file mode 100644 index c502b008..00000000 --- a/packages/git.source.sh +++ /dev/null @@ -1,50 +0,0 @@ -# Add a static content file to git -git::add () { - if [[ "$USE_GIT" != yes ]]; then - return - fi - - local -r content_dir="$CONTENT_BASE_DIR/$1"; shift - local file="$1"; shift - file=${file/$content_dir/.\/} - - cd "$content_dir" &>/dev/null - git add "$file" - cd - &>/dev/null -} - -# Remove a static content file from git -git::rm () { - if [[ "$USE_GIT" != yes ]]; then - return - fi - - local -r content_dir="$CONTENT_BASE_DIR/$1"; shift - local file="$1"; shift - file=${file/$content_dir/.\/} - - cd "$content_dir" &>/dev/null - git rm "$file" - cd - &>/dev/null -} - -# Commit all changes -git::commit () { - if [[ "$USE_GIT" != yes ]]; then - return - fi - - local -r content_dir="$CONTENT_BASE_DIR/$1"; shift - local -r message="$1"; shift - - cd "$content_dir" &>/dev/null - set +e - git commit -a -m "$message" - if [[ "$GIT_PUSH" == yes ]]; then - log INFO "Invoking git pull/push in $content_dir" - git pull - git push - fi - set -e - cd - &>/dev/null -} diff --git a/packages/html.source.sh b/packages/html.source.sh deleted file mode 100644 index 6049c2f9..00000000 --- a/packages/html.source.sh +++ /dev/null @@ -1,162 +0,0 @@ -# Convert special characters to their HTML codes -html::encode () { - $SED ' - s|\&|\&|g; - s|<|\<|g; - s|>|\>|g; - ' <<< "$@" -} - -# Make a HTML paragraph. -html::make_paragraph () { - local -r text="$1"; shift - - if [[ -n "$text" ]]; then - echo "<p>$(html::encode "$text")</p>" - fi -} - -# Make a HTML header. -html::make_heading () { - local -r text=$($SED -E 's/^#+ //' <<< "$1"); shift - local -r level="$1"; shift - echo "<h${level}>$(html::encode "$text")</h${level}>" -} - -# Make a HTML quotation -html::make_quote () { - local -r quote="${1/> }" - echo "<p class=\"quote\"><i>$(html::encode "$quote")</i></p>" -} - -# Make a HTML image -html::make_img () { - local link="$1"; shift - local descr="$1"; shift - - if [ -z "$descr" ]; then - echo -n "<a href=\"$link\"><img src=\"$link\" /></a>" - else - echo -n "<i>$descr:</i>" - echo -n "<a href=\"$link\"><img alt=\"$descr\" title=\"$descr\" src=\"$link\" /></a>" - fi - - echo "<br />" -} - -# Make a HTML hyperlink -html::make_link () { - local link="$1"; shift - local descr="$1"; shift - - if ! $GREP -F -q '://' <<< "$link"; then - link=${link/.gmi/.html} - fi - - if [[ -z "$descr" ]]; then - descr="$link" - fi - - echo "<a class=\"textlink\" href=\"$link\">$descr</a><br />" -} - -# Convert Gemtext to HTML -html::fromgmi () { - local is_list=no - local is_plain=no - - while IFS='' read -r line; do - if [[ "$is_list" == yes ]]; then - if [[ "$line" == '* '* ]]; then - echo "<li>$(html::encode "${line/\* /}")</li>" - else - is_list=no - echo "</ul>" - fi - continue - - elif [[ "$is_plain" == yes ]]; then - if [[ "$line" == '```'* ]]; then - echo "</pre>" - is_plain=no - else - html::encode "$line" - fi - continue - fi - - case "$line" in - '* '*) - is_list=yes - echo "<ul>" - echo "<li>${line/\* /}</li>" - ;; - '```'*) - is_plain=yes - echo "<pre>" - ;; - '# '*) - html::make_heading "$line" 1 - ;; - '## '*) - html::make_heading "$line" 2 - ;; - '### '*) - html::make_heading "$line" 3 - ;; - '> '*) - html::make_quote "$line" - ;; - '=> '*) - generate::make_link html "$line" - ;; - *) - html::make_paragraph "$line" - ;; - esac - done -} - -# Test HTML package. -html::test () { - local line='Hello world! This is a paragraph.' - assert::equals "$(html::make_paragraph "$line")" '<p>Hello world! This is a paragraph.</p>' - - line='' - assert::equals "$(html::make_paragraph "$line")" '' - - line='Foo &<>& Bar!' - assert::equals "$(html::make_paragraph "$line")" '<p>Foo &<>& Bar!</p>' - - line='# Header 1' - assert::equals "$(html::make_heading "$line" 1)" '<h1>Header 1</h1>' - - line='## Header 2' - assert::equals "$(html::make_heading "$line" 2)" '<h2>Header 2</h2>' - - line='### Header 3' - assert::equals "$(html::make_heading "$line" 3)" '<h3>Header 3</h3>' - - line='> This is a quote' - assert::equals "$(html::make_quote "$line")" '<p class="quote"><i>This is a quote</i></p>' - - line='=> https://example.org' - assert::equals "$(generate::make_link html "$line")" \ - '<a class="textlink" href="https://example.org">https://example.org</a><br />' - - line='=> index.html' - assert::equals "$(generate::make_link html "$line")" \ - '<a class="textlink" href="index.html">index.html</a><br />' - - line='=> http://example.org Description of the link' - assert::equals "$(generate::make_link html "$line")" \ - '<a class="textlink" href="http://example.org">Description of the link</a><br />' - - line='=> http://example.org/image.png' - assert::equals "$(generate::make_link html "$line")" \ - '<a href="http://example.org/image.png"><img src="http://example.org/image.png" /></a><br />' - - line='=> http://example.org/image.png Image description' - assert::equals "$(generate::make_link html "$line")" \ - '<i>Image description:</i><a href="http://example.org/image.png"><img alt="Image description" title="Image description" src="http://example.org/image.png" /></a><br />' -} diff --git a/packages/log.source.sh b/packages/log.source.sh deleted file mode 100644 index 56c6587e..00000000 --- a/packages/log.source.sh +++ /dev/null @@ -1,30 +0,0 @@ -# Log a message. -log () { - local -r level="$1"; shift - local message - - for message in "$@"; do - echo "$message" - done | log::_pipe "$level" -} - -# Log a stream through a pipe. -log::pipe () { - log::_pipe "$1" -} - -# Internal log implementation. -log::_pipe () { - local -r level="$1"; shift - - if [[ "$level" == VERBOSE && -z "$LOG_VERBOSE" ]]; then - return - fi - - local -r callee=${FUNCNAME[2]} - local -r stamp=$($DATE +%Y%m%d-%H%M%S) - - while read -r line; do - echo "$level|$stamp|$callee|$line" >&2 - done -} diff --git a/packages/md.source.sh b/packages/md.source.sh deleted file mode 100644 index e7bfae11..00000000 --- a/packages/md.source.sh +++ /dev/null @@ -1,63 +0,0 @@ -# Make a Markdown image. -md::make_img () { - local link="$1"; shift - local descr="$1"; shift - - if [ -z "$descr" ]; then - echo "[]($link) " - else - echo "[]($link) " - fi -} - -# Make a Markdown hyperlink. -md::make_link () { - local link="$1"; shift - local descr="$1"; shift - - if ! $GREP -F -q '://' <<< "$link"; then - link=${link/.gmi/.md} - fi - if [[ -z "$descr" ]]; then - descr="$link" - fi - - echo "[$descr]($link) " -} - -# Convert Gemtext to Markdown. -md::fromgmi () { - while IFS='' read -r line; do - case "$line" in - '=> '*) - generate::make_link md "$line" - ;; - *) - echo "$line" - ;; - esac - done -} - -# Test the Markdown package. -md::test () { - local line='=> https://example.org' - assert::equals "$(generate::make_link md "$line")" \ - '[https://example.org](https://example.org) ' - - line='=> index.md' - assert::equals "$(generate::make_link md "$line")" \ - '[index.md](index.md) ' - - line='=> http://example.org Description of the link' - assert::equals "$(generate::make_link md "$line")" \ - '[Description of the link](http://example.org) ' - - line='=> http://example.org/image.png' - assert::equals "$(generate::make_link md "$line")" \ - '[](http://example.org/image.png) ' - - line='=> http://example.org/image.png Image description' - assert::equals "$(generate::make_link md "$line")" \ - '[](http://example.org/image.png) ' -} |
