fix(vault): skip image reference scans for notes without shared images

This commit is contained in:
eezd committed 2026-10-24 19:38:40 +08:00
1 parent 8b2d32a3be
commit a26ebea843
2 files changed
+77 -4

No files matched your search

+10 -4
View File
@@ -27,6 +27,15 @@ func (v *Vault) copyNoteImages(from, to string) (transfers []imageTransfer, targ
if len(metadata.Warnings) != 0 { if len(metadata.Warnings) != 0 {
return nil, nil, fmt.Errorf("%w:%s 的元数据异常,无法确认图片引用", ErrInvalidPath, from) return nil, nil, fmt.Errorf("%w:%s 的元数据异常,无法确认图片引用", ErrInvalidPath, from)
} }
var images []Reference
for _, ref := range metadata.Assets {
if IsImage(ref.Target) && !strings.HasPrefix(ref.Target, AssetsDir(from)+"/") {
images = append(images, ref)
}
}
if len(images) == 0 {
return nil, nil, nil
}
entries, err := v.Tree() entries, err := v.Tree()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -49,10 +58,7 @@ func (v *Vault) copyNoteImages(from, to string) (transfers []imageTransfer, targ
} }
} }
targets = map[string]string{} targets = map[string]string{}
for _, ref := range metadata.Assets { for _, ref := range images {
if !IsImage(ref.Target) || strings.HasPrefix(ref.Target, AssetsDir(from)+"/") {
continue
}
if _, seen := targets[ref.Target]; seen { if _, seen := targets[ref.Target]; seen {
continue continue
} }
+67
View File
@@ -26,6 +26,73 @@ func TestNoteUploadsShareFolderAssetsAndRejectInvalidNotes(t *testing.T) {
} }
} }
func TestNoteMoveWithoutSharedImagesIgnoresUnrelatedInvalidMetadata(t *testing.T) {
for _, body := range []string{"# Plain note\n\nNo images or links.", "[attachment](./document.pdf)", "![](plain.assets/old.png)"} {
t.Run(body, func(t *testing.T) {
v := newVault(t)
if _, err := v.Write("unrelated.md", []byte("---\ntags: [broken\n---\n# Unrelated"), Precondition{}); err != nil {
t.Fatal(err)
}
if _, err := v.Write("old/plain.md", []byte(body), Precondition{}); err != nil {
t.Fatal(err)
}
if strings.Contains(body, "plain.assets") {
if err := v.Mkdir("old/plain.assets"); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(v.Root(), "old/plain.assets/old.png"), []byte("legacy"), 0644); err != nil {
t.Fatal(err)
}
}
if _, err := v.Move("old/plain.md", "new/plain.md"); err != nil {
t.Fatal("无共享图片的移动不应被无关元数据阻断", err)
}
got, _, err := v.Read("new/plain.md")
expected := strings.ReplaceAll(body, "./document.pdf", "../old/document.pdf")
if err != nil || string(got) != expected {
t.Fatalf("移动后的正文不符:%q %v", got, err)
}
if _, err := v.Stat("old/plain.md"); !errors.Is(err, ErrNotFound) {
t.Fatal("源笔记未移走", err)
}
if strings.Contains(body, "plain.assets") {
image, err := os.ReadFile(filepath.Join(v.Root(), "new/plain.assets/old.png"))
if err != nil || string(image) != "legacy" {
t.Fatalf("独立附件未随笔记移动:%q %v", image, err)
}
}
})
}
}
func TestNoteImageMoveStillRejectsUncertainReferences(t *testing.T) {
v := newVault(t)
link, err := v.SaveAsset("old/plain.md", "p.png", strings.NewReader("image"), 100)
if err != nil {
t.Fatal(err)
}
body := "![](" + link + ")"
for note, content := range map[string]string{"old/plain.md": body, "unrelated.md": "---\ntags: [broken\n---\n# Unrelated"} {
if _, err := v.Write(note, []byte(content), Precondition{}); err != nil {
t.Fatal(err)
}
}
if _, err := v.Move("old/plain.md", "new/plain.md"); !errors.Is(err, ErrInvalidPath) {
t.Fatal("无法确认其他笔记引用时不得移除共享图片", err)
}
got, _, err := v.Read("old/plain.md")
if err != nil || string(got) != body {
t.Fatalf("失败后原文被改写:%q %v", got, err)
}
image, err := os.ReadFile(filepath.Join(v.Root(), "old", link))
if err != nil || string(image) != "image" {
t.Fatalf("失败后源图丢失:%q %v", image, err)
}
if _, err := v.Stat("new/plain.md"); !errors.Is(err, ErrNotFound) {
t.Fatal("失败后出现目标笔记", err)
}
}
func TestNoteMoveTransfersSharedImagesWithoutBreakingOtherNotes(t *testing.T) { func TestNoteMoveTransfersSharedImagesWithoutBreakingOtherNotes(t *testing.T) {
for _, shared := range []bool{false, true} { for _, shared := range []bool{false, true} {
for _, collision := range []string{"none", "same", "different"} { for _, collision := range []string{"none", "same", "different"} {