view_component 2.13.0 → 2.17.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3950532a26d2d6d1ddcf412383bfd9cde269c1f69c3d6f7f03dd4e51e7d638e2
4
- data.tar.gz: ee2524ef62b335376287f30709e62f2d39a71e43c0f5ec9853db8142b6c8fb3c
3
+ metadata.gz: 63cae604f99ce706878da0fb00ddfdde223bbb1431e33e3096448e4e65b569af
4
+ data.tar.gz: 2017fe3d3b8b2979fb5854fbb40cecc5b4c760953377a8e45ceccfbcc1eb01c3
5
5
  SHA512:
6
- metadata.gz: c4cc6925445d3486e4c9a6ef915254cf3f28d973ad6a2876fca4fe3435b19ac273f18e89432622eaa38c8bba22ab9e9cafa07e417299dab8537848742175d1c8
7
- data.tar.gz: 66d2a44a74a07e78f694adc4790218ee7a9d729e8cd8bb9546d154669a79d5abaa20e7d0bffa0801dfc276ef539b93d5a13dd2b4d3d3093cd8d806972d2dac81
6
+ metadata.gz: ce31c6c2f4668c683ce037c9dc1e2de1e462e3ac5301176a70bf5ab4d7d10cafe33d611f00fd55e13f707b6c19e1731c1c18978ba5e0bc05c35c5986159ac5ef
7
+ data.tar.gz: 0fde2e678e6d671e77812f197180bcef3e90ac1e87615dede2890359bb9a594a490edbe43eee43ed60e568826e616cf16e59392427f952c35497dc3516e16bc3
@@ -1,5 +1,50 @@
1
1
  # master
2
2
 
3
+ # 2.17.0
4
+
5
+ * Slots return stripped HTML, removing leading and trailing whitespace.
6
+
7
+ *Jason Long, Joel Hawksley*
8
+
9
+ # 2.16.0
10
+
11
+ * Add `--sidecar` option to the erb, haml and slim generators. Places the generated template in the sidecar directory.
12
+
13
+ *Michael van Rooijen*
14
+
15
+ # 2.15.0
16
+
17
+ * Add support for templates as ViewComponent::Preview examples.
18
+
19
+ *Juan Manuel Ramallo
20
+
21
+ # 2.14.1
22
+
23
+ * 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.
24
+
25
+ *Clément Joubert*
26
+
27
+ * Fix kwargs warnings in slotable.
28
+
29
+ Fixes:
30
+
31
+ ```
32
+ view_component/lib/view_component/slotable.rb:98: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
33
+ view_component/test/app/components/slots_component.rb:18: warning: The called method `initialize' is defined here
34
+ ```
35
+
36
+ *Eileen M. Uchitelle*
37
+
38
+ # 2.14.0
39
+
40
+ * Add `config.preview_paths` to support multiple locations of component preview files. Deprecate `config.preview_path`.
41
+
42
+ *Tomas Celizna*
43
+
44
+ * Only print warning about a missing capybara dependency if the `DEBUG` environment variable is set.
45
+
46
+ *Richard Macklin*
47
+
3
48
  # 2.13.0
4
49
 
5
50
  * Add the ability to disable the render monkey patch with `config.view_component.render_monkey_patch_enabled`. In versions of Rails < 6.1, add `render_component` and `render_component_to_string` methods which can be used for rendering components instead of `render`.
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
- ├── test_component.rb
345
- ├── test_component
346
- | ├── test_component.css
347
- | ├── test_component.html.erb
348
- | └── test_component.js
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,11 +674,11 @@ class TestComponentPreview < ViewComponent::Preview
664
674
  end
665
675
  ```
666
676
 
667
- Preview classes live in `test/components/previews`, which can be configured using the `preview_path` option:
677
+ Preview classes live in `test/components/previews`, which can be configured using the `preview_paths` option:
668
678
 
669
679
  `config/application.rb`
670
680
  ```ruby
671
- config.view_component.preview_path = "#{Rails.root}/lib/component_previews"
681
+ config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
672
682
  ```
673
683
 
674
684
  Previews are served from <http://localhost:3000/rails/view_components> by default. To use a different endpoint, set the `preview_route` option:
@@ -680,6 +690,57 @@ config.view_component.preview_route = "/previews"
680
690
 
681
691
  This example will make the previews available from <http://localhost:3000/previews>.
682
692
 
693
+ #### Preview templates
694
+
695
+ Given a preview `test/components/previews/cell_component_preview.rb`, template files can be defined at `test/components/previews/cell_component_preview/`:
696
+
697
+ `test/components/previews/cell_component_preview.rb`
698
+ ```ruby
699
+ class CellComponentPreview < ViewComponent::Preview
700
+ def default
701
+ end
702
+ end
703
+ ```
704
+
705
+ `test/components/previews/cell_component_preview/default.html.erb`
706
+ ```erb
707
+ <table class="table">
708
+ <tbody>
709
+ <tr>
710
+ <%= render CellComponent.new %>
711
+ </tr>
712
+ </tbody>
713
+ </div>
714
+ ```
715
+
716
+ To use a different location for preview templates, pass the `template` argument:
717
+ (the path should be relative to `config.view_component.preview_path`):
718
+
719
+ `test/components/previews/cell_component_preview.rb`
720
+ ```ruby
721
+ class CellComponentPreview < ViewComponent::Preview
722
+ def default
723
+ render_with_template(template: 'custom_cell_component_preview/my_preview_template')
724
+ end
725
+ end
726
+ ```
727
+
728
+ Values from `params` can be accessed through `locals`:
729
+
730
+ `test/components/previews/cell_component_preview.rb`
731
+ ```ruby
732
+ class CellComponentPreview < ViewComponent::Preview
733
+ def default(title: "Default title", subtitle: "A subtitle")
734
+ render_with_template(locals: {
735
+ title: title,
736
+ subtitle: subtitle
737
+ })
738
+ end
739
+ end
740
+ ```
741
+
742
+ Which enables passing in a value with <http://localhost:3000/rails/components/cell_component/default?title=Custom+title&subtitle=Another+subtitle>.
743
+
683
744
  #### Configuring TestController
684
745
 
685
746
  Component tests and previews assume the existence of an `ApplicationController` class, which be can be configured using the `test_controller` option:
@@ -708,7 +769,7 @@ To use component previews:
708
769
 
709
770
  `config/application.rb`
710
771
  ```ruby
711
- config.view_component.preview_path = "#{Rails.root}/spec/components/previews"
772
+ config.view_component.preview_paths << "#{Rails.root}/spec/components/previews"
712
773
  ```
713
774
 
714
775
  ### Disabling the render monkey patch (Rails < 6.1)
@@ -929,10 +990,10 @@ ViewComponent is built by:
929
990
  |@maxbeizer|@franco|@tbroad-ramsey|@jensljungblad|@bbugh|
930
991
  |Nashville, TN|Switzerland|Spring Hill, TN|New York, NY|Austin, TX|
931
992
 
932
- |<img src="https://avatars.githubusercontent.com/johannesengl?s=256" alt="johannesengl" width="128" />|
933
- |:---:|
934
- |@johannesengl|
935
- |Berlin, Germany|
993
+ |<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" />|
994
+ |:---:|:---:|:---:|
995
+ |@johannesengl|@czj|@mrrooijen|
996
+ |Berlin, Germany|Paris, France|The Netherlands|
936
997
 
937
998
  ## License
938
999
 
@@ -24,11 +24,16 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
24
24
  render "view_components/previews"
25
25
  else
26
26
  prepend_application_view_paths
27
+ prepend_preview_examples_view_path
27
28
  @example_name = File.basename(params[:path])
28
29
  @render_args = @preview.render_args(@example_name, params: params.permit!)
29
30
  layout = @render_args[:layout]
30
- opts = layout.nil? ? {} : { layout: layout }
31
- render "view_components/preview", opts
31
+ template = @render_args[:template]
32
+ locals = @render_args[:locals]
33
+ opts = {}
34
+ opts[:layout] = layout if layout.present?
35
+ opts[:locals] = locals if locals.present?
36
+ render template, opts # rubocop:disable GitHub/RailsControllerRenderLiteral
32
37
  end
33
38
  end
34
39
 
@@ -59,4 +64,8 @@ class ViewComponentsController < Rails::ApplicationController # :nodoc:
59
64
  def prepend_application_view_paths
60
65
  prepend_view_path Rails.root.join("app/views") if defined?(Rails.root)
61
66
  end
67
+
68
+ def prepend_preview_examples_view_path
69
+ prepend_view_path(ViewComponent::Base.preview_paths)
70
+ end
62
71
  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", File.join("app/components", class_path, "#{file_name}_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", File.join("app/components", class_path, "#{file_name}_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", File.join("app/components", class_path, "#{file_name}_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
@@ -7,6 +7,7 @@ module ViewComponent
7
7
 
8
8
  autoload :Base
9
9
  autoload :Preview
10
+ autoload :PreviewTemplateError
10
11
  autoload :TestHelpers
11
12
  autoload :TestCase
12
13
  autoload :TemplateError
@@ -6,6 +6,7 @@ require "view_component"
6
6
  module ViewComponent
7
7
  class Engine < Rails::Engine # :nodoc:
8
8
  config.view_component = ActiveSupport::OrderedOptions.new
9
+ config.view_component.preview_paths ||= []
9
10
 
10
11
  initializer "view_component.set_configs" do |app|
11
12
  options = app.config.view_component
@@ -15,7 +16,14 @@ module ViewComponent
15
16
  options.preview_route ||= ViewComponent::Base.preview_route
16
17
 
17
18
  if options.show_previews
18
- options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/components/previews" : nil
19
+ options.preview_paths << "#{Rails.root}/test/components/previews" if defined?(Rails.root)
20
+
21
+ if options.preview_path.present?
22
+ ActiveSupport::Deprecation.warn(
23
+ "`preview_path` will be removed in v3.0.0. Use `preview_paths` instead."
24
+ )
25
+ options.preview_paths << options.preview_path
26
+ end
19
27
  end
20
28
 
21
29
  ActiveSupport.on_load(:view_component) do
@@ -8,7 +8,20 @@ module ViewComponent # :nodoc:
8
8
  extend ActiveSupport::DescendantsTracker
9
9
 
10
10
  def render(component, **args, &block)
11
- { component: component, args: args, block: block }
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,16 +77,30 @@ 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
68
- if preview_path
97
+ Array(preview_paths).each do |preview_path|
69
98
  Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file| require_dependency file }
70
99
  end
71
100
  end
72
101
 
73
- def preview_path
74
- Base.preview_path
102
+ def preview_paths
103
+ Base.preview_paths
75
104
  end
76
105
 
77
106
  def show_previews
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ class PreviewTemplateError < StandardError
5
+ end
6
+ end
@@ -9,8 +9,11 @@ module ViewComponent # :nodoc:
9
9
  included do
10
10
  # Set the location of component previews through app configuration:
11
11
  #
12
- # config.view_component.preview_path = "#{Rails.root}/lib/component_previews"
12
+ # config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
13
13
  #
14
+ mattr_accessor :preview_paths, instance_writer: false
15
+
16
+ # TODO: deprecated, remove in v3.0.0
14
17
  mattr_accessor :preview_path, instance_writer: false
15
18
 
16
19
  # Enable or disable component previews through app configuration:
@@ -95,10 +95,10 @@ module ViewComponent
95
95
  end
96
96
 
97
97
  # Instantiate Slot class, accommodating Slots that don't accept arguments
98
- slot_instance = args.present? ? slot_class.new(args) : slot_class.new
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).strip.html_safe if block_given?
102
102
 
103
103
  if slot[:collection]
104
104
  # Initialize instance variable as an empty array
@@ -14,13 +14,18 @@ module ViewComponent
14
14
  assert_no_selector("body")
15
15
  end
16
16
  rescue LoadError
17
- warn "WARNING in `ViewComponent::TestHelpers`: You must add `capybara` to your Gemfile to use Capybara assertions."
17
+ warn "WARNING in `ViewComponent::TestHelpers`: You must add `capybara` to your Gemfile to use Capybara assertions." if ENV["DEBUG"]
18
18
  end
19
19
 
20
20
  attr_reader :rendered_component
21
21
 
22
22
  def render_inline(component, **args, &block)
23
- @rendered_component = controller.view_context.render(component, args, &block)
23
+ @rendered_component =
24
+ if Rails.version.to_f >= 6.1
25
+ controller.view_context.render(component, args, &block)
26
+ else
27
+ controller.view_context.render_component(component, &block)
28
+ end
24
29
 
25
30
  Nokogiri::HTML.fragment(@rendered_component)
26
31
  end
@@ -3,7 +3,7 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 13
6
+ MINOR = 17
7
7
  PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
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.13.0
4
+ version: 2.17.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: 2020-07-02 00:00:00.000000000 Z
11
+ date: 2020-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -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