Package not found. Please check the package name and try again.
roda 3.57.0 → 3.60.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 +18 -0
- data/doc/release_notes/3.58.0.txt +16 -0
- data/doc/release_notes/3.59.0.txt +17 -0
- data/doc/release_notes/3.60.0.txt +56 -0
- data/lib/roda/plugins/additional_render_engines.rb +61 -0
- data/lib/roda/plugins/all_verbs.rb +0 -2
- data/lib/roda/plugins/assets.rb +1 -1
- data/lib/roda/plugins/delete_empty_headers.rb +3 -3
- data/lib/roda/plugins/disallow_file_uploads.rb +0 -2
- data/lib/roda/plugins/exception_page.rb +20 -4
- data/lib/roda/plugins/filter_common_logger.rb +46 -0
- data/lib/roda/plugins/heartbeat.rb +5 -10
- data/lib/roda/plugins/indifferent_params.rb +2 -8
- data/lib/roda/plugins/json_parser.rb +1 -3
- data/lib/roda/plugins/link_to.rb +83 -0
- data/lib/roda/plugins/mail_processor.rb +4 -5
- data/lib/roda/plugins/multi_public.rb +0 -4
- data/lib/roda/plugins/not_allowed.rb +0 -2
- data/lib/roda/plugins/public.rb +0 -6
- data/lib/roda/plugins/render.rb +3 -13
- data/lib/roda/plugins/render_each.rb +0 -2
- data/lib/roda/plugins/render_locals.rb +0 -2
- data/lib/roda/plugins/sinatra_helpers.rb +0 -6
- data/lib/roda/plugins/status_handler.rb +1 -3
- data/lib/roda/plugins/view_options.rb +0 -2
- data/lib/roda/request.rb +2 -6
- data/lib/roda/response.rb +0 -4
- data/lib/roda/version.rb +1 -1
- metadata +11 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 970d646c144f53a89f4f79e9d54b6929b7c10b55b1bbe9b2d5e72aea6a8eb3ae
|
|
4
|
+
data.tar.gz: ec2489d3d668b3abd2787a7f19c13de43c94685dce010d800296eb1194e36e11
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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&b=2\" foo=\""bar"\">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}?
|
data/lib/roda/plugins/assets.rb
CHANGED
|
@@ -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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
@@ -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"=>
|
|
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
|
|
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}: #{
|
|
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 =
|
|
36
|
-
response
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 >= '
|
|
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&b=2\" foo=\""bar"\">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
|
data/lib/roda/plugins/public.rb
CHANGED
|
@@ -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
|
data/lib/roda/plugins/render.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
|
@@ -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
|
-
|
|
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 >= '
|
|
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
|
-
|
|
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
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.
|
|
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-
|
|
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
|