Files
BSN-Chatsystem/verify_article.sh
T

125 lines
5.0 KiB
Bash
Executable File

#!/bin/bash
# verify_article.sh — Prüft Artikel-HTML auf Einhaltung aller redaktionellen Standards
# Usage: bash verify_article.sh <artikel_datei.html>
# Exit 0 = alle Checks bestanden, Exit 1 = Fehler gefunden
set -euo pipefail
FILE="${1:-}"
ERRORS=0
WARNINGS=0
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'
ok() { echo -e "${GREEN}$1${NC}"; }
fail() { echo -e "${RED}$1${NC}"; ERRORS=$((ERRORS+1)); }
warn() { echo -e "${YELLOW}⚠️ $1${NC}"; WARNINGS=$((WARNINGS+1)); }
if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then
echo "Usage: $0 <artikel_datei.html>"
exit 1
fi
echo "=== Verifiziere: $FILE ==="
echo ""
# CHECK 1: Genau 1 Read-More
READMORE_COUNT=$(grep -c 'system-readmore' "$FILE" || true)
if [ "$READMORE_COUNT" = "1" ]; then ok "Read-More: genau 1"
elif [ "$READMORE_COUNT" = "0" ]; then fail "Read-More: KEIN <hr id=\"system-readmore\" /> gefunden"
else fail "Read-More: $READMORE_COUNT Stück (muss genau 1 sein)"; fi
# CHECK 2: Kein <br> nach Read-More
if grep -A1 'system-readmore' "$FILE" | grep -q '<br'; then
fail "<br> direkt nach Read-More"; else ok "Kein <br> nach Read-More"; fi
# CHECK 3: p.meta nicht div.meta
if grep -q '<div class="meta">' "$FILE"; then
fail "<div class=\"meta\"> statt <p class=\"meta\">"; else ok "<p class=\"meta\"> korrekt"; fi
# CHECK 4: Keine Emojis
BODY=$(sed -n '/<article>/,/<\/article>/p' "$FILE")
if echo "$BODY" | grep -qP '[\x{1F300}-\x{1F9FF}\x{2600}-\x{27BF}\x{1F600}-\x{1F64F}]'; then
fail "Emojis im Artikel-Body gefunden"; else ok "Keine Emojis"; fi
# CHECK 5: Endet mit </html>
LAST_LINE=$(tail -1 "$FILE")
if echo "$LAST_LINE" | grep -q '</html>'; then ok "Datei endet mit </html>"
else fail "Letzte Zeile ist nicht </html>"; fi
# CHECK 6: Meta-Zeile im Body (Warnung)
if echo "$BODY" | grep -qP '<p[^>]*>.*\d{1,2}\.\s+\w+\s+\d{4}.*·.*Lesezeit'; then
warn "Meta-Zeile möglicherweise im Body"; fi
# CHECK 7: Quellen als span-strong, nicht h2
if echo "$BODY" | grep -q '<h2>Quellen</h2>'; then
fail "<h2>Quellen</h2> statt span-strong"; else ok "Quellen-Überschrift korrekt"; fi
# CHECK 8: Alle Links target="_blank"
LINKS_TOTAL=$(echo "$BODY" | grep -o '<a ' | wc -l)
LINKS_BLANK=$(echo "$BODY" | grep -o 'target="_blank"' | wc -l)
if [ "$LINKS_TOTAL" -gt 0 ] && [ "$LINKS_TOTAL" != "$LINKS_BLANK" ]; then
fail "$((LINKS_TOTAL - LINKS_BLANK)) von $LINKS_TOTAL Links ohne target=\"_blank\""
else ok "Alle $LINKS_TOTAL Links mit target=\"_blank\""; fi
# CHECK 9: Meta-Description
if grep -q '<meta name="description" content="[^"]*[a-zA-Z]' "$FILE"; then
ok "Meta-Description vorhanden"; else fail "Meta-Description fehlt oder leer"; fi
# CHECK 10: QC inside p.qc
QC_COUNT=$(echo "$BODY" | grep -c 'class=\"qc\"' || true)
QC_RAW=$(echo "$BODY" | grep -cP 'QC:\s*[✓✔]' || true)
if [ "$QC_RAW" -gt "$QC_COUNT" ]; then fail "QC-Hinweis nicht in <p class=\"qc\">"
else ok "QC-Zeile korrekt in <p class=\"qc\">"; fi
# CHECK 11: Umlaute (fix_umlauts.py) — 29.06.2026
UMLAUT_SCRIPT="$(dirname "$0")/fix_umlauts.py"
if [ -f "$UMLAUT_SCRIPT" ]; then
UMLAUT_OUTPUT=$(python3 "$UMLAUT_SCRIPT" "$FILE" 2>&1)
if echo "$UMLAUT_OUTPUT" | grep -q "⚠"; then
fail "Umlaut-Fehler gefunden. fix_umlauts.py angewandt — bitte erneut prüfen"
echo "$UMLAUT_OUTPUT" | grep "⚠" | head -3
else
ok "Umlaute: sauber"
fi
else
warn "fix_umlauts.py nicht gefunden, Umlaut-Check übersprungen"
fi
# CHECK 12: vorbestell-box ohne Inline-Styles (10.07.2026)
if echo "$BODY" | grep -qP '<div[^>]*class="[^"]*vorbestell-box[^"]*"[^>]*style='; then
fail "vorbestell-box hat Inline-Styles — muss clean sein (nur class=)"
else ok "vorbestell-box: keine Inline-Styles"; fi
# CHECK 13: bsn-facts ohne Inline-Styles (10.07.2026)
if echo "$BODY" | grep -qP '<div[^>]*class="[^"]*bsn-facts[^"]*"[^>]*style='; then
fail "bsn-facts hat Inline-Styles — muss clean sein (nur class=)"
else ok "bsn-facts: keine Inline-Styles"; fi
# CHECK 14: Keine veralteten affiliate-box / dotted / cream (10.07.2026)
if echo "$BODY" | grep -qP 'affiliate-box|border:[^;]*dotted|background:#f5f0eb'; then
fail "Veraltete Box-Formate (affiliate-box/dotted/cream) — vorbestell-box verwenden!"
else ok "Keine veralteten Box-Formate"; fi
# CHECK 15: Keine strukturellen Inline-Styles im Body (10.07.2026)
INLINE_DIV_COUNT=$(echo "$BODY" | grep -oP '<div[^>]*style="[^"]*(?:background|border)[^"]*"' | wc -l)
if [ "$INLINE_DIV_COUNT" -gt 0 ]; then
fail "$INLINE_DIV_COUNT div(s) mit Inline-background/border — BSN-Klassen verwenden!"
else ok "Keine strukturellen Inline-Styles im Body"; fi
echo ""
echo "═══════════════════════════════════════"
if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then
echo -e "${GREEN}✅ ALLE CHECKS BESTANDEN${NC}"
exit 0
elif [ $ERRORS -eq 0 ]; then
echo -e "${YELLOW}⚠️ $WARNINGS Warnung(en) — KEINE Fehler${NC}"
exit 0
else
echo -e "${RED}$ERRORS Fehler, $WARNINGS Warnungen${NC}"
exit 1
fi