diff options
| author | Paul Buetow <paul@buetow.org> | 2025-07-18 20:04:03 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-07-18 20:04:03 +0300 |
| commit | 186629c94152c9066158edb1b0105737ed39d6da (patch) | |
| tree | f4326ab8dc7ffa4ba9a6d6184252cdc4115079e5 | |
| parent | 85900734f1ab76b1079d935e046b6edcbfab84ae (diff) | |
fix: use unique filenames in Anki exports by prefixing with card ID
- Fixed issue where all cards used the same filenames (audio.mp3, image.jpg)
- Now prefixes media files with card ID (directory name) in Anki exports
- Updated both CSV and APKG generators to use unique names
- Ensures Anki properly associates correct media with each card
- Files in directories remain unchanged, only Anki references are prefixed
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
| -rw-r--r-- | internal/anki/apkg_generator.go | 48 | ||||
| -rw-r--r-- | internal/anki/generator.go | 25 |
2 files changed, 53 insertions, 20 deletions
diff --git a/internal/anki/apkg_generator.go b/internal/anki/apkg_generator.go index 6f0043f..6da0cfb 100644 --- a/internal/anki/apkg_generator.go +++ b/internal/anki/apkg_generator.go @@ -504,19 +504,29 @@ func (g *APKGGenerator) insertNotesAndCards(db *sql.DB) error { imageField := "" if card.ImageFile != "" && fileExists(card.ImageFile) { - basename := filepath.Base(card.ImageFile) - if _, ok := g.mediaFiles[basename]; ok { - // Use the original filename in the card content - imageField = fmt.Sprintf(`<img src="%s">`, basename) + // Get card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(card.ImageFile)) + originalFilename := filepath.Base(card.ImageFile) + // Create unique filename with card ID prefix + uniqueFilename := fmt.Sprintf("%s_%s", cardID, originalFilename) + + if _, ok := g.mediaFiles[uniqueFilename]; ok { + // Use the unique filename in the card content + imageField = fmt.Sprintf(`<img src="%s">`, uniqueFilename) } } audioField := "" if card.AudioFile != "" && fileExists(card.AudioFile) { - basename := filepath.Base(card.AudioFile) - if _, ok := g.mediaFiles[basename]; ok { - // Use the original filename in the card content - audioField = fmt.Sprintf("[sound:%s]", basename) + // Get card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(card.AudioFile)) + originalFilename := filepath.Base(card.AudioFile) + // Create unique filename with card ID prefix + uniqueFilename := fmt.Sprintf("%s_%s", cardID, originalFilename) + + if _, ok := g.mediaFiles[uniqueFilename]; ok { + // Use the unique filename in the card content + audioField = fmt.Sprintf("[sound:%s]", uniqueFilename) } } @@ -588,26 +598,36 @@ func (g *APKGGenerator) copyMediaFiles(tempDir string) error { for _, card := range g.cards { // Copy audio file if card.AudioFile != "" && fileExists(card.AudioFile) { - filename := filepath.Base(card.AudioFile) - if _, exists := g.mediaFiles[filename]; !exists { + // Get card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(card.AudioFile)) + originalFilename := filepath.Base(card.AudioFile) + // Create unique filename with card ID prefix + uniqueFilename := fmt.Sprintf("%s_%s", cardID, originalFilename) + + if _, exists := g.mediaFiles[uniqueFilename]; !exists { targetPath := filepath.Join(tempDir, fmt.Sprintf("%d", g.mediaCounter)) if err := copyFile(card.AudioFile, targetPath); err != nil { return fmt.Errorf("failed to copy audio file %s: %w", card.AudioFile, err) } - g.mediaFiles[filename] = g.mediaCounter + g.mediaFiles[uniqueFilename] = g.mediaCounter g.mediaCounter++ } } // Copy image file if card.ImageFile != "" && fileExists(card.ImageFile) { - filename := filepath.Base(card.ImageFile) - if _, exists := g.mediaFiles[filename]; !exists { + // Get card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(card.ImageFile)) + originalFilename := filepath.Base(card.ImageFile) + // Create unique filename with card ID prefix + uniqueFilename := fmt.Sprintf("%s_%s", cardID, originalFilename) + + if _, exists := g.mediaFiles[uniqueFilename]; !exists { targetPath := filepath.Join(tempDir, fmt.Sprintf("%d", g.mediaCounter)) if err := copyFile(card.ImageFile, targetPath); err != nil { return fmt.Errorf("failed to copy image file %s: %w", card.ImageFile, err) } - g.mediaFiles[filename] = g.mediaCounter + g.mediaFiles[uniqueFilename] = g.mediaCounter g.mediaCounter++ } } diff --git a/internal/anki/generator.go b/internal/anki/generator.go index 0682d94..0b393f3 100644 --- a/internal/anki/generator.go +++ b/internal/anki/generator.go @@ -109,8 +109,12 @@ func (g *Generator) formatAudioField(audioFile string) string { return "" } - // Get just the filename - filename := filepath.Base(audioFile) + // Get card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(audioFile)) + originalFilename := filepath.Base(audioFile) + + // Create filename with card ID prefix for uniqueness in Anki + filename := fmt.Sprintf("%s_%s", cardID, originalFilename) // Anki audio format: [sound:filename.mp3] return fmt.Sprintf("[sound:%s]", filename) @@ -122,8 +126,13 @@ func (g *Generator) formatImageField(imageFile string) string { return "" } - // Get just the filename - filename := filepath.Base(imageFile) + // Get card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(imageFile)) + originalFilename := filepath.Base(imageFile) + + // Create filename with card ID prefix for uniqueness in Anki + filename := fmt.Sprintf("%s_%s", cardID, originalFilename) + return fmt.Sprintf(`<img src="%s">`, filename) } @@ -279,8 +288,12 @@ func (g *Generator) copyMediaFile(src, destDir string) (string, error) { return "", err } - // Create destination path - filename := filepath.Base(src) + // Get the card ID from the source path (parent directory name) + cardID := filepath.Base(filepath.Dir(src)) + + // Create destination filename with card ID prefix + originalFilename := filepath.Base(src) + filename := fmt.Sprintf("%s_%s", cardID, originalFilename) destPath := filepath.Join(destDir, filename) // Check if file already exists |
