roda 3.57.0 → 3.60.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 578868ccd08ba1fa91302273c92176def99072db735ec119d13cbf49e78a7249
4
- data.tar.gz: b95b2a33a18a3b135f494ba7f0ffa1639a5fd876b0b199f414826cab7fa75a9d
3
+ metadata.gz: 970d646c144f53a89f4f79e9d54b6929b7c10b55b1bbe9b2d5e72aea6a8eb3ae
4
+ data.tar.gz: ec2489d3d668b3abd2787a7f19c13de43c94685dce010d800296eb1194e36e11
5
5
  SHA512:
6
- metadata.gz: 2b7b769a1653315b1fd9bca1a993ff0e699f2a09fb4db135304d8c7473f2c834c61b91e188005ac029fd85feaca6cc6a106efdd83f0e53771cddd8f3a73204aa
7
- data.tar.gz: 7bdc602a54f8f5b34a7edc0355b3e6a426b29dd4671c30ef9d7712c757e116c9e6679cd08884f28c7636a80560878284ff4de479f0c479d905948ebfce9b12b3
6
+ metadata.gz: ccc8d09c535a2c6a92ee314ff295ca5b8756b6c942f3224acbabdc6a92de5bf242a928b296c2e410ecf0bf59470a2143ac2c80d118030db5a2f45fb0cf262a8c
7
+ data.tar.gz: 79114184b64598e3d12d3773c5e7f8d717a05268c63c479758fe3ea1c3c78ccd933531c4e7ef6fd58a6d6af03a150d6e1dde8bf0f27dcc4c0c253482336879f0
data/CHANGELOG CHANGED
@@ -1,3 +1,21 @@
1
+ = 3.60.0 (2022-09-13)
2
+
3
+ * Add link_to plugin with link_to method for creating HTML links (jeremyevans)
4
+
5
+ = 3.59.0 (2022-08-12)
6
+
7
+ * Add additional_render_engines plugin, for considering multiple render engines for templates (jeremyevans)
8
+
9
+ * Fix typo in private method name in delete_empty_headers plugin (mculpt) (#279)
10
+
11
+ = 3.58.0 (2022-07-13)
12
+
13
+ * Add filter_common_logger plugin for skipping the logging of certain requests when using the common_logger plugin (jeremyevans)
14
+
15
+ * Make exception_page plugin use Exception#detailed_message on Ruby 3.2+ (jeremyevans)
16
+
17
+ * Make heartbeat plugin compatible with recent changes in the rack master branch (jeremyevans)
18
+
1
19
  = 3.57.0 (2022-06-14)
2
20
 
3
21
  * Make static_routing plugin depend on the hash_paths instead of the hash_routes plugin (jeremyevans)
@@ -0,0 +1,16 @@
1
+ = New Features
2
+
3
+ * A filter_common_logger plugin has been added, allowing you to skip
4
+ logging of certain requests in the common_logger plugin. This
5
+ allows you to only log requests for certain paths, or only log
6
+ requests for certain types of responses.
7
+
8
+ = Other Improvements
9
+
10
+ * The heartbeat plugin is now compatible with recent changes in the
11
+ rack master branch (what will be rack 3).
12
+
13
+ * The exception_page plugin will now use Exception#detailed_message
14
+ on Ruby 3.2+, preserving the did_you_mean and error_highlight
15
+ information. Additionally, the display of exception messages
16
+ has been improved.
@@ -0,0 +1,17 @@
1
+ = New Features
2
+
3
+ * An additional_render_engines plugin has been added, for considering
4
+ multiple render engines for templates. If the template path does not
5
+ exist for the default render engine, then each additional render
6
+ engine will be checked, returning the first path that exists:
7
+
8
+ plugin :additional_render_engines, ['haml', 'str']
9
+
10
+ This is similar to the additional_view_directories plugin added in
11
+ 3.53.0. Both plugins can be used if you want to consider multiple
12
+ view directories and multiple render engines.
13
+
14
+ = Other Improvements
15
+
16
+ * A typo in a private method name in the delete_empty_headers plugin
17
+ has been fixed.
@@ -0,0 +1,56 @@
1
+ = New Features
2
+
3
+ * A link_to plugin has been added with a link_to method for
4
+ creating HTML links.
5
+
6
+ The simplest usage of link_to is passing the body and the location
7
+ to link to as strings:
8
+
9
+ # Instance level
10
+ link_to("body", "/path")
11
+ # => "<a href=\"/path\">body</a>"
12
+
13
+ The link_to plugin depends on the path plugin, and allows you to
14
+ pass symbols for named paths:
15
+
16
+ # Class level
17
+ path :foo, "/path/to/too"
18
+
19
+ # Instance level
20
+ link_to("body", :foo)
21
+ # => "<a href=\"/path/to/foo\">body</a>"
22
+
23
+ It also allows you to pass instances of classes that you have
24
+ registered with the path plugin:
25
+
26
+ # Class level
27
+ A = Struct.new(:id)
28
+ path A do
29
+ "/path/to/a/#{id}"
30
+ end
31
+
32
+ # Instance level
33
+ link_to("body", A.new(1))
34
+ # => "<a href=\"/path/to/a/1\">body</a>"
35
+
36
+ To set additional HTML attributes on the tag, you can pass them as
37
+ an options hash:
38
+
39
+ link_to("body", "/path", foo: "bar")
40
+ # => "<a href=\"/path\" foo=\"bar\">body</a>"
41
+
42
+ If the body is nil, it will be set to the same as the path:
43
+
44
+ link_to(nil, "/path")
45
+ # => "<a href=\"/path\">/path</a>"
46
+
47
+ The plugin will automatically HTML escape the path and any HTML
48
+ attribute values, using the h plugin:
49
+
50
+ link_to("body", "/path?a=1&b=2", foo: '"bar"')
51
+ # => "<a href=\"/path?a=1&amp;b=2\" foo=\"&quot;bar&quot;\">body</a>"
52
+
53
+ = Other Improvements
54
+
55
+ * Coverage testing has been expanded to multiple rack versions, instead
56
+ of just the current rack release.
@@ -0,0 +1,61 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The additional_render_engines plugin allows for specifying additional render
7
+ # engines to consider for templates. When rendering a template, it will
8
+ # first try the default template engine specified in the render plugin. If the
9
+ # template file to be rendered does not exist, it will try each additional render
10
+ # engine specified in this plugin, in order, using the path to the first
11
+ # template file that exists in the file system. If no such path is found, it
12
+ # uses the default path specified by the render plugin.
13
+ #
14
+ # Example:
15
+ #
16
+ # plugin :render # default engine is 'erb'
17
+ # plugin :additional_render_engines, ['haml', 'str']
18
+ #
19
+ # route do |r|
20
+ # # Will check the following in order, using path for first
21
+ # # template file that exists:
22
+ # # * views/t.erb
23
+ # # * views/t.haml
24
+ # # * views/t.str
25
+ # render :t
26
+ # end
27
+ module AdditionalRenderEngines
28
+ def self.load_dependencies(app, render_engines)
29
+ app.plugin :render
30
+ end
31
+
32
+ # Set the additional render engines to consider.
33
+ def self.configure(app, render_engines)
34
+ app.opts[:additional_render_engines] = render_engines.dup.freeze
35
+ end
36
+
37
+ module InstanceMethods
38
+ private
39
+
40
+ # If the template path does not exist, try looking for the template
41
+ # using each of the render engines, in order, returning
42
+ # the first path that exists. If no template path exists for the
43
+ # default any or any additional engines, return the original path.
44
+ def template_path(opts)
45
+ orig_path = super
46
+
47
+ unless File.file?(orig_path)
48
+ self.opts[:additional_render_engines].each do |engine|
49
+ path = super(opts.merge(:engine=>engine))
50
+ return path if File.file?(path)
51
+ end
52
+ end
53
+
54
+ orig_path
55
+ end
56
+ end
57
+ end
58
+
59
+ register_plugin(:additional_render_engines, AdditionalRenderEngines)
60
+ end
61
+ end
@@ -34,9 +34,7 @@ class Roda
34
34
  module AllVerbs
35
35
  module RequestMethods
36
36
  %w'delete head options link patch put trace unlink'.each do |verb|
37
- # :nocov:
38
37
  if ::Rack::Request.method_defined?("#{verb}?")
39
- # :nocov:
40
38
  class_eval(<<-END, __FILE__, __LINE__+1)
41
39
  def #{verb}(*args, &block)
42
40
  _verb(args, &block) if #{verb}?
@@ -147,7 +147,7 @@ class Roda
147
147
  # If you have the yuicompressor gem installed and working, it will be used
148
148
  # automatically to compress your javascript and css assets. For javascript
149
149
  # assets, if yuicompressor is not available, the plugin will check for
150
- # closure_compiler, uglifier, and minjs and use the first one that works.
150
+ # closure-compiler, uglifier, and minjs and use the first one that works.
151
151
  # If no compressors are available, the assets will just be concatenated
152
152
  # together and not compressed during compilation. You can use the
153
153
  # :css_compressor and :js_compressor options to specify the compressor to use.
@@ -13,18 +13,18 @@ class Roda
13
13
  module ResponseMethods
14
14
  # Delete any empty headers when calling finish
15
15
  def finish
16
- delelete_empty_headers(super)
16
+ delete_empty_headers(super)
17
17
  end
18
18
 
19
19
  # Delete any empty headers when calling finish_with_body
20
20
  def finish_with_body(_)
21
- delelete_empty_headers(super)
21
+ delete_empty_headers(super)
22
22
  end
23
23
 
24
24
  private
25
25
 
26
26
  # Delete any empty headers from response
27
- def delelete_empty_headers(res)
27
+ def delete_empty_headers(res)
28
28
  res[1].delete_if{|_, v| v.is_a?(String) && v.empty?}
29
29
  res
30
30
  end
@@ -1,8 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- # :nocov:
4
3
  raise LoadError, "disallow_file_uploads plugin not supported on Rack <1.6" if Rack.release < '1.6'
5
- # :nocov:
6
4
 
7
5
  #
8
6
  class Roda
@@ -127,7 +127,7 @@ div.context ol.context-line li span { float: right; }
127
127
  div.commands { margin-left: 40px; }
128
128
  div.commands a { color:black; text-decoration:none; }
129
129
  #summary { background: #ffc; }
130
- #summary h2 { font-weight: normal; color: #666; }
130
+ #summary h2 { font-weight: normal; color: #666; font-family: monospace; white-space: pre-wrap;}
131
131
  #summary ul#quicklinks { list-style-type: none; margin-bottom: 2em; }
132
132
  #summary ul#quicklinks li { float: left; padding: 0 1em; }
133
133
  #summary ul#quicklinks>li+li { border-left: 1px #666 solid; }
@@ -196,12 +196,13 @@ END
196
196
  # Designed to be used with the +json+ exception, which will
197
197
  # automatically convert the hash to JSON format.
198
198
  def exception_page(exception, opts=OPTS)
199
+ message = exception_page_exception_message(exception)
199
200
  if opts[:json]
200
201
  @_response['Content-Type'] = "application/json"
201
202
  {
202
203
  "exception"=>{
203
204
  "class"=>exception.class.to_s,
204
- "message"=>exception.message.to_s,
205
+ "message"=>message,
205
206
  "backtrace"=>exception.backtrace.map(&:to_s)
206
207
  }
207
208
  }
@@ -319,7 +320,7 @@ END
319
320
 
320
321
  <div id="summary">
321
322
  <h1>#{h exception.class} at #{h r.path}</h1>
322
- <h2>#{h exception.message}</h2>
323
+ <h2>#{h message}</h2>
323
324
  <table><tr>
324
325
  <th>Ruby</th>
325
326
  <td>
@@ -394,7 +395,22 @@ END1
394
395
  END
395
396
  else
396
397
  @_response['Content-Type'] = "text/plain"
397
- "#{exception.class}: #{exception.message}\n#{exception.backtrace.map{|l| "\t#{l}"}.join("\n")}"
398
+ "#{exception.class}: #{message}\n#{exception.backtrace.map{|l| "\t#{l}"}.join("\n")}"
399
+ end
400
+ end
401
+
402
+ private
403
+
404
+ # :nocov:
405
+ if RUBY_VERSION >= '3.2'
406
+ def exception_page_exception_message(exception)
407
+ exception.detailed_message(highlight: false).to_s
408
+ end
409
+ # :nocov:
410
+ else
411
+ # Return message to use for exception.
412
+ def exception_page_exception_message(exception)
413
+ exception.message.to_s
398
414
  end
399
415
  end
400
416
  end
@@ -0,0 +1,46 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The skip_common_logger plugin allows for skipping common_logger logging
7
+ # of some requests. You pass a block when loading the plugin, and the
8
+ # block will be called before logging each request. The block should return
9
+ # whether the request should be logged.
10
+ #
11
+ # Example:
12
+ #
13
+ # # Only log server errors
14
+ # plugin :filter_common_logger do |result|
15
+ # result[0] >= 500
16
+ # end
17
+ #
18
+ # # Don't log requests to certain paths
19
+ # plugin :filter_common_logger do |_|
20
+ # # Block is called in the same context as the route block
21
+ # !request.path.start_with?('/admin/')
22
+ # end
23
+ module FilterCommonLogger
24
+ def self.load_dependencies(app)
25
+ app.plugin :common_logger
26
+ end
27
+
28
+ def self.configure(app, &block)
29
+ app.send(:define_method, :_common_log_request?, &block)
30
+ app.send(:private, :_common_log_request?)
31
+ app.send(:alias_method, :_common_log_request?, :_common_log_request?)
32
+ end
33
+
34
+ module InstanceMethods
35
+ private
36
+
37
+ # Log request/response information in common log format to logger.
38
+ def _roda_after_90__common_logger(result)
39
+ super if result && _common_log_request?(result)
40
+ end
41
+ end
42
+ end
43
+
44
+ register_plugin(:filter_common_logger, FilterCommonLogger)
45
+ end
46
+ end
@@ -14,13 +14,6 @@ class Roda
14
14
  #
15
15
  # plugin :heartbeat, path: '/status'
16
16
  module Heartbeat
17
- # :nocov:
18
- HEADER_CLASS = (defined?(Rack::Headers) && Rack::Headers.is_a?(Class)) ? Rack::Headers : Hash
19
- # :nocov:
20
- private_constant :HEADER_CLASS
21
-
22
- HEARTBEAT_RESPONSE = [200, {'Content-Type'=>'text/plain'}.freeze, ['OK'.freeze].freeze].freeze
23
-
24
17
  # Set the heartbeat path to the given path.
25
18
  def self.configure(app, opts=OPTS)
26
19
  app.opts[:heartbeat_path] = (opts[:path] || app.opts[:heartbeat_path] || "/heartbeat").dup.freeze
@@ -32,9 +25,11 @@ class Roda
32
25
  # If the request is for a heartbeat path, return the heartbeat response.
33
26
  def _roda_before_20__heartbeat
34
27
  if env['PATH_INFO'] == opts[:heartbeat_path]
35
- response = HEARTBEAT_RESPONSE.dup
36
- response[1] = HEADER_CLASS[response[1]]
37
- throw :halt, response
28
+ response = @_response
29
+ response.status = 200
30
+ response['Content-Type'] = 'text/plain'
31
+ response.write 'OK'
32
+ throw :halt, response.finish
38
33
  end
39
34
  end
40
35
  end
@@ -52,14 +52,12 @@ class Roda
52
52
  end
53
53
 
54
54
  class Params < Rack::QueryParser::Params
55
- # :nocov:
56
- if Rack.release >= '2.3'
55
+ if Rack.release >= '3'
57
56
  def initialize
58
57
  @size = 0
59
58
  @params = Hash.new(&INDIFFERENT_PROC)
60
59
  end
61
60
  else
62
- # :nocov:
63
61
  def initialize(limit = Rack::Utils.key_space_limit)
64
62
  @limit = limit
65
63
  @size = 0
@@ -71,9 +69,7 @@ class Roda
71
69
  end
72
70
 
73
71
  module RequestMethods
74
- # :nocov:
75
- query_parser = Rack.release >= '2.3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32)
76
- # :nocov:
72
+ query_parser = Rack.release >= '3' ? QueryParser.new(QueryParser::Params, 32) : QueryParser.new(QueryParser::Params, 65536, 32)
77
73
  QUERY_PARSER = Rack::Utils.default_query_parser = query_parser
78
74
 
79
75
  private
@@ -89,7 +85,6 @@ class Roda
89
85
  end
90
86
  end
91
87
  else
92
- # :nocov:
93
88
  module InstanceMethods
94
89
  # A copy of the request params that will automatically
95
90
  # convert symbols to strings.
@@ -115,7 +110,6 @@ class Roda
115
110
  end
116
111
  end
117
112
  end
118
- # :nocov:
119
113
  end
120
114
  end
121
115
 
@@ -86,12 +86,10 @@ class Roda
86
86
 
87
87
 
88
88
  # Rack 3 dropped requirement that input be rewindable
89
- if Rack.release >= '2.3'
90
- # :nocov:
89
+ if Rack.release >= '3'
91
90
  def _read_json_input(input)
92
91
  input.read
93
92
  end
94
- # :nocov:
95
93
  else
96
94
  def _read_json_input(input)
97
95
  input.rewind
@@ -0,0 +1,83 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The link_to plugin adds the +link_to+ instance method, which can be used for constructing
7
+ # HTML links (+a+ tag with +href+ attribute).
8
+ #
9
+ # The simplest usage of +link_to+ is passing the body and the location to link to as strings:
10
+ #
11
+ # link_to("body", "/path")
12
+ # # => "<a href=\"/path\">body</a>"
13
+ #
14
+ # The link_to plugin depends on the path plugin, and allows you to pass symbols for named paths:
15
+ #
16
+ # # Class level
17
+ # path :foo, "/path/to/too"
18
+ #
19
+ # # Instance level
20
+ # link_to("body", :foo)
21
+ # # => "<a href=\"/path/to/foo\">body</a>"
22
+ #
23
+ # It also allows you to pass instances of classes that you have registered with the path plugin:
24
+ #
25
+ # # Class level
26
+ # A = Struct.new(:id)
27
+ # path A do
28
+ # "/path/to/a/#{id}"
29
+ # end
30
+ #
31
+ # # Instance level
32
+ # link_to("body", A.new(1))
33
+ # # => "<a href=\"/path/to/a/1\">body</a>"
34
+ #
35
+ # To set additional HTML attributes on the +a+ tag, you can pass them as an options hash:
36
+ #
37
+ # link_to("body", "/path", foo: "bar")
38
+ # # => "<a href=\"/path\" foo=\"bar\">body</a>"
39
+ #
40
+ # If the body is nil, it will be set to the same as the path:
41
+ #
42
+ # link_to(nil, "/path")
43
+ # # => "<a href=\"/path\">/path</a>"
44
+ #
45
+ # The plugin will automatically HTML escape the path and any HTML attribute values, using the h plugin:
46
+ #
47
+ # link_to("body", "/path?a=1&b=2", foo: '"bar"')
48
+ # # => "<a href=\"/path?a=1&amp;b=2\" foo=\"&quot;bar&quot;\">body</a>"
49
+ module LinkTo
50
+ def self.load_dependencies(app)
51
+ app.plugin :h
52
+ app.plugin :path
53
+ end
54
+
55
+ module InstanceMethods
56
+ # Return a string with an HTML +a+ tag with an +href+ attribute. See LinkTo
57
+ # module documentation for details.
58
+ def link_to(body, href, attributes=OPTS)
59
+ case href
60
+ when Symbol
61
+ href = public_send(:"#{href}_path")
62
+ when String
63
+ # nothing
64
+ else
65
+ href = path(href)
66
+ end
67
+
68
+ href = h(href)
69
+
70
+ body = href if body.nil?
71
+
72
+ buf = String.new << "<a href=\"#{href}\""
73
+ attributes.each do |k, v|
74
+ buf << " " << k.to_s << "=\"" << h(v) << "\""
75
+ end
76
+ buf << ">" << body << "</a>"
77
+ end
78
+ end
79
+ end
80
+
81
+ register_plugin(:link_to, LinkTo)
82
+ end
83
+ end
@@ -465,7 +465,11 @@ class Roda
465
465
  def #{field}(address, &block)
466
466
  on(:#{field}=>address, &block)
467
467
  end
468
+ END
469
+
470
+ next if [:rcpt, :text, :body, :subject].include?(field)
468
471
 
472
+ class_eval(<<-END, __FILE__, __LINE__+1)
469
473
  private
470
474
 
471
475
  def match_#{field}(address)
@@ -474,11 +478,6 @@ class Roda
474
478
  END
475
479
  end
476
480
 
477
- undef_method :match_rcpt
478
- undef_method :match_text
479
- undef_method :match_body
480
- undef_method :match_subject
481
-
482
481
  # Same as +header+, but also mark the message as being handled.
483
482
  def handle_header(key, value=nil)
484
483
  header(key, value) do |*args|
@@ -3,9 +3,7 @@
3
3
  begin
4
4
  require 'rack/files'
5
5
  rescue LoadError
6
- # :nocov:
7
6
  require 'rack/file'
8
- # :nocov:
9
7
  end
10
8
 
11
9
  #
@@ -66,9 +64,7 @@ class Roda
66
64
  # end
67
65
  # end
68
66
  module MultiPublic
69
- # :nocov:
70
67
  RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
71
- # :nocov:
72
68
 
73
69
  def self.load_dependencies(app, _, opts=OPTS)
74
70
  app.plugin(:public, opts)
@@ -116,9 +116,7 @@ class Roda
116
116
  # arguments, record the verb used. If given an argument, add an is
117
117
  # check with the arguments.
118
118
  %w'get post delete head options link patch put trace unlink'.each do |verb|
119
- # :nocov:
120
119
  if ::Rack::Request.method_defined?("#{verb}?")
121
- # :nocov:
122
120
  class_eval(<<-END, __FILE__, __LINE__+1)
123
121
  def #{verb}(*args, &block)
124
122
  if (empty = args.empty?) && @_is_verbs
@@ -5,9 +5,7 @@ require 'uri'
5
5
  begin
6
6
  require 'rack/files'
7
7
  rescue LoadError
8
- # :nocov:
9
8
  require 'rack/file'
10
- # :nocov:
11
9
  end
12
10
 
13
11
  #
@@ -45,9 +43,7 @@ class Roda
45
43
  module Public
46
44
  SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact)
47
45
  PARSER = URI::DEFAULT_PARSER
48
- # :nocov:
49
46
  RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
50
- # :nocov:
51
47
 
52
48
  # Use options given to setup a Rack::File instance for serving files. Options:
53
49
  # :default_mime :: The default mime type to use if the mime type is not recognized.
@@ -142,13 +138,11 @@ class Roda
142
138
  server.serving(self, path)
143
139
  end
144
140
  else
145
- # :nocov:
146
141
  def public_serve(server, path)
147
142
  server = server.dup
148
143
  server.path = path
149
144
  server.serving(env)
150
145
  end
151
- # :nocov:
152
146
  end
153
147
  end
154
148
  end
@@ -214,18 +214,18 @@ class Roda
214
214
  tilt_compiled_method_support = defined?(Tilt::VERSION) && Tilt::VERSION >= '1.2' &&
215
215
  ([1, -2].include?(((compiled_method_arity = Tilt::Template.instance_method(:compiled_method).arity) rescue false)))
216
216
  NO_CACHE = {:cache=>false}.freeze
217
- COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' && tilt_compiled_method_support
217
+ COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' && tilt_compiled_method_support && ENV['RODA_RENDER_COMPILED_METHOD_SUPPORT'] != 'no'
218
218
 
219
219
  if compiled_method_arity == -2
220
220
  def self.tilt_template_compiled_method(template, locals_keys, scope_class)
221
221
  template.send(:compiled_method, locals_keys, scope_class)
222
222
  end
223
+ # :nocov:
223
224
  else
224
- # :nocov:
225
225
  def self.tilt_template_compiled_method(template, locals_keys, scope_class)
226
226
  template.send(:compiled_method, locals_keys)
227
227
  end
228
- # :nocov:
228
+ # :nocov:
229
229
  end
230
230
 
231
231
  # Setup default rendering options. See Render for details.
@@ -366,9 +366,7 @@ class Roda
366
366
  false
367
367
  end
368
368
 
369
- # :nocov:
370
369
  if COMPILED_METHOD_SUPPORT
371
- # :nocov:
372
370
  # Compile a method in the given module with the given name that will
373
371
  # call the compiled template method, updating the compiled template method
374
372
  def define_compiled_method(roda_class, method_name, locals_keys=EMPTY_ARRAY)
@@ -412,9 +410,7 @@ class Roda
412
410
  end
413
411
 
414
412
  module ClassMethods
415
- # :nocov:
416
413
  if COMPILED_METHOD_SUPPORT
417
- # :nocov:
418
414
  # If using compiled methods and there is an optimized layout, speed up
419
415
  # access to the layout method to improve the performance of view.
420
416
  def freeze
@@ -437,9 +433,7 @@ class Roda
437
433
  def inherited(subclass)
438
434
  super
439
435
  opts = subclass.opts[:render] = subclass.opts[:render].dup
440
- # :nocov:
441
436
  if COMPILED_METHOD_SUPPORT
442
- # :nocov:
443
437
  opts[:template_method_cache] = (opts[:cache_class] || RodaCache).new
444
438
  end
445
439
  opts[:cache] = opts[:cache].dup
@@ -459,9 +453,7 @@ class Roda
459
453
  instance = allocate
460
454
  instance.send(:retrieve_template, instance.send(:view_layout_opts, OPTS))
461
455
 
462
- # :nocov:
463
456
  if COMPILED_METHOD_SUPPORT
464
- # :nocov:
465
457
  if (layout_template = render_opts[:optimize_layout]) && !opts[:render][:optimized_layout_method_created]
466
458
  instance.send(:retrieve_template, :template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout)
467
459
  layout_method = opts[:render][:template_method_cache][:_roda_layout]
@@ -610,7 +602,6 @@ class Roda
610
602
  end
611
603
  end
612
604
  else
613
- # :nocov:
614
605
  def _cached_template_method(_)
615
606
  nil
616
607
  end
@@ -630,7 +621,6 @@ class Roda
630
621
  def _optimized_view_content(template)
631
622
  nil
632
623
  end
633
- # :nocov:
634
624
  end
635
625
 
636
626
 
@@ -109,11 +109,9 @@ class Roda
109
109
  end.join
110
110
  end
111
111
  else
112
- # :nocov:
113
112
  def _cached_render_each_template_method(template)
114
113
  nil
115
114
  end
116
- # :nocov:
117
115
  end
118
116
  end
119
117
  end
@@ -43,9 +43,7 @@ class Roda
43
43
  module InstanceMethods
44
44
  private
45
45
 
46
- # :nocov:
47
46
  if Render::COMPILED_METHOD_SUPPORT
48
- # :nocov:
49
47
  # Disable use of cached templates, since it assumes a render/view call with no
50
48
  # options will have no locals.
51
49
  def _cached_template_method(template)
@@ -4,9 +4,7 @@ require 'rack/mime'
4
4
  begin
5
5
  require 'rack/files'
6
6
  rescue LoadError
7
- # :nocov:
8
7
  require 'rack/file'
9
- # :nocov:
10
8
  end
11
9
 
12
10
 
@@ -225,9 +223,7 @@ class Roda
225
223
  ISO88591_ENCODING = Encoding.find('ISO-8859-1')
226
224
  BINARY_ENCODING = Encoding.find('BINARY')
227
225
 
228
- # :nocov:
229
226
  RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
230
- # :nocov:
231
227
 
232
228
  # Depend on the status_303 plugin.
233
229
  def self.load_dependencies(app, _opts = nil)
@@ -351,10 +347,8 @@ class Roda
351
347
  s, h, b = if Rack.release > '2'
352
348
  file.serving(self, path)
353
349
  else
354
- # :nocov:
355
350
  file.path = path
356
351
  file.serving(@env)
357
- # :nocov:
358
352
  end
359
353
 
360
354
  res.status = opts[:status] || s
@@ -45,11 +45,9 @@ class Roda
45
45
  when nil, false
46
46
  CLEAR_HEADERS
47
47
  when Array
48
- # :nocov:
49
- if Rack.release >= '2.3'
48
+ if Rack.release >= '3'
50
49
  keep_headers = keep_headers.map(&:downcase)
51
50
  end
52
- # :nocov:
53
51
  lambda{|headers| headers.delete_if{|k,_| !keep_headers.include?(k)}}
54
52
  else
55
53
  raise RodaError, "Invalid :keep_headers option"
@@ -126,9 +126,7 @@ class Roda
126
126
 
127
127
  private
128
128
 
129
- # :nocov:
130
129
  if Render::COMPILED_METHOD_SUPPORT
131
- # :nocov:
132
130
  # Return nil if using custom view or layout options.
133
131
  # If using a view subdir, prefix the template key with the subdir.
134
132
  def _cached_template_method_key(template)
data/lib/roda/request.rb CHANGED
@@ -1,18 +1,16 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- # :nocov:
4
3
  begin
5
4
  require "rack/version"
6
5
  rescue LoadError
7
6
  require "rack"
8
7
  else
9
- if Rack.release >= '2.3'
8
+ if Rack.release >= '3'
10
9
  require "rack/request"
11
10
  else
12
11
  require "rack"
13
12
  end
14
13
  end
15
- # :nocov:
16
14
 
17
15
  require_relative "cache"
18
16
 
@@ -129,8 +127,7 @@ class Roda
129
127
  "#<#{self.class.inspect} #{@env["REQUEST_METHOD"]} #{path}>"
130
128
  end
131
129
 
132
- # :nocov:
133
- if Rack.release >= '2.3'
130
+ if Rack.release >= '3'
134
131
  def http_version
135
132
  # Prefer SERVER_PROTOCOL as it is required in Rack 3.
136
133
  # Still fall back to HTTP_VERSION if SERVER_PROTOCOL
@@ -139,7 +136,6 @@ class Roda
139
136
  @env['SERVER_PROTOCOL'] || @env['HTTP_VERSION']
140
137
  end
141
138
  else
142
- # :nocov:
143
139
  # What HTTP version the request was submitted with.
144
140
  def http_version
145
141
  # Prefer HTTP_VERSION as it is backwards compatible
data/lib/roda/response.rb CHANGED
@@ -42,7 +42,6 @@ class Roda
42
42
  # code for non-empty responses and a 404 code for empty responses.
43
43
  attr_accessor :status
44
44
 
45
- # :nocov:
46
45
  if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
47
46
  # Set the default headers when creating a response.
48
47
  def initialize
@@ -51,7 +50,6 @@ class Roda
51
50
  @length = 0
52
51
  end
53
52
  else
54
- # :nocov:
55
53
  # Set the default headers when creating a response.
56
54
  def initialize
57
55
  @headers = {}
@@ -173,7 +171,6 @@ class Roda
173
171
 
174
172
  private
175
173
 
176
- # :nocov:
177
174
  if Rack.release < '2.0.2'
178
175
  # Don't use a content length for empty 205 responses on
179
176
  # rack 1, as it violates Rack::Lint in that version.
@@ -181,7 +178,6 @@ class Roda
181
178
  headers.delete("Content-Type")
182
179
  headers.delete("Content-Length")
183
180
  end
184
- # :nocov:
185
181
  else
186
182
  # Set the content length for empty 205 responses to 0
187
183
  def empty_205_headers(headers)
data/lib/roda/version.rb CHANGED
@@ -4,7 +4,7 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 57
7
+ RodaMinorVersion = 60
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.57.0
4
+ version: 3.60.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-14 00:00:00.000000000 Z
11
+ date: 2022-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -229,7 +229,10 @@ extra_rdoc_files:
229
229
  - doc/release_notes/3.55.0.txt
230
230
  - doc/release_notes/3.56.0.txt
231
231
  - doc/release_notes/3.57.0.txt
232
+ - doc/release_notes/3.58.0.txt
233
+ - doc/release_notes/3.59.0.txt
232
234
  - doc/release_notes/3.6.0.txt
235
+ - doc/release_notes/3.60.0.txt
233
236
  - doc/release_notes/3.7.0.txt
234
237
  - doc/release_notes/3.8.0.txt
235
238
  - doc/release_notes/3.9.0.txt
@@ -293,7 +296,10 @@ files:
293
296
  - doc/release_notes/3.55.0.txt
294
297
  - doc/release_notes/3.56.0.txt
295
298
  - doc/release_notes/3.57.0.txt
299
+ - doc/release_notes/3.58.0.txt
300
+ - doc/release_notes/3.59.0.txt
296
301
  - doc/release_notes/3.6.0.txt
302
+ - doc/release_notes/3.60.0.txt
297
303
  - doc/release_notes/3.7.0.txt
298
304
  - doc/release_notes/3.8.0.txt
299
305
  - doc/release_notes/3.9.0.txt
@@ -304,6 +310,7 @@ files:
304
310
  - lib/roda/plugins/_before_hook.rb
305
311
  - lib/roda/plugins/_optimized_matching.rb
306
312
  - lib/roda/plugins/_symbol_regexp_matchers.rb
313
+ - lib/roda/plugins/additional_render_engines.rb
307
314
  - lib/roda/plugins/additional_view_directories.rb
308
315
  - lib/roda/plugins/all_verbs.rb
309
316
  - lib/roda/plugins/assets.rb
@@ -336,6 +343,7 @@ files:
336
343
  - lib/roda/plugins/error_handler.rb
337
344
  - lib/roda/plugins/error_mail.rb
338
345
  - lib/roda/plugins/exception_page.rb
346
+ - lib/roda/plugins/filter_common_logger.rb
339
347
  - lib/roda/plugins/flash.rb
340
348
  - lib/roda/plugins/h.rb
341
349
  - lib/roda/plugins/halt.rb
@@ -353,6 +361,7 @@ files:
353
361
  - lib/roda/plugins/inject_erb.rb
354
362
  - lib/roda/plugins/json.rb
355
363
  - lib/roda/plugins/json_parser.rb
364
+ - lib/roda/plugins/link_to.rb
356
365
  - lib/roda/plugins/mail_processor.rb
357
366
  - lib/roda/plugins/mailer.rb
358
367
  - lib/roda/plugins/match_affix.rb