rubyblok 1.0.0 → 1.2.0
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/.rubocop.yml +0 -139
- data/CHANGELOG.md +23 -0
- data/README.md +120 -92
- data/Rakefile +1 -1
- data/lib/generators/rubyblok/hello_world_generator.rb +45 -0
- data/lib/generators/rubyblok/image_cache_generator.rb +77 -0
- data/lib/generators/rubyblok/install_generator.rb +7 -5
- data/lib/generators/rubyblok/migration_generator.rb +10 -8
- data/lib/generators/rubyblok/sitemap_config_generator.rb +40 -0
- data/lib/generators/rubyblok/webhook_controller_generator.rb +9 -7
- data/lib/generators/templates/carrier_wave_config.rb.erb +13 -0
- data/lib/generators/templates/hello_world_generator/_feature.html.erb +3 -0
- data/lib/generators/templates/hello_world_generator/_grid.html.erb +3 -0
- data/lib/generators/templates/hello_world_generator/_page.html.erb +1 -0
- data/lib/generators/templates/hello_world_generator/_teaser.html.erb +3 -0
- data/lib/generators/templates/hello_world_generator/controller.rb.erb +9 -0
- data/lib/generators/templates/hello_world_generator/index.html.erb +5 -0
- data/lib/generators/templates/hello_world_generator/styles.css +54 -0
- data/lib/generators/templates/image_cache_model.rb.erb +3 -0
- data/lib/generators/templates/image_cache_uploader.rb.erb +12 -0
- data/lib/generators/templates/migration_create_image_cache.rb.erb +12 -0
- data/lib/generators/templates/migration_update_image_cache.rb.erb +8 -0
- data/lib/generators/templates/rubyblok.rb +27 -6
- data/lib/generators/templates/sitemap.rb.erb +14 -0
- data/lib/rubyblok/configuration.rb +4 -3
- data/lib/rubyblok/helpers/storyblok_helper.rb +50 -17
- data/lib/rubyblok/mixins/model.rb +14 -0
- data/lib/rubyblok/mixins/webhook.rb +8 -4
- data/lib/rubyblok/railtie.rb +4 -2
- data/lib/rubyblok/services/get_storyblok_story.rb +5 -3
- data/lib/rubyblok/services/replace_storyblok_url.rb +64 -0
- data/lib/rubyblok/version.rb +1 -1
- data/lib/rubyblok.rb +17 -14
- data/rubyblok.gemspec +17 -17
- metadata +21 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module Rubyblok
|
|
6
|
+
module Generators
|
|
7
|
+
class SitemapConfigGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path('../templates', __dir__)
|
|
9
|
+
|
|
10
|
+
desc 'Generates a configuration for the sitemap_generator gem'
|
|
11
|
+
|
|
12
|
+
def generate_sitemap_config
|
|
13
|
+
copy_config
|
|
14
|
+
add_sitemap_generator_gem
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def copy_config
|
|
20
|
+
template('sitemap.rb.erb', 'config/sitemap.rb')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def add_sitemap_generator_gem
|
|
24
|
+
append_to_file(gemfile_path) { "gem 'sitemap_generator'" } if add_sitemap_generator_gem?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def add_sitemap_generator_gem?
|
|
28
|
+
!gemfile_content.match?(/\bsitemap_generator\b/)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def gemfile_content
|
|
32
|
+
File.read(gemfile_path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def gemfile_path
|
|
36
|
+
Rails.root.join('Gemfile')
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
3
5
|
|
|
4
6
|
module Rubyblok
|
|
5
7
|
module Generators
|
|
6
8
|
class WebhookControllerGenerator < ::Rails::Generators::NamedBase
|
|
7
|
-
source_root File.expand_path(
|
|
9
|
+
source_root File.expand_path('../templates', __dir__)
|
|
8
10
|
|
|
9
|
-
desc
|
|
11
|
+
desc 'Generates a webhook controller and a route file.'
|
|
10
12
|
|
|
11
13
|
def copy_initializer
|
|
12
|
-
template(
|
|
14
|
+
template('webhook_controller.rb.erb', "app/controllers/#{file_name}_controller.rb")
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def routes_config
|
|
16
|
-
destination_path =
|
|
17
|
-
insert_into_file destination_path, after:
|
|
18
|
+
destination_path = 'config/routes.rb'
|
|
19
|
+
insert_into_file destination_path, after: 'Rails.application.routes.draw do' do
|
|
18
20
|
routes_content
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
CarrierWave.configure do |config|
|
|
2
|
+
config.fog_credentials = {
|
|
3
|
+
provider: 'AWS',
|
|
4
|
+
aws_access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID', nil),
|
|
5
|
+
aws_secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY', nil),
|
|
6
|
+
region: ENV.fetch('AWS_DEFAULT_REGION', nil),
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
config.asset_host = ENV.fetch('AWS_CLOUDFRONT_UPLOADS_HOST', nil)
|
|
10
|
+
config.fog_directory = ENV.fetch('AWS_UPLOADS_DIRECTORY', nil)
|
|
11
|
+
config.fog_public = true
|
|
12
|
+
config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" }
|
|
13
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%%= rubyblok_blocks_tag(blok.body) %>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
.page {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
background: #FFF;
|
|
7
|
+
color: #1B243F;
|
|
8
|
+
width: 100%;
|
|
9
|
+
min-height: 100svh;
|
|
10
|
+
padding: 0;
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-family: sans-serif;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.teaser {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
align-items: center;
|
|
19
|
+
padding: 2rem 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.headline {
|
|
23
|
+
font-size: 2rem;
|
|
24
|
+
font-weight: 700;
|
|
25
|
+
margin-bottom: 1rem;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.feature {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
padding: 2rem;
|
|
34
|
+
background: #00B3B0;
|
|
35
|
+
border-radius: 0.5rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.name {
|
|
39
|
+
color: #FFF;
|
|
40
|
+
font-size: 1.25rem;
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.columns {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
gap: 1rem;
|
|
48
|
+
|
|
49
|
+
@media (min-width: 768px) {
|
|
50
|
+
display: grid;
|
|
51
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
52
|
+
gap: 1rem;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class <%= class_name %>Uploader < CarrierWave::Uploader::Base
|
|
2
|
+
storage :fog
|
|
3
|
+
|
|
4
|
+
def store_dir
|
|
5
|
+
model_name = model.model_name.singular
|
|
6
|
+
"uploads/#{model_name}/#{mounted_as}/#{model.id}"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def extension_allowlist
|
|
10
|
+
%w[gif jpeg jpg png svg mp4]
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class Create<%= class_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def change
|
|
3
|
+
create_table :<%= table_name %> do |t|
|
|
4
|
+
t.string :original_image_url
|
|
5
|
+
t.string :image
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
add_index :<%= table_name %>, :original_image_url, unique: true
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class Update<%= class_name.pluralize %> < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def change
|
|
3
|
+
add_column :<%= table_name %>, :original_image_url, :string
|
|
4
|
+
add_column :<%= table_name %>, :image, :string
|
|
5
|
+
|
|
6
|
+
add_index :<%= table_name %>, :storyblok_story_slug, unique: true
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
Rubyblok.configure do |config|
|
|
4
|
-
|
|
4
|
+
# Storyblok API token
|
|
5
|
+
config.api_token = ENV.fetch('STORYBLOK_API_TOKEN', nil)
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
config.version
|
|
8
|
-
config.webhook_secret = ENV["STORYBLOK_WEBHOOK_SECRET"]
|
|
7
|
+
# Storyblok story version (draft or published)
|
|
8
|
+
config.version = ENV.fetch('STORYBLOK_VERSION', 'draft')
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
config.
|
|
10
|
+
# Name of the model that stores Storyblok stories
|
|
11
|
+
config.model_name = ''
|
|
12
|
+
|
|
13
|
+
# Directory contains rubyblok partials (relative to app/views)
|
|
14
|
+
config.component_path = 'shared/storyblok'
|
|
15
|
+
|
|
16
|
+
# Feature flag that enables cached mode
|
|
17
|
+
config.cached = ActiveModel::Type::Boolean.new.cast(ENV.fetch('STORYBLOK_CACHED', false))
|
|
18
|
+
|
|
19
|
+
# Feature flag that enables auto update of local cache
|
|
20
|
+
config.auto_update = ActiveModel::Type::Boolean.new.cast(ENV.fetch('STORYBLOK_AUTOUPDATE', false))
|
|
21
|
+
|
|
22
|
+
# Feature flag that enables caching storyblok images
|
|
23
|
+
config.use_cdn_images = ActiveModel::Type::Boolean.new.cast(ENV.fetch('STORYBLOK_CDN_IMAGES', false))
|
|
24
|
+
|
|
25
|
+
# Name of the model that stores Storyblok cached images
|
|
26
|
+
config.image_model_name = ''
|
|
27
|
+
|
|
28
|
+
# Storyblok webhook token
|
|
29
|
+
config.webhook_secret = ENV.fetch('STORYBLOK_WEBHOOK_SECRET', nil)
|
|
30
|
+
|
|
31
|
+
# Feature flag that enables caching view fragments
|
|
32
|
+
config.cache_views = ActiveModel::Type::Boolean.new.cast(ENV.fetch('STORYBLOK_CACHE_VIEWS', false))
|
|
12
33
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'sitemap_generator'
|
|
4
|
+
|
|
5
|
+
# TODO: Configure your hostname here
|
|
6
|
+
SitemapGenerator::Sitemap.default_host = ''
|
|
7
|
+
|
|
8
|
+
if Rubyblok.configuration.cached
|
|
9
|
+
SitemapGenerator::Sitemap.create do
|
|
10
|
+
model = Rubyblok.configuration.model_name.classify.constantize
|
|
11
|
+
pages = model.all.select { |page| page.storyblok_story_content.dig('content', 'no_index') == false }
|
|
12
|
+
pages.each { |page| add(page.storyblok_story_slug, lastmod: page.updated_at) }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Rubyblok
|
|
2
4
|
class Configuration
|
|
3
|
-
attr_accessor :api_token, :
|
|
4
|
-
|
|
5
|
-
attr_writer :property
|
|
5
|
+
attr_accessor :api_token, :auto_update, :cached, :cache_views, :component_path, :image_model_name,
|
|
6
|
+
:model_name, :use_cdn_images, :version, :webhook_secret
|
|
6
7
|
end
|
|
7
8
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module StoryblokHelper
|
|
2
4
|
def rubyblok_content_tag(content)
|
|
3
5
|
return if content.blank?
|
|
@@ -10,8 +12,17 @@ module StoryblokHelper
|
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def rubyblok_story_tag(slug)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
story = get_story(slug)
|
|
16
|
+
content = story['content'].to_dot
|
|
17
|
+
|
|
18
|
+
template = <<-ERB
|
|
19
|
+
<% cache_key = "rubyblok/#{story['id']}-#{Digest::SHA1.hexdigest(story.to_json)}" %>
|
|
20
|
+
<% cache_if use_cache, cache_key do %>
|
|
21
|
+
<%= rubyblok_component_tag(partial: content.component, blok: content) %>
|
|
22
|
+
<% end %>
|
|
23
|
+
ERB
|
|
24
|
+
|
|
25
|
+
render_inline_partial template:, locals: { content:, use_cache: Rubyblok.configuration.cache_views }
|
|
15
26
|
end
|
|
16
27
|
|
|
17
28
|
def rubyblok_component_tag(blok:, partial: blok.component)
|
|
@@ -37,34 +48,48 @@ module StoryblokHelper
|
|
|
37
48
|
render_inline_partial template:, locals: { bloks: }
|
|
38
49
|
end
|
|
39
50
|
|
|
51
|
+
def get_story_content(slug)
|
|
52
|
+
get_story(slug)['content'].to_dot
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
40
57
|
def get_story(slug)
|
|
41
|
-
|
|
42
|
-
|
|
58
|
+
return get_story_via_api(slug) unless cached?
|
|
59
|
+
|
|
60
|
+
if update_storyblok?
|
|
61
|
+
get_story_via_api(slug, save: true)
|
|
43
62
|
else
|
|
44
|
-
|
|
63
|
+
get_story_via_cache(slug)
|
|
45
64
|
end
|
|
46
65
|
end
|
|
47
66
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
def get_story_via_api(slug, save: false)
|
|
68
|
+
story = Rubyblok::Services::GetStoryblokStory.call(slug:)
|
|
69
|
+
replace_storyblok_url(story).tap do |storyblok_story|
|
|
70
|
+
model.find_or_create(storyblok_story) if save
|
|
71
|
+
end
|
|
52
72
|
end
|
|
53
73
|
|
|
54
74
|
def get_story_via_cache(slug)
|
|
55
|
-
|
|
75
|
+
model.fetch_content(slug)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def replace_storyblok_url(story)
|
|
79
|
+
Rubyblok::Services::ReplaceStoryblokUrl.call(story:)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def model
|
|
83
|
+
Rubyblok.configuration.model_name.classify.constantize
|
|
56
84
|
end
|
|
57
85
|
|
|
58
|
-
def rich_text_renderer
|
|
86
|
+
def rich_text_renderer
|
|
59
87
|
ctx = {}
|
|
60
88
|
path = component_path
|
|
61
89
|
@rich_text_renderer ||=
|
|
62
90
|
Storyblok::Richtext::HtmlRenderer.new.tap do |html_renderer|
|
|
63
91
|
html_renderer.set_component_resolver(lambda { |component, data|
|
|
64
|
-
ApplicationController.render(
|
|
65
|
-
partial: "#{path}/#{component}",
|
|
66
|
-
locals: ctx.merge(blok: data)
|
|
67
|
-
)
|
|
92
|
+
ApplicationController.render(partial: "#{path}/#{component}", locals: ctx.merge(blok: data))
|
|
68
93
|
})
|
|
69
94
|
end
|
|
70
95
|
end
|
|
@@ -75,7 +100,7 @@ module StoryblokHelper
|
|
|
75
100
|
|
|
76
101
|
# rubocop:disable Rails/OutputSafety
|
|
77
102
|
def rubyblok_editable_tag(component)
|
|
78
|
-
component[
|
|
103
|
+
component['_editable']&.html_safe
|
|
79
104
|
end
|
|
80
105
|
# rubocop:enable Rails/OutputSafety
|
|
81
106
|
|
|
@@ -91,7 +116,15 @@ module StoryblokHelper
|
|
|
91
116
|
ApplicationController.render inline: template, locals:
|
|
92
117
|
end
|
|
93
118
|
|
|
94
|
-
def
|
|
119
|
+
def cached?
|
|
95
120
|
Rubyblok.configuration.cached
|
|
96
121
|
end
|
|
122
|
+
|
|
123
|
+
def auto_update?
|
|
124
|
+
Rubyblok.configuration.auto_update
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def update_storyblok?
|
|
128
|
+
auto_update? || params[:storyblok] == 'update'
|
|
129
|
+
end
|
|
97
130
|
end
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/concern'
|
|
4
|
+
|
|
1
5
|
module Rubyblok
|
|
2
6
|
module Mixins
|
|
3
7
|
module Model
|
|
@@ -15,6 +19,16 @@ module Rubyblok
|
|
|
15
19
|
def fetch_content(slug)
|
|
16
20
|
find_by(storyblok_story_slug: slug)&.storyblok_story_content
|
|
17
21
|
end
|
|
22
|
+
|
|
23
|
+
def find_or_create(story)
|
|
24
|
+
return if story.blank?
|
|
25
|
+
|
|
26
|
+
find_or_initialize_by(storyblok_story_id: story['id']).tap do |model|
|
|
27
|
+
model.storyblok_story_content = story
|
|
28
|
+
model.storyblok_story_slug = story['full_slug']
|
|
29
|
+
model.save
|
|
30
|
+
end
|
|
31
|
+
end
|
|
18
32
|
end
|
|
19
33
|
end
|
|
20
34
|
end
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/concern'
|
|
4
|
+
|
|
1
5
|
module Rubyblok
|
|
2
6
|
module Mixins
|
|
3
7
|
module Webhook
|
|
@@ -9,11 +13,11 @@ module Rubyblok
|
|
|
9
13
|
def create
|
|
10
14
|
payload = JSON.parse(request.raw_post)
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
storyblok_story = Rubyblok::Services::GetStoryblokStory.call(slug: payload['story_id'])
|
|
17
|
+
storyblok_story = Rubyblok::Services::ReplaceStoryblokUrl.call(story: storyblok_story)
|
|
18
|
+
model.find_or_create(storyblok_story)
|
|
15
19
|
|
|
16
|
-
render
|
|
20
|
+
render(json: { success: true })
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
private
|
data/lib/rubyblok/railtie.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'helpers/storyblok_helper'
|
|
2
4
|
|
|
3
5
|
module Rubyblok
|
|
4
6
|
class Railtie < Rails::Railtie
|
|
5
|
-
initializer
|
|
7
|
+
initializer 'rubyblok.storyblok_helper' do
|
|
6
8
|
ActiveSupport.on_load(:action_view) { include StoryblokHelper }
|
|
7
9
|
end
|
|
8
10
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Rubyblok
|
|
2
4
|
module Services
|
|
3
5
|
class GetStoryblokStory
|
|
@@ -15,15 +17,15 @@ module Rubyblok
|
|
|
15
17
|
|
|
16
18
|
private
|
|
17
19
|
|
|
18
|
-
def storyblok_client
|
|
20
|
+
def storyblok_client
|
|
19
21
|
Storyblok::Client.new(
|
|
20
22
|
token: Rubyblok.configuration.api_token,
|
|
21
23
|
version: Rubyblok.configuration.version
|
|
22
24
|
)
|
|
23
25
|
end
|
|
24
26
|
|
|
25
|
-
def get_story
|
|
26
|
-
storyblok_client.story(@slug)[
|
|
27
|
+
def get_story # rubocop:disable Naming/AccessorMethodName
|
|
28
|
+
storyblok_client.story(@slug)['data']['story']
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rubyblok
|
|
4
|
+
module Services
|
|
5
|
+
class ReplaceStoryblokUrl
|
|
6
|
+
attr_reader :story
|
|
7
|
+
|
|
8
|
+
def self.call(story:)
|
|
9
|
+
new(story:).call
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(story:)
|
|
13
|
+
@story = story
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
return story unless use_cdn_images?
|
|
18
|
+
|
|
19
|
+
image_fields = find_image_fields(story['content'])
|
|
20
|
+
image_fields.each do |image_field|
|
|
21
|
+
replace_url(image_field)
|
|
22
|
+
end
|
|
23
|
+
story
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# It finds image fields based on their "fieldtype"=>"asset" attribute.
|
|
29
|
+
# Please note that it caches only images added as an 'Asset' field type in Storyblok.
|
|
30
|
+
def find_image_fields(content)
|
|
31
|
+
return [content] if image_field?(content)
|
|
32
|
+
|
|
33
|
+
content.values.each_with_object([]) do |field_value, image_fields|
|
|
34
|
+
case field_value
|
|
35
|
+
when Array
|
|
36
|
+
field_value.each { |component| image_fields << find_image_fields(component) }
|
|
37
|
+
when Hash
|
|
38
|
+
image_fields << find_image_fields(field_value)
|
|
39
|
+
end
|
|
40
|
+
end.flatten
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def image_field?(field)
|
|
44
|
+
field['fieldtype'] == 'asset'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def replace_url(image_field)
|
|
48
|
+
url = image_field['filename']
|
|
49
|
+
image =
|
|
50
|
+
image_model.create_with(remote_image_url: url).find_or_create_by(original_image_url: url)
|
|
51
|
+
|
|
52
|
+
image_field['filename'] = image.image.url if image.persisted?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def image_model
|
|
56
|
+
Rubyblok.configuration.image_model_name.classify.constantize
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def use_cdn_images?
|
|
60
|
+
Rubyblok.configuration.use_cdn_images
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/rubyblok/version.rb
CHANGED
data/lib/rubyblok.rb
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require 'storyblok'
|
|
4
|
+
require 'redcarpet'
|
|
5
|
+
require 'hash_dot'
|
|
6
6
|
|
|
7
|
-
require_relative
|
|
8
|
-
require_relative
|
|
9
|
-
require_relative
|
|
10
|
-
require_relative
|
|
11
|
-
require_relative
|
|
12
|
-
require_relative
|
|
13
|
-
require_relative
|
|
14
|
-
require_relative
|
|
15
|
-
|
|
16
|
-
require_relative
|
|
17
|
-
require_relative
|
|
7
|
+
require_relative 'rubyblok/helpers/storyblok_helper'
|
|
8
|
+
require_relative 'rubyblok/version'
|
|
9
|
+
require_relative 'rubyblok/configuration'
|
|
10
|
+
require_relative 'rubyblok/railtie' if defined?(Rails)
|
|
11
|
+
require_relative 'rubyblok/services/get_storyblok_story'
|
|
12
|
+
require_relative 'rubyblok/services/replace_storyblok_url'
|
|
13
|
+
require_relative 'rubyblok/mixins/model'
|
|
14
|
+
require_relative 'rubyblok/mixins/webhook'
|
|
15
|
+
require_relative 'generators/rubyblok/migration_generator'
|
|
16
|
+
require_relative 'generators/rubyblok/install_generator'
|
|
17
|
+
require_relative 'generators/rubyblok/webhook_controller_generator'
|
|
18
|
+
require_relative 'generators/rubyblok/hello_world_generator'
|
|
19
|
+
require_relative 'generators/rubyblok/sitemap_config_generator'
|
|
20
|
+
require_relative 'generators/rubyblok/image_cache_generator'
|
|
18
21
|
|
|
19
22
|
module Rubyblok
|
|
20
23
|
def self.configuration
|
data/rubyblok.gemspec
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative 'lib/rubyblok/version'
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name =
|
|
6
|
+
spec.name = 'rubyblok'
|
|
7
7
|
spec.version = Rubyblok::VERSION
|
|
8
|
-
spec.license =
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
8
|
+
spec.license = 'MIT'
|
|
9
|
+
spec.authors = ['100 Starlings']
|
|
10
|
+
spec.email = ['rubyblok@100starlings.com']
|
|
11
11
|
|
|
12
|
-
spec.summary =
|
|
13
|
-
spec.homepage =
|
|
14
|
-
spec.required_ruby_version =
|
|
12
|
+
spec.summary = 'Simple Storyblok CMS integration for Rails'
|
|
13
|
+
spec.homepage = 'http://www.rubyblok.com'
|
|
14
|
+
spec.required_ruby_version = '>= 3.1.0'
|
|
15
15
|
|
|
16
|
-
spec.metadata[
|
|
17
|
-
spec.metadata[
|
|
16
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
17
|
+
spec.metadata['source_code_uri'] = 'https://github.com/100Starlings/rubyblok'
|
|
18
18
|
|
|
19
19
|
spec.files = Dir.chdir(__dir__) do
|
|
20
20
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
@@ -22,14 +22,14 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
|
-
spec.bindir =
|
|
25
|
+
spec.bindir = 'exe'
|
|
26
26
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
27
|
-
spec.require_paths = [
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
28
|
|
|
29
|
-
spec.add_dependency
|
|
30
|
-
spec.add_dependency
|
|
31
|
-
spec.add_dependency
|
|
32
|
-
spec.add_dependency
|
|
29
|
+
spec.add_dependency 'hash_dot', '~> 2.5'
|
|
30
|
+
spec.add_dependency 'railties', '~> 7.1'
|
|
31
|
+
spec.add_dependency 'redcarpet', '~> 3.6.0'
|
|
32
|
+
spec.add_dependency 'storyblok', '~> 3.2.0'
|
|
33
33
|
|
|
34
|
-
spec.metadata[
|
|
34
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
35
35
|
end
|