fix(rusty-image): preserve animated GIFs through markdown image processing
RustyCMS /api/transform decodes only the first frame of animated formats, which silently kills GIF animation when markdown HTML images get rewritten to /api/transform URLs. Skip the transform for `.gif` URLs so the original asset URL flows through and animation survives. Also picks up an arrow-right entry in the iconify mdi subset generated during a UI build.
This commit is contained in:
@@ -66,6 +66,9 @@
|
|||||||
"printer-outline": {
|
"printer-outline": {
|
||||||
"body": "<path fill=\"currentColor\" d=\"M19 8c1.66 0 3 1.34 3 3v6h-4v4H6v-4H2v-6c0-1.66 1.34-3 3-3h1V3h12v5zM8 5v3h8V5zm8 14v-4H8v4zm2-4h2v-4c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4h2v-2h12zm1-3.5c0 .55-.45 1-1 1s-1-.45-1-1s.45-1 1-1s1 .45 1 1\"/>"
|
"body": "<path fill=\"currentColor\" d=\"M19 8c1.66 0 3 1.34 3 3v6h-4v4H6v-4H2v-6c0-1.66 1.34-3 3-3h1V3h12v5zM8 5v3h8V5zm8 14v-4H8v4zm2-4h2v-4c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4h2v-2h12zm1-3.5c0 .55-.45 1-1 1s-1-.45-1-1s.45-1 1-1s1 .45 1 1\"/>"
|
||||||
},
|
},
|
||||||
|
"arrow-right": {
|
||||||
|
"body": "<path fill=\"currentColor\" d=\"M4 11v2h12l-5.5 5.5l1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5L16 11z\"/>"
|
||||||
|
},
|
||||||
"download-outline": {
|
"download-outline": {
|
||||||
"body": "<path fill=\"currentColor\" d=\"M13 5v6h1.17L12 13.17L9.83 11H11V5zm2-2H9v6H5l7 7l7-7h-4zm4 15H5v2h14z\"/>"
|
"body": "<path fill=\"currentColor\" d=\"M13 5v6h1.17L12 13.17L9.83 11H11V5zm2-2H9v6H5l7 7l7-7h-4zm4 15H5v2h14z\"/>"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -153,6 +153,10 @@ const MARKDOWN_IMAGE_PARAMS: RustyImageTransformParams = {
|
|||||||
|
|
||||||
const IMG_SRC_REGEX = /<img\s+([^>]*?)src\s*=\s*["']([^"']+)["']([^>]*)>/gi;
|
const IMG_SRC_REGEX = /<img\s+([^>]*?)src\s*=\s*["']([^"']+)["']([^>]*)>/gi;
|
||||||
|
|
||||||
|
// Animated formats — skip transform, keep original URL so animation survives.
|
||||||
|
// RustyCMS /api/transform decodes only the first frame.
|
||||||
|
const ANIMATED_EXT_REGEX = /\.gif(\?|$)/i;
|
||||||
|
|
||||||
export async function processMarkdownHtmlImages(html: string, _baseUrl?: string, transformParams: RustyImageTransformParams = MARKDOWN_IMAGE_PARAMS): Promise<string> {
|
export async function processMarkdownHtmlImages(html: string, _baseUrl?: string, transformParams: RustyImageTransformParams = MARKDOWN_IMAGE_PARAMS): Promise<string> {
|
||||||
const matches = [...html.matchAll(IMG_SRC_REGEX)];
|
const matches = [...html.matchAll(IMG_SRC_REGEX)];
|
||||||
const replacements: { index: number; length: number; newBlock: string }[] = [];
|
const replacements: { index: number; length: number; newBlock: string }[] = [];
|
||||||
@@ -160,7 +164,8 @@ export async function processMarkdownHtmlImages(html: string, _baseUrl?: string,
|
|||||||
const rawSrc = m[2];
|
const rawSrc = m[2];
|
||||||
const url = rawSrc.startsWith('//') ? `https:${rawSrc}` : rawSrc;
|
const url = rawSrc.startsWith('//') ? `https:${rawSrc}` : rawSrc;
|
||||||
if (!url.startsWith('http')) continue;
|
if (!url.startsWith('http')) continue;
|
||||||
const transformedPath = getCmsImageUrl(url, transformParams);
|
const isAnimated = ANIMATED_EXT_REGEX.test(url);
|
||||||
|
const transformedPath = isAnimated ? url : getCmsImageUrl(url, transformParams);
|
||||||
const href = transformedPath;
|
const href = transformedPath;
|
||||||
const newImg = m[0].replace(rawSrc, transformedPath);
|
const newImg = m[0].replace(rawSrc, transformedPath);
|
||||||
const newBlock = `<a href="${href}" target="_blank" rel="noopener noreferrer" class="markdown-image-link">${newImg}</a>`;
|
const newBlock = `<a href="${href}" target="_blank" rel="noopener noreferrer" class="markdown-image-link">${newImg}</a>`;
|
||||||
|
|||||||
Reference in New Issue
Block a user