roda 2.18.0 → 2.19.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 +12 -0
- data/doc/release_notes/2.18.0.txt +20 -20
- data/doc/release_notes/2.19.0.txt +30 -0
- data/lib/roda.rb +10 -2
- data/lib/roda/plugins/assets.rb +40 -34
- data/lib/roda/plugins/assets_preloading.rb +1 -1
- data/lib/roda/plugins/h.rb +15 -2
- data/lib/roda/plugins/indifferent_params.rb +72 -30
- data/lib/roda/version.rb +1 -1
- data/spec/plugin/assets_preloading_spec.rb +17 -1
- data/spec/plugin/assets_spec.rb +5 -5
- data/spec/plugin/content_for_spec.rb +32 -26
- data/spec/plugin/h_spec.rb +2 -2
- data/spec/plugin/indifferent_params_spec.rb +1 -0
- data/spec/response_spec.rb +10 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b6466dae7413eb39adad4261800c4a31373bd59
|
|
4
|
+
data.tar.gz: e03a612cbbcc10f0745c7c5ac90dd60ba42d2608
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eed87278923a1e0c6c02bf903a42e3951bc2d4f3b7107f3a7e7898287abc374185cdb1fa4456392695bd8649cdc132f31764054dd911a4bd3b4cea24652259ac
|
|
7
|
+
data.tar.gz: 7d79e779afcbd05769a6568920ef5854c5ae9bfdeb9cf5947177efa73a08d1350d63f758ddb747e566991dfccd7df21a1e430b35872d9bae75692b1cd29a027a
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
= 2.19.0 (2016-10-14)
|
|
2
|
+
|
|
3
|
+
* Don't add Content-Type/Content-Length headers for 1xx, 204, 205, 304 statuses (celsworth, jeremyevans) (#101, #102)
|
|
4
|
+
|
|
5
|
+
* Optimize indifferent_params plugin when using Rack 2 (jeremyevans)
|
|
6
|
+
|
|
7
|
+
* Fix assets_paths method in assets plugin when subresource integrity is used (jeremyevans, celsworth)
|
|
8
|
+
|
|
9
|
+
* Make assets plugin depend on h plugin, instead of using Rack::Utils.escape_html (jeremyevans)
|
|
10
|
+
|
|
11
|
+
* Make h plugin not escape / (celsworth, jeremyevans) (#100)
|
|
12
|
+
|
|
1
13
|
= 2.18.0 (2016-09-13)
|
|
2
14
|
|
|
3
15
|
* Add assets_preloading plugin, for creating link tags or Link header for preloading assets (celsworth, jeremyevans) (#98)
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
* A static_routing plugin has been added, which can give a 3-4x
|
|
4
4
|
increase in performance for large number of static routes, and
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
makes routing O(1) for static routes. Static routes are routes
|
|
6
|
+
that match full paths, with no placeholders, and are checked before
|
|
7
|
+
using the normal routing tree.
|
|
8
|
+
|
|
9
|
+
Static routes are defined via class-level static_* routing methods.
|
|
10
|
+
There is a static_* routing method for each HTTP verb (e.g.
|
|
11
|
+
static_get), as well as a static_route method, which will work
|
|
12
|
+
for any HTTP verb, with the verb-specific method taking priority.
|
|
13
|
+
By using static_route, you can get significantly faster performance
|
|
14
|
+
while retaining some of the benefits of Roda's routing tree design
|
|
15
15
|
(simple shared logic with verb specific behavior). Example:
|
|
16
16
|
|
|
17
17
|
plugin :static_routing
|
|
@@ -35,25 +35,25 @@
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
Because static routing routes on the full path instead of by
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
path segment, the methods takes the full path as a string,
|
|
39
|
+
including the leading slash.
|
|
40
40
|
|
|
41
41
|
* An assets_preloading plugin has been added, which makes it simple
|
|
42
42
|
to generate HTML link tags or a Link header value to tell the
|
|
43
|
-
|
|
43
|
+
browser to preload assets for performance reasons.
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
# In routes, using the Link header:
|
|
46
|
+
response.headers['Link'] = preload_assets_link_header(:css)
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
# In templates, using a link tag:
|
|
49
|
+
<%= preload_assets_link_tags(:css) %>
|
|
50
50
|
|
|
51
51
|
= New Features
|
|
52
52
|
|
|
53
53
|
* RodaRequest#real_remaining_path has been added. This is designed
|
|
54
54
|
to be overridden by plugins that modify remaining_path for internal
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
routing purposes. RodaRequest#run now uses real_remaining_path
|
|
56
|
+
when passing requests to other rack applications.
|
|
57
57
|
|
|
58
58
|
* An assets_paths method has been added to the assets plugin. This
|
|
59
59
|
is similar to the assets method, but it returns an array of paths
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
|
|
64
64
|
* The public plugin now works correctly when used with the
|
|
65
65
|
type_routing plugin, for paths ending in extensions that
|
|
66
|
-
|
|
66
|
+
type_routing is configured to handle.
|
|
67
67
|
|
|
68
68
|
* The head plugin now works with the not_allowed plugin if it is
|
|
69
69
|
loaded after the not_allowed plugin.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
= Improvements
|
|
2
|
+
|
|
3
|
+
* The indifferent_params plugin is now optimized when using Rack 2,
|
|
4
|
+
using Rack 2's query_parser API, and it no longer needs to do a
|
|
5
|
+
deep copy of the params.
|
|
6
|
+
|
|
7
|
+
* The Content-Type and Content-Length headers are no longer added
|
|
8
|
+
for 1xx, 204, 205, and 304 responses.
|
|
9
|
+
|
|
10
|
+
* The assets_paths method in the assets plugin now works
|
|
11
|
+
correctly when subresource integrity is enabled.
|
|
12
|
+
|
|
13
|
+
* The asset paths are now escaped in tags by the assets and
|
|
14
|
+
assets_preloading plugins. While it's unlikely a developer
|
|
15
|
+
would use an asset path that requires escaping, that case is
|
|
16
|
+
now handled correctly.
|
|
17
|
+
|
|
18
|
+
* The h plugin no longer calls Rack::Utils.escape_html, instead
|
|
19
|
+
implementing it's own html escaping.
|
|
20
|
+
|
|
21
|
+
* The assets plugin now uses the h plugin, instead of calling
|
|
22
|
+
Rack::Utils.escape_html.
|
|
23
|
+
|
|
24
|
+
= Backwards Compatibility
|
|
25
|
+
|
|
26
|
+
* The h plugin's html escaping no longer escapes "/", which is
|
|
27
|
+
a behavior change if you are using any recent version of rack.
|
|
28
|
+
The security arguments made to escape "/" could be applied to
|
|
29
|
+
many other characters, so if you want to escape "/", you should
|
|
30
|
+
probably use a separate method that escapes all \W characters.
|
data/lib/roda.rb
CHANGED
|
@@ -867,6 +867,7 @@ class Roda
|
|
|
867
867
|
# Instance methods for RodaResponse
|
|
868
868
|
module ResponseMethods
|
|
869
869
|
CONTENT_LENGTH = "Content-Length".freeze
|
|
870
|
+
CONTENT_TYPE = "Content-Type".freeze
|
|
870
871
|
DEFAULT_HEADERS = {"Content-Type" => "text/html".freeze}.freeze
|
|
871
872
|
LOCATION = "Location".freeze
|
|
872
873
|
|
|
@@ -932,10 +933,17 @@ class Roda
|
|
|
932
933
|
# # []]
|
|
933
934
|
def finish
|
|
934
935
|
b = @body
|
|
935
|
-
|
|
936
|
+
empty = b.empty?
|
|
937
|
+
s = (@status ||= empty ? 404 : default_status)
|
|
936
938
|
set_default_headers
|
|
937
939
|
h = @headers
|
|
938
|
-
|
|
940
|
+
|
|
941
|
+
if empty && (s == 304 || s == 204 || s == 205 || (s >= 100 && s <= 199))
|
|
942
|
+
h.delete(CONTENT_TYPE)
|
|
943
|
+
else
|
|
944
|
+
h[CONTENT_LENGTH] ||= @length.to_s
|
|
945
|
+
end
|
|
946
|
+
|
|
939
947
|
[s, h, b]
|
|
940
948
|
end
|
|
941
949
|
|
data/lib/roda/plugins/assets.rb
CHANGED
|
@@ -319,15 +319,17 @@ class Roda
|
|
|
319
319
|
CONTENT_ENCODING = 'Content-Encoding'.freeze
|
|
320
320
|
GZIP = 'gzip'.freeze
|
|
321
321
|
DOTGZ = '.gz'.freeze
|
|
322
|
+
EMPTY_ATTRS = {}.freeze
|
|
322
323
|
|
|
323
324
|
# Internal exception raised when a compressor cannot be found
|
|
324
325
|
CompressorNotFound = Class.new(RodaError)
|
|
325
326
|
|
|
326
|
-
# Load the render and
|
|
327
|
+
# Load the render, caching, and h plugins, since the assets plugin
|
|
327
328
|
# depends on them.
|
|
328
329
|
def self.load_dependencies(app, _opts = nil)
|
|
329
330
|
app.plugin :render
|
|
330
331
|
app.plugin :caching
|
|
332
|
+
app.plugin :h
|
|
331
333
|
end
|
|
332
334
|
|
|
333
335
|
# Setup the options for the plugin. See the Assets module RDoc
|
|
@@ -605,35 +607,23 @@ class Roda
|
|
|
605
607
|
# asset group. See the assets function documentation for details.
|
|
606
608
|
def assets_paths(type)
|
|
607
609
|
o = self.class.assets_opts
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
610
|
+
if type.is_a?(Array)
|
|
611
|
+
ltype, *dirs = type
|
|
612
|
+
else
|
|
613
|
+
ltype = type
|
|
614
|
+
end
|
|
615
|
+
stype = ltype.to_s
|
|
611
616
|
|
|
612
617
|
url_prefix = request.script_name if self.class.opts[:add_script_name]
|
|
613
618
|
|
|
614
619
|
if compiled = o[:compiled]
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
key = dirs.join(DOT)
|
|
618
|
-
ckey = "#{stype}.#{key}"
|
|
619
|
-
if hash = ukey = compiled[ckey]
|
|
620
|
-
ukey = "#{key}.#{ukey}"
|
|
621
|
-
end
|
|
622
|
-
else
|
|
623
|
-
hash = ukey = compiled[stype]
|
|
624
|
-
end
|
|
625
|
-
|
|
626
|
-
if ukey
|
|
627
|
-
if algo = o[:sri]
|
|
628
|
-
integrity = "\" integrity=\"#{algo}-#{ru.escape_html([[hash].pack('H*')].pack('m').tr("\n", EMPTY_STRING))}"
|
|
629
|
-
end
|
|
630
|
-
|
|
631
|
-
[ "#{asset_host}#{url_prefix}/#{o[:"compiled_#{stype}_prefix"]}.#{ukey}.#{stype}#{integrity}" ]
|
|
620
|
+
if ukey = _compiled_assets_hash(type, true)
|
|
621
|
+
["#{o[:compiled_asset_host]}#{url_prefix}/#{o[:"compiled_#{stype}_prefix"]}.#{ukey}.#{stype}"]
|
|
632
622
|
else
|
|
633
623
|
[]
|
|
634
624
|
end
|
|
635
625
|
else
|
|
636
|
-
asset_dir = o[
|
|
626
|
+
asset_dir = o[ltype]
|
|
637
627
|
if dirs && !dirs.empty?
|
|
638
628
|
dirs.each{|f| asset_dir = asset_dir[f]}
|
|
639
629
|
prefix = "#{dirs.join(SLASH)}/" if o[:group_subdirs]
|
|
@@ -652,19 +642,17 @@ class Roda
|
|
|
652
642
|
# When the assets are not compiled, this will result in a separate
|
|
653
643
|
# tag for each asset file. When the assets are compiled, this will
|
|
654
644
|
# result in a single tag to the compiled asset file.
|
|
655
|
-
def assets(type, attrs =
|
|
656
|
-
|
|
657
|
-
attrs = if attrs
|
|
658
|
-
attrs.map{|k,v| "#{k}=\"#{ru.escape_html(v.to_s)}\""}.join(SPACE)
|
|
659
|
-
else
|
|
660
|
-
EMPTY_STRING
|
|
661
|
-
end
|
|
645
|
+
def assets(type, attrs = EMPTY_ATTRS)
|
|
646
|
+
ltype = type.is_a?(Array) ? type[0] : type
|
|
662
647
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
648
|
+
o = self.class.assets_opts
|
|
649
|
+
if o[:compiled] && (algo = o[:sri]) && (hash = _compiled_assets_hash(type))
|
|
650
|
+
attrs = Hash[attrs]
|
|
651
|
+
attrs[:integrity] = "#{algo}-#{h([[hash].pack('H*')].pack('m').tr("\n", EMPTY_STRING))}"
|
|
667
652
|
end
|
|
653
|
+
|
|
654
|
+
attrs = attrs.map{|k,v| "#{k}=\"#{h(v)}\""}.join(SPACE)
|
|
655
|
+
|
|
668
656
|
if ltype == :js
|
|
669
657
|
tag_start = "<script type=\"text/javascript\" #{attrs} src=\""
|
|
670
658
|
tag_end = JS_END
|
|
@@ -673,7 +661,7 @@ class Roda
|
|
|
673
661
|
tag_end = CSS_END
|
|
674
662
|
end
|
|
675
663
|
|
|
676
|
-
assets_paths(type).map{|p| "#{tag_start}#{p}#{tag_end}"}.join(NEWLINE)
|
|
664
|
+
assets_paths(type).map{|p| "#{tag_start}#{h(p)}#{tag_end}"}.join(NEWLINE)
|
|
677
665
|
end
|
|
678
666
|
|
|
679
667
|
# Render the asset with the given filename. When assets are compiled,
|
|
@@ -719,6 +707,24 @@ class Roda
|
|
|
719
707
|
|
|
720
708
|
private
|
|
721
709
|
|
|
710
|
+
def _compiled_assets_hash(type, return_ukey=false)
|
|
711
|
+
compiled = self.class.assets_opts[:compiled]
|
|
712
|
+
type, *dirs = type if type.is_a?(Array)
|
|
713
|
+
stype = type.to_s
|
|
714
|
+
|
|
715
|
+
if dirs && !dirs.empty?
|
|
716
|
+
key = dirs.join(DOT)
|
|
717
|
+
ckey = "#{stype}.#{key}"
|
|
718
|
+
if hash = ukey = compiled[ckey]
|
|
719
|
+
ukey = "#{key}.#{ukey}"
|
|
720
|
+
end
|
|
721
|
+
else
|
|
722
|
+
hash = ukey = compiled[stype]
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
return_ukey ? ukey : hash
|
|
726
|
+
end
|
|
727
|
+
|
|
722
728
|
# Return when the file was last modified. If the file depends on any
|
|
723
729
|
# other files, check the modification times of all dependencies and
|
|
724
730
|
# return the maximum.
|
|
@@ -61,7 +61,7 @@ class Roda
|
|
|
61
61
|
# Return a string of <link> tags for the given asset
|
|
62
62
|
# types/groups.
|
|
63
63
|
def preload_assets_link_tags(*args)
|
|
64
|
-
_preload_assets_array(args).map{|path, as| "<link href=\"#{path}\" rel=\"preload\" as=\"#{as}\">"}.join(NEWLINE)
|
|
64
|
+
_preload_assets_array(args).map{|path, as| "<link href=\"#{h(path)}\" rel=\"preload\" as=\"#{as}\">"}.join(NEWLINE)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Return a string suitable for a Link header for the
|
data/lib/roda/plugins/h.rb
CHANGED
|
@@ -14,10 +14,23 @@ class Roda
|
|
|
14
14
|
# h('<foo>')
|
|
15
15
|
# end
|
|
16
16
|
module H
|
|
17
|
+
# A Hash of entities and their escaped equivalents,
|
|
18
|
+
# to be escaped by h().
|
|
19
|
+
ESCAPE_HTML = {
|
|
20
|
+
"&" => "&".freeze,
|
|
21
|
+
"<" => "<".freeze,
|
|
22
|
+
">" => ">".freeze,
|
|
23
|
+
"'" => "'".freeze,
|
|
24
|
+
'"' => """.freeze,
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
# A Regexp of HTML entities to match for escaping.
|
|
28
|
+
ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
|
|
29
|
+
|
|
17
30
|
module InstanceMethods
|
|
18
31
|
# HTML escape the input and return the escaped version.
|
|
19
|
-
def h(
|
|
20
|
-
|
|
32
|
+
def h(string)
|
|
33
|
+
string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
|
|
21
34
|
end
|
|
22
35
|
end
|
|
23
36
|
end
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
class Roda
|
|
5
5
|
module RodaPlugins
|
|
6
6
|
# The indifferent_params plugin adds a +params+ instance
|
|
7
|
-
# method which
|
|
8
|
-
#
|
|
9
|
-
# Example:
|
|
7
|
+
# method which offers indifferent access to the request
|
|
8
|
+
# params, allowing you to use symbols to lookup values in
|
|
9
|
+
# a hash where the keys are strings. Example:
|
|
10
10
|
#
|
|
11
11
|
# plugin :indifferent_params
|
|
12
12
|
#
|
|
@@ -14,39 +14,81 @@ class Roda
|
|
|
14
14
|
# params[:foo]
|
|
15
15
|
# end
|
|
16
16
|
#
|
|
17
|
-
# The
|
|
18
|
-
#
|
|
19
|
-
# the
|
|
17
|
+
# The exact behavior depends on the version of Rack in use.
|
|
18
|
+
# If you are using Rack 2, this plugin uses rack's API
|
|
19
|
+
# to set the query parser for the request to use indifferent
|
|
20
|
+
# access. Rack 1 doesn't support indifferent access to
|
|
21
|
+
# params, so if you are using Rack 1, this plugin will make
|
|
22
|
+
# a deep copy of the request params hash, where each level
|
|
23
|
+
# uses indifferent access. On Rack 1, The params hash is
|
|
24
|
+
# initialized lazily, so you only pay the penalty of
|
|
25
|
+
# copying the request params if you call the +params+ method.
|
|
20
26
|
#
|
|
21
27
|
# Note that there is a rack-indifferent gem that
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
28
|
+
# monkey patches rack to always use indifferent params. If
|
|
29
|
+
# you are using Rack 1, it is recommended to use
|
|
30
|
+
# rack-indifferent instead of this plugin, as it is faster
|
|
31
|
+
# and has some other minor advantages, though
|
|
32
|
+
# it affects all rack applications instead of just the Roda app that
|
|
26
33
|
# you load the plugin into.
|
|
27
34
|
module IndifferentParams
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
INDIFFERENT_PROC = lambda{|h,k| h[k.to_s] if k.is_a?(Symbol)}
|
|
36
|
+
|
|
37
|
+
if Rack.release > '2'
|
|
38
|
+
class QueryParser < Rack::QueryParser
|
|
39
|
+
# Work around for invalid optimization in rack
|
|
40
|
+
def parse_nested_query(qs, d=nil)
|
|
41
|
+
return make_params.to_params_hash if qs.nil? || qs.empty?
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class Params < Rack::QueryParser::Params
|
|
46
|
+
def initialize(limit = Rack::Utils.key_space_limit)
|
|
47
|
+
@limit = limit
|
|
48
|
+
@size = 0
|
|
49
|
+
@params = Hash.new(&INDIFFERENT_PROC)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
33
53
|
end
|
|
34
54
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
module RequestMethods
|
|
56
|
+
QUERY_PARSER = Rack::Utils.default_query_parser = QueryParser.new(QueryParser::Params, 65536, 100)
|
|
57
|
+
|
|
58
|
+
def query_parser
|
|
59
|
+
QUERY_PARSER
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
module InstanceMethods
|
|
64
|
+
def params
|
|
65
|
+
@_request.params
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
module InstanceMethods
|
|
70
|
+
# A copy of the request params that will automatically
|
|
71
|
+
# convert symbols to strings.
|
|
72
|
+
def params
|
|
73
|
+
@_params ||= indifferent_params(@_request.params)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
# Recursively process the request params and convert
|
|
79
|
+
# hashes to support indifferent access, leaving
|
|
80
|
+
# other values alone.
|
|
81
|
+
def indifferent_params(params)
|
|
82
|
+
case params
|
|
83
|
+
when Hash
|
|
84
|
+
hash = Hash.new(&INDIFFERENT_PROC)
|
|
85
|
+
params.each{|k, v| hash[k] = indifferent_params(v)}
|
|
86
|
+
hash
|
|
87
|
+
when Array
|
|
88
|
+
params.map{|x| indifferent_params(x)}
|
|
89
|
+
else
|
|
90
|
+
params
|
|
91
|
+
end
|
|
50
92
|
end
|
|
51
93
|
end
|
|
52
94
|
end
|
data/lib/roda/version.rb
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
|
|
2
2
|
|
|
3
|
+
run_tests = true
|
|
4
|
+
begin
|
|
5
|
+
begin
|
|
6
|
+
require 'tilt/sass'
|
|
7
|
+
rescue LoadError
|
|
8
|
+
begin
|
|
9
|
+
for lib in %w'tilt sass'
|
|
10
|
+
require lib
|
|
11
|
+
end
|
|
12
|
+
rescue LoadError
|
|
13
|
+
warn "#{lib} not installed, skipping assets_preloading plugin test"
|
|
14
|
+
run_tests = false
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
3
19
|
describe "assets_preloading plugin" do
|
|
4
20
|
before do
|
|
5
21
|
app(:bare) do
|
|
@@ -79,4 +95,4 @@ describe "assets_preloading plugin" do
|
|
|
79
95
|
html = body('/tags-js')
|
|
80
96
|
html.scan('as="script"').count.must_equal 1
|
|
81
97
|
end
|
|
82
|
-
end
|
|
98
|
+
end if run_tests
|
data/spec/plugin/assets_spec.rb
CHANGED
|
@@ -294,20 +294,20 @@ if run_tests
|
|
|
294
294
|
end
|
|
295
295
|
|
|
296
296
|
[[:sha256, 64, 44], [:sha384, 96, 64], [:sha512, 128, 88]].each do |algo, hex_length, base64_length|
|
|
297
|
-
it
|
|
297
|
+
it "should handle :sri option for subresource integrity for #{algo} when compiling assets" do
|
|
298
298
|
app.plugin :assets, :sri=>algo
|
|
299
299
|
app.compile_assets
|
|
300
300
|
html = body('/test')
|
|
301
301
|
html.scan(/<link/).length.must_equal 1
|
|
302
|
-
html =~ %r|integrity="#{algo}-([^"]+)"
|
|
303
|
-
css_hash = $1
|
|
302
|
+
html =~ %r|et" integrity="#{algo}-([^"]+)"|
|
|
303
|
+
css_hash = $1
|
|
304
304
|
css_hash.length.must_equal base64_length
|
|
305
305
|
html =~ %r|href="(/assets/app\.[a-f0-9]{#{hex_length}}\.css)"|
|
|
306
306
|
css = body($1)
|
|
307
307
|
[Digest.const_get(algo.to_s.upcase).digest(css)].pack('m').tr("\n", "").must_equal css_hash
|
|
308
308
|
html.scan(/<script/).length.must_equal 1
|
|
309
|
-
html =~ %r|integrity="#{algo}-([^"]+)"
|
|
310
|
-
js_hash = $1
|
|
309
|
+
html =~ %r|pt" integrity="#{algo}-([^"]+)"|
|
|
310
|
+
js_hash = $1
|
|
311
311
|
js_hash.length.must_equal base64_length
|
|
312
312
|
html =~ %r|src="(/assets/app\.head\.[a-f0-9]{#{hex_length}}\.js)"|
|
|
313
313
|
js = body($1)
|
|
@@ -2,9 +2,8 @@ require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
|
|
|
2
2
|
|
|
3
3
|
begin
|
|
4
4
|
require 'tilt/erb'
|
|
5
|
-
require 'tilt/haml'
|
|
6
5
|
rescue LoadError
|
|
7
|
-
warn "tilt
|
|
6
|
+
warn "tilt not installed, skipping content_for plugin test"
|
|
8
7
|
else
|
|
9
8
|
describe "content_for plugin with erb" do
|
|
10
9
|
before do
|
|
@@ -39,6 +38,37 @@ describe "content_for plugin with erb" do
|
|
|
39
38
|
end
|
|
40
39
|
end
|
|
41
40
|
|
|
41
|
+
describe "content_for plugin with multiple calls to the same key" do
|
|
42
|
+
before do
|
|
43
|
+
app(:bare) do
|
|
44
|
+
plugin :render, :views => './spec/views'
|
|
45
|
+
plugin :content_for
|
|
46
|
+
|
|
47
|
+
route do |r|
|
|
48
|
+
r.root do
|
|
49
|
+
view(:inline => "<% content_for :foo do %>foo<% end %><% content_for :foo do %>baz<% end %>bar", :layout => { :inline => '<%= yield %> <%= content_for(:foo) %>' })
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should replace with multiple calls to the same key by default" do
|
|
56
|
+
body.strip.must_equal "bar baz"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should append with multiple calls to the same key if :append plugin option is used" do
|
|
60
|
+
app.plugin :content_for, :append => true
|
|
61
|
+
body.strip.must_equal "bar foobaz"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
begin
|
|
67
|
+
require 'tilt/erb'
|
|
68
|
+
require 'tilt/haml'
|
|
69
|
+
rescue LoadError
|
|
70
|
+
warn "tilt or haml not installed, skipping content_for plugin haml tests"
|
|
71
|
+
else
|
|
42
72
|
describe "content_for plugin with haml" do
|
|
43
73
|
before do
|
|
44
74
|
app(:bare) do
|
|
@@ -107,28 +137,4 @@ describe "content_for plugin when overriding :engine" do
|
|
|
107
137
|
body('/a').strip.must_equal "bar\nfoo"
|
|
108
138
|
end
|
|
109
139
|
end
|
|
110
|
-
|
|
111
|
-
describe "content_for plugin with multiple calls to the same key" do
|
|
112
|
-
before do
|
|
113
|
-
app(:bare) do
|
|
114
|
-
plugin :render, :views => './spec/views'
|
|
115
|
-
plugin :content_for
|
|
116
|
-
|
|
117
|
-
route do |r|
|
|
118
|
-
r.root do
|
|
119
|
-
view(:inline => "<% content_for :foo do %>foo<% end %><% content_for :foo do %>baz<% end %>bar", :layout => { :inline => '<%= yield %> <%= content_for(:foo) %>' })
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
it "should replace with multiple calls to the same key by default" do
|
|
126
|
-
body.strip.must_equal "bar baz"
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
it "should append with multiple calls to the same key if :append plugin option is used" do
|
|
130
|
-
app.plugin :content_for, :append => true
|
|
131
|
-
body.strip.must_equal "bar foobaz"
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
140
|
end
|
data/spec/plugin/h_spec.rb
CHANGED
|
@@ -3,9 +3,9 @@ require File.expand_path("spec_helper", File.dirname(File.dirname(__FILE__)))
|
|
|
3
3
|
describe "h plugin" do
|
|
4
4
|
it "adds h method for html escaping" do
|
|
5
5
|
app(:h) do |r|
|
|
6
|
-
h("<form>") + h(:form)
|
|
6
|
+
h("<form>") + h(:form) + h("test&<>/'")
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
body.must_equal '<form>
|
|
9
|
+
body.must_equal '<form>formtest&<>/''
|
|
10
10
|
end
|
|
11
11
|
end
|
data/spec/response_spec.rb
CHANGED
|
@@ -65,6 +65,16 @@ describe "response #finish" do
|
|
|
65
65
|
header('Content-Length').must_equal '1'
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
+
it "should not set Content-Type header on a 204 response" do
|
|
69
|
+
app do |r|
|
|
70
|
+
response.status = 204
|
|
71
|
+
throw :halt, response.finish
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
header('Content-Type').must_equal nil
|
|
75
|
+
header('Content-Length').must_equal nil
|
|
76
|
+
end
|
|
77
|
+
|
|
68
78
|
it "should not overwrite existing status" do
|
|
69
79
|
app do |r|
|
|
70
80
|
response.status = 500
|
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: 2.
|
|
4
|
+
version: 2.19.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: 2016-
|
|
11
|
+
date: 2016-10-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -184,6 +184,7 @@ extra_rdoc_files:
|
|
|
184
184
|
- doc/release_notes/2.16.0.txt
|
|
185
185
|
- doc/release_notes/2.17.0.txt
|
|
186
186
|
- doc/release_notes/2.18.0.txt
|
|
187
|
+
- doc/release_notes/2.19.0.txt
|
|
187
188
|
files:
|
|
188
189
|
- CHANGELOG
|
|
189
190
|
- MIT-LICENSE
|
|
@@ -205,6 +206,7 @@ files:
|
|
|
205
206
|
- doc/release_notes/2.16.0.txt
|
|
206
207
|
- doc/release_notes/2.17.0.txt
|
|
207
208
|
- doc/release_notes/2.18.0.txt
|
|
209
|
+
- doc/release_notes/2.19.0.txt
|
|
208
210
|
- doc/release_notes/2.2.0.txt
|
|
209
211
|
- doc/release_notes/2.3.0.txt
|
|
210
212
|
- doc/release_notes/2.4.0.txt
|
|
@@ -420,7 +422,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
420
422
|
version: '0'
|
|
421
423
|
requirements: []
|
|
422
424
|
rubyforge_project:
|
|
423
|
-
rubygems_version: 2.
|
|
425
|
+
rubygems_version: 2.6.6
|
|
424
426
|
signing_key:
|
|
425
427
|
specification_version: 4
|
|
426
428
|
summary: Routing tree web toolkit
|