Files
SMF/Start.sh
Sterister 0f4370626c Fiks Windows-oppstart: git-symlink og PowerShell-server
To uavhengige feil hindret oppstart på Windows:

1. app/notes var committet som en git-symlink (mode 120000). På
   Windows uten symlink-støtte materialiseres den som en stray
   tekstfil («../notes»), så appen ikke fant notatene. Start.bat
   sin reparasjon brukte rmdir/mkdir som begge feiler når notes
   er en fil.
   → Avregistrert symlinken fra git og gitignorert den. app/notes
     opprettes nå per plattform av launcherne (symlink på unix,
     kopi på Windows). Start.bat normaliserer robust: sletter en
     stray fil, lager mappe og kopierer *.md. Start.sh håndterer
     også fil-tilfellet.

2. server.ps1 krasjet umiddelbart pga. Add-Type System.Web (ikke
   tilgjengelig i PowerShell 7), og cmd-vinduet forsvant uten pause.
   → Fjernet System.Web (bruker System.Uri::UnescapeDataString),
     la til HttpListener-støttesjekk og tydelige feilmeldinger.
     Start.bat pauser nå når serveren stopper, så feil kan leses.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 21:42:29 +02:00

258 lines
9.3 KiB
Bash
Executable File
Raw Permalink 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
# app/notes opprettes per plattform (gitignorert). Den skal være en symlink
# til ../notes. Håndter ødelagt symlink ELLER en git-materialisert tekstfil.
if [ -L "$APP_DIR/notes" ] && [ ! -e "$APP_DIR/notes" ]; then
warn "notes-symlink er ødelagt — gjenoppretter …"
rm -f "$APP_DIR/notes"
elif [ -f "$APP_DIR/notes" ]; then
warn "app/notes er en vanlig fil (git-symlink fra Windows) — erstatter med symlink …"
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