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.
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