mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
Web UI: allow img tags in DOMPurify so markdown images render in webchat (#15480)
Thanks @lailoo.
This commit is contained in:
@@ -82,6 +82,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Config: keep legacy audio transcription migration strict by rejecting non-string/unsafe command tokens while still migrating valid custom script executables. (#5042) Thanks @shayan919293.
|
||||
- Status/Sessions: stop clamping derived `totalTokens` to context-window size, keep prompt-token snapshots wired through session accounting, and surface context usage as unknown when fresh snapshot data is missing to avoid false 100% reports. (#15114) Thanks @echoVic.
|
||||
- Providers/MiniMax: switch implicit MiniMax API-key provider from `openai-completions` to `anthropic-messages` with the correct Anthropic-compatible base URL, fixing `invalid role: developer (2013)` errors on MiniMax M2.5. (#15275) Thanks @lailoo.
|
||||
- Web UI: add `img` to DOMPurify allowed tags and `src`/`alt` to allowed attributes so markdown images render in webchat instead of being stripped. (#15437) Thanks @lailoo.
|
||||
- Ollama/Agents: use resolved model/provider base URLs for native `/api/chat` streaming (including aliased providers), normalize `/v1` endpoints, and forward abort + `maxTokens` stream options for reliable cancellation and token caps. (#11853) Thanks @BrokenFinger98.
|
||||
|
||||
## 2026.2.12
|
||||
|
||||
@@ -28,4 +28,24 @@ describe("toSanitizedMarkdownHtml", () => {
|
||||
expect(html).toContain("<code");
|
||||
expect(html).toContain("console.log(1)");
|
||||
});
|
||||
|
||||
it("preserves img tags with src and alt from markdown images (#15437)", () => {
|
||||
const html = toSanitizedMarkdownHtml("");
|
||||
expect(html).toContain("<img");
|
||||
expect(html).toContain('src="https://example.com/image.png"');
|
||||
expect(html).toContain('alt="Alt text"');
|
||||
});
|
||||
|
||||
it("preserves base64 data URI images (#15437)", () => {
|
||||
const html = toSanitizedMarkdownHtml("");
|
||||
expect(html).toContain("<img");
|
||||
expect(html).toContain("data:image/png;base64,");
|
||||
});
|
||||
|
||||
it("strips javascript image urls", () => {
|
||||
const html = toSanitizedMarkdownHtml(")");
|
||||
expect(html).toContain("<img");
|
||||
expect(html).not.toContain("javascript:");
|
||||
expect(html).not.toContain("src=");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,9 +33,15 @@ const allowedTags = [
|
||||
"thead",
|
||||
"tr",
|
||||
"ul",
|
||||
"img",
|
||||
];
|
||||
|
||||
const allowedAttrs = ["class", "href", "rel", "target", "title", "start"];
|
||||
const allowedAttrs = ["class", "href", "rel", "target", "title", "start", "src", "alt"];
|
||||
const sanitizeOptions = {
|
||||
ALLOWED_TAGS: allowedTags,
|
||||
ALLOWED_ATTR: allowedAttrs,
|
||||
ADD_DATA_URI_TAGS: ["img"],
|
||||
};
|
||||
|
||||
let hooksInstalled = false;
|
||||
const MARKDOWN_CHAR_LIMIT = 140_000;
|
||||
@@ -103,10 +109,7 @@ export function toSanitizedMarkdownHtml(markdown: string): string {
|
||||
if (truncated.text.length > MARKDOWN_PARSE_LIMIT) {
|
||||
const escaped = escapeHtml(`${truncated.text}${suffix}`);
|
||||
const html = `<pre class="code-block">${escaped}</pre>`;
|
||||
const sanitized = DOMPurify.sanitize(html, {
|
||||
ALLOWED_TAGS: allowedTags,
|
||||
ALLOWED_ATTR: allowedAttrs,
|
||||
});
|
||||
const sanitized = DOMPurify.sanitize(html, sanitizeOptions);
|
||||
if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {
|
||||
setCachedMarkdown(input, sanitized);
|
||||
}
|
||||
@@ -115,10 +118,7 @@ export function toSanitizedMarkdownHtml(markdown: string): string {
|
||||
const rendered = marked.parse(`${truncated.text}${suffix}`, {
|
||||
renderer: htmlEscapeRenderer,
|
||||
}) as string;
|
||||
const sanitized = DOMPurify.sanitize(rendered, {
|
||||
ALLOWED_TAGS: allowedTags,
|
||||
ALLOWED_ATTR: allowedAttrs,
|
||||
});
|
||||
const sanitized = DOMPurify.sanitize(rendered, sanitizeOptions);
|
||||
if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {
|
||||
setCachedMarkdown(input, sanitized);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user