#!/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/"