nice_partials 0.1.4 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3275a33c9f1de9e8267042ab36b485297451804bb1c704082576890d800a20cd
4
- data.tar.gz: 7b55dd85d2d291eb411b564819c602e039dc412ec8cbb82df7b58f8472d062e4
3
+ metadata.gz: dc6e751d8a192aa46fe3ee5401fe924c4dc1f5c6c3c7fabe8c22f468ff3a344c
4
+ data.tar.gz: de5a48e0d84e96a40b85293933af3dadd4977e6dfa2dd06522c85e1a6fbd0576
5
5
  SHA512:
6
- metadata.gz: ef49218a25d20bb8b0446b5b0dd975fb173191ea1e236e9dfa6a700fec717ef9b24f8f06fcc114b4e1e731ddf62aed143cd225193cd6ebc64acb4fd06edb0e3b
7
- data.tar.gz: 52e0f030102269996e35132ad2ff16bcb94100faca76787b13059a31450c0d65456961b71bf69d2610f46bb8f48a9b410f4a01090c96f946d2d5b1ec6ece9b8c
6
+ metadata.gz: 5f56fb3b92520c7a818b6ced0225def224a265a9ca2400d70e283300df8eef3fc266c6b65fa2e4e24856d7eccb6c0b39bdadf056bdec76c499be68fd9d90a982
7
+ data.tar.gz: 6a58763a68c0aa76cfee32432c730166cd96a19b2c8a1e8428c26260663ff706fc4883af07e9b1782da0d7e493ca7f4f8883fde223b75674967acce7a3780bc1
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  Gemfile.lock
2
2
  /pkg
3
+ *~
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ sudo: false
2
2
  language: ruby
3
3
 
4
4
  rvm:
5
+ - 3.1
5
6
  - 3.0
6
7
  - 2.7
7
8
  - 2.6
data/CHANGELOG.md CHANGED
@@ -1,9 +1,63 @@
1
1
  ## CHANGELOG
2
2
 
3
+ * Remove need to insert `<% yield p = np %>` in partials.
4
+
5
+ Nice Partials now automatically captures blocks passed to `render`.
6
+ Instead of `p`, a `partial` method has been added to access the
7
+ current `NicePartials::Partial` object.
8
+
9
+ Here's a script to help update your view code:
10
+
11
+ ```ruby
12
+ files_to_inspect = []
13
+
14
+ Dir["app/views/**/*.html.erb"].each do |path|
15
+ if contents = File.read(path).match(/(<%=? yield\(?.*? = np\)? %>\n+)/m)&.post_match
16
+ files_to_inspect << path if contents.match?(/render.*?do \|/)
17
+
18
+ contents.gsub! /\bp\.(?=yield|helpers|content_for|content_for\?)/, "partial."
19
+ File.write path, contents
20
+ end
21
+ end
22
+
23
+ if files_to_inspect.any?
24
+ puts "These files had render calls with a block parameter and likely require some manual edits:"
25
+ puts files_to_inspect
26
+ else
27
+ puts "No files with render calls with a block parameter found, you're likely all set"
28
+ end
29
+ ```
30
+
31
+ * Support manual `yield`s in partials.
32
+
33
+ Due to the automatic yield support above, support has also been added for manual `yield some_object` calls.
34
+
35
+ Nice Partials automatically appends the `partial` to the yielded arguments, so you can
36
+ change `render … do |some_object|` to `render … do |some_object, partial|`.
37
+
38
+ * Deprecate `p` as the partial object access. Use `partial` instead.
39
+
40
+ * Expose `partial.yield` to access the captured output buffer.
41
+
42
+ Lets you access what a `<%= yield %>` call returned, like this:
43
+
44
+ ```erb
45
+ <%= render "card" do %>
46
+ This is the content of the internal output buffer
47
+ <% end %>
48
+ ```
49
+
50
+ ```erb
51
+ # app/views/cards/_card.html.erb
52
+ # This can be replaced with `partial.yield`.
53
+ <%= yield %> # Will output "This is the content of the internal output buffer"
54
+ ```
55
+
56
+ ### 0.1.7
57
+
3
58
  * Rely on `ActiveSupport.on_load :action_view`
4
59
  * Add support for Ruby 3.0
5
60
 
6
61
  ### 0.1.0
7
62
 
8
63
  * Initial release
9
-
data/README.md CHANGED
@@ -1,34 +1,34 @@
1
1
  # nice_partials [![[version]](https://badge.fury.io/rb/nice_partials.svg)](https://badge.fury.io/rb/nice_partials) [![[travis]](https://travis-ci.org/andrewculver/nice_partials.svg)](https://travis-ci.org/andrewculver/nice_partials)
2
2
 
3
- Nice Partials extends the concept of [`content_for` blocks and `yield`](https://guides.rubyonrails.org/layouts_and_rendering.html#using-the-content-for-method) for those times when a partial needs to provide one or more named "content areas" or "slots". This thin, optional layer of magic helps make traditional Rails view partials an even better fit for extracting components from your views, like so:
3
+ Nice Partials lets [`content_for` and `yield`](https://guides.rubyonrails.org/layouts_and_rendering.html#using-the-content-for-method) calls be partial specific, to provide named "content areas" or "slots". This optional layer of magic helps make traditional Rails view partials a better fit for extracting components from your views, like so:
4
4
 
5
5
  `app/views/components/_card.html.erb`:
6
6
  ```html+erb
7
7
  <div class="card">
8
- <%= p.yield :image %>
8
+ <%= partial.yield :image %>
9
9
  <div class="card-body">
10
10
  <h5 class="card-title"><%= title %></h5>
11
- <% if p.content_for? :body %>
11
+ <% if partial.content_for? :body %>
12
12
  <p class="card-text">
13
- <%= p.yield :body %>
13
+ <%= partial.yield :body %>
14
14
  </p>
15
15
  <% end %>
16
16
  </div>
17
17
  </div>
18
18
  ```
19
19
 
20
- These partials can still be utilized with a standard `render` call, but you can specify how to populate the content areas like so:
20
+ Then you can call `render`, but specify how to populate the content areas:
21
21
 
22
22
  ```html+erb
23
- <%= render 'components/card', title: 'Some Title' do |p| %>
24
- <% p.content_for :body do %>
23
+ <%= render 'components/card', title: 'Some Title' do |partial| %>
24
+ <% partial.content_for :body do %>
25
25
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
26
26
  tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
27
27
  <strong>quis nostrud exercitation ullamco laboris</strong> nisi ut aliquip
28
28
  ex ea commodo consequat.
29
29
  <% end %>
30
30
 
31
- <% p.content_for :image do %>
31
+ <% partial.content_for :image do %>
32
32
  <%= image_tag image_path('example.jpg'), alt: 'An example image' %>
33
33
  <% end %>
34
34
  <% end %>
@@ -50,7 +50,7 @@ Nice Partials is a lightweight and hopefully more Rails-native alternative to [V
50
50
 
51
51
  ## Benefits of Nice Partials
52
52
 
53
- Compared to something more heavy-handed, Nice Partials:
53
+ Nice Partials:
54
54
 
55
55
  - is just regular Rails view partials like you're used to.
56
56
  - reduces the friction when extracting components.
@@ -104,32 +104,46 @@ You only need to use Nice Partials when:
104
104
 
105
105
  - you want to specifically isolate your helper methods for a specific partial.
106
106
 
107
- ### Use Nice Partials in a partial
107
+ ### Using Nice Partials
108
108
 
109
- To invoke nice partials, start your partial file with the following:
109
+ Nice Partials is invoked automatically when you render your partial with a block like so:
110
110
 
111
111
  ```html+erb
112
- <% yield p = np %>
112
+ <%= render 'components/card' do |partial| %>
113
+ <%= partial.content_for :some_section do %>
114
+ Some content!
115
+ <% end %>
116
+ <% end %>
113
117
  ```
114
118
 
115
- Here's what is happening here:
119
+ Now within the partial file itself, you can use `<%= partial.yield :some_section %>` to render whatever content areas you want to be passed into your partial.
116
120
 
117
- - `yield` executes the block we receive when someone uses our partial.
118
- - `np` fetches an instance of the generic class that helps isolate our content buffers and helper methods.
119
- - `p = np` ensures we have a reference to that object in this partial.
120
- - `yield p = np` ensures the developer using this partial also has a reference to that object, so they can define what goes in the various content buffers.
121
+ ### Accessing the content returned from `yield`
121
122
 
122
- (This is, [as far as we know](https://github.com/bullet-train-co/nice_partials/issues/1), the minimum viable invocation.)
123
+ In a regular Rails partial:
123
124
 
124
- Once you've done this at the top of your partial file, you can then use `<%= p.yield :some_section %>` to render whatever content areas you want to be passed into your partial.
125
+ ```html+erb
126
+ <%= render 'components/card' do %>
127
+ Some content!
128
+ Yet more content!
129
+ <% end %>
130
+ ```
125
131
 
132
+ You can access the inner content lines through what's returned from `yield`:
133
+
134
+ ```html+erb
135
+ <%# app/views/components/_card.html.erb %>
136
+ <%= yield %> # => "Some content!\n\nYet more content!"
137
+ ```
138
+
139
+ With Nice Partials, you can call `partial.yield` without arguments and return the same `"Some content!\n\nYet more content!"`.
126
140
 
127
141
  ### Defining and using well isolated helper methods
128
142
 
129
143
  To minimize the amount of pollution in the global helper namespace, you can use the shared context object to define helper methods specifically for your partials _within your partial_ like so:
130
144
 
131
145
  ```html+erb
132
- <% p.helpers do
146
+ <% partial.helpers do
133
147
 
134
148
  # references should be a link if the user can drill down, otherwise just a text label.
135
149
  def reference_to(user)
@@ -147,7 +161,15 @@ end %>
147
161
  Then later in the partial you can use the helper method like so:
148
162
 
149
163
  ```html+erb
150
- <td><%= p.reference_to(user) %></td>
164
+ <td><%= partial.reference_to(user) %></td>
165
+ ```
166
+
167
+ ## Development
168
+
169
+ ### Testing
170
+
171
+ ```sh
172
+ bundle exec rake test
151
173
  ```
152
174
 
153
175
  ## MIT License
data/Rakefile CHANGED
@@ -30,8 +30,8 @@ end
30
30
  # # #
31
31
  # Run specs
32
32
 
33
- desc "#{gemspec.name} | Spec"
34
- task :spec do
35
- sh "for file in spec/*_spec.rb; do ruby $file; done"
33
+ desc "#{gemspec.name} | Test"
34
+ task :test do
35
+ sh "for file in test/{**/,}*_test.rb; do ruby -Ilib:test $file; done"
36
36
  end
37
- task default: :spec
37
+ task default: :test
@@ -1,25 +1,8 @@
1
1
  require_relative "partial"
2
2
 
3
3
  module NicePartials::Helper
4
- def np
4
+ def nice_partial
5
5
  NicePartials::Partial.new(self)
6
6
  end
7
-
8
- def nice_partials_push_t_prefix(prefix)
9
- @_nice_partials_t_prefixes ||= []
10
- @_nice_partials_t_prefixes << prefix
11
- end
12
-
13
- def nice_partials_pop_t_prefix
14
- @_nice_partials_t_prefixes ||= []
15
- @_nice_partials_t_prefixes.pop
16
- end
17
-
18
- def t(key, options = {})
19
- if @_nice_partials_t_prefixes&.any? && key.first == '.'
20
- key = "#{@_nice_partials_t_prefixes.last}#{key}"
21
- end
22
-
23
- super(key, options)
24
- end
7
+ alias_method :np, :nice_partial
25
8
  end
@@ -1,23 +1,120 @@
1
1
  # Monkey patch required to make `t` work as expected. Is this evil?
2
2
  # TODO Do we need to monkey patch other types of renderers as well?
3
- class ActionView::PartialRenderer
4
- alias_method :original_render, :render
5
-
6
- # See `content_for` in `lib/nice_partials/partial.rb` for something similar.
7
- def render(partial, context, block)
8
- if block
9
- partial_prefix = nice_partials_locale_prefix_from_view_context_and_block(context, block)
10
- context.nice_partials_push_t_prefix partial_prefix
3
+ module NicePartials::RenderingWithLocalePrefix
4
+ ActionView::Base.prepend self
5
+
6
+ def capture(*, &block)
7
+ with_nice_partials_t_prefix(lookup_context, block) { super }
8
+ end
9
+
10
+ def t(key, options = {})
11
+ if (prefix = @_nice_partials_t_prefix) && key.first == '.'
12
+ key = "#{prefix}#{key}"
13
+ end
14
+
15
+ super(key, **options)
16
+ end
17
+
18
+ private
19
+
20
+ def with_nice_partials_t_prefix(lookup_context, block)
21
+ _nice_partials_t_prefix = @_nice_partials_t_prefix
22
+ @_nice_partials_t_prefix = block ? NicePartials.locale_prefix_from(lookup_context, block) : nil
23
+ yield
24
+ ensure
25
+ @_nice_partials_t_prefix = _nice_partials_t_prefix
26
+ end
27
+ end
28
+
29
+ require "active_support/deprecation"
30
+ NicePartials::DEPRECATOR = ActiveSupport::Deprecation.new("1.0", "nice_partials")
31
+
32
+ module NicePartials::RenderingWithAutoContext
33
+ ActionView::Base.prepend self
34
+
35
+ def __partials
36
+ @__partials ||= NicePartials::Partial::Stack.new
37
+ end
38
+ delegate :partial, to: :__partials
39
+
40
+ def p(*args)
41
+ if args.empty?
42
+ NicePartials::DEPRECATOR.deprecation_warning :p, :partial # In-branch printing so we don't warn on legit `Kernel.p` calls.
43
+ partial
44
+ else
45
+ super # …we're really Kernel.p
46
+ end
47
+ end
48
+
49
+ # Overrides `ActionView::Helpers::RenderingHelper#render` to push a new `nice_partial`
50
+ # on the stack, so rendering has a fresh `partial` to store content in.
51
+ def render(*)
52
+ __partials.prepend nice_partial
53
+ super
54
+ ensure
55
+ __partials.shift
56
+ end
57
+
58
+ # Since Action View passes any `yield`s in partials through `_layout_for`, we
59
+ # override `_layout_for` to detects if it's a capturing yield and append the
60
+ # current partial to the arguments.
61
+ #
62
+ # So `render … do |some_object|` can become `render … do |some_object, partial|`
63
+ # without needing to find and update the inner `yield some_object` call.
64
+ def _layout_for(*arguments, &block)
65
+ if block && !arguments.first.is_a?(Symbol)
66
+ capture_with_outer_partial_access(*arguments, &block)
11
67
  else
12
- # Render partial calls with no block should disable any prefix magic.
13
- context.nice_partials_push_t_prefix ''
68
+ super
14
69
  end
70
+ end
71
+
72
+ # Reverts `partial` to return the outer partial before the `render` call started.
73
+ #
74
+ # So we don't clobber the `partial` shown here:
75
+ #
76
+ # <%= render "card" do |inner_partial| %>
77
+ # <% inner_partial.content_for :title, partial.content_for(:title) %>
78
+ # <% end %>
79
+ #
80
+ # Note: this happens because the `@partial` instance variable is shared between all
81
+ # `render` calls since rendering happens in one `ActionView::Base` instance.
82
+ def capture_with_outer_partial_access(*arguments, &block)
83
+ __partials.locate_previous
84
+ __partials.first.capture(*arguments, &block)
85
+ ensure
86
+ __partials.reset_locator
87
+ end
88
+ end
15
89
 
16
- result = original_render(partial, context, block)
90
+ module NicePartials::PartialRendering
91
+ ActionView::PartialRenderer.prepend self
92
+
93
+ # Automatically captures the `block` in case the partial has no manual capturing `yield` call.
94
+ #
95
+ # This manual equivalent would be inserting this:
96
+ #
97
+ # <% yield partial %>
98
+ def render_partial_template(view, locals, template, layout, block)
99
+ view.capture_with_outer_partial_access(&block) if block && !template.has_capturing_yield?
100
+ super
101
+ end
102
+ end
17
103
 
18
- # Whether there was a block or not, pop off whatever we put on the stack.
19
- context.nice_partials_pop_t_prefix
104
+ module NicePartials::CapturingYieldDetection
105
+ ActionView::Template.include self
20
106
 
21
- return result
107
+ # Matches yields that'll end up calling `capture`:
108
+ # <%= yield %>
109
+ # <%= yield something_else %>
110
+ #
111
+ # Doesn't match obfuscated `content_for` invocations, nor custom yields:
112
+ # <%= yield :message %>
113
+ # <%= something.yield %>
114
+ #
115
+ # Note: `<%= yield %>` becomes `yield :layout` with no `render` `block`, though this method assumes a block is passed.
116
+ def has_capturing_yield?
117
+ defined?(@has_capturing_yield) ? @has_capturing_yield :
118
+ @has_capturing_yield = source.match?(/\byield[\(? ]+(%>|[^:])/)
22
119
  end
23
120
  end
@@ -0,0 +1,43 @@
1
+ class NicePartials::Partial::Section
2
+ def initialize(view_context)
3
+ @view_context = view_context
4
+ @content = @pending_content = nil
5
+ end
6
+
7
+ def content_for(*arguments, &block)
8
+ if write_content_for(arguments.first, &block)
9
+ nil
10
+ else
11
+ capture_content_for(*arguments) if pending?
12
+ @content
13
+ end
14
+ end
15
+
16
+ def content?
17
+ pending? || @content
18
+ end
19
+
20
+ private
21
+
22
+ def write_content_for(content = nil, &block)
23
+ if content && !pending?
24
+ concat content
25
+ else
26
+ @pending_content = block if block
27
+ end
28
+ end
29
+
30
+ def capture_content_for(*arguments)
31
+ concat @view_context.capture(*arguments, &@pending_content)
32
+ @pending_content = nil
33
+ end
34
+
35
+ def concat(string)
36
+ @content ||= ActiveSupport::SafeBuffer.new
37
+ @content << string.to_s if string.present?
38
+ end
39
+
40
+ def pending?
41
+ @pending_content
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ class NicePartials::Partial::Stack
2
+ def initialize
3
+ @partials = []
4
+ reset_locator
5
+ end
6
+ delegate :prepend, :shift, :first, to: :@partials
7
+
8
+ def partial
9
+ @partials.public_send @locator
10
+ end
11
+
12
+ def locate_previous
13
+ @locator = :second
14
+ end
15
+
16
+ def reset_locator
17
+ @locator = :first
18
+ end
19
+ end
@@ -1,39 +1,57 @@
1
1
  module NicePartials
2
2
  class Partial
3
+ autoload :Section, "nice_partials/partial/section"
4
+ autoload :Stack, "nice_partials/partial/stack"
5
+
3
6
  delegate_missing_to :@view_context
4
7
 
8
+ # <%= render "nice_partial" do |p| %>
9
+ # <% p.content_for :title, "Yo" %>
10
+ # This content can be accessed through calling `yield`.
11
+ # <% end %>
12
+ #
13
+ # Then in the nice_partial:
14
+ # <%= content.content_for :title %> # => "Yo"
15
+ # <%= content.output_buffer %> # => "This line is printed to the `output_buffer`."
16
+ attr_accessor :output_buffer
17
+
5
18
  def initialize(view_context)
6
19
  @view_context = view_context
7
- @key = SecureRandom.uuid
20
+ @contents = Hash.new { |h, k| h[k] = Section.new(@view_context) }
8
21
  end
9
22
 
10
- def yield(name = nil)
11
- raise "You can only use Nice Partial's yield method to retrieve the content of named content area blocks. If you're not trying to fetch the content of a named content area block, you don't need Nice Partials! You can just call the vanilla Rails `yield`." unless name
12
- content_for(name)
23
+ def yield(*arguments, &block)
24
+ if arguments.empty?
25
+ output_buffer
26
+ else
27
+ content_for(*arguments, &block)
28
+ end
13
29
  end
14
30
 
15
31
  def helpers(&block)
16
32
  class_eval &block
17
33
  end
18
34
 
19
- # See the `ActionView::PartialRenderer` monkey patch in `lib/nice_partials/monkey_patch.rb` for something similar.
20
- def content_for(name, content = nil, options = {}, &block)
21
- if block_given?
22
- partial_prefix = nice_partials_locale_prefix_from_view_context_and_block(@view_context, block)
23
- @view_context.nice_partials_push_t_prefix(partial_prefix)
24
- end
25
-
26
- result = @view_context.content_for("#{name}_#{@key}".to_sym, content, options, &block)
27
-
28
- if block_given?
29
- @view_context.nice_partials_pop_t_prefix
30
- end
31
-
32
- return result
35
+ # Similar to Rails' built-in `content_for` except it defers any block execution
36
+ # and lets you pass arguments into it, like so:
37
+ #
38
+ # # Here we store a block with some eventual content…
39
+ # <% partial.content_for :title do |tag|
40
+ # <%= tag.h1 %>
41
+ # <% end %>
42
+ #
43
+ # # …which is then invoked with some predefined options later.
44
+ # <%= partial.content_for :title, tag.with_options(class: "text-bold") %>
45
+ def content_for(name, content = nil, *arguments, &block)
46
+ @contents[name].content_for(content, *arguments, &block)
33
47
  end
34
48
 
35
49
  def content_for?(name)
36
- @view_context.content_for?("#{name}_#{@key}".to_sym)
50
+ @contents[name].content?
51
+ end
52
+
53
+ def capture(*arguments, &block)
54
+ self.output_buffer = @view_context.capture(*arguments, self, &block)
37
55
  end
38
56
  end
39
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NicePartials
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.9"
5
5
  end
data/lib/nice_partials.rb CHANGED
@@ -1,21 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "nice_partials/version"
4
- require_relative "nice_partials/helper"
5
- require_relative "nice_partials/monkey_patch"
6
- require_relative "partials"
7
4
 
8
5
  module NicePartials
9
- end
10
-
11
- # TODO Is there somewhere better we can put this?
12
- def nice_partials_locale_prefix_from_view_context_and_block(context, block)
13
- root_paths = context.view_renderer.lookup_context.view_paths.map(&:path)
14
- partial_location = block.source_location.first.dup
15
- root_paths.each { |path| partial_location.gsub!(/^#{path}\//, '') }
16
- partial_location.split('.').first.gsub('/_', '/').gsub('/', '.')
6
+ def self.locale_prefix_from(lookup_context, block)
7
+ root_paths = lookup_context.view_paths.map(&:path)
8
+ partial_location = block.source_location.first.dup
9
+ root_paths.each { |path| partial_location.gsub!(/^#{path}\//, '') }
10
+ partial_location.split('.').first.gsub('/_', '/').gsub('/', '.')
11
+ end
17
12
  end
18
13
 
19
14
  ActiveSupport.on_load :action_view do
15
+ require_relative "nice_partials/monkey_patch"
16
+
17
+ require_relative "nice_partials/helper"
20
18
  include NicePartials::Helper
21
19
  end
Binary file
@@ -20,4 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.required_ruby_version = ">= 2.0"
21
21
 
22
22
  gem.add_dependency "actionview", '>= 4.2.6'
23
+
24
+ gem.add_development_dependency "rails"
25
+ gem.add_development_dependency "standard"
23
26
  end
@@ -0,0 +1 @@
1
+ <%= partial.yield :message %>
@@ -0,0 +1,11 @@
1
+ <div class="card">
2
+ <%= partial.yield :image %>
3
+ <div class="card-body">
4
+ <h5 class="card-title"><%= title %></h5>
5
+ <% if partial.content_for? :body %>
6
+ <p class="card-text">
7
+ <%= partial.content_for :body, tag.with_options(class: "text-bold") %>
8
+ </p>
9
+ <% end %>
10
+ </div>
11
+ </div>
@@ -0,0 +1,3 @@
1
+ <% p "it's clobbering time" %>
2
+ <%# TODO: Remove this file once `p` has been removed post deprecation, but don't change it yet. %>
3
+ <%= p.yield :message %>
@@ -0,0 +1,11 @@
1
+ <% partial.content_for :original_message, "hello" %>
2
+
3
+ <%= render "basic" do |cp| %>
4
+ <% cp.content_for :message, partial.content_for(:original_message) %>
5
+ <% end %>
6
+
7
+ <%= render "basic" do |cp| %>
8
+ <% cp.content_for :message, "goodbye" %>
9
+ <% end %>
10
+
11
+ <span><%= partial.content_for :message %></span>
@@ -0,0 +1,9 @@
1
+ <%= render "card", title: "Some Title" do |p| %>
2
+ <% p.content_for :body do |tag| %>
3
+ <%= tag.p "Lorem Ipsum" %>
4
+ <% end %>
5
+
6
+ <% p.content_for :image do %>
7
+ <img src="https://example.com/image.jpg" />
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <%= render("basic") do |partial| %>
2
+ <%= partial.content_for :message, t(".message") %>
3
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= t ".message" %>
@@ -0,0 +1 @@
1
+ <%= yield Hash.new(custom_key: :custom_value) %>
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,3 @@
1
+ <%= render "yields/plain" do %>
2
+ <%= yield %>
3
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= yield :message %>
@@ -0,0 +1,26 @@
1
+ require "test_helper"
2
+
3
+ module Renderer; end
4
+
5
+ class Renderer::TranslationTest < NicePartials::Test
6
+ setup do
7
+ I18n.backend.store_translations "en", { translations: {
8
+ translated: { message: "message" },
9
+ nice_partials_translated: { message: "nice_partials" }
10
+ } }
11
+ end
12
+
13
+ teardown { I18n.reload! }
14
+
15
+ test "clean translation render" do
16
+ render "translations/translated"
17
+
18
+ assert_rendered "message"
19
+ end
20
+
21
+ test "translations insert prefix from originating partial" do
22
+ render "translations/nice_partials_translated"
23
+
24
+ assert_rendered "nice_partials"
25
+ end
26
+ end
@@ -0,0 +1,83 @@
1
+ require "test_helper"
2
+
3
+ class RendererTest < NicePartials::Test
4
+ test "render basic nice partial" do
5
+ render("basic") { |p| p.content_for :message, "hello from nice partials" }
6
+
7
+ assert_rendered "hello from nice partials"
8
+ end
9
+
10
+ test "render nice partial in card template" do
11
+ render(template: "card_test")
12
+
13
+ assert_rendered "Some Title"
14
+ assert_rendered '<p class="text-bold">Lorem Ipsum</p>'
15
+ assert_rendered "https://example.com/image.jpg"
16
+ end
17
+
18
+ test "accessing partial in outer context won't leak state to inner render" do
19
+ render "partial_accessed_in_outer_context"
20
+
21
+ assert_rendered "hello"
22
+ assert_rendered "goodbye"
23
+ assert_rendered "<span></span>"
24
+ assert_not_includes rendered, "hellogoodbye"
25
+ end
26
+
27
+ test "explicit yield without any arguments auto-captures passed block" do
28
+ render "yields/plain" do |partial, auto_capture_shouldnt_pass_extra_argument|
29
+ assert_kind_of NicePartials::Partial, partial
30
+ assert_nil auto_capture_shouldnt_pass_extra_argument
31
+ end
32
+ end
33
+
34
+ test "explicit yield with symbol auto-captures passed block" do
35
+ render "yields/symbol" do |partial, auto_capture_shouldnt_pass_extra_argument|
36
+ assert_kind_of NicePartials::Partial, partial
37
+ assert_nil auto_capture_shouldnt_pass_extra_argument
38
+ end
39
+ end
40
+
41
+ test "explicit yield with object won't auto-capture but make partial available in capture" do
42
+ render "yields/object" do |object, partial|
43
+ assert_equal Hash.new(custom_key: :custom_value), object
44
+ assert_kind_of NicePartials::Partial, partial
45
+ end
46
+ end
47
+
48
+ test "explicit yield without any arguments with nesting" do
49
+ render "yields/plain_nested" do
50
+ tag.span "Output in outer partial through yield"
51
+ end
52
+
53
+ assert_rendered "<span>Output in outer partial through yield</span>"
54
+ end
55
+
56
+ test "output_buffer captures content not written via yield/content_for" do
57
+ nice_partial = nil
58
+ render "basic" do |p|
59
+ nice_partial = p
60
+ p.content_for :message, "hello from nice partials"
61
+ "Some extra content"
62
+ end
63
+
64
+ assert_rendered "hello from nice partials"
65
+ assert_equal "Some extra content", nice_partial.yield
66
+ end
67
+
68
+ test "doesn't clobber Kernel.p" do
69
+ assert_output "\"it's clobbering time\"\n" do
70
+ render("clobberer") { |p| p.content_for :message, "hello from nice partials" }
71
+ end
72
+
73
+ assert_rendered "hello from nice partials"
74
+ end
75
+
76
+ test "deprecates top-level access through p method" do
77
+ assert_deprecated /p is deprecated and will be removed from nice_partials \d/, NicePartials::DEPRECATOR do
78
+ assert_output "\"it's clobbering time\"\n" do
79
+ render("clobberer") { |p| p.content_for :message, "hello from nice partials" }
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,17 @@
1
+ require "active_support"
2
+ require "active_support/testing/autorun"
3
+ require "action_controller"
4
+ require "action_view"
5
+ require "action_view/test_case"
6
+
7
+ require "nice_partials"
8
+
9
+ class NicePartials::Test < ActionView::TestCase
10
+ TestController.view_paths << "test/fixtures"
11
+
12
+ private
13
+
14
+ def assert_rendered(matcher)
15
+ assert_match matcher, rendered
16
+ end
17
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nice_partials
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-10-05 00:00:00.000000000 Z
12
+ date: 2022-08-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionview
@@ -25,6 +25,34 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: 4.2.6
28
+ - !ruby/object:Gem::Dependency
29
+ name: rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: standard
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
28
56
  description: A little bit of magic to make partials perfect for components.
29
57
  email:
30
58
  - andrew.culver@gmail.com
@@ -45,10 +73,25 @@ files:
45
73
  - lib/nice_partials/helper.rb
46
74
  - lib/nice_partials/monkey_patch.rb
47
75
  - lib/nice_partials/partial.rb
76
+ - lib/nice_partials/partial/section.rb
77
+ - lib/nice_partials/partial/stack.rb
48
78
  - lib/nice_partials/version.rb
49
- - lib/partials.rb
79
+ - nice_partials-0.1.8.gem
50
80
  - nice_partials.gemspec
51
- - spec/nice_partials_spec.rb
81
+ - test/fixtures/_basic.html.erb
82
+ - test/fixtures/_card.html.erb
83
+ - test/fixtures/_clobberer.html.erb
84
+ - test/fixtures/_partial_accessed_in_outer_context.html.erb
85
+ - test/fixtures/card_test.html.erb
86
+ - test/fixtures/translations/_nice_partials_translated.html.erb
87
+ - test/fixtures/translations/_translated.html.erb
88
+ - test/fixtures/yields/_object.html.erb
89
+ - test/fixtures/yields/_plain.html.erb
90
+ - test/fixtures/yields/_plain_nested.html.erb
91
+ - test/fixtures/yields/_symbol.html.erb
92
+ - test/renderer/translation_test.rb
93
+ - test/renderer_test.rb
94
+ - test/test_helper.rb
52
95
  homepage: https://github.com/bullet-train-co/nice_partials
53
96
  licenses:
54
97
  - MIT
@@ -68,9 +111,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
111
  - !ruby/object:Gem::Version
69
112
  version: '0'
70
113
  requirements: []
71
- rubygems_version: 3.1.4
114
+ rubygems_version: 3.3.7
72
115
  signing_key:
73
116
  specification_version: 4
74
117
  summary: A little bit of magic to make partials perfect for components.
75
118
  test_files:
76
- - spec/nice_partials_spec.rb
119
+ - test/fixtures/_basic.html.erb
120
+ - test/fixtures/_card.html.erb
121
+ - test/fixtures/_clobberer.html.erb
122
+ - test/fixtures/_partial_accessed_in_outer_context.html.erb
123
+ - test/fixtures/card_test.html.erb
124
+ - test/fixtures/translations/_nice_partials_translated.html.erb
125
+ - test/fixtures/translations/_translated.html.erb
126
+ - test/fixtures/yields/_object.html.erb
127
+ - test/fixtures/yields/_plain.html.erb
128
+ - test/fixtures/yields/_plain_nested.html.erb
129
+ - test/fixtures/yields/_symbol.html.erb
130
+ - test/renderer/translation_test.rb
131
+ - test/renderer_test.rb
132
+ - test/test_helper.rb
data/lib/partials.rb DELETED
@@ -1,2 +0,0 @@
1
- module Partials
2
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../lib/nice_partials"
4
- require "minitest/autorun"
5
-
6
- describe NicePartials do
7
- it "works" do
8
- assert_equal true, false
9
- end
10
- end
11
-