aboutsummaryrefslogtreecommitdiffstats
path: root/build.sh
diff options
context:
space:
mode:
authorAhmed <git@gumx.cc>2026-06-02 00:21:16 +0300
committerAhmed <git@gumx.cc>2026-06-02 00:21:16 +0300
commit6e1e8effd3e595ad342d11644b072725a218c1eb (patch)
tree11d4c650734d814c6180db6618b89dbf3ae8c8d3 /build.sh
init: moved to gumx.cc
Diffstat (limited to 'build.sh')
-rw-r--r--build.sh215
1 files changed, 215 insertions, 0 deletions
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000..2973c2f
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,215 @@
+#!/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 '<pre><code|<code class='; then
+ HAS_CODE="true"
+ else
+ HAS_CODE=""
+ fi
+}
+
+render_page() {
+ local template="$1" outfile="$2"
+ mkdir -p "$(dirname "${outfile}")"
+ local tname="${template##build/templates/}"
+ cp "${template}" "build/templates/partials/${tname}"
+ (cd build/templates/partials && mo "${tname}") > "${outfile}"
+ rm -f "build/templates/partials/${tname}"
+}
+
+build_breadcrumbs() {
+ local path="$1"
+ BREADCRUMBS=""
+ local components="${path}"
+ while [[ "${components}" != "." ]]; do
+ BREADCRUMBS=" / <a href=\"/${components}\">$(basename "${components}")</a>${BREADCRUMBS}"
+ components="$(dirname "${components}")"
+ done
+}
+
+# ---------------------------------------------------------------------------
+# process_dir dir
+# Recursively renders topic and module pages, returns a markdown list
+# of direct children into ${TMPDIR_BUILD}/${dir//\//_}.list.md
+# ---------------------------------------------------------------------------
+process_dir() {
+ local dir="$1"
+ local list_file="${TMPDIR_BUILD}/${dir//\//_}.list.md"
+ : > "${list_file}"
+
+ local find_list="${TMPDIR_BUILD}/${dir//\//_}.find.list"
+ find "${dir}" -mindepth 1 -maxdepth 1 -not -name '.*' -print0 | sort -z > "${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=" / <a href=\"/license\">license</a>"
+ 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/"