feat: implement unified DocumentNavigator with lazy loading for all modes

- Add DocumentNavigator UI element for document navigation across viewing and editing modes
- Implement lazy loading approach where control appears immediately but navigation content builds on-demand
- Position controls on left side following UI convention for consistent navigation experience
- Add scroll spy functionality for current section detection
- Include responsive design with mobile auto-hide
- Create comprehensive development guardrails to prevent JavaScript corruption
- Add JavaScript validation tool for syntax error detection

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-10 19:39:46 +01:00
parent 7270bc559d
commit 2d516b205a
3 changed files with 506 additions and 0 deletions

161
tools/validate_js.py Executable file
View File

@@ -0,0 +1,161 @@
#!/usr/bin/env python3
"""
JavaScript Validation Tool
Extracts JavaScript from HTML files and validates syntax.
Detects common issues like "Uncaught SyntaxError: unexpected token"
"""
import re
import subprocess
import sys
import tempfile
from pathlib import Path
def extract_javascript_from_html(html_file):
"""Extract all JavaScript code from an HTML file."""
try:
content = Path(html_file).read_text(encoding='utf-8')
except Exception as e:
print(f"❌ Failed to read {html_file}: {e}")
return []
# Find all <script> blocks
script_pattern = r'<script[^>]*>(.*?)</script>'
scripts = re.findall(script_pattern, content, re.DOTALL | re.IGNORECASE)
# Filter out empty scripts and external script tags
js_blocks = []
for script in scripts:
script = script.strip()
if script and not script.startswith('http'): # Skip external scripts
js_blocks.append(script)
return js_blocks
def validate_javascript_syntax(js_code):
"""Validate JavaScript syntax using Node.js."""
try:
# Create temporary JS file
with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f:
f.write(js_code)
temp_file = f.name
# Try to parse with node --check
result = subprocess.run(
['node', '--check', temp_file],
capture_output=True,
text=True
)
# Clean up
Path(temp_file).unlink()
if result.returncode == 0:
return True, "✓ Syntax OK"
else:
return False, f"❌ Syntax Error: {result.stderr.strip()}"
except FileNotFoundError:
# Fallback: Try to detect obvious syntax errors
return validate_javascript_basic(js_code)
except Exception as e:
return False, f"❌ Validation failed: {e}"
def validate_javascript_basic(js_code):
"""Basic JavaScript syntax validation without Node.js."""
errors = []
# Check for common syntax issues
if js_code.count('{') != js_code.count('}'):
errors.append("Mismatched curly braces")
if js_code.count('(') != js_code.count(')'):
errors.append("Mismatched parentheses")
if js_code.count('[') != js_code.count(']'):
errors.append("Mismatched square brackets")
# Check for unescaped quotes in strings
if re.search(r'["\']\s*["\']\s*["\']\s*["\']', js_code):
errors.append("Possible quote escaping issue")
# Check for Python-style string formatting leftover
if '${' in js_code and '"}' in js_code:
errors.append("Possible Python string template leftover")
if errors:
return False, f"❌ Potential issues: {', '.join(errors)}"
else:
return True, "✓ Basic validation passed (Node.js not available)"
def validate_html_js(html_file):
"""Validate all JavaScript in an HTML file."""
print(f"🔍 Validating JavaScript in: {html_file}")
js_blocks = extract_javascript_from_html(html_file)
if not js_blocks:
print("⚠️ No JavaScript found in HTML file")
return True
print(f"📝 Found {len(js_blocks)} JavaScript blocks")
all_valid = True
for i, js_block in enumerate(js_blocks, 1):
print(f"\n--- Script Block {i} ({len(js_block)} chars) ---")
# Show first few lines for context
lines = js_block.split('\n')[:3]
preview = '\n'.join(lines)
if len(lines) < len(js_block.split('\n')):
preview += "\n..."
print(f"Preview:\n{preview}")
is_valid, message = validate_javascript_syntax(js_block)
print(message)
if not is_valid:
all_valid = False
# Show more context around potential error
if 'line' in message.lower():
try:
line_num = re.search(r'line (\d+)', message, re.IGNORECASE)
if line_num:
line_no = int(line_num.group(1))
lines = js_block.split('\n')
start = max(0, line_no - 3)
end = min(len(lines), line_no + 2)
print("\nContext around error:")
for j in range(start, end):
marker = ">>> " if j == line_no - 1 else " "
print(f"{marker}{j+1:3}: {lines[j]}")
except:
pass
print(f"\n{'' if all_valid else ''} Overall result: {'All JavaScript is valid' if all_valid else 'JavaScript validation failed'}")
return all_valid
def main():
if len(sys.argv) != 2:
print("Usage: python validate_js.py <html_file>")
print("Example: python validate_js.py /tmp/test-edit.html")
sys.exit(1)
html_file = sys.argv[1]
if not Path(html_file).exists():
print(f"❌ File not found: {html_file}")
sys.exit(1)
success = validate_html_js(html_file)
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()