hanami-view 2.1.0.rc1 → 2.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/hanami-view.gemspec +0 -1
  4. data/lib/hanami/view/cache.rb +8 -1
  5. data/lib/hanami/view/context.rb +5 -0
  6. data/lib/hanami/view/decorated_attributes.rb +8 -0
  7. data/lib/hanami/view/erb/engine.rb +1 -1
  8. data/lib/hanami/view/erb/filters/block.rb +1 -1
  9. data/lib/hanami/view/erb/filters/trimming.rb +1 -1
  10. data/lib/hanami/view/erb/parser.rb +1 -1
  11. data/lib/hanami/view/erb/template.rb +1 -1
  12. data/lib/hanami/view/errors.rb +12 -20
  13. data/lib/hanami/view/exposure.rb +32 -0
  14. data/lib/hanami/view/exposures.rb +19 -0
  15. data/lib/hanami/view/helpers/escape_helper.rb +15 -15
  16. data/lib/hanami/view/helpers/number_formatting_helper.rb +13 -13
  17. data/lib/hanami/view/helpers/tag_helper/tag_builder.rb +21 -21
  18. data/lib/hanami/view/helpers/tag_helper.rb +8 -8
  19. data/lib/hanami/view/html.rb +14 -9
  20. data/lib/hanami/view/html_safe_string_buffer.rb +1 -1
  21. data/lib/hanami/view/part.rb +29 -12
  22. data/lib/hanami/view/part_builder.rb +6 -4
  23. data/lib/hanami/view/path.rb +14 -0
  24. data/lib/hanami/view/rendered.rb +13 -7
  25. data/lib/hanami/view/renderer.rb +17 -0
  26. data/lib/hanami/view/rendering.rb +17 -0
  27. data/lib/hanami/view/rendering_missing.rb +15 -0
  28. data/lib/hanami/view/scope.rb +23 -16
  29. data/lib/hanami/view/scope_builder.rb +5 -3
  30. data/lib/hanami/view/tilt/haml_adapter.rb +2 -0
  31. data/lib/hanami/view/tilt/slim_adapter.rb +2 -0
  32. data/lib/hanami/view/tilt.rb +5 -0
  33. data/lib/hanami/view/version.rb +3 -2
  34. data/lib/hanami/view.rb +69 -30
  35. metadata +3 -18
  36. data/lib/hanami/view/application_view.rb +0 -89
@@ -12,26 +12,26 @@ module Hanami
12
12
  # @see TagHelper#tag
13
13
  #
14
14
  # @api public
15
- # @since 2.0.0
15
+ # @since 2.1.0
16
16
  class TagBuilder
17
17
  # @api private
18
- # @since 2.0.0
18
+ # @since 2.1.0
19
19
  HTML_VOID_ELEMENTS = %i(
20
20
  area base br col embed hr img input keygen link meta param source track wbr
21
21
  ).to_set
22
22
 
23
23
  # @api private
24
- # @since 2.0.0
24
+ # @since 2.1.0
25
25
  SVG_SELF_CLOSING_ELEMENTS = %i(
26
26
  animate animateMotion animateTransform circle ellipse line path polygon polyline rect set stop use view
27
27
  ).to_set
28
28
 
29
29
  # @api private
30
- # @since 2.0.0
30
+ # @since 2.1.0
31
31
  ATTRIBUTE_SEPARATOR = " "
32
32
 
33
33
  # @api private
34
- # @since 2.0.0
34
+ # @since 2.1.0
35
35
  BOOLEAN_ATTRIBUTES = %w(
36
36
  allowfullscreen allowpaymentrequest async autofocus
37
37
  autoplay checked compact controls declare default
@@ -47,15 +47,15 @@ module Hanami
47
47
  BOOLEAN_ATTRIBUTES.freeze
48
48
 
49
49
  # @api private
50
- # @since 2.0.0
50
+ # @since 2.1.0
51
51
  ARIA_PREFIXES = ["aria", :aria].to_set.freeze
52
52
 
53
53
  # @api private
54
- # @since 2.0.0
54
+ # @since 2.1.0
55
55
  DATA_PREFIXES = ["data", :data].to_set.freeze
56
56
 
57
57
  # @api private
58
- # @since 2.0.0
58
+ # @since 2.1.0
59
59
  TAG_TYPES = {}.tap do |hsh|
60
60
  BOOLEAN_ATTRIBUTES.each { |attr| hsh[attr] = :boolean }
61
61
  DATA_PREFIXES.each { |attr| hsh[attr] = :data }
@@ -64,18 +64,18 @@ module Hanami
64
64
  end
65
65
 
66
66
  # @api private
67
- # @since 2.0.0
67
+ # @since 2.1.0
68
68
  PRE_CONTENT_STRINGS = Hash.new { "" }
69
69
  PRE_CONTENT_STRINGS[:textarea] = "\n"
70
70
  PRE_CONTENT_STRINGS["textarea"] = "\n"
71
71
  PRE_CONTENT_STRINGS.freeze
72
72
 
73
73
  # @api private
74
- # @since 2.0.0
74
+ # @since 2.1.0
75
75
  attr_reader :inflector
76
76
 
77
77
  # @api private
78
- # @since 2.0.0
78
+ # @since 2.1.0
79
79
  def initialize(inflector:)
80
80
  @inflector = inflector
81
81
  end
@@ -88,7 +88,7 @@ module Hanami
88
88
  # # => <input type="text" aria-label="Search">
89
89
  #
90
90
  # @api public
91
- # @since 2.0.0
91
+ # @since 2.1.0
92
92
  def attributes(**attributes)
93
93
  tag_options(**attributes).to_s.strip.html_safe
94
94
  end
@@ -96,13 +96,13 @@ module Hanami
96
96
  # Returns a `<p>` HTML tag.
97
97
  #
98
98
  # @api public
99
- # @since 2.0.0
99
+ # @since 2.1.0
100
100
  def p(*args, **options, &block)
101
101
  tag_string(:p, *args, **options, &block)
102
102
  end
103
103
 
104
104
  # @api private
105
- # @since 2.0.0
105
+ # @since 2.1.0
106
106
  def tag_string(name, content = nil, **options)
107
107
  content = yield if block_given?
108
108
  self_closing = SVG_SELF_CLOSING_ELEMENTS.include?(name)
@@ -115,7 +115,7 @@ module Hanami
115
115
  end
116
116
 
117
117
  # @api private
118
- # @since 2.0.0
118
+ # @since 2.1.0
119
119
  def content_tag_string(name, content, **options)
120
120
  tag_options = tag_options(**options) unless options.empty?
121
121
 
@@ -126,7 +126,7 @@ module Hanami
126
126
  end
127
127
 
128
128
  # @api private
129
- # @since 2.0.0
129
+ # @since 2.1.0
130
130
  def tag_options(**options)
131
131
  return if options.none?
132
132
 
@@ -174,13 +174,13 @@ module Hanami
174
174
  end
175
175
 
176
176
  # @api private
177
- # @since 2.0.0
177
+ # @since 2.1.0
178
178
  def boolean_tag_option(key)
179
179
  %(#{key}="#{key}")
180
180
  end
181
181
 
182
182
  # @api private
183
- # @since 2.0.0
183
+ # @since 2.1.0
184
184
  def tag_option(key, value)
185
185
  key = EscapeHelper.escape_xml_name(key)
186
186
 
@@ -201,19 +201,19 @@ module Hanami
201
201
  private
202
202
 
203
203
  # @api private
204
- # @since 2.0.0
204
+ # @since 2.1.0
205
205
  def method_missing(called, *args, **options, &block)
206
206
  tag_string(called, *args, **options, &block)
207
207
  end
208
208
 
209
209
  # @api private
210
- # @since 2.0.0
210
+ # @since 2.1.0
211
211
  def respond_to_missing?(*args)
212
212
  true
213
213
  end
214
214
 
215
215
  # @api private
216
- # @since 2.0.0
216
+ # @since 2.1.0
217
217
  def prefix_tag_option(prefix, key, value)
218
218
  key = "#{prefix}-#{inflector.dasherize(key.to_s)}"
219
219
 
@@ -30,7 +30,7 @@ module Hanami
30
30
  # end
31
31
  #
32
32
  # @api public
33
- # @since 2.0.0
33
+ # @since 2.1.0
34
34
  module TagHelper
35
35
  extend self
36
36
 
@@ -64,7 +64,7 @@ module Hanami
64
64
  # <% end %>
65
65
  #
66
66
  # @api public
67
- # @since 2.0.0
67
+ # @since 2.1.0
68
68
  def tag
69
69
  tag_builder
70
70
  end
@@ -111,7 +111,7 @@ module Hanami
111
111
  # @see #tag
112
112
  #
113
113
  # @api public
114
- # @since 2.0.0
114
+ # @since 2.1.0
115
115
  def link_to(content, url = nil, **attributes, &block)
116
116
  if block
117
117
  raise ArgumentError if url && content
@@ -145,7 +145,7 @@ module Hanami
145
145
  # # => "123 foo bar"
146
146
  #
147
147
  # @api public
148
- # @since 2.0.0
148
+ # @since 2.1.0
149
149
  def token_list(*args)
150
150
  tokens = build_tag_values(*args).flat_map { |value|
151
151
  safe = value.html_safe?
@@ -158,13 +158,13 @@ module Hanami
158
158
  # @see #token_list
159
159
  #
160
160
  # @api public
161
- # @since 2.0.0
161
+ # @since 2.1.0
162
162
  def class_names(...)
163
163
  token_list(...)
164
164
  end
165
165
 
166
166
  # @api private
167
- # @since 2.0.0
167
+ # @since 2.1.0
168
168
  def build_tag_values(*args)
169
169
  tag_values = []
170
170
 
@@ -185,7 +185,7 @@ module Hanami
185
185
  end
186
186
 
187
187
  # @api private
188
- # @since 2.0.0
188
+ # @since 2.1.0
189
189
  def tag_builder
190
190
  @tag_builder ||= begin
191
191
  TagBuilder.new(inflector: tag_builder_inflector)
@@ -193,7 +193,7 @@ module Hanami
193
193
  end
194
194
 
195
195
  # @api private
196
- # @since 2.0.0
196
+ # @since 2.1.0
197
197
  def tag_builder_inflector
198
198
  if respond_to?(:_context)
199
199
  return _context.inflector
@@ -2,6 +2,10 @@
2
2
 
3
3
  module Hanami
4
4
  class View
5
+ # HTML-focused behavior for strings intended to be output in templates.
6
+ #
7
+ # @api public
8
+ # @since 2.1.0
5
9
  module HTML
6
10
  # A string that has been marked as "HTML safe", ensuring that it is not automatically escaped
7
11
  # when used in HTML view templates.
@@ -12,16 +16,17 @@ module Hanami
12
16
  # @see String#html_safe
13
17
  #
14
18
  # @api public
15
- # @since 2.0.0
19
+ # @since 2.1.0
16
20
  class SafeString < String
17
21
  # @api public
18
- # @since 2.0.0
22
+ # @since 2.1.0
19
23
  def initialize(string)
20
24
  super(string)
21
25
  freeze
22
26
  end
23
27
 
24
28
  # @api private
29
+ # @since 2.1.0
25
30
  private def initialize_copy(other)
26
31
  super
27
32
  freeze
@@ -30,7 +35,7 @@ module Hanami
30
35
  # @return [true]
31
36
  #
32
37
  # @api public
33
- # @since 2.0.0
38
+ # @since 2.1.0
34
39
  def html_safe?
35
40
  true
36
41
  end
@@ -38,7 +43,7 @@ module Hanami
38
43
  # @return [self]
39
44
  #
40
45
  # @api public
41
- # @since 2.0.0
46
+ # @since 2.1.0
42
47
  def html_safe
43
48
  self
44
49
  end
@@ -46,14 +51,14 @@ module Hanami
46
51
  # @return [self]
47
52
  #
48
53
  # @api public
49
- # @since 2.0.0
54
+ # @since 2.1.0
50
55
  def to_s
51
56
  self
52
57
  end
53
58
  end
54
59
 
55
60
  # @api private
56
- # @since 2.0.0
61
+ # @since 2.1.0
57
62
  module StringExtensions
58
63
  # Returns the string as a {Hanami::View::HTML::SafeString}, ensuring the string is not
59
64
  # automatically escaped when used in HTML view templates.
@@ -61,7 +66,7 @@ module Hanami
61
66
  # @return [Hanami::View::HTML::SafeString]
62
67
  #
63
68
  # @api public
64
- # @since 2.0.0
69
+ # @since 2.1.0
65
70
  def html_safe
66
71
  Hanami::View::HTML::SafeString.new(self)
67
72
  end
@@ -85,7 +90,7 @@ class Object
85
90
  # @return [false]
86
91
  #
87
92
  # @api public
88
- # @since 2.0.0
93
+ # @since 2.1.0
89
94
  def html_safe?
90
95
  false
91
96
  end
@@ -95,7 +100,7 @@ class Numeric
95
100
  # @return [true]
96
101
  #
97
102
  # @api public
98
- # @since 2.0.0
103
+ # @since 2.1.0
99
104
  def html_safe?
100
105
  true
101
106
  end
@@ -25,7 +25,7 @@ module Hanami
25
25
  # @see Hanami::View::SlimAdapter::Template
26
26
  #
27
27
  # @api private
28
- # @since 2.0.0
28
+ # @since 2.1.0
29
29
  class HTMLSafeStringBuffer < Temple::Generators::StringBuffer
30
30
  # Replace `Temple::Generator::ArrayBuffer#call` (which is used via the superclass of
31
31
  # `StringBuffer`) with the standard implementation from the base `Temple::Generator`.
@@ -13,8 +13,10 @@ module Hanami
13
13
  # @see https://dry-rb.org/gems/dry-view/parts/
14
14
  #
15
15
  # @api public
16
+ # @since 2.1.0
16
17
  class Part
17
18
  # @api private
19
+ # @since 2.1.0
18
20
  CONVENIENCE_METHODS = %i[
19
21
  format
20
22
  context
@@ -31,6 +33,7 @@ module Hanami
31
33
  # @return [Symbol] name
32
34
  #
33
35
  # @api public
36
+ # @since 2.1.0
34
37
  attr_reader :_name
35
38
 
36
39
  # The decorated value. This is the value returned from the exposure.
@@ -44,6 +47,7 @@ module Hanami
44
47
  # @return [Object] value
45
48
  #
46
49
  # @api public
50
+ # @since 2.1.0
47
51
  attr_reader :_value
48
52
 
49
53
  # The current rendering
@@ -51,12 +55,16 @@ module Hanami
51
55
  # @return [Rendering]
52
56
  #
53
57
  # @api private
58
+ # @since 2.1.0
54
59
  attr_reader :_rendering
55
60
 
56
- # Determins a part name (when initialized without one). Intended for use
57
- # only while unit testing Parts.
61
+ # Determines a part name (when initialized without one). Intended for internal use only while
62
+ # unit testing Parts.
63
+ #
64
+ # @return [String]
58
65
  #
59
66
  # @api private
67
+ # @since 2.1.0
60
68
  def self.part_name(inflector)
61
69
  name ? inflector.underscore(inflector.demodulize(name)) : "part"
62
70
  end
@@ -68,6 +76,7 @@ module Hanami
68
76
  # @param rendering [Rendering] the current rendering
69
77
  #
70
78
  # @api public
79
+ # @since 2.1.0
71
80
  def initialize(
72
81
  rendering: RenderingMissing.new,
73
82
  name: self.class.part_name(rendering.inflector),
@@ -78,7 +87,7 @@ module Hanami
78
87
  @_rendering = rendering
79
88
  end
80
89
 
81
- # The template format for the current render environment.
90
+ # Returns the template format for the current rendering.
82
91
  #
83
92
  # @overload _format
84
93
  # Returns the format.
@@ -89,11 +98,12 @@ module Hanami
89
98
  # @return [Symbol] format
90
99
  #
91
100
  # @api public
101
+ # @since 2.1.0
92
102
  def _format
93
103
  _rendering.format
94
104
  end
95
105
 
96
- # The context object for the current render environment
106
+ # Returns the context object for the current rendering.
97
107
  #
98
108
  # @overload _context
99
109
  # Returns the context.
@@ -104,10 +114,13 @@ module Hanami
104
114
  # @return [Context] context
105
115
  #
106
116
  # @api public
117
+ # @since 2.1.0
107
118
  def _context
108
119
  _rendering.context
109
120
  end
110
121
 
122
+ # rubocop:disable Naming/UncommunicativeMethodParamName
123
+
111
124
  # Renders a new partial with the part included in its locals.
112
125
  #
113
126
  # @overload _render(partial_name, as: _name, **locals, &block)
@@ -124,7 +137,7 @@ module Hanami
124
137
  # @return [String] rendered partial
125
138
  #
126
139
  # @api public
127
- # rubocop:disable Naming/UncommunicativeMethodParamName
140
+ # @since 2.1.0
128
141
  def _render(partial_name, as: _name, **locals, &block)
129
142
  _rendering.partial(partial_name, _rendering.scope({as => self}.merge(locals)), &block)
130
143
  end
@@ -145,26 +158,28 @@ module Hanami
145
158
  # @return [Hanami::View::Scope] scope
146
159
  #
147
160
  # @api public
161
+ # @since 2.1.0
148
162
  def _scope(scope_name = nil, **locals)
149
163
  _rendering.scope(scope_name, {_name => self}.merge(locals))
150
164
  end
151
165
 
152
- # Returns a string representation of the value
166
+ # Returns a string representation of the value.
153
167
  #
154
168
  # @return [String]
155
169
  #
156
170
  # @api public
171
+ # @since 2.1.0
157
172
  def to_s
158
173
  _value.to_s
159
174
  end
160
175
 
161
- # Builds a new a part with the given parameters
176
+ # Builds a new a part with the given parameters.
162
177
  #
163
- # This is helpful for manually constructing a new part object that
164
- # maintains the current render environment.
178
+ # This is helpful for manually constructing a new part object that maintains the current
179
+ # rendering.
165
180
  #
166
- # However, using `.decorate` is preferred for declaring attributes that
167
- # should also be decorated as parts.
181
+ # However, using `.decorate` is preferred for declaring attributes that should also be
182
+ # decorated as parts.
168
183
  #
169
184
  # @see DecoratedAttributes::ClassInterface#decorate
170
185
  #
@@ -174,6 +189,7 @@ module Hanami
174
189
  # @param options[Hash<Symbol, Object>] other options to provide when initializing the new part
175
190
  #
176
191
  # @api public
192
+ # @since 2.1.0
177
193
  def new(klass = self.class, name: _name, value: _value, **options)
178
194
  klass.new(
179
195
  name: name,
@@ -183,11 +199,12 @@ module Hanami
183
199
  )
184
200
  end
185
201
 
186
- # Returns a string representation of the part
202
+ # Returns a string representation of the part.
187
203
  #
188
204
  # @return [String]
189
205
  #
190
206
  # @api public
207
+ # @since 2.1.0
191
208
  def inspect
192
209
  %(#<#{self.class.name} name=#{_name.inspect} value=#{_value.inspect}>)
193
210
  end
@@ -2,12 +2,13 @@
2
2
 
3
3
  module Hanami
4
4
  class View
5
- # Decorates exposure values with matching parts
5
+ # Decorates exposure values with matching parts.
6
6
  #
7
- # @api private
7
+ # @api public
8
+ # @since 2.1.0
8
9
  class PartBuilder
9
10
  class << self
10
- # Decorates an exposure value
11
+ # Decorates an exposure value.
11
12
  #
12
13
  # @param name [Symbol] exposure name
13
14
  # @param value [Object] exposure value
@@ -15,7 +16,8 @@ module Hanami
15
16
  #
16
17
  # @return [Hanami::View::Part] decorated value
17
18
  #
18
- # @api private
19
+ # @api public
20
+ # @since 2.1.0
19
21
  def call(name, value, as: nil, rendering:)
20
22
  builder = value.respond_to?(:to_ary) ? :build_collection_part : :build_part
21
23
 
@@ -5,11 +5,16 @@ require "pathname"
5
5
  module Hanami
6
6
  class View
7
7
  # @api private
8
+ # @since 2.1.0
8
9
  class Path
9
10
  include Dry::Equalizer(:dir, :root)
10
11
 
12
+ # @api private
13
+ # @since 2.1.0
11
14
  attr_reader :dir, :root
12
15
 
16
+ # @api private
17
+ # @since 2.1.0
13
18
  def self.[](path)
14
19
  if path.is_a?(self)
15
20
  path
@@ -18,21 +23,30 @@ module Hanami
18
23
  end
19
24
  end
20
25
 
26
+ # @api private
27
+ # @since 2.1.0
21
28
  def initialize(dir, root: dir)
22
29
  @dir = Pathname(dir)
23
30
  @root = Pathname(root)
24
31
  end
25
32
 
26
33
  # Searches for a template using a wildcard for the engine extension
34
+ #
35
+ # @api private
36
+ # @since 2.1.0
27
37
  def lookup(prefix, name, format)
28
38
  glob = dir.join(prefix, "#{name}.#{format}.*")
29
39
  Dir[glob].first
30
40
  end
31
41
 
42
+ # @api private
43
+ # @since 2.1.0
32
44
  def chdir(dirname)
33
45
  self.class.new(dir.join(dirname), root: root)
34
46
  end
35
47
 
48
+ # @api private
49
+ # @since 2.1.0
36
50
  def to_s
37
51
  dir.to_s
38
52
  end
@@ -4,22 +4,25 @@ require "dry/core/equalizer"
4
4
 
5
5
  module Hanami
6
6
  class View
7
- # Output of a View rendering
7
+ # The output of a view rendering.
8
8
  #
9
9
  # @api public
10
10
  # @since 2.1.0
11
11
  class Rendered
12
12
  include Dry::Equalizer(:output, :locals)
13
13
 
14
- # Returns the rendered view
14
+ # Returns the rendered view output.
15
15
  #
16
16
  # @return [String]
17
17
  #
18
+ # @see to_s
19
+ # @see to_str
20
+ #
18
21
  # @api public
19
22
  # @since 2.1.0
20
23
  attr_reader :output
21
24
 
22
- # Returns the hash of locals used to render the view
25
+ # Returns the hash of locals used to render the view output.
23
26
  #
24
27
  # @return [Hash[<Symbol, Hanami::View::Part>] locals hash
25
28
  #
@@ -34,7 +37,7 @@ module Hanami
34
37
  @locals = locals
35
38
  end
36
39
 
37
- # Returns the local corresponding to the key
40
+ # Returns the local corresponding to the key.
38
41
  #
39
42
  # @param name [Symbol] local key
40
43
  #
@@ -46,7 +49,7 @@ module Hanami
46
49
  locals[name]
47
50
  end
48
51
 
49
- # Returns the rendered view
52
+ # Returns the rendered view output.
50
53
  #
51
54
  # @return [String]
52
55
  #
@@ -55,9 +58,12 @@ module Hanami
55
58
  def to_s
56
59
  output
57
60
  end
61
+
62
+ # @api public
63
+ # @since 2.1.0
58
64
  alias_method :to_str, :to_s
59
65
 
60
- # Matches given input with the rendered view
66
+ # Returns true if the given input matches the rendered view output.
61
67
  #
62
68
  # @param matcher [String, Regexp] matcher
63
69
  #
@@ -70,7 +76,7 @@ module Hanami
70
76
  end
71
77
  alias_method :match, :match?
72
78
 
73
- # Checks if given string is included in the rendered view
79
+ # Returns true if given string is included in the rendered view output.
74
80
  #
75
81
  # @param string [String] string
76
82
  #
@@ -5,18 +5,33 @@ require_relative "errors"
5
5
  module Hanami
6
6
  class View
7
7
  # @api private
8
+ # @since 2.1.0
8
9
  class Renderer
10
+ # @api private
11
+ # @since 2.1.0
9
12
  PARTIAL_PREFIX = "_"
13
+
14
+ # @api private
15
+ # @since 2.1.0
10
16
  PATH_DELIMITER = "/"
17
+
18
+ # @api private
19
+ # @since 2.1.0
11
20
  CURRENT_PATH_PREFIX = "."
12
21
 
22
+ # @api private
23
+ # @since 2.1.0
13
24
  attr_reader :config, :prefixes
14
25
 
26
+ # @api private
27
+ # @since 2.1.0
15
28
  def initialize(config)
16
29
  @config = config
17
30
  @prefixes = [CURRENT_PATH_PREFIX]
18
31
  end
19
32
 
33
+ # @api private
34
+ # @since 2.1.0
20
35
  def template(name, format, scope, &block)
21
36
  old_prefixes = @prefixes.dup
22
37
 
@@ -32,6 +47,8 @@ module Hanami
32
47
  @prefixes = old_prefixes
33
48
  end
34
49
 
50
+ # @api private
51
+ # @since 2.1.0
35
52
  def partial(name, format, scope, &block)
36
53
  template(name_for_partial(name), format, scope, &block)
37
54
  end