fix(notes): billederne i en importeret note pegede på ingenting
Release / Build and publish image (push) Failing after 9m54s

Fundet ved at importere rigtige noter frem for ti prøvenoter.

Linket blev skrevet halvt om. attachToNote kendte to måder, en note kan nævne en
fil på — den bare filnavn og stien i forhold til noten — men ikke den, en Apple
Noter-eksport faktisk skriver: `vedhaeftninger/751-2-IMG_0615.heic`, med noten i
roden ved siden af mappen. Kun det bare navn matchede, så kun det blev erstattet,
og hver eneste billede i hver eneste importerede note endte som
`vedhaeftninger//api/v1/attachments/…`, som er ingenting. Filerne var gemt og
hæftet rigtigt på; det var linket, der var forkert. Længste match først, ellers
bliver mappen stående foran adressen.

Og billederne kunne alligevel ikke vises. Alt blev serveret som
application/octet-stream med Content-Disposition: attachment, hvilket er en god
regel med en god grund — en uploadet SVG eller HTML vist inline ville køre sit
eget script på dette domæne med sessionscookien på. Men en note bærer sine
billeder i teksten som `![](…)`, og under den regel er hvert eneste af dem et
brudt billede. Hele importen findes for at tage dem med.

En kort liste af rasterformater vises nu inline med deres egen type. Det er ikke
en opblødning: listen er navngivet ét format ad gangen frem for matchet på
"image/", fordi præfikset ville lukke image/svg+xml ind — et dokument, der kan
køre script — og en liste, der vokser ved et uheld, er præcis sådan det sker.
nosniff står, så browseren skal læse filen som netop det billede eller slet ikke.

Titlen stod to gange i fjorten noter. Noter kalder noten det, der står på de
første linjer sat sammen med mellemrum, så en note, hvis to første linjer er
"CPU" og "CAN", hedder "CPU CAN" — og sammenligningen med kun den første linje
gik fri. Overskrifterne øverst tages nu med, så længe de tilsammen stadig er
begyndelsen på titlen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kristian Wind
2026-08-19 22:02:20 +02:00
co-authored by Claude Opus 5
parent f6c6bdccbb
commit 2ffbd9533b
3 changed files with 91 additions and 13 deletions
+22 -5
View File
@@ -7,6 +7,7 @@ import (
"mime"
"net/http"
"path"
"sort"
"strings"
"time"
@@ -421,10 +422,20 @@ func (s *Server) attachToNote(
continue
}
base := path.Base(f.Name)
// The two ways a Markdown file names a neighbouring image: by the path it
// was written with, and by its bare name.
// The three ways a Markdown file names a neighbouring image: by its path
// inside the archive, by the path relative to the note, and by its bare name.
//
// The archive path was missing, and it is the one an Apple Notes export
// actually writes — `vedhaeftninger/751-2-IMG_0615.heic`, with the note at the
// root beside the folder. Only the bare name matched, so only the bare name
// was replaced, and every picture in every imported note ended up pointing at
// `vedhaeftninger//api/v1/attachments/…`, which is nothing. The images were
// stored and attached correctly; it was the link that was wrong.
relative := strings.TrimPrefix(path.Join(dir, base), "./")
if !strings.Contains(body, base) && !strings.Contains(body, relative) {
refs := []string{f.Name, relative, base}
if !strings.Contains(body, f.Name) &&
!strings.Contains(body, relative) &&
!strings.Contains(body, base) {
continue
}
@@ -441,9 +452,15 @@ func (s *Server) attachToNote(
continue
}
// Længste først. Erstattes det bare navn inde i en længere sti, bliver mappen
// stående foran adressen, og linket peger på ingenting.
url := "/api/v1/attachments/" + a.ID
body = strings.ReplaceAll(body, relative, url)
body = strings.ReplaceAll(body, base, url)
sort.Slice(refs, func(i, j int) bool { return len(refs[i]) > len(refs[j]) })
for _, ref := range refs {
if ref != "" {
body = strings.ReplaceAll(body, ref, url)
}
}
attached++
}
return body, attached