view_component 4.0.2 → 4.12.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.
- checksums.yaml +4 -4
- data/app/controllers/view_components_system_test_controller.rb +12 -1
- data/docs/CHANGELOG.md +190 -108
- data/lib/generators/view_component/component/component_generator.rb +1 -1
- data/lib/view_component/base.rb +92 -23
- data/lib/view_component/collection.rb +17 -13
- data/lib/view_component/compiler.rb +12 -10
- data/lib/view_component/config.rb +5 -1
- data/lib/view_component/configurable.rb +18 -2
- data/lib/view_component/engine.rb +12 -2
- data/lib/view_component/inline_template.rb +1 -0
- data/lib/view_component/instrumentation.rb +19 -6
- data/lib/view_component/preview.rb +3 -1
- data/lib/view_component/slot.rb +3 -4
- data/lib/view_component/slotable.rb +12 -3
- data/lib/view_component/system_test_helpers.rb +1 -0
- data/lib/view_component/template.rb +55 -2
- data/lib/view_component/test_helpers.rb +25 -11
- data/lib/view_component/version.rb +2 -2
- data/lib/view_component.rb +2 -1
- metadata +15 -7
|
@@ -21,11 +21,39 @@ module ViewComponent
|
|
|
21
21
|
|
|
22
22
|
class File < Template
|
|
23
23
|
def initialize(component:, details:, path:)
|
|
24
|
+
# If the template file has no format (e.g. .erb instead of .html.erb),
|
|
25
|
+
# assume the default format (html).
|
|
26
|
+
if details.format.nil?
|
|
27
|
+
Kernel.warn("WARNING: Template format for #{path} is missing, defaulting to :html.")
|
|
28
|
+
details = ActionView::TemplateDetails.new(details.locale, details.handler, DEFAULT_FORMAT, details.variant)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@strip_annotation_line = false
|
|
32
|
+
|
|
33
|
+
# Rails 8.1 added a newline to compiled ERB output (rails/rails#53731).
|
|
34
|
+
# Use -1 to compensate for correct line numbers in stack traces.
|
|
35
|
+
# However, negative line numbers cause segfaults when Ruby's coverage
|
|
36
|
+
# is enabled (bugs.ruby-lang.org/issues/19363). In that case, strip the
|
|
37
|
+
# annotation line from compiled source instead.
|
|
38
|
+
lineno =
|
|
39
|
+
if Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0 && details.handler == :erb
|
|
40
|
+
if coverage_running?
|
|
41
|
+
# Can't use negative lineno with coverage (causes segfault on Linux).
|
|
42
|
+
# Strip annotation line if enabled to preserve correct line numbers.
|
|
43
|
+
@strip_annotation_line = ActionView::Base.annotate_rendered_view_with_filenames
|
|
44
|
+
0
|
|
45
|
+
else
|
|
46
|
+
-1
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
0
|
|
50
|
+
end
|
|
51
|
+
|
|
24
52
|
super(
|
|
25
53
|
component: component,
|
|
26
54
|
details: details,
|
|
27
55
|
path: path,
|
|
28
|
-
lineno:
|
|
56
|
+
lineno: lineno
|
|
29
57
|
)
|
|
30
58
|
end
|
|
31
59
|
|
|
@@ -37,6 +65,16 @@ module ViewComponent
|
|
|
37
65
|
def source
|
|
38
66
|
::File.read(@path)
|
|
39
67
|
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def compiled_source
|
|
72
|
+
result = super
|
|
73
|
+
# Strip the annotation line to maintain correct line numbers when coverage
|
|
74
|
+
# is running (avoids segfault from negative lineno)
|
|
75
|
+
result = result.partition(";").last if @strip_annotation_line
|
|
76
|
+
result
|
|
77
|
+
end
|
|
40
78
|
end
|
|
41
79
|
|
|
42
80
|
class Inline < Template
|
|
@@ -45,11 +83,22 @@ module ViewComponent
|
|
|
45
83
|
def initialize(component:, inline_template:)
|
|
46
84
|
details = ActionView::TemplateDetails.new(nil, inline_template.language.to_sym, nil, nil)
|
|
47
85
|
|
|
86
|
+
# Rails 8.1 added a newline to compiled ERB output (rails/rails#53731).
|
|
87
|
+
# Subtract 1 to compensate for correct line numbers in stack traces.
|
|
88
|
+
# Inline templates start at line 2+ (defined inside a class), so this
|
|
89
|
+
# won't result in negative line numbers that cause segfaults with coverage.
|
|
90
|
+
lineno =
|
|
91
|
+
if Rails::VERSION::MAJOR >= 8 && Rails::VERSION::MINOR > 0 && details.handler == :erb
|
|
92
|
+
inline_template.lineno - 1
|
|
93
|
+
else
|
|
94
|
+
inline_template.lineno
|
|
95
|
+
end
|
|
96
|
+
|
|
48
97
|
super(
|
|
49
98
|
component: component,
|
|
50
99
|
details: details,
|
|
51
100
|
path: inline_template.path,
|
|
52
|
-
lineno:
|
|
101
|
+
lineno: lineno,
|
|
53
102
|
)
|
|
54
103
|
|
|
55
104
|
@source = inline_template.source.dup
|
|
@@ -108,6 +157,10 @@ module ViewComponent
|
|
|
108
157
|
@component.define_method(safe_method_name, @component.instance_method(@call_method_name))
|
|
109
158
|
end
|
|
110
159
|
|
|
160
|
+
def coverage_running?
|
|
161
|
+
defined?(Coverage) && Coverage.running?
|
|
162
|
+
end
|
|
163
|
+
|
|
111
164
|
def safe_method_name_call
|
|
112
165
|
m = safe_method_name
|
|
113
166
|
proc { send(m) }
|
|
@@ -35,12 +35,13 @@ module ViewComponent
|
|
|
35
35
|
# ```
|
|
36
36
|
#
|
|
37
37
|
# @param component [ViewComponent::Base, ViewComponent::Collection] The instance of the component to be rendered.
|
|
38
|
+
#
|
|
38
39
|
# @return [Nokogiri::HTML5]
|
|
39
40
|
def render_inline(component, **args, &block)
|
|
40
41
|
@page = nil
|
|
41
42
|
@rendered_content = vc_test_view_context.render(component, args, &block)
|
|
42
43
|
|
|
43
|
-
fragment = Nokogiri::HTML5.fragment(@rendered_content)
|
|
44
|
+
fragment = Nokogiri::HTML5.fragment(@rendered_content, context: "template")
|
|
44
45
|
@vc_test_view_context = nil
|
|
45
46
|
fragment
|
|
46
47
|
end
|
|
@@ -71,17 +72,18 @@ module ViewComponent
|
|
|
71
72
|
# assert_text("Hello, World!")
|
|
72
73
|
# ```
|
|
73
74
|
#
|
|
74
|
-
# Note: `#rendered_preview` expects a preview to be defined with the same class
|
|
75
|
-
# name as the calling test, but with `Test` replaced with `Preview`:
|
|
76
|
-
#
|
|
77
|
-
# MyComponentTest -> MyComponentPreview etc.
|
|
78
|
-
#
|
|
79
|
-
# In RSpec, `Preview` is appended to `described_class`.
|
|
80
|
-
#
|
|
81
75
|
# @param name [String] The name of the preview to be rendered.
|
|
82
76
|
# @param from [ViewComponent::Preview] The class of the preview to be rendered.
|
|
83
77
|
# @param params [Hash] Parameters to be passed to the preview.
|
|
78
|
+
#
|
|
84
79
|
# @return [Nokogiri::HTML5]
|
|
80
|
+
#
|
|
81
|
+
# @note `#rendered_preview` expects a preview to be defined with the same class
|
|
82
|
+
# name as the calling test, but with `Test` replaced with `Preview`:
|
|
83
|
+
#
|
|
84
|
+
# MyComponentTest -> MyComponentPreview etc.
|
|
85
|
+
#
|
|
86
|
+
# In RSpec, `Preview` is appended to `described_class`.
|
|
85
87
|
def render_preview(name, from: __vc_test_helpers_preview_class, params: {})
|
|
86
88
|
previews_controller = __vc_test_helpers_build_controller(Rails.application.config.view_component.previews.controller.constantize)
|
|
87
89
|
|
|
@@ -125,7 +127,7 @@ module ViewComponent
|
|
|
125
127
|
# end
|
|
126
128
|
# ```
|
|
127
129
|
#
|
|
128
|
-
# @param variants [Symbol
|
|
130
|
+
# @param variants [Array<Symbol>] The variants to be set for the provided block.
|
|
129
131
|
def with_variant(*variants)
|
|
130
132
|
old_variants = vc_test_controller.view_context.lookup_context.variants
|
|
131
133
|
|
|
@@ -162,7 +164,7 @@ module ViewComponent
|
|
|
162
164
|
# end
|
|
163
165
|
# ```
|
|
164
166
|
#
|
|
165
|
-
# @param formats [Symbol
|
|
167
|
+
# @param formats [Array<Symbol>] The format(s) to be set for the provided block.
|
|
166
168
|
def with_format(*formats)
|
|
167
169
|
old_formats = vc_test_controller.view_context.lookup_context.formats
|
|
168
170
|
|
|
@@ -196,10 +198,19 @@ module ViewComponent
|
|
|
196
198
|
# end
|
|
197
199
|
# ```
|
|
198
200
|
#
|
|
201
|
+
# To specify a protocol, pass the protocol param:
|
|
202
|
+
#
|
|
203
|
+
# ```ruby
|
|
204
|
+
# with_request_url("/users/42", protocol: :https) do
|
|
205
|
+
# render_inline(MyComponent.new)
|
|
206
|
+
# end
|
|
207
|
+
# ```
|
|
208
|
+
#
|
|
199
209
|
# @param full_path [String] The path to set for the current request.
|
|
200
210
|
# @param host [String] The host to set for the current request.
|
|
201
211
|
# @param method [String] The request method to set for the current request.
|
|
202
|
-
|
|
212
|
+
# @param protocol [Symbol] The protocol to set for the current request (e.g., `:http` or `:https`).
|
|
213
|
+
def with_request_url(full_path, host: nil, method: nil, protocol: nil)
|
|
203
214
|
old_request_host = vc_test_request.host
|
|
204
215
|
old_request_method = vc_test_request.request_method
|
|
205
216
|
old_request_path_info = vc_test_request.path_info
|
|
@@ -207,6 +218,7 @@ module ViewComponent
|
|
|
207
218
|
old_request_query_parameters = vc_test_request.query_parameters
|
|
208
219
|
old_request_query_string = vc_test_request.query_string
|
|
209
220
|
old_request_format = vc_test_request.format.symbol
|
|
221
|
+
old_request_scheme = vc_test_request.scheme
|
|
210
222
|
old_controller = defined?(@vc_test_controller) && @vc_test_controller
|
|
211
223
|
|
|
212
224
|
path, query = full_path.split("?", 2)
|
|
@@ -214,6 +226,7 @@ module ViewComponent
|
|
|
214
226
|
vc_test_request.instance_variable_set(:@original_fullpath, full_path)
|
|
215
227
|
vc_test_request.host = host if host
|
|
216
228
|
vc_test_request.request_method = method if method
|
|
229
|
+
vc_test_request.set_header(Rack::RACK_URL_SCHEME, protocol.to_s) if protocol
|
|
217
230
|
vc_test_request.path_info = path
|
|
218
231
|
vc_test_request.path_parameters = Rails.application.routes.recognize_path_with_request(vc_test_request, path, {})
|
|
219
232
|
vc_test_request.set_header("action_dispatch.request.query_parameters",
|
|
@@ -223,6 +236,7 @@ module ViewComponent
|
|
|
223
236
|
ensure
|
|
224
237
|
vc_test_request.host = old_request_host
|
|
225
238
|
vc_test_request.request_method = old_request_method
|
|
239
|
+
vc_test_request.set_header(Rack::RACK_URL_SCHEME, old_request_scheme)
|
|
226
240
|
vc_test_request.path_info = old_request_path_info
|
|
227
241
|
vc_test_request.path_parameters = old_request_path_parameters
|
|
228
242
|
vc_test_request.set_header("action_dispatch.request.query_parameters", old_request_query_parameters)
|
data/lib/view_component.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "action_view"
|
|
4
4
|
require "active_support/dependencies/autoload"
|
|
5
|
+
require "view_component/version"
|
|
5
6
|
|
|
6
7
|
module ViewComponent
|
|
7
8
|
extend ActiveSupport::Autoload
|
|
@@ -16,7 +17,7 @@ module ViewComponent
|
|
|
16
17
|
autoload :Preview
|
|
17
18
|
autoload :Translatable
|
|
18
19
|
|
|
19
|
-
if Rails.env.test?
|
|
20
|
+
if defined?(Rails.env) && Rails.env.test?
|
|
20
21
|
autoload :TestHelpers
|
|
21
22
|
autoload :SystemSpecHelpers
|
|
22
23
|
autoload :SystemTestHelpers
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: view_component
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0
|
|
4
|
+
version: 4.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ViewComponent Team
|
|
@@ -16,9 +16,6 @@ dependencies:
|
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: 7.1.0
|
|
19
|
-
- - "<"
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version: '8.1'
|
|
22
19
|
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -26,9 +23,20 @@ dependencies:
|
|
|
26
23
|
- - ">="
|
|
27
24
|
- !ruby/object:Gem::Version
|
|
28
25
|
version: 7.1.0
|
|
29
|
-
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: actionview
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
30
31
|
- !ruby/object:Gem::Version
|
|
31
|
-
version:
|
|
32
|
+
version: 7.1.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 7.1.0
|
|
32
40
|
- !ruby/object:Gem::Dependency
|
|
33
41
|
name: concurrent-ruby
|
|
34
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -127,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
127
135
|
- !ruby/object:Gem::Version
|
|
128
136
|
version: '0'
|
|
129
137
|
requirements: []
|
|
130
|
-
rubygems_version:
|
|
138
|
+
rubygems_version: 4.0.10
|
|
131
139
|
specification_version: 4
|
|
132
140
|
summary: A framework for building reusable, testable & encapsulated view components
|
|
133
141
|
in Ruby on Rails.
|