hanami-view 1.3.0.beta1 → 2.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  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 +113 -63
  33. data/LICENSE.md +0 -22
  34. data/lib/hanami/layout.rb +0 -172
  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 -274
  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/options.rb +0 -24
  48. data/lib/hanami/view/rendering/partial.rb +0 -31
  49. data/lib/hanami/view/rendering/partial_file.rb +0 -29
  50. data/lib/hanami/view/rendering/partial_finder.rb +0 -75
  51. data/lib/hanami/view/rendering/partial_templates_finder.rb +0 -73
  52. data/lib/hanami/view/rendering/registry.rb +0 -134
  53. data/lib/hanami/view/rendering/scope.rb +0 -108
  54. data/lib/hanami/view/rendering/subscope.rb +0 -56
  55. data/lib/hanami/view/rendering/template.rb +0 -69
  56. data/lib/hanami/view/rendering/template_finder.rb +0 -55
  57. data/lib/hanami/view/rendering/template_name.rb +0 -50
  58. data/lib/hanami/view/rendering/templates_finder.rb +0 -144
  59. data/lib/hanami/view/rendering/view_finder.rb +0 -37
  60. 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