Files
SMF/Start.sh
Sterister 8933e9501d Initial commit: SMF2290 studie-app for eksamen vår 2026
Komplett pensumstudie-app med:
- 120 flashcards, 49 quiz-spørsmål, 16 eksamenstrener-oppgaver
- Sammendrag av alle 12 forelesninger
- tl;dr-side for siste-minutts pugging
- Søk gjennom hele pensumet
- Dark/light mode, mobile-vennlig

Cross-platform launchere (Start.sh + Start.bat) med auto-detect
og auto-install av HTTP-server. PowerShell-fallback for Windows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 18:44:00 +02:00

254 lines
9.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# =====================================================================
# SMF2290 Pensum — Start.sh
# Universal launcher: setter opp alt som trengs og starter studie-appen.
# Fungerer på Linux, macOS, og WSL/Git-Bash på Windows.
# =====================================================================
set -e
# --- Resolve script directory (works with symlinks too) -----------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_DIR="$SCRIPT_DIR/app"
VENDOR_DIR="$APP_DIR/vendor"
DEFAULT_PORT=8765
# --- ANSI colours --------------------------------------------------
if [ -t 1 ] && command -v tput >/dev/null 2>&1; then
BOLD="$(tput bold)"; DIM="$(tput dim)"; RESET="$(tput sgr0)"
RED="$(tput setaf 1)"; GREEN="$(tput setaf 2)"; YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"; ORANGE="$(tput setaf 208 2>/dev/null || tput setaf 3)"
else
BOLD=""; DIM=""; RESET=""; RED=""; GREEN=""; YELLOW=""; BLUE=""; ORANGE=""
fi
say() { printf "%s\n" "$*"; }
info() { printf " ${BLUE}${RESET} %s\n" "$*"; }
ok() { printf " ${GREEN}${RESET} %s\n" "$*"; }
warn() { printf " ${YELLOW}!${RESET} %s\n" "$*"; }
err() { printf " ${RED}${RESET} %s\n" "$*"; }
# --- Banner --------------------------------------------------------
banner() {
printf "\n"
printf " ${ORANGE}${BOLD}SMF · 2290${RESET} ${DIM}Etikk, bærekraft og samfunnsansvar${RESET}\n"
printf " ${BOLD}${BOLD}Pensum${RESET} ${DIM}studie-app · v1.0${RESET}\n"
printf "\n"
}
banner
# --- Sanity check --------------------------------------------------
if [ ! -d "$APP_DIR" ]; then
err "Fant ikke app-mappen: $APP_DIR"
err "Kjør Start.sh fra SMF-prosjektmappen."
exit 1
fi
# --- OS detection --------------------------------------------------
OS_NAME="$(uname -s 2>/dev/null || echo unknown)"
case "$OS_NAME" in
Linux*) PLATFORM="linux" ;;
Darwin*) PLATFORM="macos" ;;
MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
*) PLATFORM="unknown" ;;
esac
info "Plattform: ${BOLD}$PLATFORM${RESET}"
# --- Detect / install HTTP server ---------------------------------
SERVER_CMD=""
SERVER_NAME=""
find_server() {
if command -v python3 >/dev/null 2>&1; then
SERVER_CMD="python3 -m http.server PORT --bind 127.0.0.1"
SERVER_NAME="Python 3 ($(python3 --version 2>&1 | awk '{print $2}'))"
return 0
fi
if command -v python >/dev/null 2>&1 && python --version 2>&1 | grep -q "Python 3"; then
SERVER_CMD="python -m http.server PORT --bind 127.0.0.1"
SERVER_NAME="Python 3 ($(python --version 2>&1 | awk '{print $2}'))"
return 0
fi
if command -v php >/dev/null 2>&1; then
SERVER_CMD="php -S 127.0.0.1:PORT -t ."
SERVER_NAME="PHP $(php --version 2>&1 | head -1 | awk '{print $2}')"
return 0
fi
if command -v ruby >/dev/null 2>&1; then
SERVER_CMD="ruby -run -e httpd . --port=PORT --bind-address=127.0.0.1"
SERVER_NAME="Ruby $(ruby --version 2>&1 | awk '{print $2}')"
return 0
fi
if command -v node >/dev/null 2>&1 && command -v npx >/dev/null 2>&1; then
SERVER_CMD="npx --yes http-server -p PORT -a 127.0.0.1 --silent"
SERVER_NAME="Node.js $(node --version 2>&1)"
return 0
fi
return 1
}
try_install_python() {
warn "Ingen webserver funnet. Forsøker å installere Python 3 …"
local installed=0
if command -v apt-get >/dev/null 2>&1; then
info "Bruker apt (Debian/Ubuntu)"
if sudo -n true 2>/dev/null || sudo -v; then
sudo apt-get update -y && sudo apt-get install -y python3 && installed=1
fi
elif command -v dnf >/dev/null 2>&1; then
info "Bruker dnf (Fedora/RHEL)"
sudo dnf install -y python3 && installed=1
elif command -v yum >/dev/null 2>&1; then
info "Bruker yum"
sudo yum install -y python3 && installed=1
elif command -v pacman >/dev/null 2>&1; then
info "Bruker pacman (Arch)"
sudo pacman -Sy --noconfirm python && installed=1
elif command -v zypper >/dev/null 2>&1; then
info "Bruker zypper (openSUSE)"
sudo zypper install -y python3 && installed=1
elif command -v apk >/dev/null 2>&1; then
info "Bruker apk (Alpine)"
sudo apk add python3 && installed=1
elif command -v brew >/dev/null 2>&1; then
info "Bruker Homebrew (macOS)"
brew install python3 && installed=1
elif [ "$PLATFORM" = "macos" ]; then
warn "Homebrew finnes ikke. Installerer Homebrew først …"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" \
&& brew install python3 && installed=1
fi
[ $installed -eq 1 ]
}
info "Søker etter HTTP-server …"
if find_server; then
ok "Server-runtime: ${BOLD}$SERVER_NAME${RESET}"
else
if try_install_python && find_server; then
ok "Server-runtime: ${BOLD}$SERVER_NAME${RESET} (nylig installert)"
else
err "Klarte ikke installere en webserver automatisk."
say ""
say " Installer ${BOLD}én av disse${RESET} manuelt og prøv igjen:"
say " • Python 3: https://www.python.org/downloads/"
say " • Node.js: https://nodejs.org/"
say " • PHP eller Ruby via pakkesystemet ditt"
say ""
exit 1
fi
fi
# --- Verify marked.js (markdown renderer) -------------------------
if [ ! -s "$VENDOR_DIR/marked.min.js" ]; then
warn "marked.min.js mangler — laster ned …"
mkdir -p "$VENDOR_DIR"
if command -v curl >/dev/null 2>&1; then
curl -fsSL https://cdn.jsdelivr.net/npm/marked/marked.min.js -o "$VENDOR_DIR/marked.min.js" \
&& ok "marked.js lastet ned" \
|| { err "Klarte ikke laste ned marked.js. Trenger internett ved første kjøring."; exit 1; }
elif command -v wget >/dev/null 2>&1; then
wget -q https://cdn.jsdelivr.net/npm/marked/marked.min.js -O "$VENDOR_DIR/marked.min.js" \
&& ok "marked.js lastet ned" \
|| { err "Klarte ikke laste ned marked.js."; exit 1; }
else
err "Hverken curl eller wget funnet. Installer en av dem og kjør Start.sh igjen."
exit 1
fi
else
ok "marked.js OK ($(wc -c < "$VENDOR_DIR/marked.min.js") bytes)"
fi
# --- Sanity-sjekk dataene ----------------------------------------
required_files=(
"index.html"
"css/style.css"
"js/app.js"
"data/flashcards.json"
"data/quiz.json"
"data/exam.json"
"notes/uke17-eksamen.md"
)
missing=0
for f in "${required_files[@]}"; do
if [ ! -e "$APP_DIR/$f" ] && [ ! -L "$APP_DIR/$f" ]; then
err "Mangler: app/$f"
missing=$((missing + 1))
fi
done
# Notes-mappen er en symlink — sjekk at den peker rett
if [ -L "$APP_DIR/notes" ] && [ ! -e "$APP_DIR/notes" ]; then
warn "notes-symlink er ødelagt — gjenoppretter …"
rm -f "$APP_DIR/notes"
fi
if [ ! -d "$APP_DIR/notes" ]; then
if [ -d "$SCRIPT_DIR/notes" ]; then
ln -sfn "../notes" "$APP_DIR/notes"
ok "Symlink notes/ gjenopprettet"
else
err "Fant ikke notes/-mappen i prosjektet"
missing=$((missing + 1))
fi
fi
[ $missing -eq 0 ] && ok "Alle nødvendige filer på plass"
# --- Pick a free port --------------------------------------------
port_free() {
local p="$1"
if command -v lsof >/dev/null 2>&1; then
! lsof -i :"$p" -sTCP:LISTEN >/dev/null 2>&1
elif command -v ss >/dev/null 2>&1; then
! ss -ltn 2>/dev/null | awk '{print $4}' | grep -q ":$p$"
elif command -v netstat >/dev/null 2>&1; then
! netstat -ltn 2>/dev/null | awk '{print $4}' | grep -q ":$p$"
else
# No tool — assume free, the server will error out if not
return 0
fi
}
PORT="$DEFAULT_PORT"
while ! port_free "$PORT"; do
warn "Port $PORT er opptatt — prøver $((PORT + 1))"
PORT=$((PORT + 1))
if [ "$PORT" -gt 8800 ]; then
err "Fant ingen ledig port i 87658800. Lukk noen prosesser og prøv igjen."
exit 1
fi
done
URL="http://localhost:$PORT"
SERVER_CMD="${SERVER_CMD//PORT/$PORT}"
# --- Auto-open browser -------------------------------------------
open_browser() {
( sleep 1.5
if command -v xdg-open >/dev/null 2>&1; then
xdg-open "$URL" >/dev/null 2>&1 &
elif command -v open >/dev/null 2>&1; then
open "$URL" >/dev/null 2>&1 &
elif command -v start >/dev/null 2>&1; then
start "$URL" >/dev/null 2>&1 &
fi
) &
}
# --- Banner og start ----------------------------------------------
printf "\n"
printf " ${BOLD}┌──────────────────────────────────────────────┐${RESET}\n"
printf " ${BOLD}${RESET} ${ORANGE}${BOLD}SMF2290${RESET} · Pensum ${BOLD}${RESET}\n"
printf " ${BOLD}${RESET} ${BOLD}${RESET}\n"
printf " ${BOLD}${RESET} ${GREEN}→ %-42s${RESET}${BOLD}${RESET}\n" "$URL"
printf " ${BOLD}${RESET} ${BOLD}${RESET}\n"
SHORT_NAME="${SERVER_NAME:0:36}"
printf " ${BOLD}${RESET} ${DIM}Server: %-38s${RESET}${BOLD}${RESET}\n" "$SHORT_NAME"
printf " ${BOLD}${RESET} ${DIM}Trykk Ctrl+C for å stoppe${RESET} ${BOLD}${RESET}\n"
printf " ${BOLD}└──────────────────────────────────────────────┘${RESET}\n\n"
open_browser
cd "$APP_DIR"
# shellcheck disable=SC2086
exec $SERVER_CMD