Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Properly maintain aspect ratio of inline images #7503

Merged
merged 3 commits into from
Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions res/css/views/rooms/_EventTile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,15 @@ $left-gutter: 64px;
pre {
border: 1px solid transparent;
}

// selector wrongly applies to pill avatars but those have explicit width/height passed at a higher specificity
&.markdown-body img {
// the image will have max-width and max-height applied during sanitization
width: 100%;
height: 100%;
object-fit: contain;
object-position: left top;
}
}

.mx_EventTile_clamp {
Expand Down
24 changes: 17 additions & 7 deletions src/HtmlUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,12 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
return { tagName, attribs: {} };
}

const width = Number(attribs.width) || 800;
const height = Number(attribs.height) || 600;
const width = Math.min(Number(attribs.width) || 800, 800);
const height = Math.min(Number(attribs.height) || 600, 600);
// specify width/height as max values instead of absolute ones to allow object-fit to do its thing
// we only allow our own styles for this tag so overwrite the attribute
attribs.style = `max-width: ${width}px; max-height: ${height}px;`;

attribs.src = mediaFromMxc(src).getThumbnailOfSourceHttp(width, height);
return { tagName, attribs };
},
Expand All @@ -223,9 +227,12 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
return { tagName, attribs };
},
'*': function(tagName: string, attribs: sanitizeHtml.Attributes) {
// Delete any style previously assigned, style is an allowedTag for font and span
// because attributes are stripped after transforming
delete attribs.style;
// Delete any style previously assigned, style is an allowedTag for font, span & img,
// because attributes are stripped after transforming.
// For img this is trusted as it is generated wholly within the img transformation method.
if (tagName !== "img") {
delete attribs.style;
}

// Sanitise and transform data-mx-color and data-mx-bg-color to their CSS
// equivalents
Expand All @@ -249,7 +256,7 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
});

if (style) {
attribs.style = style;
attribs.style = style + (attribs.style || "");
}

return { tagName, attribs };
Expand All @@ -266,12 +273,15 @@ const sanitizeHtmlParams: IExtendedSanitizeOptions = {
'details', 'summary',
],
allowedAttributes: {
// attribute sanitization happens after transformations, so we have to accept `style` for font, span & img
// but strip during the transformation.
// custom ones first:
font: ['color', 'data-mx-bg-color', 'data-mx-color', 'style'], // custom to matrix
span: ['data-mx-maths', 'data-mx-bg-color', 'data-mx-color', 'data-mx-spoiler', 'style'], // custom to matrix
div: ['data-mx-maths'],
a: ['href', 'name', 'target', 'rel'], // remote target: custom to matrix
img: ['src', 'width', 'height', 'alt', 'title'],
// img tags also accept width/height, we just map those to max-width & max-height during transformation
img: ['src', 'alt', 'title', 'style'],
ol: ['start'],
code: ['class'], // We don't actually allow all classes, we filter them in transformTags
},
Expand Down