Last active
November 22, 2020 13:32
-
-
Save rivenvirus/7f236b7abbc1eb7ddb476730cc462a66 to your computer and use it in GitHub Desktop.
Thumbor Pipe for Angular 7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NgModule } from '@angular/core'; | |
import { ThumborPipe } from './thumbor.pipe'; | |
@NgModule({ | |
imports: [ | |
// dep modules | |
], | |
declarations: [ | |
ThumborPipe | |
], | |
exports: [ | |
ThumborPipe | |
] | |
}) | |
export class PipesModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Pipe, PipeTransform} from '@angular/core'; | |
import * as crypto from 'crypto-browserify'; | |
import { environment } from '../../environments/environment'; | |
@Pipe ({ | |
name : 'thumbor' | |
}) | |
export class ThumborPipe implements PipeTransform { | |
transform(url : string, resize? : number[], smartCrop?: boolean ) : string { | |
var thumbor = new Thumbor(environment.thumbor.key, environment.thumbor.url); | |
thumbor.setImagePath(url); | |
if(resize){ | |
var width = resize[0] || 0; | |
var height = resize[1] || 0; | |
thumbor.resize(width,height); | |
} | |
if(smartCrop){ | |
thumbor.smartCrop(smartCrop); | |
} | |
return thumbor.buildUrl(); | |
} | |
} | |
/** | |
* Thumbor client for Node JS | |
* https://github.com/policymic/thumbor | |
* @param {[type]} securityKey | |
* @param {[type]} thumborServerUrl | |
*/ | |
function Thumbor(securityKey, thumborServerUrl) { | |
'use strict'; | |
this.THUMBOR_SECURITY_KEY = securityKey; | |
this.THUMBOR_URL_SERVER = thumborServerUrl; | |
this.imagePath = ''; | |
this.width = 0; | |
this.height = 0; | |
this.smart = false; | |
this.fitInFlag = false; | |
this.withFlipHorizontally = false; | |
this.withFlipVertically = false; | |
this.halignValue = null; | |
this.valignValue = null; | |
this.cropValues = null; | |
this.meta = false; | |
this.filtersCalls = []; | |
} | |
Thumbor.prototype = { | |
TOP: 'top', | |
MIDDLE: 'middle', | |
BOTTOM: 'bottom', | |
RIGHT: 'right', | |
CENTER: 'center', | |
LEFT: 'left', | |
/** | |
* Set path of image | |
* @param {String} imagePath [description] | |
*/ | |
setImagePath: function(imagePath) { | |
this.imagePath = (imagePath.charAt(0) === '/') ? | |
imagePath.substring(1, imagePath.length) : imagePath; | |
return this; | |
}, | |
/** | |
* Converts operation array to string | |
* @return {String} | |
*/ | |
getOperationPath: function() { | |
var parts = this.urlParts(); | |
if (0 === parts.length) { | |
return ''; | |
} | |
return parts.join('/') + '/'; | |
}, | |
/** | |
* Build operation array | |
* | |
* @TODO Should be refactored so that strings are generated in the | |
* commands as opposed to in 1 massive function | |
* | |
* @return {Array} | |
*/ | |
urlParts: function() { | |
if (!this.imagePath) { | |
throw new Error('The image url can\'t be null or empty.'); | |
} | |
var parts = []; | |
if (this.meta) { | |
parts.push('meta'); | |
} | |
if (this.cropValues) { | |
parts.push( | |
this.cropValues.left + | |
'x' + this.cropValues.top + | |
':' + this.cropValues.right + | |
'x' + this.cropValues.bottom | |
); | |
} | |
if (this.fitInFlag) { | |
parts.push('fit-in'); | |
} | |
if ( | |
this.width || | |
this.height || | |
this.withFlipHorizontally || | |
this.withFlipVertically | |
) { | |
var sizeString = ''; | |
if (this.withFlipHorizontally) { | |
sizeString += '-'; | |
} | |
sizeString += this.width; | |
sizeString += 'x'; | |
if (this.withFlipVertically) { | |
sizeString += '-'; | |
} | |
sizeString += this.height; | |
parts.push(sizeString); | |
} | |
if (this.halignValue) { | |
parts.push(this.halignValue); | |
} | |
if (this.valignValue) { | |
parts.push(this.valignValue); | |
} | |
if (this.smart) { | |
parts.push('smart'); | |
} | |
if (this.filtersCalls.length) { | |
parts.push('filters:' + this.filtersCalls.join(':')); | |
} | |
return parts; | |
}, | |
/** | |
* Resize the image to the specified dimensions. Overrides any previous call | |
* to `fitIn` or `resize`. | |
* | |
* Use a value of 0 for proportional resizing. E.g. for a 640 x 480 image, | |
* `.resize(320, 0)` yields a 320 x 240 thumbnail. | |
* | |
* Use a value of 'orig' to use an original image dimension. E.g. for a 640 | |
* x 480 image, `.resize(320, 'orig')` yields a 320 x 480 thumbnail. | |
* @param {String} width | |
* @param {String} height | |
*/ | |
resize: function(width, height) { | |
this.width = width; | |
this.height = height; | |
this.fitInFlag = false; | |
return this; | |
}, | |
smartCrop: function(smartCrop) { | |
this.smart = smartCrop; | |
return this; | |
}, | |
/** | |
* Resize the image to fit in a box of the specified dimensions. Overrides | |
* any previous call to `fitIn` or `resize`. | |
* | |
* @param {String} width | |
* @param {String} height | |
*/ | |
fitIn: function(width, height) { | |
this.width = width; | |
this.height = height; | |
this.fitInFlag = true; | |
return this; | |
}, | |
/** | |
* Flip image horizontally | |
*/ | |
flipHorizontally: function() { | |
this.withFlipHorizontally = true; | |
return this; | |
}, | |
/** | |
* Flip image vertically | |
*/ | |
flipVertically: function() { | |
this.withFlipVertically = true; | |
return this; | |
}, | |
/** | |
* Specify horizontal alignment used if width is altered due to cropping | |
* @param {String} halign 'left', 'center', 'right' | |
*/ | |
halign: function(halign) { | |
if ( | |
halign === this.LEFT || | |
halign === this.RIGHT || | |
halign === this.CENTER | |
) { | |
this.halignValue = halign; | |
} else { | |
throw new Error('Horizontal align must be left, right or center.'); | |
} | |
return this; | |
}, | |
/** | |
* Specify vertical alignment used if height is altered due to cropping | |
* @param {String} valign 'top', 'middle', 'bottom' | |
*/ | |
valign: function(valign) { | |
if ( | |
valign === this.TOP || | |
valign === this.BOTTOM || | |
valign === this.MIDDLE | |
) { | |
this.valignValue = valign; | |
} else { | |
throw new Error('Vertical align must be top, bottom or middle.'); | |
} | |
return this; | |
}, | |
/** | |
* Specify that JSON metadata should be returned instead of the thumbnailed | |
* image. | |
* @param {Boolean} metaDataOnly [description] | |
*/ | |
metaDataOnly: function(metaDataOnly) { | |
this.meta = metaDataOnly; | |
return this; | |
}, | |
/** | |
* Append a filter, e.g. quality(80) | |
* @param {String} filterCall | |
*/ | |
filter: function(filterCall) { | |
this.filtersCalls.push(filterCall); | |
return this; | |
}, | |
/** | |
* Manually specify crop window. | |
* @param {Integer} left | |
* @param {Integer} top | |
* @param {Integer} right | |
* @param {Integer} bottom | |
* @return {[type]} | |
*/ | |
crop: function(left, top, right, bottom) { | |
this.cropValues = { | |
left: left, | |
top: top, | |
right: right, | |
bottom: bottom | |
}; | |
return this; | |
}, | |
/** | |
* Combine image url and operations with secure and unsecure (unsafe) paths | |
* @return {String} | |
*/ | |
buildUrl: function() { | |
var operation = this.getOperationPath(); | |
if (this.THUMBOR_SECURITY_KEY) { | |
var key = crypto | |
.createHmac('sha1', this.THUMBOR_SECURITY_KEY) | |
.update(operation + this.imagePath) | |
.digest('base64'); | |
key = key.replace(/\+/g, '-').replace(/\//g, '_'); | |
return this.THUMBOR_URL_SERVER + | |
'/' + key + | |
'/' + operation + | |
this.imagePath; | |
} else { | |
return this.THUMBOR_URL_SERVER + '/unsafe/' + operation + this.imagePath; | |
} | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare class Thumbor { | |
constructor(securityKey: any, thumborServerUrl: any); | |
THUMBOR_SECURITY_KEY: any; | |
THUMBOR_URL_SERVER: any; | |
imagePath: any; | |
width: any; | |
height: any; | |
smart: any; | |
fitInFlag: any; | |
withFlipHorizontally: any; | |
withFlipVertically: any; | |
halignValue: any; | |
valignValue: any; | |
cropValues: any; | |
meta: any; | |
filtersCalls: any; | |
buildUrl(): any; | |
crop(left: any, top: any, right: any, bottom: any): any; | |
filter(filterCall: any): any; | |
fitIn(width: any, height: any): any; | |
flipHorizontally(): any; | |
flipVertically(): any; | |
getOperationPath(): any; | |
halign(halign: any): any; | |
metaDataOnly(metaDataOnly: any): any; | |
resize(width: any, height: any): any; | |
setImagePath(imagePath: any): any; | |
smartCrop(smartCrop: any): any; | |
urlParts(): any; | |
valign(valign: any): any; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment