addressable 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of addressable might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/Gemfile +2 -2
- data/README.md +3 -6
- data/Rakefile +2 -0
- data/lib/addressable.rb +2 -0
- data/lib/addressable/idna.rb +2 -0
- data/lib/addressable/idna/native.rb +4 -2
- data/lib/addressable/idna/pure.rb +2 -3
- data/lib/addressable/template.rb +38 -44
- data/lib/addressable/uri.rb +51 -33
- data/lib/addressable/version.rb +3 -1
- data/spec/addressable/idna_spec.rb +20 -6
- data/spec/addressable/net_http_compat_spec.rb +2 -0
- data/spec/addressable/rack_mount_compat_spec.rb +2 -0
- data/spec/addressable/security_spec.rb +2 -0
- data/spec/addressable/template_spec.rb +66 -2
- data/spec/addressable/uri_spec.rb +84 -11
- data/spec/spec_helper.rb +3 -0
- data/tasks/clobber.rake +2 -0
- data/tasks/gem.rake +4 -2
- data/tasks/git.rake +2 -0
- data/tasks/metrics.rake +2 -0
- data/tasks/rspec.rake +2 -0
- data/tasks/yard.rake +2 -0
- metadata +16 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afa411655b3715e655e0cdca551d20df31b83491
|
4
|
+
data.tar.gz: 0cd2871c45abb19f6b6238ad202856e7afb8619d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16274bd51d38c58b3712dbbdad1368417051937dbe33d74fa73951a39b71d824092c0ecd50005d467db9c914cc074fd0344282df2e23e1182c764b1a1da9750a
|
7
|
+
data.tar.gz: c53ff1d0e09a5e3d997a13a464d50c45fd7d548326f94d3ad40dc97753ce3a47aad4804a62faea48b89775394538982e70ac22d7488fab8ee6594b6816d8ff28
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Addressable 2.6.0
|
2
|
+
- added `tld=` method to allow assignment to the public suffix
|
3
|
+
- most `heuristic_parse` patterns are now case-insensitive
|
4
|
+
- `heuristic_parse` handles more `file://` URI variations
|
5
|
+
- fixes bug in `heuristic_parse` when uri starts with digit
|
6
|
+
- fixes bug in `request_uri=` with query strings
|
7
|
+
- fixes template issues with `nil` and `?` operator
|
8
|
+
- `frozen_string_literal` pragmas added
|
9
|
+
- minor performance improvements in regexps
|
10
|
+
- fixes to eliminate warnings
|
11
|
+
|
12
|
+
# Addressable 2.5.2
|
13
|
+
- better support for frozen string literals
|
14
|
+
- fixed bug w/ uppercase characters in scheme
|
15
|
+
- IDNA errors w/ emoji URLs
|
16
|
+
- compatibility w/ public_suffix 3.x
|
17
|
+
|
18
|
+
# Addressable 2.5.1
|
19
|
+
- allow unicode normalization to be disabled for URI Template expansion
|
20
|
+
- removed duplicate test
|
21
|
+
|
1
22
|
# Addressable 2.5.0
|
2
23
|
- dropping support for Ruby 1.9
|
3
24
|
- adding support for Ruby 2.4 preview
|
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :test do
|
6
|
-
gem 'rspec', '~> 3.
|
6
|
+
gem 'rspec', '~> 3.5'
|
7
7
|
gem 'rspec-its', '~> 1.1'
|
8
8
|
end
|
9
9
|
|
@@ -29,4 +29,4 @@ group :test, :development do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
gem 'idn-ruby', :platform => [:mri_20, :mri_21, :mri_22]
|
32
|
+
gem 'idn-ruby', :platform => [:mri_20, :mri_21, :mri_22, :mri_23, :mri_24]
|
data/README.md
CHANGED
@@ -8,15 +8,12 @@
|
|
8
8
|
</dl>
|
9
9
|
|
10
10
|
[![Gem Version](http://img.shields.io/gem/dt/addressable.svg)][gem]
|
11
|
-
[![Build Status](https://secure.travis-ci.org/sporkmonger/addressable.
|
12
|
-
[![Dependency Status](https://gemnasium.com/sporkmonger/addressable.png?travis)][gemnasium]
|
11
|
+
[![Build Status](https://secure.travis-ci.org/sporkmonger/addressable.svg?branch=master)][travis]
|
13
12
|
[![Test Coverage Status](https://img.shields.io/coveralls/sporkmonger/addressable.svg)][coveralls]
|
14
13
|
[![Documentation Coverage Status](http://inch-ci.org/github/sporkmonger/addressable.svg?branch=master)][inch]
|
15
|
-
[![Gittip Donate](http://img.shields.io/gittip/sporkmonger.png)](https://www.gittip.com/sporkmonger/ "Support Open Source Development w/ Gittip")
|
16
14
|
|
17
15
|
[gem]: https://rubygems.org/gems/addressable
|
18
16
|
[travis]: http://travis-ci.org/sporkmonger/addressable
|
19
|
-
[gemnasium]: https://gemnasium.com/sporkmonger/addressable
|
20
17
|
[coveralls]: https://coveralls.io/r/sporkmonger/addressable
|
21
18
|
[inch]: http://inch-ci.org/github/sporkmonger/addressable
|
22
19
|
|
@@ -59,7 +56,7 @@ For more details, see [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570.txt).
|
|
59
56
|
|
60
57
|
require "addressable/template"
|
61
58
|
|
62
|
-
template = Addressable::Template.new("http://example.com/{?query*}
|
59
|
+
template = Addressable::Template.new("http://example.com/{?query*}")
|
63
60
|
template.expand({
|
64
61
|
"query" => {
|
65
62
|
'foo' => 'bar',
|
@@ -106,7 +103,7 @@ $ gem install idn-ruby
|
|
106
103
|
|
107
104
|
# Semantic Versioning
|
108
105
|
|
109
|
-
This project uses
|
106
|
+
This project uses [Semantic Versioning](https://semver.org/). You can (and should) specify your
|
110
107
|
dependency using a pessimistic version constraint covering the major and minor
|
111
108
|
values:
|
112
109
|
|
data/Rakefile
CHANGED
data/lib/addressable.rb
CHANGED
data/lib/addressable/idna.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding:utf-8
|
2
4
|
#--
|
3
5
|
# Copyright (C) Bob Aman
|
@@ -35,7 +37,7 @@ module Addressable
|
|
35
37
|
def self.to_ascii(value)
|
36
38
|
value.to_s.split('.', -1).map do |segment|
|
37
39
|
if segment.size > 0 && segment.size < 64
|
38
|
-
IDN::Idna.toASCII(segment)
|
40
|
+
IDN::Idna.toASCII(segment, IDN::Idna::ALLOW_UNASSIGNED)
|
39
41
|
elsif segment.size >= 64
|
40
42
|
segment
|
41
43
|
else
|
@@ -47,7 +49,7 @@ module Addressable
|
|
47
49
|
def self.to_unicode(value)
|
48
50
|
value.to_s.split('.', -1).map do |segment|
|
49
51
|
if segment.size > 0 && segment.size < 64
|
50
|
-
IDN::Idna.toUnicode(segment)
|
52
|
+
IDN::Idna.toUnicode(segment, IDN::Idna::ALLOW_UNASSIGNED)
|
51
53
|
elsif segment.size >= 64
|
52
54
|
segment
|
53
55
|
else
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding:utf-8
|
2
4
|
#--
|
3
5
|
# Copyright (C) Bob Aman
|
@@ -146,16 +148,13 @@ module Addressable
|
|
146
148
|
starter_cc = 256 if starter_cc != 0
|
147
149
|
for i in 1...length
|
148
150
|
ch = unpacked[i]
|
149
|
-
cc = lookup_unicode_combining_class(ch)
|
150
151
|
|
151
152
|
if (starter_cc == 0 &&
|
152
153
|
(composite = unicode_compose_pair(starter, ch)) != nil)
|
153
154
|
starter = composite
|
154
|
-
startercc = lookup_unicode_combining_class(composite)
|
155
155
|
else
|
156
156
|
unpacked_result << starter
|
157
157
|
starter = ch
|
158
|
-
startercc = cc
|
159
158
|
end
|
160
159
|
end
|
161
160
|
unpacked_result << starter
|
data/lib/addressable/template.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding:utf-8
|
2
4
|
#--
|
3
5
|
# Copyright (C) Bob Aman
|
@@ -488,6 +490,8 @@ module Addressable
|
|
488
490
|
# @param [Hash] mapping The mapping that corresponds to the pattern.
|
489
491
|
# @param [#validate, #transform] processor
|
490
492
|
# An optional processor object may be supplied.
|
493
|
+
# @param [Boolean] normalize_values
|
494
|
+
# Optional flag to enable/disable unicode normalization. Default: true
|
491
495
|
#
|
492
496
|
# The object should respond to either the <tt>validate</tt> or
|
493
497
|
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
@@ -518,11 +522,11 @@ module Addressable
|
|
518
522
|
# "http://example.com/{?one,two,three}/"
|
519
523
|
# ).partial_expand({"one" => "1", "three" => 3}).pattern
|
520
524
|
# #=> "http://example.com/?one=1{&two}&three=3"
|
521
|
-
def partial_expand(mapping, processor=nil)
|
525
|
+
def partial_expand(mapping, processor=nil, normalize_values=true)
|
522
526
|
result = self.pattern.dup
|
523
527
|
mapping = normalize_keys(mapping)
|
524
528
|
result.gsub!( EXPRESSION ) do |capture|
|
525
|
-
transform_partial_capture(mapping, capture, processor)
|
529
|
+
transform_partial_capture(mapping, capture, processor, normalize_values)
|
526
530
|
end
|
527
531
|
return Addressable::Template.new(result)
|
528
532
|
end
|
@@ -533,6 +537,8 @@ module Addressable
|
|
533
537
|
# @param [Hash] mapping The mapping that corresponds to the pattern.
|
534
538
|
# @param [#validate, #transform] processor
|
535
539
|
# An optional processor object may be supplied.
|
540
|
+
# @param [Boolean] normalize_values
|
541
|
+
# Optional flag to enable/disable unicode normalization. Default: true
|
536
542
|
#
|
537
543
|
# The object should respond to either the <tt>validate</tt> or
|
538
544
|
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
@@ -583,11 +589,11 @@ module Addressable
|
|
583
589
|
# ExampleProcessor
|
584
590
|
# ).to_str
|
585
591
|
# #=> Addressable::Template::InvalidTemplateValueError
|
586
|
-
def expand(mapping, processor=nil)
|
592
|
+
def expand(mapping, processor=nil, normalize_values=true)
|
587
593
|
result = self.pattern.dup
|
588
594
|
mapping = normalize_keys(mapping)
|
589
595
|
result.gsub!( EXPRESSION ) do |capture|
|
590
|
-
transform_capture(mapping, capture, processor)
|
596
|
+
transform_capture(mapping, capture, processor, normalize_values)
|
591
597
|
end
|
592
598
|
return Addressable::URI.parse(result)
|
593
599
|
end
|
@@ -704,6 +710,8 @@ module Addressable
|
|
704
710
|
# The expression to expand
|
705
711
|
# @param [#validate, #transform] processor
|
706
712
|
# An optional processor object may be supplied.
|
713
|
+
# @param [Boolean] normalize_values
|
714
|
+
# Optional flag to enable/disable unicode normalization. Default: true
|
707
715
|
#
|
708
716
|
# The object should respond to either the <tt>validate</tt> or
|
709
717
|
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
@@ -718,56 +726,36 @@ module Addressable
|
|
718
726
|
# after sending the value to the transform method.
|
719
727
|
#
|
720
728
|
# @return [String] The expanded expression
|
721
|
-
def transform_partial_capture(mapping, capture, processor = nil
|
729
|
+
def transform_partial_capture(mapping, capture, processor = nil,
|
730
|
+
normalize_values = true)
|
722
731
|
_, operator, varlist = *capture.match(EXPRESSION)
|
723
732
|
|
724
|
-
vars = varlist.split(
|
733
|
+
vars = varlist.split(",")
|
725
734
|
|
726
|
-
if
|
735
|
+
if operator == "?"
|
727
736
|
# partial expansion of form style query variables sometimes requires a
|
728
737
|
# slight reordering of the variables to produce a valid url.
|
729
738
|
first_to_expand = vars.find { |varspec|
|
730
739
|
_, name, _ = *varspec.match(VARSPEC)
|
731
|
-
mapping.key? name
|
740
|
+
mapping.key?(name) && !mapping[name].nil?
|
732
741
|
}
|
733
742
|
|
734
743
|
vars = [first_to_expand] + vars.reject {|varspec| varspec == first_to_expand} if first_to_expand
|
735
744
|
end
|
736
745
|
|
737
|
-
vars
|
738
|
-
|
739
|
-
.reduce("") do |acc, (varspec, op)|
|
746
|
+
vars.
|
747
|
+
inject("".dup) do |acc, varspec|
|
740
748
|
_, name, _ = *varspec.match(VARSPEC)
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
# Creates a lazy Enumerator of the operators that should be used to expand
|
752
|
-
# variables in a varlist starting with `operator`. For example, an operator
|
753
|
-
# `"?"` results in the sequence `"?","&","&"...`
|
754
|
-
#
|
755
|
-
# @param [String] operator from which to generate a sequence
|
756
|
-
#
|
757
|
-
# @return [Enumerator] sequence of operators
|
758
|
-
def operator_sequence(operator)
|
759
|
-
rest_operator = if "?" == operator
|
760
|
-
"&"
|
761
|
-
else
|
762
|
-
operator
|
763
|
-
end
|
764
|
-
head_operator = operator
|
765
|
-
|
766
|
-
Enumerator.new do |y|
|
767
|
-
y << head_operator.to_s
|
768
|
-
while true
|
769
|
-
y << rest_operator.to_s
|
770
|
-
end
|
749
|
+
next_val = if mapping.key? name
|
750
|
+
transform_capture(mapping, "{#{operator}#{varspec}}",
|
751
|
+
processor, normalize_values)
|
752
|
+
else
|
753
|
+
"{#{operator}#{varspec}}"
|
754
|
+
end
|
755
|
+
# If we've already expanded at least one '?' operator with non-empty
|
756
|
+
# value, change to '&'
|
757
|
+
operator = "&" if (operator == "?") && (next_val != "")
|
758
|
+
acc << next_val
|
771
759
|
end
|
772
760
|
end
|
773
761
|
|
@@ -780,6 +768,9 @@ module Addressable
|
|
780
768
|
# The expression to replace
|
781
769
|
# @param [#validate, #transform] processor
|
782
770
|
# An optional processor object may be supplied.
|
771
|
+
# @param [Boolean] normalize_values
|
772
|
+
# Optional flag to enable/disable unicode normalization. Default: true
|
773
|
+
#
|
783
774
|
#
|
784
775
|
# The object should respond to either the <tt>validate</tt> or
|
785
776
|
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
@@ -794,7 +785,8 @@ module Addressable
|
|
794
785
|
# after sending the value to the transform method.
|
795
786
|
#
|
796
787
|
# @return [String] The expanded expression
|
797
|
-
def transform_capture(mapping, capture, processor=nil
|
788
|
+
def transform_capture(mapping, capture, processor=nil,
|
789
|
+
normalize_values=true)
|
798
790
|
_, operator, varlist = *capture.match(EXPRESSION)
|
799
791
|
return_value = varlist.split(',').inject([]) do |acc, varspec|
|
800
792
|
_, name, modifier = *varspec.match(VARSPEC)
|
@@ -814,7 +806,7 @@ module Addressable
|
|
814
806
|
"Can't convert #{value.class} into String or Array."
|
815
807
|
end
|
816
808
|
|
817
|
-
value = normalize_value(value)
|
809
|
+
value = normalize_value(value) if normalize_values
|
818
810
|
|
819
811
|
if processor == nil || !processor.respond_to?(:transform)
|
820
812
|
# Handle percent escaping
|
@@ -877,7 +869,9 @@ module Addressable
|
|
877
869
|
end
|
878
870
|
if processor.respond_to?(:transform)
|
879
871
|
transformed_value = processor.transform(name, value)
|
880
|
-
|
872
|
+
if normalize_values
|
873
|
+
transformed_value = normalize_value(transformed_value)
|
874
|
+
end
|
881
875
|
end
|
882
876
|
end
|
883
877
|
acc << [name, transformed_value]
|
data/lib/addressable/uri.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding:utf-8
|
2
4
|
#--
|
3
5
|
# Copyright (C) Bob Aman
|
@@ -122,9 +124,9 @@ module Addressable
|
|
122
124
|
user = userinfo.strip[/^([^:]*):?/, 1]
|
123
125
|
password = userinfo.strip[/:(.*)$/, 1]
|
124
126
|
end
|
125
|
-
host = authority.
|
127
|
+
host = authority.sub(
|
126
128
|
/^([^\[\]]*)@/, EMPTY_STR
|
127
|
-
).
|
129
|
+
).sub(
|
128
130
|
/:([^:@\[\]]*?)$/, EMPTY_STR
|
129
131
|
)
|
130
132
|
port = authority[/:([^:@\[\]]*?)$/, 1]
|
@@ -182,18 +184,24 @@ module Addressable
|
|
182
184
|
:scheme => "http"
|
183
185
|
}.merge(hints)
|
184
186
|
case uri
|
185
|
-
when /^http
|
186
|
-
uri.
|
187
|
-
when /^https
|
188
|
-
uri.
|
189
|
-
when /^feed:\/+http
|
190
|
-
uri.
|
191
|
-
when /^feed
|
192
|
-
uri.
|
193
|
-
when
|
194
|
-
uri.
|
187
|
+
when /^http:\//i
|
188
|
+
uri.sub!(/^http:\/+/i, "http://")
|
189
|
+
when /^https:\//i
|
190
|
+
uri.sub!(/^https:\/+/i, "https://")
|
191
|
+
when /^feed:\/+http:\//i
|
192
|
+
uri.sub!(/^feed:\/+http:\/+/i, "feed:http://")
|
193
|
+
when /^feed:\//i
|
194
|
+
uri.sub!(/^feed:\/+/i, "feed://")
|
195
|
+
when %r[^file:/{4}]i
|
196
|
+
uri.sub!(%r[^file:/+]i, "file:////")
|
197
|
+
when %r[^file://localhost/]i
|
198
|
+
uri.sub!(%r[^file://localhost/+]i, "file:///")
|
199
|
+
when %r[^file:/+]i
|
200
|
+
uri.sub!(%r[^file:/+]i, "file:///")
|
195
201
|
when /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
|
196
|
-
uri.
|
202
|
+
uri.sub!(/^/, hints[:scheme] + "://")
|
203
|
+
when /\A\d+\..*:\d+\z/
|
204
|
+
uri = "#{hints[:scheme]}://#{uri}"
|
197
205
|
end
|
198
206
|
match = uri.match(URIREGEX)
|
199
207
|
fragments = match.captures
|
@@ -202,6 +210,7 @@ module Addressable
|
|
202
210
|
new_authority = authority.gsub(/\\/, '/').gsub(/ /, '%20')
|
203
211
|
# NOTE: We want offset 4, not 3!
|
204
212
|
offset = match.offset(4)
|
213
|
+
uri = uri.dup
|
205
214
|
uri[offset[0]...offset[1]] = new_authority
|
206
215
|
end
|
207
216
|
parsed = self.parse(uri)
|
@@ -212,7 +221,7 @@ module Addressable
|
|
212
221
|
new_host = parsed.path[/^([^\/]+\.[^\/]*)/, 1]
|
213
222
|
if new_host
|
214
223
|
parsed.defer_validation do
|
215
|
-
new_path = parsed.path.
|
224
|
+
new_path = parsed.path.sub(
|
216
225
|
Regexp.new("^" + Regexp.escape(new_host)), EMPTY_STR)
|
217
226
|
parsed.host = new_host
|
218
227
|
parsed.path = new_path
|
@@ -263,19 +272,19 @@ module Addressable
|
|
263
272
|
# Otherwise, convert to a String
|
264
273
|
path = path.to_str.strip
|
265
274
|
|
266
|
-
path.
|
275
|
+
path.sub!(/^file:\/?\/?/, EMPTY_STR) if path =~ /^file:\/?\/?/
|
267
276
|
path = SLASH + path if path =~ /^([a-zA-Z])[\|:]/
|
268
277
|
uri = self.parse(path)
|
269
278
|
|
270
279
|
if uri.scheme == nil
|
271
280
|
# Adjust windows-style uris
|
272
|
-
uri.path.
|
281
|
+
uri.path.sub!(/^\/?([a-zA-Z])[\|:][\\\/]/) do
|
273
282
|
"/#{$1.downcase}:/"
|
274
283
|
end
|
275
284
|
uri.path.gsub!(/\\/, SLASH)
|
276
285
|
if File.exist?(uri.path) &&
|
277
286
|
File.stat(uri.path).directory?
|
278
|
-
uri.path.
|
287
|
+
uri.path.sub!(/\/$/, EMPTY_STR)
|
279
288
|
uri.path = uri.path + '/'
|
280
289
|
end
|
281
290
|
|
@@ -436,7 +445,7 @@ module Addressable
|
|
436
445
|
uri = uri.dup
|
437
446
|
# Seriously, only use UTF-8. I'm really not kidding!
|
438
447
|
uri.force_encoding("utf-8")
|
439
|
-
leave_encoded.force_encoding("utf-8")
|
448
|
+
leave_encoded = leave_encoded.dup.force_encoding("utf-8")
|
440
449
|
result = uri.gsub(/%[0-9a-f]{2}/iu) do |sequence|
|
441
450
|
c = sequence[1..3].to_i(16).chr
|
442
451
|
c.force_encoding("utf-8")
|
@@ -847,7 +856,7 @@ module Addressable
|
|
847
856
|
return nil unless self.scheme
|
848
857
|
@normalized_scheme ||= begin
|
849
858
|
if self.scheme =~ /^\s*ssh\+svn\s*$/i
|
850
|
-
"svn+ssh"
|
859
|
+
"svn+ssh".dup
|
851
860
|
else
|
852
861
|
Addressable::URI.normalize_component(
|
853
862
|
self.scheme.strip.downcase,
|
@@ -1032,9 +1041,9 @@ module Addressable
|
|
1032
1041
|
if !current_user && !current_password
|
1033
1042
|
nil
|
1034
1043
|
elsif current_user && current_password
|
1035
|
-
"#{current_user}:#{current_password}"
|
1044
|
+
"#{current_user}:#{current_password}".dup
|
1036
1045
|
elsif current_user && !current_password
|
1037
|
-
"#{current_user}"
|
1046
|
+
"#{current_user}".dup
|
1038
1047
|
end
|
1039
1048
|
end
|
1040
1049
|
# All normalized values should be UTF-8
|
@@ -1101,7 +1110,7 @@ module Addressable
|
|
1101
1110
|
CharacterClasses::HOST)
|
1102
1111
|
result
|
1103
1112
|
else
|
1104
|
-
EMPTY_STR
|
1113
|
+
EMPTY_STR.dup
|
1105
1114
|
end
|
1106
1115
|
end
|
1107
1116
|
# All normalized values should be UTF-8
|
@@ -1168,6 +1177,15 @@ module Addressable
|
|
1168
1177
|
PublicSuffix.parse(self.host, ignore_private: true).tld
|
1169
1178
|
end
|
1170
1179
|
|
1180
|
+
##
|
1181
|
+
# Sets the top-level domain for this URI.
|
1182
|
+
#
|
1183
|
+
# @param [String, #to_str] new_tld The new top-level domain.
|
1184
|
+
def tld=(new_tld)
|
1185
|
+
replaced_tld = domain.sub(/#{tld}\z/, new_tld)
|
1186
|
+
self.host = PublicSuffix::Domain.new(replaced_tld).to_s
|
1187
|
+
end
|
1188
|
+
|
1171
1189
|
##
|
1172
1190
|
# Returns the public suffix domain for this host.
|
1173
1191
|
#
|
@@ -1235,9 +1253,9 @@ module Addressable
|
|
1235
1253
|
new_user = new_userinfo.strip[/^([^:]*):?/, 1]
|
1236
1254
|
new_password = new_userinfo.strip[/:(.*)$/, 1]
|
1237
1255
|
end
|
1238
|
-
new_host = new_authority.
|
1256
|
+
new_host = new_authority.sub(
|
1239
1257
|
/^([^\[\]]*)@/, EMPTY_STR
|
1240
|
-
).
|
1258
|
+
).sub(
|
1241
1259
|
/:([^:@\[\]]*?)$/, EMPTY_STR
|
1242
1260
|
)
|
1243
1261
|
new_port =
|
@@ -1421,7 +1439,7 @@ module Addressable
|
|
1421
1439
|
# @return [String] The components that identify a site.
|
1422
1440
|
def site
|
1423
1441
|
(self.scheme || self.authority) && @site ||= begin
|
1424
|
-
site_string = ""
|
1442
|
+
site_string = "".dup
|
1425
1443
|
site_string << "#{self.scheme}:" if self.scheme != nil
|
1426
1444
|
site_string << "//#{self.authority}" if self.authority != nil
|
1427
1445
|
site_string
|
@@ -1440,7 +1458,7 @@ module Addressable
|
|
1440
1458
|
def normalized_site
|
1441
1459
|
return nil unless self.site
|
1442
1460
|
@normalized_site ||= begin
|
1443
|
-
site_string = ""
|
1461
|
+
site_string = "".dup
|
1444
1462
|
if self.normalized_scheme != nil
|
1445
1463
|
site_string << "#{self.normalized_scheme}:"
|
1446
1464
|
end
|
@@ -1508,7 +1526,7 @@ module Addressable
|
|
1508
1526
|
result = URI.normalize_path(result)
|
1509
1527
|
if result.empty? &&
|
1510
1528
|
["http", "https", "ftp", "tftp"].include?(self.normalized_scheme)
|
1511
|
-
result = SLASH
|
1529
|
+
result = SLASH.dup
|
1512
1530
|
end
|
1513
1531
|
result
|
1514
1532
|
end
|
@@ -1544,7 +1562,7 @@ module Addressable
|
|
1544
1562
|
# @return [String] The path's basename.
|
1545
1563
|
def basename
|
1546
1564
|
# Path cannot be nil
|
1547
|
-
return File.basename(self.path).
|
1565
|
+
return File.basename(self.path).sub(/;[^\/]*$/, EMPTY_STR)
|
1548
1566
|
end
|
1549
1567
|
|
1550
1568
|
##
|
@@ -1694,7 +1712,7 @@ module Addressable
|
|
1694
1712
|
end
|
1695
1713
|
|
1696
1714
|
# new_query_values have form [['key1', 'value1'], ['key2', 'value2']]
|
1697
|
-
buffer = ""
|
1715
|
+
buffer = "".dup
|
1698
1716
|
new_query_values.each do |key, value|
|
1699
1717
|
encoded_key = URI.encode_component(
|
1700
1718
|
key, CharacterClasses::UNRESERVED
|
@@ -1724,7 +1742,7 @@ module Addressable
|
|
1724
1742
|
#
|
1725
1743
|
# @return [String] The request URI required for an HTTP request.
|
1726
1744
|
def request_uri
|
1727
|
-
return nil if self.absolute? && self.scheme !~ /^https?$/
|
1745
|
+
return nil if self.absolute? && self.scheme !~ /^https?$/i
|
1728
1746
|
return (
|
1729
1747
|
(!self.path.empty? ? self.path : SLASH) +
|
1730
1748
|
(self.query ? "?#{self.query}" : EMPTY_STR)
|
@@ -1739,12 +1757,12 @@ module Addressable
|
|
1739
1757
|
if !new_request_uri.respond_to?(:to_str)
|
1740
1758
|
raise TypeError, "Can't convert #{new_request_uri.class} into String."
|
1741
1759
|
end
|
1742
|
-
if self.absolute? && self.scheme !~ /^https?$/
|
1760
|
+
if self.absolute? && self.scheme !~ /^https?$/i
|
1743
1761
|
raise InvalidURIError,
|
1744
1762
|
"Cannot set an HTTP request URI for a non-HTTP URI."
|
1745
1763
|
end
|
1746
1764
|
new_request_uri = new_request_uri.to_str
|
1747
|
-
path_component = new_request_uri[/^([^\?]*)
|
1765
|
+
path_component = new_request_uri[/^([^\?]*)\??(?:.*)$/, 1]
|
1748
1766
|
query_component = new_request_uri[/^(?:[^\?]*)\?(.*)$/, 1]
|
1749
1767
|
path_component = path_component.to_s
|
1750
1768
|
path_component = (!path_component.empty? ? path_component : SLASH)
|
@@ -1900,7 +1918,7 @@ module Addressable
|
|
1900
1918
|
#
|
1901
1919
|
# Removes the right-most path segment from the base path.
|
1902
1920
|
if base_path =~ /\//
|
1903
|
-
base_path.
|
1921
|
+
base_path.sub!(/\/[^\/]+$/, SLASH)
|
1904
1922
|
else
|
1905
1923
|
base_path = EMPTY_STR
|
1906
1924
|
end
|
data/lib/addressable/version.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# encoding:utf-8
|
2
4
|
#--
|
3
5
|
# Copyright (C) Bob Aman
|
@@ -21,7 +23,7 @@ if !defined?(Addressable::VERSION)
|
|
21
23
|
module Addressable
|
22
24
|
module VERSION
|
23
25
|
MAJOR = 2
|
24
|
-
MINOR =
|
26
|
+
MINOR = 6
|
25
27
|
TINY = 0
|
26
28
|
|
27
29
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# coding: utf-8
|
2
4
|
# Copyright (C) Bob Aman
|
3
5
|
#
|
@@ -26,9 +28,9 @@ shared_examples_for "converting from unicode to ASCII" do
|
|
26
28
|
expect(Addressable::IDNA.to_ascii("www.google.com")).to eq("www.google.com")
|
27
29
|
end
|
28
30
|
|
29
|
-
|
30
|
-
it "should convert '#{
|
31
|
-
expect(Addressable::IDNA.to_ascii(
|
31
|
+
long = 'AcinusFallumTrompetumNullunCreditumVisumEstAtCuadLongumEtCefallum.com'
|
32
|
+
it "should convert '#{long}' correctly" do
|
33
|
+
expect(Addressable::IDNA.to_ascii(long)).to eq(long)
|
32
34
|
end
|
33
35
|
|
34
36
|
it "should convert 'www.詹姆斯.com' correctly" do
|
@@ -134,6 +136,12 @@ shared_examples_for "converting from unicode to ASCII" do
|
|
134
136
|
)).to eq("xn--4ud")
|
135
137
|
end
|
136
138
|
|
139
|
+
it "should convert '🌹🌹🌹.ws' correctly" do
|
140
|
+
expect(Addressable::IDNA.to_ascii(
|
141
|
+
"\360\237\214\271\360\237\214\271\360\237\214\271.ws"
|
142
|
+
)).to eq("xn--2h8haa.ws")
|
143
|
+
end
|
144
|
+
|
137
145
|
it "should handle two adjacent '.'s correctly" do
|
138
146
|
expect(Addressable::IDNA.to_ascii(
|
139
147
|
"example..host"
|
@@ -142,9 +150,9 @@ shared_examples_for "converting from unicode to ASCII" do
|
|
142
150
|
end
|
143
151
|
|
144
152
|
shared_examples_for "converting from ASCII to unicode" do
|
145
|
-
|
146
|
-
it "should convert '#{
|
147
|
-
expect(Addressable::IDNA.to_unicode(
|
153
|
+
long = 'AcinusFallumTrompetumNullunCreditumVisumEstAtCuadLongumEtCefallum.com'
|
154
|
+
it "should convert '#{long}' correctly" do
|
155
|
+
expect(Addressable::IDNA.to_unicode(long)).to eq(long)
|
148
156
|
end
|
149
157
|
|
150
158
|
it "should return the identity conversion when punycode decode fails" do
|
@@ -231,6 +239,12 @@ shared_examples_for "converting from ASCII to unicode" do
|
|
231
239
|
)).to eq("\341\206\265")
|
232
240
|
end
|
233
241
|
|
242
|
+
it "should convert '🌹🌹🌹.ws' correctly" do
|
243
|
+
expect(Addressable::IDNA.to_unicode(
|
244
|
+
"xn--2h8haa.ws"
|
245
|
+
)).to eq("\360\237\214\271\360\237\214\271\360\237\214\271.ws")
|
246
|
+
end
|
247
|
+
|
234
248
|
it "should handle two adjacent '.'s correctly" do
|
235
249
|
expect(Addressable::IDNA.to_unicode(
|
236
250
|
"example..host"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# coding: utf-8
|
2
4
|
# Copyright (C) Bob Aman
|
3
5
|
#
|
@@ -82,7 +84,7 @@ describe "Type conversion" do
|
|
82
84
|
:hello => 1234,
|
83
85
|
:nothing => nil,
|
84
86
|
:sym => :symbolic,
|
85
|
-
:decimal => BigDecimal
|
87
|
+
:decimal => BigDecimal('1')
|
86
88
|
}
|
87
89
|
}
|
88
90
|
|
@@ -91,7 +93,7 @@ describe "Type conversion" do
|
|
91
93
|
'{hello}' => '1234',
|
92
94
|
'{nothing}' => '',
|
93
95
|
'{sym}' => 'symbolic',
|
94
|
-
'{decimal}' => '0.1E1'
|
96
|
+
'{decimal}' => RUBY_VERSION < '2.4.0' ? '0.1E1' : '0.1e1'
|
95
97
|
}
|
96
98
|
end
|
97
99
|
|
@@ -949,6 +951,36 @@ describe Addressable::Template do
|
|
949
951
|
)
|
950
952
|
end
|
951
953
|
end
|
954
|
+
context "issue #307 - partial_expand form query with nil params" do
|
955
|
+
subject do
|
956
|
+
Addressable::Template.new("http://example.com/{?one,two,three}/")
|
957
|
+
end
|
958
|
+
it "builds a new pattern with two=nil" do
|
959
|
+
expect(subject.partial_expand(two: nil).pattern).to eq(
|
960
|
+
"http://example.com/{?one}{&three}/"
|
961
|
+
)
|
962
|
+
end
|
963
|
+
it "builds a new pattern with one=nil and two=nil" do
|
964
|
+
expect(subject.partial_expand(one: nil, two: nil).pattern).to eq(
|
965
|
+
"http://example.com/{?three}/"
|
966
|
+
)
|
967
|
+
end
|
968
|
+
it "builds a new pattern with one=1 and two=nil" do
|
969
|
+
expect(subject.partial_expand(one: 1, two: nil).pattern).to eq(
|
970
|
+
"http://example.com/?one=1{&three}/"
|
971
|
+
)
|
972
|
+
end
|
973
|
+
it "builds a new pattern with one=nil and two=2" do
|
974
|
+
expect(subject.partial_expand(one: nil, two: 2).pattern).to eq(
|
975
|
+
"http://example.com/?two=2{&three}/"
|
976
|
+
)
|
977
|
+
end
|
978
|
+
it "builds a new pattern with one=nil" do
|
979
|
+
expect(subject.partial_expand(one: nil).pattern).to eq(
|
980
|
+
"http://example.com/{?two}{&three}/"
|
981
|
+
)
|
982
|
+
end
|
983
|
+
end
|
952
984
|
context "partial_expand with query string" do
|
953
985
|
subject {
|
954
986
|
Addressable::Template.new("http://example.com/{?two,one}/")
|
@@ -969,6 +1001,24 @@ describe Addressable::Template do
|
|
969
1001
|
)
|
970
1002
|
end
|
971
1003
|
end
|
1004
|
+
context "partial expand with unicode values" do
|
1005
|
+
subject do
|
1006
|
+
Addressable::Template.new("http://example.com/{resource}/{query}/")
|
1007
|
+
end
|
1008
|
+
it "normalizes unicode by default" do
|
1009
|
+
template = subject.partial_expand("query" => "Cafe\u0301")
|
1010
|
+
expect(template.pattern).to eq(
|
1011
|
+
"http://example.com/{resource}/Caf%C3%A9/"
|
1012
|
+
)
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
it "does not normalize unicode when byte semantics requested" do
|
1016
|
+
template = subject.partial_expand({"query" => "Cafe\u0301"}, nil, false)
|
1017
|
+
expect(template.pattern).to eq(
|
1018
|
+
"http://example.com/{resource}/Cafe%CC%81/"
|
1019
|
+
)
|
1020
|
+
end
|
1021
|
+
end
|
972
1022
|
end
|
973
1023
|
describe "Partial expand with strings" do
|
974
1024
|
context "partial_expand with two simple values" do
|
@@ -1013,6 +1063,20 @@ describe Addressable::Template do
|
|
1013
1063
|
end
|
1014
1064
|
end
|
1015
1065
|
describe "Expand" do
|
1066
|
+
context "expand with unicode values" do
|
1067
|
+
subject do
|
1068
|
+
Addressable::Template.new("http://example.com/search/{query}/")
|
1069
|
+
end
|
1070
|
+
it "normalizes unicode by default" do
|
1071
|
+
uri = subject.expand("query" => "Cafe\u0301").to_str
|
1072
|
+
expect(uri).to eq("http://example.com/search/Caf%C3%A9/")
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
it "does not normalize unicode when byte semantics requested" do
|
1076
|
+
uri = subject.expand({ "query" => "Cafe\u0301" }, nil, false).to_str
|
1077
|
+
expect(uri).to eq("http://example.com/search/Cafe%CC%81/")
|
1078
|
+
end
|
1079
|
+
end
|
1016
1080
|
context "expand with a processor" do
|
1017
1081
|
subject {
|
1018
1082
|
Addressable::Template.new("http://example.com/search/{query}/")
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# coding: utf-8
|
2
4
|
# Copyright (C) Bob Aman
|
3
5
|
#
|
@@ -125,14 +127,6 @@ describe Addressable::URI, "when created with a non-string authority" do
|
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
128
|
-
describe Addressable::URI, "when created with a non-string authority" do
|
129
|
-
it "should raise an error" do
|
130
|
-
expect(lambda do
|
131
|
-
Addressable::URI.new(:authority => :bogus)
|
132
|
-
end).to raise_error(TypeError)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
130
|
describe Addressable::URI, "when created with a non-string path" do
|
137
131
|
it "should raise an error" do
|
138
132
|
expect(lambda do
|
@@ -963,6 +957,10 @@ describe Addressable::URI, "when frozen" do
|
|
963
957
|
expect(@uri.normalize.query).to eq("a=1")
|
964
958
|
end
|
965
959
|
|
960
|
+
it "returns '/%70a%74%68?a=%31' for #request_uri" do
|
961
|
+
expect(@uri.request_uri).to eq("/%70a%74%68?a=%31")
|
962
|
+
end
|
963
|
+
|
966
964
|
it "returns '1%323' for #fragment" do
|
967
965
|
expect(@uri.fragment).to eq("1%323")
|
968
966
|
end
|
@@ -1979,15 +1977,29 @@ end
|
|
1979
1977
|
|
1980
1978
|
# Section 5.1.2 of RFC 2616
|
1981
1979
|
describe Addressable::URI, "when parsed from " +
|
1982
|
-
"'
|
1980
|
+
"'HTTP://www.w3.org/pub/WWW/TheProject.html'" do
|
1983
1981
|
before do
|
1984
|
-
@uri = Addressable::URI.parse("
|
1982
|
+
@uri = Addressable::URI.parse("HTTP://www.w3.org/pub/WWW/TheProject.html")
|
1985
1983
|
end
|
1986
1984
|
|
1987
1985
|
it "should have the correct request URI" do
|
1988
1986
|
expect(@uri.request_uri).to eq("/pub/WWW/TheProject.html")
|
1989
1987
|
end
|
1990
1988
|
|
1989
|
+
it "should have the correct request URI after assignment" do
|
1990
|
+
@uri.request_uri = "/pub/WWW/TheProject.html?"
|
1991
|
+
expect(@uri.request_uri).to eq("/pub/WWW/TheProject.html?")
|
1992
|
+
expect(@uri.path).to eq("/pub/WWW/TheProject.html")
|
1993
|
+
expect(@uri.query).to eq("")
|
1994
|
+
end
|
1995
|
+
|
1996
|
+
it "should have the correct request URI after assignment" do
|
1997
|
+
@uri.request_uri = "/some/where/else.html"
|
1998
|
+
expect(@uri.request_uri).to eq("/some/where/else.html")
|
1999
|
+
expect(@uri.path).to eq("/some/where/else.html")
|
2000
|
+
expect(@uri.query).to eq(nil)
|
2001
|
+
end
|
2002
|
+
|
1991
2003
|
it "should have the correct request URI after assignment" do
|
1992
2004
|
@uri.request_uri = "/some/where/else.html?query?string"
|
1993
2005
|
expect(@uri.request_uri).to eq("/some/where/else.html?query?string")
|
@@ -2016,7 +2028,7 @@ describe Addressable::URI, "when parsed from " +
|
|
2016
2028
|
|
2017
2029
|
it "should correctly convert to a hash" do
|
2018
2030
|
expect(@uri.to_hash).to eq({
|
2019
|
-
:scheme => "
|
2031
|
+
:scheme => "HTTP",
|
2020
2032
|
:user => nil,
|
2021
2033
|
:password => nil,
|
2022
2034
|
:host => "www.w3.org",
|
@@ -5494,6 +5506,31 @@ describe Addressable::URI, "when given the path '/one/two/'" do
|
|
5494
5506
|
end
|
5495
5507
|
end
|
5496
5508
|
|
5509
|
+
describe Addressable::URI, "when given the tld " do
|
5510
|
+
it "'uk' should have a tld of 'uk'" do
|
5511
|
+
uri = Addressable::URI.parse("http://example.com")
|
5512
|
+
uri.tld = "uk"
|
5513
|
+
|
5514
|
+
expect(uri.tld).to eq("uk")
|
5515
|
+
end
|
5516
|
+
|
5517
|
+
context "which " do
|
5518
|
+
let (:uri) { Addressable::URI.parse("http://comrade.net/path/to/source/") }
|
5519
|
+
|
5520
|
+
it "contains a subdomain" do
|
5521
|
+
uri.tld = "co.uk"
|
5522
|
+
|
5523
|
+
expect(uri.to_s).to eq("http://comrade.co.uk/path/to/source/")
|
5524
|
+
end
|
5525
|
+
|
5526
|
+
it "is part of the domain" do
|
5527
|
+
uri.tld = "com"
|
5528
|
+
|
5529
|
+
expect(uri.to_s).to eq("http://comrade.com/path/to/source/")
|
5530
|
+
end
|
5531
|
+
end
|
5532
|
+
end
|
5533
|
+
|
5497
5534
|
describe Addressable::URI, "when given the path " +
|
5498
5535
|
"'c:\\windows\\My Documents 100%20\\foo.txt'" do
|
5499
5536
|
before do
|
@@ -6231,6 +6268,18 @@ describe Addressable::URI, "when given the input " +
|
|
6231
6268
|
end
|
6232
6269
|
end
|
6233
6270
|
|
6271
|
+
describe Addressable::URI, "when given the input which "\
|
6272
|
+
"start with digits and has specified port" do
|
6273
|
+
before do
|
6274
|
+
@input = "7777.example.org:8089"
|
6275
|
+
end
|
6276
|
+
|
6277
|
+
it "should heuristically parse to 'http://7777.example.org:8089'" do
|
6278
|
+
uri = Addressable::URI.heuristic_parse(@input)
|
6279
|
+
expect(uri.to_s).to eq("http://7777.example.org:8089")
|
6280
|
+
end
|
6281
|
+
end
|
6282
|
+
|
6234
6283
|
describe Addressable::URI, "when given the input " +
|
6235
6284
|
"'feed:///example.com'" do
|
6236
6285
|
before do
|
@@ -6243,6 +6292,18 @@ describe Addressable::URI, "when given the input " +
|
|
6243
6292
|
end
|
6244
6293
|
end
|
6245
6294
|
|
6295
|
+
describe Addressable::URI, "when given the input " +
|
6296
|
+
"'file://localhost/path/to/resource/'" do
|
6297
|
+
before do
|
6298
|
+
@input = "file://localhost/path/to/resource/"
|
6299
|
+
end
|
6300
|
+
|
6301
|
+
it "should heuristically parse to 'file:///path/to/resource/'" do
|
6302
|
+
@uri = Addressable::URI.heuristic_parse(@input)
|
6303
|
+
expect(@uri.to_s).to eq("file:///path/to/resource/")
|
6304
|
+
end
|
6305
|
+
end
|
6306
|
+
|
6246
6307
|
describe Addressable::URI, "when given the input " +
|
6247
6308
|
"'file://path/to/resource/'" do
|
6248
6309
|
before do
|
@@ -6255,6 +6316,18 @@ describe Addressable::URI, "when given the input " +
|
|
6255
6316
|
end
|
6256
6317
|
end
|
6257
6318
|
|
6319
|
+
describe Addressable::URI, "when given the input " +
|
6320
|
+
"'file://///path/to/resource/'" do
|
6321
|
+
before do
|
6322
|
+
@input = "file:///////path/to/resource/"
|
6323
|
+
end
|
6324
|
+
|
6325
|
+
it "should heuristically parse to 'file:////path/to/resource/'" do
|
6326
|
+
@uri = Addressable::URI.heuristic_parse(@input)
|
6327
|
+
expect(@uri.to_s).to eq("file:////path/to/resource/")
|
6328
|
+
end
|
6329
|
+
end
|
6330
|
+
|
6258
6331
|
describe Addressable::URI, "when given the input " +
|
6259
6332
|
"'feed://http://example.com'" do
|
6260
6333
|
before do
|
data/spec/spec_helper.rb
CHANGED
data/tasks/clobber.rake
CHANGED
data/tasks/gem.rake
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rubygems/package_task"
|
2
4
|
|
3
5
|
namespace :gem do
|
@@ -20,8 +22,8 @@ namespace :gem do
|
|
20
22
|
|
21
23
|
s.required_ruby_version = '>= 2.0'
|
22
24
|
|
23
|
-
s.add_runtime_dependency 'public_suffix', '
|
24
|
-
s.add_development_dependency 'bundler', '
|
25
|
+
s.add_runtime_dependency 'public_suffix', '>= 2.0.2', '< 4.0'
|
26
|
+
s.add_development_dependency 'bundler', '>= 1.0', '< 3.0'
|
25
27
|
|
26
28
|
s.require_path = "lib"
|
27
29
|
|
data/tasks/git.rake
CHANGED
data/tasks/metrics.rake
CHANGED
data/tasks/rspec.rake
CHANGED
data/tasks/yard.rake
CHANGED
metadata
CHANGED
@@ -1,49 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: addressable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Aman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: public_suffix
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.0'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: 2.0.2
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '4.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '2.0'
|
30
27
|
- - ">="
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: 2.0.2
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '4.0'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '1.0'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.0'
|
40
43
|
type: :development
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
44
|
-
- - "
|
47
|
+
- - ">="
|
45
48
|
- !ruby/object:Gem::Version
|
46
49
|
version: '1.0'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '3.0'
|
47
53
|
description: |
|
48
54
|
Addressable is a replacement for the URI implementation that is part of
|
49
55
|
Ruby's standard library. It more closely conforms to the relevant RFCs and
|