diff --git a/web/src/rendered_markdown.ts b/web/src/rendered_markdown.ts index e45d73ab8c..a96e0c1e8a 100644 --- a/web/src/rendered_markdown.ts +++ b/web/src/rendered_markdown.ts @@ -16,6 +16,7 @@ import * as realm_playground from "./realm_playground"; import * as rows from "./rows"; import * as rtl from "./rtl"; import * as sub_store from "./sub_store"; +import * as thumbnail from "./thumbnail"; import * as timerender from "./timerender"; import * as user_groups from "./user_groups"; import {user_settings} from "./user_settings"; @@ -337,4 +338,18 @@ export const update_elements = ($content: JQuery): void => { .contents() .unwrap(); } + + $content + .find('div.message_inline_image > a > img[src^="/user_uploads/thumbnail/"]') + .each(function (): void { + const $inline_img_thumbnail = $(this); + let thumbnail_name = thumbnail.preferred_format.name; + if ($inline_img_thumbnail.attr("data-animated") === "true") { + thumbnail_name = thumbnail.animated_format.name; + } + $inline_img_thumbnail.attr( + "src", + $inline_img_thumbnail.attr("src")!.replace(/\/[^/]+$/, "/" + thumbnail_name), + ); + }); }; diff --git a/web/tests/rendered_markdown.test.js b/web/tests/rendered_markdown.test.js index 46203330c0..7e04a35f1c 100644 --- a/web/tests/rendered_markdown.test.js +++ b/web/tests/rendered_markdown.test.js @@ -23,6 +23,7 @@ mock_cjs("clipboard", Clipboard); const realm_playground = mock_esm("../src/realm_playground"); const copied_tooltip = mock_esm("../src/copied_tooltip"); +const thumbnail = mock_esm("../src/thumbnail"); user_settings.emojiset = "apple"; const rm = zrequire("rendered_markdown"); @@ -138,6 +139,15 @@ const get_content_element = () => { $content.set_find_results("div.spoiler-header", $array([])); $content.set_find_results("div.codehilite", $array([])); $content.set_find_results(".message_inline_video video", $array([])); + $content.set_find_results( + 'div.message_inline_image > a > img[src^="/user_uploads/thumbnail/"]', + $array([]), + ); + $content.set_find_results( + "div.message_inline_image img, div.message_inline_image video", + $array([]), + ); + set_message_for_message_content($content, undefined); // Fend off dumb security bugs by forcing devs to be @@ -191,6 +201,67 @@ run_test("message_inline_video", () => { window.GestureEvent = false; }); +run_test("message_inline_animated_image", ({override}) => { + const $content = get_content_element(); + const $elem = $.create("img"); + + $elem.attr("data-animated", "false"); + $elem.attr("src", "/path/to/image.png"); + + $content.set_find_results( + 'div.message_inline_image > a > img[src^="/user_uploads/thumbnail/"]', + $array([$elem]), + ); + + const thumbnail_formats = [ + { + name: "840x560-anim.webp", + max_width: 840, + max_height: 560, + format: "webp", + animated: true, + }, + { + name: "840x560.webp", + max_width: 840, + max_height: 560, + format: "webp", + animated: false, + }, + { + name: "300x200-anim.webp", + max_width: 300, + max_height: 200, + format: "webp", + animated: true, + }, + { + name: "300x200.webp", + max_width: 300, + max_height: 200, + format: "webp", + animated: false, + }, + { + name: "300x200.jpg", + max_width: 300, + max_height: 200, + format: "jpg", + animated: false, + }, + ]; + // TODO: Initialize the real thumbnail.ts rather than mocking it. + override(thumbnail, "preferred_format", thumbnail_formats[1]); + override(thumbnail, "animated_format", thumbnail_formats[0]); + + rm.update_elements($content); + assert.equal($elem.attr("src"), "/path/to/840x560.webp"); + + $elem.attr("data-animated", "true"); + rm.update_elements($content); + assert.equal($elem.attr("src"), "/path/to/840x560-anim.webp"); +}); + run_test("user-mention", () => { // Setup const $content = get_content_element();