6.6 KiB
6.6 KiB
Changelog - Obsidian Image Rendering Feature
Version 1.2.0 - Image Rendering Support
🖼️ New Features
Comprehensive Image Syntax Support
- Standard Markdown with HTML attributes:
[<img width="180" height="60" src="path"/>](url) - Obsidian wiki-link embeds (full path):
![[folder/subfolder/image.svg]] - Obsidian wiki-link embeds (filename only):
![[image.png]] - Standard Markdown images:

Intelligent Multi-Strategy Path Resolution
Implements 7-tier resolution system with priority order:
- Absolute path detection
- Configured attachments folder lookup
- Startup index unique match
- Same directory as markdown file
- Vault root relative resolution
- Startup index closest path match
- Styled placeholder fallback
Attachment Indexing System
- Asynchronous vault scanning at startup
- Supports:
.png,.jpg,.jpeg,.gif,.svg,.webp,.bmp,.ico - Per-vault index with filename → absolute path mapping
- Resolution cache for performance optimization
- Detailed logging of indexed attachments
Vault Configuration Extensions
New optional environment variables:
VAULT_N_ATTACHMENTS_PATH: Relative path to primary attachments folderVAULT_N_SCAN_ATTACHMENTS: Enable/disable attachment scanning (default: true)
API Endpoints
GET /api/image/{vault}?path=...: Serve images with proper MIME typesPOST /api/attachments/rescan/{vault}: Manual vault attachment rescanGET /api/attachments/stats?vault=...: Attachment statistics per vault
Frontend Enhancements
- Responsive image rendering with max-width constraints
- Styled placeholders for missing images with tooltips
- Hover effects on linked images
- Rounded corners and subtle shadows
📁 New Files
backend/attachment_indexer.py: Image scanning, indexing, and resolutionbackend/image_processor.py: Markdown preprocessing for all image syntaxesIMAGE_RENDERING_GUIDE.md: Comprehensive implementation and testing guideCHANGELOG_IMAGE_RENDERING.md: This file
🔧 Modified Files
Backend
-
backend/indexer.py:- Updated vault config to support attachments configuration
- Integrated attachment index building at startup
- Added config storage in vault data structure
-
backend/main.py:- Added image preprocessing to markdown rendering pipeline
- Implemented
/api/image/{vault}endpoint with MIME type detection - Added
/api/attachments/rescan/{vault}endpoint - Added
/api/attachments/statsendpoint - Updated
_render_markdown()to accept current file path - Imported
mimetypesmodule for content-type detection
Frontend
frontend/style.css:- Added
.image-not-foundplaceholder styling - Added responsive image rendering styles
- Added hover effects for linked images
- Added
Documentation
README.md:- Added image rendering feature to features list
- Added new environment variables documentation
- Added new API endpoints to API section
- Added comprehensive "Rendu d'images Obsidian" section
- Updated usage instructions
🎯 Implementation Details
Resolution Algorithm
def resolve_image_path(image_src, vault_name, vault_root, current_file_path, attachments_path):
# 1. Check cache
# 2. Try absolute path
# 3. Try config attachments folder
# 4. Try startup index (unique match)
# 5. Try same directory as markdown file
# 6. Try vault root relative
# 7. Try startup index (closest match)
# 8. Return None (fallback to placeholder)
Image Preprocessing Pipeline
def preprocess_images(content, vault_name, vault_root, current_file_path, attachments_path):
# 1. Process HTML img in markdown links
# 2. Process wiki-link embeds
# 3. Process standard markdown images
# All paths resolved and transformed to /api/image endpoint
Attachment Index Structure
attachment_index = {
"VaultName": {
"image.png": [Path("/absolute/path/to/image.png")],
"logo.svg": [Path("/path/1/logo.svg"), Path("/path/2/logo.svg")]
}
}
🔒 Security
- Path traversal protection maintained for image serving
- All image paths validated through
_resolve_safe_path() - MIME type detection prevents serving arbitrary files
- Read-only vault mounts recommended in docker-compose
⚡ Performance
- Startup: O(n) scan where n = number of files in vault
- Resolution (cached): O(1) hash table lookup
- Resolution (uncached): O(k) where k ≤ 7 strategies
- Memory: ~100 bytes per indexed image
- Cache invalidation: On manual rescan only
📊 Logging
New log messages:
Vault '{name}': indexed {count} attachments(INFO)Vault '{name}': attachment scanning disabled(INFO)Image resolved via strategy N (description)(DEBUG)Image not resolved (fallback)(DEBUG)Rescanned attachments for vault '{name}': {count} attachments(INFO)
🧪 Testing
All acceptance criteria met:
- ✅ All 4 image syntaxes render correctly
- ✅ Startup scan is asynchronous and non-blocking
- ✅ Filename-only wiki-links resolve via index
- ✅ Config attachmentsPath used as priority
- ✅ Unresolved images show styled placeholder
- ✅ No regression on standard markdown syntax
- ✅ Rescan command works without restart
🐛 Known Limitations
- No automatic file watching: Changes to image files require manual rescan
- No thumbnail generation: Large images served at full resolution
- No image optimization: Images served as-is from filesystem
- Case sensitivity: Filename matching is case-insensitive, but path matching respects OS
🔄 Migration Guide
For Existing Installations
- No breaking changes: Feature is fully backward compatible
- Optional configuration: Works without any new environment variables
- Automatic indexing: Enabled by default for all vaults
To Enable Optimized Resolution
Add to your docker-compose.yml:
environment:
- VAULT_1_ATTACHMENTS_PATH=Assets/Images # Your attachments folder
To Disable Scanning (for vaults without images)
environment:
- VAULT_N_SCAN_ATTACHMENTS=false
📝 Documentation
- README.md: Updated with feature overview and configuration
- IMAGE_RENDERING_GUIDE.md: Comprehensive implementation guide
- CHANGELOG_IMAGE_RENDERING.md: This detailed changelog
🙏 Acknowledgments
Implementation based on Obsidian's image handling specifications and community feedback regarding vault attachment organization patterns.
Release Date: 2025
Compatibility: ObsiGate 1.1.0+
Python Version: 3.11+
Dependencies: No new dependencies required