@ -1,6 +1,9 @@
'use strict' ;
/ *
Copyright 2015 , 2016 OpenMarket Ltd
With modifications , by f0x
With modifications , by Sven Slootweg < admin @ cryto . net >
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
@ -14,7 +17,6 @@ limitations under the License.
const Promise = require ( 'bluebird' ) ;
const sanitize = require ( 'sanitize-html' ) ;
//require("blueimp-canvas-to-blob");
const COLOR _REGEX = /^#[0-9a-fA-F]{6}$/ ;
/ * *
@ -36,29 +38,86 @@ const COLOR_REGEX = /^#[0-9a-fA-F]{6}$/;
* and a thumbnail key .
* /
function canvasToBlob ( canvas , mimeType ) {
return new Promise ( ( resolve , _reject ) => {
canvas . toBlob ( function ( blob ) {
resolve ( blob ) ;
} , mimeType ) ;
} ) ;
}
function awaitImageLoad ( image ) {
return new Promise ( ( resolve , reject ) => {
image . onload = function ( ) {
resolve ( ) ;
} ;
image . onerror = function ( e ) {
reject ( e ) ;
} ;
} ) ;
}
function awaitFileReader ( dataUrl ) {
return new Promise ( ( resolve , reject ) => {
const reader = new FileReader ( ) ;
reader . onload = function ( event ) {
resolve ( event . target . result ) ;
} ;
reader . onerror = function ( error ) {
reject ( error ) ;
} ;
reader . readAsDataURL ( dataUrl ) ;
} ) ;
}
function awaitVideoLoad ( video ) {
return new Promise ( ( resolve , reject ) => {
video . onloadeddata = function ( ) {
resolve ( {
width : video . videoWidth ,
height : video . videoHeight
} ) ;
} ;
video . onerror = function ( error ) {
reject ( error ) ;
} ;
} ) ;
}
module . exports = {
createThumbnail : function ( element , inputWidth , inputHeight , mimeType ) {
return new Promise ( function ( resolve , reject ) {
return Promise . try ( ( ) => {
const MAX _WIDTH = 800 ;
const MAX _HEIGHT = 600 ;
let targetWidth = inputWidth ;
let targetHeight = inputHeight ;
if ( targetHeight > MAX _HEIGHT ) {
targetWidth = Math . floor ( targetWidth * ( MAX _HEIGHT / targetHeight ) ) ;
targetHeight = MAX _HEIGHT ;
}
if ( targetWidth > MAX _WIDTH ) {
targetHeight = Math . floor ( targetHeight * ( MAX _WIDTH / targetWidth ) ) ;
targetWidth = MAX _WIDTH ;
}
const canvas = Object . assign ( document . createElement ( "canvas" ) , {
width : targetWidth ,
height : targetHeight
} ) ;
const canvas = document . createElement ( "canvas" ) ;
canvas . width = targetWidth ;
canvas . height = targetHeight ;
canvas . getContext ( "2d" ) . drawImage ( element , 0 , 0 , targetWidth , targetHeight ) ;
canvas . toBlob ( function ( thumbnail ) {
resolve ( {
return Promise . try ( ( ) => {
return canvasToBlob ( canvas , mimeType ) ;
} ) . then ( ( thumbnail ) => {
return {
info : {
thumbnail _info : {
w : targetWidth ,
@ -70,8 +129,8 @@ module.exports = {
h : inputHeight ,
} ,
thumbnail : thumbnail ,
} ) ;
} , mimeType );
} ;
} );
} ) ;
} ,
@ -82,20 +141,16 @@ module.exports = {
* @ return { Promise } A promise that resolves with the html image element .
* /
loadImageElement : function ( imageFile ) {
return new Promise ( function ( resolve , reject ) {
// Load the file into an html element
return Promise . try ( ( ) => {
const img = document . createElement ( "img" ) ;
const objectUrl = URL . createObjectURL ( imageFile ) ;
img . src = objectUrl ;
// Once ready, create a thumbnail
img . onload = function ( ) {
return Promise . try ( ( ) => {
return awaitImageLoad ( img ) ;
} ) . then ( ( ) => {
URL . revokeObjectURL ( objectUrl ) ;
resolve ( img ) ;
} ;
img . onerror = function ( e ) {
reject ( e ) ;
} ;
} ) ;
} ) ;
} ,
@ -106,29 +161,19 @@ module.exports = {
* @ return { Promise } A promise that resolves with the video image element .
* /
loadVideoElement : function ( videoFile ) {
return new Promise ( function ( resolve , reject ) {
// Load the file into an html element
const video = document . createElement ( "video" ) ;
const reader = new FileReader ( ) ;
reader . onload = function ( e ) {
video . src = e . target . result ;
// Once ready, returns its size
// Wait until we have enough data to thumbnail the first frame.
video . onloadeddata = function ( ) {
video . width = video . videoWidth ;
video . height = video . videoHeight ;
resolve ( video ) ;
} ;
video . onerror = function ( e ) {
reject ( e ) ;
} ;
} ;
reader . onerror = function ( e ) {
reject ( e ) ;
} ;
reader . readAsDataURL ( videoFile ) ;
return Promise . try ( ( ) => {
return awaitFileReader ( videoFile ) ;
} ) . then ( ( url ) => {
const video = Object . assign ( document . createElement ( "video" ) , {
src : url
} ) ;
return Promise . try ( ( ) => {
return awaitVideoLoad ( video ) ;
} ) . then ( ( dimensions ) => {
/* FIXME: Check whether this can be improved, it's a bit dirty to shoehorn the dimensions onto the video object like this */
return Object . assign ( video , dimensions ) ;
} ) ;
} ) ;
} ,
@ -163,7 +208,7 @@ module.exports = {
transformTags : { // custom to matrix
// add blank targets to all hyperlinks except vector URLs
'img' : function ( tagName , attribs) {
'img' : function ( tagName , _ attribs) {
// Strip out imgs that aren't `mxc` here instead of using allowedSchemesByTag
// because transformTags is used _before_ we filter by allowedSchemesByTag and
// we don't want to allow images with `https?` `src`s.
@ -209,10 +254,7 @@ module.exports = {
Object . keys ( customCSSMapper ) . forEach ( ( customAttributeKey ) => {
const cssAttributeKey = customCSSMapper [ customAttributeKey ] ;
const customAttributeValue = attribs [ customAttributeKey ] ;
if ( customAttributeValue &&
typeof customAttributeValue === 'string' &&
COLOR _REGEX . test ( customAttributeValue )
) {
if ( customAttributeValue && typeof customAttributeValue === 'string' && COLOR _REGEX . test ( customAttributeValue ) ) {
style += cssAttributeKey + ":" + customAttributeValue + ";" ;
delete attribs [ customAttributeKey ] ;
}