From 8fe5387c47196d09063e12ca6b9ad768ad4849b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Gon=C3=A7alves?= Date: Mon, 27 Sep 2021 15:08:34 +0200 Subject: all: Bump to version 3 of static site generation --- bin/func | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/ssg | 127 +++++------------------------------- bin/ssg-template | 194 ------------------------------------------------------- 3 files changed, 204 insertions(+), 304 deletions(-) create mode 100644 bin/func delete mode 100644 bin/ssg-template (limited to 'bin') 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 + + $(__get_value_date_human ${2}) + + EOF + fi + + cat <<-EOF + + $(__get_value_title ${2}) + + 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 "" +} + +__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 <> "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@]* href=\"[/^\"]*/@]* href=\"[/^\"]*/@]* src=\"[/^\"]*/@ ${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 "
    " - for key in ${_ENABLED_METADATA}; do - value=$(lowdown -X "${key}" "${1}" 2>/dev/null) - [ -z "${value}" ] && continue - - echo "
  • ${key}: ${value}
  • " - done - echo "
" - - if [ "${title}" ]; then - echo "

${title}

" - fi -} - -_render_index() { - # 1: filename - # 2: out - # 3: path - local file - local path - local title - - echo "
" -} - -_render_toc() { - local chapter - local chapter_title - - echo "
    " - for chapter in $(_get_chapters "${1}"); do - chapter_title=$(_get_chapter_title "${chapter}") - - cat <<-EOF -
  • - ${chapter_title} -
  • - EOF - done - echo "
" -} -- cgit v1.2.3