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:
parent
82704caa97
commit
35c7d0bdc9
5 changed files with 179 additions and 31 deletions
147
lint-references.py
Executable file
147
lint-references.py
Executable 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())
|
||||
Loading…
Add table
Add a link
Reference in a new issue