view_component 3.0.0.rc2 → 3.0.0.rc4
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/app/controllers/view_components_system_test_controller.rb +22 -1
- data/docs/CHANGELOG.md +36 -0
- data/lib/view_component/base.rb +5 -0
- data/lib/view_component/compiler.rb +49 -11
- data/lib/view_component/inline_template.rb +55 -0
- data/lib/view_component/system_test_helpers.rb +5 -5
- data/lib/view_component/test_helpers.rb +53 -31
- data/lib/view_component/translatable.rb +33 -23
- data/lib/view_component/version.rb +1 -1
- data/lib/view_component.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53d058ef489a0f7230b3a83fe92d36fab42b9b8ccf0cd2bba0d12f7320f2c261
|
4
|
+
data.tar.gz: de28dc5a7e3e9c34c3cf81bbd5d52f518c653950552547c86a547bb4a577bdfa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6161e41e5b9b82ce20f9ffc624cfe2910e707d867e2ba0019bc960a02353e7d2b083700e3504ea1f84da83f9a31110eb581a07a16609d30c6a7737806f5986e
|
7
|
+
data.tar.gz: c137ce79675ec78c4f31dff419b42fdf31d2af696e2275047d74058c7e1402be00e0e44df125ea6c5803b59e6931d8a7619c9c266376b02881965a778e60d784
|
@@ -1,7 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ViewComponentsSystemTestController < ActionController::Base # :nodoc:
|
4
|
+
TEMP_DIR = FileUtils.mkdir_p("./tmp/view_components/").first
|
5
|
+
|
6
|
+
before_action :validate_test_env
|
7
|
+
before_action :validate_file_path
|
8
|
+
|
4
9
|
def system_test_entrypoint
|
5
|
-
render file:
|
10
|
+
render file: @path
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def validate_test_env
|
16
|
+
raise "ViewComponentsSystemTestController must only be called in a test environment" unless Rails.env.test?
|
17
|
+
end
|
18
|
+
|
19
|
+
# Ensure that the file path is valid and doesn't target files outside
|
20
|
+
# the expected directory (e.g. via a path traversal or symlink attack)
|
21
|
+
def validate_file_path
|
22
|
+
base_path = ::File.realpath(TEMP_DIR)
|
23
|
+
@path = ::File.realpath(params.permit(:file)[:file], base_path)
|
24
|
+
unless @path.start_with?(base_path)
|
25
|
+
raise ArgumentError, "Invalid file path"
|
26
|
+
end
|
6
27
|
end
|
7
28
|
end
|
data/docs/CHANGELOG.md
CHANGED
@@ -10,6 +10,42 @@ nav_order: 5
|
|
10
10
|
|
11
11
|
## main
|
12
12
|
|
13
|
+
## v3.0.0.rc4
|
14
|
+
|
15
|
+
Run into an issue with this release candidate? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
16
|
+
|
17
|
+
* Add `TestHelpers#vc_test_request`.
|
18
|
+
|
19
|
+
*Joel Hawksley*
|
20
|
+
|
21
|
+
## v3.0.0.rc3
|
22
|
+
|
23
|
+
Run into an issue with this release candidate? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
24
|
+
|
25
|
+
* Fix typos in generator docs.
|
26
|
+
|
27
|
+
*Sascha Karnatz*
|
28
|
+
|
29
|
+
* Add `TestHelpers#vc_test_controller`.
|
30
|
+
|
31
|
+
*Joel Hawksley*
|
32
|
+
|
33
|
+
* Document `config.view_component.capture_compatibility_patch_enabled` as option for the known incompatibilities with Rails form helpers.
|
34
|
+
|
35
|
+
*Tobias L. Maier*
|
36
|
+
|
37
|
+
* Add support for experimental inline templates.
|
38
|
+
|
39
|
+
*Blake Williams*
|
40
|
+
|
41
|
+
* Expose `translate` and `t` I18n methods on component classes.
|
42
|
+
|
43
|
+
*Elia Schito*
|
44
|
+
|
45
|
+
* Protect against Arbitrary File Read edge case in `ViewComponentsSystemTestController`.
|
46
|
+
|
47
|
+
*Nick Malcolm*
|
48
|
+
|
13
49
|
## v3.0.0.rc2
|
14
50
|
|
15
51
|
Run into an issue with this release? [Let us know](https://github.com/ViewComponent/view_component/issues/1629).
|
data/lib/view_component/base.rb
CHANGED
@@ -481,6 +481,11 @@ module ViewComponent
|
|
481
481
|
compiler.compiled?
|
482
482
|
end
|
483
483
|
|
484
|
+
# @private
|
485
|
+
def ensure_compiled
|
486
|
+
compile unless compiled?
|
487
|
+
end
|
488
|
+
|
484
489
|
# Compile templates to instance methods, assuming they haven't been compiled already.
|
485
490
|
#
|
486
491
|
# Do as much work as possible in this step, as doing so reduces the amount
|
@@ -51,24 +51,46 @@ module ViewComponent
|
|
51
51
|
component_class.validate_collection_parameter!
|
52
52
|
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
# as Ruby warns when redefining a method.
|
57
|
-
method_name = call_method_name(template[:variant])
|
54
|
+
if has_inline_template?
|
55
|
+
template = component_class.inline_template
|
58
56
|
|
59
57
|
redefinition_lock.synchronize do
|
60
|
-
component_class.silence_redefinition_of_method(
|
58
|
+
component_class.silence_redefinition_of_method("call")
|
61
59
|
# rubocop:disable Style/EvalWithLocation
|
62
|
-
component_class.class_eval <<-RUBY, template
|
63
|
-
def
|
64
|
-
#{
|
60
|
+
component_class.class_eval <<-RUBY, template.path, template.lineno
|
61
|
+
def call
|
62
|
+
#{compiled_inline_template(template)}
|
65
63
|
end
|
66
64
|
RUBY
|
67
65
|
# rubocop:enable Style/EvalWithLocation
|
66
|
+
|
67
|
+
component_class.silence_redefinition_of_method("render_template_for")
|
68
|
+
component_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
69
|
+
def render_template_for(variant = nil)
|
70
|
+
call
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
end
|
74
|
+
else
|
75
|
+
templates.each do |template|
|
76
|
+
# Remove existing compiled template methods,
|
77
|
+
# as Ruby warns when redefining a method.
|
78
|
+
method_name = call_method_name(template[:variant])
|
79
|
+
|
80
|
+
redefinition_lock.synchronize do
|
81
|
+
component_class.silence_redefinition_of_method(method_name)
|
82
|
+
# rubocop:disable Style/EvalWithLocation
|
83
|
+
component_class.class_eval <<-RUBY, template[:path], 0
|
84
|
+
def #{method_name}
|
85
|
+
#{compiled_template(template[:path])}
|
86
|
+
end
|
87
|
+
RUBY
|
88
|
+
# rubocop:enable Style/EvalWithLocation
|
89
|
+
end
|
68
90
|
end
|
69
|
-
end
|
70
91
|
|
71
|
-
|
92
|
+
define_render_template_for
|
93
|
+
end
|
72
94
|
|
73
95
|
component_class.build_i18n_backend
|
74
96
|
|
@@ -103,12 +125,16 @@ module ViewComponent
|
|
103
125
|
end
|
104
126
|
end
|
105
127
|
|
128
|
+
def has_inline_template?
|
129
|
+
component_class.respond_to?(:inline_template) && component_class.inline_template.present?
|
130
|
+
end
|
131
|
+
|
106
132
|
def template_errors
|
107
133
|
@__vc_template_errors ||=
|
108
134
|
begin
|
109
135
|
errors = []
|
110
136
|
|
111
|
-
if (templates + inline_calls).empty?
|
137
|
+
if (templates + inline_calls).empty? && !has_inline_template?
|
112
138
|
errors << "Couldn't find a template file or inline render method for #{component_class}."
|
113
139
|
end
|
114
140
|
|
@@ -216,9 +242,21 @@ module ViewComponent
|
|
216
242
|
end
|
217
243
|
end
|
218
244
|
|
245
|
+
def compiled_inline_template(template)
|
246
|
+
handler = ActionView::Template.handler_for_extension(template.language)
|
247
|
+
template.rstrip! if component_class.strip_trailing_whitespace?
|
248
|
+
|
249
|
+
compile_template(template.source, handler)
|
250
|
+
end
|
251
|
+
|
219
252
|
def compiled_template(file_path)
|
220
253
|
handler = ActionView::Template.handler_for_extension(File.extname(file_path).delete("."))
|
221
254
|
template = File.read(file_path)
|
255
|
+
|
256
|
+
compile_template(template, handler)
|
257
|
+
end
|
258
|
+
|
259
|
+
def compile_template(template, handler)
|
222
260
|
template.rstrip! if component_class.strip_trailing_whitespace?
|
223
261
|
|
224
262
|
if handler.method(:call).parameters.length > 1
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViewComponent # :nodoc:
|
4
|
+
module InlineTemplate
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
Template = Struct.new(:source, :language, :path, :lineno)
|
7
|
+
|
8
|
+
class_methods do
|
9
|
+
def method_missing(method, *args)
|
10
|
+
return super if !method.end_with?("_template")
|
11
|
+
|
12
|
+
if defined?(@__vc_inline_template_defined) && @__vc_inline_template_defined
|
13
|
+
raise ViewComponent::ComponentError, "inline templates can only be defined once per-component"
|
14
|
+
end
|
15
|
+
|
16
|
+
if args.size != 1
|
17
|
+
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 1)"
|
18
|
+
end
|
19
|
+
|
20
|
+
ext = method.to_s.gsub("_template", "")
|
21
|
+
template = args.first
|
22
|
+
|
23
|
+
@__vc_inline_template_language = ext
|
24
|
+
|
25
|
+
caller = caller_locations(1..1)[0]
|
26
|
+
@__vc_inline_template = Template.new(
|
27
|
+
template,
|
28
|
+
ext,
|
29
|
+
caller.absolute_path || caller.path,
|
30
|
+
caller.lineno
|
31
|
+
)
|
32
|
+
|
33
|
+
@__vc_inline_template_defined = true
|
34
|
+
end
|
35
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
36
|
+
|
37
|
+
def respond_to_missing?(method, include_all = false)
|
38
|
+
method.end_with?("_template") || super
|
39
|
+
end
|
40
|
+
|
41
|
+
def inline_template
|
42
|
+
@__vc_inline_template
|
43
|
+
end
|
44
|
+
|
45
|
+
def inline_template_language
|
46
|
+
@__vc_inline_template_language if defined?(@__vc_inline_template_language)
|
47
|
+
end
|
48
|
+
|
49
|
+
def inherited(subclass)
|
50
|
+
super
|
51
|
+
subclass.instance_variable_set(:@__vc_inline_template_language, inline_template_language)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -10,12 +10,12 @@ module ViewComponent
|
|
10
10
|
# @param layout [String] The (optional) layout to use.
|
11
11
|
# @return [Proc] A block that can be used to visit the path of the inline rendered component.
|
12
12
|
def with_rendered_component_path(fragment, layout: false, &block)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
file = Tempfile.new(
|
14
|
+
["rendered_#{fragment.class.name}", ".html"],
|
15
|
+
ViewComponentsSystemTestController::TEMP_DIR
|
16
|
+
)
|
17
17
|
begin
|
18
|
-
file.write(
|
18
|
+
file.write(vc_test_controller.render_to_string(html: fragment.to_html.html_safe, layout: layout))
|
19
19
|
file.rewind
|
20
20
|
|
21
21
|
block.call("/_system_test_entrypoint?file=#{file.path.split("/").last}")
|
@@ -47,9 +47,9 @@ module ViewComponent
|
|
47
47
|
@page = nil
|
48
48
|
@rendered_content =
|
49
49
|
if Rails.version.to_f >= 6.1
|
50
|
-
|
50
|
+
vc_test_controller.view_context.render(component, args, &block)
|
51
51
|
else
|
52
|
-
|
52
|
+
vc_test_controller.view_context.render_component(component, &block)
|
53
53
|
end
|
54
54
|
|
55
55
|
Nokogiri::HTML.fragment(@rendered_content)
|
@@ -105,7 +105,7 @@ module ViewComponent
|
|
105
105
|
# ```
|
106
106
|
def render_in_view_context(*args, &block)
|
107
107
|
@page = nil
|
108
|
-
@rendered_content =
|
108
|
+
@rendered_content = vc_test_controller.view_context.instance_exec(*args, &block)
|
109
109
|
Nokogiri::HTML.fragment(@rendered_content)
|
110
110
|
end
|
111
111
|
ruby2_keywords(:render_in_view_context) if respond_to?(:ruby2_keywords, true)
|
@@ -120,12 +120,12 @@ module ViewComponent
|
|
120
120
|
#
|
121
121
|
# @param variant [Symbol] The variant to be set for the provided block.
|
122
122
|
def with_variant(variant)
|
123
|
-
old_variants =
|
123
|
+
old_variants = vc_test_controller.view_context.lookup_context.variants
|
124
124
|
|
125
|
-
|
125
|
+
vc_test_controller.view_context.lookup_context.variants = variant
|
126
126
|
yield
|
127
127
|
ensure
|
128
|
-
|
128
|
+
vc_test_controller.view_context.lookup_context.variants = old_variants
|
129
129
|
end
|
130
130
|
|
131
131
|
# Set the controller to be used while executing the given block,
|
@@ -139,12 +139,12 @@ module ViewComponent
|
|
139
139
|
#
|
140
140
|
# @param klass [ActionController::Base] The controller to be used.
|
141
141
|
def with_controller_class(klass)
|
142
|
-
old_controller = defined?(@
|
142
|
+
old_controller = defined?(@vc_test_controller) && @vc_test_controller
|
143
143
|
|
144
|
-
@
|
144
|
+
@vc_test_controller = __vc_test_helpers_build_controller(klass)
|
145
145
|
yield
|
146
146
|
ensure
|
147
|
-
@
|
147
|
+
@vc_test_controller = old_controller
|
148
148
|
end
|
149
149
|
|
150
150
|
# Set the URL of the current request (such as when using request-dependent path helpers):
|
@@ -157,35 +157,54 @@ module ViewComponent
|
|
157
157
|
#
|
158
158
|
# @param path [String] The path to set for the current request.
|
159
159
|
def with_request_url(path)
|
160
|
-
old_request_path_info =
|
161
|
-
old_request_path_parameters =
|
162
|
-
old_request_query_parameters =
|
163
|
-
old_request_query_string =
|
164
|
-
old_controller = defined?(@
|
160
|
+
old_request_path_info = vc_test_request.path_info
|
161
|
+
old_request_path_parameters = vc_test_request.path_parameters
|
162
|
+
old_request_query_parameters = vc_test_request.query_parameters
|
163
|
+
old_request_query_string = vc_test_request.query_string
|
164
|
+
old_controller = defined?(@vc_test_controller) && @vc_test_controller
|
165
165
|
|
166
166
|
path, query = path.split("?", 2)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
167
|
+
vc_test_request.path_info = path
|
168
|
+
vc_test_request.path_parameters = Rails.application.routes.recognize_path_with_request(vc_test_request, path, {})
|
169
|
+
vc_test_request.set_header("action_dispatch.request.query_parameters", Rack::Utils.parse_nested_query(query))
|
170
|
+
vc_test_request.set_header(Rack::QUERY_STRING, query)
|
171
171
|
yield
|
172
172
|
ensure
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
@
|
173
|
+
vc_test_request.path_info = old_request_path_info
|
174
|
+
vc_test_request.path_parameters = old_request_path_parameters
|
175
|
+
vc_test_request.set_header("action_dispatch.request.query_parameters", old_request_query_parameters)
|
176
|
+
vc_test_request.set_header(Rack::QUERY_STRING, old_request_query_string)
|
177
|
+
@vc_test_controller = old_controller
|
178
178
|
end
|
179
179
|
|
180
|
-
#
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
180
|
+
# Access the controller used by `render_inline`:
|
181
|
+
#
|
182
|
+
# ```ruby
|
183
|
+
# test "logged out user sees login link" do
|
184
|
+
# vc_test_controller.expects(:logged_in?).at_least_once.returns(false)
|
185
|
+
# render_inline(LoginComponent.new)
|
186
|
+
# assert_selector("[aria-label='You must be signed in']")
|
187
|
+
# end
|
188
|
+
# ```
|
189
|
+
#
|
190
|
+
# @return [ActionController::Base]
|
191
|
+
def vc_test_controller
|
192
|
+
@vc_test_controller ||= __vc_test_helpers_build_controller(Base.test_controller.constantize)
|
185
193
|
end
|
186
194
|
|
187
|
-
|
188
|
-
|
195
|
+
# Access the request used by `render_inline`:
|
196
|
+
#
|
197
|
+
# ```ruby
|
198
|
+
# test "component does not render in Firefox" do
|
199
|
+
# request.env["HTTP_USER_AGENT"] = "Mozilla/5.0"
|
200
|
+
# render_inline(NoFirefoxComponent.new)
|
201
|
+
# refute_component_rendered
|
202
|
+
# end
|
203
|
+
# ```
|
204
|
+
#
|
205
|
+
# @return [ActionDispatch::TestRequest]
|
206
|
+
def vc_test_request
|
207
|
+
@vc_test_request ||=
|
189
208
|
begin
|
190
209
|
out = ActionDispatch::TestRequest.create
|
191
210
|
out.session = ActionController::TestSession.new
|
@@ -193,8 +212,11 @@ module ViewComponent
|
|
193
212
|
end
|
194
213
|
end
|
195
214
|
|
215
|
+
# Note: We prefix private methods here to prevent collisions in consumer's tests.
|
216
|
+
private
|
217
|
+
|
196
218
|
def __vc_test_helpers_build_controller(klass)
|
197
|
-
klass.new.tap { |c| c.request =
|
219
|
+
klass.new.tap { |c| c.request = vc_test_request }.extend(Rails.application.routes.url_helpers)
|
198
220
|
end
|
199
221
|
|
200
222
|
def __vc_test_helpers_preview_class
|
@@ -21,7 +21,7 @@ module ViewComponent
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def build_i18n_backend
|
24
|
-
return if
|
24
|
+
return if compiled?
|
25
25
|
|
26
26
|
self.i18n_backend = if (translation_files = sidecar_files(%w[yml yaml])).any?
|
27
27
|
# Returning nil cleans up if translations file has been removed since the last compilation
|
@@ -32,6 +32,27 @@ module ViewComponent
|
|
32
32
|
)
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
def i18n_key(key, scope = nil)
|
37
|
+
scope = scope.join(".") if scope.is_a? Array
|
38
|
+
key = key&.to_s unless key.is_a?(String)
|
39
|
+
key = "#{scope}.#{key}" if scope
|
40
|
+
key = "#{i18n_scope}#{key}" if key.start_with?(".")
|
41
|
+
key
|
42
|
+
end
|
43
|
+
|
44
|
+
def translate(key = nil, **options)
|
45
|
+
return key.map { |k| translate(k, **options) } if key.is_a?(Array)
|
46
|
+
|
47
|
+
ensure_compiled
|
48
|
+
|
49
|
+
locale = options.delete(:locale) || ::I18n.locale
|
50
|
+
key = i18n_key(key, options.delete(:scope))
|
51
|
+
|
52
|
+
i18n_backend.translate(locale, key, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :t, :translate
|
35
56
|
end
|
36
57
|
|
37
58
|
class I18nBackend < ::I18n::Backend::Simple
|
@@ -64,15 +85,10 @@ module ViewComponent
|
|
64
85
|
return key.map { |k| translate(k, **options) } if key.is_a?(Array)
|
65
86
|
|
66
87
|
locale = options.delete(:locale) || ::I18n.locale
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
key = "#{i18n_scope}#{key}" if key.start_with?(".")
|
72
|
-
|
73
|
-
if HTML_SAFE_TRANSLATION_KEY.match?(key)
|
74
|
-
html_escape_translation_options!(options)
|
75
|
-
end
|
88
|
+
key = self.class.i18n_key(key, options.delete(:scope))
|
89
|
+
as_html = HTML_SAFE_TRANSLATION_KEY.match?(key)
|
90
|
+
|
91
|
+
html_escape_translation_options!(options) if as_html
|
76
92
|
|
77
93
|
if key.start_with?(i18n_scope + ".")
|
78
94
|
translated =
|
@@ -85,10 +101,7 @@ module ViewComponent
|
|
85
101
|
return super(key, locale: locale, **options)
|
86
102
|
end
|
87
103
|
|
88
|
-
|
89
|
-
translated = html_safe_translation(translated)
|
90
|
-
end
|
91
|
-
|
104
|
+
translated = html_safe_translation(translated) if as_html
|
92
105
|
translated
|
93
106
|
else
|
94
107
|
super(key, locale: locale, **options)
|
@@ -101,6 +114,8 @@ module ViewComponent
|
|
101
114
|
self.class.i18n_scope
|
102
115
|
end
|
103
116
|
|
117
|
+
private
|
118
|
+
|
104
119
|
def html_safe_translation(translation)
|
105
120
|
if translation.respond_to?(:map)
|
106
121
|
translation.map { |element| html_safe_translation(element) }
|
@@ -112,18 +127,13 @@ module ViewComponent
|
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
115
|
-
private
|
116
|
-
|
117
130
|
def html_escape_translation_options!(options)
|
118
131
|
options.each do |name, value|
|
119
|
-
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
132
|
+
next if ::I18n.reserved_keys_pattern.match?(name)
|
133
|
+
next if name == :count && value.is_a?(Numeric)
|
124
134
|
|
125
|
-
|
126
|
-
|
135
|
+
options[name] = ERB::Util.html_escape(value.to_s)
|
136
|
+
end
|
127
137
|
end
|
128
138
|
end
|
129
139
|
end
|
data/lib/view_component.rb
CHANGED
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: 3.0.0.
|
4
|
+
version: 3.0.0.rc4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ViewComponent Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -363,6 +363,7 @@ files:
|
|
363
363
|
- lib/view_component/docs_builder_component.html.erb
|
364
364
|
- lib/view_component/docs_builder_component.rb
|
365
365
|
- lib/view_component/engine.rb
|
366
|
+
- lib/view_component/inline_template.rb
|
366
367
|
- lib/view_component/instrumentation.rb
|
367
368
|
- lib/view_component/preview.rb
|
368
369
|
- lib/view_component/preview_template_error.rb
|