nice_partials 0.1.6 → 0.1.9
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/.travis.yml +1 -0
- data/CHANGELOG.md +55 -1
- data/README.md +34 -20
- data/Rakefile +1 -1
- data/lib/nice_partials/helper.rb +2 -19
- data/lib/nice_partials/monkey_patch.rb +105 -44
- data/lib/nice_partials/partial/section.rb +43 -0
- data/lib/nice_partials/partial/stack.rb +19 -0
- data/lib/nice_partials/partial.rb +37 -19
- data/lib/nice_partials/version.rb +1 -1
- data/lib/nice_partials.rb +9 -10
- data/nice_partials-0.1.8.gem +0 -0
- data/nice_partials.gemspec +1 -0
- data/test/fixtures/_basic.html.erb +1 -2
- data/test/fixtures/_card.html.erb +3 -5
- data/test/fixtures/_clobberer.html.erb +3 -0
- data/test/fixtures/_partial_accessed_in_outer_context.html.erb +11 -0
- data/test/fixtures/card_test.html.erb +2 -2
- data/test/fixtures/translations/_nice_partials_translated.html.erb +3 -0
- data/test/fixtures/translations/_translated.html.erb +1 -0
- data/test/fixtures/yields/_object.html.erb +1 -0
- data/test/fixtures/yields/_plain.html.erb +1 -0
- data/test/fixtures/yields/_plain_nested.html.erb +3 -0
- data/test/fixtures/yields/_symbol.html.erb +1 -0
- data/test/renderer/translation_test.rb +26 -0
- data/test/renderer_test.rb +64 -38
- data/test/test_helper.rb +11 -1
- metadata +38 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc6e751d8a192aa46fe3ee5401fe924c4dc1f5c6c3c7fabe8c22f468ff3a344c
|
4
|
+
data.tar.gz: de5a48e0d84e96a40b85293933af3dadd4977e6dfa2dd06522c85e1a6fbd0576
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f56fb3b92520c7a818b6ced0225def224a265a9ca2400d70e283300df8eef3fc266c6b65fa2e4e24856d7eccb6c0b39bdadf056bdec76c499be68fd9d90a982
|
7
|
+
data.tar.gz: 6a58763a68c0aa76cfee32432c730166cd96a19b2c8a1e8428c26260663ff706fc4883af07e9b1782da0d7e493ca7f4f8883fde223b75674967acce7a3780bc1
|
data/.travis.yml
CHANGED
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
|
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
|
-
<%=
|
8
|
+
<%= partial.yield :image %>
|
9
9
|
<div class="card-body">
|
10
10
|
<h5 class="card-title"><%= title %></h5>
|
11
|
-
<% if
|
11
|
+
<% if partial.content_for? :body %>
|
12
12
|
<p class="card-text">
|
13
|
-
<%=
|
13
|
+
<%= partial.yield :body %>
|
14
14
|
</p>
|
15
15
|
<% end %>
|
16
16
|
</div>
|
17
17
|
</div>
|
18
18
|
```
|
19
19
|
|
20
|
-
|
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 |
|
24
|
-
<%
|
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
|
-
<%
|
31
|
+
<% partial.content_for :image do %>
|
32
32
|
<%= image_tag image_path('example.jpg'), alt: 'An example image' %>
|
33
33
|
<% end %>
|
34
34
|
<% end %>
|
@@ -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
|
-
###
|
107
|
+
### Using Nice Partials
|
108
108
|
|
109
|
-
|
109
|
+
Nice Partials is invoked automatically when you render your partial with a block like so:
|
110
110
|
|
111
111
|
```html+erb
|
112
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
123
|
+
In a regular Rails partial:
|
123
124
|
|
124
|
-
|
125
|
+
```html+erb
|
126
|
+
<%= render 'components/card' do %>
|
127
|
+
Some content!
|
128
|
+
Yet more content!
|
129
|
+
<% end %>
|
130
|
+
```
|
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
|
+
```
|
125
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
|
-
<%
|
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,7 @@ end %>
|
|
147
161
|
Then later in the partial you can use the helper method like so:
|
148
162
|
|
149
163
|
```html+erb
|
150
|
-
<td><%=
|
164
|
+
<td><%= partial.reference_to(user) %></td>
|
151
165
|
```
|
152
166
|
|
153
167
|
## Development
|
data/Rakefile
CHANGED
data/lib/nice_partials/helper.rb
CHANGED
@@ -1,25 +1,8 @@
|
|
1
1
|
require_relative "partial"
|
2
2
|
|
3
3
|
module NicePartials::Helper
|
4
|
-
def
|
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,59 +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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
context.nice_partials_push_t_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}"
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
23
46
|
end
|
47
|
+
end
|
24
48
|
|
25
|
-
|
26
|
-
|
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
|
27
57
|
|
28
|
-
|
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)
|
67
|
+
else
|
68
|
+
super
|
69
|
+
end
|
29
70
|
end
|
30
71
|
|
31
|
-
#
|
32
|
-
#
|
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
|
89
|
+
|
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 %>
|
33
98
|
def render_partial_template(view, locals, template, layout, block)
|
34
|
-
|
35
|
-
|
36
|
-
identifier: template.identifier,
|
37
|
-
layout: layout && layout.virtual_path
|
38
|
-
) do |payload|
|
39
|
-
content = template.render(view, locals, ActionView::OutputBuffer.new, {add_to_stack: !block}) do |*name|
|
40
|
-
view._layout_for(*name, &block)
|
41
|
-
end
|
42
|
-
|
43
|
-
content = layout.render(view, locals) { content } if layout
|
44
|
-
payload[:cache_hit] = view.view_renderer.cache_hits[template.virtual_path]
|
45
|
-
build_rendered_template(content, template)
|
46
|
-
end
|
99
|
+
view.capture_with_outer_partial_access(&block) if block && !template.has_capturing_yield?
|
100
|
+
super
|
47
101
|
end
|
48
102
|
end
|
49
103
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
104
|
+
module NicePartials::CapturingYieldDetection
|
105
|
+
ActionView::Template.include self
|
106
|
+
|
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[\(? ]+(%>|[^:])/)
|
58
119
|
end
|
59
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
|
-
@
|
20
|
+
@contents = Hash.new { |h, k| h[k] = Section.new(@view_context) }
|
8
21
|
end
|
9
22
|
|
10
|
-
def yield(
|
11
|
-
|
12
|
-
|
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
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
@
|
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
|
data/lib/nice_partials.rb
CHANGED
@@ -1,20 +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
4
|
|
7
5
|
module NicePartials
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
root_paths.each { |path| partial_location.gsub!(/^#{path}\//, '') }
|
15
|
-
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
|
16
12
|
end
|
17
13
|
|
18
14
|
ActiveSupport.on_load :action_view do
|
15
|
+
require_relative "nice_partials/monkey_patch"
|
16
|
+
|
17
|
+
require_relative "nice_partials/helper"
|
19
18
|
include NicePartials::Helper
|
20
19
|
end
|
Binary file
|
data/nice_partials.gemspec
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
<%= p.yield :message %>
|
1
|
+
<%= partial.yield :message %>
|
@@ -1,12 +1,10 @@
|
|
1
|
-
<% yield p = np %>
|
2
|
-
|
3
1
|
<div class="card">
|
4
|
-
<%=
|
2
|
+
<%= partial.yield :image %>
|
5
3
|
<div class="card-body">
|
6
4
|
<h5 class="card-title"><%= title %></h5>
|
7
|
-
<% if
|
5
|
+
<% if partial.content_for? :body %>
|
8
6
|
<p class="card-text">
|
9
|
-
<%=
|
7
|
+
<%= partial.content_for :body, tag.with_options(class: "text-bold") %>
|
10
8
|
</p>
|
11
9
|
<% end %>
|
12
10
|
</div>
|
@@ -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 @@
|
|
1
|
+
<%= t ".message" %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= yield Hash.new(custom_key: :custom_value) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= yield %>
|
@@ -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
|
data/test/renderer_test.rb
CHANGED
@@ -1,57 +1,83 @@
|
|
1
|
-
|
1
|
+
require "test_helper"
|
2
2
|
|
3
|
-
class RendererTest <
|
4
|
-
|
5
|
-
|
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"
|
6
8
|
end
|
7
|
-
|
8
|
-
def setup_view(paths)
|
9
|
-
ActionView::Base.include(NicePartials::Helper)
|
10
9
|
|
11
|
-
|
10
|
+
test "render nice partial in card template" do
|
11
|
+
render(template: "card_test")
|
12
12
|
|
13
|
-
|
14
|
-
|
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
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
end.with_view_paths(paths, @assigns)
|
18
|
+
test "accessing partial in outer context won't leak state to inner render" do
|
19
|
+
render "partial_accessed_in_outer_context"
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
assert_rendered "hello"
|
22
|
+
assert_rendered "goodbye"
|
23
|
+
assert_rendered "<span></span>"
|
24
|
+
assert_not_includes rendered, "hellogoodbye"
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
30
32
|
end
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
setup_view(view_paths)
|
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
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
|
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
|
42
46
|
end
|
43
47
|
|
44
|
-
test "
|
45
|
-
|
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
|
46
52
|
|
47
|
-
|
53
|
+
assert_rendered "<span>Output in outer partial through yield</span>"
|
48
54
|
end
|
49
55
|
|
50
|
-
test "
|
51
|
-
|
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
|
52
72
|
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
56
82
|
end
|
57
83
|
end
|
data/test/test_helper.rb
CHANGED
@@ -2,6 +2,16 @@ require "active_support"
|
|
2
2
|
require "active_support/testing/autorun"
|
3
3
|
require "action_controller"
|
4
4
|
require "action_view"
|
5
|
+
require "action_view/test_case"
|
6
|
+
|
5
7
|
require "nice_partials"
|
6
8
|
|
7
|
-
|
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
|
+
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: 2022-
|
12
|
+
date: 2022-08-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionview
|
@@ -39,6 +39,20 @@ dependencies:
|
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
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'
|
42
56
|
description: A little bit of magic to make partials perfect for components.
|
43
57
|
email:
|
44
58
|
- andrew.culver@gmail.com
|
@@ -59,11 +73,23 @@ files:
|
|
59
73
|
- lib/nice_partials/helper.rb
|
60
74
|
- lib/nice_partials/monkey_patch.rb
|
61
75
|
- lib/nice_partials/partial.rb
|
76
|
+
- lib/nice_partials/partial/section.rb
|
77
|
+
- lib/nice_partials/partial/stack.rb
|
62
78
|
- lib/nice_partials/version.rb
|
79
|
+
- nice_partials-0.1.8.gem
|
63
80
|
- nice_partials.gemspec
|
64
81
|
- test/fixtures/_basic.html.erb
|
65
82
|
- test/fixtures/_card.html.erb
|
83
|
+
- test/fixtures/_clobberer.html.erb
|
84
|
+
- test/fixtures/_partial_accessed_in_outer_context.html.erb
|
66
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
|
67
93
|
- test/renderer_test.rb
|
68
94
|
- test/test_helper.rb
|
69
95
|
homepage: https://github.com/bullet-train-co/nice_partials
|
@@ -85,13 +111,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
111
|
- !ruby/object:Gem::Version
|
86
112
|
version: '0'
|
87
113
|
requirements: []
|
88
|
-
rubygems_version: 3.
|
114
|
+
rubygems_version: 3.3.7
|
89
115
|
signing_key:
|
90
116
|
specification_version: 4
|
91
117
|
summary: A little bit of magic to make partials perfect for components.
|
92
118
|
test_files:
|
93
119
|
- test/fixtures/_basic.html.erb
|
94
120
|
- test/fixtures/_card.html.erb
|
121
|
+
- test/fixtures/_clobberer.html.erb
|
122
|
+
- test/fixtures/_partial_accessed_in_outer_context.html.erb
|
95
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
|
96
131
|
- test/renderer_test.rb
|
97
132
|
- test/test_helper.rb
|