cloudinary 1.11.1 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  4. data/.github/pull_request_template.md +24 -0
  5. data/.gitignore +6 -1
  6. data/.travis.yml +15 -5
  7. data/CHANGELOG.md +149 -0
  8. data/Rakefile +3 -45
  9. data/cloudinary.gemspec +20 -4
  10. data/lib/active_storage/blob_key.rb +20 -0
  11. data/lib/active_storage/service/cloudinary_service.rb +229 -0
  12. data/lib/cloudinary.rb +31 -22
  13. data/lib/cloudinary/api.rb +173 -5
  14. data/lib/cloudinary/auth_token.rb +6 -4
  15. data/lib/cloudinary/carrier_wave.rb +3 -1
  16. data/lib/cloudinary/carrier_wave/remote.rb +3 -2
  17. data/lib/cloudinary/carrier_wave/storage.rb +2 -1
  18. data/lib/cloudinary/cloudinary_controller.rb +2 -4
  19. data/lib/cloudinary/helper.rb +30 -3
  20. data/lib/cloudinary/railtie.rb +7 -3
  21. data/lib/cloudinary/uploader.rb +35 -6
  22. data/lib/cloudinary/utils.rb +112 -40
  23. data/lib/cloudinary/version.rb +1 -1
  24. data/lib/cloudinary/video_helper.rb +96 -22
  25. data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
  26. data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
  27. data/tools/allocate_test_cloud.sh +9 -0
  28. data/tools/get_test_cloud.sh +9 -0
  29. data/tools/update_version +29 -11
  30. data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +48 -14
  31. data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
  32. data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
  33. data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
  34. metadata +62 -67
  35. data/spec/access_control_spec.rb +0 -102
  36. data/spec/api_spec.rb +0 -567
  37. data/spec/archive_spec.rb +0 -129
  38. data/spec/auth_token_spec.rb +0 -77
  39. data/spec/cache_spec.rb +0 -109
  40. data/spec/cloudinary_helper_spec.rb +0 -325
  41. data/spec/cloudinary_spec.rb +0 -32
  42. data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
  43. data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
  44. data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
  45. data/spec/docx.docx +0 -0
  46. data/spec/favicon.ico +0 -0
  47. data/spec/image_spec.rb +0 -107
  48. data/spec/logo.png +0 -0
  49. data/spec/rake_spec.rb +0 -160
  50. data/spec/sample_asset_file.tsv +0 -4
  51. data/spec/search_spec.rb +0 -109
  52. data/spec/spec_helper.rb +0 -266
  53. data/spec/storage_spec.rb +0 -44
  54. data/spec/streaminig_profiles_api_spec.rb +0 -74
  55. data/spec/support/helpers/temp_file_helpers.rb +0 -22
  56. data/spec/support/shared_contexts/rake.rb +0 -19
  57. data/spec/uploader_spec.rb +0 -392
  58. data/spec/utils_methods_spec.rb +0 -54
  59. data/spec/utils_spec.rb +0 -970
  60. data/spec/video_tag_spec.rb +0 -253
  61. data/spec/video_url_spec.rb +0 -185
@@ -1,2 +1,2 @@
1
- !function(e){"use strict";function t(e,i,a){var o,n=document.createElement("img");return n.onerror=function(o){return t.onerror(n,o,e,i,a)},n.onload=function(o){return t.onload(n,o,e,i,a)},"string"==typeof e?(t.fetchBlob(e,function(i){i?(e=i,o=t.createObjectURL(e)):(o=e,a&&a.crossOrigin&&(n.crossOrigin=a.crossOrigin)),n.src=o},a),n):t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e)?(o=n._objectURL=t.createObjectURL(e))?(n.src=o,n):t.readFile(e,function(e){var t=e.target;t&&t.result?n.src=t.result:i&&i(e)}):void 0}function i(e,i){!e._objectURL||i&&i.noRevoke||(t.revokeObjectURL(e._objectURL),delete e._objectURL)}var a=e.createObjectURL&&e||e.URL&&URL.revokeObjectURL&&URL||e.webkitURL&&webkitURL;t.fetchBlob=function(e,t,i){t()},t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transform=function(e,t,i,a,o){i(e,o)},t.onerror=function(e,t,a,o,n){i(e,n),o&&o.call(e,t)},t.onload=function(e,a,o,n,r){i(e,r),n&&t.transform(e,r,n,o,{})},t.createObjectURL=function(e){return!!a&&a.createObjectURL(e)},t.revokeObjectURL=function(e){return!!a&&a.revokeObjectURL(e)},t.readFile=function(t,i,a){if(e.FileReader){var o=new FileReader;if(o.onload=o.onerror=i,a=a||"readAsDataURL",o[a])return o[a](t),o}return!1},"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:e.loadImage=t}("undefined"!=typeof window&&window||this),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):e("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(e){"use strict";var t=e.transform;e.transform=function(i,a,o,n,r){t.call(e,e.scale(i,a,r),a,o,n,r)},e.transformCoordinates=function(){},e.getTransformedOptions=function(e,t){var i,a,o,n,r=t.aspectRatio;if(!r)return t;i={};for(a in t)t.hasOwnProperty(a)&&(i[a]=t[a]);return i.crop=!0,o=e.naturalWidth||e.width,n=e.naturalHeight||e.height,o/n>r?(i.maxWidth=n*r,i.maxHeight=n):(i.maxWidth=o,i.maxHeight=o/r),i},e.renderImageToCanvas=function(e,t,i,a,o,n,r,s,l,d){return e.getContext("2d").drawImage(t,i,a,o,n,r,s,l,d),e},e.hasCanvasOption=function(e){return e.canvas||e.crop||!!e.aspectRatio},e.scale=function(t,i,a){function o(){var e=Math.max((l||v)/v,(d||P)/P);e>1&&(v*=e,P*=e)}function n(){var e=Math.min((r||v)/v,(s||P)/P);e<1&&(v*=e,P*=e)}i=i||{};var r,s,l,d,c,u,f,g,h,m,p,S=document.createElement("canvas"),b=t.getContext||e.hasCanvasOption(i)&&S.getContext,y=t.naturalWidth||t.width,x=t.naturalHeight||t.height,v=y,P=x;if(b&&(f=(i=e.getTransformedOptions(t,i,a)).left||0,g=i.top||0,i.sourceWidth?(c=i.sourceWidth,void 0!==i.right&&void 0===i.left&&(f=y-c-i.right)):c=y-f-(i.right||0),i.sourceHeight?(u=i.sourceHeight,void 0!==i.bottom&&void 0===i.top&&(g=x-u-i.bottom)):u=x-g-(i.bottom||0),v=c,P=u),r=i.maxWidth,s=i.maxHeight,l=i.minWidth,d=i.minHeight,b&&r&&s&&i.crop?(v=r,P=s,(p=c/u-r/s)<0?(u=s*c/r,void 0===i.top&&void 0===i.bottom&&(g=(x-u)/2)):p>0&&(c=r*u/s,void 0===i.left&&void 0===i.right&&(f=(y-c)/2))):((i.contain||i.cover)&&(l=r=r||l,d=s=s||d),i.cover?(n(),o()):(o(),n())),b){if((h=i.pixelRatio)>1&&(S.style.width=v+"px",S.style.height=P+"px",v*=h,P*=h,S.getContext("2d").scale(h,h)),(m=i.downsamplingRatio)>0&&m<1&&v<c&&P<u)for(;c*m>v;)S.width=c*m,S.height=u*m,e.renderImageToCanvas(S,t,f,g,c,u,0,0,S.width,S.height),f=0,g=0,c=S.width,u=S.height,(t=document.createElement("canvas")).width=c,t.height=u,e.renderImageToCanvas(t,S,0,0,c,u,0,0,c,u);return S.width=v,S.height=P,e.transformCoordinates(S,i),e.renderImageToCanvas(S,t,f,g,c,u,0,0,v,P)}return t.width=v,t.height=P,t}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):e("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(e){"use strict";var t="undefined"!=typeof Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){return(this.slice||this.webkitSlice||this.mozSlice).apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a,o){a=a||{},o=o||{};var n=this,r=a.maxMetaDataSize||262144;!!("undefined"!=typeof DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice)&&e.readFile(e.blobSlice.call(t,0,r),function(t){if(t.target.error)return console.log(t.target.error),void i(o);var r,s,l,d,c=t.target.result,u=new DataView(c),f=2,g=u.byteLength-4,h=f;if(65496===u.getUint16(0)){for(;f<g&&((r=u.getUint16(f))>=65504&&r<=65519||65534===r);){if(s=u.getUint16(f+2)+2,f+s>u.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(l=e.metaDataParsers.jpeg[r])for(d=0;d<l.length;d+=1)l[d].call(n,u,f,s,o,a);h=f+=s}!a.disableImageHead&&h>6&&(c.slice?o.imageHead=c.slice(0,h):o.imageHead=new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(o)},"readAsArrayBuffer")||i(o)},e.hasMetaOption=function(e){return e&&e.meta};var i=e.transform;e.transform=function(t,a,o,n,r){e.hasMetaOption(a)?e.parseMetaData(n,function(r){i.call(e,t,a,o,n,r)},a,r):i.apply(e,arguments)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";"undefined"!=typeof fetch&&"undefined"!=typeof Request&&(e.fetchBlob=function(t,i,a){if(e.hasMetaOption(a))return fetch(new Request(t,a)).then(function(e){return e.blob()}).then(i).catch(function(e){console.log(e),i()});i()})}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,o,n;{if(i&&!(t+i>e.byteLength)){for(a=[],o=0;o<i;o+=1)n=e.getUint8(t+o),a.push((n<16?"0":"")+n.toString(16));return"data:image/jpeg,%"+a.join("%")}console.log("Invalid Exif data: Invalid thumbnail data.")}},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,o,n,r){var s,l,d,c,u,f,g=e.exifTagTypes[o];if(g){if(s=g.size*n,!((l=s>4?i+t.getUint32(a+8,r):a+8)+s>t.byteLength)){if(1===n)return g.getValue(t,l,r);for(d=[],c=0;c<n;c+=1)d[c]=g.getValue(t,l+c*g.size,r);if(g.ascii){for(u="",c=0;c<d.length&&"\0"!==(f=d[c]);c+=1)u+=f;return u}return d}console.log("Invalid Exif data: Invalid data offset.")}else console.log("Invalid Exif data: Invalid tag type.")},e.parseExifTag=function(t,i,a,o,n){var r=t.getUint16(a,o);n.exif[r]=e.getExifValue(t,i,a,t.getUint16(a+2,o),t.getUint32(a+4,o),o)},e.parseExifTags=function(e,t,i,a,o){var n,r,s;if(i+6>e.byteLength)console.log("Invalid Exif data: Invalid directory offset.");else{if(n=e.getUint16(i,a),!((r=i+2+12*n)+4>e.byteLength)){for(s=0;s<n;s+=1)this.parseExifTag(e,t,i+2+12*s,a,o);return e.getUint32(r,a)}console.log("Invalid Exif data: Invalid directory size.")}},e.parseExifData=function(t,i,a,o,n){if(!n.disableExif){var r,s,l,d=i+10;if(1165519206===t.getUint32(i+4))if(d+8>t.byteLength)console.log("Invalid Exif data: Invalid segment size.");else if(0===t.getUint16(i+8)){switch(t.getUint16(d)){case 18761:r=!0;break;case 19789:r=!1;break;default:return void console.log("Invalid Exif data: Invalid byte alignment marker.")}42===t.getUint16(d+2,r)?(s=t.getUint32(d+4,r),o.exif=new e.ExifMap,(s=e.parseExifTags(t,d,d+s,r,o))&&!n.disableExifThumbnail&&(l={exif:{}},s=e.parseExifTags(t,d,d+s,r,l),l.exif[513]&&(o.exif.Thumbnail=e.getExifThumbnail(t,d+l.exif[513],l.exif[514]))),o.exif[34665]&&!n.disableExifSub&&e.parseExifTags(t,d,d+o.exif[34665],r,o),o.exif[34853]&&!n.disableExifGps&&e.parseExifTags(t,d,d+o.exif[34853],r,o)):console.log("Invalid Exif data: Missing TIFF marker.")}else console.log("Invalid Exif data: Missing byte alignment offset.")}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-exif"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-exif")):e(window.loadImage)}(function(e){"use strict";e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":if(!t)return;return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":if(!t)return;return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":if(!t)return;return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return String(t)},function(e){var t,i=e.tags,a=e.map;for(t in i)i.hasOwnProperty(t)&&(a[i[t]]=t)}(e.ExifMap.prototype),e.ExifMap.prototype.getAll=function(){var e,t,i={};for(e in this)this.hasOwnProperty(e)&&(t=this.tags[e])&&(i[t]=this.getText(t));return i}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-scale","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-scale"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";var t=e.hasCanvasOption,i=e.hasMetaOption,a=e.transformCoordinates,o=e.getTransformedOptions;e.hasCanvasOption=function(i){return!!i.orientation||t.call(e,i)},e.hasMetaOption=function(t){return t&&!0===t.orientation||i.call(e,t)},e.transformCoordinates=function(t,i){a.call(e,t,i);var o=t.getContext("2d"),n=t.width,r=t.height,s=t.style.width,l=t.style.height,d=i.orientation;if(d&&!(d>8))switch(d>4&&(t.width=r,t.height=n,t.style.width=l,t.style.height=s),d){case 2:o.translate(n,0),o.scale(-1,1);break;case 3:o.translate(n,r),o.rotate(Math.PI);break;case 4:o.translate(0,r),o.scale(1,-1);break;case 5:o.rotate(.5*Math.PI),o.scale(1,-1);break;case 6:o.rotate(.5*Math.PI),o.translate(0,-r);break;case 7:o.rotate(.5*Math.PI),o.translate(n,-r),o.scale(-1,1);break;case 8:o.rotate(-.5*Math.PI),o.translate(-n,0)}},e.getTransformedOptions=function(t,i,a){var n,r,s=o.call(e,t,i),l=s.orientation;if(!0===l&&a&&a.exif&&(l=a.exif.get("Orientation")),!l||l>8||1===l)return s;n={};for(r in s)s.hasOwnProperty(r)&&(n[r]=s[r]);switch(n.orientation=l,l){case 2:n.left=s.right,n.right=s.left;break;case 3:n.left=s.right,n.top=s.bottom,n.right=s.left,n.bottom=s.top;break;case 4:n.top=s.bottom,n.bottom=s.top;break;case 5:n.left=s.top,n.top=s.left,n.right=s.bottom,n.bottom=s.right;break;case 6:n.left=s.top,n.top=s.right,n.right=s.bottom,n.bottom=s.left;break;case 7:n.left=s.bottom,n.top=s.right,n.right=s.top,n.bottom=s.left;break;case 8:n.left=s.bottom,n.top=s.left,n.right=s.top,n.bottom=s.right}return n.orientation>4&&(n.maxWidth=s.maxHeight,n.maxHeight=s.maxWidth,n.minWidth=s.minHeight,n.minHeight=s.minWidth,n.sourceWidth=s.sourceHeight,n.sourceHeight=s.sourceWidth),n}});
1
+ !function(e){"use strict";function t(e,i,a){var o,n=document.createElement("img");return n.onerror=function(o){return t.onerror(n,o,e,i,a)},n.onload=function(o){return t.onload(n,o,e,i,a)},"string"==typeof e?(t.fetchBlob(e,function(i){i?(e=i,o=t.createObjectURL(e)):(o=e,a&&a.crossOrigin&&(n.crossOrigin=a.crossOrigin)),n.src=o},a),n):t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e)?(o=n._objectURL=t.createObjectURL(e))?(n.src=o,n):t.readFile(e,function(e){var t=e.target;t&&t.result?n.src=t.result:i&&i(e)}):void 0}function i(e,i){!e._objectURL||i&&i.noRevoke||(t.revokeObjectURL(e._objectURL),delete e._objectURL)}var a=e.createObjectURL&&e||e.URL&&URL.revokeObjectURL&&URL||e.webkitURL&&webkitURL;t.fetchBlob=function(e,t,i){t()},t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transform=function(e,t,i,a,o){i(e,o)},t.onerror=function(e,t,a,o,n){i(e,n),o&&o.call(e,t)},t.onload=function(e,a,o,n,r){i(e,r),n&&t.transform(e,r,n,o,{})},t.createObjectURL=function(e){return!!a&&a.createObjectURL(e)},t.revokeObjectURL=function(e){return!!a&&a.revokeObjectURL(e)},t.readFile=function(t,i,a){if(e.FileReader){var o=new FileReader;if(o.onload=o.onerror=i,a=a||"readAsDataURL",o[a])return o[a](t),o}return!1},"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:e.loadImage=t}("undefined"!=typeof window&&window||this),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):e("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(e){"use strict";var t=e.transform;e.transform=function(i,a,o,n,r){t.call(e,e.scale(i,a,r),a,o,n,r)},e.transformCoordinates=function(){},e.getTransformedOptions=function(e,t){var i,a,o,n,r=t.aspectRatio;if(!r)return t;i={};for(a in t)t.hasOwnProperty(a)&&(i[a]=t[a]);return i.crop=!0,o=e.naturalWidth||e.width,n=e.naturalHeight||e.height,o/n>r?(i.maxWidth=n*r,i.maxHeight=n):(i.maxWidth=o,i.maxHeight=o/r),i},e.renderImageToCanvas=function(e,t,i,a,o,n,r,s,l,c){return e.getContext("2d").drawImage(t,i,a,o,n,r,s,l,c),e},e.hasCanvasOption=function(e){return e.canvas||e.crop||!!e.aspectRatio},e.scale=function(t,i,a){function o(){var e=Math.max((l||I)/I,(c||v)/v);e>1&&(I*=e,v*=e)}function n(){var e=Math.min((r||I)/I,(s||v)/v);e<1&&(I*=e,v*=e)}i=i||{};var r,s,l,c,d,u,f,g,p,m,h,S=document.createElement("canvas"),b=t.getContext||e.hasCanvasOption(i)&&S.getContext,y=t.naturalWidth||t.width,x=t.naturalHeight||t.height,I=y,v=x;if(b&&(f=(i=e.getTransformedOptions(t,i,a)).left||0,g=i.top||0,i.sourceWidth?(d=i.sourceWidth,void 0!==i.right&&void 0===i.left&&(f=y-d-i.right)):d=y-f-(i.right||0),i.sourceHeight?(u=i.sourceHeight,void 0!==i.bottom&&void 0===i.top&&(g=x-u-i.bottom)):u=x-g-(i.bottom||0),I=d,v=u),r=i.maxWidth,s=i.maxHeight,l=i.minWidth,c=i.minHeight,b&&r&&s&&i.crop?(I=r,v=s,(h=d/u-r/s)<0?(u=s*d/r,void 0===i.top&&void 0===i.bottom&&(g=(x-u)/2)):h>0&&(d=r*u/s,void 0===i.left&&void 0===i.right&&(f=(y-d)/2))):((i.contain||i.cover)&&(l=r=r||l,c=s=s||c),i.cover?(n(),o()):(o(),n())),b){if((p=i.pixelRatio)>1&&(S.style.width=I+"px",S.style.height=v+"px",I*=p,v*=p,S.getContext("2d").scale(p,p)),(m=i.downsamplingRatio)>0&&m<1&&I<d&&v<u)for(;d*m>I;)S.width=d*m,S.height=u*m,e.renderImageToCanvas(S,t,f,g,d,u,0,0,S.width,S.height),f=0,g=0,d=S.width,u=S.height,(t=document.createElement("canvas")).width=d,t.height=u,e.renderImageToCanvas(t,S,0,0,d,u,0,0,d,u);return S.width=I,S.height=v,e.transformCoordinates(S,i),e.renderImageToCanvas(S,t,f,g,d,u,0,0,I,v)}return t.width=I,t.height=v,t}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):e("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(e){"use strict";var t="undefined"!=typeof Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){return(this.slice||this.webkitSlice||this.mozSlice).apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[],65517:[]}},e.parseMetaData=function(t,i,a,o){a=a||{},o=o||{};var n=this,r=a.maxMetaDataSize||262144;!!("undefined"!=typeof DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice)&&e.readFile(e.blobSlice.call(t,0,r),function(t){if(t.target.error)return console.log(t.target.error),void i(o);var r,s,l,c,d=t.target.result,u=new DataView(d),f=2,g=u.byteLength-4,p=f;if(65496===u.getUint16(0)){for(;f<g&&((r=u.getUint16(f))>=65504&&r<=65519||65534===r);){if(s=u.getUint16(f+2)+2,f+s>u.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(l=e.metaDataParsers.jpeg[r])for(c=0;c<l.length;c+=1)l[c].call(n,u,f,s,o,a);p=f+=s}!a.disableImageHead&&p>6&&(d.slice?o.imageHead=d.slice(0,p):o.imageHead=new Uint8Array(d).subarray(0,p))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(o)},"readAsArrayBuffer")||i(o)},e.hasMetaOption=function(e){return e&&e.meta};var i=e.transform;e.transform=function(t,a,o,n,r){e.hasMetaOption(a)?e.parseMetaData(n,function(r){i.call(e,t,a,o,n,r)},a,r):i.apply(e,arguments)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";"undefined"!=typeof fetch&&"undefined"!=typeof Request&&(e.fetchBlob=function(t,i,a){if(e.hasMetaOption(a))return fetch(new Request(t,a)).then(function(e){return e.blob()}).then(i).catch(function(e){console.log(e),i()});i()})}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-scale","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-scale"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";var t=e.hasCanvasOption,i=e.hasMetaOption,a=e.transformCoordinates,o=e.getTransformedOptions;e.hasCanvasOption=function(i){return!!i.orientation||t.call(e,i)},e.hasMetaOption=function(t){return t&&!0===t.orientation||i.call(e,t)},e.transformCoordinates=function(t,i){a.call(e,t,i);var o=t.getContext("2d"),n=t.width,r=t.height,s=t.style.width,l=t.style.height,c=i.orientation;if(c&&!(c>8))switch(c>4&&(t.width=r,t.height=n,t.style.width=l,t.style.height=s),c){case 2:o.translate(n,0),o.scale(-1,1);break;case 3:o.translate(n,r),o.rotate(Math.PI);break;case 4:o.translate(0,r),o.scale(1,-1);break;case 5:o.rotate(.5*Math.PI),o.scale(1,-1);break;case 6:o.rotate(.5*Math.PI),o.translate(0,-r);break;case 7:o.rotate(.5*Math.PI),o.translate(n,-r),o.scale(-1,1);break;case 8:o.rotate(-.5*Math.PI),o.translate(-n,0)}},e.getTransformedOptions=function(t,i,a){var n,r,s=o.call(e,t,i),l=s.orientation;if(!0===l&&a&&a.exif&&(l=a.exif.get("Orientation")),!l||l>8||1===l)return s;n={};for(r in s)s.hasOwnProperty(r)&&(n[r]=s[r]);switch(n.orientation=l,l){case 2:n.left=s.right,n.right=s.left;break;case 3:n.left=s.right,n.top=s.bottom,n.right=s.left,n.bottom=s.top;break;case 4:n.top=s.bottom,n.bottom=s.top;break;case 5:n.left=s.top,n.top=s.left,n.right=s.bottom,n.bottom=s.right;break;case 6:n.left=s.top,n.top=s.right,n.right=s.bottom,n.bottom=s.left;break;case 7:n.left=s.bottom,n.top=s.right,n.right=s.top,n.bottom=s.left;break;case 8:n.left=s.bottom,n.top=s.left,n.right=s.top,n.bottom=s.right}return n.orientation>4&&(n.maxWidth=s.maxHeight,n.maxHeight=s.maxWidth,n.minWidth=s.minHeight,n.minHeight=s.minWidth,n.sourceWidth=s.sourceHeight,n.sourceHeight=s.sourceWidth),n}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(t,i,a){if(a&&!(i+a>t.byteLength))return e.createObjectURL(new Blob([t.buffer.slice(i,i+a)]));console.log("Invalid Exif data: Invalid thumbnail data.")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,o,n,r){var s,l,c,d,u,f,g=e.exifTagTypes[o];if(g){if(s=g.size*n,!((l=s>4?i+t.getUint32(a+8,r):a+8)+s>t.byteLength)){if(1===n)return g.getValue(t,l,r);for(c=[],d=0;d<n;d+=1)c[d]=g.getValue(t,l+d*g.size,r);if(g.ascii){for(u="",d=0;d<c.length&&"\0"!==(f=c[d]);d+=1)u+=f;return u}return c}console.log("Invalid Exif data: Invalid data offset.")}else console.log("Invalid Exif data: Invalid tag type.")},e.parseExifTag=function(t,i,a,o,n){var r=t.getUint16(a,o);n.exif[r]=e.getExifValue(t,i,a,t.getUint16(a+2,o),t.getUint32(a+4,o),o)},e.parseExifTags=function(e,t,i,a,o){var n,r,s;if(i+6>e.byteLength)console.log("Invalid Exif data: Invalid directory offset.");else{if(n=e.getUint16(i,a),!((r=i+2+12*n)+4>e.byteLength)){for(s=0;s<n;s+=1)this.parseExifTag(e,t,i+2+12*s,a,o);return e.getUint32(r,a)}console.log("Invalid Exif data: Invalid directory size.")}},e.parseExifData=function(t,i,a,o,n){if(!n.disableExif){var r,s,l,c=i+10;if(1165519206===t.getUint32(i+4))if(c+8>t.byteLength)console.log("Invalid Exif data: Invalid segment size.");else if(0===t.getUint16(i+8)){switch(t.getUint16(c)){case 18761:r=!0;break;case 19789:r=!1;break;default:return void console.log("Invalid Exif data: Invalid byte alignment marker.")}42===t.getUint16(c+2,r)?(s=t.getUint32(c+4,r),o.exif=new e.ExifMap,(s=e.parseExifTags(t,c,c+s,r,o))&&!n.disableExifThumbnail&&(l={exif:{}},s=e.parseExifTags(t,c,c+s,r,l),l.exif[513]&&(o.exif.Thumbnail=e.getExifThumbnail(t,c+l.exif[513],l.exif[514]))),o.exif[34665]&&!n.disableExifSub&&e.parseExifTags(t,c,c+o.exif[34665],r,o),o.exif[34853]&&!n.disableExifGps&&e.parseExifTags(t,c,c+o.exif[34853],r,o)):console.log("Invalid Exif data: Missing TIFF marker.")}else console.log("Invalid Exif data: Missing byte alignment offset.")}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-exif"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-exif")):e(window.loadImage)}(function(e){"use strict";e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":if(!t)return;return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":if(!t)return;return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":if(!t)return;return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return String(t)},function(e){var t,i=e.tags,a=e.map;for(t in i)i.hasOwnProperty(t)&&(a[i[t]]=t)}(e.ExifMap.prototype),e.ExifMap.prototype.getAll=function(){var e,t,i={};for(e in this)this.hasOwnProperty(e)&&(t=this.tags[e])&&(i[t]=this.getText(t));return i}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";e.IptcMap=function(){return this},e.IptcMap.prototype.map={ObjectName:5},e.IptcMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.parseIptcTags=function(e,t,i,a){for(var o,n,r=t;r<t+i;)28===e.getUint8(r)&&2===e.getUint8(r+1)&&(n=e.getUint8(r+2))in a.iptc.tags&&(o=function(e,t,i){for(var a="",o=t;o<t+i;o++)a+=String.fromCharCode(e.getUint8(o));return a}(e,r+5,e.getInt16(r+3)),a.iptc.hasOwnProperty(n)?a.iptc[n]instanceof Array?a.iptc[n].push(o):a.iptc[n]=[a.iptc[n],o]:a.iptc[n]=o),r++},e.parseIptcData=function(t,i,a,o,n){if(!n.disableIptc){for(var r=i+a;i+8<r;){if(function(e,t){return 943868237===e.getUint32(t)&&1028===e.getUint16(t+4)}(t,i)){var s=t.getUint8(i+7);s%2!=0&&(s+=1),0===s&&(s=4);var l=i+8+s;if(l>r){console.log("Invalid IPTC data: Invalid segment offset.");break}var c=t.getUint16(i+6+s);if(i+c>r){console.log("Invalid IPTC data: Invalid segment size.");break}return o.iptc=new e.IptcMap,e.parseIptcTags(t,l,c,o)}i++}console.log("No IPTC data at this offset - could be XMP")}},e.metaDataParsers.jpeg[65517].push(e.parseIptcData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-iptc"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-iptc")):e(window.loadImage)}(function(e){"use strict";e.IptcMap.prototype.tags={3:"ObjectType",4:"ObjectAttribute",5:"ObjectName",7:"EditStatus",8:"EditorialUpdate",10:"Urgency",12:"SubjectRef",15:"Category",20:"SupplCategory",22:"FixtureID",25:"Keywords",26:"ContentLocCode",27:"ContentLocName",30:"ReleaseDate",35:"ReleaseTime",37:"ExpirationDate",38:"ExpirationTime",40:"SpecialInstructions",42:"ActionAdvised",45:"RefService",47:"RefDate",50:"RefNumber",55:"DateCreated",60:"TimeCreated",62:"DigitalCreationDate",63:"DigitalCreationTime",65:"OriginatingProgram",70:"ProgramVersion",75:"ObjectCycle",80:"Byline",85:"BylineTitle",90:"City",92:"Sublocation",95:"State",100:"CountryCode",101:"CountryName",103:"OrigTransRef",105:"Headline",110:"Credit",115:"Source",116:"CopyrightNotice",118:"Contact",120:"Caption",122:"WriterEditor",130:"ImageType",131:"ImageOrientation",135:"LanguageID"},e.IptcMap.prototype.getText=function(e){var t=this.get(e);return String(t)},function(e){var t,i=e.tags,a=e.map||{};for(t in i)i.hasOwnProperty(t)&&(a[i[t]]=t)}(e.IptcMap.prototype),e.IptcMap.prototype.getAll=function(){var e,t,i={};for(e in this)this.hasOwnProperty(e)&&(t=this.tags[e])&&(i[t]=this.getText(t));return i}});
2
2
  //# sourceMappingURL=load-image.all.min.js.map
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudinary
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.1
4
+ version: 1.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nadav Soferman
8
8
  - Itai Lahan
9
9
  - Tal Lev-Ami
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-12-22 00:00:00.000000000 Z
13
+ date: 2020-09-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws_cf_signer
@@ -70,6 +70,20 @@ dependencies:
70
70
  version: '0'
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: rake
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 13.0.1
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 13.0.1
85
+ - !ruby/object:Gem::Dependency
86
+ name: sqlite3
73
87
  requirement: !ruby/object:Gem::Requirement
74
88
  requirements:
75
89
  - - ">="
@@ -96,6 +110,34 @@ dependencies:
96
110
  - - ">="
97
111
  - !ruby/object:Gem::Version
98
112
  version: '3.5'
113
+ - !ruby/object:Gem::Dependency
114
+ name: rspec-retry
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: rails
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: '5.2'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - "~>"
139
+ - !ruby/object:Gem::Version
140
+ version: '5.2'
99
141
  - !ruby/object:Gem::Dependency
100
142
  name: rspec-rails
101
143
  requirement: !ruby/object:Gem::Requirement
@@ -128,16 +170,16 @@ dependencies:
128
170
  name: simplecov
129
171
  requirement: !ruby/object:Gem::Requirement
130
172
  requirements:
131
- - - ">="
173
+ - - ">"
132
174
  - !ruby/object:Gem::Version
133
- version: '0'
175
+ version: 0.18.0
134
176
  type: :development
135
177
  prerelease: false
136
178
  version_requirements: !ruby/object:Gem::Requirement
137
179
  requirements:
138
- - - ">="
180
+ - - ">"
139
181
  - !ruby/object:Gem::Version
140
- version: '0'
182
+ version: 0.18.0
141
183
  description: Client library for easily using the Cloudinary service
142
184
  email:
143
185
  - nadav.soferman@cloudinary.com
@@ -147,6 +189,9 @@ executables: []
147
189
  extensions: []
148
190
  extra_rdoc_files: []
149
191
  files:
192
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
193
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
194
+ - ".github/pull_request_template.md"
150
195
  - ".gitignore"
151
196
  - ".rspec"
152
197
  - ".travis.yml"
@@ -156,6 +201,8 @@ files:
156
201
  - README.md
157
202
  - Rakefile
158
203
  - cloudinary.gemspec
204
+ - lib/active_storage/blob_key.rb
205
+ - lib/active_storage/service/cloudinary_service.rb
159
206
  - lib/cloudinary.rb
160
207
  - lib/cloudinary/api.rb
161
208
  - lib/cloudinary/auth_token.rb
@@ -188,34 +235,10 @@ files:
188
235
  - lib/cloudinary/utils.rb
189
236
  - lib/cloudinary/version.rb
190
237
  - lib/cloudinary/video_helper.rb
191
- - lib/tasks/cloudinary.rake
192
- - spec/access_control_spec.rb
193
- - spec/api_spec.rb
194
- - spec/archive_spec.rb
195
- - spec/auth_token_spec.rb
196
- - spec/cache_spec.rb
197
- - spec/cloudinary_helper_spec.rb
198
- - spec/cloudinary_spec.rb
199
- - spec/data/sync_static/app/assets/javascripts/1.coffee
200
- - spec/data/sync_static/app/assets/javascripts/1.js
201
- - spec/data/sync_static/app/assets/stylesheets/1.css
202
- - spec/docx.docx
203
- - spec/favicon.ico
204
- - spec/image_spec.rb
205
- - spec/logo.png
206
- - spec/rake_spec.rb
207
- - spec/sample_asset_file.tsv
208
- - spec/search_spec.rb
209
- - spec/spec_helper.rb
210
- - spec/storage_spec.rb
211
- - spec/streaminig_profiles_api_spec.rb
212
- - spec/support/helpers/temp_file_helpers.rb
213
- - spec/support/shared_contexts/rake.rb
214
- - spec/uploader_spec.rb
215
- - spec/utils_methods_spec.rb
216
- - spec/utils_spec.rb
217
- - spec/video_tag_spec.rb
218
- - spec/video_url_spec.rb
238
+ - lib/tasks/cloudinary/fetch_assets.rake
239
+ - lib/tasks/cloudinary/sync_static.rake
240
+ - tools/allocate_test_cloud.sh
241
+ - tools/get_test_cloud.sh
219
242
  - tools/update_version
220
243
  - vendor/assets/html/cloudinary_cors.html
221
244
  - vendor/assets/javascripts/cloudinary/canvas-to-blob.min.js
@@ -233,7 +256,7 @@ homepage: http://cloudinary.com
233
256
  licenses:
234
257
  - MIT
235
258
  metadata: {}
236
- post_install_message:
259
+ post_install_message:
237
260
  rdoc_options: []
238
261
  require_paths:
239
262
  - lib
@@ -248,36 +271,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
248
271
  - !ruby/object:Gem::Version
249
272
  version: '0'
250
273
  requirements: []
251
- rubyforge_project: cloudinary
252
- rubygems_version: 2.7.8
253
- signing_key:
274
+ rubygems_version: 3.1.4
275
+ signing_key:
254
276
  specification_version: 4
255
277
  summary: Client library for easily using the Cloudinary service
256
- test_files:
257
- - spec/access_control_spec.rb
258
- - spec/api_spec.rb
259
- - spec/archive_spec.rb
260
- - spec/auth_token_spec.rb
261
- - spec/cache_spec.rb
262
- - spec/cloudinary_helper_spec.rb
263
- - spec/cloudinary_spec.rb
264
- - spec/data/sync_static/app/assets/javascripts/1.coffee
265
- - spec/data/sync_static/app/assets/javascripts/1.js
266
- - spec/data/sync_static/app/assets/stylesheets/1.css
267
- - spec/docx.docx
268
- - spec/favicon.ico
269
- - spec/image_spec.rb
270
- - spec/logo.png
271
- - spec/rake_spec.rb
272
- - spec/sample_asset_file.tsv
273
- - spec/search_spec.rb
274
- - spec/spec_helper.rb
275
- - spec/storage_spec.rb
276
- - spec/streaminig_profiles_api_spec.rb
277
- - spec/support/helpers/temp_file_helpers.rb
278
- - spec/support/shared_contexts/rake.rb
279
- - spec/uploader_spec.rb
280
- - spec/utils_methods_spec.rb
281
- - spec/utils_spec.rb
282
- - spec/video_tag_spec.rb
283
- - spec/video_url_spec.rb
278
+ test_files: []
@@ -1,102 +0,0 @@
1
- require 'rspec'
2
- require 'cloudinary'
3
- require 'spec_helper'
4
- require 'time'
5
-
6
- # Calculates days as seconds
7
- def days(n)
8
- n * 3600 * 24
9
- end
10
-
11
- describe "Access Control" do
12
- before :each do
13
- Cloudinary.reset_config
14
- end
15
- let (:acl) {{
16
- :access_type => 'anonymous',
17
- :start => '2019-02-22 16:20:57 +0200',
18
- :end => '2019-03-22 00:00 +0200'
19
- }}
20
- let (:acl_2) {{
21
- :access_type => 'anonymous',
22
- :start => '2019-02-22 16:20:57Z',
23
- :end => '2019-03-22 00:00 +0200'
24
- }}
25
- let (:acl_string) {
26
- '{"access_type":"anonymous","start":"2019-02-22 16:20:57 +0200","end":"2019-03-22 00:00 +0200"}'
27
- }
28
- let (:options) {{
29
- :public_id => TIMESTAMP_TAG,
30
- :tags => [TEST_TAG, TIMESTAMP_TAG, 'access_control_test']
31
- }}
32
- let(:resource ){
33
- Cloudinary::Uploader.upload(
34
- TEST_IMG,
35
- options)
36
- }
37
- describe 'build_upload_params' do
38
- it "should accept a Hash value" do
39
- params = Cloudinary::Uploader.build_upload_params access_control: acl
40
- expect(params).to have_key(:access_control)
41
- expect(params[:access_control]).to be_a String
42
- expect(params[:access_control]).to match(/^\[.+\]$/)
43
-
44
- end
45
- it "should accept an array of Hash values" do
46
- params = Cloudinary::Uploader.build_upload_params access_control: [acl, acl_2]
47
- expect(params).to have_key(:access_control)
48
- expect(params[:access_control]).to be_a String
49
- expect(params[:access_control]).to match(/^\[.+\]$/)
50
- j = JSON.parse(params[:access_control])
51
- expect(j.length).to be(2)
52
- expect(j[0]["access_type"]).to eql(acl[:access_type])
53
- expect(j[0]["start"]).to eql(acl[:start])
54
- expect(j[0]["end"]).to eql(acl[:end])
55
- end
56
- it "should accept a JSON string" do
57
- params = Cloudinary::Uploader.build_upload_params access_control: acl_string
58
- expect(params).to have_key(:access_control)
59
- expect(params[:access_control]).to be_a String
60
- expect(params[:access_control]).to eql("[#{acl_string}]")
61
- end
62
- end
63
-
64
- describe 'upload' do
65
- break puts("Please setup environment for api test to run") if Cloudinary.config.api_secret.blank?
66
- include_context "cleanup", TIMESTAMP_TAG
67
-
68
- it 'should allow the user to define ACL in the upload parameters' do
69
- options[:access_control] = [acl]
70
- expect(RestClient::Request).to receive(:execute).with(
71
- deep_hash_value( {[:payload, :access_control] => "[#{acl_string}]"})
72
- ).and_call_original
73
- expect(resource).to have_key('access_control')
74
- response_acl = resource["access_control"]
75
- expect(response_acl.length).to be(1)
76
- expect(response_acl[0]["access_type"]).to eq("anonymous")
77
- expect(Time.parse(response_acl[0]["start"])).to eq(Time.parse(acl[:start]))
78
- expect(Time.parse(response_acl[0]["end"])).to eq(Time.parse(acl[:end]))
79
- end
80
- end
81
- describe 'update' do
82
- break puts("Please setup environment for api test to run") if Cloudinary.config.api_secret.blank?
83
- include_context "cleanup", TIMESTAMP_TAG
84
-
85
- it 'should allow the user to define ACL in the update parameters' do
86
- resource # upload before setting the expect
87
- expect(RestClient::Request).to receive(:execute).with(
88
- deep_hash_value( {[:payload, :access_control] => "[#{acl_string}]"})
89
- ).and_call_original
90
- result = Cloudinary::Api.update(
91
- resource['public_id'],
92
- :tags => [TEST_TAG, TIMESTAMP_TAG, 'access_control_test'],
93
- :access_control => acl)
94
- expect(result).to have_key('access_control')
95
- response_acl = result["access_control"]
96
- expect(response_acl.length).to be(1)
97
- expect(response_acl[0]["access_type"]).to eq("anonymous")
98
- expect(Time.parse(response_acl[0]["start"])).to eq(Time.parse(acl[:start]))
99
- expect(Time.parse(response_acl[0]["end"])).to eq(Time.parse(acl[:end]))
100
- end
101
- end
102
- end
@@ -1,567 +0,0 @@
1
- require 'spec_helper'
2
- require 'cloudinary'
3
-
4
- describe Cloudinary::Api do
5
- break puts("Please setup environment for api test to run") if Cloudinary.config.api_secret.blank?
6
- include_context "cleanup", TIMESTAMP_TAG
7
- TEST_WIDTH = rand(1000)
8
- TEST_TRANSFOMATION = "c_scale,w_#{TEST_WIDTH}"
9
- prefix = "api_test_#{SUFFIX}"
10
- test_id_1 = "#{prefix}_1"
11
- test_id_2 = "#{prefix}_2"
12
- test_id_3 = "#{prefix}_3"
13
- test_key = "test_key_#{SUFFIX}"
14
- before(:all) do
15
-
16
- @api = Cloudinary::Api
17
- Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_1, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
18
- Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_2, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
19
- Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_3, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
20
- Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_1, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "#{test_key}=test", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
21
- Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_3, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "#{test_key}=tasty", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
22
- end
23
-
24
- after(:all) do
25
- # in addition to "cleanup" context
26
- unless Cloudinary.config.keep_test_products
27
- up = Cloudinary::Api.upload_presets max_results: 500
28
- up["presets"].each do |u|
29
- tags = u["settings"]["tags"]
30
- name = u["name"]
31
- if tags =~ /.*#{TIMESTAMP_TAG}.*/
32
- Cloudinary::Api.delete_upload_preset(name)
33
- end
34
- end
35
- end
36
- end
37
-
38
- it "should allow listing resource_types" do
39
- expect(@api.resource_types()["resource_types"]).to include("image")
40
- end
41
-
42
- it "should allow listing resources" do
43
- resource = @api.resources()["resources"].find{|resource| resource["public_id"] == test_id_1
44
- }
45
- expect(resource).not_to be_blank
46
- expect(resource["type"]).to eq("upload")
47
- end
48
-
49
- it "should allow listing resources with cursor" do
50
- result = @api.resources(:max_results=>1)
51
- expect(result["resources"]).not_to be_blank
52
- expect(result["resources"].length).to eq(1)
53
- expect(result["next_cursor"]).not_to be_blank
54
- result2 = @api.resources(:max_results=>1, :next_cursor=>result["next_cursor"])
55
- expect(result2["resources"]).not_to be_blank
56
- expect(result2["resources"].length).to eq(1)
57
- expect(result2["resources"][0]["public_id"]).not_to eq(result["resources"][0]["public_id"] )
58
- end
59
-
60
- it "should allow listing resources by type" do
61
- resource = @api.resources(:type=>"upload", :tags=>true)["resources"].find{|resource| resource["public_id"] == test_id_1
62
- }
63
- expect(resource).not_to be_blank
64
- expect(resource["tags"]).to match_array([TEST_TAG, TIMESTAMP_TAG])
65
- end
66
-
67
- it "should allow listing resources by prefix" do
68
- resources = @api.resources(:type =>"upload", :prefix => prefix, :tags => true, :context => true)["resources"]
69
- expect(resources.map{|resource| resource["public_id"]}).to include(test_id_1, test_id_2)
70
- expect(resources.map{|resource| resource["tags"]}.flatten).to include(TEST_TAG, TIMESTAMP_TAG)
71
- expect(resources.map{|resource| resource["context"]}).to include({"custom" => {"key" => "value"}})
72
- end
73
-
74
- it "should allow listing resources by tag" do
75
- resources = @api.resources_by_tag(TEST_TAG, :tags => true, :context => true)["resources"]
76
- expect(resources.find{|resource| resource["public_id"] == test_id_1
77
- }).not_to be_blank
78
- expect(resources.map{|resource| resource["tags"]}.flatten).to include(TEST_TAG, TIMESTAMP_TAG)
79
- expect(resources.map{|resource| resource["context"]}).to include({"custom" => {"key" => "value"}})
80
- end
81
-
82
- it "should allow listing resources by context" do
83
- resources = @api.resources_by_context(test_key)["resources"]
84
- expect(resources.count).to eq(2)
85
- resources = @api.resources_by_context(test_key,'test')["resources"]
86
- expect(resources.count).to eq(1)
87
- end
88
-
89
- it "should allow listing resources by public ids" do
90
- resources = @api.resources_by_ids([test_id_1, test_id_2], :tags => true, :context => true)["resources"]
91
- expect(resources.length).to eq(2)
92
- expect(resources.find{|resource| resource["public_id"] == test_id_1
93
- }).not_to be_blank
94
- expect(resources.map{|resource| resource["tags"]}.flatten).to include(TEST_TAG, TIMESTAMP_TAG)
95
- expect(resources.map{|resource| resource["context"]}).to include({"custom" => {"key" => "value"}})
96
- end
97
-
98
- it "should allow listing resources by start date", :start_at => true do
99
- start_at = Time.now
100
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :start_at] => start_at, [:payload, :direction] => "asc"}))
101
- @api.resources(:type=>"upload", :start_at=>start_at, :direction => "asc")
102
- end
103
-
104
- describe ":direction" do
105
-
106
- it "should accept a string 'desc' and 'asc'" do
107
- expected = {
108
- :url => /.*\/resources\/image\/tags\/#{TIMESTAMP_TAG}/,
109
- [:payload, :direction] => "asc"
110
- }
111
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
112
-
113
- @api.resources_by_tag(TIMESTAMP_TAG, :type=>"upload", :direction => "asc")
114
- end
115
- it "should accept an integer of '1' or '-1'" do
116
- expected = {
117
- :url => /.*\/resources\/image\/tags\/#{TIMESTAMP_TAG}/,
118
- [:payload, :direction] => "-1"
119
- }
120
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
121
- @api.resources_by_tag(TIMESTAMP_TAG, :type=>"upload", :direction => "-1")
122
- end
123
- end
124
-
125
- it "should allow get resource metadata" do
126
- resource = @api.resource(test_id_1)
127
- expect(resource).not_to be_blank
128
- expect(resource["public_id"]).to eq(test_id_1)
129
- expect(resource["bytes"]).to eq(3381)
130
- expect(resource["derived"].length).to eq(1)
131
- end
132
-
133
- it "should support the quality_analysis parameter" do
134
- resource = @api.resource(test_id_1, :quality_analysis => true)
135
- expect(resource).not_to be_blank
136
- expect(resource).to have_key("quality_analysis")
137
- expect(resource["quality_analysis"]).to have_key("focus")
138
- end
139
-
140
- it "should allow deleting derived resource" do
141
- derived_resource_id = "derived_id"
142
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :derived_resource_ids] => derived_resource_id}))
143
- @api.delete_derived_resources(derived_resource_id)
144
- end
145
-
146
- it "should allow deleting derived resources by transformations" do
147
- public_id = "public_id"
148
- transformations = "c_crop,w_100"
149
- expect(RestClient::Request).to receive(:execute).with(
150
- deep_hash_value( {[:payload, :public_ids] => public_id,
151
- [:payload, :transformations] => "c_crop,w_100"}))
152
- @api.delete_derived_by_transformation(public_id, "c_crop,w_100")
153
-
154
- transformations = {:crop => "crop", :width => 100}
155
- expect(RestClient::Request).to receive(:execute).with(
156
- deep_hash_value( {[:payload, :public_ids] => public_id,
157
- [:payload, :transformations] => "c_crop,w_100"}))
158
- @api.delete_derived_by_transformation(public_id, transformations)
159
-
160
- transformations = [{:crop => "crop", :width => 100}, {:crop => "scale", :width => 300}]
161
- expect(RestClient::Request).to receive(:execute).with(
162
- deep_hash_value( {[:payload, :public_ids] => public_id,
163
- [:payload, :transformations] => "c_crop,w_100|c_scale,w_300"}))
164
- @api.delete_derived_by_transformation(public_id, transformations)
165
-
166
- end
167
-
168
- it "should allow deleting multiple resources and comma inclusive public IDs", :focus => true do
169
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :public_ids] => ["apit_test", "test_id_2", "api_test3"]}))
170
- @api.delete_resources(["apit_test", "test_id_2", "api_test3"])
171
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :public_ids] => "apit_test,test_id_2,api_test3"}))
172
- @api.delete_resources("apit_test,test_id_2,api_test3")
173
- end
174
-
175
- it "should allow deleting resource transformations" do
176
- resource = Cloudinary::Uploader.upload(TEST_IMG, :eager => [{:width=>101,:crop=>:scale}, {:width=>200,:crop=>:crop}])
177
- public_id = resource["public_id"]
178
- expect(resource).not_to be_blank
179
- derived = resource["eager"].map{|d| d["transformation"]}
180
- expect(derived).to include("c_scale,w_101", "c_crop,w_200")
181
- @api.delete_resources([public_id], :transformations => "c_crop,w_200")
182
- resource = @api.resource(public_id)
183
- derived = resource["derived"].map{|d| d["transformation"]}
184
- expect(derived).not_to include("c_crop,w_200")
185
- expect(derived).to include("c_scale,w_101")
186
- end
187
-
188
- it "should allow deleting resources by prefix" do
189
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( {[:payload, :prefix] => "api_test_by"}))
190
- @api.delete_resources_by_prefix("api_test_by")
191
- end
192
-
193
- it "should allow deleting resources by tags" do
194
- expect(RestClient::Request).to receive(:execute).with(hash_including( :url => /.*\/tags\/api_test_tag_for_delete$/))
195
- @api.delete_resources_by_tag("api_test_tag_for_delete")
196
- end
197
-
198
- it "should allow listing tags" do
199
- tags = @api.tags(:max_results => 500)["tags"]
200
- expect(tags).to include(TEST_TAG)
201
- end
202
-
203
- it "should allow listing tag by prefix" do
204
- tags = @api.tags(:prefix=> TEST_TAG)["tags"]
205
- expect(tags).to include(TIMESTAMP_TAG)
206
- tags = @api.tags(:prefix=>"api_test_no_such_tag")["tags"]
207
- expect(tags).to be_blank
208
- end
209
-
210
- describe 'transformations' do
211
- it "should allow listing transformations" do
212
- transformations = @api.transformations()["transformations"]
213
- t0 = transformations[0]
214
- expect(t0).not_to be_empty
215
- expect(t0).to have_key("used")
216
- end
217
-
218
- it "should allow getting transformation metadata" do
219
- transformation = @api.transformation(TEST_TRANSFOMATION)
220
- expect(transformation).not_to be_blank
221
- expect(transformation["info"]).to eq(["crop" => "scale", "width" => TEST_WIDTH])
222
- transformation = @api.transformation("crop" => "scale", "width" => TEST_WIDTH)
223
- expect(transformation).not_to be_blank
224
- expect(transformation["info"]).to eq(["crop" => "scale", "width" => TEST_WIDTH])
225
- end
226
-
227
- it "should allow updating transformation allowed_for_strict" do
228
- @api.update_transformation(TEST_TRANSFOMATION, :allowed_for_strict => true)
229
- transformation = @api.transformation(TEST_TRANSFOMATION)
230
- expect(transformation).not_to be_blank
231
- expect(transformation["allowed_for_strict"]).to eq(true)
232
- @api.update_transformation(TEST_TRANSFOMATION, :allowed_for_strict => false)
233
- transformation = @api.transformation(TEST_TRANSFOMATION)
234
- expect(transformation).not_to be_blank
235
- expect(transformation["allowed_for_strict"]).to eq(false)
236
- end
237
-
238
- it "should fetch two different derived images using next_cursor" do
239
- result = @api.transformation(TEST_TRANSFOMATION, :max_results=>1)
240
- expect(result["derived"]).not_to be_blank
241
- expect(result["derived"].length).to eq(1)
242
- expect(result["next_cursor"]).not_to be_blank
243
- result2 = @api.transformation(TEST_TRANSFOMATION, :max_results=>1, :next_cursor=>result["next_cursor"])
244
- expect(result2["derived"]).not_to be_blank
245
- expect(result2["derived"].length).to eq(1)
246
- expect(result2["derived"][0]["id"]).not_to eq(result["derived"][0]["id"] )
247
- end
248
-
249
- describe "named transformations" do
250
- it "should allow creating named transformation" do
251
- public_id = "api_test_transformation_#{Time.now.to_i}"
252
- @api.create_transformation(public_id, "crop" => "scale", "width" => 102)
253
- transformation = @api.transformation(public_id)
254
- expect(transformation).not_to be_blank
255
- expect(transformation["allowed_for_strict"]).to eq(true)
256
- expect(transformation["info"]).to eq(["crop" => "scale", "width" => 102])
257
- expect(transformation["used"]).to eq(false)
258
- end
259
-
260
- it "should allow deleting named transformation" do
261
- public_id = "api_test_transformation_#{Time.now.to_i}"
262
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( :url => /.*\/transformations\/#{public_id}/, :method => :delete))
263
- @api.delete_transformation(public_id)
264
- end
265
-
266
- it "should allow unsafe update of named transformation" do
267
- public_id = "api_test_transformation_#{Time.now.to_i}"
268
- expected = {
269
- :url => /.*\/transformations\/#{public_id}$/,
270
- :method => :put,
271
- [:payload, :unsafe_update] => "c_scale,w_103"}
272
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
273
- @api.update_transformation(public_id, :unsafe_update => { "crop" => "scale", "width" => 103 })
274
- end
275
-
276
- it "should allow listing of named transformations" do
277
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :named ]=> true))
278
- @api.transformations :named => true
279
- end
280
-
281
- end
282
- it "should allow deleting implicit transformation" do
283
- @api.transformation(TEST_TRANSFOMATION)
284
- @api.delete_transformation(TEST_TRANSFOMATION)
285
- expect { @api.transformation(TEST_TRANSFOMATION) }.to raise_error(Cloudinary::Api::NotFound)
286
- end
287
- end
288
-
289
- it "should allow creating upload_presets" do
290
- expected = {:url => /.*\/upload_presets$/,
291
- [:payload, :name] => "new_preset",
292
- [:payload, :folder] => "some_folder"}
293
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
294
-
295
- @api.create_upload_preset(:name => "new_preset", :folder => "some_folder", :tags => [TEST_TAG, TIMESTAMP_TAG])
296
- end
297
-
298
- describe "upload_presets" do
299
- it 'should not accept parameters' do
300
- expected = {
301
- :url => /.*\/upload_presets/,
302
- [:payload, :next_cursor] => 1234567,
303
- [:payload, :max_results] => 10
304
- }
305
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
306
- @api.upload_presets :next_cursor => 1234567, :max_results => 10
307
-
308
- end
309
- end
310
- it "should allow getting a single upload_preset", :upload_preset => true do
311
- result = @api.create_upload_preset(:unsigned => true, :folder => "folder", :width => 100, :crop => :scale, :tags => ["a","b","c", TEST_TAG, TIMESTAMP_TAG], :context => {:a => "b", :c => "d"})
312
- name = result["name"]
313
- preset = @api.upload_preset(name)
314
- expect(preset["name"]).to eq(name)
315
- expect(preset["unsigned"]).to eq(true)
316
- expect(preset["settings"]["folder"]).to eq("folder")
317
- expect(preset["settings"]["transformation"]).to eq([{"width" => 100, "crop" => "scale"}])
318
- expect(preset["settings"]["context"]).to eq({"a" => "b", "c" => "d"})
319
- expect(preset["settings"]["tags"]).to eq(["a","b","c", TEST_TAG, TIMESTAMP_TAG])
320
- end
321
-
322
- it "should allow deleting upload_presets", :upload_preset => true do
323
- id = "#{prefix}_upload_preset"
324
- @api.create_upload_preset(:name => id, :folder => "folder", :tags => [TEST_TAG, TIMESTAMP_TAG])
325
- preset = @api.upload_preset(id)
326
- @api.delete_upload_preset(id)
327
- expect{preset = @api.upload_preset(id)}.to raise_error(Cloudinary::Api::NotFound)
328
- end
329
-
330
- it "should allow updating upload_presets", :upload_preset => true do
331
- name = @api.create_upload_preset(:folder => "folder", :tags => [TEST_TAG, TIMESTAMP_TAG])["name"]
332
- preset = @api.upload_preset(name)
333
- @api.update_upload_preset(name, preset["settings"].merge(:colors => true, :unsigned => true, :disallow_public_id => true))
334
- preset = @api.upload_preset(name)
335
- expect(preset["name"]).to eq(name)
336
- expect(preset["unsigned"]).to eq(true)
337
- expect(preset["settings"]).to eq({"folder" => "folder", "colors" => true, "disallow_public_id" => true, "tags" => [TEST_TAG, TIMESTAMP_TAG]})
338
- end
339
-
340
- # this test must be last because it deletes (potentially) all dependent transformations which some tests rely on. Excluded by default.
341
- skip "should allow deleting all resources", :delete_all=>true do
342
- Cloudinary::Uploader.upload(TEST_IMG, :public_id=>"api_test5", :eager=>[:width=>101,:crop=>:scale], :tags => [TEST_TAG, TIMESTAMP_TAG])
343
- resource = @api.resource("api_test5")
344
- expect(resource).not_to be_blank
345
- expect(resource["derived"].length).to eq(1)
346
- @api.delete_all_resources(:keep_original => true)
347
- resource = @api.resource("api_test5")
348
- expect(resource).not_to be_blank
349
- expect(resource["derived"].length).to eq(0)
350
- end
351
-
352
- it "should support setting manual moderation status" do
353
- result = Cloudinary::Uploader.upload(TEST_IMG, {:moderation => :manual, :tags => [TEST_TAG, TIMESTAMP_TAG]})
354
- expect(result["moderation"][0]["status"]).to eq("pending")
355
- expect(result["moderation"][0]["kind"]).to eq("manual")
356
- api_result = Cloudinary::Api.update(result["public_id"], {:moderation_status => :approved})
357
- expect(api_result["moderation"][0]["status"]).to eq("approved")
358
- expect(api_result["moderation"][0]["kind"]).to eq("manual")
359
- end
360
-
361
- it "should support requesting raw conversion" do
362
- result = Cloudinary::Uploader.upload("spec/docx.docx", :resource_type => :raw, :tags => [TEST_TAG, TIMESTAMP_TAG])
363
- expect{Cloudinary::Api.update(result["public_id"], {:resource_type => :raw, :raw_convert => :illegal})}.to raise_error(Cloudinary::Api::BadRequest, /^Illegal value|not a valid/)
364
- end
365
-
366
- it "should support requesting categorization" do
367
- result = Cloudinary::Uploader.upload(TEST_IMG, :tags => [TEST_TAG, TIMESTAMP_TAG])
368
- expect{Cloudinary::Api.update(result["public_id"], {:categorization => :illegal})}.to raise_error(Cloudinary::Api::BadRequest, /^Illegal value/)
369
- end
370
-
371
- it "should support requesting detection with server notification", :focus => true do
372
- expected = {
373
- [:payload, :detection] => "adv_face",
374
- [:payload, :notification_url] => "http://example.com"
375
- }
376
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
377
- Cloudinary::Api.update("public_id", {:detection => "adv_face", :notification_url => "http://example.com"})
378
- end
379
-
380
- it "should support requesting auto_tagging" do
381
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :auto_tagging] => 0.5))
382
- Cloudinary::Api.update("public_id", {:auto_tagging => 0.5})
383
- end
384
-
385
- it "should support quality_override" do
386
- ['auto:advanced', 'auto:best', '80:420', 'none'].each do |q|
387
- expected = {[:payload, :quality_override] => q}
388
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value(expected))
389
- Cloudinary::Api.update Pathname.new(TEST_IMG), :quality_override => q
390
- end
391
- end
392
-
393
- it "should support listing by moderation kind and value" do
394
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value([:url] => /.*manual\/approved$/, [:payload, :max_results] => 1000))
395
- Cloudinary::Api.resources_by_moderation(:manual, :approved, :max_results => 1000)
396
- end
397
-
398
- it "should support listing folders" do
399
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:url] => /.*\/folders$/, [:method] => :get))
400
- Cloudinary::Api.root_folders
401
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:url] => /.*\/folders\/test_folder1$/, [:method] => :get))
402
- Cloudinary::Api.subfolders("test_folder1")
403
- end
404
-
405
- it "should throw if folder is missing" do
406
- expect{Cloudinary::Api.subfolders("I_do_not_exist")}.to raise_error(Cloudinary::Api::NotFound)
407
- end
408
-
409
- describe '.restore' do
410
- it 'should restore a deleted resource' do
411
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :public_ids] => "api_test_restore", [:url] => /.*\/restore$/))
412
- Cloudinary::Api.restore("api_test_restore")
413
- end
414
- end
415
-
416
- describe 'create_upload_mapping' do
417
- mapping = "api_test_upload_mapping#{rand(100000)}"
418
- it 'should create mapping' do
419
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :template] => "http://cloudinary.com"))
420
- Cloudinary::Api.create_upload_mapping(mapping, :template =>"http://cloudinary.com")
421
- expect(RestClient::Request).to receive(:execute).with(deep_hash_value( [:payload, :template] => "http://res.cloudinary.com"))
422
- Cloudinary::Api.update_upload_mapping(mapping, "template" =>"http://res.cloudinary.com")
423
- end
424
-
425
-
426
- end
427
- describe "access_mode" do
428
- i = 0
429
-
430
- publicId = ""
431
- access_mode_tag = ''
432
- before(:each) do
433
- i += 1
434
- access_mode_tag = TEST_TAG + "access_mode" + i.to_s
435
- result = Cloudinary::Uploader.upload TEST_IMG, access_mode: "authenticated", tags: [TEST_TAG, TIMESTAMP_TAG, access_mode_tag]
436
- publicId = result["public_id"]
437
- expect(result["access_mode"]).to eq("authenticated")
438
- end
439
-
440
- it "should update access mode by ids" do
441
- result = Cloudinary::Api.update_resources_access_mode_by_ids "public", [publicId]
442
-
443
- expect(result["updated"]).to be_an_instance_of(Array)
444
- expect(result["updated"].length).to eq(1)
445
- resource = result["updated"][0]
446
- expect(resource["public_id"]).to eq(publicId)
447
- expect(resource["access_mode"]).to eq('public')
448
- end
449
- it "should update access mode by prefix" do
450
- result = Cloudinary::Api.update_resources_access_mode_by_prefix "public", publicId[0..-3]
451
-
452
- expect(result["updated"]).to be_an_instance_of(Array)
453
- expect(result["updated"].length).to eq(1)
454
- resource = result["updated"][0]
455
- expect(resource["public_id"]).to eq(publicId)
456
- expect(resource["access_mode"]).to eq('public')
457
- end
458
- it "should update access mode by tag" do
459
- result = Cloudinary::Api.update_resources_access_mode_by_tag "public", access_mode_tag
460
-
461
- expect(result["updated"]).to be_an_instance_of(Array)
462
- expect(result["updated"].length).to eq(1)
463
- resource = result["updated"][0]
464
- expect(resource["public_id"]).to eq(publicId)
465
- expect(resource["access_mode"]).to eq('public')
466
- end
467
- end
468
-
469
- context "resource of type authenticated" do
470
- i = 0
471
- bytes = nil
472
- publicId = ""
473
- publish_resource_tag = "publish_resource_tag"
474
- before(:each) do
475
- i += 1
476
- result = Cloudinary::Uploader.upload TEST_IMG, type: "authenticated", tags: [TEST_TAG, TIMESTAMP_TAG, publish_resource_tag], transformation: {width: 100*i, crop: "scale"}
477
- publicId = result["public_id"]
478
- expect(result["type"]).to eq("authenticated")
479
- end
480
-
481
- it "should publish resources by ids" do
482
- result = Cloudinary::Api.publish_by_ids( [publicId])
483
-
484
- expect(result["published"]).to be_an_instance_of(Array)
485
- expect(result["published"].length).to eq(1)
486
-
487
- resource = result["published"][0]
488
-
489
- expect(resource["public_id"]).to eq(publicId)
490
- expect(resource["type"]).to eq('upload')
491
-
492
- bytes = resource["bytes"]
493
- end
494
- it "should publish resources by prefix and overwrite" do
495
- result = Cloudinary::Api.publish_by_prefix(publicId[0..-3], overwrite: true)
496
-
497
- expect(result["published"]).to be_an_instance_of(Array)
498
- expect(result["published"].length).to eq(1)
499
-
500
- resource = result["published"][0]
501
-
502
- expect(resource["public_id"]).to eq(publicId)
503
- expect(resource["bytes"]).not_to eq(bytes)
504
- expect(resource["type"]).to eq('upload')
505
-
506
- bytes = resource["bytes"]
507
- end
508
- it "should publish resources by tag and overwrite" do
509
- result = Cloudinary::Api.publish_by_tag(publish_resource_tag, overwrite: true)
510
-
511
- expect(result["published"]).to be_an_instance_of(Array)
512
- expect(result["published"].length).to eq(1)
513
-
514
- resource = result["published"][0]
515
-
516
- expect(resource["public_id"]).to eq(publicId)
517
- expect(resource["bytes"]).not_to eq(bytes)
518
- expect(resource["type"]).to eq('upload')
519
-
520
- bytes = resource["bytes"]
521
- end
522
- end
523
- describe "json breakpoints" do
524
- it "should retrieve breakpoints as json array" do
525
- bp = Cloudinary::Api.get_breakpoints(test_id_1, srcset: {min_width:10, max_width:2000, bytes_step: 10, max_images: 20})
526
- expect(bp).to be_truthy
527
- end
528
- end
529
- end
530
-
531
- describe Cloudinary::Api::Response do
532
- let(:api_response) { described_class.new }
533
-
534
- shared_examples 'a Hash' do
535
- it 'inherits from Hash' do
536
- expect(api_response).to be_a Hash
537
- end
538
- end
539
-
540
- context 'when there is no argument given on instantiation' do
541
- it 'does not raise an error' do
542
- expect { api_response }.to_not raise_error
543
- end
544
-
545
- it_behaves_like 'a Hash'
546
- end
547
-
548
- context 'when the response is nil' do
549
- it 'does not raise an error' do
550
- expect { described_class.new nil }.to_not raise_error
551
- end
552
-
553
- it_behaves_like 'a Hash'
554
- end
555
-
556
- context 'when the response is present' do
557
- let(:body) { { 'foo' => 'bar' } }
558
- let(:http_response) { double code: 200, body: body.to_json, headers: { x_featureratelimit_reset: Time.new.to_s } }
559
- let(:api_response) { described_class.new http_response }
560
-
561
- it 'sets the instantiated self as the parsed response which is a Hash' do
562
- expect(api_response).to eq body
563
- end
564
-
565
- it_behaves_like 'a Hash'
566
- end
567
- end