shimmer 0.0.1 → 0.0.7
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/.editorconfig +12 -0
- data/.eslintrc.js +25 -0
- data/.prettierrc +3 -0
- data/.ruby-version +1 -0
- data/.solargraph.yml +4 -0
- data/.vscode/settings.json +3 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +87 -0
- data/README.md +172 -14
- data/lib/shimmer/controllers/files_controller.rb +15 -0
- data/lib/shimmer/controllers/sitemaps_controller.rb +10 -0
- data/lib/shimmer/jobs/sitemap_job.rb +10 -0
- data/lib/shimmer/middlewares/cloudflare.rb +17 -0
- data/lib/shimmer/railtie.rb +8 -0
- data/lib/shimmer/tasks/db.rake +42 -0
- data/lib/shimmer/tasks/lint.rake +9 -0
- data/lib/shimmer/utils/file_helper.rb +27 -0
- data/lib/shimmer/utils/file_proxy.rb +65 -0
- data/lib/shimmer/utils/localizable.rb +58 -0
- data/lib/shimmer/utils/remote_navigation.rb +112 -0
- data/lib/shimmer/utils/sitemap_adapter.rb +10 -0
- data/lib/shimmer/version.rb +1 -1
- data/lib/shimmer.rb +5 -0
- data/package.json +51 -0
- data/rollup.config.js +26 -0
- data/src/controllers/remote-navigation.ts +9 -0
- data/src/index.ts +32 -0
- data/src/locale.ts +3 -0
- data/src/modal.ts +73 -0
- data/src/popover.ts +89 -0
- data/src/serviceworker.ts +7 -0
- data/src/touch.ts +20 -0
- data/src/util.ts +31 -0
- data/tsconfig.json +28 -0
- data/typings.d.ts +1 -0
- data/yarn.lock +1055 -0
- metadata +35 -4
- data/shimmer.gemspec +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4c44b134bb61f78f82008a1907c738d358b48147ad6518211b7ffcef9fa4aab
|
4
|
+
data.tar.gz: 4b7eb93d01ed55818f0845498e3b33a531352dde7d72b491addded5a77f81ce5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49e8e4866c5d8bafc59d5ccbcac324afd214d2e83f31845a3ff207400059f25061629261ab494fbaf2d2ce1f8be575f978938f11b347d7e751606724e48b666d
|
7
|
+
data.tar.gz: 1e0892571dc244cd238be164c61d4c1b5480e38a994dc266c1d8e8652102a89efcf4ffa8686dd7d8d439dad8aad5080b2faadaa6b3b426f933567a36e16e7b7e
|
data/.editorconfig
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
; EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
; top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
; Unix-style newlines with a newline ending every file
|
7
|
+
[*]
|
8
|
+
indent_style = spaces
|
9
|
+
end_of_line = lf
|
10
|
+
insert_final_newline = true
|
11
|
+
trim_trailing_whitespace = true
|
12
|
+
indent_size = 2
|
data/.eslintrc.js
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module.exports = {
|
2
|
+
env: {
|
3
|
+
browser: true,
|
4
|
+
es6: true,
|
5
|
+
},
|
6
|
+
parser: "@typescript-eslint/parser",
|
7
|
+
extends: [
|
8
|
+
"plugin:@typescript-eslint/recommended",
|
9
|
+
"plugin:prettier/recommended",
|
10
|
+
],
|
11
|
+
parserOptions: {
|
12
|
+
ecmaVersion: 2018,
|
13
|
+
sourceType: "module",
|
14
|
+
},
|
15
|
+
plugins: ["@typescript-eslint"],
|
16
|
+
rules: {
|
17
|
+
"no-console": 2,
|
18
|
+
"@typescript-eslint/explicit-function-return-type": [
|
19
|
+
"error",
|
20
|
+
{
|
21
|
+
allowExpressions: true,
|
22
|
+
},
|
23
|
+
],
|
24
|
+
},
|
25
|
+
};
|
data/.prettierrc
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.3
|
data/.solargraph.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
shimmer (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
backport (1.2.0)
|
11
|
+
benchmark (0.2.0)
|
12
|
+
diff-lcs (1.4.4)
|
13
|
+
e2mmap (0.1.0)
|
14
|
+
jaro_winkler (1.5.4)
|
15
|
+
kramdown (2.3.1)
|
16
|
+
rexml
|
17
|
+
kramdown-parser-gfm (1.1.0)
|
18
|
+
kramdown (~> 2.0)
|
19
|
+
nokogiri (1.12.5-x86_64-darwin)
|
20
|
+
racc (~> 1.4)
|
21
|
+
nokogiri (1.12.5-x86_64-linux)
|
22
|
+
racc (~> 1.4)
|
23
|
+
parallel (1.21.0)
|
24
|
+
parser (3.0.3.2)
|
25
|
+
ast (~> 2.4.1)
|
26
|
+
racc (1.6.0)
|
27
|
+
rainbow (3.0.0)
|
28
|
+
rake (13.0.6)
|
29
|
+
regexp_parser (2.2.0)
|
30
|
+
reverse_markdown (2.1.1)
|
31
|
+
nokogiri
|
32
|
+
rexml (3.2.5)
|
33
|
+
rubocop (1.23.0)
|
34
|
+
parallel (~> 1.10)
|
35
|
+
parser (>= 3.0.0.0)
|
36
|
+
rainbow (>= 2.2.2, < 4.0)
|
37
|
+
regexp_parser (>= 1.8, < 3.0)
|
38
|
+
rexml
|
39
|
+
rubocop-ast (>= 1.12.0, < 2.0)
|
40
|
+
ruby-progressbar (~> 1.7)
|
41
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
42
|
+
rubocop-ast (1.15.0)
|
43
|
+
parser (>= 3.0.1.1)
|
44
|
+
rubocop-performance (1.12.0)
|
45
|
+
rubocop (>= 1.7.0, < 2.0)
|
46
|
+
rubocop-ast (>= 0.4.0)
|
47
|
+
ruby-progressbar (1.11.0)
|
48
|
+
solargraph (0.44.2)
|
49
|
+
backport (~> 1.2)
|
50
|
+
benchmark
|
51
|
+
bundler (>= 1.17.2)
|
52
|
+
diff-lcs (~> 1.4)
|
53
|
+
e2mmap
|
54
|
+
jaro_winkler (~> 1.5)
|
55
|
+
kramdown (~> 2.3)
|
56
|
+
kramdown-parser-gfm (~> 1.1)
|
57
|
+
parser (~> 3.0)
|
58
|
+
reverse_markdown (>= 1.0.5, < 3)
|
59
|
+
rubocop (>= 0.52)
|
60
|
+
thor (~> 1.0)
|
61
|
+
tilt (~> 2.0)
|
62
|
+
yard (~> 0.9, >= 0.9.24)
|
63
|
+
solargraph-standardrb (0.0.4)
|
64
|
+
solargraph (>= 0.39.1)
|
65
|
+
standard (>= 0.4.1)
|
66
|
+
standard (1.5.0)
|
67
|
+
rubocop (= 1.23.0)
|
68
|
+
rubocop-performance (= 1.12.0)
|
69
|
+
thor (1.1.0)
|
70
|
+
tilt (2.0.10)
|
71
|
+
unicode-display_width (2.1.0)
|
72
|
+
webrick (1.7.0)
|
73
|
+
yard (0.9.27)
|
74
|
+
webrick (~> 1.7.0)
|
75
|
+
|
76
|
+
PLATFORMS
|
77
|
+
x86_64-darwin-21
|
78
|
+
x86_64-linux
|
79
|
+
|
80
|
+
DEPENDENCIES
|
81
|
+
rake (~> 13.0)
|
82
|
+
shimmer!
|
83
|
+
solargraph-standardrb
|
84
|
+
standard
|
85
|
+
|
86
|
+
BUNDLED WITH
|
87
|
+
2.2.32
|
data/README.md
CHANGED
@@ -1,38 +1,196 @@
|
|
1
|
-
# Shimmer
|
1
|
+
# Shimmer - Because Ruby could be more shiny!
|
2
2
|
|
3
|
-
|
3
|
+
Shimmer is a collection of Rails extensions that bring advanced UI features into your app and make your life easier as a developer.
|
4
4
|
|
5
|
-
|
5
|
+
## Features
|
6
|
+
|
7
|
+
### Static File Serving
|
8
|
+
|
9
|
+
`ActiveStorage` is great, but serving of files, especially behind a CDN, can be complicated to get right. This can be fixed easily:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# use an image tag
|
13
|
+
image_tag user.avatar, width: 300
|
14
|
+
```
|
15
|
+
|
16
|
+
This extension overrides `image_tag` and also supplies a matching `image_file_url` that automatically resizes your image and creates a static, cacheable url.
|
17
|
+
|
18
|
+
### Modals
|
19
|
+
|
20
|
+
Modals are the designer's best friend, but developers usually hate them for their complexity. Fear no more: Shimmer has you covered.
|
21
|
+
|
22
|
+
```slim
|
23
|
+
a href=modal_path(new_post_path) Create a new Post
|
24
|
+
```
|
25
|
+
|
26
|
+
This will open a modal on click and then asynchronously request the modal content from the controller. Modals can also be controlled via JavaScript via the global `ui` variable:
|
27
|
+
|
28
|
+
```js
|
29
|
+
ui.modal.open({ url: "/posts/new" });
|
30
|
+
ui.modal.close();
|
31
|
+
```
|
32
|
+
|
33
|
+
### Popovers
|
34
|
+
|
35
|
+
When modals are annoying to implement, popovers are even worse. Thankfully, Shimmer comes to the rescue:
|
36
|
+
|
37
|
+
```slim
|
38
|
+
a href=popover_path(new_post_path, placement: :left)
|
39
|
+
```
|
40
|
+
|
41
|
+
This will request `new_post_path` and display it left of the anchor thanks to PopperJS.
|
42
|
+
|
43
|
+
### Remote Navigation
|
44
|
+
|
45
|
+
Remote navigation takes Hotwire to the next level with built-in navigation actions, integrated with modals and popovers.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
def create
|
49
|
+
@post = current_user.posts.create! post_params
|
50
|
+
ui.navigate_to @post
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
This will automatically close the current modal or popover and navigate via Turbo Drive to the post's url - no redirects necessary.
|
55
|
+
|
56
|
+
The `ui` helper comes with several built-in functions:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
# run any kind of javascript upon request completion
|
60
|
+
ui.run_javascript("alert('hello world')")
|
61
|
+
|
62
|
+
# open or replace a modal's content (dependent on its ID)
|
63
|
+
ui.open_modal(new_post_path, size: :small)
|
64
|
+
|
65
|
+
# close an open modal
|
66
|
+
ui.close_modal
|
67
|
+
|
68
|
+
# same methods also available for popovers
|
69
|
+
ui.open_popover(new_post_path, selector: "#user-profile", placement: :left)
|
70
|
+
ui.close_popover
|
71
|
+
|
72
|
+
# navigate via Turbo Drive
|
73
|
+
ui.navigate_to(@post)
|
74
|
+
|
75
|
+
# manipulate the page's content
|
76
|
+
ui.append(@post, with: "comments/comment", comment: @comment)
|
77
|
+
ui.prepend("#user-profile", with: "users/extra")
|
78
|
+
ui.replace(@post)
|
79
|
+
ui.remove(@post)
|
80
|
+
```
|
81
|
+
|
82
|
+
### Sitemaps
|
83
|
+
|
84
|
+
Want to implement sitemaps, but the ephemeral filesystem of Heroku hates you? Here's a simple way to upload sitemaps:
|
85
|
+
|
86
|
+
- install the sitemap gem and configure the `sitemap.rb` as usual
|
87
|
+
- use the shimmer adapter to automatically upload your sitemap to your configured ActiveStorage adapter
|
88
|
+
- use the shimmer controller to display the sitemap in your app
|
89
|
+
- (optional) tell sidekiq scheduler to regularly update your sitemap
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
# sitemap.rb
|
93
|
+
SitemapGenerator::Sitemap.adapter = Shimmer::SitemapAdapter.new
|
94
|
+
|
95
|
+
# routes.rb
|
96
|
+
get "sitemaps/*path", to: "shimmer/sitemaps#show"
|
97
|
+
|
98
|
+
# sidekiq.yml
|
99
|
+
:schedule:
|
100
|
+
sitemap:
|
101
|
+
cron: '0 0 12 * * * Europe/Berlin' # every day at 16:00, Berlin time
|
102
|
+
class: Shimmer::SitemapJob
|
103
|
+
```
|
104
|
+
|
105
|
+
### Cloudflare Support
|
106
|
+
|
107
|
+
As you might have noticed, Cloudflare SSL will cause some issues with your Rails app if you're not using SSL strict mode (https://github.com/rails/rails/issues/22965). If you can't switch to strict mode, go for the standard flexible mode instead and add this middleware to your stack:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
# application.rb
|
111
|
+
config.middleware.use Shimmer::CloudflareProxy
|
112
|
+
```
|
113
|
+
|
114
|
+
### Heroku Database Helpers
|
115
|
+
|
116
|
+
Can't reproduce an issue with your local test data and just want the production or staging data on your development machine? Here you go:
|
117
|
+
|
118
|
+
```bash
|
119
|
+
rails db:pull
|
120
|
+
```
|
121
|
+
|
122
|
+
This will drop your local database and pull in the database of your connected Heroku app (make sure you executed `heroku git:remote -a your_app` before to have the git remote). But what about assets you might ask? Easy - assets are pulled from S3 as well via the AWS CLI automatically (make sure your environment variables in Heroku are correctly named as `AWS_REGION`, `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`) and the database is updated to use your local filesystem instead.
|
123
|
+
|
124
|
+
If you don't want the asset support, you can also only pull the database or only the assets:
|
125
|
+
|
126
|
+
```bash
|
127
|
+
rails db:pull_data
|
128
|
+
rails db:pull_assets
|
129
|
+
```
|
130
|
+
|
131
|
+
### Localizable Routes with Browser Locale Support
|
132
|
+
|
133
|
+
To localize a page via urls, this will help you tremendously.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
# routes.rb
|
137
|
+
Rails.application.routes.draw do
|
138
|
+
scope "/(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
|
139
|
+
get "login", to: "sessions#new"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
From now on you can prefix your routes with a locale like `/de/login` or `/en/login` and `I18n.locale` will automatically be set. If there is no locale in the url (it's optional), this will automatically use the browser's locale.
|
145
|
+
|
146
|
+
You want to redirect from unlocalized paths? Add a before action to your controller:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
before_action :check_locale
|
150
|
+
```
|
151
|
+
|
152
|
+
Trying to figure out which key a certain translation on the page has? Append `?debug` to the url and `I18n.debug?` will be set - which leads to keys being printed on the page.
|
6
153
|
|
7
154
|
## Installation
|
8
155
|
|
9
156
|
Add this line to your application's Gemfile:
|
10
157
|
|
11
158
|
```ruby
|
12
|
-
gem
|
159
|
+
gem "shimmer"
|
13
160
|
```
|
14
161
|
|
15
162
|
And then execute:
|
16
163
|
|
17
|
-
|
164
|
+
```bash
|
165
|
+
$ bundle install
|
166
|
+
```
|
18
167
|
|
19
|
-
|
168
|
+
Add some configuration to your project:
|
20
169
|
|
21
|
-
|
170
|
+
```ruby
|
171
|
+
# routes.rb
|
22
172
|
|
23
|
-
|
173
|
+
resources :files, only: :show, controller: "shimmer/files"
|
24
174
|
|
25
|
-
|
175
|
+
# application_controller.rb
|
176
|
+
class ApplicationController < ActionController::Base
|
177
|
+
include Shimmer::Localizable
|
178
|
+
include Shimmer::RemoteNavigation
|
179
|
+
end
|
180
|
+
```
|
26
181
|
|
27
|
-
|
182
|
+
```ts
|
183
|
+
// application.ts
|
28
184
|
|
29
|
-
|
185
|
+
import { start } from "@nerdgeschoss/shimmer";
|
186
|
+
import { application } from "controllers/application";
|
30
187
|
|
31
|
-
|
188
|
+
start({ application });
|
189
|
+
```
|
32
190
|
|
33
191
|
## Contributing
|
34
192
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
193
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nerdgeschoss/shimmer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/nerdgeschoss/shimmer/blob/master/CODE_OF_CONDUCT.md).
|
36
194
|
|
37
195
|
## License
|
38
196
|
|
@@ -40,4 +198,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
40
198
|
|
41
199
|
## Code of Conduct
|
42
200
|
|
43
|
-
Everyone interacting in the Shimmer project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
201
|
+
Everyone interacting in the Shimmer project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/nerdgeschoss/shimmer/blob/master/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
class FilesController < ActionController::Base
|
5
|
+
def show
|
6
|
+
expires_in 1.year, public: true
|
7
|
+
request.session_options[:skip] = true # prevents a session cookie from being set (would prevent caching on CDNs)
|
8
|
+
proxy = FileProxy.restore(params.require(:id))
|
9
|
+
send_data proxy.file,
|
10
|
+
filename: proxy.filename.to_s,
|
11
|
+
type: proxy.content_type,
|
12
|
+
disposition: "inline"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# https://github.com/rails/rails/issues/22965
|
4
|
+
module Shimmer
|
5
|
+
class CloudflareProxy
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
return @app.call(env) unless env["HTTP_CF_VISITOR"]
|
12
|
+
|
13
|
+
env["HTTP_X_FORWARDED_PROTO"] = JSON.parse(env["HTTP_CF_VISITOR"])["scheme"]
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :db do
|
4
|
+
desc "Downloads the app database from heroku to local db"
|
5
|
+
task pull_data: :environment do
|
6
|
+
config = ActiveRecord::Base.connection_db_config.config
|
7
|
+
# binding.pry
|
8
|
+
ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] = "1"
|
9
|
+
Rake::Task["db:drop"].invoke
|
10
|
+
ENV["PGUSER"] = config["username"]
|
11
|
+
ENV["PGHOST"] = config["host"]
|
12
|
+
ENV["PGPORT"] = config["port"].to_s
|
13
|
+
sh "heroku pg:pull DATABASE_URL #{config["database"]} --app thefetishtraveller"
|
14
|
+
sh "rails db:environment:set"
|
15
|
+
sh "RAILS_ENV=test rails db:create"
|
16
|
+
end
|
17
|
+
|
18
|
+
task pull_assets: :environment do
|
19
|
+
config = JSON.parse(`heroku config --json`)
|
20
|
+
ENV["AWS_DEFAULT_REGION"] = config.fetch("AWS_REGION")
|
21
|
+
bucket = config.fetch("AWS_BUCKET")
|
22
|
+
ENV["AWS_ACCESS_KEY_ID"] = config.fetch("AWS_ACCESS_KEY_ID")
|
23
|
+
ENV["AWS_SECRET_ACCESS_KEY"] = config.fetch("AWS_SECRET_ACCESS_KEY")
|
24
|
+
storage_folder = Rails.root.join("storage")
|
25
|
+
download_folder = storage_folder.join("downloads")
|
26
|
+
FileUtils.mkdir_p download_folder
|
27
|
+
sh "aws s3 sync s3://#{bucket} #{storage_folder}/downloads"
|
28
|
+
download_folder.each_child do |file|
|
29
|
+
next if file.directory?
|
30
|
+
|
31
|
+
new_path = storage_folder.join file.basename.to_s.then { |e| [e[0..1], e[2..3], e] }.join("/")
|
32
|
+
FileUtils.mkdir_p(new_path.dirname)
|
33
|
+
FileUtils.cp(file, new_path)
|
34
|
+
end
|
35
|
+
# purge variants
|
36
|
+
ActiveStorage::VariantRecord.delete_all
|
37
|
+
ActiveStorage::Blob.update_all(service_name: :local)
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Download all app data, including assets"
|
41
|
+
task pull: [:pull_data, :pull_assets]
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module FileHelper
|
5
|
+
def image_tag(source, **options)
|
6
|
+
return nil if source.blank?
|
7
|
+
|
8
|
+
if source.is_a?(ActiveStorage::Variant) || source.is_a?(ActiveStorage::Attached) || source.is_a?(ActiveStorage::Attachment) || source.is_a?(ActionText::Attachment)
|
9
|
+
attachment = source
|
10
|
+
width = options[:width]
|
11
|
+
height = options[:height]
|
12
|
+
source = image_file_url(source, width: width, height: height)
|
13
|
+
options[:loading] = :lazy
|
14
|
+
options[:srcset] = "#{source} 1x, #{image_file_url(attachment, width: width.to_i * 2, height: height ? height.to_i * 2 : nil)} 2x" if options[:width].present?
|
15
|
+
end
|
16
|
+
super source, options
|
17
|
+
end
|
18
|
+
|
19
|
+
def image_file_url(source, width: nil, height: nil)
|
20
|
+
return if source.blank?
|
21
|
+
return source if source.is_a?(String)
|
22
|
+
|
23
|
+
blob = source.try(:blob) || source
|
24
|
+
Shimmer::FileProxy.new(blob_id: blob.id, width: width, height: height).url
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
class FileProxy
|
5
|
+
attr_reader :blob_id, :resize
|
6
|
+
|
7
|
+
delegate :message_verifier, to: :class
|
8
|
+
delegate :content_type, :filename, to: :blob
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def restore(id)
|
12
|
+
blob_id, resize = message_verifier.verified(id)
|
13
|
+
new blob_id: blob_id, resize: resize
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(blob_id:, resize: nil, width: nil, height: nil)
|
18
|
+
@blob_id = blob_id
|
19
|
+
if !resize && width
|
20
|
+
resize = if height
|
21
|
+
"#{width}x#{height}>"
|
22
|
+
else
|
23
|
+
"#{width}x"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@resize = resize
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def message_verifier
|
31
|
+
@message_verifier ||= ApplicationRecord.signed_id_verifier
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def path
|
36
|
+
Rails.application.routes.url_helpers.file_path(id, locale: nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def url(protocol: Rails.env.production? ? :https : :http)
|
40
|
+
Rails.application.routes.url_helpers.file_url(id, locale: nil, protocol: protocol)
|
41
|
+
end
|
42
|
+
|
43
|
+
def blob
|
44
|
+
@blob ||= ActiveStorage::Blob.find(blob_id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def resizeable
|
48
|
+
resize.present? && !blob.content_type.include?("svg")
|
49
|
+
end
|
50
|
+
|
51
|
+
def variant
|
52
|
+
@variantvariant ||= resizeable ? blob.representation(resize: resize).processed : blob
|
53
|
+
end
|
54
|
+
|
55
|
+
def file
|
56
|
+
@file ||= blob.service.download(variant.key)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def id
|
62
|
+
@id ||= message_verifier.generate([blob_id, resize])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shimmer
|
4
|
+
module Localizable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_action :set_locale
|
9
|
+
|
10
|
+
def default_url_options(options = {})
|
11
|
+
options = {locale: I18n.locale}.merge options
|
12
|
+
options[:debug] = true if I18n.debug?
|
13
|
+
options
|
14
|
+
end
|
15
|
+
|
16
|
+
def request_locale
|
17
|
+
request.env["HTTP_ACCEPT_LANGUAGE"].to_s[0..1].downcase.presence&.then { |e| e if I18n.available_locales.include?(e.to_sym) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_locale
|
21
|
+
I18n.locale = url_locale || request_locale || I18n.default_locale
|
22
|
+
I18n.debug = params.key?(:debug)
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_locale
|
26
|
+
redirect_to url_for(locale: I18n.locale) if params[:locale].blank? && request.get? && request.format.html?
|
27
|
+
end
|
28
|
+
|
29
|
+
def url_locale
|
30
|
+
params[:locale]
|
31
|
+
end
|
32
|
+
|
33
|
+
I18n.class_eval do
|
34
|
+
thread_mattr_accessor :debug
|
35
|
+
|
36
|
+
class << self
|
37
|
+
alias_method :old_translate, :translate
|
38
|
+
def translate(key, options = {})
|
39
|
+
untranslated_scopes = ["number", "transliterate", "date", "datetime", "errors", "helpers", "support", "time", "faker"].map { |k| "#{k}." }
|
40
|
+
key = key.to_s.downcase
|
41
|
+
untranslated = untranslated_scopes.any? { |e| key.include? e }
|
42
|
+
key_name = [options[:scope], key].flatten.compact.join(".")
|
43
|
+
option_names = options.except(:count, :default, :raise, :scope).map { |k, v| "#{k}=#{v}" }.join(", ")
|
44
|
+
return "#{key_name} #{option_names}" if I18n.debug && !untranslated
|
45
|
+
|
46
|
+
options.reverse_merge!(default: old_translate(key, **options.merge(locale: :de))) if untranslated
|
47
|
+
old_translate(key, **options)
|
48
|
+
end
|
49
|
+
alias_method :t, :translate
|
50
|
+
|
51
|
+
def debug?
|
52
|
+
debug
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|