imgproxy 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +8 -0
- data/CHANGELOG.md +74 -0
- data/README.md +176 -135
- data/UPGRADE.md +136 -0
- data/docs/info_options.md +223 -0
- data/docs/processing_options.md +724 -0
- data/docs/yard/fix_pictures.rb +25 -0
- data/docs/yard/github_alerts.rb +16 -0
- data/docs/yard/relative_markdown_links.rb +31 -0
- data/lib/imgproxy/config.rb +96 -41
- data/lib/imgproxy/extensions/active_storage.rb +6 -4
- data/lib/imgproxy/extensions/shrine.rb +6 -4
- data/lib/imgproxy/option_aliases/info.rb +33 -0
- data/lib/imgproxy/option_aliases/processing.rb +74 -0
- data/lib/imgproxy/options_builders/base.rb +54 -0
- data/lib/imgproxy/options_builders/info.rb +52 -0
- data/lib/imgproxy/options_builders/processing.rb +150 -0
- data/lib/imgproxy/options_casters/adjust.rb +3 -1
- data/lib/imgproxy/options_casters/alpha.rb +27 -0
- data/lib/imgproxy/options_casters/array.rb +3 -1
- data/lib/imgproxy/options_casters/autoquality.rb +28 -0
- data/lib/imgproxy/options_casters/average.rb +27 -0
- data/lib/imgproxy/options_casters/background.rb +27 -0
- data/lib/imgproxy/options_casters/base64.rb +2 -0
- data/lib/imgproxy/options_casters/blur_detections.rb +28 -0
- data/lib/imgproxy/options_casters/blurhash.rb +21 -0
- data/lib/imgproxy/options_casters/bool.rb +3 -1
- data/lib/imgproxy/options_casters/crop.rb +3 -1
- data/lib/imgproxy/options_casters/dominant_colors.rb +27 -0
- data/lib/imgproxy/options_casters/draw_detections.rb +28 -0
- data/lib/imgproxy/options_casters/extend.rb +3 -1
- data/lib/imgproxy/options_casters/filename.rb +31 -0
- data/lib/imgproxy/options_casters/float.rb +3 -1
- data/lib/imgproxy/options_casters/format_quality.rb +19 -0
- data/lib/imgproxy/options_casters/gradient.rb +31 -0
- data/lib/imgproxy/options_casters/gravity.rb +20 -6
- data/lib/imgproxy/options_casters/group.rb +2 -0
- data/lib/imgproxy/options_casters/hashsum.rb +24 -0
- data/lib/imgproxy/options_casters/integer.rb +2 -0
- data/lib/imgproxy/options_casters/jpeg_options.rb +3 -1
- data/lib/imgproxy/options_casters/padding.rb +41 -0
- data/lib/imgproxy/options_casters/png_options.rb +3 -1
- data/lib/imgproxy/options_casters/resize.rb +3 -1
- data/lib/imgproxy/options_casters/size.rb +3 -1
- data/lib/imgproxy/options_casters/string.rb +2 -0
- data/lib/imgproxy/options_casters/trim.rb +3 -1
- data/lib/imgproxy/options_casters/unsharp_masking.rb +25 -0
- data/lib/imgproxy/options_casters/video_thumbnail_tile.rb +34 -0
- data/lib/imgproxy/options_casters/watermark.rb +5 -4
- data/lib/imgproxy/options_casters/watermark_size.rb +21 -0
- data/lib/imgproxy/options_casters/{gif_options.rb → webp_options.rb} +6 -5
- data/lib/imgproxy/options_casters/zoom.rb +27 -0
- data/lib/imgproxy/service_config.rb +111 -0
- data/lib/imgproxy/trim_array.rb +2 -0
- data/lib/imgproxy/url_adapters/active_storage.rb +2 -0
- data/lib/imgproxy/url_adapters/shrine.rb +8 -2
- data/lib/imgproxy/url_adapters.rb +3 -0
- data/lib/imgproxy/url_builders/base.rb +184 -0
- data/lib/imgproxy/url_builders/info.rb +44 -0
- data/lib/imgproxy/url_builders/processing.rb +59 -0
- data/lib/imgproxy/version.rb +3 -1
- data/lib/imgproxy.rb +19 -57
- data/logo/logo-dark.svg +22 -0
- data/logo/logo-light.svg +31 -0
- metadata +70 -32
- data/lib/imgproxy/builder.rb +0 -140
- data/lib/imgproxy/options.rb +0 -119
- data/lib/imgproxy/options_aliases.rb +0 -45
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "imgproxy/options_casters/integer"
|
4
|
+
require "imgproxy/options_casters/bool"
|
5
|
+
require "imgproxy/options_casters/extend"
|
6
|
+
|
7
|
+
module Imgproxy
|
8
|
+
module OptionsCasters
|
9
|
+
# Casts `watermark_size` processing option
|
10
|
+
module WatermarkSize
|
11
|
+
def self.cast(raw)
|
12
|
+
return raw unless raw.is_a?(Hash)
|
13
|
+
|
14
|
+
[
|
15
|
+
Imgproxy::OptionsCasters::Integer.cast(raw[:width]) || 0,
|
16
|
+
Imgproxy::OptionsCasters::Integer.cast(raw[:height]) || 0,
|
17
|
+
]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "imgproxy/options_casters/group"
|
2
|
-
require "imgproxy/options_casters/
|
4
|
+
require "imgproxy/options_casters/string"
|
3
5
|
|
4
6
|
module Imgproxy
|
5
7
|
module OptionsCasters
|
6
|
-
# Casts
|
7
|
-
module
|
8
|
+
# Casts `webp_options` processing option
|
9
|
+
module WebpOptions
|
8
10
|
CASTER = Imgproxy::OptionsCasters::Group.new(
|
9
|
-
|
10
|
-
optimize_transparency: Imgproxy::OptionsCasters::Bool,
|
11
|
+
compression: Imgproxy::OptionsCasters::String,
|
11
12
|
).freeze
|
12
13
|
|
13
14
|
def self.cast(raw)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "imgproxy/trim_array"
|
4
|
+
require "imgproxy/options_casters/float"
|
5
|
+
|
6
|
+
module Imgproxy
|
7
|
+
module OptionsCasters
|
8
|
+
# Casts `zoom` info option
|
9
|
+
module Zoom
|
10
|
+
using TrimArray
|
11
|
+
|
12
|
+
def self.cast(raw)
|
13
|
+
# Allow zoom to be just a float
|
14
|
+
return Imgproxy::OptionsCasters::Float.cast(raw) if raw.is_a?(Numeric)
|
15
|
+
|
16
|
+
return raw unless raw.is_a?(Hash)
|
17
|
+
|
18
|
+
return Imgproxy::OptionsCasters::Float.cast(raw[:zoom_x_y]) if raw.key?(:zoom_x_y)
|
19
|
+
|
20
|
+
[
|
21
|
+
Imgproxy::OptionsCasters::Float.cast(raw[:zoom_x]) || 1,
|
22
|
+
Imgproxy::OptionsCasters::Float.cast(raw[:zoom_y]) || 1,
|
23
|
+
].trim!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "anyway_config"
|
4
|
+
|
5
|
+
module Imgproxy
|
6
|
+
# Imgproxy custom config for services
|
7
|
+
#
|
8
|
+
# @!attribute endpoint
|
9
|
+
# imgproxy endpoint
|
10
|
+
# @return [String]
|
11
|
+
# @!attribute key
|
12
|
+
# imgproxy hex-encoded signature key
|
13
|
+
# @return [String]
|
14
|
+
# @!attribute salt
|
15
|
+
# imgproxy hex-encoded signature salt
|
16
|
+
# @return [String]
|
17
|
+
# @!attribute raw_key
|
18
|
+
# Decoded signature key
|
19
|
+
# @return [String]
|
20
|
+
# @!attribute raw_salt
|
21
|
+
# Decoded signature salt
|
22
|
+
# @return [String]
|
23
|
+
# @!attribute signature_size
|
24
|
+
# imgproxy signature size. Defaults to 32
|
25
|
+
# @return [String]
|
26
|
+
# @!attribute source_url_encryption_key
|
27
|
+
# imgproxy hex-encoded source URL encryption key
|
28
|
+
# @return [String]
|
29
|
+
# @!attribute raw_source_url_encryption_key
|
30
|
+
# Decoded source URL encryption key
|
31
|
+
# @return [String]
|
32
|
+
# @!attribute always_encrypt_source_urls
|
33
|
+
# Always encrypt source URLs. Defaults to false
|
34
|
+
# @return [String]
|
35
|
+
#
|
36
|
+
# @see Imgproxy::Config
|
37
|
+
class ServiceConfig < Anyway::Config
|
38
|
+
# Inherit global config values
|
39
|
+
config_name :imgproxy
|
40
|
+
|
41
|
+
attr_config(
|
42
|
+
:endpoint,
|
43
|
+
:key,
|
44
|
+
:salt,
|
45
|
+
:raw_key,
|
46
|
+
:raw_salt,
|
47
|
+
:source_url_encryption_key,
|
48
|
+
:raw_source_url_encryption_key,
|
49
|
+
signature_size: 32,
|
50
|
+
always_encrypt_source_urls: false,
|
51
|
+
)
|
52
|
+
|
53
|
+
coerce_types(
|
54
|
+
endpoint: :string,
|
55
|
+
key: :string,
|
56
|
+
salt: :string,
|
57
|
+
raw_key: :string,
|
58
|
+
raw_salt: :string,
|
59
|
+
signature_size: :integer,
|
60
|
+
source_url_encryption_key: :string,
|
61
|
+
raw_source_url_encryption_key: :string,
|
62
|
+
always_encrypt_source_urls: :boolean,
|
63
|
+
)
|
64
|
+
|
65
|
+
alias_method :set_key, :key=
|
66
|
+
alias_method :set_raw_key, :raw_key=
|
67
|
+
alias_method :set_salt, :salt=
|
68
|
+
alias_method :set_raw_salt, :raw_salt=
|
69
|
+
alias_method :set_source_url_encryption_key, :source_url_encryption_key=
|
70
|
+
alias_method :set_raw_source_url_encryption_key, :raw_source_url_encryption_key=
|
71
|
+
|
72
|
+
private :set_key, :set_raw_key, :set_salt, :set_raw_salt,
|
73
|
+
:set_source_url_encryption_key, :set_raw_source_url_encryption_key
|
74
|
+
|
75
|
+
def key=(value)
|
76
|
+
value = value&.to_s
|
77
|
+
super(value)
|
78
|
+
set_raw_key(value && [value].pack("H*"))
|
79
|
+
end
|
80
|
+
|
81
|
+
def raw_key=(value)
|
82
|
+
value = value&.to_s
|
83
|
+
super(value)
|
84
|
+
set_key(value&.unpack!("H*"))
|
85
|
+
end
|
86
|
+
|
87
|
+
def salt=(value)
|
88
|
+
value = value&.to_s
|
89
|
+
super(value)
|
90
|
+
set_raw_salt(value && [value].pack("H*"))
|
91
|
+
end
|
92
|
+
|
93
|
+
def raw_salt=(value)
|
94
|
+
value = value&.to_s
|
95
|
+
super(value)
|
96
|
+
set_salt(value&.unpack1("H*"))
|
97
|
+
end
|
98
|
+
|
99
|
+
def source_url_encryption_key=(value)
|
100
|
+
value = value&.to_s
|
101
|
+
super(value)
|
102
|
+
set_raw_source_url_encryption_key(value && [value].pack("H*"))
|
103
|
+
end
|
104
|
+
|
105
|
+
def raw_source_url_encryption_key=(value)
|
106
|
+
value = value&.to_s
|
107
|
+
super(value)
|
108
|
+
set_source_url_encryption_key(value&.unpack1("H*"))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/lib/imgproxy/trim_array.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Imgproxy
|
2
4
|
class UrlAdapters
|
3
5
|
# Adapter for Shrine
|
@@ -16,7 +18,7 @@ module Imgproxy
|
|
16
18
|
return s3_url(image) if use_s3_url(image)
|
17
19
|
|
18
20
|
opts = {}
|
19
|
-
opts[:host] =
|
21
|
+
opts[:host] = config.shrine_host if config.shrine_host
|
20
22
|
image.url(**opts)
|
21
23
|
end
|
22
24
|
|
@@ -28,9 +30,13 @@ module Imgproxy
|
|
28
30
|
end
|
29
31
|
|
30
32
|
def use_s3_url(image)
|
31
|
-
|
33
|
+
config.use_s3_urls &&
|
32
34
|
image.storage.is_a?(::Shrine::Storage::S3)
|
33
35
|
end
|
36
|
+
|
37
|
+
def config
|
38
|
+
Imgproxy.config
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
36
42
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "imgproxy/url_adapters/active_storage"
|
2
4
|
require "imgproxy/url_adapters/shrine"
|
3
5
|
|
@@ -11,6 +13,7 @@ module Imgproxy
|
|
11
13
|
# Imgproxy.url_for(user.avatar)
|
12
14
|
class UrlAdapters
|
13
15
|
class NotFound < StandardError; end
|
16
|
+
|
14
17
|
class NotConfigured < StandardError; end
|
15
18
|
|
16
19
|
# @return [Array] Currently added adapters
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "openssl"
|
4
|
+
require "base64"
|
5
|
+
require "erb"
|
6
|
+
|
7
|
+
require "imgproxy/options_builders/base"
|
8
|
+
|
9
|
+
module Imgproxy
|
10
|
+
module UrlBuilders
|
11
|
+
class UnknownServiceError < StandardError; end
|
12
|
+
|
13
|
+
class InvalidEncryptionKeyError < StandardError; end
|
14
|
+
|
15
|
+
# Builds imgproxy URL
|
16
|
+
#
|
17
|
+
# builder = Imgproxy::UrlBuilders::Base.new(
|
18
|
+
# width: 500,
|
19
|
+
# height: 400,
|
20
|
+
# resizing_type: :fill,
|
21
|
+
# sharpen: 0.5
|
22
|
+
# )
|
23
|
+
#
|
24
|
+
# builder.url_for("http://images.example.com/images/image1.jpg")
|
25
|
+
# builder.url_for("http://images.example.com/images/image2.jpg")
|
26
|
+
class Base
|
27
|
+
OPTIONS_BUILDER = OptionsBuilders::Base
|
28
|
+
OPTION_ALIASES = {}.freeze
|
29
|
+
|
30
|
+
# @param [Hash] options imgproxy URL options
|
31
|
+
# @see Imgproxy.url_for
|
32
|
+
# @see Imgproxy.info_url_for
|
33
|
+
def initialize(options = {})
|
34
|
+
options = options.dup
|
35
|
+
|
36
|
+
extract_builder_options(options)
|
37
|
+
|
38
|
+
@options = self.class::OPTIONS_BUILDER.new(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Genrates imgproxy URL
|
42
|
+
#
|
43
|
+
# @return [String] imgproxy URL
|
44
|
+
# @param [String,URI, Object] _image Source image URL or object applicable for
|
45
|
+
# the configured URL adapters
|
46
|
+
# @see Imgproxy.url_for
|
47
|
+
# @see Imgproxy.info_url_for
|
48
|
+
def url_for(_image)
|
49
|
+
raise NotImplementedError
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_reader :service
|
55
|
+
|
56
|
+
NEED_ESCAPE_RE = /[@?% ]|[^\p{Ascii}]/.freeze
|
57
|
+
AES_SIZES = {32 => 256, 24 => 196, 16 => 128}.freeze
|
58
|
+
|
59
|
+
def extract_builder_options(options)
|
60
|
+
@service = options.delete(:service)&.to_sym || :default
|
61
|
+
|
62
|
+
@use_short_options =
|
63
|
+
not_nil_or(options.delete(:use_short_options), config.use_short_options)
|
64
|
+
@base64_encode_url =
|
65
|
+
not_nil_or(options.delete(:base64_encode_url), config.base64_encode_urls)
|
66
|
+
@escape_plain_url =
|
67
|
+
not_nil_or(options.delete(:escape_plain_url), config.always_escape_plain_urls)
|
68
|
+
@encrypt_source_url =
|
69
|
+
not_nil_or(options.delete(:encrypt_source_url), service_config.always_encrypt_source_urls)
|
70
|
+
@source_url_encryption_iv = options.delete(:source_url_encryption_iv)
|
71
|
+
end
|
72
|
+
|
73
|
+
def option_strings
|
74
|
+
@option_strings ||= @options.map do |key, value|
|
75
|
+
[option_alias(key), value].join(":")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def sourcce_url(image, ext: nil)
|
80
|
+
url = config.url_adapters.url_of(image)
|
81
|
+
|
82
|
+
return encrypted_sourcce_url_for(url, ext: ext) if @encrypt_source_url
|
83
|
+
return base64_sourcce_url_for(url, ext: ext) if @base64_encode_url
|
84
|
+
plain_url_for(url, ext: ext)
|
85
|
+
end
|
86
|
+
|
87
|
+
def plain_url_for(url, ext: nil)
|
88
|
+
escaped_url = need_escape_url?(url) ? ERB::Util.url_encode(url) : url
|
89
|
+
|
90
|
+
ext ? "plain/#{escaped_url}@#{ext}" : "plain/#{escaped_url}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def base64_sourcce_url_for(url, ext: nil)
|
94
|
+
encoded_url = Base64.urlsafe_encode64(url).tr("=", "").scan(/.{1,16}/).join("/")
|
95
|
+
|
96
|
+
ext ? "#{encoded_url}.#{ext}" : encoded_url
|
97
|
+
end
|
98
|
+
|
99
|
+
def encrypted_sourcce_url_for(url, ext: nil)
|
100
|
+
cipher = build_cipher
|
101
|
+
|
102
|
+
iv = @source_url_encryption_iv || cipher.random_iv
|
103
|
+
cipher.iv = iv
|
104
|
+
|
105
|
+
"enc/#{base64_sourcce_url_for(iv + cipher.update(url) + cipher.final, ext: ext)}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def need_escape_url?(url)
|
109
|
+
@escape_plain_url || url.match?(NEED_ESCAPE_RE)
|
110
|
+
end
|
111
|
+
|
112
|
+
def build_cipher
|
113
|
+
key = encryption_key.to_s
|
114
|
+
|
115
|
+
aes_size = AES_SIZES.fetch(key.length) do
|
116
|
+
raise Imgproxy::UrlBuilders::InvalidEncryptionKeyError,
|
117
|
+
"Encryption key should be 16/24/32 bytes long, now - #{key.length}"
|
118
|
+
end
|
119
|
+
|
120
|
+
OpenSSL::Cipher::AES.new(aes_size, :CBC).tap do |cipher|
|
121
|
+
cipher.encrypt
|
122
|
+
cipher.key = key
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def option_alias(name)
|
127
|
+
return name unless @use_short_options
|
128
|
+
|
129
|
+
self.class::OPTION_ALIASES.fetch(name, name)
|
130
|
+
end
|
131
|
+
|
132
|
+
def sign_path(path)
|
133
|
+
return "unsafe" unless ready_to_sign?
|
134
|
+
|
135
|
+
digest = OpenSSL::HMAC.digest(
|
136
|
+
OpenSSL::Digest.new("sha256"),
|
137
|
+
signature_key,
|
138
|
+
"#{signature_salt}/#{path}",
|
139
|
+
)[0, signature_size]
|
140
|
+
|
141
|
+
Base64.urlsafe_encode64(digest).tr("=", "")
|
142
|
+
end
|
143
|
+
|
144
|
+
def ready_to_sign?
|
145
|
+
!(signature_key.nil? || signature_salt.nil? ||
|
146
|
+
signature_key.empty? || signature_salt.empty?)
|
147
|
+
end
|
148
|
+
|
149
|
+
def signature_key
|
150
|
+
service_config.raw_key
|
151
|
+
end
|
152
|
+
|
153
|
+
def signature_salt
|
154
|
+
service_config.raw_salt
|
155
|
+
end
|
156
|
+
|
157
|
+
def signature_size
|
158
|
+
service_config.signature_size
|
159
|
+
end
|
160
|
+
|
161
|
+
def encryption_key
|
162
|
+
service_config.raw_source_url_encryption_key
|
163
|
+
end
|
164
|
+
|
165
|
+
def not_nil_or(value, fallback)
|
166
|
+
value.nil? ? fallback : value
|
167
|
+
end
|
168
|
+
|
169
|
+
def endpoint
|
170
|
+
service_config.endpoint
|
171
|
+
end
|
172
|
+
|
173
|
+
def service_config
|
174
|
+
@service_config ||= config.services[service].tap do |c|
|
175
|
+
raise Imgproxy::UrlBuilders::UnknownServiceError, service unless c
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def config
|
180
|
+
Imgproxy.config
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "imgproxy/option_aliases/info"
|
4
|
+
require "imgproxy/options_builders/info"
|
5
|
+
require "imgproxy/url_builders/base"
|
6
|
+
|
7
|
+
module Imgproxy
|
8
|
+
module UrlBuilders
|
9
|
+
# Builds imgproxy info URL
|
10
|
+
#
|
11
|
+
# builder = Imgproxy::UrlBuilders::Info.new(
|
12
|
+
# width: 500,
|
13
|
+
# height: 400,
|
14
|
+
# resizing_type: :fill,
|
15
|
+
# sharpen: 0.5
|
16
|
+
# )
|
17
|
+
#
|
18
|
+
# builder.url_for("http://images.example.com/images/image1.jpg")
|
19
|
+
# builder.url_for("http://images.example.com/images/image2.jpg")
|
20
|
+
class Info < Base
|
21
|
+
OPTIONS_BUILDER = OptionsBuilders::Info
|
22
|
+
OPTION_ALIASES = Imgproxy::OptionAliases::INFO
|
23
|
+
|
24
|
+
# @param [Hash] options Info options
|
25
|
+
# @see Imgproxy.info_url_for
|
26
|
+
def initialize(options = {})
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
# Genrates imgproxy info URL
|
31
|
+
#
|
32
|
+
# @return [String] imgproxy info URL
|
33
|
+
# @param [String,URI, Object] image Source image URL or object applicable for
|
34
|
+
# the configured URL adapters
|
35
|
+
# @see Imgproxy.info_url_for
|
36
|
+
def url_for(image)
|
37
|
+
path = [*option_strings, sourcce_url(image)].join("/")
|
38
|
+
signature = sign_path(path)
|
39
|
+
|
40
|
+
File.join(endpoint.to_s, "info", signature, path)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "imgproxy/option_aliases/processing"
|
4
|
+
require "imgproxy/options_builders/processing"
|
5
|
+
require "imgproxy/url_builders/base"
|
6
|
+
|
7
|
+
module Imgproxy
|
8
|
+
module UrlBuilders
|
9
|
+
# Builds imgproxy URL
|
10
|
+
#
|
11
|
+
# builder = Imgproxy::UrlBuilders::Processing.new(
|
12
|
+
# width: 500,
|
13
|
+
# height: 400,
|
14
|
+
# resizing_type: :fill,
|
15
|
+
# sharpen: 0.5
|
16
|
+
# )
|
17
|
+
#
|
18
|
+
# builder.url_for("http://images.example.com/images/image1.jpg")
|
19
|
+
# builder.url_for("http://images.example.com/images/image2.jpg")
|
20
|
+
class Processing < Base
|
21
|
+
OPTIONS_BUILDER = OptionsBuilders::Processing
|
22
|
+
OPTION_ALIASES = Imgproxy::OptionAliases::PROCESSING
|
23
|
+
|
24
|
+
# @param [Hash] options Processing options
|
25
|
+
# @see Imgproxy.url_for
|
26
|
+
def initialize(options = {})
|
27
|
+
super(options)
|
28
|
+
|
29
|
+
@format = @options.delete(:format)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Genrates imgproxy URL
|
33
|
+
#
|
34
|
+
# @return [String] imgproxy URL
|
35
|
+
# @param [String,URI, Object] image Source image URL or object applicable for
|
36
|
+
# the configured URL adapters
|
37
|
+
# @see Imgproxy.url_for
|
38
|
+
def url_for(image)
|
39
|
+
path = [*option_strings, sourcce_url(image, ext: @format)].join("/")
|
40
|
+
signature = sign_path(path)
|
41
|
+
|
42
|
+
File.join(endpoint.to_s, signature, path)
|
43
|
+
end
|
44
|
+
|
45
|
+
# # Genrates imgproxy info URL
|
46
|
+
# #
|
47
|
+
# # @return [String] imgproxy info URL
|
48
|
+
# # @param [String,URI, Object] image Source image URL or object applicable for
|
49
|
+
# # the configured URL adapters
|
50
|
+
# # @see Imgproxy.info_url_for
|
51
|
+
# def info_url_for(image)
|
52
|
+
# path = url(image)
|
53
|
+
# signature = sign_path(path)
|
54
|
+
|
55
|
+
# File.join(endpoint.to_s, "info", signature, path)
|
56
|
+
# end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/imgproxy/version.rb
CHANGED
data/lib/imgproxy.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "imgproxy/version"
|
2
4
|
require "imgproxy/config"
|
3
|
-
require "imgproxy/
|
5
|
+
require "imgproxy/url_builders/processing"
|
6
|
+
require "imgproxy/url_builders/info"
|
4
7
|
|
5
8
|
require "imgproxy/extensions/active_storage"
|
6
9
|
require "imgproxy/extensions/shrine"
|
@@ -58,71 +61,30 @@ module Imgproxy
|
|
58
61
|
# @return [String] imgproxy URL
|
59
62
|
# @param [String,URI, Object] image Source image URL or object applicable for
|
60
63
|
# the configured URL adapters
|
61
|
-
# @param [Hash] options Processing options
|
62
|
-
#
|
63
|
-
# @option options [Hash|Array|String] :size
|
64
|
-
# @option options [String] :resizing_type
|
65
|
-
# @option options [String] :resizing_algorithm supported only by imgproxy pro
|
66
|
-
# @option options [Integer] :width
|
67
|
-
# @option options [Integer] :height
|
68
|
-
# @option options [Float] :dpr
|
69
|
-
# @option options [Boolean] :enlarge
|
70
|
-
# @option options [Hash|Array|Boolean|String] :extend
|
71
|
-
# @option options [Hash|Array|String] :gravity
|
72
|
-
# @option options [Hash|Array|String] :crop
|
73
|
-
# @option options [Array] :padding
|
74
|
-
# @option options [Hash|Array|String] :trim
|
75
|
-
# @option options [Integer] :rotate
|
76
|
-
# @option options [Integer] :quality
|
77
|
-
# @option options [Integer] :max_bytes
|
78
|
-
# @option options [Array|String] :background
|
79
|
-
# @option options [Float] :background_alpha supported only by imgproxy pro
|
80
|
-
# @option options [Hash|Array|String] :adjust
|
81
|
-
# @option options [Integer] :brightness supported only by imgproxy pro
|
82
|
-
# @option options [Float] :contrast supported only by imgproxy pro
|
83
|
-
# @option options [Float] :saturation supported only by imgproxy pro
|
84
|
-
# @option options [Float] :blur
|
85
|
-
# @option options [Float] :sharpen
|
86
|
-
# @option options [Integer] :pixelate supported only by imgproxy pro
|
87
|
-
# @option options [String] :unsharpening supported only by imgproxy pro
|
88
|
-
# @option options [Hash|Array|Float|String] :watermark
|
89
|
-
# @option options [String] :watermark_url supported only by imgproxy pro
|
90
|
-
# @option options [String] :style supported only by imgproxy pro
|
91
|
-
# @option options [Hash|Array|String] :jpeg_options supported only by imgproxy pro
|
92
|
-
# @option options [Hash|Array|String] :png_options supported only by imgproxy pro
|
93
|
-
# @option options [Hash|Array|String] :gif_options supported only by imgproxy pro
|
94
|
-
# @option options [Integer] :page supported only by imgproxy pro
|
95
|
-
# @option options [Integer] :video_thumbnail_second supported only by imgproxy pro
|
96
|
-
# @option options [Array] :preset
|
97
|
-
# @option options [String] :cachebuster
|
98
|
-
# @option options [Boolean] :strip_metadata
|
99
|
-
# @option options [Boolean] :strip_color_profile
|
100
|
-
# @option options [Boolean] :auto_rotate
|
101
|
-
# @option options [String] :filename
|
102
|
-
# @option options [String] :format
|
103
|
-
# @option options [Boolean] :return_attachment
|
104
|
-
# @option options [Integer] :expires
|
105
|
-
# @option options [Boolean] :use_short_options
|
106
|
-
# @option options [Boolean] :base64_encode_urls
|
107
|
-
# @option options [Boolean] :escape_plain_url
|
108
|
-
# @see https://docs.imgproxy.net/#/generating_the_url_advanced?id=processing-options
|
109
|
-
# Available imgproxy URL processing options and their arguments
|
64
|
+
# @param [Hash] options Processing options.
|
65
|
+
# See: {file:docs/processing_options.md Supported processing options}
|
110
66
|
def url_for(image, options = {})
|
111
|
-
Imgproxy::
|
67
|
+
Imgproxy::UrlBuilders::Processing.new(options).url_for(image)
|
112
68
|
end
|
113
69
|
|
114
|
-
# Genrates imgproxy info URL. Supported only by imgproxy
|
70
|
+
# Genrates imgproxy info URL. Supported only by imgproxy Pro
|
115
71
|
#
|
116
|
-
# Imgproxy.info_url_for(
|
72
|
+
# Imgproxy.info_url_for(
|
73
|
+
# "http://images.example.com/images/image.jpg",
|
74
|
+
# alpha: {
|
75
|
+
# alpha: true,
|
76
|
+
# check_transparency: true
|
77
|
+
# },
|
78
|
+
# palette: 128,
|
79
|
+
# )
|
117
80
|
#
|
118
81
|
# @return [String] imgproxy info URL
|
119
82
|
# @param [String,URI, Object] image Source image URL or object applicable for
|
120
83
|
# the configured URL adapters
|
121
|
-
# @param [Hash] options
|
122
|
-
#
|
123
|
-
# @option options [Boolean] :escape_plain_url
|
84
|
+
# @param [Hash] options Info options.
|
85
|
+
# See: {file:docs/info_options.md Supported info options}
|
124
86
|
def info_url_for(image, options = {})
|
125
|
-
Imgproxy::
|
87
|
+
Imgproxy::UrlBuilders::Info.new(options).url_for(image)
|
126
88
|
end
|
127
89
|
|
128
90
|
# Extends +ActiveStorage::Blob+ with {Imgproxy::Extensions::ActiveStorage.imgproxy_url} method
|
data/logo/logo-dark.svg
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="266" height="100" fill="none">
|
2
|
+
<g clip-path="url(#a)">
|
3
|
+
<path fill="#fff" d="M94.056 42.55v2.915h5.803v11.648h-5.803v2.915h14.733v-2.915h-5.69V42.549h-9.043Zm4.916-4.367c0 1.423.83 2.423 2.451 2.423 1.619 0 2.45-1 2.45-2.423 0-1.422-.831-2.422-2.45-2.422-1.62 0-2.451 1-2.451 2.422Zm14.479 4.366v17.465h3.239V48.746c0-2.507.859-3.633 2.775-3.633 1.915 0 2.774 1.14 2.774 3.633v11.268h3.24V48.746c0-2.535.859-3.633 2.775-3.633 1.915 0 2.774 1.112 2.774 3.633v11.268h3.24V47.845c0-3.465-2.099-5.76-5.24-5.76-1.648 0-3.155.732-4.014 1.915h-.591c-.86-1.225-2.155-1.916-3.747-1.916-1.648 0-2.887.578-3.563 1.634h-.409V42.55h-3.253Zm42.704 16.902V42.549h-3.24v1.578h-.887c-.831-1.226-2.676-2.043-4.662-2.043-4.662 0-7.774 3.437-7.774 8.62 0 5.099 3.126 8.507 7.774 8.507 1.916 0 3.775-.76 4.662-1.915h.887v1.859c0 2.676-1.887 4.253-5.07 4.253-2.535 0-4.422-1.042-5.07-2.788h-3.183c.183 3.436 3.478 5.704 8.253 5.704 5.155-.014 8.31-2.746 8.31-6.873Zm-13.324-8.747c0-3.465 1.944-5.591 5.127-5.591s5.127 2.126 5.127 5.591c0 3.465-1.944 5.592-5.127 5.592s-5.127-2.127-5.127-5.592Zm28.648-8.62c-2.127 0-4.071.874-4.887 2.212h-.888v-1.747h-3.239v23.296h3.239v-7.577h.888c.816 1.338 2.774 2.21 4.887 2.21 4.775 0 7.958-3.675 7.958-9.196s-3.183-9.197-7.958-9.197Zm-5.887 9.212c0-3.817 2-6.17 5.309-6.17 3.296 0 5.31 2.353 5.31 6.17 0 3.817-2 6.169-5.31 6.169-3.309 0-5.309-2.366-5.309-6.17Zm18.845-8.747v2.916h4.14v11.648h-4.14v2.915h13.746v-2.915h-6.366v-6.409c0-3.704 1.155-5.591 3.422-5.591 1.831 0 2.775 1.07 2.775 3.14v2.057h3.352v-2.521c0-3.55-1.915-5.705-5.07-5.705-1.676 0-3.071.634-3.831 1.803h-.888V42.55h-7.14Zm30.042 17.944c5.211 0 8.69-3.676 8.69-9.197 0-5.521-3.479-9.197-8.69-9.197-5.211 0-8.69 3.676-8.69 9.197 0 5.52 3.465 9.197 8.69 9.197Zm-5.451-9.197c0-3.817 2.071-6.17 5.451-6.17 3.394 0 5.451 2.353 5.451 6.17 0 3.817-2.057 6.169-5.451 6.169-3.394 0-5.451-2.366-5.451-6.17ZM227 60.028h3.718l4.127-6.056.324-.845h.296l.324.845 4.07 6.056h3.944l-5.747-8.591 6.099-8.888h-3.62l-4.62 6.705-.323.845h-.296l-.324-.845-4.423-6.705h-3.887l6.042 9.17-5.704 8.31Zm20.69-17.479 6.338 16.014h2.648l-1.056 2.972c-.535 1.31-1.057 1.86-2.028 1.86-1.057 0-1.62-.55-2.184-1.86h-2.943c.239 3.056 2.155 4.775 5.31 4.775 2.126 0 3.859-1.395 4.718-3.789l7.127-19.972h-3.296l-4.62 13.099h-1.267l-5.155-13.099h-3.592Z"/>
|
4
|
+
<mask id="b" width="94" height="79" x="0" y="22" maskUnits="userSpaceOnUse" style="mask-type:luminance">
|
5
|
+
<path fill="#fff" d="M.394 22.535h92.817v78.169H.394V22.535Z"/>
|
6
|
+
</mask>
|
7
|
+
<g mask="url(#b)">
|
8
|
+
<path fill="url(#c)" d="M78.493 32.732V22.535H68.31v2.831H44.535v-2.83H34.352v2.83H10.577v-2.83H.394v10.196h2.831v12.465H.395v10.197h2.83V67.86H.395v10.197h10.182v-2.845h23.775v2.831h10.183v-2.83H68.31v2.83h10.183V67.845h-2.831V55.38h2.83V45.183h-2.83V32.718h2.83v.014Zm-41.873-7.93h5.662v5.663H36.62v-5.662ZM2.662 30.466v-5.662h5.662v5.662H2.662Zm0 22.662v-5.662h5.662v5.662H2.662Zm5.662 22.648H2.662v-5.662h5.662v5.662Zm33.958 0H36.62v-5.662h5.662v5.662Zm26.028-5.099H44.535v-2.83H34.352v2.83H10.577v-2.83h-2.83V55.38h2.83V45.183h-2.83V32.718h2.83v-2.83h23.775v2.83h10.183v-2.83H68.31v2.83h2.83v12.465h-2.83V55.38h2.83v12.465h-2.83v2.831Zm7.93-.563v5.662h-5.663v-5.662h5.662Zm0-22.648v5.662h-5.663v-5.662h5.662Zm-5.663-17v-5.662h5.662v5.662h-5.662Z"/>
|
9
|
+
<path fill="#1960C4" d="M22.55 45.192v.864h.592a1.98 1.98 0 0 1 .8-.848 2.36 2.36 0 0 1 1.2-.304c.778 0 1.37.293 1.776.88.405.587.608 1.445.608 2.576v1.552h-2.544V48.68c0-.459-.086-.8-.256-1.024-.17-.235-.432-.352-.784-.352-.438 0-.763.197-.976.592-.203.395-.304.997-.304 1.808v3.072h2.8V55h-6.88v-2.224h1.664v-5.36h-1.872v-2.224h4.176ZM35.545 55v-9.808h2.496V55h-2.496Zm-3.44-4.192c0 .715.144 1.253.432 1.616.288.363.715.544 1.28.544.576 0 1.008-.181 1.296-.544.288-.363.432-.901.432-1.616h.368v3.312h-.96a2.293 2.293 0 0 1-.896.88c-.384.203-.827.304-1.328.304-.65 0-1.21-.155-1.68-.464-.459-.31-.816-.752-1.072-1.328-.245-.587-.368-1.28-.368-2.08v-6.24h2.496v5.616Zm14.019 4.448c-.49 0-.933-.107-1.328-.32a2.085 2.085 0 0 1-.88-.864h-.592V55h-2.496V41.432h2.496v4.672h.592c.192-.352.485-.635.88-.848.395-.213.837-.32 1.328-.32.79 0 1.477.213 2.064.64.597.416 1.056 1.013 1.376 1.792.32.768.48 1.68.48 2.736 0 1.045-.16 1.957-.48 2.736-.32.768-.779 1.365-1.376 1.792-.587.416-1.275.624-2.064.624Zm-2.944-5.168c0 .928.192 1.653.576 2.176.395.512.944.768 1.648.768s1.248-.256 1.632-.768c.395-.523.592-1.248.592-2.176 0-.928-.197-1.648-.592-2.16-.384-.512-.928-.768-1.632-.768-.704 0-1.253.261-1.648.784-.384.512-.576 1.227-.576 2.144Zm10.835-4.896 2.256 7.072h1.376L57.12 54.2h-2.704l-2.96-9.008h2.56Zm4.144 10.864c-.245.8-.624 1.408-1.136 1.824-.501.416-1.125.624-1.872.624-.928 0-1.659-.256-2.192-.768-.523-.512-.832-1.259-.928-2.24h2.192c.117.32.245.544.384.672a.715.715 0 0 0 .528.208.623.623 0 0 0 .496-.224c.139-.139.261-.373.368-.704l2.848-10.256h2.368L58.16 56.056Z"/>
|
10
|
+
<path fill="#fff" fill-rule="evenodd" d="M81.437 91.746h10.957L73.606 72.945l7.83 18.802Zm-7.831-18.802v26.62l7.817-7.832" clip-rule="evenodd"/>
|
11
|
+
</g>
|
12
|
+
</g>
|
13
|
+
<defs>
|
14
|
+
<linearGradient id="c" x1="39.445" x2="39.445" y1="78.046" y2="22.535" gradientUnits="userSpaceOnUse">
|
15
|
+
<stop stop-color="#1D40B2"/>
|
16
|
+
<stop offset="1" stop-color="#1680D6"/>
|
17
|
+
</linearGradient>
|
18
|
+
<clipPath id="a">
|
19
|
+
<path fill="#fff" d="M0 0h266v100H0z"/>
|
20
|
+
</clipPath>
|
21
|
+
</defs>
|
22
|
+
</svg>
|