aboutsummaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorRomain Gonçalves <me@rgoncalves.se>2021-09-27 15:08:34 +0200
committerRomain Gonçalves <me@rgoncalves.se>2021-09-27 15:08:34 +0200
commit8fe5387c47196d09063e12ca6b9ad768ad4849b0 (patch)
treedc75df123d86c4027b9fb18218d1bafdc13819fe /bin
parent17278427d7e7eecd95c8bf808501188342cd8435 (diff)
downloadwebsite-8fe5387c47196d09063e12ca6b9ad768ad4849b0.tar.gz
all: Bump to version 3 of static site generation
Diffstat (limited to 'bin')
-rw-r--r--bin/func187
-rwxr-xr-xbin/ssg127
-rw-r--r--bin/ssg-template194
3 files changed, 204 insertions, 304 deletions
diff --git a/bin/func b/bin/func
new file mode 100644
index 0000000..af81d92
--- /dev/null
+++ b/bin/func
@@ -0,0 +1,187 @@
+#!/bin/sh
+
+media_dir="media"
+src_dir="src"
+tmp_dir="tmp"
+out_dir="out"
+
+tmp_file="${tmp_dir}/tmp"
+
+__get_value() {
+ # 1: filename
+ # 2: Attribute name
+ # Retrieve and return the key/value of a lowdown source file.
+ lowdown -T ms -X "${2}" "${1}" 2>/dev/null
+}
+
+__get_value_title() {
+ # 1: filename
+ # Get the title of a file and return a safe string.
+ local _title
+
+ _title="$(__get_value ${1} title || true)"
+ if [ "${_title}" = "" ]; then
+ _title="$(basename ${1} |
+ rev |
+ cut -d "." -f 2 |
+ rev |
+ sed 's/-/ /g')"
+ fi
+
+ echo "${_title}"
+}
+
+__get_value_date() {
+ # 1: filename
+ # Get the date of a file and return a safe string.
+ local _date
+
+ _date="$(__get_value ${1} date || true)"
+ if [ "${_date}" = "" ]; then
+ _date="1970-01-01"
+ fi
+
+ echo "${_date}"
+}
+
+__get_value_date_human() {
+ # 1: filename
+ # Get a human readable date from a file and return a safe string.
+ __get_value_date "${1}" | xargs date -j -f "%Y-%m-%d" +"%B %d, %Y"
+}
+
+__get_out_filename() {
+ # 1: filename
+ # Convert the source filename to its output destination.
+ local _filename
+
+ _filename="${1}"
+
+ if $(__get_value "${1}" draft || false); then
+ _filename="$(dirname ${1})/$(basename ${1} | sha256).html"
+ fi
+
+ echo "${_filename}" |
+ sed 's/.md$/.html/g' |
+ sed "s/${src_dir}/${out_dir}/g"
+}
+
+__get_final_filename() {
+ # 1: filename
+ # Convert the source filename to its final filename for a webserver.
+ __get_out_filename "${1}" | cut -d "/" -f 2-
+}
+
+__list_files() {
+ # 1: directory
+ # List all regular files in a directory and its subdirectories.
+ find "${1}" -type f
+}
+
+__list_files_date() {
+ # 1: directory
+ local _files
+ local _file
+ local _tmp_file
+
+ _files=$(__list_files "${1}")
+ _tmp_file="${tmp_file}.list_files_date"
+
+ cp /dev/null "${_tmp_file}"
+
+ for _file in ${_files}; do
+ echo "$(__get_value_date ${_file})" "${_file}" >> "${_tmp_file}"
+ done
+
+ sort -r "${_tmp_file}" | cut -d " " -f 2-
+}
+
+__install() {
+ # 1: filename
+ # Copy a file to the output directory.
+ install -D -m 0644 "${1}" "${2}"
+}
+
+__lowdown() {
+ # Output a file to html
+ lowdown --html-no-skiphtml --html-no-escapehtml "${1}"
+}
+
+__apply_template() {
+ # 1: template name or default
+ m4 "templates/${1:-default}"
+}
+
+__generate_index_line() {
+ # 1: filename where index will be displayed
+ # 2: filename contained in line
+ local _show_date
+
+ _show_date="$(__get_value ${1} index_date || echo false)"
+
+ if "${_show_date}"; then
+ cat <<-EOF
+ <span>
+ $(__get_value_date_human ${2})
+ </span>
+ EOF
+ fi
+
+ cat <<-EOF
+ <a href="$(__get_final_filename ${2})">
+ $(__get_value_title ${2})
+ </a>
+ EOF
+}
+
+__generate_index() {
+ # 1: filename
+ # Generate and output to stdout the index of a file.
+ local _file
+ local _index_dir
+
+ _index_dir="${src_dir}/$(__get_value "${1}" index)"
+ [ -f "${_index_dir}" ] && _index_dir=$(dirname "${_index_dir}")
+ [ ! -d "${_index_dir}" ] && return
+
+ echo "<ul class=\"index\">"
+
+ for _file in $(__list_files_date "${_index_dir}"); do
+ [ "${1}" = "${_file}" ] && continue
+ __get_value "${_file}" "draft" >/dev/null && continue
+
+ echo "<li>"
+ __generate_index_line "${1}" "${_file}"
+ echo "</li>"
+ done
+
+ echo "</ul>"
+}
+
+__handle_md() {
+ # 1: filename
+ # Handle markdown files.
+ __lowdown "${1}" > "${tmp_file}.body"
+
+ if [ ! "$(__get_value ${1} index)" = "" ]; then
+ __generate_index "${1}" > "${tmp_file}.index"
+ else
+ [ -f "${tmp_file}.index" ] && rm "${tmp_file}.index"
+ fi
+
+ __apply_template "$(__get_value ${1} template)" > "${tmp_file}"
+ __install "${tmp_file}" "$(__get_out_filename ${1})"
+}
+
+__handle() {
+ # 1: filename
+ # Handle file depending on its filename and filetype.
+ case "${1}" in
+ *.md)
+ __handle_md "${1}"
+ ;;
+ *)
+ __install "${1}" "$(__get_out_filename ${1})"
+ ;;
+ esac
+}
diff --git a/bin/ssg b/bin/ssg
index 28eeea0..d3f2e02 100755
--- a/bin/ssg
+++ b/bin/ssg
@@ -1,117 +1,24 @@
#!/bin/sh
-TEMPLATE="templates/default.html"
-STATIC_DIRS="style img"
-TMP_FILE=".tmp"
-SRC="src"
-OUT="out"
-#BASE_URL=""
+. $(dirname "${0}")/func
-. ./bin/ssg-template
+set -xe
-_log() {
- echo [${0}] "$@"
-}
+# Check if the working directory is valid.
+echo "${0}" | grep '^./bin/ssg$'
-_to_html() {
- # 1: filename
- # stdout: content
- lowdown --html-no-skiphtml --html-no-escapehtml "${1}"
-}
+src_files="$(__list_files ${src_dir})"
+dirs="${media_dir} \
+ ${src_dir} \
+ ${tmp_dir} \
+ ${out_dir}"
-_install() {
- # 1: filename
- install -D "${TMP_FILE}" $(_get_out_path "${1}")
-}
+# Ensure directories exist.
+for dir in ${dirs}; do
+ [ ! -d "${dir}" ] && mkdir "${dir}"
+done
-_template_heredoc() {
- echo ". ${PWD}/bin/ssg-template" > "tmp/heredoc"
- echo "cat <<EOF_TEMPLATE" >> "tmp/heredoc"
- cat "${1}" >> "tmp/heredoc"
- echo EOF_TEMPLATE >> "tmp/heredoc"
-
- sh "tmp/heredoc" "${1}" > "${TMP_FILE}"
- _to_html "${TMP_FILE}" > "${2}"
-}
-
-_convert_urls() {
- # file url
- if ! echo "${2}" | grep "^http" >/dev/null; then
- sed -i "s@href=/@href=$2/@g" "${1}"
- fi
- sed -i "s@<a[^>]* href=\"[/^\"]*/@<a href=\"$2/@g" "${1}"
- sed -i "s@<link[^>]* href=\"[/^\"]*/@<link href=\"$2/@g" "${1}"
- sed -i "s@<img[^>]* src=\"[/^\"]*/@<img src=\"$2/@g" "${1}"
-}
-
-main() {
- local file
- local out_path
-
- # template files
- for template in header footer; do
- _log "> ${template}"
- _to_html "templates/${template}.md" > "${TMP_FILE}"
- install -D "${TMP_FILE}" "tmp/${template}.html"
- done
-
- # markdown files
- for file in $(find "${SRC}" -iname "*.md"); do
- out_path=$(_get_out_path "${file}")
-
- if [ "${file}" -ot "${out_path}" ]; then
- _log "! ${file}"
- continue
- fi
-
- _log "> ${file}"
-
- # Metadata
- _cleanup_tmp_file "tmp/metadata.html"
- _render_metadata "${file}" > "tmp/metadata.html"
-
- # Table of content
- _cleanup_tmp_file "tmp/toc.html"
- if [ $(_get_value "${file}" "toc") ]; then
- _render_toc "${file}" > "tmp/toc.html"
- fi
-
- # Index of directory
- _cleanup_tmp_file "tmp/index.html"
- if [ $(_get_value "${file}" "index") ]; then
- _render_index "${file}" > "tmp/index.html"
- fi
-
- # Render body content
- _to_html "${file}" > "tmp/body.html"
-
- # Erase body content with templating
- if basename "${file}" | grep "^_"; then
- _template_heredoc "${file}" "tmp/body.html"
- fi
-
- # Concatenate temporary files to final page
- template=$(_get_value "${file}" "template")
- template="${template:-default}"
- m4 "templates/${template}.html" > "${TMP_FILE}"
- install -D "${TMP_FILE}" "${out_path}"
- done
-
- # html files
- for file in $(find "${SRC}" -iname "*.html"); do
- _log "> ${file}"
- _install "${file}"
- done
-
- # convert urls
- for file in $(find "${OUT}" -iname "*.html"); do
- _convert_urls "${file}" "${BASE_URL}"
- done
-
- for dir in ${STATIC_DIRS}; do
- _log "> ${dir}/"
- cp -R "src/${dir}" "out/${dir}"
- done
-}
-
-main
+# Generate output files from sources.
+for src_file in ${src_files}; do
+ __handle "${src_file}"
+done
diff --git a/bin/ssg-template b/bin/ssg-template
deleted file mode 100644
index eacf2ae..0000000
--- a/bin/ssg-template
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/bin/sh
-
-SRC_FILE="${1}"
-
-_echo_ifset() {
- [ ! -z "${1}" ] && echo "${1}"
-}
-
-_get_value() {
- # 1: filename
- # 2: key
- # stdout: value
- local value
- local ret
-
- value=$(lowdown -T ms -X "${2}" "${1}" 2>/dev/null)
- ret="${?}"
-
- echo "${value:-${3}}"
-
- return "${ret}"
-}
-
-_get_value_date() {
- _get_value "${1}" "${2}" "1970-01-01"
-}
-
-_get_out_path() {
- # 1: filename
- # stdout: filename
- local path
-
- path=$(echo "${1}" | sed -e 's/^src/out/g' -e 's/.md$/.html/g' -e 's/_//g')
-
- if _get_value "${1}" "draft" >/dev/null; then
- path="$(dirname ${path})/$(echo ${path} | sha1).html"
- fi
-
- echo "${path}"
-}
-
-_get_final_path() {
- # 1: filename
- # stdout: filename
- _get_out_path "${1}" | sed 's/^out\///g'
-}
-
-_get_title() {
- # 1: filename
- local title
- local file_title
-
- file_title=$(basename "${1}" | sed 's/\..*//g' | tr - " ")
- title=$(_get_value "${1}" "title" "${file_title}")
-
- echo "${title}"
-}
-
-_get_date_human() {
- # 1: filename
- date -j -f "%Y-%m-%d" $(_get_value_date ${1} "date") +"%B %d, %Y"
-}
-
-_get_index_files() {
- # 1: filename
- local path
-
- path=$(_get_value "${1}" index)
- find "src/${path}" -mindepth 1 -maxdepth 1
-}
-
-_sort_index_per_date() {
- # 1: filename
- local files
- local file
- local date
-
- for file in $(_get_index_files "${1}"); do
- date=$(_get_value_date "${file}" "date")
- files="${files} ${date}@${file}"
- done
-
- echo ${files} | tr " " "\n" | sort -rn | cut -d "@" -f 2
-}
-
-_get_filetype() {
- # 1: filename
- local filetype
-
- filetype=$(ls -ld "${1}" | cut -c 1)
-
- case "${filetype}" in
- -)
- filetype="file"
- ;;
- d)
- filetype="directory"
- ;;
- esac
-
- echo "${filetype}"
-}
-
-_get_chapters() {
- # 1: filename
- grep "^#" "${1}" | sed 's/# /#_/g'
-}
-
-_get_chapter_title() {
- # 1: chapter
- echo "${1}" | sed -e 's/#_//' -e 's/#//g'
-}
-
-_parse_option() {
- # 1: metadata
- # 2: key
- echo "${metadata}" | grep "^${2}"
-}
-
-_cleanup_tmp_file() {
- [ -f "${1}" ] && rm "${1}"
-}
-
-_parse_metadata() {
- # 1: filename
- sed -n '/^$/q;p' "${file}" | grep "^.*: .*$"
-}
-
-_render_metadata() {
- # 1: filename
- # 2: output
- local key
- local value
- local title
-
- # _ENABLED_METADATA="date author"
- title=$(_get_value "${1}" "title")
-
- echo "<ul class=\"metadata\">"
- for key in ${_ENABLED_METADATA}; do
- value=$(lowdown -X "${key}" "${1}" 2>/dev/null)
- [ -z "${value}" ] && continue
-
- echo "<li>${key}: ${value}</li>"
- done
- echo "</ul>"
-
- if [ "${title}" ]; then
- echo "<h1>${title}</h1>"
- fi
-}
-
-_render_index() {
- # 1: filename
- # 2: out
- # 3: path
- local file
- local path
- local title
-
- echo "<ul class=\"index\">"
- for file in $(_sort_index_per_date "${1}"); do
- path=$(_get_final_path "${file}")
- [ "${path}" = "$(_get_final_path ${1})" ] && continue
- _get_value "${file}" "draft" >/dev/null && continue
-
- title=$(_get_value "${file}" "title" "$(_get_title ${file})")
-
- echo "<li>"
- if _get_value "${1}" "index_show_date" >/dev/null; then
- echo "<span>$(_get_date_human ${file})</span>"
- fi
- echo "<a href=\"${path}\">${title}</a>"
- echo "</li>"
- done
- echo "</ul>"
-}
-
-_render_toc() {
- local chapter
- local chapter_title
-
- echo "<ul class=\"toc\">"
- for chapter in $(_get_chapters "${1}"); do
- chapter_title=$(_get_chapter_title "${chapter}")
-
- cat <<-EOF
- <li>
- <a href=#${chapter_title}>${chapter_title}</a>
- </li>
- EOF
- done
- echo "</ul>"
-}
remember that computers suck.