fileboost 0.2.0.pre → 0.2.0.pre2
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.
- checksums.yaml +4 -4
- data/README.md +137 -6
- data/lib/fileboost/url_builder.rb +14 -4
- data/lib/fileboost/variant_transformer.rb +130 -0
- data/lib/fileboost/version.rb +1 -1
- data/lib/fileboost.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b09c6f264244d950aef3d870c4e102e3766449f24b724834de3d58c08e9eecd8
|
4
|
+
data.tar.gz: beaf90aa5f6a0b579fd54298b108fe9fa427356d3fce5f6bffe570d828cbc0ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 143c252e1134fef6790e18ac6d9ea6b85995fb90bd7755475cbdc8411ab85aefa9ae1d80c7362ebc8fadc53500109449ffef66818ebdb641dd302129e5a9bd1e
|
7
|
+
data.tar.gz: d90e35602b8be26133a51ca1ff25d65db41080ebdadff3988e81888b90c9b69e2843c2d84c58f67c8e5bcc8075d705782f575ac9b9f44d15e7725bc9e1ec549a
|
data/README.md
CHANGED
@@ -4,13 +4,39 @@
|
|
4
4
|
|
5
5
|
Fileboost is a Rails gem that provides seamless integration with the Fileboost.dev image optimization service. It offers drop-in replacement helpers for Rails' native image helpers with automatic optimization, HMAC authentication, and comprehensive transformation support for ActiveStorage objects.
|
6
6
|
|
7
|
+
## Table of Contents
|
8
|
+
|
9
|
+
- [Features](#features)
|
10
|
+
- [Installation](#installation)
|
11
|
+
- [Configuration](#configuration)
|
12
|
+
- [Usage](#usage)
|
13
|
+
- [Drop-in Replacement (Recommended)](#drop-in-replacement-recommended)
|
14
|
+
- [Manual Helper Method](#manual-helper-method)
|
15
|
+
- [URL Generation](#url-generation)
|
16
|
+
- [Transformation Options](#transformation-options)
|
17
|
+
- [Parameter Aliases](#parameter-aliases)
|
18
|
+
- [ActiveStorage Support](#activestorage-support)
|
19
|
+
- [ActiveStorage Variants (NEW in v0.2.0)](#activestorage-variants-new-in-v020)
|
20
|
+
- [Variant Transformation Mapping](#variant-transformation-mapping)
|
21
|
+
- [Combining Variants with Custom Options](#combining-variants-with-custom-options)
|
22
|
+
- [Responsive Images](#responsive-images)
|
23
|
+
- [Error Handling](#error-handling)
|
24
|
+
- [Security](#security)
|
25
|
+
- [Development](#development)
|
26
|
+
- [Testing](#testing)
|
27
|
+
- [Contributing](#contributing)
|
28
|
+
- [License](#license)
|
29
|
+
- [Support](#support)
|
30
|
+
|
7
31
|
## Features
|
8
32
|
|
9
|
-
- 🚀 **Drop-in replacement** for Rails `image_tag`
|
33
|
+
- 🚀 **Drop-in replacement** for Rails `image_tag` with zero code changes (NEW in v0.2.0)
|
34
|
+
- 🎨 **Full ActiveStorage Variant support** with automatic transformation mapping (NEW in v0.2.0)
|
10
35
|
- 🔒 **Secure HMAC authentication** with Fileboost.dev service
|
11
36
|
- 📱 **ActiveStorage only** - works exclusively with ActiveStorage attachments
|
12
37
|
- 🎛️ **Comprehensive transformations** - resize, quality, format conversion, and more
|
13
38
|
- 🔧 **Simple configuration** - just project ID and token required
|
39
|
+
- 🔄 **Automatic fallback** - non-ActiveStorage images work exactly as before
|
14
40
|
|
15
41
|
## Installation
|
16
42
|
|
@@ -43,11 +69,59 @@ export FILEBOOST_PROJECT_ID="your-project-id"
|
|
43
69
|
export FILEBOOST_TOKEN="your-secret-token"
|
44
70
|
```
|
45
71
|
|
72
|
+
Or configure directly in your initializer:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
# config/initializers/fileboost.rb
|
76
|
+
Fileboost.configure do |config|
|
77
|
+
config.project_id = ENV["FILEBOOST_PROJECT_ID"]
|
78
|
+
config.token = ENV["FILEBOOST_TOKEN"]
|
79
|
+
|
80
|
+
# Optional: Enable drop-in replacement for Rails image_tag (default: false)
|
81
|
+
config.patch_image_tag = true
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
46
85
|
## Usage
|
47
86
|
|
48
|
-
###
|
87
|
+
### Drop-in Replacement (Recommended)
|
88
|
+
|
89
|
+
Enable `patch_image_tag` in your configuration to automatically optimize ActiveStorage images with your existing `image_tag` calls:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
# config/initializers/fileboost.rb
|
93
|
+
Fileboost.configure do |config|
|
94
|
+
config.project_id = ENV["FILEBOOST_PROJECT_ID"]
|
95
|
+
config.token = ENV["FILEBOOST_TOKEN"]
|
96
|
+
config.patch_image_tag = true # Enable automatic optimization
|
97
|
+
end
|
98
|
+
```
|
49
99
|
|
50
|
-
|
100
|
+
With this enabled, your existing Rails code automatically gets Fileboost optimization:
|
101
|
+
|
102
|
+
```erb
|
103
|
+
<!-- This now automatically uses Fileboost for ActiveStorage objects -->
|
104
|
+
<%= image_tag user.avatar, resize: { w: 300, h: 300 }, alt: "Avatar" %>
|
105
|
+
<%= image_tag post.featured_image, resize: { width: 800, quality: 85 }, class: "hero" %>
|
106
|
+
|
107
|
+
<!-- ActiveStorage variants work seamlessly -->
|
108
|
+
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100]), alt: "Thumbnail" %>
|
109
|
+
<%= image_tag post.image.variant(:thumb), alt: "Post thumbnail" %>
|
110
|
+
|
111
|
+
<!-- Non-ActiveStorage images work exactly as before -->
|
112
|
+
<%= image_tag "/assets/logo.png", alt: "Logo" %>
|
113
|
+
<%= image_tag "https://example.com/image.jpg", alt: "External" %>
|
114
|
+
```
|
115
|
+
|
116
|
+
**Benefits:**
|
117
|
+
- Zero code changes required for existing ActiveStorage images
|
118
|
+
- Full ActiveStorage variant support with automatic transformation mapping
|
119
|
+
- Automatic fallback to Rails behavior for non-ActiveStorage assets
|
120
|
+
- Gradual migration path - enable/disable with single configuration option
|
121
|
+
|
122
|
+
### Manual Helper Method
|
123
|
+
|
124
|
+
Alternatively, use `fileboost_image_tag` explicitly for ActiveStorage objects:
|
51
125
|
|
52
126
|
```erb
|
53
127
|
<!-- Before (Rails) -->
|
@@ -104,7 +178,7 @@ fileboost_image_tag(image, resize: { w: 400, h: 300, q: 85 })
|
|
104
178
|
fileboost_image_tag(image, resize: { width: 400, height: 300, quality: 85 })
|
105
179
|
```
|
106
180
|
|
107
|
-
|
181
|
+
**🎯 Smart Optimization:** Fileboost's CDN automatically detects and delivers the optimal image format (WebP, AVIF, JPEG, etc.) based on browser capabilities, device type, and connection speed for maximum performance.
|
108
182
|
|
109
183
|
### ActiveStorage Support
|
110
184
|
|
@@ -123,6 +197,63 @@ Works seamlessly with all ActiveStorage attachment types:
|
|
123
197
|
<%= fileboost_image_tag post.featured_image.blob, resize: { w: 800 } %>
|
124
198
|
```
|
125
199
|
|
200
|
+
### ActiveStorage Variants (NEW in v0.2.0)
|
201
|
+
|
202
|
+
Fileboost now provides full support for ActiveStorage variants with automatic transformation mapping:
|
203
|
+
|
204
|
+
```erb
|
205
|
+
<!-- Basic variants with automatic transformation mapping -->
|
206
|
+
<%= image_tag user.avatar.variant(resize_to_limit: [200, 200]) %>
|
207
|
+
<!-- ↓ Automatically becomes: w=200&h=200&fit=scale-down -->
|
208
|
+
|
209
|
+
<%= image_tag post.image.variant(resize_to_fit: [400, 300]) %>
|
210
|
+
<!-- ↓ Automatically becomes: w=400&h=300&fit=contain -->
|
211
|
+
|
212
|
+
<%= image_tag hero.banner.variant(resize_to_fill: [800, 400]) %>
|
213
|
+
<!-- ↓ Automatically becomes: w=800&h=400&fit=cover -->
|
214
|
+
|
215
|
+
<!-- Complex variants with multiple transformations -->
|
216
|
+
<%= image_tag post.image.variant(
|
217
|
+
resize_to_limit: [600, 400],
|
218
|
+
quality: 85
|
219
|
+
) %>
|
220
|
+
<!-- ↓ Automatically becomes: w=600&h=400&fit=scale-down&q=85 -->
|
221
|
+
|
222
|
+
<!-- Named variants work seamlessly -->
|
223
|
+
<%= image_tag user.avatar.variant(:thumb) %>
|
224
|
+
<!-- ↓ Uses predefined variant transformations -->
|
225
|
+
```
|
226
|
+
|
227
|
+
#### Variant Transformation Mapping
|
228
|
+
|
229
|
+
Fileboost automatically maps ActiveStorage variant transformations to optimized URL parameters:
|
230
|
+
|
231
|
+
| ActiveStorage Variant | Fileboost Parameters | Description |
|
232
|
+
|----------------------|---------------------|-------------|
|
233
|
+
| `resize_to_limit: [w, h]` | `w=W&h=H&fit=scale-down` | Resize within bounds, preserving aspect ratio |
|
234
|
+
| `resize_to_fit: [w, h]` | `w=W&h=H&fit=contain` | Resize to fit exactly, with letterboxing if needed |
|
235
|
+
| `resize_to_fill: [w, h]` | `w=W&h=H&fit=cover` | Resize and crop to fill exactly |
|
236
|
+
| `resize_and_pad: [w, h]` | `w=W&h=H&fit=pad` | Resize with padding |
|
237
|
+
| `quality: 85` | `q=85` | JPEG/WebP quality (1-100) |
|
238
|
+
| `rotate: "-90"` | `r=-90` | Rotation in degrees |
|
239
|
+
|
240
|
+
|
241
|
+
#### Combining Variants with Custom Options
|
242
|
+
|
243
|
+
You can combine variant transformations with additional Fileboost options:
|
244
|
+
|
245
|
+
```erb
|
246
|
+
<!-- Variant transformations + additional options -->
|
247
|
+
<%= image_tag user.avatar.variant(resize_to_limit: [200, 200]),
|
248
|
+
resize: { blur: 5, brightness: 110 } %>
|
249
|
+
<!-- ↓ Combines variant params with additional blur and brightness -->
|
250
|
+
|
251
|
+
<!-- Override variant parameters -->
|
252
|
+
<%= image_tag post.image.variant(resize_to_limit: [400, 300]),
|
253
|
+
resize: { w: 500 } %>
|
254
|
+
<!-- ↓ Uses h=300&fit=scale-down from variant, but overrides width to 500 -->
|
255
|
+
```
|
256
|
+
|
126
257
|
### Responsive Images
|
127
258
|
|
128
259
|
Generate multiple sizes for responsive designs:
|
@@ -171,7 +302,7 @@ After checking out the repo, run:
|
|
171
302
|
|
172
303
|
```bash
|
173
304
|
$ bundle install
|
174
|
-
$
|
305
|
+
$ bundle exec rspec
|
175
306
|
```
|
176
307
|
|
177
308
|
To test against the dummy Rails application:
|
@@ -186,7 +317,7 @@ $ rails server
|
|
186
317
|
Run the test suite:
|
187
318
|
|
188
319
|
```bash
|
189
|
-
$
|
320
|
+
$ bundle exec rspec
|
190
321
|
```
|
191
322
|
|
192
323
|
Run RuboCop:
|
@@ -43,7 +43,7 @@ module Fileboost
|
|
43
43
|
full_path = "/#{project_id}#{asset_path}"
|
44
44
|
|
45
45
|
# Extract and normalize transformation parameters
|
46
|
-
transformation_params = extract_transformation_params(options)
|
46
|
+
transformation_params = extract_transformation_params(asset, options)
|
47
47
|
|
48
48
|
# Generate HMAC signature for secure authentication
|
49
49
|
signature = Fileboost::SignatureGenerator.generate(
|
@@ -89,10 +89,16 @@ module Fileboost
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
-
def self.extract_transformation_params(options)
|
92
|
+
def self.extract_transformation_params(asset, options)
|
93
93
|
params = {}
|
94
94
|
|
95
|
-
#
|
95
|
+
# First, extract variant transformations if this is a variant
|
96
|
+
if asset.is_a?(ActiveStorage::VariantWithRecord)
|
97
|
+
variant_params = Fileboost::VariantTransformer.transform_variant_params(asset)
|
98
|
+
params.merge!(variant_params)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Then handle explicit resize parameter (this can override variant params)
|
96
102
|
if options[:resize].is_a?(Hash)
|
97
103
|
resize_options = options[:resize]
|
98
104
|
resize_options.each do |key, value|
|
@@ -117,9 +123,13 @@ module Fileboost
|
|
117
123
|
|
118
124
|
def self.normalize_param_value(key, value)
|
119
125
|
case key
|
120
|
-
when "w", "h", "
|
126
|
+
when "w", "h", "b", "br", "c", "r"
|
121
127
|
# Numeric parameters
|
122
128
|
value.to_i.to_s if value.to_i > 0
|
129
|
+
when "q"
|
130
|
+
# Quality parameter - validate range 1-100
|
131
|
+
q = value.to_i
|
132
|
+
(q > 0 && q <= 100) ? q.to_s : nil
|
123
133
|
when "f"
|
124
134
|
# Format parameter - validate against common formats
|
125
135
|
valid_formats = %w[webp jpeg jpg png gif avif]
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Fileboost
|
2
|
+
# Maps ActiveStorage variant transformations to Fileboost URL parameters
|
3
|
+
class VariantTransformer
|
4
|
+
# Maps ActiveStorage transformation operations to Fileboost parameters
|
5
|
+
TRANSFORMATION_MAPPING = {
|
6
|
+
# Resize operations
|
7
|
+
resize_to_limit: { fit: "scale-down" },
|
8
|
+
resize_to_fit: { fit: "contain" },
|
9
|
+
resize_to_fill: { fit: "cover" },
|
10
|
+
resize_and_pad: { fit: "pad" },
|
11
|
+
|
12
|
+
# Quality settings
|
13
|
+
quality: { param: "q" },
|
14
|
+
|
15
|
+
# Format settings
|
16
|
+
format: { param: "f" },
|
17
|
+
|
18
|
+
# Rotation
|
19
|
+
rotate: { param: "r" },
|
20
|
+
|
21
|
+
# Crop operations - need special handling
|
22
|
+
crop: { special: :crop_handler }
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
# Convert ActiveStorage variant transformations to Fileboost parameters
|
26
|
+
def self.transform_variant_params(variant)
|
27
|
+
return {} unless variant.respond_to?(:variation)
|
28
|
+
|
29
|
+
transformations = variant.variation.transformations
|
30
|
+
params = {}
|
31
|
+
|
32
|
+
transformations.each do |operation, value|
|
33
|
+
case operation
|
34
|
+
when :resize_to_limit, :resize_to_fit, :resize_to_fill, :resize_and_pad
|
35
|
+
resize_params = handle_resize_operation(operation, value)
|
36
|
+
params.merge!(resize_params)
|
37
|
+
|
38
|
+
when :quality
|
39
|
+
params["q"] = normalize_quality(value)
|
40
|
+
|
41
|
+
when :format
|
42
|
+
params["f"] = normalize_format(value)
|
43
|
+
|
44
|
+
when :rotate
|
45
|
+
params["r"] = normalize_rotation(value)
|
46
|
+
|
47
|
+
when :crop
|
48
|
+
crop_params = handle_crop_operation(value)
|
49
|
+
params.merge!(crop_params) if crop_params
|
50
|
+
|
51
|
+
# Add more transformations as needed
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
params
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Handle resize operations (resize_to_limit, resize_to_fit, etc.)
|
61
|
+
def self.handle_resize_operation(operation, dimensions)
|
62
|
+
return {} unless dimensions.is_a?(Array) && dimensions.length >= 2
|
63
|
+
|
64
|
+
width, height = dimensions[0], dimensions[1]
|
65
|
+
params = {}
|
66
|
+
|
67
|
+
# Set dimensions
|
68
|
+
params["w"] = width.to_s if width && width > 0
|
69
|
+
params["h"] = height.to_s if height && height > 0
|
70
|
+
|
71
|
+
# Set fit parameter based on resize operation
|
72
|
+
fit_mapping = TRANSFORMATION_MAPPING[operation]
|
73
|
+
params["fit"] = fit_mapping[:fit] if fit_mapping && fit_mapping[:fit]
|
74
|
+
|
75
|
+
params
|
76
|
+
end
|
77
|
+
|
78
|
+
# Handle crop operations
|
79
|
+
def self.handle_crop_operation(crop_params)
|
80
|
+
# Crop can be in different formats depending on the processor
|
81
|
+
# For now, we'll handle simple array format: [x, y, width, height]
|
82
|
+
if crop_params.is_a?(Array) && crop_params.length == 4
|
83
|
+
x, y, w, h = crop_params
|
84
|
+
return { "crop" => "#{x},#{y},#{w},#{h}" }
|
85
|
+
end
|
86
|
+
|
87
|
+
# Could extend this for other crop formats
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
91
|
+
# Normalize quality value (0-100)
|
92
|
+
def self.normalize_quality(quality)
|
93
|
+
q = quality.to_i
|
94
|
+
return nil if q <= 0 || q > 100
|
95
|
+
q.to_s
|
96
|
+
end
|
97
|
+
|
98
|
+
# Normalize format value
|
99
|
+
def self.normalize_format(format)
|
100
|
+
# Convert to string and lowercase
|
101
|
+
format_str = format.to_s.downcase
|
102
|
+
|
103
|
+
# Map common format variations
|
104
|
+
case format_str
|
105
|
+
when "jpg", "jpeg"
|
106
|
+
"jpg"
|
107
|
+
when "png"
|
108
|
+
"png"
|
109
|
+
when "webp"
|
110
|
+
"webp"
|
111
|
+
when "avif"
|
112
|
+
"avif"
|
113
|
+
when "gif"
|
114
|
+
"gif"
|
115
|
+
else
|
116
|
+
# If it's already a recognized format, use it
|
117
|
+
valid_formats = %w[webp jpeg jpg png gif avif]
|
118
|
+
valid_formats.include?(format_str) ? format_str : nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Normalize rotation value
|
123
|
+
def self.normalize_rotation(rotation)
|
124
|
+
# Rotation should be a number (degrees)
|
125
|
+
r = rotation.to_s.gsub(/[^\d\-]/, "") # Remove non-numeric chars except minus
|
126
|
+
return nil if r.empty?
|
127
|
+
r
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/fileboost/version.rb
CHANGED
data/lib/fileboost.rb
CHANGED
@@ -2,6 +2,7 @@ require "fileboost/version"
|
|
2
2
|
require "fileboost/config"
|
3
3
|
require "fileboost/error_handler"
|
4
4
|
require "fileboost/signature_generator"
|
5
|
+
require "fileboost/variant_transformer"
|
5
6
|
require "fileboost/url_builder"
|
6
7
|
require "fileboost/helpers"
|
7
8
|
require "fileboost/image_tag_patch"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fileboost
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.
|
4
|
+
version: 0.2.0.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bilal
|
@@ -141,6 +141,7 @@ files:
|
|
141
141
|
- lib/fileboost/image_tag_patch.rb
|
142
142
|
- lib/fileboost/signature_generator.rb
|
143
143
|
- lib/fileboost/url_builder.rb
|
144
|
+
- lib/fileboost/variant_transformer.rb
|
144
145
|
- lib/fileboost/version.rb
|
145
146
|
- lib/generators/fileboost/install_generator.rb
|
146
147
|
- lib/generators/fileboost/templates/INSTALL.md
|