198 lines
6.6 KiB
Markdown
198 lines
6.6 KiB
Markdown
# 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:
|
|
1. Absolute path detection
|
|
2. Configured attachments folder lookup
|
|
3. Startup index unique match
|
|
4. Same directory as markdown file
|
|
5. Vault root relative resolution
|
|
6. Startup index closest path match
|
|
7. 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 folder
|
|
- `VAULT_N_SCAN_ATTACHMENTS`: Enable/disable attachment scanning (default: true)
|
|
|
|
#### API Endpoints
|
|
- `GET /api/image/{vault}?path=...`: Serve images with proper MIME types
|
|
- `POST /api/attachments/rescan/{vault}`: Manual vault attachment rescan
|
|
- `GET /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 resolution
|
|
- `backend/image_processor.py`: Markdown preprocessing for all image syntaxes
|
|
- `IMAGE_RENDERING_GUIDE.md`: Comprehensive implementation and testing guide
|
|
- `CHANGELOG_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/stats` endpoint
|
|
- Updated `_render_markdown()` to accept current file path
|
|
- Imported `mimetypes` module for content-type detection
|
|
|
|
#### Frontend
|
|
- `frontend/style.css`:
|
|
- Added `.image-not-found` placeholder styling
|
|
- Added responsive image rendering styles
|
|
- Added hover effects for linked images
|
|
|
|
#### 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
|
|
```python
|
|
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
|
|
```python
|
|
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
|
|
```python
|
|
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
|
|
|
|
1. **No automatic file watching**: Changes to image files require manual rescan
|
|
2. **No thumbnail generation**: Large images served at full resolution
|
|
3. **No image optimization**: Images served as-is from filesystem
|
|
4. **Case sensitivity**: Filename matching is case-insensitive, but path matching respects OS
|
|
|
|
### 🔄 Migration Guide
|
|
|
|
#### For Existing Installations
|
|
|
|
1. **No breaking changes**: Feature is fully backward compatible
|
|
2. **Optional configuration**: Works without any new environment variables
|
|
3. **Automatic indexing**: Enabled by default for all vaults
|
|
|
|
#### To Enable Optimized Resolution
|
|
|
|
Add to your `docker-compose.yml`:
|
|
```yaml
|
|
environment:
|
|
- VAULT_1_ATTACHMENTS_PATH=Assets/Images # Your attachments folder
|
|
```
|
|
|
|
#### To Disable Scanning (for vaults without images)
|
|
|
|
```yaml
|
|
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
|