view_component 2.28.0 → 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 +4 -4
- data/CHANGELOG.md +25 -0
- data/README.md +0 -8
- data/lib/view_component.rb +1 -0
- data/lib/view_component/base.rb +42 -1
- data/lib/view_component/compiler.rb +11 -43
- data/lib/view_component/slot_v2.rb +12 -9
- data/lib/view_component/slotable_v2.rb +3 -1
- data/lib/view_component/translatable.rb +81 -0
- data/lib/view_component/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8c387807061db7889dbc2e49ccb75a15a2cacd416048a6681b046eb321fb27b
|
4
|
+
data.tar.gz: fbddc58ff50b3ddaf615f773a681a7a8b7bef3972581dad8b87bf8425efff275
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63a070fc0a5001b888dbd57a2a9fb0660b351a05b522d9a832efdd2a60f981d218eda2f500a50d01ca6a8c5ada4cccb61f2837e7b956215e89528d9454d3fd39
|
7
|
+
data.tar.gz: 8176f0427272a8305a520eeaa72ae58be2d9df42282a981f376eb69ac0543017f98d737ecb09f6fa6fc8cacf85adbbf82fbefe337da22432448ab361f35ae447
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
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
|
+
|
5
30
|
## 2.28.0
|
6
31
|
|
7
32
|
* Include SlotableV2 by default in Base. **Note:** It's no longer necessary to include `ViewComponent::SlotableV2` to use Slots.
|
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.
|
data/lib/view_component.rb
CHANGED
data/lib/view_component/base.rb
CHANGED
@@ -131,7 +131,7 @@ module ViewComponent
|
|
131
131
|
@helpers ||= controller.view_context
|
132
132
|
end
|
133
133
|
|
134
|
-
# Exposes .
|
134
|
+
# Exposes .virtual_path as an instance method
|
135
135
|
def virtual_path
|
136
136
|
self.class.virtual_path
|
137
137
|
end
|
@@ -206,6 +206,47 @@ module ViewComponent
|
|
206
206
|
class << self
|
207
207
|
attr_accessor :source_location, :virtual_path
|
208
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
|
+
|
209
250
|
# Render a component collection.
|
210
251
|
def with_collection(collection, **args)
|
211
252
|
Collection.new(self, collection, **args)
|
@@ -114,50 +114,18 @@ module ViewComponent
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def templates
|
117
|
-
@templates ||=
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
def matching_views_in_source_location
|
129
|
-
source_location = component_class.source_location
|
130
|
-
return [] unless source_location
|
131
|
-
|
132
|
-
extensions = ActionView::Template.template_handler_extensions.join(",")
|
133
|
-
|
134
|
-
# view files in a directory named like the component
|
135
|
-
directory = File.dirname(source_location)
|
136
|
-
filename = File.basename(source_location, ".rb")
|
137
|
-
component_name = component_class.name.demodulize.underscore
|
138
|
-
|
139
|
-
# Add support for nested components defined in the same file.
|
140
|
-
#
|
141
|
-
# e.g.
|
142
|
-
#
|
143
|
-
# class MyComponent < ViewComponent::Base
|
144
|
-
# class MyOtherComponent < ViewComponent::Base
|
145
|
-
# end
|
146
|
-
# end
|
147
|
-
#
|
148
|
-
# Without this, `MyOtherComponent` will not look for `my_component/my_other_component.html.erb`
|
149
|
-
nested_component_files = if component_class.name.include?("::") && component_name != filename
|
150
|
-
Dir["#{directory}/#{filename}/#{component_name}.*{#{extensions}}"]
|
151
|
-
else
|
152
|
-
[]
|
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
|
153
128
|
end
|
154
|
-
|
155
|
-
# view files in the same directory as the component
|
156
|
-
sidecar_files = Dir["#{directory}/#{component_name}.*{#{extensions}}"]
|
157
|
-
|
158
|
-
sidecar_directory_files = Dir["#{directory}/#{component_name}/#{filename}.*{#{extensions}}"]
|
159
|
-
|
160
|
-
(sidecar_files - [source_location] + sidecar_directory_files + nested_component_files)
|
161
129
|
end
|
162
130
|
|
163
131
|
def inline_calls
|
@@ -25,19 +25,22 @@ module ViewComponent
|
|
25
25
|
return @content if defined?(@content)
|
26
26
|
|
27
27
|
view_context = @parent.send(:view_context)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
32
33
|
@_component_instance.render_in(view_context, &@_content_block)
|
33
|
-
|
34
|
+
end
|
35
|
+
else
|
36
|
+
view_context.capture do
|
34
37
|
@_component_instance.render_in(view_context)
|
35
38
|
end
|
36
|
-
elsif defined?(@_content)
|
37
|
-
@_content
|
38
|
-
elsif defined?(@_content_block)
|
39
|
-
@_content_block.call
|
40
39
|
end
|
40
|
+
elsif defined?(@_content)
|
41
|
+
@_content
|
42
|
+
elsif defined?(@_content_block)
|
43
|
+
view_context.capture(&@_content_block)
|
41
44
|
end
|
42
45
|
|
43
46
|
@content
|
@@ -227,7 +227,9 @@ module ViewComponent
|
|
227
227
|
# current component. This is necessary to allow the lambda to access helper
|
228
228
|
# methods like `content_tag` as well as parent component state.
|
229
229
|
renderable_value = if block_given?
|
230
|
-
slot_definition[:renderable_function].bind(self).call(*args, **kwargs)
|
230
|
+
slot_definition[:renderable_function].bind(self).call(*args, **kwargs) do |*args, **kwargs|
|
231
|
+
view_context.capture(*args, **kwargs, &block)
|
232
|
+
end
|
231
233
|
else
|
232
234
|
slot_definition[:renderable_function].bind(self).call(*args, **kwargs)
|
233
235
|
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
|
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.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-
|
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:
|