Fix manifest icon references and add file reference linter

Manifest fixes:
- Updated all icon references from .png to .svg files
- Changed MIME types from image/png to image/svg+xml
- Removed missing screenshots section
- Fixed HTML favicon references to use SVG files

New reference linter (lint-references.py):
- Validates all file references in HTML and manifest files
- Checks that referenced files actually exist
- Prevents broken links and missing assets
- Integrated into justfile as 'validate-references'
- Added to check-all command for comprehensive validation

Justfile enhancements:
- Added validate-references command
- Updated check-all to include reference validation
- Enhanced validate command with reference checking

Documentation updates:
- Updated CLAUDE.md with reference validation info
- Added file reference checking to code quality standards

This prevents issues where manifest/HTML reference non-existent files,
improving PWA reliability and catching asset mismatches early.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2025-08-18 20:18:51 +02:00
commit 35c7d0bdc9
5 changed files with 179 additions and 31 deletions

147
lint-references.py Executable file
View file

@ -0,0 +1,147 @@
#!/usr/bin/env python3
"""
Reference validator for GlitchCraft
Checks that all file references in HTML and manifest actually exist
"""
import json
import os
import re
import sys
from pathlib import Path
def check_file_exists(file_path, base_dir):
"""Check if a file exists relative to base directory."""
full_path = base_dir / file_path
return full_path.exists()
def extract_html_references(html_content):
"""Extract file references from HTML content."""
references = []
# Link href attributes
for match in re.finditer(r'<link[^>]+href=["\']([^"\']+)["\']', html_content):
href = match.group(1)
if not href.startswith(('http://', 'https://', '//', 'data:', '#')):
references.append(href)
# Script src attributes
for match in re.finditer(r'<script[^>]+src=["\']([^"\']+)["\']', html_content):
src = match.group(1)
if not src.startswith(('http://', 'https://', '//', 'data:')):
references.append(src)
# Image src attributes
for match in re.finditer(r'<img[^>]+src=["\']([^"\']+)["\']', html_content):
src = match.group(1)
if not src.startswith(('http://', 'https://', '//', 'data:')):
references.append(src)
return references
def extract_manifest_references(manifest_data):
"""Extract file references from manifest JSON."""
references = []
# Icon sources
if 'icons' in manifest_data:
for icon in manifest_data['icons']:
if 'src' in icon:
references.append(icon['src'])
# Screenshot sources
if 'screenshots' in manifest_data:
for screenshot in manifest_data['screenshots']:
if 'src' in screenshot:
references.append(screenshot['src'])
return references
def check_html_file(file_path, base_dir):
"""Check all references in an HTML file."""
errors = []
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
references = extract_html_references(content)
for ref in references:
if not check_file_exists(ref, base_dir):
errors.append(f"Missing file: {ref}")
except Exception as e:
errors.append(f"Error reading {file_path}: {e}")
return errors
def check_manifest_file(file_path, base_dir):
"""Check all references in a manifest file."""
errors = []
try:
with open(file_path, 'r', encoding='utf-8') as f:
manifest_data = json.load(f)
references = extract_manifest_references(manifest_data)
for ref in references:
if not check_file_exists(ref, base_dir):
errors.append(f"Missing file: {ref}")
except Exception as e:
errors.append(f"Error reading {file_path}: {e}")
return errors
def main():
"""Main function to check all references."""
script_dir = Path(__file__).parent
app_dir = script_dir / 'app'
print("🔍 Checking file references...")
total_errors = 0
# Check HTML files
html_files = list(app_dir.glob('*.html'))
for html_file in html_files:
errors = check_html_file(html_file, app_dir)
if errors:
print(f"\n{html_file.name}:")
for error in errors:
print(f"{error}")
total_errors += 1
else:
print(f"{html_file.name}")
# Check manifest file
manifest_file = app_dir / 'manifest.json'
if manifest_file.exists():
errors = check_manifest_file(manifest_file, app_dir)
if errors:
print(f"\n❌ manifest.json:")
for error in errors:
print(f"{error}")
total_errors += 1
else:
print("✅ manifest.json")
# Summary
if total_errors == 0:
print(f"\n🎉 All file references are valid!")
return 0
else:
print(f"\n💥 Found {total_errors} reference error(s)")
return 1
if __name__ == '__main__':
sys.exit(main())