fix: recover compressed WeChat image resource references

This commit is contained in:
tianma-if committed 2026-09-23 18:38:29 +08:00
1 parent e21583dfb8
commit 672016cc3c
3 files changed
+53 -4

No files matched your search

+16 -3
View File
@@ -13,6 +13,7 @@ globalThis.window = {
sidecarRequest: async (method, params) => {
lastRequest = { method, params };
if (method === "memo.get") {
const filename = params.memoId === "memo_wechat" ? "微信图片_202609231723_1.jpg" : "screenshot.webp";
return {
memo: {
id: params.memoId,
@@ -20,10 +21,10 @@ globalThis.window = {
type: "doc",
content: [{
type: "image",
attrs: { alt: "screenshot.webp", src: "edgeever-staged://stage_dead" },
attrs: { alt: filename, src: "edgeever-staged://stage_dead" },
}],
},
contentMarkdown: "![screenshot.webp](edgeever-staged://stage_dead)\n\n",
contentMarkdown: `![${filename}](edgeever-staged://stage_dead)\n\n`,
},
};
}
@@ -35,8 +36,14 @@ globalThis.window = {
kind: "image",
filename: "screenshot.webp",
url: "/api/v1/resources/res_shot/blob",
}, {
id: "res_wechat",
memoId: "memo_wechat",
kind: "image",
filename: "微信图片_202609231723_1.webp",
url: "/api/v1/resources/res_wechat/blob",
}],
summary: { totalCount: 1, totalBytes: 1, imageCount: 1, attachmentCount: 0 },
summary: { totalCount: 2, totalBytes: 2, imageCount: 2, attachmentCount: 0 },
};
}
if (method === "memo.update") {
@@ -132,4 +139,10 @@ describe("desktop repository memo reads", () => {
expect(result.memo.contentMarkdown).not.toContain("edgeever-staged://");
expect(result.memo.contentJson.content[0].attrs.src).toBe("edgeever-resource://resource/res_shot");
});
test("recovers an imported WeChat image after jpg compression changed its extension", async () => {
const result = await createDesktopRepository().getMemo("memo_wechat");
expect(result.memo.contentJson.content[0].attrs.src).toBe("edgeever-resource://resource/res_wechat");
expect(result.memo.contentMarkdown).toContain("edgeever-resource://resource/res_wechat");
});
});
@@ -81,6 +81,36 @@ describe("staged resource repair", () => {
.toEqual([]);
});
test("recovers a WeChat image whose uploaded filename changed from jpg to webp", () => {
const memo = {
contentJson: { type: "doc", content: [{ type: "image", attrs: {
alt: "微信图片_202609231723_1.jpg",
src: "edgeever-staged://stage_missing",
width: 35,
} }] },
contentMarkdown: "![微信图片_202609231723_1.jpg](edgeever-staged://stage_missing)",
};
const resourceUrl = "/api/v1/resources/res_wechat/blob";
const repaired = repairMemoStagedResourceUrls(memo, [{
url: resourceUrl,
filename: "微信图片_202609231723_1.webp",
kind: "image",
}]);
expect(repaired.contentJson.content[0].attrs).toEqual({
alt: "微信图片_202609231723_1.jpg",
src: resourceUrl,
width: 35,
});
expect(repaired.contentMarkdown).toBe(`![微信图片_202609231723_1.jpg](${resourceUrl})`);
});
test("does not guess between resources with the same filename stem", () => {
expect(findMatchingMemoResource([
{ url: "/api/v1/resources/res_a/blob", filename: "image.jpg", kind: "image" },
{ url: "/api/v1/resources/res_b/blob", filename: "image.webp", kind: "image" },
], "image.png", "image")).toBeNull();
});
test("does not guess when a memo has several images and the placeholder has no filename", () => {
expect(findMatchingMemoResource([
screenshotResource,
+7 -1
View File
@@ -106,7 +106,13 @@ export const findMatchingMemoResource = (
const normalizedFilename = filename?.trim();
if (normalizedFilename) {
const named = pool.filter((resource) => resource.filename === normalizedFilename);
return named[0] ?? null;
if (named.length === 1) return named[0];
if (named.length > 1) return null;
// Image compression may change only the extension (for example, .jpg to
// .webp) while the editor keeps the original filename as the image alt.
const stem = normalizedFilename.replace(/\.[^.]+$/, "");
const sameStem = pool.filter((resource) => resource.filename?.replace(/\.[^.]+$/, "") === stem);
return sameStem.length === 1 ? sameStem[0] : null;
}
if (pool.length === 1) return pool[0];
return null;