Skip to content

Commit 48cdefe

Browse files
fix(web): size markdown media whose width and height carry a px unit (#32108)
1 parent 134ab31 commit 48cdefe

2 files changed

Lines changed: 30 additions & 2 deletions

File tree

‎apps/web/src/components/ChatMarkdown.browser.test.tsx‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,30 @@ it("loads the <picture> source for the current theme through the image route", a
249249
.toHaveAttribute("src", `${pixel}#/work/dark.png`);
250250
});
251251

252+
it("sizes a raw HTML image by width and height written with px units", async () => {
253+
setup();
254+
const largeImage = `data:image/svg+xml,${encodeURIComponent(
255+
'<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"/>',
256+
)}`;
257+
await using screen = await render(
258+
<HostImageUrlContext value={() => largeImage}>
259+
<ChatMarkdown
260+
cwd={undefined}
261+
parseRawHtml
262+
text={
263+
'### PR Review in progress <img src="/work/spinner.gif" alt="spinner" width="14px" height="7px" />'
264+
}
265+
/>
266+
</HostImageUrlContext>,
267+
);
268+
const image = screen.getByAltText("spinner");
269+
await expect.element(image).toHaveAttribute("src", largeImage);
270+
const element = image.element() as HTMLImageElement;
271+
await element.decode();
272+
const { width, height } = element.getBoundingClientRect();
273+
expect({ width, height }).toEqual({ width: 14, height: 7 });
274+
});
275+
252276
it("reuses the parse of a streaming reply's finished blocks when it remounts", async () => {
253277
setup();
254278
const message = (

‎apps/web/src/components/chat/ChatMarkdownMedia.tsx‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ function markdownDestination(src: string): string {
5252
return `<${escaped}>`;
5353
}
5454

55+
function parseImageDimension(value: string | number | undefined): number {
56+
return Number(typeof value === "string" ? value.trim().replace(/px$/i, "") : value);
57+
}
58+
5559
/**
5660
* `maxHeightRem` folds a height cap into the width bound: `max-height` alone
5761
* would not feed back through `aspect-ratio` once `width` is definite, so a
@@ -62,8 +66,8 @@ export function authoredImageSizeStyle(
6266
height: string | number | undefined,
6367
maxHeightRem = 30,
6468
): CSSProperties | undefined {
65-
const parsedWidth = Number(width);
66-
const parsedHeight = Number(height);
69+
const parsedWidth = parseImageDimension(width);
70+
const parsedHeight = parseImageDimension(height);
6771
const hasWidth = Number.isFinite(parsedWidth) && parsedWidth > 0;
6872
const hasHeight = Number.isFinite(parsedHeight) && parsedHeight > 0;
6973
if (hasWidth && hasHeight) {

0 commit comments

Comments
 (0)