Do not try render invalid image paths in message on web app

Avoids rendering flicker from attempt to render invalid image paths
referenced in message by khoj on web app.

The rendering flicker made it very annoying to interact with
conversations containing such messages on the web app.

The current change does lightweight validation of image url before
attempting to render it. If invalid image url detected, the image is
replaced with just its alt text.
This commit is contained in:
Debanjum
2025-11-29 15:09:21 -08:00
parent 51b893d51d
commit dd4381c25c
2 changed files with 72 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ import {
} from "@/app/components/referencePanel/referencePanel";
import { renderCodeGenImageInline } from "@/app/common/chatFunctions";
import { fileLinksPlugin } from "@/app/components/chatMessage/fileLinksPlugin";
import { imageValidationPlugin } from "@/app/components/chatMessage/imageValidationPlugin";
import FileContentSnippet from "@/app/components/chatMessage/FileContentSnippet";
import { useFileContent } from "@/app/components/chatMessage/useFileContent";
@@ -75,6 +76,7 @@ md.use(mditHljs, {
});
md.use(fileLinksPlugin);
md.use(imageValidationPlugin);
export interface Context {
compiled: string;

View File

@@ -0,0 +1,70 @@
import MarkdownIt from "markdown-it";
/**
* Checks if a URL is a valid, loadable image URL.
* Returns true for URLs that browsers can actually fetch:
* - data: URLs (base64 encoded)
* - blob: URLs (object URLs)
* - http:// and https:// URLs
*/
function isValidImageUrl(url: string): boolean {
if (!url || typeof url !== "string") {
return false;
}
const trimmedUrl = url.trim();
// Allow data URLs (base64 encoded images)
if (trimmedUrl.startsWith("data:")) {
return true;
}
// Allow blob URLs
if (trimmedUrl.startsWith("blob:")) {
return true;
}
// Allow HTTP/HTTPS URLs
if (trimmedUrl.startsWith("http://") || trimmedUrl.startsWith("https://")) {
return true;
}
// Reject everything else (file://, relative paths, absolute paths, etc.)
return false;
}
/**
* Image validation plugin for markdown-it
* Filters out images with invalid/non-loadable URLs at render time.
* This prevents broken images from ever being added to the DOM.
*/
export function imageValidationPlugin(md: MarkdownIt) {
// Store the original image renderer
const defaultImageRenderer =
md.renderer.rules.image ||
function (tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
// Override the image renderer
md.renderer.rules.image = function (tokens, idx, options, env, self) {
const token = tokens[idx];
const srcIndex = token.attrIndex("src");
if (srcIndex >= 0 && token.attrs) {
const src = token.attrs[srcIndex][1];
// If the URL is not valid, don't render the image at all
if (!isValidImageUrl(src)) {
// Return alt text as fallback, or empty string
const altText = token.content || "";
if (altText) {
return `<em style="color: #888; font-size: 0.9em;">[Image: ${md.utils.escapeHtml(altText)}]</em>`;
}
return "";
}
}
return defaultImageRenderer(tokens, idx, options, env, self);
};
}