view_component 2.29.0 → 2.33.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 +4 -4
- data/CHANGELOG.md +80 -0
- data/lib/view_component.rb +1 -0
- data/lib/view_component/base.rb +63 -13
- data/lib/view_component/collection.rb +1 -0
- data/lib/view_component/compiler.rb +7 -1
- data/lib/view_component/component_error.rb +6 -0
- data/lib/view_component/engine.rb +1 -1
- data/lib/view_component/slot_v2.rb +16 -2
- data/lib/view_component/slotable.rb +5 -0
- data/lib/view_component/slotable_v2.rb +9 -5
- data/lib/view_component/test_helpers.rb +17 -1
- data/lib/view_component/translatable.rb +22 -8
- data/lib/view_component/version.rb +1 -1
- data/lib/view_component/with_content_helper.rb +15 -0
- metadata +23 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e1d8f453f26f7d62a3549dcfb34a85a6fadfc05a7b38515ebe53bba7500acc9
|
4
|
+
data.tar.gz: 39122c530de9fb557f7e66a0a3e6b94c20c492776edc45b193e2b3b60b834e39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f016eb4da5b952a220971e0163853b8ca77dd5bc820b634d525316b4117654b78a279ffeb7bb8d66ce68401cc41a350861696152992923445a1c3d6c587b2ed
|
7
|
+
data.tar.gz: 4203337d6188eea75e7d79ca246ca5309e5af7197256207e48c37b248958dbad49c07efff0a964d206d9c462ee5d1af3365f36f9f2d9e68661f7dbfe066e4a01
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,86 @@
|
|
2
2
|
|
3
3
|
## main
|
4
4
|
|
5
|
+
## 2.33.0
|
6
|
+
|
7
|
+
* Add support for `_iteration` parameter when rendering in a collection
|
8
|
+
|
9
|
+
*Will Cosgrove*
|
10
|
+
|
11
|
+
* Don't raise an error when rendering empty components.
|
12
|
+
|
13
|
+
*Alex Robbin*
|
14
|
+
|
15
|
+
## 2.32.0
|
16
|
+
|
17
|
+
* Enable previews by default in test environment.
|
18
|
+
|
19
|
+
*Edouard Piron*
|
20
|
+
|
21
|
+
* Fix test helper compatibility with Rails 7.0, TestRequest, and TestSession.
|
22
|
+
|
23
|
+
*Leo Correa*
|
24
|
+
|
25
|
+
* Add experimental `_output_postamble` lifecyle method.
|
26
|
+
|
27
|
+
*Joel Hawksley*
|
28
|
+
|
29
|
+
* Add compatibility notes on FAQ.
|
30
|
+
|
31
|
+
*Matheus Richard*
|
32
|
+
|
33
|
+
* Add Bridgetown on Compatibility documentation.
|
34
|
+
|
35
|
+
*Matheus Richard*
|
36
|
+
|
37
|
+
* Are you interested in building the future of ViewComponent? GitHub is looking to hire a Senior Engineer to work on Primer ViewComponents and ViewComponent. Apply here: [US/Canada](https://github.com/careers) / [Europe](https://boards.greenhouse.io/github/jobs/3132294). Feel free to reach out to joelhawksley@github.com with any questions.
|
38
|
+
|
39
|
+
*Joel Hawksley*
|
40
|
+
|
41
|
+
## 2.31.1
|
42
|
+
|
43
|
+
* Fix `DEPRECATION WARNING: before_render_check` when compiling `ViewComponent::Base`
|
44
|
+
|
45
|
+
*Dave Kroondyk*
|
46
|
+
|
47
|
+
## 2.31.0
|
48
|
+
|
49
|
+
_Note: This release includes an underlying change to Slots that may affect incorrect usage of the API, where Slots were set on a line prefixed by `<%=`. The result of setting a Slot should not be returned. (`<%`)_
|
50
|
+
|
51
|
+
* Add `#with_content` to allow setting content without a block.
|
52
|
+
|
53
|
+
*Jordan Raine, Manuel Puyol*
|
54
|
+
|
55
|
+
* Add `with_request_url` test helper.
|
56
|
+
|
57
|
+
*Mario Schüttel*
|
58
|
+
|
59
|
+
* Improve feature parity with Rails translations
|
60
|
+
* Don't create a translation backend if the component has no translation file
|
61
|
+
* Mark translation keys ending with `html` as HTML-safe
|
62
|
+
* Always convert keys to String
|
63
|
+
* Support multiple keys
|
64
|
+
|
65
|
+
*Elia Schito*
|
66
|
+
|
67
|
+
* Fix errors on `asset_url` helpers when `asset_host` has no protocol.
|
68
|
+
|
69
|
+
*Elia Schito*
|
70
|
+
|
71
|
+
* Prevent slots from overriding the `#content` method when registering a slot with that name.
|
72
|
+
|
73
|
+
*Blake Williams*
|
74
|
+
|
75
|
+
* Deprecate `with_slot` in favor of the new [slots API](https://viewcomponent.org/guide/slots.html).
|
76
|
+
|
77
|
+
*Manuel Puyol*
|
78
|
+
|
79
|
+
## 2.30.0
|
80
|
+
|
81
|
+
* Deprecate `with_content_areas` in favor of [slots](https://viewcomponent.org/guide/slots.html).
|
82
|
+
|
83
|
+
*Joel Hawksley*
|
84
|
+
|
5
85
|
## 2.29.0
|
6
86
|
|
7
87
|
* Allow Slot lambdas to share data from the parent component and allow chaining on the returned component.
|
data/lib/view_component.rb
CHANGED
data/lib/view_component/base.rb
CHANGED
@@ -7,12 +7,14 @@ require "view_component/compile_cache"
|
|
7
7
|
require "view_component/previewable"
|
8
8
|
require "view_component/slotable"
|
9
9
|
require "view_component/slotable_v2"
|
10
|
+
require "view_component/with_content_helper"
|
10
11
|
|
11
12
|
module ViewComponent
|
12
13
|
class Base < ActionView::Base
|
13
14
|
include ActiveSupport::Configurable
|
14
15
|
include ViewComponent::Previewable
|
15
16
|
include ViewComponent::SlotableV2
|
17
|
+
include ViewComponent::WithContentHelper
|
16
18
|
|
17
19
|
ViewContextCalledBeforeRenderError = Class.new(StandardError)
|
18
20
|
|
@@ -28,6 +30,7 @@ module ViewComponent
|
|
28
30
|
# Hook for allowing components to do work as part of the compilation process.
|
29
31
|
#
|
30
32
|
# For example, one might compile component-specific assets at this point.
|
33
|
+
# @private TODO: add documentation
|
31
34
|
def self._after_compile
|
32
35
|
# noop
|
33
36
|
end
|
@@ -56,6 +59,7 @@ module ViewComponent
|
|
56
59
|
# returns:
|
57
60
|
# <span title="greeting">Hello, world!</span>
|
58
61
|
#
|
62
|
+
# @private
|
59
63
|
def render_in(view_context, &block)
|
60
64
|
self.class.compile(raise_errors: true)
|
61
65
|
|
@@ -79,13 +83,15 @@ module ViewComponent
|
|
79
83
|
old_current_template = @current_template
|
80
84
|
@current_template = self
|
81
85
|
|
86
|
+
raise ArgumentError.new("Block provided after calling `with_content`. Use one or the other.") if block && defined?(@_content_set_by_with_content)
|
87
|
+
|
82
88
|
@_content_evaluated = false
|
83
89
|
@_render_in_block = block
|
84
90
|
|
85
91
|
before_render
|
86
92
|
|
87
93
|
if render?
|
88
|
-
render_template_for(@variant)
|
94
|
+
render_template_for(@variant).to_s + _output_postamble
|
89
95
|
else
|
90
96
|
""
|
91
97
|
end
|
@@ -93,18 +99,36 @@ module ViewComponent
|
|
93
99
|
@current_template = old_current_template
|
94
100
|
end
|
95
101
|
|
102
|
+
# EXPERIMENTAL: Optional content to be returned after the rendered template.
|
103
|
+
#
|
104
|
+
# @return [String]
|
105
|
+
def _output_postamble
|
106
|
+
""
|
107
|
+
end
|
108
|
+
|
109
|
+
# Called before rendering the component. Override to perform operations that depend on having access to the view context, such as helpers.
|
110
|
+
#
|
111
|
+
# @return [void]
|
96
112
|
def before_render
|
97
113
|
before_render_check
|
98
114
|
end
|
99
115
|
|
116
|
+
# Called after rendering the component.
|
117
|
+
#
|
118
|
+
# @deprecated Use `before_render` instead. Will be removed in v3.0.0.
|
119
|
+
# @return [void]
|
100
120
|
def before_render_check
|
101
121
|
# noop
|
102
122
|
end
|
103
123
|
|
124
|
+
# Override to determine whether the ViewComponent should render.
|
125
|
+
#
|
126
|
+
# @return [Boolean]
|
104
127
|
def render?
|
105
128
|
true
|
106
129
|
end
|
107
130
|
|
131
|
+
# @private
|
108
132
|
def initialize(*); end
|
109
133
|
|
110
134
|
# Re-use original view_context if we're not rendering a component.
|
@@ -112,6 +136,7 @@ module ViewComponent
|
|
112
136
|
# This prevents an exception when rendering a partial inside of a component that has also been rendered outside
|
113
137
|
# of the component. This is due to the partials compiled template method existing in the parent `view_context`,
|
114
138
|
# and not the component's `view_context`.
|
139
|
+
# @private
|
115
140
|
def render(options = {}, args = {}, &block)
|
116
141
|
if options.is_a? ViewComponent::Base
|
117
142
|
super
|
@@ -120,28 +145,36 @@ module ViewComponent
|
|
120
145
|
end
|
121
146
|
end
|
122
147
|
|
148
|
+
# The current controller. Use sparingly as doing so introduces coupling that inhibits encapsulation & reuse, often making testing difficult.
|
149
|
+
#
|
150
|
+
# @return [ActionController::Base]
|
123
151
|
def controller
|
124
152
|
raise ViewContextCalledBeforeRenderError, "`controller` can only be called at render time." if view_context.nil?
|
125
153
|
@controller ||= view_context.controller
|
126
154
|
end
|
127
155
|
|
128
|
-
#
|
156
|
+
# A proxy through which to access helpers. Use sparingly as doing so introduces coupling that inhibits encapsulation & reuse, often making testing difficult.
|
157
|
+
#
|
158
|
+
# @return [ActionView::Base]
|
129
159
|
def helpers
|
130
160
|
raise ViewContextCalledBeforeRenderError, "`helpers` can only be called at render time." if view_context.nil?
|
131
161
|
@helpers ||= controller.view_context
|
132
162
|
end
|
133
163
|
|
134
164
|
# Exposes .virtual_path as an instance method
|
165
|
+
# @private
|
135
166
|
def virtual_path
|
136
167
|
self.class.virtual_path
|
137
168
|
end
|
138
169
|
|
139
170
|
# For caching, such as #cache_if
|
171
|
+
# @private
|
140
172
|
def view_cache_dependencies
|
141
173
|
[]
|
142
174
|
end
|
143
175
|
|
144
176
|
# For caching, such as #cache_if
|
177
|
+
# @private
|
145
178
|
def format
|
146
179
|
# Ruby 2.6 throws a warning without checking `defined?`, 2.7 does not
|
147
180
|
if defined?(@variant)
|
@@ -150,6 +183,7 @@ module ViewComponent
|
|
150
183
|
end
|
151
184
|
|
152
185
|
# Assign the provided content to the content area accessor
|
186
|
+
# @private
|
153
187
|
def with(area, content = nil, &block)
|
154
188
|
unless content_areas.include?(area)
|
155
189
|
raise ArgumentError.new "Unknown content_area '#{area}' - expected one of '#{content_areas}'"
|
@@ -163,21 +197,22 @@ module ViewComponent
|
|
163
197
|
nil
|
164
198
|
end
|
165
199
|
|
200
|
+
# @private TODO: add documentation
|
166
201
|
def with_variant(variant)
|
167
202
|
@variant = variant
|
168
203
|
|
169
204
|
self
|
170
205
|
end
|
171
206
|
|
172
|
-
|
173
|
-
|
174
|
-
#
|
175
|
-
# Use sparingly as doing so introduces coupling
|
176
|
-
# that inhibits encapsulation & reuse.
|
207
|
+
# The current request. Use sparingly as doing so introduces coupling that inhibits encapsulation & reuse, often making testing difficult.
|
208
|
+
#
|
209
|
+
# @return [ActionDispatch::Request]
|
177
210
|
def request
|
178
211
|
@request ||= controller.request
|
179
212
|
end
|
180
213
|
|
214
|
+
private
|
215
|
+
|
181
216
|
attr_reader :view_context
|
182
217
|
|
183
218
|
def content
|
@@ -186,6 +221,8 @@ module ViewComponent
|
|
186
221
|
|
187
222
|
@_content = if @view_context && @_render_in_block
|
188
223
|
view_context.capture(self, &@_render_in_block)
|
224
|
+
elsif defined?(@_content_set_by_with_content)
|
225
|
+
@_content_set_by_with_content
|
189
226
|
end
|
190
227
|
end
|
191
228
|
|
@@ -280,7 +317,7 @@ module ViewComponent
|
|
280
317
|
end
|
281
318
|
|
282
319
|
def compiled?
|
283
|
-
|
320
|
+
compiler.compiled?
|
284
321
|
end
|
285
322
|
|
286
323
|
# Compile templates to instance methods, assuming they haven't been compiled already.
|
@@ -288,11 +325,11 @@ module ViewComponent
|
|
288
325
|
# Do as much work as possible in this step, as doing so reduces the amount
|
289
326
|
# of work done each time a component is rendered.
|
290
327
|
def compile(raise_errors: false)
|
291
|
-
|
328
|
+
compiler.compile(raise_errors: raise_errors)
|
292
329
|
end
|
293
330
|
|
294
|
-
def
|
295
|
-
@
|
331
|
+
def compiler
|
332
|
+
@_compiler ||= Compiler.new(self)
|
296
333
|
end
|
297
334
|
|
298
335
|
# we'll eventually want to update this to support other types
|
@@ -309,6 +346,11 @@ module ViewComponent
|
|
309
346
|
end
|
310
347
|
|
311
348
|
def with_content_areas(*areas)
|
349
|
+
ActiveSupport::Deprecation.warn(
|
350
|
+
"`with_content_areas` is deprecated and will be removed in ViewComponent v3.0.0.\n" \
|
351
|
+
"Use slots (https://viewcomponent.org/guide/slots.html) instead."
|
352
|
+
)
|
353
|
+
|
312
354
|
if areas.include?(:content)
|
313
355
|
raise ArgumentError.new ":content is a reserved content area name. Please use another name, such as ':body'"
|
314
356
|
end
|
@@ -360,7 +402,7 @@ module ViewComponent
|
|
360
402
|
def validate_initialization_parameters!
|
361
403
|
return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
|
362
404
|
|
363
|
-
raise
|
405
|
+
raise ViewComponent::ComponentError.new(
|
364
406
|
"#{self} initializer cannot contain " \
|
365
407
|
"`#{RESERVED_PARAMETER}` since it will override a " \
|
366
408
|
"public ViewComponent method."
|
@@ -380,7 +422,15 @@ module ViewComponent
|
|
380
422
|
end
|
381
423
|
|
382
424
|
def counter_argument_present?
|
383
|
-
|
425
|
+
initialize_parameter_names.include?(collection_counter_parameter)
|
426
|
+
end
|
427
|
+
|
428
|
+
def collection_iteration_parameter
|
429
|
+
"#{collection_parameter}_iteration".to_sym
|
430
|
+
end
|
431
|
+
|
432
|
+
def iteration_argument_present?
|
433
|
+
initialize_parameter_names.include?(collection_iteration_parameter)
|
384
434
|
end
|
385
435
|
|
386
436
|
private
|
@@ -38,6 +38,7 @@ module ViewComponent
|
|
38
38
|
def component_options(item, iterator)
|
39
39
|
item_options = { component.collection_parameter => item }
|
40
40
|
item_options[component.collection_counter_parameter] = iterator.index + 1 if component.counter_argument_present?
|
41
|
+
item_options[component.collection_iteration_parameter] = iterator if component.iteration_argument_present?
|
41
42
|
|
42
43
|
@options.merge(item_options)
|
43
44
|
end
|
@@ -13,12 +13,18 @@ module ViewComponent
|
|
13
13
|
def compile(raise_errors: false)
|
14
14
|
return if compiled?
|
15
15
|
|
16
|
+
subclass_instance_methods = component_class.instance_methods(false)
|
17
|
+
|
18
|
+
if subclass_instance_methods.include?(:with_content) && raise_errors
|
19
|
+
raise ViewComponent::ComponentError.new("#{component_class} implements a reserved method, `with_content`.")
|
20
|
+
end
|
21
|
+
|
16
22
|
if template_errors.present?
|
17
23
|
raise ViewComponent::TemplateError.new(template_errors) if raise_errors
|
18
24
|
return false
|
19
25
|
end
|
20
26
|
|
21
|
-
if
|
27
|
+
if subclass_instance_methods.include?(:before_render_check)
|
22
28
|
ActiveSupport::Deprecation.warn(
|
23
29
|
"`before_render_check` will be removed in v3.0.0. Use `before_render` instead."
|
24
30
|
)
|
@@ -12,7 +12,7 @@ module ViewComponent
|
|
12
12
|
options = app.config.view_component
|
13
13
|
|
14
14
|
options.render_monkey_patch_enabled = true if options.render_monkey_patch_enabled.nil?
|
15
|
-
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
15
|
+
options.show_previews = Rails.env.development? || Rails.env.test? if options.show_previews.nil?
|
16
16
|
options.preview_route ||= ViewComponent::Base.preview_route
|
17
17
|
options.preview_controller ||= ViewComponent::Base.preview_controller
|
18
18
|
|
@@ -1,7 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "view_component/with_content_helper"
|
4
|
+
|
3
5
|
module ViewComponent
|
4
6
|
class SlotV2
|
7
|
+
include ViewComponent::WithContentHelper
|
8
|
+
|
5
9
|
attr_writer :_component_instance, :_content_block, :_content
|
6
10
|
|
7
11
|
def initialize(parent)
|
@@ -26,10 +30,18 @@ module ViewComponent
|
|
26
30
|
|
27
31
|
view_context = @parent.send(:view_context)
|
28
32
|
|
33
|
+
raise ArgumentError.new("Block provided after calling `with_content`. Use one or the other.") if defined?(@_content_block) && defined?(@_content_set_by_with_content)
|
34
|
+
|
29
35
|
@content = if defined?(@_component_instance)
|
30
|
-
|
31
|
-
|
36
|
+
if defined?(@_content_set_by_with_content)
|
37
|
+
@_component_instance.with_content(@_content_set_by_with_content)
|
38
|
+
|
39
|
+
view_context.capture do
|
40
|
+
@_component_instance.render_in(view_context)
|
41
|
+
end
|
42
|
+
elsif defined?(@_content_block)
|
32
43
|
view_context.capture do
|
44
|
+
# render_in is faster than `parent.render`
|
33
45
|
@_component_instance.render_in(view_context, &@_content_block)
|
34
46
|
end
|
35
47
|
else
|
@@ -41,6 +53,8 @@ module ViewComponent
|
|
41
53
|
@_content
|
42
54
|
elsif defined?(@_content_block)
|
43
55
|
view_context.capture(&@_content_block)
|
56
|
+
elsif defined?(@_content_set_by_with_content)
|
57
|
+
@_content_set_by_with_content
|
44
58
|
end
|
45
59
|
|
46
60
|
@content
|
@@ -23,6 +23,11 @@ module ViewComponent
|
|
23
23
|
# class_name: "Header" # class name string, used to instantiate Slot
|
24
24
|
# )
|
25
25
|
def with_slot(*slot_names, collection: false, class_name: nil)
|
26
|
+
ActiveSupport::Deprecation.warn(
|
27
|
+
"`with_slot` is deprecated and will be removed in ViewComponent v3.0.0.\n" \
|
28
|
+
"Use the new slots API (https://viewcomponent.org/guide/slots.html) instead."
|
29
|
+
)
|
30
|
+
|
26
31
|
slot_names.each do |slot_name|
|
27
32
|
# Ensure slot_name is not already declared
|
28
33
|
if self.slots.key?(slot_name)
|
@@ -60,7 +60,7 @@ module ViewComponent
|
|
60
60
|
# helper method with the same name as the slot.
|
61
61
|
#
|
62
62
|
# <%= render_inline(MyComponent.new) do |component| %>
|
63
|
-
#
|
63
|
+
# <% component.header(classes: "Foo") do %>
|
64
64
|
# <p>Bar</p>
|
65
65
|
# <% end %>
|
66
66
|
# <% end %>
|
@@ -95,7 +95,7 @@ module ViewComponent
|
|
95
95
|
# helper method with the same name as the slot.
|
96
96
|
#
|
97
97
|
# <h1>
|
98
|
-
#
|
98
|
+
# <% items.each do |item| %>
|
99
99
|
# <%= item %>
|
100
100
|
# <% end %>
|
101
101
|
# </h1>
|
@@ -107,11 +107,11 @@ module ViewComponent
|
|
107
107
|
# called multiple times to append to the slot.
|
108
108
|
#
|
109
109
|
# <%= render_inline(MyComponent.new) do |component| %>
|
110
|
-
#
|
110
|
+
# <% component.item(name: "Foo") do %>
|
111
111
|
# <p>One</p>
|
112
112
|
# <% end %>
|
113
113
|
#
|
114
|
-
#
|
114
|
+
# <% component.item(name: "Bar") do %>
|
115
115
|
# <p>two</p>
|
116
116
|
# <% end %>
|
117
117
|
# <% end %>
|
@@ -175,6 +175,10 @@ module ViewComponent
|
|
175
175
|
end
|
176
176
|
|
177
177
|
def validate_slot_name(slot_name)
|
178
|
+
if slot_name.to_sym == :content
|
179
|
+
raise ArgumentError.new("#{slot_name} is not a valid slot name.")
|
180
|
+
end
|
181
|
+
|
178
182
|
if self.registered_slots.key?(slot_name)
|
179
183
|
# TODO remove? This breaks overriding slots when slots are inherited
|
180
184
|
raise ArgumentError.new("#{slot_name} slot declared multiple times")
|
@@ -251,7 +255,7 @@ module ViewComponent
|
|
251
255
|
@_set_slots[slot_name] = slot
|
252
256
|
end
|
253
257
|
|
254
|
-
|
258
|
+
slot
|
255
259
|
end
|
256
260
|
end
|
257
261
|
end
|
@@ -39,7 +39,12 @@ module ViewComponent
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def request
|
42
|
-
@request ||=
|
42
|
+
@request ||=
|
43
|
+
begin
|
44
|
+
request = ActionDispatch::TestRequest.create
|
45
|
+
request.session = ActionController::TestSession.new
|
46
|
+
request
|
47
|
+
end
|
43
48
|
end
|
44
49
|
|
45
50
|
def with_variant(variant)
|
@@ -60,6 +65,17 @@ module ViewComponent
|
|
60
65
|
@controller = old_controller
|
61
66
|
end
|
62
67
|
|
68
|
+
def with_request_url(path)
|
69
|
+
old_request_path_parameters = request.path_parameters
|
70
|
+
old_controller = defined?(@controller) && @controller
|
71
|
+
|
72
|
+
request.path_parameters = Rails.application.routes.recognize_path(path)
|
73
|
+
yield
|
74
|
+
ensure
|
75
|
+
request.path_parameters = old_request_path_parameters
|
76
|
+
@controller = old_controller
|
77
|
+
end
|
78
|
+
|
63
79
|
def build_controller(klass)
|
64
80
|
klass.new.tap { |c| c.request = request }.extend(Rails.application.routes.url_helpers)
|
65
81
|
end
|
@@ -9,6 +9,8 @@ module ViewComponent
|
|
9
9
|
module Translatable
|
10
10
|
extend ActiveSupport::Concern
|
11
11
|
|
12
|
+
HTML_SAFE_TRANSLATION_KEY = /(?:_|\b)html\z/.freeze
|
13
|
+
|
12
14
|
included do
|
13
15
|
class_attribute :i18n_backend, instance_writer: false, instance_predicate: false
|
14
16
|
end
|
@@ -21,11 +23,16 @@ module ViewComponent
|
|
21
23
|
def _after_compile
|
22
24
|
super
|
23
25
|
|
24
|
-
|
26
|
+
return if CompileCache.compiled? self
|
27
|
+
|
28
|
+
if (translation_files = _sidecar_files(%w[yml yaml])).any?
|
25
29
|
self.i18n_backend = I18nBackend.new(
|
26
30
|
i18n_scope: i18n_scope,
|
27
|
-
load_paths:
|
31
|
+
load_paths: translation_files,
|
28
32
|
)
|
33
|
+
else
|
34
|
+
# Cleanup if translations file has been removed since the last compilation
|
35
|
+
self.i18n_backend = nil
|
29
36
|
end
|
30
37
|
end
|
31
38
|
end
|
@@ -55,21 +62,28 @@ module ViewComponent
|
|
55
62
|
end
|
56
63
|
end
|
57
64
|
|
58
|
-
def translate(key = nil,
|
59
|
-
|
65
|
+
def translate(key = nil, **options)
|
66
|
+
return super unless i18n_backend
|
67
|
+
return key.map { |k| translate(k, **options) } if key.is_a?(Array)
|
60
68
|
|
69
|
+
locale = options.delete(:locale) || ::I18n.locale
|
70
|
+
key = key&.to_s unless key.is_a?(String)
|
61
71
|
key = "#{i18n_scope}#{key}" if key.start_with?(".")
|
62
72
|
|
63
|
-
|
73
|
+
translated = catch(:exception) do
|
64
74
|
i18n_backend.translate(locale, key, options)
|
65
75
|
end
|
66
76
|
|
67
77
|
# Fallback to the global translations
|
68
|
-
if
|
69
|
-
|
78
|
+
if translated.is_a? ::I18n::MissingTranslation
|
79
|
+
return super(key, locale: locale, **options)
|
80
|
+
end
|
81
|
+
|
82
|
+
if HTML_SAFE_TRANSLATION_KEY.match?(key)
|
83
|
+
translated = translated.html_safe
|
70
84
|
end
|
71
85
|
|
72
|
-
|
86
|
+
translated
|
73
87
|
end
|
74
88
|
alias :t :translate
|
75
89
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent
|
4
|
+
module WithContentHelper
|
5
|
+
def with_content(value)
|
6
|
+
if value.nil?
|
7
|
+
raise ArgumentError.new("No content provided.")
|
8
|
+
else
|
9
|
+
@_content_set_by_with_content = value
|
10
|
+
end
|
11
|
+
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
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.
|
4
|
+
version: 2.33.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -212,7 +212,21 @@ dependencies:
|
|
212
212
|
- - "~>"
|
213
213
|
- !ruby/object:Gem::Version
|
214
214
|
version: '0.13'
|
215
|
-
|
215
|
+
- !ruby/object:Gem::Dependency
|
216
|
+
name: yard
|
217
|
+
requirement: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - "~>"
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: 0.9.25
|
222
|
+
type: :development
|
223
|
+
prerelease: false
|
224
|
+
version_requirements: !ruby/object:Gem::Requirement
|
225
|
+
requirements:
|
226
|
+
- - "~>"
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
version: 0.9.25
|
229
|
+
description:
|
216
230
|
email:
|
217
231
|
- opensource+view_component@github.com
|
218
232
|
executables: []
|
@@ -246,6 +260,7 @@ files:
|
|
246
260
|
- lib/view_component/collection.rb
|
247
261
|
- lib/view_component/compile_cache.rb
|
248
262
|
- lib/view_component/compiler.rb
|
263
|
+
- lib/view_component/component_error.rb
|
249
264
|
- lib/view_component/engine.rb
|
250
265
|
- lib/view_component/preview.rb
|
251
266
|
- lib/view_component/preview_template_error.rb
|
@@ -265,12 +280,13 @@ files:
|
|
265
280
|
- lib/view_component/test_helpers.rb
|
266
281
|
- lib/view_component/translatable.rb
|
267
282
|
- lib/view_component/version.rb
|
283
|
+
- lib/view_component/with_content_helper.rb
|
268
284
|
homepage: https://github.com/github/view_component
|
269
285
|
licenses:
|
270
286
|
- MIT
|
271
287
|
metadata:
|
272
288
|
allowed_push_host: https://rubygems.org
|
273
|
-
post_install_message:
|
289
|
+
post_install_message:
|
274
290
|
rdoc_options: []
|
275
291
|
require_paths:
|
276
292
|
- lib
|
@@ -285,8 +301,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
285
301
|
- !ruby/object:Gem::Version
|
286
302
|
version: '0'
|
287
303
|
requirements: []
|
288
|
-
rubygems_version: 3.
|
289
|
-
signing_key:
|
304
|
+
rubygems_version: 3.2.3
|
305
|
+
signing_key:
|
290
306
|
specification_version: 4
|
291
307
|
summary: View components for Rails
|
292
308
|
test_files: []
|