restructure: rename termin to kapitel, flatten folder structure

- rename slide files: YYYY-MM-DD-termin-N-topic.md → NN-topic.md
- flatten folders: courses/X/slides/ → slides/X/
- replace "Termin" with "Kapitel" in all content
- add klausur extraction script (make klausur)
- update Makefile, generate-index.sh, dev-server.sh
- add README.md with full documentation
This commit is contained in:
2026-01-25 11:26:15 +01:00
parent b951341376
commit a8343c9937
128 changed files with 1464 additions and 3484 deletions

View File

@@ -8,7 +8,7 @@ set -e
INDEX_PORT=1310
COURSE_B_PORT=1311
COURSE_C_PORT=1312
COURSE_DIR="courses"
SLIDES_DIR="slides"
DEV_INDEX_DIR=".dev-index"
# Colors
@@ -94,12 +94,12 @@ echo ""
python3 -m http.server $INDEX_PORT --directory "$DEV_INDEX_DIR" &
PID_INDEX=$!
PORT=$COURSE_B_PORT npx @marp-team/marp-cli --server "$COURSE_DIR/223015b/slides/" &
PORT=$COURSE_B_PORT npx @marp-team/marp-cli --server "$SLIDES_DIR/223015b/" &
PID_B=$!
sleep 3 # Stagger starts to avoid WebSocket port collision
PORT=$COURSE_C_PORT npx @marp-team/marp-cli --server "$COURSE_DIR/223015c/slides/" &
PORT=$COURSE_C_PORT npx @marp-team/marp-cli --server "$SLIDES_DIR/223015c/" &
PID_C=$!
# Wait for any process to exit

112
scripts/extract-klausur.sh Executable file
View File

@@ -0,0 +1,112 @@
#!/usr/bin/env bash
# Extract klausur-relevant slides from all kapitel
# Usage: ./extract-klausur.sh <course_id>
# Output: slides/<course>/klausur.md
set -e
COURSE="${1:-223015b}"
SLIDES_DIR="slides/$COURSE"
OUTPUT_FILE="$SLIDES_DIR/klausur.md"
# Find the first kapitel file (01-*.md) to copy styles from
FIRST_KAPITEL=$(ls "$SLIDES_DIR"/01-*.md 2>/dev/null | head -1)
if [[ -z "$FIRST_KAPITEL" ]]; then
echo "Error: No 01-*.md file found in $SLIDES_DIR"
exit 1
fi
echo "Extracting klausur slides for $COURSE..."
# Extract frontmatter and styles (everything up to first <!-- _class: line after style block)
# This gets the YAML frontmatter + <style> block
awk '
BEGIN { in_frontmatter = 0; in_style = 0; done = 0 }
/^---$/ && !in_frontmatter { in_frontmatter = 1; print; next }
/^---$/ && in_frontmatter && !in_style { in_frontmatter = 0; print; next }
in_frontmatter { print; next }
/<style>/ { in_style = 1; print; next }
/<\/style>/ { in_style = 0; print; print ""; done = 1; next }
in_style { print; next }
done { exit }
' "$FIRST_KAPITEL" > "$OUTPUT_FILE"
# Add warning comment
cat >> "$OUTPUT_FILE" << 'EOF'
<!--
╔═══════════════════════════════════════════════════════════════════╗
║ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY ║
║ ║
║ This file is generated by: make klausur ║
║ Source: scripts/extract-klausur.sh ║
║ ║
║ To update, edit the source slides and re-run make klausur ║
╚═══════════════════════════════════════════════════════════════════╝
-->
EOF
# Extract and copy the cover slide (first slide after frontmatter/styles, up to first ---)
awk '
BEGIN { past_style = 0; in_cover = 0; printed = 0 }
/<\/style>/ { past_style = 1; next }
past_style && !in_cover && /^[^[:space:]]/ { in_cover = 1 }
in_cover && /^---$/ { print "---\n"; exit }
in_cover { print }
' "$FIRST_KAPITEL" >> "$OUTPUT_FILE"
# Process each kapitel file in order - extract klausur slides only
for md_file in $(ls "$SLIDES_DIR"/[0-9][0-9]-*.md 2>/dev/null | grep -v klausur | sort); do
filename=$(basename "$md_file")
kapitel_num=$(echo "$filename" | grep -oE '^[0-9]+' | sed 's/^0*//')
# Skip intro (kapitel 0)
if [[ "$kapitel_num" == "0" ]] || [[ -z "$kapitel_num" ]]; then
continue
fi
# Check if file has any klausur slides
if ! grep -q '<!-- _class: klausur -->' "$md_file"; then
continue
fi
echo " Processing Kapitel $kapitel_num..."
# Extract klausur slides, hide header/footer, convert * to - bullets
awk '
/<!-- _class: klausur -->/ {
in_klausur = 1
# Add header/footer hiding
print "<!-- _header: \"\" -->"
print "<!-- _footer: \"\" -->"
print ""
next
}
in_klausur && /^---$/ {
print "\n---\n"
in_klausur = 0
next
}
in_klausur {
# Skip marp directives (we add our own)
if (/<!-- _header:/ || /<!-- _footer:/ || /<!-- _backgroundColor:/) next
# Convert * bullets to - bullets (avoid fragments)
gsub(/^\* /, "- ")
gsub(/^ \* /, " - ")
gsub(/^ \* /, " - ")
print
}
' "$md_file" >> "$OUTPUT_FILE"
done
# Remove trailing --- and empty lines
perl -i -0777 -pe 's/\n*---\n*$/\n/' "$OUTPUT_FILE"
# Count slides
slide_count=$(grep -c '^---$' "$OUTPUT_FILE" 2>/dev/null || echo "0")
echo ""
echo "Generated: $OUTPUT_FILE"
echo "Total slides: $slide_count"

View File

@@ -77,13 +77,13 @@ cat > "$BUILD_DIR/index.html" << HEADER
font-size: 0.875rem;
margin-top: 0.25rem;
}
.termine {
.kapitel {
margin-top: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.termin-card {
.kapitel-card {
position: relative;
background: #fff;
border-radius: 12px;
@@ -94,31 +94,31 @@ cat > "$BUILD_DIR/index.html" << HEADER
align-items: center;
gap: 1rem;
}
.termin-card:hover {
.kapitel-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}
.termin-link {
.kapitel-link {
display: block;
padding: 1.25rem 1.5rem;
text-decoration: none;
color: inherit;
grid-column: 1;
}
.termin-label {
.kapitel-label {
font-size: 0.7rem;
font-weight: 600;
color: $ACCENT_COLOR;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.termin-title {
.kapitel-title {
font-size: 1.05rem;
font-weight: 500;
color: #1d1d1f;
margin: 0.15rem 0;
}
.termin-date {
.kapitel-date {
font-size: 0.8rem;
color: #86868b;
}
@@ -151,7 +151,7 @@ cat > "$BUILD_DIR/index.html" << HEADER
}
.btn-pdf:hover { background: #e8e8ed; }
/* Make entire card clickable via overlay */
.termin-link::after {
.kapitel-link::after {
content: '';
position: absolute;
inset: 0;
@@ -184,10 +184,10 @@ cat > "$BUILD_DIR/index.html" << HEADER
color: #86868b;
}
@media (max-width: 600px) {
.termin-card {
.kapitel-card {
grid-template-columns: 1fr;
}
.termin-link {
.kapitel-link {
padding-bottom: 0.75rem;
}
.btn-slides, .btn-pdf {
@@ -205,14 +205,13 @@ cat > "$BUILD_DIR/index.html" << HEADER
<div class="termine">
HEADER
# Generate links for each termin (sorted)
for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
# Generate links for each kapitel (sorted)
for html in $(ls "$BUILD_DIR"/[0-9][0-9]-*.html 2>/dev/null | sort); do
filename=$(basename "$html")
# Extract components from filename
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-9x]{2}-[0-9x]{2}-termin-[0-9]+-//' | sed 's/\.html$//')
# Extract components from filename (format: NN-topic.html)
kapitel_num=$(echo "$filename" | grep -oE '^[0-9]+' | sed 's/^0*//')
topic_raw=$(echo "$filename" | sed -E 's/^[0-9]+-//' | sed 's/\.html$//')
# Look up nice topic name or fallback
topic="${TOPIC_MAP[$topic_raw]}"
@@ -220,18 +219,11 @@ for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
topic=$(echo "$topic_raw" | sed 's/-/ /g' | sed 's/.*/\u&/')
fi
# Format 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")
# Handle kapitel number
if [[ "$kapitel_num" == "0" ]] || [[ -z "$kapitel_num" ]]; then
kapitel_label="Einführung"
else
formatted_date="Termin folgt"
fi
# Handle termin number
if [[ "$termin_num" == "0" ]]; then
termin_label="Einführung"
else
termin_label="Termin $termin_num"
kapitel_label="Kapitel $kapitel_num"
fi
pdf_filename="${filename%.html}.pdf"
@@ -243,11 +235,10 @@ for html in $(ls "$BUILD_DIR"/2*.html 2>/dev/null | sort); do
fi
cat >> "$BUILD_DIR/index.html" << LINK
<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>
<div class="kapitel-card">
<a href="$filename" class="kapitel-link">
<div class="kapitel-label">$kapitel_label</div>
<div class="kapitel-title">$topic</div>
</a>
<a href="$filename" class="btn btn-slides">Folien</a>
$pdf_link