hanami-view 1.3.0.beta1 → 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 (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,83 +0,0 @@
1
- module Hanami
2
- module View
3
- module Rendering
4
- # Null Object pattern for layout template
5
- #
6
- # It's used when a layout doesn't have an associated template.
7
- #
8
- # A common scenario is for non-html requests.
9
- # Usually we have a template for the application layout
10
- # (eg `templates/application.html.erb`), but we don't use to have the
11
- # template for JSON requests (eg `templates/application.json.erb`).
12
- # Because most of the times, we only return the output of the view.
13
- #
14
- # @api private
15
- # @since 0.1.0
16
- #
17
- # @example
18
- # require 'hanami/view'
19
- #
20
- # # We have an ApplicationLayout (views/application_layout.rb):
21
- # class ApplicationLayout
22
- # include Hanami::Layout
23
- # end
24
- #
25
- # # Our layout has a template for HTML requests, located at:
26
- # # templates/application.html.erb
27
- #
28
- # # We set it as global layout
29
- # Hanami::View.layout = :application
30
- #
31
- # # We have two views for HTML and JSON articles.
32
- # # They have a template each:
33
- # #
34
- # # * templates/articles/show.html.erb
35
- # # * templates/articles/show.json.erb
36
- # module Articles
37
- # class Show
38
- # include Hanami::View
39
- # format :html
40
- # end
41
- #
42
- # class JsonShow < Show
43
- # format :json
44
- # end
45
- # end
46
- #
47
- # # We initialize the framework
48
- # Hanami::View.load!
49
- #
50
- #
51
- #
52
- # # When we ask for a HTML rendering, it will use `Articles::Show` and
53
- # # ApplicationLayout. The output will be a composition of:
54
- # #
55
- # # * templates/articles/show.html.erb
56
- # # * templates/application.html.erb
57
- #
58
- # # When we ask for a JSON rendering, it will use `Articles::JsonShow`
59
- # # and ApplicationLayout. Since, the layout doesn't have any associated
60
- # # template for JSON, the output will be a composition of:
61
- # #
62
- # # * templates/articles/show.json.erb
63
- class NullTemplate
64
- # Render the layout template
65
- #
66
- # @param scope [Hanami::View::Scope] the rendering scope
67
- # @param locals [Hash] a set of objects available during the rendering
68
- # @yield [Proc] yields the given block
69
- #
70
- # @return [String] the output of the rendering process
71
- #
72
- # @api private
73
- # @since 0.1.0
74
- #
75
- # @see Hanami::Layout#render
76
- # @see Hanami::View::Rendering#render
77
- def render(scope, locals = {})
78
- yield
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- module View
5
- module Rendering
6
- # Rendering options
7
- #
8
- # @since 1.1.1
9
- # @api private
10
- class Options
11
- # @since 1.1.1
12
- # @api private
13
- def self.build(options, locals, format)
14
- options.dup.tap do |opts|
15
- opts[:format] ||= format
16
- opts[:locals] = locals
17
- opts[:locals].merge!(options.fetch(:locals) { ::Hash.new })
18
- opts[:locals].merge!(format: opts.fetch(:format, format))
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,31 +0,0 @@
1
- require 'hanami/view/rendering/partial_finder'
2
-
3
- module Hanami
4
- module View
5
- module Rendering
6
- # Rendering partial
7
- #
8
- # It's used when a template wants to render a partial.
9
- #
10
- # @api private
11
- # @since 0.1.0
12
- #
13
- # @see Hanami::View::Rendering::Template
14
- # @see Hanami::View::Rendering::LayoutScope#render
15
- #
16
- # @example
17
- # # We have an application template (templates/application.html.erb)
18
- # # that uses the following line:
19
- #
20
- # <%= render partial: 'shared/sidebar' %>
21
- class Partial < Template
22
- protected
23
- # @api private
24
- # @since 0.1.0
25
- def template
26
- PartialFinder.new(@view.class, @options).find
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,29 +0,0 @@
1
- module Hanami
2
- module View
3
- module Rendering
4
- # @since 0.7.0
5
- # @api private
6
- class PartialFile
7
- # @since 0.7.0
8
- # @api private
9
- attr_reader :key
10
-
11
- # @since 0.7.0
12
- # @api private
13
- attr_reader :format
14
-
15
- # @since 0.7.0
16
- # @api private
17
- attr_reader :template
18
-
19
- # @since 0.7.0
20
- # @api private
21
- def initialize(key, format, template)
22
- @key = key
23
- @format = format
24
- @template = template
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,75 +0,0 @@
1
- require 'hanami/view/rendering/template_finder'
2
-
3
- module Hanami
4
- module View
5
- module Rendering
6
- # Find a partial for the current view context.
7
- # It's used when a template wants to render a partial.
8
- #
9
- # @see Hanami::View::Rendering::Partial
10
- # @see Hanami::View::Rendering::TemplateFinder
11
- #
12
- # @api private
13
- # @since 0.1.0
14
- class PartialFinder < TemplateFinder
15
- # Template file name prefix.
16
- # By convention a partial file name starts with this prefix.
17
- #
18
- # @api private
19
- # @since 0.1.0
20
- #
21
- # @example
22
- # "_sidebar.html.erb"
23
- PREFIX = '_'.freeze
24
-
25
- # Find a template for a partial. Initially it will look for the
26
- # partial template in the framework configuration where it may
27
- # already be cached. Failing that it will look under the
28
- # directory of the parent directory view template, if not found
29
- # it will search recursively from the view root.
30
- #
31
- # @return [Hanami::View::Template] the requested template
32
- #
33
- # @see Hanami::View::Rendering::TemplateFinder#find
34
- #
35
- # @since 0.4.3
36
- # @api private
37
- def find
38
- Hanami::View::Configuration.for(@view).
39
- find_partial(relative_partial_path, template_name, format)
40
- end
41
-
42
- protected
43
-
44
- # @since 0.7.0
45
- # @api private
46
- def relative_partial_path
47
- [view_template_dir, template_name].join(separator)
48
- end
49
-
50
- # @since 0.4.3
51
- # @api private
52
- def view_template_dir
53
- *all, _ = @view.template.split(separator)
54
- all.join(separator)
55
- end
56
-
57
- # @api private
58
- def template_name
59
- *all, last = partial_name.split(separator)
60
- all.push( last.prepend(prefix) ).join(separator)
61
- end
62
-
63
- # @api private
64
- def partial_name
65
- @options[:partial]
66
- end
67
-
68
- # @api private
69
- def prefix
70
- PREFIX
71
- end
72
- end
73
- end
74
- end
75
- end
@@ -1,73 +0,0 @@
1
- require 'hanami/view/template'
2
- require 'hanami/view/rendering/partial_file'
3
-
4
- module Hanami
5
- module View
6
- module Rendering
7
- # Find partial templates in the file system
8
- #
9
- # @api private
10
- # @since 0.7.0
11
- #
12
- # @see View::Template
13
- class PartialTemplatesFinder
14
- # Search pattern for partial file names
15
- #
16
- # @api private
17
- # @since 0.7.0
18
- PARTIAL_PATTERN = '_*'.freeze
19
-
20
- # @api private
21
- # @since 0.7.0
22
- PARTIAL_PARTS_SEPARATOR = '.'.freeze
23
-
24
- # @api private
25
- # @since 0.7.0
26
- attr_reader :configuration
27
-
28
- # Initializes a new PartialTemplatesFinder
29
- #
30
- # @param configuration [Configuration] the configuration object
31
- #
32
- # @since 0.7.0
33
- # @api private
34
- def initialize(configuration)
35
- @configuration = configuration
36
- end
37
-
38
- # Find partials under the given path
39
- #
40
- # @return [Array] array of PartialFinder objects
41
- #
42
- # @since 0.7.0
43
- # @api private
44
- def find
45
- _find_partials(configuration.root).map do |template|
46
- partial_path, partial_base_name = Pathname(template).relative_path_from(configuration.root).split
47
- partial_base_parts = partial_base_name.to_s.split(PARTIAL_PARTS_SEPARATOR)
48
-
49
- PartialFile.new(
50
- "#{partial_path}#{::File::SEPARATOR}#{partial_base_parts[0]}",
51
- partial_base_parts[1],
52
- View::Template.new(template, configuration.default_encoding)
53
- )
54
- end
55
- end
56
-
57
- private
58
-
59
- # Find partial template file paths
60
- #
61
- # @param path [String] the path under which we should search for partials
62
- #
63
- # @return [Array] an array of strings for each matching partial template file found
64
- #
65
- # @since 0.7.0
66
- # @api private
67
- def _find_partials(path)
68
- Dir.glob("#{ [path, TemplatesFinder::RECURSIVE, PARTIAL_PATTERN].join(::File::SEPARATOR) }.#{TemplatesFinder::FORMAT}.#{TemplatesFinder::ENGINES}")
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,134 +0,0 @@
1
- require 'hanami/view/rendering/layout_registry'
2
- require 'hanami/view/rendering/view_finder'
3
-
4
- module Hanami
5
- module View
6
- module Rendering
7
- # Holds all the references of all the registered subclasses of a view.
8
- # We have one registry for each superclass view.
9
- #
10
- # @api private
11
- # @since 0.1.0
12
- #
13
- # @see Hanami::View::Rendering::LayoutRegistry
14
- # @see Hanami::View::Rendering#registry
15
- #
16
- # @example
17
- # require 'hanami/view'
18
- #
19
- # module Articles
20
- # class Index
21
- # include Hanami::View
22
- # end
23
- #
24
- # class Show
25
- # include Hanami::View
26
- # end
27
- #
28
- # class JsonShow < Show
29
- # format :json
30
- # end
31
- #
32
- # class XmlShow < Show
33
- # format :xml
34
- #
35
- # def render
36
- # ArticleSerializer.new(article).to_xml
37
- # end
38
- # end
39
- # end
40
- #
41
- # # We have the following templates:
42
- # #
43
- # # * articles/index.html.erb
44
- # # * articles/index.atom.erb
45
- # # * articles/show.html.erb
46
- # # * articles/show.json.erb
47
- #
48
- # # One registry per superclass view
49
- # Articles::Index.send(:registry).object_id # => 70135342862240
50
- #
51
- # Articles::Show.send(:registry).object_id # => 70135342110540
52
- # Articles::XmlShow.send(:registry).object_id # => 70135342110540
53
- # Articles::JsonShow.send(:registry).object_id # => 70135342110540
54
- #
55
- #
56
- #
57
- # # It holds the references for all the templates and the views
58
- # Articles::Index.send(:registry).inspect
59
- # # => { :all => [Articles::Index, nil],
60
- # # :atom => [Articles::Index, #<Hanami::View::Template ... @file="/path/to/templates/articles/index.atom.erb"],
61
- # # :html => [Articles::Index, #<Hanami::View::Template ... @file="/path/to/templates/articles/index.html.erb"] }
62
- #
63
- # Articles::Show.send(:registry).inspect
64
- # # => { :all => [Articles::Show, nil],
65
- # # :html => [Articles::Show, #<Hanami::View::Template ... @file="/path/to/templates/articles/show.html.erb"],
66
- # # :json => [Articles::JsonShow, #<Hanami::View::Template ... @file="/path/to/templates/articles/show.json.erb"],
67
- # # :xml => [Articles::XmlShow, nil] }
68
- class Registry < LayoutRegistry
69
- # Default format for views without an explicit format.
70
- #
71
- # @api private
72
- # @since 0.1.0
73
- #
74
- # @see Hanami::View::Dsl#format
75
- DEFAULT_FORMAT = :all
76
-
77
- # Returns the view for the given context.
78
- #
79
- # @param context [Hash] the rendering context
80
- # @option context [Symbol] :format the requested format
81
- #
82
- # @return [Hanami::View] the view associated with the given context
83
- #
84
- # @raise [Hanami::View::MissingFormatError] if the given context doesn't
85
- # have the :format key
86
- #
87
- # @api private
88
- # @since 0.1.0
89
- #
90
- # @see Hanami::View::Rendering#render
91
- def resolve(context)
92
- view, template = @registry.fetch(format(context)) { @registry[DEFAULT_FORMAT] }
93
- view.new(template, context)
94
- end
95
-
96
- private
97
- # @api private
98
- def prepare!
99
- prepare_views!
100
- prepare_templates!
101
- end
102
-
103
- # @api private
104
- def prepare_views!
105
- views.each do |view|
106
- @registry.merge! view.format || DEFAULT_FORMAT => [ view, template_for(view) ]
107
- end
108
- end
109
-
110
- # @api private
111
- def prepare_templates!
112
- templates.each do |template|
113
- @registry.merge! template.format => [ view_for(template), template ]
114
- end
115
- end
116
-
117
- # @api private
118
- def views
119
- @view.subclasses + [ @view ]
120
- end
121
-
122
- # @api private
123
- def view_for(template)
124
- ViewFinder.new(@view).find(template)
125
- end
126
-
127
- # @api private
128
- def template_for(view)
129
- templates.find {|template| template.format == view.format }
130
- end
131
- end
132
- end
133
- end
134
- end