roda 3.80.0 → 3.82.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +16 -0
- data/doc/release_notes/3.81.0.txt +24 -0
- data/doc/release_notes/3.82.0.txt +43 -0
- data/lib/roda/plugins/assets.rb +3 -1
- data/lib/roda/plugins/capture_erb.rb +17 -5
- data/lib/roda/plugins/exception_page.rb +1 -1
- data/lib/roda/plugins/filter_common_logger.rb +1 -1
- data/lib/roda/plugins/hmac_paths.rb +41 -1
- data/lib/roda/plugins/indifferent_params.rb +0 -3
- data/lib/roda/plugins/not_found.rb +1 -1
- data/lib/roda/plugins/plain_hash_response_headers.rb +1 -1
- data/lib/roda/plugins/public.rb +49 -19
- data/lib/roda/plugins/render.rb +13 -0
- data/lib/roda/plugins/route_csrf.rb +1 -1
- data/lib/roda/plugins/sessions.rb +1 -1
- data/lib/roda/version.rb +1 -1
- metadata +7 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdf5797c96af1d28dc4d13f0c95ac0468d60eb30b6a128b2cee2c26a08eb0a7f
|
4
|
+
data.tar.gz: d687b3cd03657bdcfda6f87a7a7a2a3b55e9a0c4f856cabd3d080865cc7d9ad2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e518b9638e98713ed54fd4c609069edf81a81987adf53ce2b7a09fa7110244f67b109cbe91c9c03d713f824900649d1c4b2ad435823852dcdfd01094f506afae
|
7
|
+
data.tar.gz: '00877a1338b70a5b96dab7fb946e21c7c916c776666286f80251b362e29ca6e040ffeb9b7a7258cf3af4c9246de5a6c35c5332385bd3cb926505776102c9112c'
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
= 3.82.0 (2024-07-12)
|
2
|
+
|
3
|
+
* Add :encodings option to public plugin to support configurable encoding order (jeremyevans)
|
4
|
+
|
5
|
+
* Add :zstd option to public plugin to supplement it to serve zstd-compressed files with .zst extension (jeremyevans)
|
6
|
+
|
7
|
+
* Make capture_erb plugin call integrate better with erubi/capture_block (jeremyevans)
|
8
|
+
|
9
|
+
= 3.81.0 (2024-06-12)
|
10
|
+
|
11
|
+
* Make assets plugin :early_hints option follow Rack 3 SPEC if using Rack 3 (jeremyevans)
|
12
|
+
|
13
|
+
* Correctly parse Ruby 3.4 backtraces in exception_page plugin (jeremyevans)
|
14
|
+
|
15
|
+
* Support :until and :seconds option in hmac_paths plugin, for paths valid only until a specific time (jeremyevans)
|
16
|
+
|
1
17
|
= 3.80.0 (2024-05-10)
|
2
18
|
|
3
19
|
* Support :namespace option in hmac_paths plugin, allowing for easy per-user/per-group HMAC paths (jeremyevans)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* The hmac_paths plugin now supports :until and :seconds options for
|
4
|
+
hmac_path, to create a path that is only valid for a specific amount of
|
5
|
+
time. :until sets a specific time that the path will be valid until,
|
6
|
+
and :seconds makes the path only valid for the given number of seconds.
|
7
|
+
|
8
|
+
hmac_path('/widget/1', until: Time.utc(2100))
|
9
|
+
# => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
|
10
|
+
|
11
|
+
Requests for the path after the given time will not be matched by
|
12
|
+
r.hmac_path.
|
13
|
+
|
14
|
+
= Other Improvements
|
15
|
+
|
16
|
+
* The early_hints plugin now correctly follows the Rack 3 SPEC when
|
17
|
+
using Rack 3. This was not caught previously because Rack only
|
18
|
+
added official support for early_hints in the last month.
|
19
|
+
|
20
|
+
* Ruby 3.4 backtraces are now parsed correctly in the exception_page
|
21
|
+
plugin.
|
22
|
+
|
23
|
+
* Some plugins that accept a block no longer issue an unused block
|
24
|
+
warning on Ruby 3.4.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A :zstd option has been added to the public and multi_public
|
4
|
+
plugins to support serving zstd-compressed files with a .zst
|
5
|
+
extension. This option is similar to the existing :gzip and
|
6
|
+
:brotli plugin options. Chrome started supporting zstd encoding
|
7
|
+
in March.
|
8
|
+
|
9
|
+
* An :encodings option has been added to the public and multi_public
|
10
|
+
plugins, for more control over how encodings are handled. This
|
11
|
+
allows for changing the order in which encodings are attempted, the
|
12
|
+
use of custom encodings, and the use of different file extensions
|
13
|
+
for encodings. Example:
|
14
|
+
|
15
|
+
plugin :public, encodings: {'zstd'=>'.zst', 'deflate'=>'.deflate'}
|
16
|
+
|
17
|
+
If the :encodings option is not provided, the :zstd, :brotli, and
|
18
|
+
:gzip options are used to build an equivalent :encodings option.
|
19
|
+
|
20
|
+
= Other Improvements
|
21
|
+
|
22
|
+
* The capture_erb plugin now integrates better when using
|
23
|
+
erubi/capture_block for <%= method do %> support in ERB templates,
|
24
|
+
using the native capture method provided by the buffer object.
|
25
|
+
|
26
|
+
* Encoding handling has been more optimized in the public plugin.
|
27
|
+
Regexps for the encodings are precomputed, avoiding a regexp
|
28
|
+
allocation per request per encoding attempted. On Ruby 2.4+
|
29
|
+
Regexp#match? is used for better performance. If the
|
30
|
+
Accept-Encoding header is not present, no encoding matching
|
31
|
+
is attemped.
|
32
|
+
|
33
|
+
= Backwards Compatibility
|
34
|
+
|
35
|
+
* The private public_serve_compressed request method in the public
|
36
|
+
plugin now assumes it is called after the encoding is already
|
37
|
+
valid. If you are calling this method in your own code, you now
|
38
|
+
need to perform checks to make sure the client can accept the
|
39
|
+
encoding before calling this method.
|
40
|
+
|
41
|
+
* The :public_gzip and :public_brotli application options are no
|
42
|
+
longer set by the public plugin. The :public_encodings option
|
43
|
+
is now set.
|
data/lib/roda/plugins/assets.rb
CHANGED
@@ -736,7 +736,9 @@ class Roda
|
|
736
736
|
paths = assets_paths(type)
|
737
737
|
if o[:early_hints]
|
738
738
|
early_hint_as = ltype == :js ? 'script' : 'style'
|
739
|
-
|
739
|
+
early_hints = paths.map{|p| "<#{p}>; rel=preload; as=#{early_hint_as}"}
|
740
|
+
early_hints = early_hints.join("\n") if Rack.release < '3'
|
741
|
+
send_early_hints(RodaResponseHeaders::LINK=>early_hints)
|
740
742
|
end
|
741
743
|
paths.map{|p| "#{tag_start}#{h(p)}#{tag_end}"}.join("\n")
|
742
744
|
end
|
@@ -15,6 +15,11 @@ class Roda
|
|
15
15
|
# inside templates. It can be combined with the inject_erb plugin
|
16
16
|
# to wrap template blocks with arbitrary output and then inject the
|
17
17
|
# wrapped output into the template.
|
18
|
+
#
|
19
|
+
# If the output buffer object responds to +capture+ (e.g. when
|
20
|
+
# +erubi/capture_block+ is being used as the template engine),
|
21
|
+
# this will call +capture+ on the output buffer object, instead
|
22
|
+
# of setting the output buffer object temporarily to a new object.
|
18
23
|
module CaptureERB
|
19
24
|
def self.load_dependencies(app)
|
20
25
|
app.plugin :render
|
@@ -25,13 +30,20 @@ class Roda
|
|
25
30
|
# with an empty string, and then yield to the block.
|
26
31
|
# Return the value of the block, converted to a string.
|
27
32
|
# Restore the previous ERB output buffer before returning.
|
28
|
-
def capture_erb
|
33
|
+
def capture_erb(&block)
|
29
34
|
outvar = render_opts[:template_opts][:outvar]
|
30
35
|
buf_was = instance_variable_get(outvar)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
|
37
|
+
if buf_was.respond_to?(:capture)
|
38
|
+
buf_was.capture(&block)
|
39
|
+
else
|
40
|
+
begin
|
41
|
+
instance_variable_set(outvar, String.new)
|
42
|
+
yield.to_s
|
43
|
+
ensure
|
44
|
+
instance_variable_set(outvar, buf_was) if outvar && buf_was
|
45
|
+
end
|
46
|
+
end
|
35
47
|
end
|
36
48
|
end
|
37
49
|
end
|
@@ -245,7 +245,7 @@ END
|
|
245
245
|
|
246
246
|
frames = exception.backtrace.map.with_index do |line, i|
|
247
247
|
frame = {:id=>i}
|
248
|
-
if line =~ /\A(.*?):(\d+)(?::in `(.*)')?\Z/
|
248
|
+
if line =~ /\A(.*?):(\d+)(?::in [`'](.*)')?\Z/
|
249
249
|
filename = frame[:filename] = $1
|
250
250
|
lineno = frame[:lineno] = $2.to_i
|
251
251
|
frame[:function] = $3
|
@@ -112,6 +112,16 @@ class Roda
|
|
112
112
|
# this for POST requests (or other HTTP verbs that can have request bodies), use +r.GET+
|
113
113
|
# instead of +r.params+ to specifically check query string parameters.
|
114
114
|
#
|
115
|
+
# The generated paths can be timestamped, so that they are only valid until a given time
|
116
|
+
# or for a given number of seconds after they are generated, using the :until or :seconds
|
117
|
+
# options:
|
118
|
+
#
|
119
|
+
# hmac_path('/widget/1', until: Time.utc(2100))
|
120
|
+
# # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
|
121
|
+
#
|
122
|
+
# hmac_path('/widget/1', seconds: Time.utc(2100).to_i - Time.now.to_i)
|
123
|
+
# # => "/dc8b6e56e4cbe7815df7880d42f0e02956b2e4c49881b6060ceb0e49745a540d/t/4102444800/widget/1"
|
124
|
+
#
|
115
125
|
# The :namespace option, if provided, should be a string, and it modifies the generated HMACs
|
116
126
|
# to only match those in the same namespace. This can be used to provide different paths to
|
117
127
|
# different users or groups of users.
|
@@ -190,6 +200,11 @@ class Roda
|
|
190
200
|
# r.hmac_path('/1', params: {k: 2})
|
191
201
|
# HMAC_hex(HMAC_hex(secret, ''), '/p/1?k=2')
|
192
202
|
#
|
203
|
+
# The +:until+ and +:seconds+ option include the timestamp in the HMAC:
|
204
|
+
#
|
205
|
+
# r.hmac_path('/1', until: Time.utc(2100))
|
206
|
+
# HMAC_hex(HMAC_hex(secret, ''), '/t/4102444800/1')
|
207
|
+
#
|
193
208
|
# If a +:namespace+ option is provided, the original secret used before the +:root+ option is
|
194
209
|
# an HMAC of the +:secret+ plugin option and the given namespace.
|
195
210
|
#
|
@@ -232,6 +247,8 @@ class Roda
|
|
232
247
|
# the already matched path of the routing tree using r.hmac_path. Defaults
|
233
248
|
# to the empty string, which will returns paths valid for r.hmac_path at
|
234
249
|
# the top level of the routing tree.
|
250
|
+
# :seconds :: Make the given path valid for the given integer number of seconds.
|
251
|
+
# :until :: Make the given path valid until the given Time.
|
235
252
|
def hmac_path(path, opts=OPTS)
|
236
253
|
unless path.is_a?(String) && path.getbyte(0) == 47
|
237
254
|
raise RodaError, "path must be a string starting with /"
|
@@ -242,6 +259,12 @@ class Roda
|
|
242
259
|
raise RodaError, "root must be empty string or string starting with /"
|
243
260
|
end
|
244
261
|
|
262
|
+
if valid_until = opts[:until]
|
263
|
+
valid_until = valid_until.to_i
|
264
|
+
elsif seconds = opts[:seconds]
|
265
|
+
valid_until = Time.now.to_i + seconds
|
266
|
+
end
|
267
|
+
|
245
268
|
flags = String.new
|
246
269
|
path = path.dup
|
247
270
|
|
@@ -258,6 +281,11 @@ class Roda
|
|
258
281
|
flags << 'n'
|
259
282
|
end
|
260
283
|
|
284
|
+
if valid_until
|
285
|
+
flags << 't'
|
286
|
+
path = "/#{valid_until}#{path}"
|
287
|
+
end
|
288
|
+
|
261
289
|
flags << '0' if flags.empty?
|
262
290
|
|
263
291
|
hmac_path = if method
|
@@ -335,7 +363,19 @@ class Roda
|
|
335
363
|
end
|
336
364
|
|
337
365
|
if hmac_path_valid?(mpath, rpath, submitted_hmac, opts)
|
338
|
-
|
366
|
+
if flags.include?('t')
|
367
|
+
on Integer do |int|
|
368
|
+
if int >= Time.now.to_i
|
369
|
+
always(&block)
|
370
|
+
else
|
371
|
+
# Return from method without matching
|
372
|
+
@remaining_path = orig_path
|
373
|
+
return
|
374
|
+
end
|
375
|
+
end
|
376
|
+
else
|
377
|
+
always(&block)
|
378
|
+
end
|
339
379
|
end
|
340
380
|
end
|
341
381
|
|
@@ -53,13 +53,10 @@ class Roda
|
|
53
53
|
|
54
54
|
class Params < Rack::QueryParser::Params
|
55
55
|
if Rack.release >= '3'
|
56
|
-
# rack main branch compatibility
|
57
|
-
# :nocov:
|
58
56
|
if Params < Hash
|
59
57
|
def initialize
|
60
58
|
super(&INDIFFERENT_PROC)
|
61
59
|
end
|
62
|
-
# :nocov:
|
63
60
|
else
|
64
61
|
def initialize
|
65
62
|
@size = 0
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
class Roda
|
5
5
|
module RodaPlugins
|
6
|
-
# The
|
6
|
+
# The plain_hash_response_headers plugin will change Roda to
|
7
7
|
# use a plain hash for response headers. This is Roda's
|
8
8
|
# default behavior on Rack 2, but on Rack 3+, Roda defaults
|
9
9
|
# to using Rack::Headers for response headers for backwards
|
data/lib/roda/plugins/public.rb
CHANGED
@@ -44,15 +44,30 @@ class Roda
|
|
44
44
|
SPLIT = Regexp.union(*[File::SEPARATOR, File::ALT_SEPARATOR].compact)
|
45
45
|
PARSER = URI::DEFAULT_PARSER
|
46
46
|
RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
|
47
|
+
ENCODING_MAP = {:zstd=>'zstd', :brotli=>'br', :gzip=>'gzip'}.freeze
|
48
|
+
ENCODING_EXTENSIONS = {'br'=>'.br', 'gzip'=>'.gz', 'zstd'=>'.zst'}.freeze
|
49
|
+
|
50
|
+
# :nocov:
|
51
|
+
MATCH_METHOD = RUBY_VERSION >= '2.4' ? :match? : :match
|
52
|
+
# :nocov:
|
47
53
|
|
48
54
|
# Use options given to setup a Rack::File instance for serving files. Options:
|
55
|
+
# :brotli :: Whether to serve already brotli-compressed files with a .br extension
|
56
|
+
# for clients supporting "br" transfer encoding.
|
49
57
|
# :default_mime :: The default mime type to use if the mime type is not recognized.
|
58
|
+
# :encodings :: An enumerable of pairs to handle accepted encodings. The first
|
59
|
+
# element of the pair is the accepted encoding name (e.g. 'gzip'),
|
60
|
+
# and the second element of the pair is the file extension (e.g.
|
61
|
+
# '.gz'). This allows configuration of the order in which encodings
|
62
|
+
# are tried, to prefer brotli to zstd for example, or to support
|
63
|
+
# encodings other than zstd, brotli, and gzip. This takes
|
64
|
+
# precedence over the :brotli, :gzip, and :zstd options if given.
|
50
65
|
# :gzip :: Whether to serve already gzipped files with a .gz extension for clients
|
51
|
-
# supporting
|
52
|
-
# :brotli :: Whether to serve already brotli-compressed files with a .br extension
|
53
|
-
# for clients supporting brotli transfer encoding.
|
66
|
+
# supporting "gzip" transfer encoding.
|
54
67
|
# :headers :: A hash of headers to use for statically served files
|
55
68
|
# :root :: Use this option for the root of the public directory (default: "public")
|
69
|
+
# :zstd :: Whether to serve already zstd-compressed files with a .zst extension
|
70
|
+
# for clients supporting "zstd" transfer encoding.
|
56
71
|
def self.configure(app, opts={})
|
57
72
|
if opts[:root]
|
58
73
|
app.opts[:public_root] = app.expand_path(opts[:root])
|
@@ -60,8 +75,18 @@ class Roda
|
|
60
75
|
app.opts[:public_root] = app.expand_path("public")
|
61
76
|
end
|
62
77
|
app.opts[:public_server] = RACK_FILES.new(app.opts[:public_root], opts[:headers]||{}, opts[:default_mime] || 'text/plain')
|
63
|
-
|
64
|
-
|
78
|
+
|
79
|
+
unless encodings = opts[:encodings]
|
80
|
+
if ENCODING_MAP.any?{|k,| opts.has_key?(k)}
|
81
|
+
encodings = ENCODING_MAP.map{|k, v| [v, ENCODING_EXTENSIONS[v]] if opts[k]}.compact
|
82
|
+
end
|
83
|
+
end
|
84
|
+
encodings = (encodings || app.opts[:public_encodings] || EMPTY_ARRAY).map(&:dup).freeze
|
85
|
+
encodings.each do |a|
|
86
|
+
a << /\b#{a[0]}\b/
|
87
|
+
end
|
88
|
+
encodings.each(&:freeze)
|
89
|
+
app.opts[:public_encodings] = encodings
|
65
90
|
end
|
66
91
|
|
67
92
|
module RequestMethods
|
@@ -102,8 +127,13 @@ class Roda
|
|
102
127
|
roda_opts = roda_class.opts
|
103
128
|
path = ::File.join(server.root, *public_path_segments(path))
|
104
129
|
|
105
|
-
|
106
|
-
|
130
|
+
if accept_encoding = env['HTTP_ACCEPT_ENCODING']
|
131
|
+
roda_opts[:public_encodings].each do |enc, ext, regexp|
|
132
|
+
if regexp.send(MATCH_METHOD, accept_encoding)
|
133
|
+
public_serve_compressed(server, path, ext, enc)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
107
137
|
|
108
138
|
if public_file_readable?(path)
|
109
139
|
s, h, b = public_serve(server, path)
|
@@ -113,22 +143,22 @@ class Roda
|
|
113
143
|
end
|
114
144
|
end
|
115
145
|
|
146
|
+
# Serve the compressed file if it exists. This should only
|
147
|
+
# be called if the client will accept the related encoding.
|
116
148
|
def public_serve_compressed(server, path, suffix, encoding)
|
117
|
-
|
118
|
-
compressed_path = path + suffix
|
149
|
+
compressed_path = path + suffix
|
119
150
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
unless s == 304
|
126
|
-
headers[RodaResponseHeaders::CONTENT_TYPE] = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
127
|
-
headers[RodaResponseHeaders::CONTENT_ENCODING] = encoding
|
128
|
-
end
|
151
|
+
if public_file_readable?(compressed_path)
|
152
|
+
s, h, b = public_serve(server, compressed_path)
|
153
|
+
headers = response.headers
|
154
|
+
headers.replace(h)
|
129
155
|
|
130
|
-
|
156
|
+
unless s == 304
|
157
|
+
headers[RodaResponseHeaders::CONTENT_TYPE] = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
|
158
|
+
headers[RodaResponseHeaders::CONTENT_ENCODING] = encoding
|
131
159
|
end
|
160
|
+
|
161
|
+
halt [s, headers, b]
|
132
162
|
end
|
133
163
|
end
|
134
164
|
|
data/lib/roda/plugins/render.rb
CHANGED
@@ -148,6 +148,19 @@ class Roda
|
|
148
148
|
# inject the content into the output. To get similar behavior with Roda, you have
|
149
149
|
# a few different options you can use.
|
150
150
|
#
|
151
|
+
# == Use Erubi::CaptureBlockEngine
|
152
|
+
#
|
153
|
+
# Roda defaults to using Erubi for erb template rendering. Erubi 1.13.0+ includes
|
154
|
+
# support for an erb variant that supports blocks in <tt><%=</tt> and <tt><%==</tt>
|
155
|
+
# tags. To use it:
|
156
|
+
#
|
157
|
+
# require 'erubi/capture_block'
|
158
|
+
# plugin :render, template_opts: {engine_class: Erubi::CaptureBlockEngine}
|
159
|
+
#
|
160
|
+
# See the Erubi documentation for how to capture data inside the block. Make sure
|
161
|
+
# the method call (+some_method+ in the example) returns the output you want added
|
162
|
+
# to the rendered body.
|
163
|
+
#
|
151
164
|
# == Directly Inject Template Output
|
152
165
|
#
|
153
166
|
# You can switch from a <tt><%=</tt> tag to using a <tt><%</tt> tag:
|
@@ -476,7 +476,7 @@ class Roda
|
|
476
476
|
serialized_data << json_data
|
477
477
|
|
478
478
|
cipher_secret = opts[:cipher_secret]
|
479
|
-
if
|
479
|
+
if opts[:per_cookie_cipher_secret]
|
480
480
|
version = "\1"
|
481
481
|
per_cookie_secret_base = SecureRandom.random_bytes(32)
|
482
482
|
cipher_secret = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, cipher_secret, per_cookie_secret_base)
|
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.82.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: 2024-
|
11
|
+
date: 2024-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -122,20 +122,6 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: sassc
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: json
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -255,6 +241,8 @@ extra_rdoc_files:
|
|
255
241
|
- doc/release_notes/3.79.0.txt
|
256
242
|
- doc/release_notes/3.8.0.txt
|
257
243
|
- doc/release_notes/3.80.0.txt
|
244
|
+
- doc/release_notes/3.81.0.txt
|
245
|
+
- doc/release_notes/3.82.0.txt
|
258
246
|
- doc/release_notes/3.9.0.txt
|
259
247
|
files:
|
260
248
|
- CHANGELOG
|
@@ -342,6 +330,8 @@ files:
|
|
342
330
|
- doc/release_notes/3.79.0.txt
|
343
331
|
- doc/release_notes/3.8.0.txt
|
344
332
|
- doc/release_notes/3.80.0.txt
|
333
|
+
- doc/release_notes/3.81.0.txt
|
334
|
+
- doc/release_notes/3.82.0.txt
|
345
335
|
- doc/release_notes/3.9.0.txt
|
346
336
|
- lib/roda.rb
|
347
337
|
- lib/roda/cache.rb
|
@@ -507,7 +497,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
507
497
|
- !ruby/object:Gem::Version
|
508
498
|
version: '0'
|
509
499
|
requirements: []
|
510
|
-
rubygems_version: 3.5.
|
500
|
+
rubygems_version: 3.5.11
|
511
501
|
signing_key:
|
512
502
|
specification_version: 4
|
513
503
|
summary: Routing tree web toolkit
|