From 6a658dab52551920e374aca15ba699eecb358486 Mon Sep 17 00:00:00 2001 From: Eirini Galati Date: Wed, 4 Nov 2026 10:51:44 +0100 Subject: [PATCH 1/2] feat: add Format constants for convert media types, release 1.9.0 Adds a Format namespace of media-type string constants so the types accepted by convert() are discoverable via autocomplete, including JPEG XL (image/jxl), which the API already accepts. String constants rather than a language-level enum: the JSON body must carry the media type verbatim, and an enum would serialize as its name. Existing callers passing raw strings are unaffected. JPG documents image/jpg as the alternative spelling the API also accepts. It normalises to image/jpeg before conversion, so the two constants hold different strings but select the same format. Bumps to 1.9.0, promotes the changelog entry out of Unreleased, and updates Gemfile.lock to match -- bundler runs frozen in CI and exits 16 when the lockfile still pins the previous version. The change is additive, so this is a minor release; nothing is published until the matching tag is pushed. --- CHANGELOG.md | 4 +++ Gemfile.lock | 2 +- lib/tinify.rb | 1 + lib/tinify/format.rb | 39 ++++++++++++++++++++++++++ lib/tinify/version.rb | 2 +- test/tinify_format_test.rb | 56 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 lib/tinify/format.rb create mode 100644 test/tinify_format_test.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 1aef02f..88dfbc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.0 + +* Added `Tinify::Format` constants for the media types `convert` accepts, including JPEG XL (`image/jxl`). + ## 1.8.0 * Update development dependencies. diff --git a/Gemfile.lock b/Gemfile.lock index cc3d042..7dc7bcf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - tinify (1.8.0) + tinify (1.9.0) httpclient (>= 2.9, < 3) GEM diff --git a/lib/tinify.rb b/lib/tinify.rb index 9fbc4a4..f1e7b8f 100644 --- a/lib/tinify.rb +++ b/lib/tinify.rb @@ -1,5 +1,6 @@ require "tinify/version" require "tinify/error" +require "tinify/format" require "tinify/client" require "tinify/result_meta" diff --git a/lib/tinify/format.rb b/lib/tinify/format.rb new file mode 100644 index 0000000..6e60900 --- /dev/null +++ b/lib/tinify/format.rb @@ -0,0 +1,39 @@ +module Tinify + # Media types that images can be converted to. + # + # Use these constants with Source#convert: + # + # Tinify.from_file("input.png") + # .convert(type: Tinify::Format::JXL) + # .to_file("output.jxl") + # + # Multiple types may be supplied, in which case the API returns the smallest + # result: + # + # convert(type: [Tinify::Format::JXL, Tinify::Format::WEBP]) + module Format + # WebP. + WEBP = "image/webp".freeze + + # PNG. + PNG = "image/png".freeze + + # JPEG. + JPEG = "image/jpeg".freeze + + # JPEG, under the alternative image/jpg media type the API also accepts. + # The API normalises this to image/jpeg, so the result is identical to + # JPEG. The two constants hold different strings but select the same + # format. + JPG = "image/jpg".freeze + + # AVIF. + AVIF = "image/avif".freeze + + # JPEG XL. + JXL = "image/jxl".freeze + + # Wildcard, returns the smallest of the supported types. + ANY = "*/*".freeze + end +end diff --git a/lib/tinify/version.rb b/lib/tinify/version.rb index 472ed08..f926f6d 100644 --- a/lib/tinify/version.rb +++ b/lib/tinify/version.rb @@ -1,3 +1,3 @@ module Tinify - VERSION = "1.8.0" + VERSION = "1.9.0" end diff --git a/test/tinify_format_test.rb b/test/tinify_format_test.rb new file mode 100644 index 0000000..94420bf --- /dev/null +++ b/test/tinify_format_test.rb @@ -0,0 +1,56 @@ +require File.expand_path("../helper", __FILE__) + +describe Tinify::Format do + describe "constants" do + it "should expose the supported media types" do + assert_equal "image/webp", Tinify::Format::WEBP + assert_equal "image/png", Tinify::Format::PNG + assert_equal "image/jpeg", Tinify::Format::JPEG + assert_equal "image/jpg", Tinify::Format::JPG + assert_equal "image/avif", Tinify::Format::AVIF + assert_equal "image/jxl", Tinify::Format::JXL + assert_equal "*/*", Tinify::Format::ANY + end + end + + describe "convert" do + before do + Tinify.key = "valid" + + stub_request(:post, "https://api.tinify.com/shrink") + .with(basic_auth: ['api', 'valid']) + .to_return( + status: 201, + headers: { Location: "https://api.tinify.com/some/location" }, + body: '{}') + end + + it "should serialize a single format" do + stub_request(:post, "https://api.tinify.com/some/location") + .with( + basic_auth: ['api', 'valid'], + body: '{"convert":{"type":"image/jxl"}}') + .to_return( + status: 200, + body: "converted file") + + source = Tinify::Source.from_buffer("png file") + .convert(type: Tinify::Format::JXL) + assert_equal "converted file", source.to_buffer + end + + it "should serialize multiple formats" do + stub_request(:post, "https://api.tinify.com/some/location") + .with( + basic_auth: ['api', 'valid'], + body: '{"convert":{"type":["image/jxl","image/webp"]}}') + .to_return( + status: 200, + body: "converted file") + + source = Tinify::Source.from_buffer("png file") + .convert(type: [Tinify::Format::JXL, Tinify::Format::WEBP]) + assert_equal "converted file", source.to_buffer + end + end +end From bfb5f19f80d7ad0dcc1dcd98745dd2ac1d677a3d Mon Sep 17 00:00:00 2001 From: Eirini Galati Date: Wed, 4 Nov 2026 14:53:00 +0100 Subject: [PATCH 2/2] docs: document the Format constants in the README The README only showed compression, so the constants this release adds had no example outside the API docs site. Adds a convert example using Tinify::Format, the multiple-types case, and a note that the plain strings still work. --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 4be21f1..bd21edc 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,27 @@ Tinify.key = "YOUR_API_KEY" Tinify.from_file("unoptimized.png").to_file("optimized.png") ``` +Convert to another format with the `Tinify::Format` constants (`WEBP`, `PNG`, +`JPEG`, `JPG`, `AVIF`, `JXL` and `ANY`): + +```ruby +Tinify.from_file("unoptimized.png") + .convert(type: Tinify::Format::JXL) + .to_file("optimized.jxl") +``` + +Pass several and the API returns the smallest result: + +```ruby +result = Tinify.from_file("unoptimized.png") + .convert(type: [Tinify::Format::JXL, Tinify::Format::WEBP]) + .result + +result.to_file("optimized.#{result.extension}") +``` + +The constants are plain strings, so `type: "image/jxl"` keeps working. + ## Running tests ```