add slide content improvements and dev server setup

223015b:
- add WTF hex code explanation slide (89=137 decimal, PNG signature)
- add ASCII lead slide with historical context
- remove Hilbert-Studie reference from title

223015c termin 2:
- add OSI layer 5 (session) and layer 6 (presentation) slides
- add URL/domain anatomy slide
- mark HTTP/S section as klausur
- improve status codes formatting with client/server examples
- add CRUD column to HTTP methods table

infrastructure:
- add dev-server.sh for multi-course development
- update generate-index.sh with course-specific colors
- add QR codes for slide URLs
This commit is contained in:
2025-12-30 16:24:44 +01:00
parent 0ff5e94e20
commit 1b9b2f315a
36 changed files with 837 additions and 230 deletions

View File

@@ -8,22 +8,40 @@ BUILD_DIR="${2:-build/$COURSE}"
# Course-specific configuration
case "$COURSE" in
223015b)
TITLE="223015b - Dateiformate, Schnittstellen, Speichermedien"
SUBTITLE="Dateiformate, Schnittstellen, Speichermedien & Distributionswege"
REPO_URL="https://git.librete.ch/hdm/223015b"
TITLE="Dateiformate, Schnittstellen, Speichermedien & Distributionswege"
SUBTITLE="223015b · Modul \"Technik 1\" · 1. Semester"
SLIDES_URL="https://librete.ch/hdm/223015b"
ACCENT_COLOR="#5da9e9"
ACCENT_LIGHT="#e8f4fc"
;;
223015c)
TITLE="223015c - Internettechnologien"
SUBTITLE="Internettechnologien"
REPO_URL="https://git.librete.ch/hdm/223015c"
TITLE="Grundlagen IT- und Internettechnik"
SUBTITLE="223015c · Modul \"Technik 1\" · 1. Semester"
SLIDES_URL="https://librete.ch/hdm/223015c"
ACCENT_COLOR="#d63384"
ACCENT_LIGHT="#fce4ec"
;;
*)
TITLE="$COURSE - HdM Slides"
SUBTITLE="Lecture Slides"
REPO_URL="https://git.librete.ch/hdm/$COURSE"
SLIDES_URL="https://librete.ch/hdm/$COURSE"
ACCENT_COLOR="#0066cc"
ACCENT_LIGHT="#e8f4fc"
;;
esac
# Topic mappings for nice German titles
declare -A TOPIC_MAP
TOPIC_MAP["intro"]="Einführung"
TOPIC_MAP["grundlagen-text-audio"]="Grundlagen, Text & Audio"
TOPIC_MAP["bild-audio-video"]="Bild, Audio & Video"
TOPIC_MAP["speichermedien-schnittstellen"]="Speichermedien & Schnittstellen"
TOPIC_MAP["distribution-apis-zukunft"]="Distribution, APIs & Zukunft"
TOPIC_MAP["vertiefung-offene-fragen"]="Vertiefung & Offene Fragen"
TOPIC_MAP["geschichte-grundlagen-html"]="Geschichte, Grundlagen & HTML"
TOPIC_MAP["netzwerke-protokolle-css"]="Netzwerke, Protokolle & CSS"
TOPIC_MAP["interaktivitaet-javascript"]="Interaktivität & JavaScript"
cat > "$BUILD_DIR/index.html" << HEADER
<!DOCTYPE html>
<html lang="de">
@@ -32,65 +50,142 @@ cat > "$BUILD_DIR/index.html" << HEADER
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$TITLE</title>
<style>
* { box-sizing: border-box; }
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
max-width: 800px;
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, sans-serif;
max-width: 720px;
margin: 0 auto;
padding: 2rem;
background: #1a1a2e;
color: #eee;
padding: 3rem 1.5rem;
background: #fafafa;
color: #1d1d1f;
line-height: 1.5;
}
h1 { color: #fff; margin-bottom: 0.5rem; }
.subtitle { color: #888; margin-bottom: 2rem; }
.termin-row {
header { margin-bottom: 2rem; }
h1 {
font-size: 1.75rem;
font-weight: 600;
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
color: $ACCENT_COLOR;
}
.subtitle {
color: #86868b;
font-size: 0.95rem;
}
.meta {
color: #86868b;
font-size: 0.875rem;
margin-top: 0.25rem;
}
.termine {
margin-top: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.termin-card {
position: relative;
background: #fff;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
transition: all 0.2s ease;
display: grid;
grid-template-columns: 1fr auto auto;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.termin {
background: #16213e;
border-radius: 8px;
padding: 1.5rem;
text-decoration: none;
.termin-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}
.termin-link {
display: block;
flex: 1;
transition: transform 0.2s, background 0.2s;
}
.termin:hover { background: #1f4068; transform: translateX(5px); }
.termin h2 { color: #fff; margin: 0 0 0.5rem 0; font-size: 1.2rem; }
.termin .date { color: #4ecca3; font-size: 0.9rem; }
.termin .topic { color: #aaa; font-size: 0.95rem; margin-left: 1rem; }
.pdf {
background: #e94560;
color: #fff;
padding: 0.5rem 1rem;
border-radius: 4px;
padding: 1.25rem 1.5rem;
text-decoration: none;
font-size: 0.85rem;
color: inherit;
grid-column: 1;
}
.termin-label {
font-size: 0.7rem;
font-weight: 600;
color: $ACCENT_COLOR;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.termin-title {
font-size: 1.05rem;
font-weight: 500;
transition: background 0.2s;
color: #1d1d1f;
margin: 0.15rem 0;
}
.pdf:hover { background: #ff6b6b; }
.qr-section {
margin-top: 2rem;
text-align: center;
.termin-date {
font-size: 0.8rem;
color: #86868b;
}
.qr-section img {
max-width: 150px;
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 8px;
background: #fff;
padding: 0.5rem;
text-decoration: none;
font-size: 0.8rem;
font-weight: 500;
transition: all 0.2s;
white-space: nowrap;
position: relative;
z-index: 1;
}
.btn-slides {
background: $ACCENT_COLOR;
color: #fff;
margin-right: 0.5rem;
}
.btn-slides:hover {
filter: brightness(1.1);
}
.btn-pdf {
background: #f5f5f7;
color: #1d1d1f;
margin-right: 1rem;
}
.btn-pdf:hover { background: #e8e8ed; }
/* Make entire card clickable via overlay */
.termin-link::after {
content: '';
position: absolute;
inset: 0;
border-radius: 12px;
}
footer {
margin-top: 2.5rem;
padding-top: 1.5rem;
border-top: 1px solid #e5e5e7;
color: #86868b;
font-size: 0.85rem;
}
footer a { color: $ACCENT_COLOR; text-decoration: none; }
footer a:hover { text-decoration: underline; }
@media (max-width: 600px) {
.termin-card {
grid-template-columns: 1fr;
}
.termin-link {
padding-bottom: 0.75rem;
}
.btn-slides, .btn-pdf {
margin: 0 1rem 1rem 1.5rem;
}
}
footer { margin-top: 2rem; color: #666; font-size: 0.85rem; text-align: center; }
footer a { color: #4ecca3; }
</style>
</head>
<body>
<h1>$COURSE</h1>
<p class="subtitle">$SUBTITLE<br>
HdM Stuttgart - WS 2025/26 - Michael Czechowski</p>
<header>
<h1>$TITLE</h1>
<p class="subtitle">$SUBTITLE</p>
<p class="meta">HdM Stuttgart · Wintersemester 2025/26 · Michael Czechowski</p>
</header>
<div class="termine">
HEADER
# Generate links for each termin (sorted)
@@ -98,23 +193,26 @@ for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
filename=$(basename "$html")
# Extract components from filename
date=$(echo "$filename" | grep -oE '^[0-9]{4}-[0-9]{2}-[0-9]{2}')
date=$(echo "$filename" | grep -oE '^[0-9]{4}-[0-9x]{2}-[0-9x]{2}')
termin_num=$(echo "$filename" | grep -oE 'termin-[0-9]+' | grep -oE '[0-9]+')
topic_raw=$(echo "$filename" | sed -E 's/^[0-9]{4}-[0-9]{2}-[0-9]{2}-termin-[0-9]+-//' | sed 's/\.html$//')
topic_raw=$(echo "$filename" | sed -E 's/^[0-9]{4}-[0-9x]{2}-[0-9x]{2}-termin-[0-9]+-//' | sed 's/\.html$//')
# Format topic: replace - with space, capitalize
topic=$(echo "$topic_raw" | sed 's/-/ /g' | sed 's/.*/\u&/')
# Look up nice topic name or fallback
topic="${TOPIC_MAP[$topic_raw]}"
if [[ -z "$topic" ]]; then
topic=$(echo "$topic_raw" | sed 's/-/ /g' | sed 's/.*/\u&/')
fi
# Format date
if [[ "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
formatted_date=$(date -d "$date" "+%d.%m.%Y" 2>/dev/null || echo "$date")
if [[ "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && [[ ! "$date" =~ xx ]]; then
formatted_date=$(date -d "$date" "+%d. %B %Y" 2>/dev/null || echo "$date")
else
formatted_date="TBA"
formatted_date="Termin folgt"
fi
# Handle termin number
if [[ "$termin_num" == "0" ]]; then
termin_label="Einfuhrung"
termin_label="Einführung"
else
termin_label="Termin $termin_num"
fi
@@ -124,35 +222,27 @@ for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
# Check if PDF exists
pdf_link=""
if [[ -f "$BUILD_DIR/$pdf_filename" ]]; then
pdf_link="<a href=\"$pdf_filename\" class=\"pdf\">PDF</a>"
pdf_link="<a href=\"$pdf_filename\" class=\"btn btn-pdf\">PDF</a>"
fi
cat >> "$BUILD_DIR/index.html" << LINK
<div class="termin-row">
<a href="$filename" class="termin">
<h2>$termin_label</h2>
<span class="date">$formatted_date</span>
<span class="topic">$topic</span>
</a>
$pdf_link
</div>
<div class="termin-card">
<a href="$filename" class="termin-link">
<div class="termin-label">$termin_label</div>
<div class="termin-title">$topic</div>
<div class="termin-date">$formatted_date</div>
</a>
<a href="$filename" class="btn btn-slides">Folien</a>
$pdf_link
</div>
LINK
done
# Add QR code if exists
if [[ -f "$BUILD_DIR/qr-$COURSE.png" ]]; then
cat >> "$BUILD_DIR/index.html" << QRSECTION
<div class="qr-section">
<img src="qr-$COURSE.png" alt="QR Code">
<p style="color: #888; font-size: 0.8rem;">Scan to open on mobile</p>
</div>
QRSECTION
fi
cat >> "$BUILD_DIR/index.html" << FOOTER
</div>
<footer>
<a href="$REPO_URL">Git Repository</a> -
<a href="mailto:mail@librete.ch">Kontakt</a>
<a href="mailto:mail@librete.ch">Kontakt</a> ·
<a href="../">Alle Kurse</a>
</footer>
</body>
</html>