view_component 2.14.1 → 2.18.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 +38 -0
- data/README.md +78 -9
- data/app/controllers/view_components_controller.rb +36 -4
- data/lib/rails/generators/erb/component_generator.rb +10 -1
- data/lib/rails/generators/haml/component_generator.rb +10 -1
- data/lib/rails/generators/slim/component_generator.rb +10 -1
- data/lib/view_component.rb +1 -0
- data/lib/view_component/base.rb +6 -3
- data/lib/view_component/engine.rb +2 -2
- data/lib/view_component/preview.rb +30 -1
- data/lib/view_component/preview_template_error.rb +6 -0
- data/lib/view_component/previewable.rb +8 -0
- data/lib/view_component/slotable.rb +1 -1
- data/lib/view_component/version.rb +2 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6fcbca08ed9ca2f6cf62a7ad154dc297ba4606a62faf0aebeeaa544c2c76a663
|
4
|
+
data.tar.gz: 677f442dbcf86d4ca7cfbf4d3ad71a8cb92756ddfeb85afb3b973bd1238a56b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd47863117cc291707ccee9b3bed69daeea0dd432cead045f6d8211ad201bbec34a23132836815751f9a5df64ab92fd3724dc3bf61e03282741d3d468e7c1faa
|
7
|
+
data.tar.gz: 150ebb993d9cdca790ffa437540cb454bea5021350a5a5f96b7596cb522b552a8507c5456e3353b6e2c7ee2df6edfb5eb5b92815f81c38996cb47c5e7351c324
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,43 @@
|
|
1
1
|
# master
|
2
2
|
|
3
|
+
# 2.18.0
|
4
|
+
|
5
|
+
* Fix auto-loading of previews (changes no longer require a server restart)
|
6
|
+
|
7
|
+
*Matt Brictson*
|
8
|
+
|
9
|
+
* Add `default_preview_layout` configuration option to load custom app/views/layouts.
|
10
|
+
|
11
|
+
*Jared White, Juan Manuel Ramallo*
|
12
|
+
|
13
|
+
* Calculate virtual_path once for all instances of a component class to improve performance.
|
14
|
+
|
15
|
+
*Brad Parker*
|
16
|
+
|
17
|
+
# 2.17.1
|
18
|
+
|
19
|
+
* Fix bug where rendering Slot with empty block resulted in error.
|
20
|
+
|
21
|
+
*Joel Hawksley*
|
22
|
+
|
23
|
+
# 2.17.0
|
24
|
+
|
25
|
+
* Slots return stripped HTML, removing leading and trailing whitespace.
|
26
|
+
|
27
|
+
*Jason Long, Joel Hawksley*
|
28
|
+
|
29
|
+
# 2.16.0
|
30
|
+
|
31
|
+
* Add `--sidecar` option to the erb, haml and slim generators. Places the generated template in the sidecar directory.
|
32
|
+
|
33
|
+
*Michael van Rooijen*
|
34
|
+
|
35
|
+
# 2.15.0
|
36
|
+
|
37
|
+
* Add support for templates as ViewComponent::Preview examples.
|
38
|
+
|
39
|
+
*Juan Manuel Ramallo
|
40
|
+
|
3
41
|
# 2.14.1
|
4
42
|
|
5
43
|
* Allow using `render_inline` in test when the render monkey patch is disabled with `config.view_component.render_monkey_patch_enabled = false` in versions of Rails < 6.1.
|
data/README.md
CHANGED
@@ -341,15 +341,25 @@ As an alternative, views and other assets can be placed in a sidecar directory w
|
|
341
341
|
```
|
342
342
|
app/components
|
343
343
|
├── ...
|
344
|
-
├──
|
345
|
-
├──
|
346
|
-
| ├──
|
347
|
-
| ├──
|
348
|
-
| └──
|
344
|
+
├── example_component.rb
|
345
|
+
├── example_component
|
346
|
+
| ├── example_component.css
|
347
|
+
| ├── example_component.html.erb
|
348
|
+
| └── example_component.js
|
349
349
|
├── ...
|
350
350
|
|
351
351
|
```
|
352
352
|
|
353
|
+
To generate a component with a sidecar directory, use the `--sidecar` flag:
|
354
|
+
|
355
|
+
```
|
356
|
+
bin/rails generate component Example title content --sidecar
|
357
|
+
invoke test_unit
|
358
|
+
create test/components/example_component_test.rb
|
359
|
+
create app/components/example_component.rb
|
360
|
+
create app/components/example_component/example_component.html.erb
|
361
|
+
```
|
362
|
+
|
353
363
|
### Conditional Rendering
|
354
364
|
|
355
365
|
Components can implement a `#render?` method to be called after initialization to determine if the component should render.
|
@@ -664,6 +674,14 @@ class TestComponentPreview < ViewComponent::Preview
|
|
664
674
|
end
|
665
675
|
```
|
666
676
|
|
677
|
+
You can also set a custom layout to be used by default for previews as well as the preview index pages via the `default_preview_layout` configuration option:
|
678
|
+
|
679
|
+
`config/application.rb`
|
680
|
+
```ruby
|
681
|
+
# Set the default layout to app/views/layouts/component_preview.html.erb
|
682
|
+
config.default_preview_layout = "component_preview"
|
683
|
+
```
|
684
|
+
|
667
685
|
Preview classes live in `test/components/previews`, which can be configured using the `preview_paths` option:
|
668
686
|
|
669
687
|
`config/application.rb`
|
@@ -680,6 +698,57 @@ config.view_component.preview_route = "/previews"
|
|
680
698
|
|
681
699
|
This example will make the previews available from <http://localhost:3000/previews>.
|
682
700
|
|
701
|
+
#### Preview templates
|
702
|
+
|
703
|
+
Given a preview `test/components/previews/cell_component_preview.rb`, template files can be defined at `test/components/previews/cell_component_preview/`:
|
704
|
+
|
705
|
+
`test/components/previews/cell_component_preview.rb`
|
706
|
+
```ruby
|
707
|
+
class CellComponentPreview < ViewComponent::Preview
|
708
|
+
def default
|
709
|
+
end
|
710
|
+
end
|
711
|
+
```
|
712
|
+
|
713
|
+
`test/components/previews/cell_component_preview/default.html.erb`
|
714
|
+
```erb
|
715
|
+
<table class="table">
|
716
|
+
<tbody>
|
717
|
+
<tr>
|
718
|
+
<%= render CellComponent.new %>
|
719
|
+
</tr>
|
720
|
+
</tbody>
|
721
|
+
</div>
|
722
|
+
```
|
723
|
+
|
724
|
+
To use a different location for preview templates, pass the `template` argument:
|
725
|
+
(the path should be relative to `config.view_component.preview_path`):
|
726
|
+
|
727
|
+
`test/components/previews/cell_component_preview.rb`
|
728
|
+
```ruby
|
729
|
+
class CellComponentPreview < ViewComponent::Preview
|
730
|
+
def default
|
731
|
+
render_with_template(template: 'custom_cell_component_preview/my_preview_template')
|
732
|
+
end
|
733
|
+
end
|
734
|
+
```
|
735
|
+
|
736
|
+
Values from `params` can be accessed through `locals`:
|
737
|
+
|
738
|
+
`test/components/previews/cell_component_preview.rb`
|
739
|
+
```ruby
|
740
|
+
class CellComponentPreview < ViewComponent::Preview
|
741
|
+
def default(title: "Default title", subtitle: "A subtitle")
|
742
|
+
render_with_template(locals: {
|
743
|
+
title: title,
|
744
|
+
subtitle: subtitle
|
745
|
+
})
|
746
|
+
end
|
747
|
+
end
|
748
|
+
```
|
749
|
+
|
750
|
+
Which enables passing in a value with <http://localhost:3000/rails/components/cell_component/default?title=Custom+title&subtitle=Another+subtitle>.
|
751
|
+
|
683
752
|
#### Configuring TestController
|
684
753
|
|
685
754
|
Component tests and previews assume the existence of an `ApplicationController` class, which be can be configured using the `test_controller` option:
|
@@ -929,10 +998,10 @@ ViewComponent is built by:
|
|
929
998
|
|@maxbeizer|@franco|@tbroad-ramsey|@jensljungblad|@bbugh|
|
930
999
|
|Nashville, TN|Switzerland|Spring Hill, TN|New York, NY|Austin, TX|
|
931
1000
|
|
932
|
-
|<img src="https://avatars.githubusercontent.com/johannesengl?s=256" alt="johannesengl" width="128" />|<img src="https://avatars.githubusercontent.com/czj?s=256" alt="czj" width="128" />|
|
933
|
-
|
934
|
-
|@johannesengl|@czj|
|
935
|
-
|Berlin, Germany|Paris, France|
|
1001
|
+
|<img src="https://avatars.githubusercontent.com/johannesengl?s=256" alt="johannesengl" width="128" />|<img src="https://avatars.githubusercontent.com/czj?s=256" alt="czj" width="128" />|<img src="https://avatars.githubusercontent.com/mrrooijen?s=256" alt="mrrooijen" width="128" />|<img src="https://avatars.githubusercontent.com/bradparker?s=256" alt="bradparker" width="128" />|<img src="https://avatars.githubusercontent.com/mattbrictson?s=256" alt="mattbrictson" width="128" />|
|
1002
|
+
|:---:|:---:|:---:|:---:|:---:|
|
1003
|
+
|@johannesengl|@czj|@mrrooijen|@bradparker|@mattbrictson|
|
1004
|
+
|Berlin, Germany|Paris, France|The Netherlands|Brisbane, Australia|San Francisco|
|
936
1005
|
|
937
1006
|
## License
|
938
1007
|
|
@@ -16,24 +16,34 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
|
|
16
16
|
def index
|
17
17
|
@previews = ViewComponent::Preview.all
|
18
18
|
@page_title = "Component Previews"
|
19
|
+
render "view_components/index", **determine_layout
|
19
20
|
end
|
20
21
|
|
21
22
|
def previews
|
22
23
|
if params[:path] == @preview.preview_name
|
23
24
|
@page_title = "Component Previews for #{@preview.preview_name}"
|
24
|
-
render "view_components/previews"
|
25
|
+
render "view_components/previews", **determine_layout
|
25
26
|
else
|
26
27
|
prepend_application_view_paths
|
28
|
+
prepend_preview_examples_view_path
|
27
29
|
@example_name = File.basename(params[:path])
|
28
30
|
@render_args = @preview.render_args(@example_name, params: params.permit!)
|
29
|
-
layout = @render_args[:layout]
|
30
|
-
|
31
|
-
|
31
|
+
layout = determine_layout(@render_args[:layout], prepend_views: false)[:layout]
|
32
|
+
template = @render_args[:template]
|
33
|
+
locals = @render_args[:locals]
|
34
|
+
opts = {}
|
35
|
+
opts[:layout] = layout if layout.present? || layout == false
|
36
|
+
opts[:locals] = locals if locals.present?
|
37
|
+
render template, opts # rubocop:disable GitHub/RailsControllerRenderLiteral
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
35
41
|
private
|
36
42
|
|
43
|
+
def default_preview_layout # :doc:
|
44
|
+
ViewComponent::Base.default_preview_layout
|
45
|
+
end
|
46
|
+
|
37
47
|
def show_previews? # :doc:
|
38
48
|
ViewComponent::Base.show_previews
|
39
49
|
end
|
@@ -56,7 +66,29 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
|
|
56
66
|
end
|
57
67
|
end
|
58
68
|
|
69
|
+
# Returns either {} or {layout: value} depending on configuration
|
70
|
+
def determine_layout(layout_override = nil, prepend_views: true)
|
71
|
+
return {} unless defined?(Rails.root)
|
72
|
+
|
73
|
+
layout_declaration = {}
|
74
|
+
|
75
|
+
if !layout_override.nil?
|
76
|
+
# Allow component-level override, even if false (thus no layout rendered)
|
77
|
+
layout_declaration[:layout] = layout_override
|
78
|
+
elsif default_preview_layout.present?
|
79
|
+
layout_declaration[:layout] = default_preview_layout
|
80
|
+
end
|
81
|
+
|
82
|
+
prepend_application_view_paths if layout_declaration[:layout].present? && prepend_views
|
83
|
+
|
84
|
+
layout_declaration
|
85
|
+
end
|
86
|
+
|
59
87
|
def prepend_application_view_paths
|
60
88
|
prepend_view_path Rails.root.join("app/views") if defined?(Rails.root)
|
61
89
|
end
|
90
|
+
|
91
|
+
def prepend_preview_examples_view_path
|
92
|
+
prepend_view_path(ViewComponent::Base.preview_paths)
|
93
|
+
end
|
62
94
|
end
|
@@ -6,13 +6,22 @@ module Erb
|
|
6
6
|
module Generators
|
7
7
|
class ComponentGenerator < Base
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
9
|
+
class_option :sidecar, type: :boolean, default: false
|
9
10
|
|
10
11
|
def copy_view_file
|
11
|
-
template "component.html.erb",
|
12
|
+
template "component.html.erb", destination
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
15
16
|
|
17
|
+
def destination
|
18
|
+
if options["sidecar"]
|
19
|
+
File.join("app/components", class_path, "#{file_name}_component", "#{file_name}_component.html.erb")
|
20
|
+
else
|
21
|
+
File.join("app/components", class_path, "#{file_name}_component.html.erb")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
def file_name
|
17
26
|
@_file_name ||= super.sub(/_component\z/i, "")
|
18
27
|
end
|
@@ -6,13 +6,22 @@ module Haml
|
|
6
6
|
module Generators
|
7
7
|
class ComponentGenerator < Erb::Generators::ComponentGenerator
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
9
|
+
class_option :sidecar, type: :boolean, default: false
|
9
10
|
|
10
11
|
def copy_view_file
|
11
|
-
template "component.html.haml",
|
12
|
+
template "component.html.haml", destination
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
15
16
|
|
17
|
+
def destination
|
18
|
+
if options["sidecar"]
|
19
|
+
File.join("app/components", class_path, "#{file_name}_component", "#{file_name}_component.html.haml")
|
20
|
+
else
|
21
|
+
File.join("app/components", class_path, "#{file_name}_component.html.haml")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
def file_name
|
17
26
|
@_file_name ||= super.sub(/_component\z/i, "")
|
18
27
|
end
|
@@ -6,13 +6,22 @@ module Slim
|
|
6
6
|
module Generators
|
7
7
|
class ComponentGenerator < Erb::Generators::ComponentGenerator
|
8
8
|
source_root File.expand_path("templates", __dir__)
|
9
|
+
class_option :sidecar, type: :boolean, default: false
|
9
10
|
|
10
11
|
def copy_view_file
|
11
|
-
template "component.html.slim",
|
12
|
+
template "component.html.slim", destination
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
15
16
|
|
17
|
+
def destination
|
18
|
+
if options["sidecar"]
|
19
|
+
File.join("app/components", class_path, "#{file_name}_component", "#{file_name}_component.html.slim")
|
20
|
+
else
|
21
|
+
File.join("app/components", class_path, "#{file_name}_component.html.slim")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
def file_name
|
17
26
|
@_file_name ||= super.sub(/_component\z/i, "")
|
18
27
|
end
|
data/lib/view_component.rb
CHANGED
data/lib/view_component/base.rb
CHANGED
@@ -116,9 +116,9 @@ module ViewComponent
|
|
116
116
|
@helpers ||= controller.view_context
|
117
117
|
end
|
118
118
|
|
119
|
-
#
|
119
|
+
# Exposes .virutal_path as an instance method
|
120
120
|
def virtual_path
|
121
|
-
self.class.
|
121
|
+
self.class.virtual_path
|
122
122
|
end
|
123
123
|
|
124
124
|
# For caching, such as #cache_if
|
@@ -166,7 +166,7 @@ module ViewComponent
|
|
166
166
|
mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
|
167
167
|
|
168
168
|
class << self
|
169
|
-
attr_accessor :source_location
|
169
|
+
attr_accessor :source_location, :virtual_path
|
170
170
|
|
171
171
|
# Render a component collection.
|
172
172
|
def with_collection(collection, **args)
|
@@ -189,6 +189,9 @@ module ViewComponent
|
|
189
189
|
# has been re-defined by the consuming application, likely in ApplicationComponent.
|
190
190
|
child.source_location = caller_locations(1, 10).reject { |l| l.label == "inherited" }[0].absolute_path
|
191
191
|
|
192
|
+
# Removes the first part of the path and the extension.
|
193
|
+
child.virtual_path = child.source_location.gsub(%r{(.*app/components)|(\.rb)}, "")
|
194
|
+
|
192
195
|
# Clone slot configuration into child class
|
193
196
|
# see #test_slots_pollution
|
194
197
|
child.slots = self.slots.clone
|
@@ -34,8 +34,8 @@ module ViewComponent
|
|
34
34
|
initializer "view_component.set_autoload_paths" do |app|
|
35
35
|
options = app.config.view_component
|
36
36
|
|
37
|
-
if options.show_previews && options.
|
38
|
-
ActiveSupport::Dependencies.autoload_paths
|
37
|
+
if options.show_previews && !options.preview_paths.empty?
|
38
|
+
ActiveSupport::Dependencies.autoload_paths.concat(options.preview_paths)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -8,7 +8,20 @@ module ViewComponent # :nodoc:
|
|
8
8
|
extend ActiveSupport::DescendantsTracker
|
9
9
|
|
10
10
|
def render(component, **args, &block)
|
11
|
-
{
|
11
|
+
{
|
12
|
+
args: args,
|
13
|
+
block: block,
|
14
|
+
component: component,
|
15
|
+
locals: {},
|
16
|
+
template: "view_components/preview",
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_with_template(template: nil, locals: {})
|
21
|
+
{
|
22
|
+
template: template,
|
23
|
+
locals: locals
|
24
|
+
}
|
12
25
|
end
|
13
26
|
|
14
27
|
class << self
|
@@ -23,6 +36,8 @@ module ViewComponent # :nodoc:
|
|
23
36
|
example_params_names = instance_method(example).parameters.map(&:last)
|
24
37
|
provided_params = params.slice(*example_params_names).to_h.symbolize_keys
|
25
38
|
result = provided_params.empty? ? new.public_send(example) : new.public_send(example, **provided_params)
|
39
|
+
result ||= {}
|
40
|
+
result[:template] = preview_example_template_path(example) if result[:template].nil?
|
26
41
|
@layout = nil unless defined?(@layout)
|
27
42
|
result.merge(layout: @layout)
|
28
43
|
end
|
@@ -62,6 +77,20 @@ module ViewComponent # :nodoc:
|
|
62
77
|
@layout = layout_name
|
63
78
|
end
|
64
79
|
|
80
|
+
# Returns the relative path (from preview_path) to the preview example template if the template exists
|
81
|
+
def preview_example_template_path(example)
|
82
|
+
preview_path = Array(preview_paths).detect do |preview_path|
|
83
|
+
Dir["#{preview_path}/#{preview_name}_preview/#{example}.html.*"].first
|
84
|
+
end
|
85
|
+
|
86
|
+
if preview_path.nil?
|
87
|
+
raise PreviewTemplateError, "preview template for example #{example} does not exist"
|
88
|
+
end
|
89
|
+
|
90
|
+
path = Dir["#{preview_path}/#{preview_name}_preview/#{example}.html.*"].first
|
91
|
+
Pathname.new(path).relative_path_from(Pathname.new(preview_path)).to_s
|
92
|
+
end
|
93
|
+
|
65
94
|
private
|
66
95
|
|
67
96
|
def load_previews
|
@@ -7,6 +7,14 @@ module ViewComponent # :nodoc:
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
included do
|
10
|
+
# Set a custom default preview layout through app configuration:
|
11
|
+
#
|
12
|
+
# config.view_component.default_preview_layout = "component_preview"
|
13
|
+
#
|
14
|
+
# This affects preview index pages as well as individual component previews
|
15
|
+
#
|
16
|
+
mattr_accessor :default_preview_layout, instance_writer: false
|
17
|
+
|
10
18
|
# Set the location of component previews through app configuration:
|
11
19
|
#
|
12
20
|
# config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
|
@@ -98,7 +98,7 @@ module ViewComponent
|
|
98
98
|
slot_instance = args.present? ? slot_class.new(**args) : slot_class.new
|
99
99
|
|
100
100
|
# Capture block and assign to slot_instance#content
|
101
|
-
slot_instance.content = view_context.capture(&block) if block_given?
|
101
|
+
slot_instance.content = view_context.capture(&block).to_s.strip.html_safe if block_given?
|
102
102
|
|
103
103
|
if slot[:collection]
|
104
104
|
# Initialize instance variable as an empty array
|
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.18.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: 2020-07-
|
11
|
+
date: 2020-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -170,7 +170,7 @@ dependencies:
|
|
170
170
|
- - "~>"
|
171
171
|
- !ruby/object:Gem::Version
|
172
172
|
version: '0.1'
|
173
|
-
description:
|
173
|
+
description:
|
174
174
|
email:
|
175
175
|
- opensource+view_component@github.com
|
176
176
|
executables: []
|
@@ -203,6 +203,7 @@ files:
|
|
203
203
|
- lib/view_component/compile_cache.rb
|
204
204
|
- lib/view_component/engine.rb
|
205
205
|
- lib/view_component/preview.rb
|
206
|
+
- lib/view_component/preview_template_error.rb
|
206
207
|
- lib/view_component/previewable.rb
|
207
208
|
- lib/view_component/render_component_helper.rb
|
208
209
|
- lib/view_component/render_component_to_string_helper.rb
|
@@ -221,7 +222,7 @@ licenses:
|
|
221
222
|
- MIT
|
222
223
|
metadata:
|
223
224
|
allowed_push_host: https://rubygems.org
|
224
|
-
post_install_message:
|
225
|
+
post_install_message:
|
225
226
|
rdoc_options: []
|
226
227
|
require_paths:
|
227
228
|
- lib
|
@@ -237,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
238
|
version: '0'
|
238
239
|
requirements: []
|
239
240
|
rubygems_version: 3.1.2
|
240
|
-
signing_key:
|
241
|
+
signing_key:
|
241
242
|
specification_version: 4
|
242
243
|
summary: View components for Rails
|
243
244
|
test_files: []
|