Properly maintain aspect ratio of inline images (#7503)
This commit is contained in:
parent
5cfb046816
commit
3c1ce77d48
3 changed files with 28 additions and 8 deletions
|
@ -450,6 +450,15 @@ $left-gutter: 64px;
|
||||||
pre {
|
pre {
|
||||||
border: 1px solid transparent;
|
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 {
|
.mx_EventTile_clamp {
|
||||||
|
|
|
@ -207,8 +207,12 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
|
||||||
return { tagName, attribs: {} };
|
return { tagName, attribs: {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
const width = Number(attribs.width) || 800;
|
const width = Math.min(Number(attribs.width) || 800, 800);
|
||||||
const height = Number(attribs.height) || 600;
|
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);
|
attribs.src = mediaFromMxc(src).getThumbnailOfSourceHttp(width, height);
|
||||||
return { tagName, attribs };
|
return { tagName, attribs };
|
||||||
},
|
},
|
||||||
|
@ -223,9 +227,12 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
|
||||||
return { tagName, attribs };
|
return { tagName, attribs };
|
||||||
},
|
},
|
||||||
'*': function(tagName: string, attribs: sanitizeHtml.Attributes) {
|
'*': function(tagName: string, attribs: sanitizeHtml.Attributes) {
|
||||||
// Delete any style previously assigned, style is an allowedTag for font and span
|
// Delete any style previously assigned, style is an allowedTag for font, span & img,
|
||||||
// because attributes are stripped after transforming
|
// because attributes are stripped after transforming.
|
||||||
delete attribs.style;
|
// 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
|
// Sanitise and transform data-mx-color and data-mx-bg-color to their CSS
|
||||||
// equivalents
|
// equivalents
|
||||||
|
@ -249,7 +256,7 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
|
||||||
});
|
});
|
||||||
|
|
||||||
if (style) {
|
if (style) {
|
||||||
attribs.style = style;
|
attribs.style = style + (attribs.style || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return { tagName, attribs };
|
return { tagName, attribs };
|
||||||
|
@ -266,12 +273,15 @@ const sanitizeHtmlParams: IExtendedSanitizeOptions = {
|
||||||
'details', 'summary',
|
'details', 'summary',
|
||||||
],
|
],
|
||||||
allowedAttributes: {
|
allowedAttributes: {
|
||||||
|
// attribute sanitization happens after transformations, so we have to accept `style` for font, span & img
|
||||||
|
// but strip during the transformation.
|
||||||
// custom ones first:
|
// custom ones first:
|
||||||
font: ['color', 'data-mx-bg-color', 'data-mx-color', 'style'], // custom to matrix
|
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
|
span: ['data-mx-maths', 'data-mx-bg-color', 'data-mx-color', 'data-mx-spoiler', 'style'], // custom to matrix
|
||||||
div: ['data-mx-maths'],
|
div: ['data-mx-maths'],
|
||||||
a: ['href', 'name', 'target', 'rel'], // remote target: custom to matrix
|
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'],
|
ol: ['start'],
|
||||||
code: ['class'], // We don't actually allow all classes, we filter them in transformTags
|
code: ['class'], // We don't actually allow all classes, we filter them in transformTags
|
||||||
},
|
},
|
||||||
|
|
|
@ -264,7 +264,8 @@ describe('GroupView', function() {
|
||||||
|
|
||||||
const imgSrc = "https://my.home.server/_matrix/media/r0/thumbnail/someimageurl" +
|
const imgSrc = "https://my.home.server/_matrix/media/r0/thumbnail/someimageurl" +
|
||||||
"?width=800&height=600&method=scale";
|
"?width=800&height=600&method=scale";
|
||||||
expect(longDescElement.innerHTML).toContain('<img src="' + imgSrc + '">');
|
expect(longDescElement.innerHTML).toContain('<img src="' + imgSrc + '" ' +
|
||||||
|
'style="max-width:800px;max-height:600px">');
|
||||||
});
|
});
|
||||||
|
|
||||||
httpBackend
|
httpBackend
|
||||||
|
|
Loading…
Reference in a new issue