hanami-view 1.3.3 → 2.0.0.alpha2

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -10
  3. data/LICENSE +20 -0
  4. data/README.md +20 -862
  5. data/hanami-view.gemspec +26 -16
  6. data/lib/hanami-view.rb +3 -1
  7. data/lib/hanami/view.rb +208 -223
  8. data/lib/hanami/view/application_configuration.rb +77 -0
  9. data/lib/hanami/view/application_context.rb +35 -0
  10. data/lib/hanami/view/application_view.rb +89 -0
  11. data/lib/hanami/view/context.rb +97 -0
  12. data/lib/hanami/view/context_helpers/content_helpers.rb +26 -0
  13. data/lib/hanami/view/decorated_attributes.rb +82 -0
  14. data/lib/hanami/view/errors.rb +19 -56
  15. data/lib/hanami/view/exposure.rb +126 -0
  16. data/lib/hanami/view/exposures.rb +74 -0
  17. data/lib/hanami/view/part.rb +217 -0
  18. data/lib/hanami/view/part_builder.rb +140 -0
  19. data/lib/hanami/view/path.rb +68 -0
  20. data/lib/hanami/view/render_environment.rb +62 -0
  21. data/lib/hanami/view/render_environment_missing.rb +44 -0
  22. data/lib/hanami/view/rendered.rb +55 -0
  23. data/lib/hanami/view/renderer.rb +79 -0
  24. data/lib/hanami/view/scope.rb +189 -0
  25. data/lib/hanami/view/scope_builder.rb +98 -0
  26. data/lib/hanami/view/standalone_view.rb +396 -0
  27. data/lib/hanami/view/tilt.rb +78 -0
  28. data/lib/hanami/view/tilt/erb.rb +26 -0
  29. data/lib/hanami/view/tilt/erbse.rb +21 -0
  30. data/lib/hanami/view/tilt/haml.rb +26 -0
  31. data/lib/hanami/view/version.rb +5 -5
  32. metadata +114 -70
  33. data/LICENSE.md +0 -22
  34. data/lib/hanami/layout.rb +0 -190
  35. data/lib/hanami/presenter.rb +0 -98
  36. data/lib/hanami/view/configuration.rb +0 -504
  37. data/lib/hanami/view/dsl.rb +0 -347
  38. data/lib/hanami/view/escape.rb +0 -225
  39. data/lib/hanami/view/inheritable.rb +0 -54
  40. data/lib/hanami/view/rendering.rb +0 -294
  41. data/lib/hanami/view/rendering/layout_finder.rb +0 -128
  42. data/lib/hanami/view/rendering/layout_registry.rb +0 -69
  43. data/lib/hanami/view/rendering/layout_scope.rb +0 -281
  44. data/lib/hanami/view/rendering/null_layout.rb +0 -52
  45. data/lib/hanami/view/rendering/null_local.rb +0 -82
  46. data/lib/hanami/view/rendering/null_template.rb +0 -83
  47. data/lib/hanami/view/rendering/null_view.rb +0 -26
  48. data/lib/hanami/view/rendering/options.rb +0 -24
  49. data/lib/hanami/view/rendering/partial.rb +0 -31
  50. data/lib/hanami/view/rendering/partial_file.rb +0 -29
  51. data/lib/hanami/view/rendering/partial_finder.rb +0 -75
  52. data/lib/hanami/view/rendering/partial_templates_finder.rb +0 -73
  53. data/lib/hanami/view/rendering/registry.rb +0 -134
  54. data/lib/hanami/view/rendering/scope.rb +0 -108
  55. data/lib/hanami/view/rendering/subscope.rb +0 -56
  56. data/lib/hanami/view/rendering/template.rb +0 -69
  57. data/lib/hanami/view/rendering/template_finder.rb +0 -55
  58. data/lib/hanami/view/rendering/template_name.rb +0 -50
  59. data/lib/hanami/view/rendering/templates_finder.rb +0 -144
  60. data/lib/hanami/view/rendering/view_finder.rb +0 -37
  61. data/lib/hanami/view/template.rb +0 -57
@@ -1,347 +0,0 @@
1
- require 'hanami/view/rendering/template_name'
2
- require 'hanami/view/rendering/layout_finder'
3
-
4
- module Hanami
5
- module View
6
- # Class level DSL
7
- #
8
- # @since 0.1.0
9
- module Dsl
10
- # When a value is given, specify a templates root path for the view.
11
- # Otherwise, it returns templates root path.
12
- #
13
- # When not initialized, it will return the global value from `Hanami::View.root`.
14
- #
15
- # @param value [String] the templates root for this view
16
- #
17
- # @return [Pathname] the specified root for this view or the global value
18
- #
19
- # @since 0.1.0
20
- #
21
- # @example Default usage
22
- # require 'hanami/view'
23
- #
24
- # module Articles
25
- # class Show
26
- # include Hanami::View
27
- # end
28
- # end
29
- #
30
- # Hanami::View.configuration.root # => 'app/templates'
31
- # Articles::Show.root # => 'app/templates'
32
- #
33
- # @example Custom root
34
- # require 'hanami/view'
35
- #
36
- # module Articles
37
- # class Show
38
- # include Hanami::View
39
- # root 'path/to/articles/templates'
40
- # end
41
- # end
42
- #
43
- # Hanami::View.configuration.root # => 'app/templates'
44
- # Articles::Show.root # => 'path/to/articles/templates'
45
- def root(value = nil)
46
- if value.nil?
47
- configuration.root
48
- else
49
- configuration.root(value)
50
- end
51
- end
52
-
53
- # When a value is given, specify the handled format.
54
- # Otherwise, it returns the previously specified format.
55
- #
56
- # @param value [Symbol] the format
57
- #
58
- # @return [Symbol, nil] the specified format for this view, if set
59
- #
60
- # @since 0.1.0
61
- #
62
- # @example
63
- # require 'hanami/view'
64
- #
65
- # module Articles
66
- # class Show
67
- # include Hanami::View
68
- # end
69
- #
70
- # class JsonShow < Show
71
- # format :json
72
- # end
73
- # end
74
- #
75
- # Articles::Show.format # => nil
76
- # Articles::JsonShow.format # => :json
77
- def format(value = nil)
78
- if value.nil?
79
- @format ||= nil
80
- else
81
- @format = value
82
- end
83
- end
84
-
85
- # When a value is given, specify the relative path to the template.
86
- # Otherwise, it returns the name that follows Hanami::View conventions.
87
- #
88
- # @param value [String] relative template path
89
- #
90
- # @return [String] the specified template for this view or the name
91
- # that follows the convention
92
- #
93
- # @since 0.1.0
94
- #
95
- # @example Default usage
96
- # require 'hanami/view'
97
- #
98
- # module Articles
99
- # class Show
100
- # include Hanami::View
101
- # end
102
- #
103
- # class JsonShow < Show
104
- # format :json
105
- # end
106
- # end
107
- #
108
- # Articles::Show.template # => 'articles/show'
109
- # Articles::JsonShow.template # => 'articles/show'
110
- #
111
- # @example Custom template
112
- # require 'hanami/view'
113
- #
114
- # module Articles
115
- # class Show
116
- # include Hanami::View
117
- # template 'articles/single_article'
118
- # end
119
- #
120
- # class JsonShow < Show
121
- # format :json
122
- # end
123
- # end
124
- #
125
- # Articles::Show.template # => 'articles/single_article'
126
- # Articles::JsonShow.template # => 'articles/single_article'
127
- #
128
- # @example With namespace
129
- # require 'hanami/view'
130
- #
131
- # module Furnitures
132
- # View = Hanami::View.generate(self)
133
- #
134
- # class Standalone
135
- # include Furnitures::View
136
- # end
137
- #
138
- # module Catalog
139
- # class Index
140
- # Furnitures::View
141
- # end
142
- # end
143
- # end
144
- #
145
- # Furnitures::Standalone.template # => 'standalone'
146
- # Furnitures::Catalog::Index.template # => 'catalog/index'
147
- #
148
- # @example With nested namespace
149
- # require 'hanami/view'
150
- #
151
- # module Frontend
152
- # View = Hanami::View.generate(self)
153
- #
154
- # class StandaloneView
155
- # include Frontend::View
156
- # end
157
- #
158
- # module Views
159
- # class Standalone
160
- # include Frontend::View
161
- # end
162
- #
163
- # module Sessions
164
- # class New
165
- # include Frontend::View
166
- # end
167
- # end
168
- # end
169
- # end
170
- #
171
- # Frontend::StandaloneView.template # => 'standalone_view'
172
- # Frontend::Views::Standalone.template # => 'standalone'
173
- # Frontend::Views::Sessions::New.template # => 'sessions/new'
174
- #
175
- # @example With deeply nested namespace
176
- # require 'hanami/view'
177
- #
178
- # module Bookshelf
179
- # module Web
180
- # View = Hanami::View.generate(self)
181
- #
182
- # module Views
183
- # module Books
184
- # class Show
185
- # include Bookshelf::Web::View
186
- # end
187
- # end
188
- # end
189
- # end
190
- #
191
- # module Api
192
- # View = Hanami::View.generate(self)
193
- #
194
- # module Views
195
- # module Books
196
- # class Show
197
- # include Bookshelf::Api::View
198
- # end
199
- # end
200
- # end
201
- # end
202
- # end
203
- #
204
- # Bookshelf::Web::Views::Books::Index.template # => 'books/index'
205
- # Bookshelf::Api::Views::Books::Index.template # => 'books/index'
206
- def template(value = nil)
207
- if value.nil?
208
- @template ||= Rendering::TemplateName.new(name, configuration.namespace).to_s
209
- else
210
- @template = value
211
- end
212
- end
213
-
214
- # When a value is given, it specifies the layout.
215
- # When false is given, Hanami::View::Rendering::NullLayout is returned.
216
- # Otherwise, it returns the previously specified layout.
217
- #
218
- # When the global configuration is set (`Hanami::View.layout=`), after the
219
- # loading process, it will return that layout if not otherwise specified.
220
- #
221
- # @param value [Symbol, FalseClass, nil] the layout name
222
- #
223
- # @return [Symbol, nil] the specified layout for this view, if set
224
- #
225
- # @since 0.1.0
226
- #
227
- # @see Hanami::Layout
228
- #
229
- # @example Default usage
230
- # require 'hanami/view'
231
- #
232
- # module Articles
233
- # class Show
234
- # include Hanami::View
235
- # end
236
- # end
237
- #
238
- # Articles::Show.layout # => nil
239
- #
240
- # @example Custom layout
241
- # require 'hanami/view'
242
- #
243
- # class ArticlesLayout
244
- # include Hanami::Layout
245
- # end
246
- #
247
- # module Articles
248
- # class Show
249
- # include Hanami::View
250
- # layout :articles
251
- # end
252
- # end
253
- #
254
- # Articles::Show.layout # => :articles
255
- #
256
- # @example Global configuration
257
- # require 'hanami/view'
258
- #
259
- # class ApplicationLayout
260
- # include Hanami::Layout
261
- # end
262
- #
263
- # module Articles
264
- # class Show
265
- # include Hanami::View
266
- # end
267
- # end
268
- #
269
- # Hanami::View.layout = :application
270
- # Articles::Show.layout # => nil
271
- #
272
- # Hanami::View.load!
273
- # Articles::Show.layout # => :application
274
- #
275
- # @example Global configuration with custom layout
276
- # require 'hanami/view'
277
- #
278
- # class ApplicationLayout
279
- # include Hanami::Layout
280
- # end
281
- #
282
- # class ArticlesLayout
283
- # include Hanami::Layout
284
- # end
285
- #
286
- # module Articles
287
- # class Show
288
- # include Hanami::View
289
- # layout :articles
290
- # end
291
- # end
292
- #
293
- # Hanami::View.layout = :application
294
- # Articles::Show.layout # => :articles
295
- #
296
- # Hanami::View.load!
297
- # Articles::Show.layout # => :articles
298
- #
299
- # @example Disable layout for the view
300
- # require 'hanami/view'
301
- #
302
- # class ApplicationLayout
303
- # include Hanami::Layout
304
- # end
305
- #
306
- # module Articles
307
- # class Show
308
- # include Hanami::View
309
- # layout false
310
- # end
311
- # end
312
- #
313
- # Hanami::View.load!
314
- # Articles::Show.layout # => Hanami::View::Rendering::NullLayout
315
- def layout(value = nil)
316
- if value.nil?
317
- @layout ||= nil
318
- @_layout ||= Rendering::LayoutFinder.find(@layout || configuration.layout, configuration.namespace)
319
- elsif !value
320
- @layout = Hanami::View::Rendering::NullLayout
321
- else
322
- @layout = value
323
- end
324
- end
325
-
326
- protected
327
-
328
- # Loading mechanism hook.
329
- #
330
- # @api private
331
- # @since 0.1.0
332
- #
333
- # @see Hanami::View.load!
334
- def load!
335
- super
336
-
337
- views.each do |v|
338
- v.root.freeze
339
- v.format.freeze
340
- v.template.freeze
341
- v.layout#.freeze
342
- v.configuration.freeze
343
- end
344
- end
345
- end
346
- end
347
- end
@@ -1,225 +0,0 @@
1
- require 'hanami/utils/escape'
2
-
3
- module Hanami
4
- module View
5
- # Auto escape logic for views and presenters.
6
- #
7
- # @since 0.4.0
8
- module Escape
9
- module InstanceMethods
10
- private
11
-
12
- # Mark the given string as safe to render.
13
- #
14
- # !!! ATTENTION !!! This may open your application to XSS attacks.
15
- #
16
- # @param string [String] the input string
17
- #
18
- # @return [Hanami::Utils::Escape::SafeString] the string marked as safe
19
- #
20
- # @since 0.4.0
21
- #
22
- # @example View usage
23
- # require 'hanami/view'
24
- #
25
- # User = Struct.new(:name)
26
- #
27
- # module Users
28
- # class Show
29
- # include Hanami::View
30
- #
31
- # def user_name
32
- # _raw user.name
33
- # end
34
- # end
35
- # end
36
- #
37
- # # ERB template
38
- # # <div id="user_name"><%= user_name %></div>
39
- #
40
- # user = User.new("<script>alert('xss')</script>")
41
- # html = Users::Show.render(format: :html, user: user)
42
- #
43
- # html # => <div id="user_name"><script>alert('xss')</script></div>
44
- #
45
- # @example Presenter usage
46
- # require 'hanami/view'
47
- #
48
- # User = Struct.new(:name)
49
- #
50
- # class UserPresenter
51
- # include Hanami::Presenter
52
- #
53
- # def name
54
- # _raw @object.name
55
- # end
56
- # end
57
- #
58
- # user = User.new("<script>alert('xss')</script>")
59
- # presenter = UserPresenter.new(user)
60
- #
61
- # presenter.name # => "<script>alert('xss')</script>"
62
- def _raw(string)
63
- ::Hanami::Utils::Escape::SafeString.new(string)
64
- end
65
-
66
- # Force the output escape for the given object
67
- #
68
- # @param object [Object] the input object
69
- #
70
- # @return [Hanami::View::Escape::Presenter] a presenter with output
71
- # autoescape
72
- #
73
- # @since 0.4.0
74
- #
75
- # @see Hanami::View::Escape::Presenter
76
- #
77
- # @example View usage
78
- # require 'hanami/view'
79
- #
80
- # User = Struct.new(:first_name, :last_name)
81
- #
82
- # module Users
83
- # class Show
84
- # include Hanami::View
85
- #
86
- # def user
87
- # _escape locals[:user]
88
- # end
89
- # end
90
- # end
91
- #
92
- # # ERB template:
93
- # #
94
- # # <div id="first_name">
95
- # # <%= user.first_name %>
96
- # # </div>
97
- # # <div id="last_name">
98
- # # <%= user.last_name %>
99
- # # </div>
100
- #
101
- # first_name = "<script>alert('first_name')</script>"
102
- # last_name = "<script>alert('last_name')</script>"
103
- #
104
- # user = User.new(first_name, last_name)
105
- # html = Users::Show.render(format: :html, user: user)
106
- #
107
- # html
108
- # # =>
109
- # # <div id="first_name">
110
- # # &lt;script&gt;alert(&apos;first_name&apos;)&lt;&#x2F;script&gt;
111
- # # </div>
112
- # # <div id="last_name">
113
- # # &lt;script&gt;alert(&apos;last_name&apos;)&lt;&#x2F;script&gt;
114
- # # </div>
115
- def _escape(object)
116
- ::Hanami::View::Escape::Presenter.new(object)
117
- end
118
- end
119
-
120
- module Presentable
121
- # Inject escape logic into the given class.
122
- #
123
- # @since 0.7.0
124
- # @api private
125
- #
126
- # @see Hanami::View::Escape
127
- def self.included(base)
128
- base.extend ::Hanami::View::Escape
129
- end
130
-
131
- # Initialize the presenter
132
- #
133
- # @param object [Object] the object to present
134
- #
135
- # @since 0.7.0
136
- def initialize(object)
137
- @object = object
138
- end
139
-
140
- protected
141
-
142
- # Override Ruby's method_missing
143
- #
144
- # @api private
145
- # @since 0.7.0
146
- def method_missing(m, *args, &blk)
147
- if @object.respond_to?(m)
148
- ::Hanami::View::Escape.html(@object.__send__(m, *args, &blk))
149
- else
150
- super
151
- end
152
- end
153
-
154
- # Override Ruby's respond_to_missing? in order to support proper delegation
155
- #
156
- # @api private
157
- # @since 0.3.0
158
- def respond_to_missing?(m, include_private = false)
159
- @object.respond_to?(m, include_private)
160
- end
161
- end
162
-
163
- # Auto escape presenter
164
- #
165
- # @since 0.4.0
166
- # @api private
167
- #
168
- # @see Hanami::View::Escape::InstanceMethods#_escape
169
- class Presenter
170
- include Presentable
171
- end
172
-
173
- # Escape the given input if it's a string, otherwise return the oject as it is.
174
- #
175
- # @param input [Object] the input
176
- #
177
- # @return [Object,String] the escaped string or the given object
178
- #
179
- # @since 0.4.0
180
- # @api private
181
- def self.html(input)
182
- case input
183
- when String
184
- Utils::Escape.html(input)
185
- else
186
- input
187
- end
188
- end
189
-
190
- # Module extended override
191
- #
192
- # @since 0.4.0
193
- # @api private
194
- def self.extended(base)
195
- base.class_eval do
196
- include ::Hanami::Utils::ClassAttribute
197
- include ::Hanami::View::Escape::InstanceMethods
198
-
199
- class_attribute :autoescape_methods
200
- self.autoescape_methods = {}
201
- end
202
- end
203
-
204
- # Wraps concrete view methods with escape logic.
205
- #
206
- # @since 0.4.0
207
- # @api private
208
- def method_added(method_name)
209
- visibility = :public
210
- visibility = :private if private_method_defined? method_name
211
- visibility = :protected if protected_method_defined? method_name
212
-
213
- unless autoescape_methods[method_name]
214
- prepend Module.new {
215
- module_eval %{
216
- #{ visibility } def #{ method_name }(*args, &blk); ::Hanami::View::Escape.html super; end
217
- }
218
- }
219
-
220
- autoescape_methods[method_name] = true
221
- end
222
- end
223
- end
224
- end
225
- end