From 78d3fcff3278d934f59dd5b7d3c57964c3c2c21d Mon Sep 17 00:00:00 2001 From: RTLcoil Date: Mon, 22 Apr 2019 16:18:01 +0300 Subject: [PATCH] Support different radius for each corner (containing images and overlays) --- lib-es5/utils/index.js | 27 ++++++++++++++++++++++++++- lib/utils/index.js | 27 +++++++++++++++++++++++++-- test/cloudinary_spec.js | 37 +++++++++++++++++++++++++++++++++++++ test/utils_spec.js | 20 ++++++++++++++++++++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/lib-es5/utils/index.js b/lib-es5/utils/index.js index d9604b73..0daf50a7 100644 --- a/lib-es5/utils/index.js +++ b/lib-es5/utils/index.js @@ -299,6 +299,30 @@ function process_layer(layer) { return result; } +/** + * Parse radius options + * @private + * @param {Array|string|number} radius The radius to parse + * @return {string} radius transformation string + */ +function process_radius(radius) { + if (!radius) { + return radius; + } + if (!isArray(radius)) { + radius = [radius]; + } + if (radius.length === 0 || radius.length > 4) { + throw new Error("Radius array should contain between 1 and 4 values"); + } + if (radius.findIndex(function (x) { + return x === null; + }) >= 0) { + throw new Error("Corner: Cannot be null"); + } + return radius.map(normalize_expression).join(':'); +} + function base64EncodeURL(url) { var ignore; try { @@ -545,6 +569,7 @@ exports.generate_transformation_string = function generate_transformation_string options["end_offset"] = _split_range2[1]; } var overlay = process_layer(utils.option_consume(options, "overlay")); + var radius = process_radius(utils.option_consume(options, "radius")); var underlay = process_layer(utils.option_consume(options, "underlay")); var ifValue = process_if(utils.option_consume(options, "if")); var fps = utils.option_consume(options, 'fps'); @@ -567,7 +592,7 @@ exports.generate_transformation_string = function generate_transformation_string l: overlay, o: normalize_expression(utils.option_consume(options, "opacity")), q: normalize_expression(utils.option_consume(options, "quality")), - r: normalize_expression(utils.option_consume(options, "radius")), + r: radius, t: named_transformation, u: underlay, w: normalize_expression(width), diff --git a/lib/utils/index.js b/lib/utils/index.js index bcf7c385..f4bb2260 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -295,6 +295,28 @@ function process_layer(layer) { return result; } +/** + * Parse radius options + * @private + * @param {Array|string|number} radius The radius to parse + * @return {string} radius transformation string + */ +function process_radius(radius) { + if (!radius) { + return radius; + } + if (!isArray(radius)) { + radius = [radius]; + } + if (radius.length === 0 || radius.length > 4) { + throw new Error("Radius array should contain between 1 and 4 values"); + } + if (radius.findIndex(x => x === null) >= 0) { + throw new Error("Corner: Cannot be null"); + } + return radius.map(normalize_expression).join(':'); +} + function base64EncodeURL(url) { var ignore; try { @@ -552,10 +574,11 @@ exports.generate_transformation_string = function generate_transformation_string [options["start_offset"], options["end_offset"]] = split_range(utils.option_consume(options, "offset")); } let overlay = process_layer(utils.option_consume(options, "overlay")); + let radius = process_radius(utils.option_consume(options, "radius")); let underlay = process_layer(utils.option_consume(options, "underlay")); let ifValue = process_if(utils.option_consume(options, "if")); let fps = utils.option_consume(options, 'fps'); - if(isArray(fps)){ + if (isArray(fps)){ fps = fps.join('-'); } let params = { @@ -574,7 +597,7 @@ exports.generate_transformation_string = function generate_transformation_string l: overlay, o: normalize_expression(utils.option_consume(options, "opacity")), q: normalize_expression(utils.option_consume(options, "quality")), - r: normalize_expression(utils.option_consume(options, "radius")), + r: radius, t: named_transformation, u: underlay, w: normalize_expression(width), diff --git a/test/cloudinary_spec.js b/test/cloudinary_spec.js index 8120be8d..6aede357 100644 --- a/test/cloudinary_spec.js +++ b/test/cloudinary_spec.js @@ -181,6 +181,43 @@ describe("cloudinary", function() { }), `${upload_path}/g_center,p_a,q_auto:good,r_3,x_1,y_2/test`); }); }); + describe(":radius", function() { + const upload_path = 'http://res.cloudinary.com/test123/image/upload'; + it("should support a single value", function() { + expect(cloudinary.utils.url("test", { + radius: 10 + })).to.eql(`${upload_path}/r_10/test`); + expect(cloudinary.utils.url("test", { + radius: '10' + })).to.eql(`${upload_path}/r_10/test`); + expect(cloudinary.utils.url("test", { + variables: [['$v', 10]], + radius: '$v', + })).to.eql(`${upload_path}/$v_10,r_$v/test`); + }); + it("should support an array of values", function() { + expect(cloudinary.utils.url("test", { + radius: [10,20,30] + })).to.eql(`${upload_path}/r_10:20:30/test`); + expect(cloudinary.utils.url("test", { + variables: [['$v', 10]], + radius: [10,20,'$v'], + })).to.eql(`${upload_path}/$v_10,r_10:20:$v/test`); + expect(cloudinary.utils.url("test", { + variables: [['$v', 10]], + radius: [10,20,'$v',40], + })).to.eql(`${upload_path}/$v_10,r_10:20:$v:40/test`); + }) + it("should support colon separated values", function() { + expect(cloudinary.utils.url("test", { + radius: "10:20" + })).to.eql(`${upload_path}/r_10:20/test`); + expect(cloudinary.utils.url("test", { + variables: [['$v', 10]], + radius: "10:20:$v:40" + })).to.eql(`${upload_path}/$v_10,r_10:20:$v:40/test`); + }) + }) it("should support named transformation", function() { var options, result; options = { diff --git a/test/utils_spec.js b/test/utils_spec.js index f1913593..8c0d523d 100644 --- a/test/utils_spec.js +++ b/test/utils_spec.js @@ -340,6 +340,25 @@ describe("utils", function () { angle: 'auto' }, `http://res.cloudinary.com/${cloud_name}/image/upload/a_auto,c_scale,h_100,w_100/test`, {}); }); + it("should disallow radius arrays that contain 0 or more than 4 values", function () { + expect(function () { + return utils.url("test", { + radius: [10, 20, 30, 10, 20] + }); + }).to.throwError(/Radius array should contain between 1 and 4 values/); + expect(function () { + return utils.url("test", { + radius: [] + }); + }).to.throwError(/Radius array should contain between 1 and 4 values/); + }); + it("should disallow radius arrays containing null values", function () { + expect(function () { + return utils.url("test", { + radius: [null, 20, 30, 10] + }); + }).to.throwError(/Corner: Cannot be null/); + }); it("should use x, y, radius, prefix, gravity and quality from options", function () { test_cloudinary_url("test", { x: 1, @@ -1438,3 +1457,4 @@ describe("utils", function () { }) }); +