From fc324319d88a54180c9782e6fa4541c7c6681b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jim=20Liu=20=E5=AE=9D=E7=8E=89?= Date: Fri, 13 Mar 2026 10:44:23 -0500 Subject: [PATCH] fix: preserve weibo image metadata in shared md package --- packages/baoyu-md/src/images.ts | 41 ++++++++++++++++--- .../scripts/vendor/baoyu-md/src/images.ts | 41 ++++++++++++++++--- .../scripts/vendor/baoyu-md/src/images.ts | 41 ++++++++++++++++--- .../baoyu-post-to-weibo/scripts/md-to-html.ts | 1 + .../scripts/vendor/baoyu-md/src/images.ts | 41 ++++++++++++++++--- 5 files changed, 141 insertions(+), 24 deletions(-) diff --git a/packages/baoyu-md/src/images.ts b/packages/baoyu-md/src/images.ts index f0a3f00..b28f041 100644 --- a/packages/baoyu-md/src/images.ts +++ b/packages/baoyu-md/src/images.ts @@ -7,6 +7,7 @@ import path from "node:path"; export interface ImagePlaceholder { originalPath: string; placeholder: string; + alt?: string; } export interface ResolvedImageInfo extends ImagePlaceholder { @@ -23,9 +24,10 @@ export function replaceMarkdownImagesWithPlaceholders( const images: ImagePlaceholder[] = []; let imageCounter = 0; - const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, _alt, src) => { + const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, alt, src) => { const placeholder = `${placeholderPrefix}${++imageCounter}`; images.push({ + alt, originalPath: src, placeholder, }); @@ -101,11 +103,10 @@ export async function resolveImagePath( return localPath; } - if (path.isAbsolute(imagePath)) { - return imagePath; - } - - return path.resolve(baseDir, imagePath); + const resolved = path.isAbsolute(imagePath) + ? imagePath + : path.resolve(baseDir, imagePath); + return resolveLocalWithFallback(resolved, logLabel); } export async function resolveContentImages( @@ -125,3 +126,31 @@ export async function resolveContentImages( return resolved; } + +function resolveLocalWithFallback(resolved: string, logLabel: string): string { + if (fs.existsSync(resolved)) { + return resolved; + } + + const ext = path.extname(resolved); + const base = ext ? resolved.slice(0, -ext.length) : resolved; + const alternatives = [ + `${base}.webp`, + `${base}.jpg`, + `${base}.jpeg`, + `${base}.png`, + `${base}.gif`, + `${base}_original.png`, + `${base}_original.jpg`, + ].filter((candidate) => candidate !== resolved); + + for (const alternative of alternatives) { + if (!fs.existsSync(alternative)) continue; + console.error( + `[${logLabel}] Image fallback: ${path.basename(resolved)} -> ${path.basename(alternative)}`, + ); + return alternative; + } + + return resolved; +} diff --git a/skills/baoyu-markdown-to-html/scripts/vendor/baoyu-md/src/images.ts b/skills/baoyu-markdown-to-html/scripts/vendor/baoyu-md/src/images.ts index f0a3f00..b28f041 100644 --- a/skills/baoyu-markdown-to-html/scripts/vendor/baoyu-md/src/images.ts +++ b/skills/baoyu-markdown-to-html/scripts/vendor/baoyu-md/src/images.ts @@ -7,6 +7,7 @@ import path from "node:path"; export interface ImagePlaceholder { originalPath: string; placeholder: string; + alt?: string; } export interface ResolvedImageInfo extends ImagePlaceholder { @@ -23,9 +24,10 @@ export function replaceMarkdownImagesWithPlaceholders( const images: ImagePlaceholder[] = []; let imageCounter = 0; - const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, _alt, src) => { + const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, alt, src) => { const placeholder = `${placeholderPrefix}${++imageCounter}`; images.push({ + alt, originalPath: src, placeholder, }); @@ -101,11 +103,10 @@ export async function resolveImagePath( return localPath; } - if (path.isAbsolute(imagePath)) { - return imagePath; - } - - return path.resolve(baseDir, imagePath); + const resolved = path.isAbsolute(imagePath) + ? imagePath + : path.resolve(baseDir, imagePath); + return resolveLocalWithFallback(resolved, logLabel); } export async function resolveContentImages( @@ -125,3 +126,31 @@ export async function resolveContentImages( return resolved; } + +function resolveLocalWithFallback(resolved: string, logLabel: string): string { + if (fs.existsSync(resolved)) { + return resolved; + } + + const ext = path.extname(resolved); + const base = ext ? resolved.slice(0, -ext.length) : resolved; + const alternatives = [ + `${base}.webp`, + `${base}.jpg`, + `${base}.jpeg`, + `${base}.png`, + `${base}.gif`, + `${base}_original.png`, + `${base}_original.jpg`, + ].filter((candidate) => candidate !== resolved); + + for (const alternative of alternatives) { + if (!fs.existsSync(alternative)) continue; + console.error( + `[${logLabel}] Image fallback: ${path.basename(resolved)} -> ${path.basename(alternative)}`, + ); + return alternative; + } + + return resolved; +} diff --git a/skills/baoyu-post-to-wechat/scripts/vendor/baoyu-md/src/images.ts b/skills/baoyu-post-to-wechat/scripts/vendor/baoyu-md/src/images.ts index f0a3f00..b28f041 100644 --- a/skills/baoyu-post-to-wechat/scripts/vendor/baoyu-md/src/images.ts +++ b/skills/baoyu-post-to-wechat/scripts/vendor/baoyu-md/src/images.ts @@ -7,6 +7,7 @@ import path from "node:path"; export interface ImagePlaceholder { originalPath: string; placeholder: string; + alt?: string; } export interface ResolvedImageInfo extends ImagePlaceholder { @@ -23,9 +24,10 @@ export function replaceMarkdownImagesWithPlaceholders( const images: ImagePlaceholder[] = []; let imageCounter = 0; - const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, _alt, src) => { + const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, alt, src) => { const placeholder = `${placeholderPrefix}${++imageCounter}`; images.push({ + alt, originalPath: src, placeholder, }); @@ -101,11 +103,10 @@ export async function resolveImagePath( return localPath; } - if (path.isAbsolute(imagePath)) { - return imagePath; - } - - return path.resolve(baseDir, imagePath); + const resolved = path.isAbsolute(imagePath) + ? imagePath + : path.resolve(baseDir, imagePath); + return resolveLocalWithFallback(resolved, logLabel); } export async function resolveContentImages( @@ -125,3 +126,31 @@ export async function resolveContentImages( return resolved; } + +function resolveLocalWithFallback(resolved: string, logLabel: string): string { + if (fs.existsSync(resolved)) { + return resolved; + } + + const ext = path.extname(resolved); + const base = ext ? resolved.slice(0, -ext.length) : resolved; + const alternatives = [ + `${base}.webp`, + `${base}.jpg`, + `${base}.jpeg`, + `${base}.png`, + `${base}.gif`, + `${base}_original.png`, + `${base}_original.jpg`, + ].filter((candidate) => candidate !== resolved); + + for (const alternative of alternatives) { + if (!fs.existsSync(alternative)) continue; + console.error( + `[${logLabel}] Image fallback: ${path.basename(resolved)} -> ${path.basename(alternative)}`, + ); + return alternative; + } + + return resolved; +} diff --git a/skills/baoyu-post-to-weibo/scripts/md-to-html.ts b/skills/baoyu-post-to-weibo/scripts/md-to-html.ts index 8c26033..1296c6c 100644 --- a/skills/baoyu-post-to-weibo/scripts/md-to-html.ts +++ b/skills/baoyu-post-to-weibo/scripts/md-to-html.ts @@ -21,6 +21,7 @@ interface ImageInfo { placeholder: string; localPath: string; originalPath: string; + alt?: string; } interface ParsedMarkdown { diff --git a/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-md/src/images.ts b/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-md/src/images.ts index f0a3f00..b28f041 100644 --- a/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-md/src/images.ts +++ b/skills/baoyu-post-to-weibo/scripts/vendor/baoyu-md/src/images.ts @@ -7,6 +7,7 @@ import path from "node:path"; export interface ImagePlaceholder { originalPath: string; placeholder: string; + alt?: string; } export interface ResolvedImageInfo extends ImagePlaceholder { @@ -23,9 +24,10 @@ export function replaceMarkdownImagesWithPlaceholders( const images: ImagePlaceholder[] = []; let imageCounter = 0; - const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, _alt, src) => { + const rewritten = markdown.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_match, alt, src) => { const placeholder = `${placeholderPrefix}${++imageCounter}`; images.push({ + alt, originalPath: src, placeholder, }); @@ -101,11 +103,10 @@ export async function resolveImagePath( return localPath; } - if (path.isAbsolute(imagePath)) { - return imagePath; - } - - return path.resolve(baseDir, imagePath); + const resolved = path.isAbsolute(imagePath) + ? imagePath + : path.resolve(baseDir, imagePath); + return resolveLocalWithFallback(resolved, logLabel); } export async function resolveContentImages( @@ -125,3 +126,31 @@ export async function resolveContentImages( return resolved; } + +function resolveLocalWithFallback(resolved: string, logLabel: string): string { + if (fs.existsSync(resolved)) { + return resolved; + } + + const ext = path.extname(resolved); + const base = ext ? resolved.slice(0, -ext.length) : resolved; + const alternatives = [ + `${base}.webp`, + `${base}.jpg`, + `${base}.jpeg`, + `${base}.png`, + `${base}.gif`, + `${base}_original.png`, + `${base}_original.jpg`, + ].filter((candidate) => candidate !== resolved); + + for (const alternative of alternatives) { + if (!fs.existsSync(alternative)) continue; + console.error( + `[${logLabel}] Image fallback: ${path.basename(resolved)} -> ${path.basename(alternative)}`, + ); + return alternative; + } + + return resolved; +}