rubyblok 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -139
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +120 -92
  5. data/Rakefile +1 -1
  6. data/lib/generators/rubyblok/hello_world_generator.rb +45 -0
  7. data/lib/generators/rubyblok/image_cache_generator.rb +77 -0
  8. data/lib/generators/rubyblok/install_generator.rb +7 -5
  9. data/lib/generators/rubyblok/migration_generator.rb +10 -8
  10. data/lib/generators/rubyblok/sitemap_config_generator.rb +40 -0
  11. data/lib/generators/rubyblok/webhook_controller_generator.rb +9 -7
  12. data/lib/generators/templates/carrier_wave_config.rb.erb +13 -0
  13. data/lib/generators/templates/hello_world_generator/_feature.html.erb +3 -0
  14. data/lib/generators/templates/hello_world_generator/_grid.html.erb +3 -0
  15. data/lib/generators/templates/hello_world_generator/_page.html.erb +1 -0
  16. data/lib/generators/templates/hello_world_generator/_teaser.html.erb +3 -0
  17. data/lib/generators/templates/hello_world_generator/controller.rb.erb +9 -0
  18. data/lib/generators/templates/hello_world_generator/index.html.erb +5 -0
  19. data/lib/generators/templates/hello_world_generator/styles.css +54 -0
  20. data/lib/generators/templates/image_cache_model.rb.erb +3 -0
  21. data/lib/generators/templates/image_cache_uploader.rb.erb +12 -0
  22. data/lib/generators/templates/migration_create_image_cache.rb.erb +12 -0
  23. data/lib/generators/templates/migration_update_image_cache.rb.erb +8 -0
  24. data/lib/generators/templates/rubyblok.rb +27 -6
  25. data/lib/generators/templates/sitemap.rb.erb +14 -0
  26. data/lib/rubyblok/configuration.rb +4 -3
  27. data/lib/rubyblok/helpers/storyblok_helper.rb +50 -17
  28. data/lib/rubyblok/mixins/model.rb +14 -0
  29. data/lib/rubyblok/mixins/webhook.rb +8 -4
  30. data/lib/rubyblok/railtie.rb +4 -2
  31. data/lib/rubyblok/services/get_storyblok_story.rb +5 -3
  32. data/lib/rubyblok/services/replace_storyblok_url.rb +64 -0
  33. data/lib/rubyblok/version.rb +1 -1
  34. data/lib/rubyblok.rb +17 -14
  35. data/rubyblok.gemspec +17 -17
  36. 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
- require "rails/generators"
2
- require "rails/generators/active_record"
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("../templates", __dir__)
9
+ source_root File.expand_path('../templates', __dir__)
8
10
 
9
- desc "Generates a webhook controller and a route file."
11
+ desc 'Generates a webhook controller and a route file.'
10
12
 
11
13
  def copy_initializer
12
- template("webhook_controller.rb.erb", "app/controllers/#{file_name}_controller.rb")
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 = "config/routes.rb"
17
- insert_into_file destination_path, after: "Rails.application.routes.draw do" do
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,3 @@
1
+ <div class="feature">
2
+ <span class="name"><%%= blok.name %></span>
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="columns">
2
+ <%%= rubyblok_blocks_tag(blok.columns) %>
3
+ </div>
@@ -0,0 +1 @@
1
+ <%%= rubyblok_blocks_tag(blok.body) %>
@@ -0,0 +1,3 @@
1
+ <div class="teaser">
2
+ <span class="headline"><%%= blok.headline %></span>
3
+ </div>
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= class_name.pluralize %>Controller < ApplicationController
4
+ include StoryblokHelper
5
+
6
+ def index
7
+ @slug = "home"
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ <%%= stylesheet_link_tag("hello.css") %>
2
+
3
+ <div class="page">
4
+ <%%= rubyblok_story_tag(@slug) %>
5
+ </div>
@@ -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,3 @@
1
+ class <%= class_name %> < ApplicationRecord
2
+ mount_uploader :image, <%= class_name %>Uploader
3
+ end
@@ -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
- config.cached = true
4
+ # Storyblok API token
5
+ config.api_token = ENV.fetch('STORYBLOK_API_TOKEN', nil)
5
6
 
6
- config.api_token = ENV["STORYBLOK_API_TOKEN"]
7
- config.version = ENV["STORYBLOK_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
- config.model_name = ""
11
- config.component_path = "shared/storyblok"
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, :version, :component_path, :webhook_secret, :model_name, :cached
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
- content = get_story(slug)
14
- rubyblok_component_tag(partial: content.component, blok: content)
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
- if use_cache?
42
- get_story_via_cache(slug)["content"].to_dot
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
- get_story_via_api(slug)["content"].to_dot
63
+ get_story_via_cache(slug)
45
64
  end
46
65
  end
47
66
 
48
- private
49
-
50
- def get_story_via_api(slug)
51
- Rubyblok::Services::GetStoryblokStory.call(slug:)
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
- Rubyblok.configuration.model_name.classify.constantize.fetch_content(slug)
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 # rubocop:disable Metrics/MethodLength
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["_editable"]&.html_safe
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 use_cache?
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
- storyblok_story_content = Rubyblok::Services::GetStoryblokStory.call(slug: payload["story_id"])
13
- model.find_or_initialize_by(storyblok_story_id: payload["story_id"])
14
- .update(storyblok_story_content:, storyblok_story_slug: storyblok_story_content["full_slug"])
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 json: { success: true }
20
+ render(json: { success: true })
17
21
  end
18
22
 
19
23
  private
@@ -1,8 +1,10 @@
1
- require_relative "helpers/storyblok_helper"
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 "rubyblok.storyblok_helper" do
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(version: "draft") # rubocop:disable Lint/UnusedMethodArgument
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)["data"]["story"]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubyblok
4
- VERSION = "1.0.0"
4
+ VERSION = '1.2.0'
5
5
  end
data/lib/rubyblok.rb CHANGED
@@ -1,20 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hash_dot"
4
- require "rails"
5
- require "action_controller"
3
+ require 'storyblok'
4
+ require 'redcarpet'
5
+ require 'hash_dot'
6
6
 
7
- require_relative "rubyblok/helpers/storyblok_helper"
8
- require_relative "rubyblok/version"
9
- require_relative "rubyblok/configuration"
10
- require_relative "rubyblok/services/get_storyblok_story"
11
- require_relative "rubyblok/railtie" if defined?(Rails)
12
- require_relative "rubyblok/mixins/model"
13
- require_relative "generators/rubyblok/migration_generator"
14
- require_relative "generators/rubyblok/install_generator"
15
-
16
- require_relative "rubyblok/mixins/webhook"
17
- require_relative "generators/rubyblok/webhook_controller_generator"
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 "lib/rubyblok/version"
3
+ require_relative 'lib/rubyblok/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "rubyblok"
6
+ spec.name = 'rubyblok'
7
7
  spec.version = Rubyblok::VERSION
8
- spec.license = "MIT"
9
- spec.authors = ["100 Starlings"]
10
- spec.email = ["rubyblok@100starlings.com"]
8
+ spec.license = 'MIT'
9
+ spec.authors = ['100 Starlings']
10
+ spec.email = ['rubyblok@100starlings.com']
11
11
 
12
- spec.summary = "Simple Storyblok CMS integration for Rails"
13
- spec.homepage = "http://www.rubyblok.com"
14
- spec.required_ruby_version = ">= 3.1.0"
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["homepage_uri"] = spec.homepage
17
- spec.metadata["source_code_uri"] = "https://github.com/100Starlings/rubyblok"
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 = "exe"
25
+ spec.bindir = 'exe'
26
26
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
- spec.require_paths = ["lib"]
27
+ spec.require_paths = ['lib']
28
28
 
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"
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["rubygems_mfa_required"] = "true"
34
+ spec.metadata['rubygems_mfa_required'] = 'true'
35
35
  end