lotus-view 0.1.0 → 0.2.0
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 +105 -0
- data/{LICENSE.txt → LICENSE.md} +0 -0
- data/README.md +117 -28
- data/lib/lotus/layout.rb +11 -4
- data/lib/lotus/view/configuration.rb +298 -0
- data/lib/lotus/view/dsl.rb +89 -10
- data/lib/lotus/view/inheritable.rb +4 -0
- data/lib/lotus/view/rendering/layout_finder.rb +31 -7
- data/lib/lotus/view/rendering/layout_scope.rb +2 -2
- data/lib/lotus/view/rendering/registry.rb +0 -1
- data/lib/lotus/view/rendering/scope.rb +2 -2
- data/lib/lotus/view/rendering/template_name.rb +37 -0
- data/lib/lotus/view/rendering/templates_finder.rb +36 -5
- data/lib/lotus/view/version.rb +1 -1
- data/lib/lotus/view.rb +196 -88
- data/lotus-view.gemspec +2 -2
- metadata +9 -67
- data/.gitignore +0 -8
- data/.travis.yml +0 -6
- data/.yardopts +0 -3
- data/Gemfile +0 -15
- data/Rakefile +0 -17
- data/test/fixtures/templates/app/app_view.html.erb +0 -0
- data/test/fixtures/templates/app/view.html.erb +0 -0
- data/test/fixtures/templates/application.html.erb +0 -10
- data/test/fixtures/templates/articles/_form.html.erb +0 -4
- data/test/fixtures/templates/articles/alternative_new.html.erb +0 -1
- data/test/fixtures/templates/articles/index.atom.erb +0 -5
- data/test/fixtures/templates/articles/index.html.erb +0 -3
- data/test/fixtures/templates/articles/index.json.erb +0 -9
- data/test/fixtures/templates/articles/index.rss.erb +0 -0
- data/test/fixtures/templates/articles/new.html.erb +0 -7
- data/test/fixtures/templates/articles/show.html.erb +0 -1
- data/test/fixtures/templates/articles/show.json.erb +0 -5
- data/test/fixtures/templates/contacts/show.html.haml +0 -1
- data/test/fixtures/templates/dashboard/index.html.erb +0 -2
- data/test/fixtures/templates/hello_world_view.html.erb +0 -1
- data/test/fixtures/templates/index_view.html.erb +0 -1
- data/test/fixtures/templates/json_render_view.json.erb +0 -3
- data/test/fixtures/templates/render_view.html.erb +0 -1
- data/test/fixtures/templates/shared/_sidebar.html.erb +0 -1
- data/test/fixtures.rb +0 -187
- data/test/layout_test.rb +0 -10
- data/test/load_test.rb +0 -79
- data/test/presenter_test.rb +0 -31
- data/test/rendering_test.rb +0 -125
- data/test/root_test.rb +0 -38
- data/test/test_helper.rb +0 -24
- data/test/version_test.rb +0 -7
- data/test/view_test.rb +0 -27
@@ -0,0 +1,298 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'lotus/utils/class'
|
3
|
+
require 'lotus/utils/kernel'
|
4
|
+
require 'lotus/utils/string'
|
5
|
+
require 'lotus/utils/load_paths'
|
6
|
+
require 'lotus/view/rendering/layout_finder'
|
7
|
+
|
8
|
+
module Lotus
|
9
|
+
module View
|
10
|
+
# Configuration for the framework, controllers and actions.
|
11
|
+
#
|
12
|
+
# Lotus::Controller has its own global configuration that can be manipulated
|
13
|
+
# via `Lotus::View.configure`.
|
14
|
+
#
|
15
|
+
# Every time that `Lotus::View` and `Lotus::Layout` are included, that
|
16
|
+
# global configuration is being copied to the recipient. The copy will
|
17
|
+
# inherit all the settings from the original, but all the subsequent changes
|
18
|
+
# aren't reflected from the parent to the children, and viceversa.
|
19
|
+
#
|
20
|
+
# This architecture allows to have a global configuration that capture the
|
21
|
+
# most common cases for an application, and let views and layouts
|
22
|
+
# layouts to specify exceptions.
|
23
|
+
#
|
24
|
+
# @since 0.2.0
|
25
|
+
class Configuration
|
26
|
+
# Default root
|
27
|
+
#
|
28
|
+
# @since 0.2.0
|
29
|
+
# @api private
|
30
|
+
DEFAULT_ROOT = '.'.freeze
|
31
|
+
|
32
|
+
attr_reader :load_paths
|
33
|
+
attr_reader :views
|
34
|
+
attr_reader :layouts
|
35
|
+
|
36
|
+
# Return the original configuration of the framework instance associated
|
37
|
+
# with the given class.
|
38
|
+
#
|
39
|
+
# When multiple instances of Lotus::View are used in the same application,
|
40
|
+
# we want to make sure that a controller or an action will receive the
|
41
|
+
# expected configuration.
|
42
|
+
#
|
43
|
+
# @param base [Class] a view or a layout
|
44
|
+
#
|
45
|
+
# @return [Lotus::Controller::Configuration] the configuration associated
|
46
|
+
# to the given class.
|
47
|
+
#
|
48
|
+
# @since 0.2.0
|
49
|
+
# @api private
|
50
|
+
#
|
51
|
+
# @example Direct usage of the framework
|
52
|
+
# require 'lotus/view'
|
53
|
+
#
|
54
|
+
# class Show
|
55
|
+
# include Lotus::View
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# Lotus::View::Configuration.for(Show)
|
59
|
+
# # => will return from Lotus::View
|
60
|
+
#
|
61
|
+
# @example Multiple instances of the framework
|
62
|
+
# require 'lotus/view'
|
63
|
+
#
|
64
|
+
# module MyApp
|
65
|
+
# View = Lotus::View.duplicate(self)
|
66
|
+
#
|
67
|
+
# module Views::Dashboard
|
68
|
+
# class Index
|
69
|
+
# include MyApp::View
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# class Show
|
75
|
+
# include Lotus::Action
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# Lotus::View::Configuration.for(Show)
|
79
|
+
# # => will return from Lotus::View
|
80
|
+
#
|
81
|
+
# Lotus::View::Configuration.for(MyApp::Views::Dashboard::Index)
|
82
|
+
# # => will return from MyApp::View
|
83
|
+
def self.for(base)
|
84
|
+
# TODO this implementation is similar to Lotus::Controller::Configuration consider to extract it into Lotus::Utils
|
85
|
+
namespace = Utils::String.new(base).namespace
|
86
|
+
framework = Utils::Class.load!("(#{namespace}|Lotus)::View")
|
87
|
+
framework.configuration
|
88
|
+
end
|
89
|
+
|
90
|
+
# Initialize a configuration instance
|
91
|
+
#
|
92
|
+
# @return [Lotus::View::Configuration] a new configuration's instance
|
93
|
+
#
|
94
|
+
# @since 0.2.0
|
95
|
+
def initialize
|
96
|
+
@namespace = Object
|
97
|
+
reset!
|
98
|
+
end
|
99
|
+
|
100
|
+
# Set the Ruby namespace where to lookup for views.
|
101
|
+
#
|
102
|
+
# When multiple instances of the framework are used, we want to make sure
|
103
|
+
# that if a `MyApp` wants a `Dashboard::Index` view, we are loading the
|
104
|
+
# right one.
|
105
|
+
#
|
106
|
+
# If not set, this value defaults to `Object`.
|
107
|
+
#
|
108
|
+
# This is part of a DSL, for this reason when this method is called with
|
109
|
+
# an argument, it will set the corresponding instance variable. When
|
110
|
+
# called without, it will return the already set value, or the default.
|
111
|
+
#
|
112
|
+
# @overload namespace(value)
|
113
|
+
# Sets the given value
|
114
|
+
# @param value [Class, Module, String] a valid Ruby namespace identifier
|
115
|
+
#
|
116
|
+
# @overload namespace
|
117
|
+
# Gets the value
|
118
|
+
# @return [Class, Module, String]
|
119
|
+
#
|
120
|
+
# @since 0.2.0
|
121
|
+
#
|
122
|
+
# @example Getting the value
|
123
|
+
# require 'lotus/view'
|
124
|
+
#
|
125
|
+
# Lotus::View.configuration.namespace # => Object
|
126
|
+
#
|
127
|
+
# @example Setting the value
|
128
|
+
# require 'lotus/view'
|
129
|
+
#
|
130
|
+
# Lotus::View.configure do
|
131
|
+
# namespace 'MyApp::Views'
|
132
|
+
# end
|
133
|
+
def namespace(value = nil)
|
134
|
+
if value
|
135
|
+
@namespace = value
|
136
|
+
else
|
137
|
+
@namespace
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Set the root path where to search for templates
|
142
|
+
#
|
143
|
+
# If not set, this value defaults to the current directory.
|
144
|
+
#
|
145
|
+
# This is part of a DSL, for this reason when this method is called with
|
146
|
+
# an argument, it will set the corresponding instance variable. When
|
147
|
+
# called without, it will return the already set value, or the default.
|
148
|
+
#
|
149
|
+
# @overload root(value)
|
150
|
+
# Sets the given value
|
151
|
+
# @param value [String,Pathname,#to_pathname] an object that can be
|
152
|
+
# coerced to Pathname
|
153
|
+
# @raise [Errno::ENOENT] if the given path doesn't exist
|
154
|
+
#
|
155
|
+
# @overload root
|
156
|
+
# Gets the value
|
157
|
+
# @return [Pathname]
|
158
|
+
#
|
159
|
+
# @since 0.2.0
|
160
|
+
#
|
161
|
+
# @see Lotus::View::Dsl#root
|
162
|
+
# @see http://www.ruby-doc.org/stdlib-2.1.2/libdoc/pathname/rdoc/Pathname.html
|
163
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Pathname-class_method
|
164
|
+
#
|
165
|
+
# @example Getting the value
|
166
|
+
# require 'lotus/view'
|
167
|
+
#
|
168
|
+
# Lotus::View.configuration.root # => #<Pathname:.>
|
169
|
+
#
|
170
|
+
# @example Setting the value
|
171
|
+
# require 'lotus/view'
|
172
|
+
#
|
173
|
+
# Lotus::View.configure do
|
174
|
+
# root '/path/to/templates'
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# Lotus::View.configuration.root # => #<Pathname:/path/to/templates>
|
178
|
+
def root(value = nil)
|
179
|
+
if value
|
180
|
+
@root = Utils::Kernel.Pathname(value).realpath
|
181
|
+
else
|
182
|
+
@root
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Set the global layout
|
187
|
+
#
|
188
|
+
# If not set, this value defaults to `nil`, while at the rendering time
|
189
|
+
# it will use `Lotus::View::Rendering::NullLayout`.
|
190
|
+
#
|
191
|
+
# This is part of a DSL, for this reason when this method is called with
|
192
|
+
# an argument, it will set the corresponding instance variable. When
|
193
|
+
# called without, it will return the already set value, or the default.
|
194
|
+
#
|
195
|
+
# @overload layout(value)
|
196
|
+
# Sets the given value
|
197
|
+
# @param value [Symbol] the name of the layout
|
198
|
+
#
|
199
|
+
# @overload layout
|
200
|
+
# Gets the value
|
201
|
+
# @return [Class]
|
202
|
+
#
|
203
|
+
# @since 0.2.0
|
204
|
+
#
|
205
|
+
# @see Lotus::View::Dsl#layout
|
206
|
+
#
|
207
|
+
# @example Getting the value
|
208
|
+
# require 'lotus/view'
|
209
|
+
#
|
210
|
+
# Lotus::View.configuration.layout # => nil
|
211
|
+
#
|
212
|
+
# @example Setting the value
|
213
|
+
# require 'lotus/view'
|
214
|
+
#
|
215
|
+
# Lotus::View.configure do
|
216
|
+
# layout :application
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# Lotus::View.configuration.layout # => ApplicationLayout
|
220
|
+
#
|
221
|
+
# @example Setting the value in a namespaced app
|
222
|
+
# require 'lotus/view'
|
223
|
+
#
|
224
|
+
# module MyApp
|
225
|
+
# View = Lotus::View.duplicate(self) do
|
226
|
+
# layout :application
|
227
|
+
# end
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# MyApp::View.configuration.layout # => MyApp::ApplicationLayout
|
231
|
+
def layout(value = nil)
|
232
|
+
if value
|
233
|
+
@layout = value
|
234
|
+
else
|
235
|
+
Rendering::LayoutFinder.find(@layout, @namespace)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Add a view to the registry
|
240
|
+
#
|
241
|
+
# @since 0.2.0
|
242
|
+
# @api private
|
243
|
+
def add_view(view)
|
244
|
+
@views.add(view)
|
245
|
+
end
|
246
|
+
|
247
|
+
# Add a layout to the registry
|
248
|
+
#
|
249
|
+
# @since 0.2.0
|
250
|
+
# @api private
|
251
|
+
def add_layout(layout)
|
252
|
+
@layouts.add(layout)
|
253
|
+
end
|
254
|
+
|
255
|
+
# Duplicate by copying the settings in a new instance.
|
256
|
+
#
|
257
|
+
# @return [Lotus::View::Configuration] a copy of the configuration
|
258
|
+
#
|
259
|
+
# @since 0.2.0
|
260
|
+
# @api private
|
261
|
+
def duplicate
|
262
|
+
Configuration.new.tap do |c|
|
263
|
+
c.namespace = namespace
|
264
|
+
c.root = root
|
265
|
+
c.layout = @layout # lazy loading of the class
|
266
|
+
c.load_paths = load_paths.dup
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Load the configuration for the current framework
|
271
|
+
#
|
272
|
+
# @since 0.2.0
|
273
|
+
# @api private
|
274
|
+
def load!
|
275
|
+
views.each {|v| v.__send__(:load!) }
|
276
|
+
layouts.each {|l| l.__send__(:load!) }
|
277
|
+
end
|
278
|
+
|
279
|
+
# Reset all the values to the defaults
|
280
|
+
#
|
281
|
+
# @since 0.2.0
|
282
|
+
# @api private
|
283
|
+
def reset!
|
284
|
+
root(DEFAULT_ROOT)
|
285
|
+
|
286
|
+
@views = Set.new
|
287
|
+
@layouts = Set.new
|
288
|
+
@load_paths = Utils::LoadPaths.new(root)
|
289
|
+
@layout = nil
|
290
|
+
end
|
291
|
+
|
292
|
+
alias_method :unload!, :reset!
|
293
|
+
|
294
|
+
protected
|
295
|
+
attr_writer :namespace, :root, :load_paths, :layout
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
data/lib/lotus/view/dsl.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'lotus/
|
1
|
+
require 'lotus/view/rendering/template_name'
|
2
2
|
require 'lotus/view/rendering/layout_finder'
|
3
3
|
|
4
4
|
module Lotus
|
@@ -27,8 +27,8 @@ module Lotus
|
|
27
27
|
# end
|
28
28
|
# end
|
29
29
|
#
|
30
|
-
# Lotus::View.root
|
31
|
-
# Articles::Show.root
|
30
|
+
# Lotus::View.configuration.root # => 'app/templates'
|
31
|
+
# Articles::Show.root # => 'app/templates'
|
32
32
|
#
|
33
33
|
# @example Custom root
|
34
34
|
# require 'lotus/view'
|
@@ -40,13 +40,13 @@ module Lotus
|
|
40
40
|
# end
|
41
41
|
# end
|
42
42
|
#
|
43
|
-
# Lotus::View.root
|
44
|
-
# Articles::Show.root
|
43
|
+
# Lotus::View.configuration.root # => 'app/templates'
|
44
|
+
# Articles::Show.root # => 'path/to/articles/templates'
|
45
45
|
def root(value = nil)
|
46
46
|
if value
|
47
|
-
|
47
|
+
configuration.root(value)
|
48
48
|
else
|
49
|
-
|
49
|
+
configuration.root
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -124,11 +124,90 @@ module Lotus
|
|
124
124
|
#
|
125
125
|
# Articles::Show.template # => 'articles/single_article'
|
126
126
|
# Articles::JsonShow.template # => 'articles/single_article'
|
127
|
+
#
|
128
|
+
# @example With namespace
|
129
|
+
# require 'lotus/view'
|
130
|
+
#
|
131
|
+
# module Furnitures
|
132
|
+
# View = Lotus::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 'lotus/view'
|
150
|
+
#
|
151
|
+
# module Frontend
|
152
|
+
# View = Lotus::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 'lotus/view'
|
177
|
+
#
|
178
|
+
# module Bookshelf
|
179
|
+
# module Web
|
180
|
+
# View = Lotus::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 = Lotus::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'
|
127
206
|
def template(value = nil)
|
128
207
|
if value
|
129
208
|
@@template = value
|
130
209
|
else
|
131
|
-
@@template ||=
|
210
|
+
@@template ||= Rendering::TemplateName.new(name, configuration.namespace).to_s
|
132
211
|
end
|
133
212
|
end
|
134
213
|
|
@@ -219,7 +298,7 @@ module Lotus
|
|
219
298
|
if value
|
220
299
|
@layout = value
|
221
300
|
else
|
222
|
-
@layout
|
301
|
+
@layout ||= configuration.layout
|
223
302
|
end
|
224
303
|
end
|
225
304
|
|
@@ -239,7 +318,7 @@ module Lotus
|
|
239
318
|
v.format.freeze
|
240
319
|
v.template.freeze
|
241
320
|
v.layout(Rendering::LayoutFinder.new(v).find)
|
242
|
-
v.layout
|
321
|
+
v.layout#.freeze
|
243
322
|
end
|
244
323
|
end
|
245
324
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'lotus/utils/string'
|
2
|
+
require 'lotus/utils/class'
|
3
|
+
require 'lotus/view/rendering/null_layout'
|
2
4
|
|
3
5
|
module Lotus
|
4
6
|
module View
|
@@ -21,6 +23,8 @@ module Lotus
|
|
21
23
|
# @param layout [Symbol,String,NilClass] layout name or nil if you want
|
22
24
|
# to fallback to the framework defaults (see `Lotus::View.layout`).
|
23
25
|
#
|
26
|
+
# @param namespace [Class,Module] a Ruby namespace where to lookup
|
27
|
+
#
|
24
28
|
# @return [Lotus::Layout] the layout for the given name or
|
25
29
|
# `Lotus::View.layout`
|
26
30
|
#
|
@@ -33,20 +37,40 @@ module Lotus
|
|
33
37
|
# Lotus::View::Rendering::LayoutFinder.find(:article) # =>
|
34
38
|
# ArticleLayout
|
35
39
|
#
|
40
|
+
# @example With a class
|
41
|
+
# require 'lotus/view'
|
42
|
+
#
|
43
|
+
# Lotus::View::Rendering::LayoutFinder.find(ArticleLayout) # =>
|
44
|
+
# ArticleLayout
|
45
|
+
#
|
46
|
+
# @example With namespace
|
47
|
+
# require 'lotus/view'
|
48
|
+
#
|
49
|
+
# Lotus::View::Rendering::LayoutFinder.find(:application, CardDeck) # =>
|
50
|
+
# CardDeck::ApplicationLayout
|
51
|
+
#
|
36
52
|
# @example With nil
|
37
53
|
# require 'lotus/view'
|
38
54
|
#
|
39
|
-
# Lotus::View.layout # => :application
|
40
55
|
# Lotus::View::Rendering::LayoutFinder.find(nil) # =>
|
41
|
-
#
|
42
|
-
|
56
|
+
# Lotus::View::Rendering::NullLayout
|
57
|
+
#
|
58
|
+
# @example With unknown layout
|
59
|
+
# require 'lotus/view'
|
60
|
+
#
|
61
|
+
# Lotus::View::Rendering::LayoutFinder.find(:unknown) # =>
|
62
|
+
# Lotus::View::Rendering::NullLayout
|
63
|
+
#
|
64
|
+
def self.find(layout, namespace = Object)
|
43
65
|
case layout
|
44
66
|
when Symbol, String
|
67
|
+
# TODO Move this low level logic into a Lotus::Utils solution
|
45
68
|
class_name = "#{ Utils::String.new(layout).classify }#{ SUFFIX }"
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
69
|
+
namespace = Utils::Class.load!(namespace)
|
70
|
+
namespace.const_get(class_name)
|
71
|
+
when Class
|
72
|
+
layout
|
73
|
+
end || NullLayout
|
50
74
|
end
|
51
75
|
|
52
76
|
# Initialize the finder
|
@@ -128,8 +128,8 @@ module Lotus
|
|
128
128
|
def _options(options)
|
129
129
|
options.dup.tap do |opts|
|
130
130
|
opts.merge!(format: format)
|
131
|
-
opts[:locals]
|
132
|
-
opts[:locals].merge!(locals)
|
131
|
+
opts[:locals] = locals
|
132
|
+
opts[:locals].merge!(options.fetch(:locals){ Hash[] })
|
133
133
|
end
|
134
134
|
end
|
135
135
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'lotus/utils/string'
|
2
|
+
|
3
|
+
module Lotus
|
4
|
+
module View
|
5
|
+
module Rendering
|
6
|
+
# @since 0.2.0
|
7
|
+
class TemplateName
|
8
|
+
NAMESPACE_SEPARATOR = '::'.freeze
|
9
|
+
|
10
|
+
def initialize(name, namespace)
|
11
|
+
@name = name
|
12
|
+
compile!(namespace)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
@name
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def compile!(namespace)
|
21
|
+
tokens(namespace) {|token| replace!(token) }
|
22
|
+
@name = Utils::String.new(@name).underscore
|
23
|
+
end
|
24
|
+
|
25
|
+
def tokens(namespace)
|
26
|
+
namespace.to_s.split(NAMESPACE_SEPARATOR).each do |token|
|
27
|
+
yield token
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def replace!(token)
|
32
|
+
@name.gsub!(%r{\A#{ token }#{ NAMESPACE_SEPARATOR }}, '')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -10,8 +10,23 @@ module Lotus
|
|
10
10
|
#
|
11
11
|
# @see View::Template
|
12
12
|
class TemplatesFinder
|
13
|
-
|
14
|
-
|
13
|
+
# Default format
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
# @since 0.1.0
|
17
|
+
FORMAT = '*'.freeze
|
18
|
+
|
19
|
+
# Default template engines
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.1.0
|
23
|
+
ENGINES = '*'.freeze
|
24
|
+
|
25
|
+
# Recursive pattern
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
# @since 0.2.0
|
29
|
+
RECURSIVE = '**'.freeze
|
15
30
|
|
16
31
|
# Initialize a finder
|
17
32
|
#
|
@@ -24,8 +39,8 @@ module Lotus
|
|
24
39
|
end
|
25
40
|
|
26
41
|
# Find all the associated templates to the view.
|
27
|
-
# It looks for templates under the root path of the view,
|
28
|
-
# matching the template name
|
42
|
+
# It recursively looks for templates under the root path of the view,
|
43
|
+
# that are matching the template name
|
29
44
|
#
|
30
45
|
# @return [Array<Lotus::View::Template>] the templates
|
31
46
|
#
|
@@ -54,28 +69,44 @@ module Lotus
|
|
54
69
|
# Lotus::View::Rendering::TemplatesFinder.new(Articles::Show).find
|
55
70
|
# # => [#<Lotus::View::Template:0x007f8a0a86a970 ... @file="/path/to/templates/articles/show.html.erb">]
|
56
71
|
def find
|
57
|
-
Dir.glob( "#{ [root, template_name].join(separator) }.#{ format }.#{ engines }" ).map do |template|
|
72
|
+
Dir.glob( "#{ [root, recursive, template_name].join(separator) }.#{ format }.#{ engines }" ).map do |template|
|
58
73
|
View::Template.new template
|
59
74
|
end
|
60
75
|
end
|
61
76
|
|
62
77
|
protected
|
78
|
+
# @api private
|
79
|
+
# @since 0.1.0
|
63
80
|
def template_name
|
64
81
|
@view.template
|
65
82
|
end
|
66
83
|
|
84
|
+
# @api private
|
85
|
+
# @since 0.1.0
|
67
86
|
def root
|
68
87
|
@view.root
|
69
88
|
end
|
70
89
|
|
90
|
+
# @api private
|
91
|
+
# @since 0.2.0
|
92
|
+
def recursive
|
93
|
+
RECURSIVE
|
94
|
+
end
|
95
|
+
|
96
|
+
# @api private
|
97
|
+
# @since 0.1.0
|
71
98
|
def separator
|
72
99
|
::File::SEPARATOR
|
73
100
|
end
|
74
101
|
|
102
|
+
# @api private
|
103
|
+
# @since 0.1.0
|
75
104
|
def format
|
76
105
|
FORMAT
|
77
106
|
end
|
78
107
|
|
108
|
+
# @api private
|
109
|
+
# @since 0.1.0
|
79
110
|
def engines
|
80
111
|
ENGINES
|
81
112
|
end
|