view_component 2.25.1 → 2.29.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.

Potentially problematic release.


This version of view_component might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c411f9f34b25054093f7abe23c5842c7523f083ecdb1ba586429545548eca423
4
- data.tar.gz: 744c27c0907544dfb93eb37ecf47c74dd7df86855c0e2b91f9619a77bd8eefc8
3
+ metadata.gz: f8c387807061db7889dbc2e49ccb75a15a2cacd416048a6681b046eb321fb27b
4
+ data.tar.gz: fbddc58ff50b3ddaf615f773a681a7a8b7bef3972581dad8b87bf8425efff275
5
5
  SHA512:
6
- metadata.gz: bee62ecbcfecbc53146b8a8e55207baf2d14769adda2bb2349494a82224acf12fa6584bfc32512e96474f28f011823f2c5712cbc021773d439c43fab8b090503
7
- data.tar.gz: 3f519b85b066d89fdf75afb17563cb868bb4fb673caa21326661f0738b9b4398af068421064ca6f77abf08b7b46bdc549c132252b111b8fb3009809d430b9682
6
+ metadata.gz: 63a070fc0a5001b888dbd57a2a9fb0660b351a05b522d9a832efdd2a60f981d218eda2f500a50d01ca6a8c5ada4cccb61f2837e7b956215e89528d9454d3fd39
7
+ data.tar.gz: 8176f0427272a8305a520eeaa72ae58be2d9df42282a981f376eb69ac0543017f98d737ecb09f6fa6fc8cacf85adbbf82fbefe337da22432448ab361f35ae447
data/CHANGELOG.md CHANGED
@@ -2,6 +2,75 @@
2
2
 
3
3
  ## main
4
4
 
5
+ ## 2.29.0
6
+
7
+ * Allow Slot lambdas to share data from the parent component and allow chaining on the returned component.
8
+
9
+ *Sjors Baltus, Blake Williams*
10
+
11
+ * Experimental: Add `ViewComponent::Translatable`
12
+ * `t` and `translate` now will look first into the sidecar YAML translations file.
13
+ * `helpers.t` and `I18n.t` still reference the global Rails translation files.
14
+ * `l` and `localize` will still reference the global Rails translation files.
15
+
16
+ *Elia Schito*
17
+
18
+ * Fix rendering output of pass through slots when using HAML.
19
+
20
+ *Alex Robbin, Blake Williams*
21
+
22
+ * Experimental: call `._sidecar_files` to fetch the sidecar files for a given list of extensions, e.g. passing `["yml", "yaml"]`.
23
+
24
+ *Elia Schito*
25
+
26
+ * Fix bug where a single `jbuilder` template matched multiple template handlers.
27
+
28
+ *Niels Slot*
29
+
30
+ ## 2.28.0
31
+
32
+ * Include SlotableV2 by default in Base. **Note:** It's no longer necessary to include `ViewComponent::SlotableV2` to use Slots.
33
+
34
+ *Joel Hawksley*
35
+
36
+ * Prepend Preview routes instead of appending, accounting for cases where host application has catchall route.
37
+
38
+ *Joel Hawksley*
39
+
40
+ * Fix bug where blocks passed to lambda slots will render incorrectly in certain situations.
41
+
42
+ *Blake Williams*
43
+
44
+ ## 2.27.0
45
+
46
+ * Allow customization of the controller used in component tests.
47
+
48
+ *Alex Robbin*
49
+
50
+ * Generate preview at overridden path if one exists when using `--preview` flag.
51
+
52
+ *Nishiki Liu*
53
+
54
+ ## 2.26.1
55
+
56
+ * Fix bug that raises when trying to use a collection before the component has been compiled.
57
+
58
+ *Blake Williams*
59
+
60
+ ## 2.26.0
61
+
62
+ * Lazily evaluate component `content` in `render?`, preventing the `content` block from being evaluated when `render?` returns false.
63
+
64
+ *Blake Williams*
65
+
66
+ * Do not generate template when using `--inline` flag.
67
+
68
+ *Hans Lemuet*
69
+
70
+ * Add `--inline` option to the Haml and Slim generators
71
+
72
+ *Hans Lemuet*
73
+
5
74
  ## 2.25.1
6
75
 
7
76
  * Experimental: call `._after_compile` class method after a component is compiled.
data/README.md CHANGED
@@ -6,14 +6,6 @@ A framework for building reusable, testable & encapsulated view components in Ru
6
6
 
7
7
  See [viewcomponent.org](https://viewcomponent.org/) for documentation.
8
8
 
9
- ## Installation
10
-
11
- In `Gemfile`, add:
12
-
13
- ```ruby
14
- gem "view_component", require: "view_component/engine"
15
- ```
16
-
17
9
  ## Contributing
18
10
 
19
11
  This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. We recommend reading the [contributing guide](./CONTRIBUTING.md) as well.
@@ -10,18 +10,18 @@ module Erb
10
10
  class_option :inline, type: :boolean, default: false
11
11
 
12
12
  def copy_view_file
13
- template "component.html.erb", destination
13
+ unless options["inline"]
14
+ template "component.html.erb", destination
15
+ end
14
16
  end
15
17
 
16
18
  private
17
19
 
18
20
  def destination
19
- if !options["inline"]
20
- if options["sidecar"]
21
- File.join("app/components", class_path, "#{file_name}_component", "#{file_name}_component.html.erb")
22
- else
23
- File.join("app/components", class_path, "#{file_name}_component.html.erb")
24
- end
21
+ if options["sidecar"]
22
+ File.join("app/components", class_path, "#{file_name}_component", "#{file_name}_component.html.erb")
23
+ else
24
+ File.join("app/components", class_path, "#{file_name}_component.html.erb")
25
25
  end
26
26
  end
27
27
 
@@ -9,7 +9,9 @@ module Haml
9
9
  class_option :sidecar, type: :boolean, default: false
10
10
 
11
11
  def copy_view_file
12
- template "component.html.haml", destination
12
+ if !options["inline"]
13
+ template "component.html.haml", destination
14
+ end
13
15
  end
14
16
 
15
17
  private
@@ -8,7 +8,11 @@ module Preview
8
8
  check_class_collision suffix: "ComponentPreview"
9
9
 
10
10
  def create_preview_file
11
- template "component_preview.rb", File.join("test/components/previews", class_path, "#{file_name}_component_preview.rb")
11
+ preview_paths = Rails.application.config.view_component.preview_paths
12
+ return if preview_paths.count > 1
13
+
14
+ path_prefix = preview_paths.one? ? preview_paths.first : "test/components/previews"
15
+ template "component_preview.rb", File.join(path_prefix, class_path, "#{file_name}_component_preview.rb")
12
16
  end
13
17
 
14
18
  private
@@ -9,7 +9,9 @@ module Slim
9
9
  class_option :sidecar, type: :boolean, default: false
10
10
 
11
11
  def copy_view_file
12
- template "component.html.slim", destination
12
+ if !options["inline"]
13
+ template "component.html.slim", destination
14
+ end
13
15
  end
14
16
 
15
17
  private
@@ -12,4 +12,5 @@ module ViewComponent
12
12
  autoload :TestHelpers
13
13
  autoload :TestCase
14
14
  autoload :TemplateError
15
+ autoload :Translatable
15
16
  end
@@ -12,6 +12,7 @@ module ViewComponent
12
12
  class Base < ActionView::Base
13
13
  include ActiveSupport::Configurable
14
14
  include ViewComponent::Previewable
15
+ include ViewComponent::SlotableV2
15
16
 
16
17
  ViewContextCalledBeforeRenderError = Class.new(StandardError)
17
18
 
@@ -78,8 +79,8 @@ module ViewComponent
78
79
  old_current_template = @current_template
79
80
  @current_template = self
80
81
 
81
- # Assign captured content passed to component as a block to @content
82
- @content = view_context.capture(self, &block) if block_given?
82
+ @_content_evaluated = false
83
+ @_render_in_block = block
83
84
 
84
85
  before_render
85
86
 
@@ -130,7 +131,7 @@ module ViewComponent
130
131
  @helpers ||= controller.view_context
131
132
  end
132
133
 
133
- # Exposes .virutal_path as an instance method
134
+ # Exposes .virtual_path as an instance method
134
135
  def virtual_path
135
136
  self.class.virtual_path
136
137
  end
@@ -177,11 +178,25 @@ module ViewComponent
177
178
  @request ||= controller.request
178
179
  end
179
180
 
180
- attr_reader :content, :view_context
181
+ attr_reader :view_context
182
+
183
+ def content
184
+ return @_content if defined?(@_content)
185
+ @_content_evaluated = true
186
+
187
+ @_content = if @view_context && @_render_in_block
188
+ view_context.capture(self, &@_render_in_block)
189
+ end
190
+ end
191
+
192
+ def content_evaluated?
193
+ @_content_evaluated
194
+ end
181
195
 
182
196
  # The controller used for testing components.
183
- # Defaults to ApplicationController. This should be set early
184
- # in the initialization process and should be set to a string.
197
+ # Defaults to ApplicationController, but can be configured
198
+ # on a per-test basis using `with_controller_class`.
199
+ # This should be set early in the initialization process and should be a string.
185
200
  mattr_accessor :test_controller
186
201
  @@test_controller = "ApplicationController"
187
202
 
@@ -191,6 +206,47 @@ module ViewComponent
191
206
  class << self
192
207
  attr_accessor :source_location, :virtual_path
193
208
 
209
+ # EXPERIMENTAL: This API is experimental and may be removed at any time.
210
+ # Find sidecar files for the given extensions.
211
+ #
212
+ # The provided array of extensions is expected to contain
213
+ # strings starting without the "dot", example: `["erb", "haml"]`.
214
+ #
215
+ # For example, one might collect sidecar CSS files that need to be compiled.
216
+ def _sidecar_files(extensions)
217
+ return [] unless source_location
218
+
219
+ extensions = extensions.join(",")
220
+
221
+ # view files in a directory named like the component
222
+ directory = File.dirname(source_location)
223
+ filename = File.basename(source_location, ".rb")
224
+ component_name = name.demodulize.underscore
225
+
226
+ # Add support for nested components defined in the same file.
227
+ #
228
+ # e.g.
229
+ #
230
+ # class MyComponent < ViewComponent::Base
231
+ # class MyOtherComponent < ViewComponent::Base
232
+ # end
233
+ # end
234
+ #
235
+ # Without this, `MyOtherComponent` will not look for `my_component/my_other_component.html.erb`
236
+ nested_component_files = if name.include?("::") && component_name != filename
237
+ Dir["#{directory}/#{filename}/#{component_name}.*{#{extensions}}"]
238
+ else
239
+ []
240
+ end
241
+
242
+ # view files in the same directory as the component
243
+ sidecar_files = Dir["#{directory}/#{component_name}.*{#{extensions}}"]
244
+
245
+ sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extensions}}"]
246
+
247
+ (sidecar_files - [source_location] + sidecar_directory_files + nested_component_files).uniq
248
+ end
249
+
194
250
  # Render a component collection.
195
251
  def with_collection(collection, **args)
196
252
  Collection.new(self, collection, **args)
@@ -256,7 +312,14 @@ module ViewComponent
256
312
  if areas.include?(:content)
257
313
  raise ArgumentError.new ":content is a reserved content area name. Please use another name, such as ':body'"
258
314
  end
259
- attr_reader(*areas)
315
+
316
+ areas.each do |area|
317
+ define_method area.to_sym do
318
+ content unless content_evaluated? # ensure content is loaded so content_areas will be defined
319
+ instance_variable_get(:"@#{area}") if instance_variable_defined?(:"@#{area}")
320
+ end
321
+ end
322
+
260
323
  self.content_areas = areas
261
324
  end
262
325
 
@@ -304,6 +367,22 @@ module ViewComponent
304
367
  )
305
368
  end
306
369
 
370
+ def collection_parameter
371
+ if provided_collection_parameter
372
+ provided_collection_parameter
373
+ else
374
+ name && name.demodulize.underscore.chomp("_component").to_sym
375
+ end
376
+ end
377
+
378
+ def collection_counter_parameter
379
+ "#{collection_parameter}_counter".to_sym
380
+ end
381
+
382
+ def counter_argument_present?
383
+ instance_method(:initialize).parameters.map(&:second).include?(collection_counter_parameter)
384
+ end
385
+
307
386
  private
308
387
 
309
388
  def initialize_parameter_names
@@ -10,7 +10,6 @@ module ViewComponent
10
10
  def render_in(view_context, &block)
11
11
  iterator = ActionView::PartialIteration.new(@collection.size)
12
12
 
13
- component.compile(raise_errors: true)
14
13
  component.validate_collection_parameter!(validate_default: true)
15
14
 
16
15
  @collection.map do |item|
@@ -24,28 +24,6 @@ module ViewComponent
24
24
  )
25
25
  end
26
26
 
27
- # Remove any existing singleton methods,
28
- # as Ruby warns when redefining a method.
29
- component_class.remove_possible_singleton_method(:collection_parameter)
30
- component_class.remove_possible_singleton_method(:collection_counter_parameter)
31
- component_class.remove_possible_singleton_method(:counter_argument_present?)
32
-
33
- component_class.define_singleton_method(:collection_parameter) do
34
- if provided_collection_parameter
35
- provided_collection_parameter
36
- else
37
- name.demodulize.underscore.chomp("_component").to_sym
38
- end
39
- end
40
-
41
- component_class.define_singleton_method(:collection_counter_parameter) do
42
- "#{collection_parameter}_counter".to_sym
43
- end
44
-
45
- component_class.define_singleton_method(:counter_argument_present?) do
46
- instance_method(:initialize).parameters.map(&:second).include?(collection_counter_parameter)
47
- end
48
-
49
27
  if raise_errors
50
28
  component_class.validate_initialization_parameters!
51
29
  component_class.validate_collection_parameter!
@@ -83,7 +61,7 @@ module ViewComponent
83
61
  "elsif variant.to_sym == :#{variant}\n #{call_method_name(variant)}"
84
62
  end.join("\n")
85
63
 
86
- component_class.class_eval <<-RUBY
64
+ component_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
87
65
  def render_template_for(variant = nil)
88
66
  if variant.nil?
89
67
  call
@@ -136,50 +114,18 @@ module ViewComponent
136
114
  end
137
115
 
138
116
  def templates
139
- @templates ||= matching_views_in_source_location.each_with_object([]) do |path, memo|
140
- pieces = File.basename(path).split(".")
141
-
142
- memo << {
143
- path: path,
144
- variant: pieces.second.split("+").second&.to_sym,
145
- handler: pieces.last
146
- }
147
- end
148
- end
149
-
150
- def matching_views_in_source_location
151
- source_location = component_class.source_location
152
- return [] unless source_location
153
-
154
- extensions = ActionView::Template.template_handler_extensions.join(",")
155
-
156
- # view files in a directory named like the component
157
- directory = File.dirname(source_location)
158
- filename = File.basename(source_location, ".rb")
159
- component_name = component_class.name.demodulize.underscore
160
-
161
- # Add support for nested components defined in the same file.
162
- #
163
- # e.g.
164
- #
165
- # class MyComponent < ViewComponent::Base
166
- # class MyOtherComponent < ViewComponent::Base
167
- # end
168
- # end
169
- #
170
- # Without this, `MyOtherComponent` will not look for `my_component/my_other_component.html.erb`
171
- nested_component_files = if component_class.name.include?("::") && component_name != filename
172
- Dir["#{directory}/#{filename}/#{component_name}.*{#{extensions}}"]
173
- else
174
- []
117
+ @templates ||= begin
118
+ extensions = ActionView::Template.template_handler_extensions
119
+
120
+ component_class._sidecar_files(extensions).each_with_object([]) do |path, memo|
121
+ pieces = File.basename(path).split(".")
122
+ memo << {
123
+ path: path,
124
+ variant: pieces.second.split("+").second&.to_sym,
125
+ handler: pieces.last
126
+ }
127
+ end
175
128
  end
176
-
177
- # view files in the same directory as the component
178
- sidecar_files = Dir["#{directory}/#{component_name}.*{#{extensions}}"]
179
-
180
- sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extensions}}"]
181
-
182
- (sidecar_files - [source_location] + sidecar_directory_files + nested_component_files)
183
129
  end
184
130
 
185
131
  def inline_calls
@@ -90,7 +90,7 @@ module ViewComponent
90
90
  options = app.config.view_component
91
91
 
92
92
  if options.show_previews
93
- app.routes.append do
93
+ app.routes.prepend do
94
94
  preview_controller = options.preview_controller.sub(/Controller$/, "").underscore
95
95
 
96
96
  get options.preview_route, to: "#{preview_controller}#index", as: :preview_view_components, internal: true
@@ -25,15 +25,22 @@ module ViewComponent
25
25
  return @content if defined?(@content)
26
26
 
27
27
  view_context = @parent.send(:view_context)
28
- @content = view_context.capture do
29
- if defined?(@_component_instance)
30
- # render_in is faster than `parent.render`
31
- @_component_instance.render_in(view_context, &@_content_block)
32
- elsif defined?(@_content)
33
- @_content
34
- elsif defined?(@_content_block)
35
- @_content_block.call
28
+
29
+ @content = if defined?(@_component_instance)
30
+ # render_in is faster than `parent.render`
31
+ if defined?(@_content_block)
32
+ view_context.capture do
33
+ @_component_instance.render_in(view_context, &@_content_block)
34
+ end
35
+ else
36
+ view_context.capture do
37
+ @_component_instance.render_in(view_context)
38
+ end
36
39
  end
40
+ elsif defined?(@_content)
41
+ @_content
42
+ elsif defined?(@_content_block)
43
+ view_context.capture(&@_content_block)
37
44
  end
38
45
 
39
46
  @content
@@ -49,13 +49,19 @@ module ViewComponent
49
49
 
50
50
  # If the slot is a collection, define an accesor that defaults to an empty array
51
51
  if collection
52
- class_eval <<-RUBY
52
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
53
53
  def #{accessor_name}
54
+ content unless content_evaluated? # ensure content is loaded so slots will be defined
54
55
  #{instance_variable_name} ||= []
55
56
  end
56
57
  RUBY
57
58
  else
58
- attr_reader accessor_name
59
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
60
+ def #{accessor_name}
61
+ content unless content_evaluated? # ensure content is loaded so slots will be defined
62
+ #{instance_variable_name} if defined?(#{instance_variable_name})
63
+ end
64
+ RUBY
59
65
  end
60
66
 
61
67
  # Default class_name to ViewComponent::Slot
@@ -183,6 +183,8 @@ module ViewComponent
183
183
  end
184
184
 
185
185
  def get_slot(slot_name)
186
+ content unless content_evaluated? # ensure content is loaded so slots will be defined
187
+
186
188
  slot = self.class.registered_slots[slot_name]
187
189
  @_set_slots ||= {}
188
190
 
@@ -224,7 +226,13 @@ module ViewComponent
224
226
  # Use `bind(self)` to ensure lambda is executed in the context of the
225
227
  # current component. This is necessary to allow the lambda to access helper
226
228
  # methods like `content_tag` as well as parent component state.
227
- renderable_value = slot_definition[:renderable_function].bind(self).call(*args, **kwargs, &block)
229
+ renderable_value = if block_given?
230
+ slot_definition[:renderable_function].bind(self).call(*args, **kwargs) do |*args, **kwargs|
231
+ view_context.capture(*args, **kwargs, &block)
232
+ end
233
+ else
234
+ slot_definition[:renderable_function].bind(self).call(*args, **kwargs)
235
+ end
228
236
 
229
237
  # Function calls can return components, so if it's a component handle it specially
230
238
  if renderable_value.respond_to?(:render_in)
@@ -35,7 +35,7 @@ module ViewComponent
35
35
  end
36
36
 
37
37
  def controller
38
- @controller ||= Base.test_controller.constantize.new.tap { |c| c.request = request }.extend(Rails.application.routes.url_helpers)
38
+ @controller ||= build_controller(Base.test_controller.constantize)
39
39
  end
40
40
 
41
41
  def request
@@ -47,7 +47,21 @@ module ViewComponent
47
47
 
48
48
  controller.view_context.lookup_context.variants = variant
49
49
  yield
50
+ ensure
50
51
  controller.view_context.lookup_context.variants = old_variants
51
52
  end
53
+
54
+ def with_controller_class(klass)
55
+ old_controller = defined?(@controller) && @controller
56
+
57
+ @controller = build_controller(klass)
58
+ yield
59
+ ensure
60
+ @controller = old_controller
61
+ end
62
+
63
+ def build_controller(klass)
64
+ klass.new.tap { |c| c.request = request }.extend(Rails.application.routes.url_helpers)
65
+ end
52
66
  end
53
67
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "i18n"
5
+ require "action_view/helpers/translation_helper"
6
+ require "active_support/concern"
7
+
8
+ module ViewComponent
9
+ module Translatable
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ class_attribute :i18n_backend, instance_writer: false, instance_predicate: false
14
+ end
15
+
16
+ class_methods do
17
+ def i18n_scope
18
+ @i18n_scope ||= virtual_path.sub(%r{^/}, "").gsub(%r{/_?}, ".")
19
+ end
20
+
21
+ def _after_compile
22
+ super
23
+
24
+ unless CompileCache.compiled? self
25
+ self.i18n_backend = I18nBackend.new(
26
+ i18n_scope: i18n_scope,
27
+ load_paths: _sidecar_files(%w[yml yaml]),
28
+ )
29
+ end
30
+ end
31
+ end
32
+
33
+ class I18nBackend < ::I18n::Backend::Simple
34
+ EMPTY_HASH = {}.freeze
35
+
36
+ def initialize(i18n_scope:, load_paths:)
37
+ @i18n_scope = i18n_scope.split(".")
38
+ @load_paths = load_paths
39
+ end
40
+
41
+ # Ensure the Simple backend won't load paths from ::I18n.load_path
42
+ def load_translations
43
+ super(@load_paths)
44
+ end
45
+
46
+ def scope_data(data)
47
+ @i18n_scope.reverse_each do |part|
48
+ data = { part => data}
49
+ end
50
+ data
51
+ end
52
+
53
+ def store_translations(locale, data, options = EMPTY_HASH)
54
+ super(locale, scope_data(data), options)
55
+ end
56
+ end
57
+
58
+ def translate(key = nil, locale: nil, **options)
59
+ locale ||= ::I18n.locale
60
+
61
+ key = "#{i18n_scope}#{key}" if key.start_with?(".")
62
+
63
+ result = catch(:exception) do
64
+ i18n_backend.translate(locale, key, options)
65
+ end
66
+
67
+ # Fallback to the global translations
68
+ if result.is_a? ::I18n::MissingTranslation
69
+ result = helpers.t(key, locale: locale, **options)
70
+ end
71
+
72
+ result
73
+ end
74
+ alias :t :translate
75
+
76
+ # Exposes .i18n_scope as an instance method
77
+ def i18n_scope
78
+ self.class.i18n_scope
79
+ end
80
+ end
81
+ end
@@ -3,9 +3,11 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 25
7
- PATCH = 1
6
+ MINOR = 29
7
+ PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
10
10
  end
11
11
  end
12
+
13
+ puts ViewComponent::VERSION::STRING if __FILE__ == $PROGRAM_NAME
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: view_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.25.1
4
+ version: 2.29.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-01 00:00:00.000000000 Z
11
+ date: 2021-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -128,6 +128,20 @@ dependencies:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
130
  version: '1'
131
+ - !ruby/object:Gem::Dependency
132
+ name: jbuilder
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '2'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '2'
131
145
  - !ruby/object:Gem::Dependency
132
146
  name: rubocop
133
147
  requirement: !ruby/object:Gem::Requirement
@@ -249,6 +263,7 @@ files:
249
263
  - lib/view_component/template_error.rb
250
264
  - lib/view_component/test_case.rb
251
265
  - lib/view_component/test_helpers.rb
266
+ - lib/view_component/translatable.rb
252
267
  - lib/view_component/version.rb
253
268
  homepage: https://github.com/github/view_component
254
269
  licenses:
@@ -270,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
285
  - !ruby/object:Gem::Version
271
286
  version: '0'
272
287
  requirements: []
273
- rubygems_version: 3.0.3
288
+ rubygems_version: 3.1.2
274
289
  signing_key:
275
290
  specification_version: 4
276
291
  summary: View components for Rails