feat: verify_article.sh +4 CSS-Compliance-Checks (vorbestell-box, bsn-facts, veraltete Boxen, Inline-Styles)
This commit is contained in:
+115
-17
@@ -1,26 +1,124 @@
|
|||||||
#!/bin/bash
|
#!/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
|
set -euo pipefail
|
||||||
|
|
||||||
FILE="${1:-}"
|
FILE="${1:-}"
|
||||||
ERRORS=0
|
ERRORS=0
|
||||||
WARNINGS=0
|
WARNINGS=0
|
||||||
ok() { echo "✅ $1"; }
|
|
||||||
fail() { echo "❌ $1"; ERRORS=$((ERRORS+1)); }
|
RED='\033[0;31m'
|
||||||
warn() { echo "⚠️ $1"; WARNINGS=$((WARNINGS+1)); }
|
GREEN='\033[0;32m'
|
||||||
if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then echo "Usage: $0 <file>"; exit 1; fi
|
YELLOW='\033[0;33m'
|
||||||
echo "=== $FILE ==="
|
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)
|
READMORE_COUNT=$(grep -c 'system-readmore' "$FILE" || true)
|
||||||
if [ "$READMORE_COUNT" = "1" ]; then ok "Read-More: 1"
|
if [ "$READMORE_COUNT" = "1" ]; then ok "Read-More: genau 1"
|
||||||
elif [ "$READMORE_COUNT" = "0" ]; then fail "Read-More: FEHLT"
|
elif [ "$READMORE_COUNT" = "0" ]; then fail "Read-More: KEIN <hr id=\"system-readmore\" /> gefunden"
|
||||||
else fail "Read-More: $READMORE_COUNT (muss 1)"; fi
|
else fail "Read-More: $READMORE_COUNT Stück (muss genau 1 sein)"; fi
|
||||||
if grep -q '<div class="meta">' "$FILE"; then fail "div.meta statt p.meta"; else ok "p.meta korrekt"; fi
|
|
||||||
BODY=$(sed -n '/<body>/,/<\/body>/p' "$FILE")
|
# CHECK 2: Kein <br> nach Read-More
|
||||||
if echo "$BODY" | grep -qP '[\x{1F300}-\x{1F9FF}\x{2600}-\x{27BF}\x{1F600}-\x{1F64F}]'; then fail "Emojis im Body"; else ok "Keine Emojis"; fi
|
if grep -A1 'system-readmore' "$FILE" | grep -q '<br'; then
|
||||||
if echo "$BODY" | grep -q '<h2>Quellen</h2>'; then fail "h2>Quellen statt span-strong"; else ok "Quellen-Überschrift korrekt"; fi
|
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_TOTAL=$(echo "$BODY" | grep -o '<a ' | wc -l)
|
||||||
LINKS_BLANK=$(echo "$BODY" | grep -o 'target="_blank"' | 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"
|
if [ "$LINKS_TOTAL" -gt 0 ] && [ "$LINKS_TOTAL" != "$LINKS_BLANK" ]; then
|
||||||
else ok "Alle $LINKS_TOTAL Links mit target=_blank"; fi
|
fail "$((LINKS_TOTAL - LINKS_BLANK)) von $LINKS_TOTAL Links ohne target=\"_blank\""
|
||||||
if grep -q '<meta name="description" content="[^"]*[a-zA-Z]' "$FILE"; then ok "Meta-Description"; else fail "Meta-Description fehlt"; fi
|
else ok "Alle $LINKS_TOTAL Links mit target=\"_blank\""; fi
|
||||||
if grep -q '<meta name="keywords" content="[^"]*[a-zA-Z]' "$FILE"; then ok "Meta-Keywords"; else fail "Meta-Keywords fehlen"; 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 ""
|
||||||
[ $ERRORS -eq 0 ] && echo "✅ ALLE CHECKS BESTANDEN" || echo "❌ $ERRORS Fehler"
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user