#!/bin/bash # build.sh - ubergeek static site generator # Converts the wiki markdown structure into HTML using lowdown + mo. [[ "$(basename "${0}")" == "build.sh" ]] || { echo "Do not source build.sh"; exit 1; } set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [[ ! -f "${SCRIPT_DIR}/build/mo" ]]; then echo "[error] build/mo not found. Run: curl -sL https://raw.githubusercontent.com/tests-always-included/mo/master/mo -o build/mo && chmod +x build/mo" >&2 exit 1 fi . "${SCRIPT_DIR}/build/mo" FORCE=false while [[ $# -gt 0 ]]; do case "$1" in -f|--force) FORCE=true ;; *) echo "[error] Unknown option: $1" >&2; exit 1 ;; esac shift done TMPDIR_BUILD="$(mktemp -d)" cleanup() { rm -rf "${TMPDIR_BUILD}"; } trap cleanup EXIT INT TERM # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- get_frontmatter() { local key="$1" file="$2" lowdown -X "${key}" "${file}" 2>/dev/null || true } check_has_code() { local html="$1" if echo "${html}" | grep -qE '
"${find_list}"
while IFS= read -r -d '' node; do
if [[ -d "${node}" ]]; then
local subdir_title
subdir_title="$(get_frontmatter title "${node}/index.md" 2>/dev/null || true)"
[[ -z "${subdir_title}" ]] && subdir_title="$(basename "${node}")"
printf -- '- [%s](/%s)\n' "${subdir_title}" "${node}" >> "${list_file}"
process_dir "${node}"
elif [[ "${node}" == *.md && "$(basename "${node}")" != "index.md" ]]; then
local slug="${node%.md}"
local title date lang
title="$(get_frontmatter title "${node}")"
[[ -z "${title}" ]] && title="$(basename "${slug}")"
date="$(get_frontmatter date "${node}")"
lang="$(get_frontmatter lang "${node}")"
local out_html="output/${slug}/index.html"
local content
content="$(lowdown "${node}")"
check_has_code "${content}"
build_breadcrumbs "${slug}"
export PAGE_TITLE="${title}"
export CONTENT="${content}"
export BREADCRUMBS
export HEADER_EXTRA="${date}"
export META_DATE="${date}"
export META_DESCRIPTION=""
export HAS_CODE
export LANG="${lang:-en}"
export DIR=""
render_page "build/templates/page.html" "${out_html}"
printf -- '- [%s](/%s)\n' "${title}" "${slug}" >> "${list_file}"
echo "[built] ${out_html}"
fi
done < "${find_list}"
# Build this directory's index page
local index_src="${dir}/index.md"
local index_md="${TMPDIR_BUILD}/${dir//\//_}.index.md"
local dir_title
if [[ -f "${index_src}" ]]; then
dir_title="$(get_frontmatter title "${index_src}")"
cp "${index_src}" "${index_md}"
else
dir_title="$(basename "${dir}")"
printf '# %s\n\n' "${dir_title}" > "${index_md}"
fi
printf '\n\n' >> "${index_md}"
cat "${list_file}" >> "${index_md}"
local out_html="output/${dir}/index.html"
local content
content="$(lowdown "${index_md}")"
check_has_code "${content}"
build_breadcrumbs "${dir}"
export PAGE_TITLE="${dir_title}"
export CONTENT="${content}"
export BREADCRUMBS
export HEADER_EXTRA=""
export META_DATE=""
export META_DESCRIPTION=""
export HAS_CODE
export LANG="en"
export DIR=""
render_page "build/templates/page.html" "${out_html}"
echo "[built] output/${dir}/index.html"
}
# ---------------------------------------------------------------------------
# Main build
# ---------------------------------------------------------------------------
mkdir -p output
# Discover top-level topic directories (exclude hidden, build, output)
topics_list="${TMPDIR_BUILD}/topics.list.md"
: > "${topics_list}"
find_list="${TMPDIR_BUILD}/toplevel.find.list"
find . -mindepth 1 -maxdepth 1 -type d \
-not -name '.*' -not -name 'build' -not -name 'output' \
-print0 | sort -z > "${find_list}"
while IFS= read -r -d '' topic; do
topic="${topic#./}"
topic_title="$(get_frontmatter title "${topic}/index.md" 2>/dev/null || true)"
[[ -z "${topic_title}" ]] && topic_title="${topic}"
printf -- '- [%s](/%s)\n' "${topic_title}" "${topic}" >> "${topics_list}"
process_dir "${topic}"
done < "${find_list}"
# Home page — README.md + topic listing
home_md="${TMPDIR_BUILD}/home.md"
cp README.md "${home_md}"
printf '\n\n## topics:\n\n' >> "${home_md}"
cat "${topics_list}" >> "${home_md}"
content="$(lowdown "${home_md}")"
check_has_code "${content}"
export PAGE_TITLE=""
export CONTENT="${content}"
export BREADCRUMBS=""
export HEADER_EXTRA=""
export META_DATE=""
export META_DESCRIPTION=""
export HAS_CODE
export LANG="en"
export DIR=""
render_page "build/templates/home.html" "output/index.html"
echo "[built] output/index.html"
# License page
if [[ -f "LICENSE.md" ]]; then
content="$(lowdown LICENSE.md)"
check_has_code "${content}"
export PAGE_TITLE="license"
export CONTENT="${content}"
export BREADCRUMBS=" / license"
export HEADER_EXTRA=""
export META_DATE=""
export META_DESCRIPTION=""
export HAS_CODE
export LANG="en"
export DIR=""
render_page "build/templates/page.html" "output/license/index.html"
echo "[built] output/license/index.html"
fi
echo ""
echo "[done] Build complete. Output in output/"