roger 1.6.4 → 1.7.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/CHANGELOG.md +12 -0
  4. data/Gemfile +4 -3
  5. data/Rakefile +1 -0
  6. data/doc/cli.md +12 -1
  7. data/doc/templating.md +9 -0
  8. data/lib/roger/cli/serve.rb +12 -8
  9. data/lib/roger/cli.rb +78 -5
  10. data/lib/roger/helpers/registration.rb +33 -0
  11. data/lib/roger/project.rb +14 -8
  12. data/lib/roger/rack/roger.rb +1 -1
  13. data/lib/roger/release/finalizers/dir.rb +10 -7
  14. data/lib/roger/release/finalizers/git_branch.rb +18 -32
  15. data/lib/roger/release/finalizers/rsync.rb +24 -23
  16. data/lib/roger/release/finalizers/zip.rb +16 -16
  17. data/lib/roger/release/finalizers.rb +3 -19
  18. data/lib/roger/release/processors/mockup.rb +17 -28
  19. data/lib/roger/release/processors/url_relativizer.rb +11 -13
  20. data/lib/roger/release/processors.rb +50 -22
  21. data/lib/roger/release/scm/git.rb +15 -15
  22. data/lib/roger/release.rb +12 -37
  23. data/lib/roger/renderer.rb +16 -8
  24. data/lib/roger/server.rb +59 -3
  25. data/lib/roger/template/helpers/partial.rb +6 -1
  26. data/lib/roger/version.rb +1 -1
  27. data/roger.gemspec +1 -1
  28. data/test/helpers/generators.rb +25 -0
  29. data/test/project/layouts/bracket.html.erb +1 -0
  30. data/test/project/partials/test/locals.html.erb +1 -0
  31. data/test/project/partials/test/max_depth.html.erb +1 -1
  32. data/test/project/partials/test/parent_template.html.erb +1 -0
  33. data/test/unit/cli/cli_base_test.rb +67 -0
  34. data/test/unit/cli/cli_generate_test.rb +0 -20
  35. data/test/unit/cli/cli_serve_test.rb +19 -4
  36. data/test/unit/generators_test.rb +5 -28
  37. data/test/unit/rack/roger_test.rb +19 -3
  38. data/test/unit/release/finalizers/rsync_test.rb +11 -9
  39. data/test/unit/release/processors/mockup_test.rb +12 -0
  40. data/test/unit/release_test.rb +27 -4
  41. data/test/unit/renderer/renderer_base_test.rb +24 -0
  42. data/test/unit/renderer/renderer_layout_test.rb +26 -2
  43. data/test/unit/renderer/renderer_partial_test.rb +12 -2
  44. data/test/unit/server_test.rb +32 -0
  45. data/test/unit/test_helper.rb +2 -7
  46. metadata +13 -4
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + "/../../renderer"
3
3
  module Roger::Release::Processors
4
4
  # The Mockup processor that will process all templates
5
5
  class Mockup < Base
6
- attr_accessor :project
6
+ self.name = :mockup
7
7
 
8
8
  MIME_TYPES_TO_EXTENSION = {
9
9
  "text/html" => "html",
@@ -15,31 +15,31 @@ module Roger::Release::Processors
15
15
  "application/json" => "json"
16
16
  }
17
17
 
18
- def initialize(options = {})
19
- @options = {
18
+ def default_options
19
+ {
20
20
  env: {},
21
21
  match: ["**/*.{html,md,html.erb}"],
22
22
  skip: [/\Astylesheets/, /\Ajavascripts/]
23
23
  }
24
-
25
- @options.update(options) if options
26
24
  end
27
25
 
28
- def call(release, options = {})
29
- self.project = release.project
26
+ def project
27
+ release.project
28
+ end
30
29
 
31
- options = update_call_options(options)
30
+ def perform
31
+ @options[:env].update("roger.project" => project, "MOCKUP_PROJECT" => project)
32
32
 
33
- log_call(release, options)
33
+ log_call
34
34
 
35
- release.get_files(options[:match], options[:skip]).each do |file_path|
35
+ release.get_files(@options[:match], @options[:skip]).each do |file_path|
36
36
  release.log(self, " Extract: #{file_path}", true)
37
37
 
38
38
  # Avoid rendering partials which can also be included
39
39
  # in the roger.base_path
40
40
  next if File.basename(file_path).start_with? "_"
41
41
 
42
- self.run_on_file!(file_path, options[:env])
42
+ run_on_file!(file_path, @options[:env])
43
43
  end
44
44
  end
45
45
 
@@ -62,7 +62,7 @@ module Roger::Release::Processors
62
62
  partials_path: project.partial_path,
63
63
  layouts_path: project.layouts_path
64
64
  )
65
- renderer.render(file_path)
65
+ renderer.render(file_path, project.options[:renderer] || {})
66
66
  end
67
67
 
68
68
  # Determines the output path for a mockup path with a certain template
@@ -92,25 +92,14 @@ module Roger::Release::Processors
92
92
 
93
93
  protected
94
94
 
95
- def update_call_options(options)
96
- updated_options = {}
97
- updated_options.update(@options)
98
-
99
- updated_options.update(options) if options
100
-
101
- updated_options[:env].update("roger.project" => project, "MOCKUP_PROJECT" => project)
102
-
103
- updated_options
104
- end
105
-
106
- def log_call(release, options)
95
+ def log_call
107
96
  release.log(self, "Processing mockup files")
108
97
 
109
- release.log(self, " Matching: #{options[:match].inspect}", true)
110
- release.log(self, " Skiping : #{options[:skip].inspect}", true)
111
- release.log(self, " Env : #{options[:env].inspect}", true)
98
+ release.log(self, " Matching: #{@options[:match].inspect}", true)
99
+ release.log(self, " Skiping : #{@options[:skip].inspect}", true)
100
+ release.log(self, " Env : #{@options[:env].inspect}", true)
112
101
  release.log(self, " Files :", true)
113
102
  end
114
103
  end
115
104
  end
116
- Roger::Release::Processors.register(:mockup, Roger::Release::Processors::Mockup)
105
+ Roger::Release::Processors.register(Roger::Release::Processors::Mockup)
@@ -6,20 +6,18 @@ module Roger::Release::Processors
6
6
  # The relativizer can be used to rewrite absolute paths in attributes to relative paths
7
7
  # during release.
8
8
  class UrlRelativizer < Base
9
- def initialize(options = {})
10
- @options = {
9
+ self.name = :url_relativizer
10
+
11
+ def default_options
12
+ {
11
13
  url_attributes: %w(src href action),
12
14
  match: ["**/*.html"],
13
15
  skip: []
14
16
  }
15
-
16
- @options.update(options) if options
17
17
  end
18
18
 
19
- def call(release, options = {})
20
- options = {}.update(@options).update(options)
21
-
22
- log_call(release, options)
19
+ def perform
20
+ log_call
23
21
 
24
22
  @resolver = Roger::Resolver.new(release.build_path)
25
23
 
@@ -32,10 +30,10 @@ module Roger::Release::Processors
32
30
 
33
31
  protected
34
32
 
35
- def log_call(release, options)
36
- log_message = "Relativizing all URLS in #{options[:match].inspect}"
37
- log_message << "files in attributes #{options[:url_attributes].inspect},"
38
- log_message << "skipping #{options[:skip].any? ? options[:skip].inspect : 'none' }"
33
+ def log_call
34
+ log_message = "Relativizing all URLS in #{@options[:match].inspect}"
35
+ log_message << "files in attributes #{@options[:url_attributes].inspect},"
36
+ log_message << "skipping #{@options[:skip].any? ? @options[:skip].inspect : 'none'}"
39
37
  release.log(self, log_message)
40
38
  end
41
39
 
@@ -73,4 +71,4 @@ module Roger::Release::Processors
73
71
  end
74
72
  end
75
73
 
76
- Roger::Release::Processors.register(:url_relativizer, Roger::Release::Processors::UrlRelativizer)
74
+ Roger::Release::Processors.register(Roger::Release::Processors::UrlRelativizer)
@@ -1,30 +1,58 @@
1
- module Roger
2
- class Release
3
- # The Processors namespace
4
- module Processors
5
- # Abstract Processor class
6
- class Base
7
- def initialize(options = {})
8
- @options = {}
9
- @options.update(options) if options
10
- end
11
-
12
- def call(_release, _options = {})
13
- fail ArgumentError, "Implement in subclass"
14
- end
15
- end
1
+ # Processors can perform any action on a release
2
+ module Roger::Release::Processors
3
+ extend Roger::Helpers::Registration
16
4
 
17
- def self.register(name, processor)
18
- fail ArgumentError, "Processor name '#{name.inspect}' already in use" if map.key?(name)
19
- fail ArgumentError, "Name must be a symbol" unless name.is_a?(Symbol)
20
- map[name] = processor
21
- end
5
+ # Abstract Processor class
6
+ class Base
7
+ attr_reader :options, :release
8
+
9
+ class << self
10
+ attr_writer :name
22
11
 
23
- def self.map
24
- @_map ||= {}
12
+ # Name of this processor
13
+ def name
14
+ @name || fail(ArgumentError, "Implement in subclass")
25
15
  end
26
16
  end
17
+
18
+ # Default options for this processor
19
+ def default_options
20
+ {}
21
+ end
22
+
23
+ # Name of this processor.
24
+ # - Can be set by setting the :name config in the release block
25
+ # - Can be overwritten in implementation if needed
26
+ def name
27
+ options && options[:name] || self.class.name
28
+ end
29
+
30
+ def call(release, options = {})
31
+ @release = release
32
+ @options = {}.update(default_options)
33
+ @options.update(options) if options
34
+ @options.update(my_project_options)
35
+
36
+ # Stop immideatly if we've been disabled
37
+ return if @options[:disable]
38
+
39
+ perform
40
+ end
41
+
42
+ protected
43
+
44
+ # The options passed through the project. This can contain
45
+ # command line options
46
+ def my_project_options
47
+ project_options = release.project.options
48
+ project_options[:release] && project_options[:release][name] || {}
49
+ end
50
+
51
+ def perform
52
+ fail ArgumentError, "Implement in subclass"
53
+ end
27
54
  end
28
55
  end
56
+
29
57
  require File.dirname(__FILE__) + "/processors/mockup"
30
58
  require File.dirname(__FILE__) + "/processors/url_relativizer"
@@ -6,6 +6,20 @@ module Roger
6
6
  module Scm
7
7
  # The GIT SCM implementation for Roger release
8
8
  class Git < Base
9
+ # Find the .git dir in path and all it's parents
10
+ def self.find_git_dir(path)
11
+ path = Pathname.new(path).realpath
12
+ while path.parent != path && !(path + ".git").directory?
13
+ path = path.parent
14
+ end
15
+
16
+ path += ".git"
17
+
18
+ fail "Could not find suitable .git dir in #{path}" unless path.directory?
19
+
20
+ path
21
+ end
22
+
9
23
  # @option config [String] :ref Ref to use for current tag
10
24
  # @option config [String, Pathname] :path Path to working dir
11
25
  def initialize(config = {})
@@ -51,7 +65,7 @@ module Roger
51
65
  end
52
66
 
53
67
  def git_dir
54
- @git_dir ||= find_git_dir(@config[:path])
68
+ @git_dir ||= self.class.find_git_dir(@config[:path])
55
69
  end
56
70
 
57
71
  # Safely escaped git dir
@@ -96,20 +110,6 @@ module Roger
96
110
  rescue RuntimeError
97
111
  nil
98
112
  end
99
-
100
- # Find the git dir
101
- def find_git_dir(path)
102
- path = Pathname.new(path).realpath
103
- while path.parent != path && !(path + ".git").directory?
104
- path = path.parent
105
- end
106
-
107
- path += ".git"
108
-
109
- fail "Could not find suitable .git dir in #{path}" unless path.directory?
110
-
111
- path
112
- end
113
113
  end
114
114
  end
115
115
  end
data/lib/roger/release.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + "/helpers/get_callable"
2
2
  require File.dirname(__FILE__) + "/helpers/get_files"
3
3
  require File.dirname(__FILE__) + "/helpers/logging"
4
+ require File.dirname(__FILE__) + "/helpers/registration"
4
5
 
5
6
  require "shellwords"
6
7
 
@@ -12,18 +13,10 @@ module Roger
12
13
 
13
14
  attr_reader :config, :project
14
15
 
15
- attr_reader :finalizers, :stack
16
+ attr_reader :stack
16
17
 
17
18
  class << self
18
19
  include Roger::Helpers::GetCallable
19
-
20
- def default_stack
21
- []
22
- end
23
-
24
- def default_finalizers
25
- [[get_callable(:dir, Roger::Release::Finalizers.map), {}]]
26
- end
27
20
  end
28
21
 
29
22
  # @option config [:git, :fixed] :scm The SCM to use (default = :git)
@@ -39,7 +32,7 @@ module Roger
39
32
  real_project_path = project.path.realpath
40
33
  defaults = {
41
34
  scm: :git,
42
- source_path: real_project_path + "html",
35
+ source_path: project.html_path.realpath,
43
36
  target_path: real_project_path + "releases",
44
37
  build_path: real_project_path + "build",
45
38
  cp: ["cp", "-RL"],
@@ -51,7 +44,6 @@ module Roger
51
44
 
52
45
  @project = project
53
46
  @stack = []
54
- @finalizers = []
55
47
  end
56
48
 
57
49
  # Accessor for target_path
@@ -121,7 +113,7 @@ module Roger
121
113
  # @examples
122
114
  # release.finalize :zip
123
115
  def finalize(finalizer, options = {})
124
- @finalizers << [self.class.get_callable(finalizer, Roger::Release::Finalizers.map), options]
116
+ @stack << [self.class.get_callable(finalizer, Roger::Release::Finalizers.map), options]
125
117
  end
126
118
 
127
119
  # Files to clean up in the build directory just before finalization happens
@@ -180,9 +172,6 @@ module Roger
180
172
  # Run stack
181
173
  run_stack!
182
174
 
183
- # Run finalizers
184
- run_finalizers!
185
-
186
175
  # Cleanup
187
176
  cleanup! if config[:cleanup_build]
188
177
  ensure
@@ -262,16 +251,17 @@ module Roger
262
251
  def validate_stack!
263
252
  return if config[:blank]
264
253
 
265
- mockup_options = {}
266
- relativizer_options = {}
267
-
268
254
  unless find_in_stack(Roger::Release::Processors::Mockup)
269
- @stack.unshift([Roger::Release::Processors::Mockup.new, mockup_options])
255
+ @stack.unshift([Roger::Release::Processors::Mockup.new, {}])
270
256
  end
271
257
 
272
- # rubocop:disable Style/GuardClause
273
258
  unless find_in_stack(Roger::Release::Processors::UrlRelativizer)
274
- @stack.push([Roger::Release::Processors::UrlRelativizer.new, relativizer_options])
259
+ @stack.push([Roger::Release::Processors::UrlRelativizer.new, {}])
260
+ end
261
+
262
+ # rubocop:disable Style/GuardClause
263
+ unless find_in_stack(Roger::Release::Finalizers::Dir)
264
+ @stack.push([Roger::Release::Finalizers::Dir.new, {}])
275
265
  end
276
266
  end
277
267
 
@@ -295,8 +285,6 @@ module Roger
295
285
  end
296
286
 
297
287
  def run_stack!
298
- @stack = self.class.default_stack.dup if @stack.empty?
299
-
300
288
  # call all objects in @stack
301
289
  @stack.each do |task|
302
290
  if task.is_a?(Array)
@@ -307,19 +295,6 @@ module Roger
307
295
  end
308
296
  end
309
297
 
310
- # Will run all finalizers, if no finalizers are set it will take the
311
- # default finalizers.
312
- #
313
- # If config[:blank] is true, it will not use the default finalizers
314
- def run_finalizers!
315
- @finalizers = self.class.default_finalizers.dup if @finalizers.empty? && !config[:blank]
316
-
317
- # call all objects in @finalizes
318
- @finalizers.each do |finalizer|
319
- finalizer[0].call(self, finalizer[1])
320
- end
321
- end
322
-
323
298
  def cleanup!
324
299
  log(self, "Cleaning up build path #{build_path}")
325
300
  rm_rf(build_path)
@@ -330,5 +305,5 @@ end
330
305
  require File.dirname(__FILE__) + "/release/scm"
331
306
  require File.dirname(__FILE__) + "/release/injector"
332
307
  require File.dirname(__FILE__) + "/release/cleaner"
333
- require File.dirname(__FILE__) + "/release/finalizers"
334
308
  require File.dirname(__FILE__) + "/release/processors"
309
+ require File.dirname(__FILE__) + "/release/finalizers"
@@ -111,8 +111,9 @@ module Roger
111
111
  #
112
112
  # If you just want to render an arbitrary file, use #render_file instead
113
113
  #
114
- # @option options [Hash] :locals
115
- # @option options [String] :source
114
+ # @option options [Hash] :locals Locals to use during rendering
115
+ # @option options [String] :source The source for the template
116
+ # @option options [String, nil] :layout The default layout to use
116
117
  def render(path, options = {}, &block)
117
118
  template, layout = template_and_layout_for_render(path, options)
118
119
 
@@ -196,16 +197,23 @@ module Roger
196
197
  template_type = current_template ? :partial : :template
197
198
  template = template(path, options[:source], template_type)
198
199
 
199
- # Only attempt to load layout for toplevel
200
- if !current_template && template.data[:layout]
201
- layout = template(template.data[:layout], nil, :layout)
202
- else
203
- layout = BlankTemplate.new
204
- end
200
+ layout = layout_for_template(template, options)
205
201
 
206
202
  [template, layout]
207
203
  end
208
204
 
205
+ # Gets the layout for a specific template
206
+ def layout_for_template(template, options)
207
+ layout_name = template.data.key?(:layout) ? template.data[:layout] : options[:layout]
208
+
209
+ # Only attempt to load layout when:
210
+ # - Template is the toplevel template
211
+ # - A layout_name is available
212
+ return BlankTemplate.new if current_template || !layout_name
213
+
214
+ template(layout_name, nil, :layout)
215
+ end
216
+
209
217
  # Will check the template nesting if we haven't already
210
218
  # rendered this path before. If it has we'll throw an argumenteerror
211
219
  def prevent_recursion!(template)
data/lib/roger/server.rb CHANGED
@@ -7,12 +7,26 @@ require "webrick/https"
7
7
 
8
8
  module Roger
9
9
  # The Roger webserver. Initializes a rack server.
10
+ #
11
+ # @option options :port [Integer] The specified port you'd want to use
12
+ # @option options :auto_port [Boolean] Wether or not you want Roger
13
+ # to find a suitable port if the specified port is in use.
14
+ # @option options :handler [String] The preferred handler to use
10
15
  class Server
11
16
  attr_reader :server_options
12
17
 
18
+ # @attr_reader [Roger::Project] project The project used in this server
13
19
  attr_reader :project
14
20
 
15
- attr_accessor :port, :handler, :host
21
+ # @attr_reader [nil, Integer] used_port The actual port used to start
22
+ # the webserver. Only set if the server is running.
23
+ attr_reader :used_port
24
+
25
+ # @attr_reader [nil, Class] used_handler The actual used handler.
26
+ # Only set if the server is running.
27
+ attr_reader :used_handler
28
+
29
+ attr_accessor :port, :handler, :host, :auto_port
16
30
 
17
31
  def initialize(project, options = {})
18
32
  @project = project
@@ -25,6 +39,10 @@ module Roger
25
39
  self.port = 9000
26
40
  self.handler = nil
27
41
  self.host = "0.0.0.0"
42
+ self.auto_port = true
43
+
44
+ @used_port = nil
45
+ @used_handler = nil
28
46
 
29
47
  set_options(options)
30
48
  end
@@ -32,9 +50,10 @@ module Roger
32
50
  # Sets the options, this is a separate method as we want to override certain
33
51
  # things set in the rogerfile from the commandline
34
52
  def set_options(options)
35
- self.port = options[:port] if options.key?(:port)
53
+ self.port = options[:port].to_i if options.key?(:port)
36
54
  self.handler = options[:handler] if options.key?(:handler)
37
55
  self.host = options[:host] if options.key?(:host)
56
+ self.auto_port = options[:auto_port] if options.key?(:auto_port)
38
57
  end
39
58
 
40
59
  # Use the specified Rack middleware
@@ -53,18 +72,38 @@ module Roger
53
72
 
54
73
  def run!
55
74
  project.mode = :server
56
- handler.run application, server_options do |server|
75
+
76
+ options = server_options_for_handler
77
+ @used_port = options[:Port]
78
+ @used_handler = handler
79
+
80
+ handler.run application, options do |server|
57
81
  trap(:INT) do
58
82
  ## Use thins' hard #stop! if available, otherwise just #stop
59
83
  server.respond_to?(:stop!) ? server.stop! : server.stop
60
84
  puts "Roger, out!"
61
85
  end
86
+
87
+ yield server if block_given?
62
88
  end
63
89
  ensure
64
90
  project.mode = nil
91
+ @used_port = nil
92
+ @used_handler = nil
65
93
  end
66
94
  alias_method :run, :run!
67
95
 
96
+ def server_options_for_handler
97
+ # Search for available port
98
+ options = server_options.dup
99
+ if auto_port && !port_free?(options[:Host], options[:Port])
100
+ options[:Port] = free_port_for_host_above(options[:Host], options[:Port])
101
+ end
102
+
103
+ # Return the options
104
+ options
105
+ end
106
+
68
107
  def port=(p)
69
108
  @port = server_options[:Port] = p
70
109
  end
@@ -83,6 +122,23 @@ module Roger
83
122
 
84
123
  protected
85
124
 
125
+ # Get the first free port for host above port
126
+ # Will only ever test 100 ports.
127
+ def free_port_for_host_above(host, port)
128
+ test_port = port
129
+ test_port += 1 until port_free?(host, test_port) || port + 100 <= test_port
130
+ test_port
131
+ end
132
+
133
+ # See if a certain port is free on a certain host
134
+ def port_free?(host, port)
135
+ Addrinfo.tcp(host, port).listen.close
136
+
137
+ true
138
+ rescue SocketError, Errno::EADDRINUSE
139
+ false
140
+ end
141
+
86
142
  # Build the final application that get's run by the Rack Handler
87
143
  def application
88
144
  return @app if @app
@@ -3,7 +3,12 @@ module Roger
3
3
  module Helpers
4
4
  # The partial helper
5
5
  module Partial
6
- def partial(name, options = {}, &block)
6
+ def partial(name, locals = {}, &block)
7
+ if locals[:locals]
8
+ options = locals
9
+ else
10
+ options = { locals: locals }
11
+ end
7
12
  if block_given?
8
13
  partial_with_block(name, options, &block)
9
14
  else
data/lib/roger/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Roger main namespace
2
2
  module Roger
3
- VERSION = "1.6.4"
3
+ VERSION = "1.7.0"
4
4
  end
data/roger.gemspec CHANGED
@@ -41,6 +41,6 @@ Gem::Specification.new do |s|
41
41
  s.add_development_dependency("test-unit", "~> 3.0.0")
42
42
  s.add_development_dependency("mocha", "~> 1.1.0")
43
43
  s.add_development_dependency("simplecov", "~> 0.10.0")
44
- s.add_development_dependency("puma", "~> 2.10.0")
44
+ s.add_development_dependency("puma", "~> 3.6.0")
45
45
  s.add_development_dependency("rubocop", "~> 0.31.0")
46
46
  end
@@ -0,0 +1,25 @@
1
+ # Generator scope
2
+ module Generators
3
+ # Simple Mock generator
4
+ class MockedGenerator < Roger::Generators::Base
5
+ desc "@mocked description"
6
+ argument :path, type: :string, required: false, desc: "Path to generate project into"
7
+ argument :another_arg, type: :string, required: false, desc: "Mocked or what?!"
8
+
9
+ def test
10
+ # Somewhat ugly way of checking
11
+ fail NotImplementedError
12
+ end
13
+ end
14
+
15
+ Roger::Generators.register :mocked, MockedGenerator
16
+
17
+ # Simple Mocku generator that has a project
18
+ class MockedWithProjectGenerator < Roger::Generators::Base
19
+ desc "Returns a project"
20
+ def test
21
+ # Somewhat ugly way of checking
22
+ fail StandardError if @project
23
+ end
24
+ end
25
+ end
@@ -0,0 +1 @@
1
+ [<%= yield %>]
@@ -0,0 +1 @@
1
+ <%= locals[:variable] %>
@@ -1,5 +1,5 @@
1
1
  <% if depth < max_depth %>
2
- <%= partial 'test/max_depth', locals: { depth: locals[:depth] + 1, max_depth: locals[:max_depth] } %>
2
+ <%= partial 'test/max_depth', { depth: locals[:depth] + 1, max_depth: locals[:max_depth] } %>
3
3
  <% else %>
4
4
  Stop! Hammertime!
5
5
  <% end %>
@@ -0,0 +1 @@
1
+ <%= renderer.parent_template.source_path %>