diff --git a/.gitea/workflows/test-skins.yml b/.gitea/workflows/test-skins.yml index 4aac9bf..2a76f89 100644 --- a/.gitea/workflows/test-skins.yml +++ b/.gitea/workflows/test-skins.yml @@ -138,196 +138,109 @@ jobs: fi fi - - name: Check internal markdown file references + - name: Check all links in markdown files run: | #!/bin/bash echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "🔍 Checking Internal Markdown File References in All Markdown Files" + echo "🔍 Checking ALL Links in All Markdown Files" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" - # Find all markdown files and extract internal links with context - > internal_links_with_context.txt - find . -name "*.md" -type f | while IFS= read -r file; do - # Extract links with the skin name from headers - current_skin="" - while IFS= read -r line; do - # Check if it's a header (skin name) - if [[ "$line" =~ ^##[[:space:]]+\[([^\]]+)\] ]]; then - current_skin="${BASH_REMATCH[1]}" - fi - # Check for internal markdown links - if [[ "$line" =~ \]\((/[^\)]+\.md) ]]; then - link="${BASH_REMATCH[1]}" - echo "$current_skin|$link" >> internal_links_with_context.txt - fi - done < "$file" - done - - total_count=$(wc -l < internal_links_with_context.txt) - echo "📊 Total internal markdown links found: $total_count" + # Find all markdown files + find . -name "*.md" -type f | sort > all_markdown_files.txt + total_files=$(wc -l < all_markdown_files.txt) + echo "📊 Found $total_files markdown files to check" echo "" - # Group by skin and check - declare -A skin_all_files - declare -A skin_missing_files - checked_count=0 - total_missing=0 + has_errors=0 - while IFS='|' read -r skin link; do - checked_count=$((checked_count + 1)) + # Process each markdown file + while IFS= read -r md_file; do + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "📄 Checking: $md_file" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - # Decode URL-encoded characters - decoded_link=$(echo "$link" | sed 's/%20/ /g' | sed 's/%23/#/g' | sed 's/%28/(/g' | sed 's/%29/)/g' | sed 's/%E2%80%A2/•/g' | sed 's/%E1%9A%96/ᚖ/g' | sed 's/%E3%80%8A/《/g' | sed 's/%E3%80%8B/》/g' | sed 's/%E3%80%8E/『/g' | sed 's/%E3%80%8F/』/g' | sed 's/%E2%9B%94/⛔/g' | sed 's/%E2%9C%A8/✨/g' | sed 's/%7B/{/g' | sed 's/%7D/}/g' | sed 's/%2B/+/g' | sed 's/%E3%83%86/テ/g' | sed 's/%E3%83%B3/ン/g' | sed 's/%E3%83%8D/ネ/g' | sed 's/%E3%82%B9/ス/g' | sed 's/%E3%82%A4/イ/g' | sed 's/%E3%83%BB/・/g' | sed 's/%E3%83%95/フ/g' | sed 's/%E3%83%AA/リ/g' | sed 's/%E3%83%BC/ー/g' | sed 's/%E3%83%8A/ナ/g' | sed 's/%5B/[/g' | sed 's/%5D/]/g') + file_has_errors=0 - # Remove leading slash to make it relative - file_path="${decoded_link#/}" + # Extract ALL links from the markdown file + # Match both []() and direct URLs + grep -oP '\[([^\]]+)\]\(([^\)]+)\)' "$md_file" | sed 's/\[.*\](\(.*\))/\1/' > /tmp/links_$$.txt || true - if [ -z "$skin" ]; then - skin="General" - fi + # Also extract image links + grep -oP '!\[([^\]]*)\]\(([^\)]+)\)' "$md_file" | sed 's/!\[.*\](\(.*\))/\1/' >> /tmp/links_$$.txt || true - # Check if file exists - if [ -f "$file_path" ]; then - skin_all_files["$skin"]+="✅ $file_path"$'\n' - else - skin_all_files["$skin"]+="❌ $file_path"$'\n' - skin_missing_files["$skin"]+="$file_path"$'\n' - total_missing=$((total_missing + 1)) - fi - done < internal_links_with_context.txt - - # Report results - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - if [ $total_missing -gt 0 ]; then - echo "⚠️ RESULT: $total_missing of $total_count internal markdown files are MISSING" - else - echo "✅ RESULT: All $total_count internal markdown files exist!" - fi - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "" - - # Display all links grouped by skin - if [ ${#skin_all_files[@]} -gt 0 ]; then - for skin in "${!skin_all_files[@]}"; do - echo "📄 $skin:" - # Save to temp file to avoid subshell issues with pipes - printf '%s\n' "${skin_all_files[$skin]}" > /tmp/skin_files_$$.txt - while IFS= read -r line; do - [ -n "$line" ] && echo " $line" - done < /tmp/skin_files_$$.txt - rm -f /tmp/skin_files_$$.txt + link_count=$(wc -l < /tmp/links_$$.txt) + + if [ $link_count -eq 0 ]; then + echo " ℹ️ No links found in this file" echo "" - done - fi - - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - # Exit with error if files are missing - if [ $total_missing -gt 0 ]; then - echo "❌ SUMMARY: Workflow failed due to $total_missing missing markdown file(s)" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - exit 1 - else - echo "✅ SUMMARY: All checks passed!" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - fi - - - name: Check for broken image references - run: | - #!/bin/bash - - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "🖼️ Checking Image References in All Markdown Files" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "" - - # Extract all image links from all markdown files with context - > image_links_with_context.txt - find . -name "*.md" -type f | while IFS= read -r file; do - current_skin="" - while IFS= read -r line; do - # Check if it's a header (skin name) - if [[ "$line" =~ ^##[[:space:]]+\[([^\]]+)\] ]]; then - current_skin="${BASH_REMATCH[1]}" - fi - # Check for image links - if [[ "$line" =~ !\[.*\]\(([^\)]+\.(png|jpg|jpeg|gif|webp|svg)) ]]; then - link="${BASH_REMATCH[1]}" - # Skip external URLs - if [[ ! "$link" =~ ^https?:// ]]; then - echo "$current_skin|$link" >> image_links_with_context.txt + continue + fi + + echo " 📊 Found $link_count links to check" + echo "" + + # Check each link + while IFS= read -r link; do + # Decode URL-encoded characters + decoded_link=$(echo "$link" | sed 's/%20/ /g' | sed 's/%23/#/g' | sed 's/%28/(/g' | sed 's/%29/)/g' | sed 's/%E2%80%A2/•/g' | sed 's/%E1%9A%96/ᚖ/g' | sed 's/%E3%80%8A/《/g' | sed 's/%E3%80%8B/》/g' | sed 's/%E3%80%8E/『/g' | sed 's/%E3%80%8F/』/g' | sed 's/%E2%9B%94/⛔/g' | sed 's/%E2%9C%A8/✨/g' | sed 's/%7B/{/g' | sed 's/%7D/}/g' | sed 's/%2B/+/g' | sed 's/%E3%83%86/テ/g' | sed 's/%E3%83%B3/ン/g' | sed 's/%E3%83%8D/ネ/g' | sed 's/%E3%82%B9/ス/g' | sed 's/%E3%82%A4/イ/g' | sed 's/%E3%83%BB/・/g' | sed 's/%E3%83%95/フ/g' | sed 's/%E3%83%AA/リ/g' | sed 's/%E3%83%BC/ー/g' | sed 's/%E3%83%8A/ナ/g' | sed 's/%5B/[/g' | sed 's/%5D/]/g') + + # Check if it's an external URL + if [[ "$decoded_link" =~ ^https?:// ]]; then + # Check external URL with curl + if curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$decoded_link" | grep -q "^[23]"; then + echo " ✅ $decoded_link" + else + echo " ❌ $decoded_link (URL not accessible)" + file_has_errors=1 + has_errors=1 + fi + else + # Local file - remove leading slash if present + if [[ "$decoded_link" =~ ^/ ]]; then + file_path="${decoded_link#/}" + else + # Relative path - resolve from markdown file location + md_dir=$(dirname "$md_file") + file_path="$md_dir/$decoded_link" + fi + + # Normalize path + file_path=$(realpath -m "$file_path" 2>/dev/null || echo "$file_path") + + if [ -f "$file_path" ]; then + echo " ✅ $decoded_link" + else + echo " ❌ $decoded_link (file not found: $file_path)" + file_has_errors=1 + has_errors=1 fi fi - done < "$file" - done - - total_count=$(wc -l < image_links_with_context.txt) - echo "📊 Total local image references found: $total_count" - echo "" - - # Group by skin and check - declare -A skin_all_images - declare -A skin_missing_images - checked_count=0 - total_missing=0 - - while IFS='|' read -r skin link; do - checked_count=$((checked_count + 1)) + done < /tmp/links_$$.txt - # Decode URL-encoded characters - decoded_link=$(echo "$link" | sed 's/%20/ /g' | sed 's/%23/#/g' | sed 's/%28/(/g' | sed 's/%29/)/g' | sed 's/%E2%80%A2/•/g' | sed 's/%E1%9A%96/ᚖ/g' | sed 's/%E3%80%8A/《/g' | sed 's/%E3%80%8B/》/g' | sed 's/%E3%80%8E/『/g' | sed 's/%E3%80%8F/』/g' | sed 's/%E2%9B%94/⛔/g' | sed 's/%E2%9C%A8/✨/g' | sed 's/%7B/{/g' | sed 's/%7D/}/g' | sed 's/%2B/+/g' | sed 's/%E3%83%86/テ/g' | sed 's/%E3%83%B3/ン/g' | sed 's/%E3%83%8D/ネ/g' | sed 's/%E3%82%B9/ス/g' | sed 's/%E3%82%A4/イ/g' | sed 's/%E3%83%BB/・/g' | sed 's/%E3%83%95/フ/g' | sed 's/%E3%83%AA/リ/g' | sed 's/%E3%83%BC/ー/g' | sed 's/%E3%83%8A/ナ/g' | sed 's/%5B/[/g' | sed 's/%5D/]/g') + rm -f /tmp/links_$$.txt - # Remove leading slash for absolute paths - if [[ "$decoded_link" =~ ^/ ]]; then - decoded_link="${decoded_link#/}" - fi - - if [ -z "$skin" ]; then - skin="General" - fi - - # Check if file exists - if [ -f "$decoded_link" ]; then - skin_all_images["$skin"]+="✅ $decoded_link"$'\n' - else - skin_all_images["$skin"]+="❌ $decoded_link"$'\n' - skin_missing_images["$skin"]+="$decoded_link"$'\n' - total_missing=$((total_missing + 1)) - fi - done < image_links_with_context.txt - - # Report results - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - if [ $total_missing -gt 0 ]; then - echo "⚠️ RESULT: $total_missing of $total_count image files are MISSING (non-blocking)" - else - echo "✅ RESULT: All $total_count image files exist!" - fi - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "" - - # Display all images grouped by skin - if [ ${#skin_all_images[@]} -gt 0 ]; then - for skin in "${!skin_all_images[@]}"; do - echo "🖼️ $skin:" - # Save to temp file to avoid subshell issues with pipes - printf '%s\n' "${skin_all_images[$skin]}" > /tmp/skin_images_$$.txt - while IFS= read -r line; do - [ -n "$line" ] && echo " $line" - done < /tmp/skin_images_$$.txt - rm -f /tmp/skin_images_$$.txt + if [ $file_has_errors -eq 0 ]; then echo "" - done - fi + echo " ✅ All links valid in this file" + else + echo "" + echo " ❌ Some links are broken in this file" + fi + echo "" + + done < all_markdown_files.txt - # Don't fail the workflow for missing images, just warn - exit 0 + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + if [ $has_errors -eq 0 ]; then + echo "✅ FINAL RESULT: All links are valid across all markdown files!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 + else + echo "❌ FINAL RESULT: Some links are broken. Please review the output above." + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + exit 1 + fi