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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/LICENSE +20 -0
- data/README.md +20 -862
- data/hanami-view.gemspec +26 -16
- data/lib/hanami-view.rb +3 -1
- data/lib/hanami/view.rb +208 -223
- data/lib/hanami/view/application_configuration.rb +77 -0
- data/lib/hanami/view/application_context.rb +35 -0
- data/lib/hanami/view/application_view.rb +89 -0
- data/lib/hanami/view/context.rb +97 -0
- data/lib/hanami/view/context_helpers/content_helpers.rb +26 -0
- data/lib/hanami/view/decorated_attributes.rb +82 -0
- data/lib/hanami/view/errors.rb +19 -56
- data/lib/hanami/view/exposure.rb +126 -0
- data/lib/hanami/view/exposures.rb +74 -0
- data/lib/hanami/view/part.rb +217 -0
- data/lib/hanami/view/part_builder.rb +140 -0
- data/lib/hanami/view/path.rb +68 -0
- data/lib/hanami/view/render_environment.rb +62 -0
- data/lib/hanami/view/render_environment_missing.rb +44 -0
- data/lib/hanami/view/rendered.rb +55 -0
- data/lib/hanami/view/renderer.rb +79 -0
- data/lib/hanami/view/scope.rb +189 -0
- data/lib/hanami/view/scope_builder.rb +98 -0
- data/lib/hanami/view/standalone_view.rb +396 -0
- data/lib/hanami/view/tilt.rb +78 -0
- data/lib/hanami/view/tilt/erb.rb +26 -0
- data/lib/hanami/view/tilt/erbse.rb +21 -0
- data/lib/hanami/view/tilt/haml.rb +26 -0
- data/lib/hanami/view/version.rb +5 -5
- metadata +113 -63
- data/LICENSE.md +0 -22
- data/lib/hanami/layout.rb +0 -172
- data/lib/hanami/presenter.rb +0 -98
- data/lib/hanami/view/configuration.rb +0 -504
- data/lib/hanami/view/dsl.rb +0 -347
- data/lib/hanami/view/escape.rb +0 -225
- data/lib/hanami/view/inheritable.rb +0 -54
- data/lib/hanami/view/rendering.rb +0 -294
- data/lib/hanami/view/rendering/layout_finder.rb +0 -128
- data/lib/hanami/view/rendering/layout_registry.rb +0 -69
- data/lib/hanami/view/rendering/layout_scope.rb +0 -274
- data/lib/hanami/view/rendering/null_layout.rb +0 -52
- data/lib/hanami/view/rendering/null_local.rb +0 -82
- data/lib/hanami/view/rendering/null_template.rb +0 -83
- data/lib/hanami/view/rendering/options.rb +0 -24
- data/lib/hanami/view/rendering/partial.rb +0 -31
- data/lib/hanami/view/rendering/partial_file.rb +0 -29
- data/lib/hanami/view/rendering/partial_finder.rb +0 -75
- data/lib/hanami/view/rendering/partial_templates_finder.rb +0 -73
- data/lib/hanami/view/rendering/registry.rb +0 -134
- data/lib/hanami/view/rendering/scope.rb +0 -108
- data/lib/hanami/view/rendering/subscope.rb +0 -56
- data/lib/hanami/view/rendering/template.rb +0 -69
- data/lib/hanami/view/rendering/template_finder.rb +0 -55
- data/lib/hanami/view/rendering/template_name.rb +0 -50
- data/lib/hanami/view/rendering/templates_finder.rb +0 -144
- data/lib/hanami/view/rendering/view_finder.rb +0 -37
- 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
|