shimmer 0.0.42 → 0.0.44
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/Gemfile.lock +24 -26
- data/README.md +1 -1
- data/lib/shimmer/controllers/files_controller.rb +4 -1
- data/lib/shimmer/utils/file_helper.rb +14 -6
- data/lib/shimmer/utils/file_proxy.rb +11 -14
- data/lib/shimmer/utils/remote_navigation.rb +2 -2
- data/lib/shimmer/version.rb +1 -1
- data/src/popover.ts +19 -3
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 43a551bb9b24c84773b363f1c409390b996e6d4cdb39feee930b4e29ffebc424
|
|
4
|
+
data.tar.gz: c49e0b734bc2f778558403d0f2d8205eed1559fd4ea474ff888e4f8d0fe35724
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1a12fe759f7cbab657a245594d21c05a0851e0550346a9357d59e2486ba29145678eed270acb0a0ea10bf625fca58dc77d98201875c884bd32a06d7e261596c7
|
|
7
|
+
data.tar.gz: 606d2a31214247a24274341ffa499cf97796569dee5bcb5c58e9bfaeec457ef59e5b865da2820d46d912300195cf32b66f9a35b298c9916fd745e4e7d06553a1
|
data/Gemfile.lock
CHANGED
|
@@ -76,8 +76,8 @@ GEM
|
|
|
76
76
|
minitest (>= 5.1)
|
|
77
77
|
securerandom (>= 0.3)
|
|
78
78
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
79
|
-
addressable (2.
|
|
80
|
-
public_suffix (>= 2.0.2, <
|
|
79
|
+
addressable (2.9.0)
|
|
80
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
81
81
|
annotate (3.2.0)
|
|
82
82
|
activerecord (>= 3.2, < 8.0)
|
|
83
83
|
rake (>= 10.4, < 14.0)
|
|
@@ -98,11 +98,11 @@ GEM
|
|
|
98
98
|
rack-test (>= 0.6.3)
|
|
99
99
|
regexp_parser (>= 1.5, < 3.0)
|
|
100
100
|
xpath (~> 3.2)
|
|
101
|
-
capybara-playwright-driver (0.5.
|
|
101
|
+
capybara-playwright-driver (0.5.9)
|
|
102
102
|
addressable
|
|
103
103
|
capybara
|
|
104
104
|
playwright-ruby-client (>= 1.16.0)
|
|
105
|
-
concurrent-ruby (1.3.
|
|
105
|
+
concurrent-ruby (1.3.6)
|
|
106
106
|
connection_pool (2.4.1)
|
|
107
107
|
crass (1.0.6)
|
|
108
108
|
cssbundling-rails (1.4.1)
|
|
@@ -118,10 +118,7 @@ GEM
|
|
|
118
118
|
railties (>= 6.1)
|
|
119
119
|
drb (2.2.1)
|
|
120
120
|
erubi (1.13.0)
|
|
121
|
-
ffi (1.17.0
|
|
122
|
-
ffi (1.17.0-arm64-darwin)
|
|
123
|
-
ffi (1.17.0-x86_64-darwin)
|
|
124
|
-
ffi (1.17.0-x86_64-linux-gnu)
|
|
121
|
+
ffi (1.17.0)
|
|
125
122
|
globalid (1.2.1)
|
|
126
123
|
activesupport (>= 6.1)
|
|
127
124
|
i18n (1.14.6)
|
|
@@ -141,7 +138,7 @@ GEM
|
|
|
141
138
|
json (2.7.2)
|
|
142
139
|
language_server-protocol (3.17.0.3)
|
|
143
140
|
lint_roller (1.1.0)
|
|
144
|
-
logger (1.
|
|
141
|
+
logger (1.7.0)
|
|
145
142
|
loofah (2.22.0)
|
|
146
143
|
crass (~> 1.0.2)
|
|
147
144
|
nokogiri (>= 1.12.0)
|
|
@@ -151,13 +148,14 @@ GEM
|
|
|
151
148
|
net-pop
|
|
152
149
|
net-smtp
|
|
153
150
|
marcel (1.0.4)
|
|
154
|
-
matrix (0.4.
|
|
155
|
-
mime-types (3.
|
|
151
|
+
matrix (0.4.3)
|
|
152
|
+
mime-types (3.7.0)
|
|
156
153
|
logger
|
|
157
|
-
mime-types-data (~> 3.
|
|
158
|
-
mime-types-data (3.
|
|
154
|
+
mime-types-data (~> 3.2025, >= 3.2025.0507)
|
|
155
|
+
mime-types-data (3.2026.0414)
|
|
159
156
|
mini_magick (4.13.2)
|
|
160
157
|
mini_mime (1.1.5)
|
|
158
|
+
mini_portile2 (2.8.9)
|
|
161
159
|
minitest (5.25.1)
|
|
162
160
|
msgpack (1.7.3)
|
|
163
161
|
net-imap (0.5.0)
|
|
@@ -170,19 +168,20 @@ GEM
|
|
|
170
168
|
net-smtp (0.5.0)
|
|
171
169
|
net-protocol
|
|
172
170
|
nio4r (2.7.3)
|
|
173
|
-
nokogiri (1.
|
|
171
|
+
nokogiri (1.19.3-aarch64-linux-gnu)
|
|
174
172
|
racc (~> 1.4)
|
|
175
|
-
nokogiri (1.
|
|
173
|
+
nokogiri (1.19.3-arm64-darwin)
|
|
176
174
|
racc (~> 1.4)
|
|
177
|
-
nokogiri (1.
|
|
175
|
+
nokogiri (1.19.3-x86_64-darwin)
|
|
178
176
|
racc (~> 1.4)
|
|
179
|
-
nokogiri (1.
|
|
177
|
+
nokogiri (1.19.3-x86_64-linux-gnu)
|
|
180
178
|
racc (~> 1.4)
|
|
181
179
|
parallel (1.26.3)
|
|
182
180
|
parser (3.3.5.0)
|
|
183
181
|
ast (~> 2.4.1)
|
|
184
182
|
racc
|
|
185
|
-
playwright-ruby-client (1.
|
|
183
|
+
playwright-ruby-client (1.59.1)
|
|
184
|
+
base64
|
|
186
185
|
concurrent-ruby (>= 1.1.6)
|
|
187
186
|
mime-types (>= 3.0)
|
|
188
187
|
prism (1.2.0)
|
|
@@ -193,14 +192,14 @@ GEM
|
|
|
193
192
|
railties (>= 7.0.0)
|
|
194
193
|
psych (5.1.2)
|
|
195
194
|
stringio
|
|
196
|
-
public_suffix (
|
|
195
|
+
public_suffix (7.0.5)
|
|
197
196
|
puma (6.4.3)
|
|
198
197
|
nio4r (~> 2.0)
|
|
199
198
|
racc (1.8.1)
|
|
200
|
-
rack (3.1.
|
|
199
|
+
rack (3.1.21)
|
|
201
200
|
rack-session (2.0.0)
|
|
202
201
|
rack (>= 3.0.0)
|
|
203
|
-
rack-test (2.
|
|
202
|
+
rack-test (2.2.0)
|
|
204
203
|
rack (>= 1.3)
|
|
205
204
|
rack_session_access (0.2.0)
|
|
206
205
|
builder (>= 2.0.0)
|
|
@@ -243,7 +242,7 @@ GEM
|
|
|
243
242
|
logger
|
|
244
243
|
rdoc (6.7.0)
|
|
245
244
|
psych (>= 4.0.0)
|
|
246
|
-
regexp_parser (2.
|
|
245
|
+
regexp_parser (2.12.0)
|
|
247
246
|
reline (0.5.10)
|
|
248
247
|
io-console (~> 0.5)
|
|
249
248
|
rspec-core (3.13.2)
|
|
@@ -309,10 +308,8 @@ GEM
|
|
|
309
308
|
railties (>= 3.1)
|
|
310
309
|
slim (>= 3.0, < 6.0, != 5.0.0)
|
|
311
310
|
sorbet-runtime (0.5.11611)
|
|
312
|
-
sqlite3 (2.1.1
|
|
313
|
-
|
|
314
|
-
sqlite3 (2.1.1-x86_64-darwin)
|
|
315
|
-
sqlite3 (2.1.1-x86_64-linux-gnu)
|
|
311
|
+
sqlite3 (2.1.1)
|
|
312
|
+
mini_portile2 (~> 2.8.0)
|
|
316
313
|
standard (1.35.0.1)
|
|
317
314
|
language_server-protocol (~> 3.17.0.2)
|
|
318
315
|
lint_roller (~> 1.0)
|
|
@@ -355,6 +352,7 @@ GEM
|
|
|
355
352
|
PLATFORMS
|
|
356
353
|
aarch64-linux
|
|
357
354
|
arm64-darwin-22
|
|
355
|
+
arm64-darwin-25
|
|
358
356
|
x86_64-darwin-22
|
|
359
357
|
x86_64-linux
|
|
360
358
|
|
data/README.md
CHANGED
|
@@ -140,7 +140,7 @@ Then, if there are specific cops you want to use in the specific project you are
|
|
|
140
140
|
|
|
141
141
|
`ActiveStorage` is great, but serving of files, especially behind a CDN, can be complicated to get right. Shimmer has your back.
|
|
142
142
|
|
|
143
|
-
It overrides `image_tag` and automatically resizes your image and creates a static, cacheable URL.
|
|
143
|
+
It overrides `image_tag` and automatically resizes your image, converts it to WebP, and creates a static, cacheable URL.
|
|
144
144
|
|
|
145
145
|
```ruby
|
|
146
146
|
# use an image tag
|
|
@@ -5,11 +5,14 @@ module Shimmer
|
|
|
5
5
|
def show
|
|
6
6
|
expires_in 1.year, public: true
|
|
7
7
|
request.session_options[:skip] = true # prevents a session cookie from being set (would prevent caching on CDNs)
|
|
8
|
+
|
|
8
9
|
proxy = FileProxy.restore(params.require(:id))
|
|
9
|
-
send_data
|
|
10
|
+
send_data(
|
|
11
|
+
proxy.file,
|
|
10
12
|
filename: proxy.filename.to_s,
|
|
11
13
|
type: proxy.content_type,
|
|
12
14
|
disposition: "inline"
|
|
15
|
+
)
|
|
13
16
|
rescue ActiveRecord::RecordNotFound, ActiveStorage::FileNotFoundError
|
|
14
17
|
head :not_found
|
|
15
18
|
end
|
|
@@ -15,23 +15,31 @@ module Shimmer
|
|
|
15
15
|
def image_tag(source, **options)
|
|
16
16
|
return nil if source.blank?
|
|
17
17
|
|
|
18
|
-
if source.is_a?(ActiveStorage::Variant) ||
|
|
18
|
+
if source.is_a?(ActiveStorage::Variant) ||
|
|
19
|
+
source.is_a?(ActiveStorage::VariantWithRecord) ||
|
|
20
|
+
source.is_a?(ActiveStorage::Attached) ||
|
|
21
|
+
source.is_a?(ActiveStorage::Attachment) ||
|
|
22
|
+
(Object.const_defined?("ActionText::Attachment") && source.is_a?(ActionText::Attachment))
|
|
19
23
|
attachment = source
|
|
20
24
|
width = options[:width]
|
|
21
25
|
height = options[:height]
|
|
22
26
|
source = image_file_path(source, width: width, height: height)
|
|
23
27
|
options[:loading] ||= :lazy
|
|
24
|
-
|
|
28
|
+
if options[:width].present?
|
|
29
|
+
source_2x = image_file_path(attachment, width: width.to_i * 2, height: height ? height.to_i * 2 : nil)
|
|
30
|
+
options[:srcset] = "#{source} 1x, #{source_2x} 2x"
|
|
31
|
+
end
|
|
25
32
|
end
|
|
33
|
+
|
|
26
34
|
super(source, options)
|
|
27
35
|
end
|
|
28
36
|
|
|
29
|
-
def image_file_path(source,
|
|
30
|
-
image_file_proxy(source,
|
|
37
|
+
def image_file_path(source, **)
|
|
38
|
+
image_file_proxy(source, **, return_type: :path)
|
|
31
39
|
end
|
|
32
40
|
|
|
33
|
-
def image_file_url(source,
|
|
34
|
-
image_file_proxy(source,
|
|
41
|
+
def image_file_url(source, **)
|
|
42
|
+
image_file_proxy(source, **, return_type: :url)
|
|
35
43
|
end
|
|
36
44
|
|
|
37
45
|
def image_file_proxy(source, width: nil, height: nil, return_type: nil)
|
|
@@ -5,25 +5,21 @@ module Shimmer
|
|
|
5
5
|
attr_reader :blob_id
|
|
6
6
|
|
|
7
7
|
delegate :message_verifier, to: :class
|
|
8
|
-
delegate :content_type, :filename, to: :
|
|
8
|
+
delegate :content_type, :filename, to: :variant
|
|
9
9
|
|
|
10
10
|
class << self
|
|
11
11
|
def restore(id)
|
|
12
12
|
blob_id, resize = message_verifier.verified(id)
|
|
13
|
-
|
|
14
|
-
if resize.is_a?(String)
|
|
15
|
-
width, height = legacy_resize_string_to_tuple(resize)
|
|
16
|
-
elsif resize.is_a?(Array)
|
|
17
|
-
width, height = resize
|
|
18
|
-
end
|
|
13
|
+
width, height = parse_resize(resize)
|
|
19
14
|
|
|
20
15
|
new(blob_id: blob_id, width: width, height: height)
|
|
21
16
|
end
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
def legacy_resize_string_to_tuple(resize)
|
|
18
|
+
def parse_resize(resize)
|
|
25
19
|
return if resize.blank?
|
|
20
|
+
return resize if resize.is_a?(Array)
|
|
26
21
|
|
|
22
|
+
# In the past, we generated the IDs with ImageMagick style "200x200>" strings. We don't do that anymore, but to prevent all old URLs breaking and caches invalidating at once, we grandfather these URLs in.
|
|
27
23
|
matches = resize.match(/(?<width>\d*)x(?<height>\d*)/)
|
|
28
24
|
|
|
29
25
|
[
|
|
@@ -54,12 +50,13 @@ module Shimmer
|
|
|
54
50
|
@blob ||= ActiveStorage::Blob.find(blob_id)
|
|
55
51
|
end
|
|
56
52
|
|
|
57
|
-
def resizeable?
|
|
58
|
-
@resize.present? && blob.content_type.exclude?("svg")
|
|
59
|
-
end
|
|
60
|
-
|
|
61
53
|
def variant
|
|
62
|
-
@variant ||=
|
|
54
|
+
@variant ||= if blob.representable?
|
|
55
|
+
options = {resize_to_limit: @resize, format: "webp"}
|
|
56
|
+
blob.representation(options.compact).processed
|
|
57
|
+
else
|
|
58
|
+
blob
|
|
59
|
+
end
|
|
63
60
|
end
|
|
64
61
|
|
|
65
62
|
def file
|
|
@@ -33,8 +33,8 @@ module Shimmer
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
helper_method :popover_path
|
|
36
|
-
def popover_path(url, id: nil, selector: nil, placement: nil)
|
|
37
|
-
"javascript:ui.popover.open(#{{url: url, id: id, selector: selector, placement: placement}.compact.to_json})"
|
|
36
|
+
def popover_path(url, id: nil, selector: nil, placement: nil, class_name: nil)
|
|
37
|
+
"javascript:ui.popover.open(#{{url: url, id: id, selector: selector, placement: placement, className: class_name}.compact.to_json})"
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def shimmer_request?
|
data/lib/shimmer/version.rb
CHANGED
data/src/popover.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface PopoverOptions {
|
|
|
6
6
|
url: string;
|
|
7
7
|
selector?: HTMLElement | string;
|
|
8
8
|
placement?: Placement;
|
|
9
|
+
className?: string;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export class PopoverPresenter {
|
|
@@ -43,7 +44,12 @@ export class Popover {
|
|
|
43
44
|
private popper?: Popper;
|
|
44
45
|
private popoverDiv?: HTMLDivElement;
|
|
45
46
|
|
|
46
|
-
async open({
|
|
47
|
+
async open({
|
|
48
|
+
url,
|
|
49
|
+
selector,
|
|
50
|
+
placement,
|
|
51
|
+
className,
|
|
52
|
+
}: PopoverOptions): Promise<void> {
|
|
47
53
|
const root =
|
|
48
54
|
typeof selector === "string"
|
|
49
55
|
? document.querySelector(selector)
|
|
@@ -51,11 +57,15 @@ export class Popover {
|
|
|
51
57
|
if (!root) {
|
|
52
58
|
return;
|
|
53
59
|
}
|
|
54
|
-
|
|
60
|
+
|
|
61
|
+
const popoverClassName = ["popover", "popover--loading"];
|
|
62
|
+
if (className) {
|
|
63
|
+
popoverClassName.push(className);
|
|
64
|
+
}
|
|
65
|
+
const popoverDiv = createElement(document.body, popoverClassName.join(" "));
|
|
55
66
|
const arrow = createElement(popoverDiv, "popover__arrow");
|
|
56
67
|
arrow.setAttribute("data-popper-arrow", "true");
|
|
57
68
|
const content = createElement(popoverDiv, "popover__content");
|
|
58
|
-
content.innerHTML = await getHTML(url);
|
|
59
69
|
this.popper = createPopper(root, popoverDiv, {
|
|
60
70
|
placement: placement ?? "auto",
|
|
61
71
|
modifiers: [
|
|
@@ -68,7 +78,13 @@ export class Popover {
|
|
|
68
78
|
],
|
|
69
79
|
});
|
|
70
80
|
this.popoverDiv = popoverDiv;
|
|
81
|
+
|
|
71
82
|
document.addEventListener("click", this.clickOutside);
|
|
83
|
+
|
|
84
|
+
const response = await getHTML(url);
|
|
85
|
+
content.innerHTML = response;
|
|
86
|
+
popoverDiv.classList.remove("popover--loading");
|
|
87
|
+
this.popper?.update();
|
|
72
88
|
}
|
|
73
89
|
|
|
74
90
|
async close(): Promise<void> {
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shimmer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.44
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jens Ravens
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email:
|