uri-whatwg_parser 0.2.1 → 0.3.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.md +5 -0
- data/README.md +1 -1
- data/lib/uri/whatwg_parser/generic.rb +103 -31
- data/lib/uri/whatwg_parser/version.rb +1 -1
- data/lib/uri/whatwg_parser.rb +47 -32
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7e3c073b711f9600fd66938070b1cc254a1067b684437f27038a69bc65076c9c
|
|
4
|
+
data.tar.gz: fe833972e0fe8265958d94a97b127983bca064cd29f554c78fb1c2459be008f9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 541f8b1b1d02b2ac2f16b4af59e5fe3b02e01b2f291529b2698590d01dfc6e1da528926920af1dad8c2d21a11437030356859b30d6e972d2fd3e54aad04cd89a
|
|
7
|
+
data.tar.gz: 639c0241664afd68d4f0f4c2cea36e71f484cb53215fc12bb89e65749626e1769e9a777420201468e7863a624afe62a0bb8839776a9e565252a35211c845dbf4
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Ruby implementation of the [WHATWG URL Living Standard](https://url.spec.whatwg.org/).
|
|
4
4
|
|
|
5
|
-
The latest revision that this package implements of the standard is [
|
|
5
|
+
The latest revision that this package implements of the standard is [14 April 2026](https://url.spec.whatwg.org/commit-snapshots/b11d73b8caefe90403afe19210db05acba897722/)
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -3,16 +3,11 @@ require "uri/generic"
|
|
|
3
3
|
module URI
|
|
4
4
|
class WhatwgParser
|
|
5
5
|
module Generic
|
|
6
|
-
def initialize(scheme,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
parser = DEFAULT_PARSER,
|
|
12
|
-
arg_check = false)
|
|
13
|
-
|
|
14
|
-
return super unless URI::DEFAULT_PARSER.is_a?(URI::WhatwgParser)
|
|
15
|
-
return super if registry
|
|
6
|
+
def initialize(scheme, userinfo, host, port, registry, path, opaque, query, fragment, parser = DEFAULT_PARSER, arg_check = false)
|
|
7
|
+
@parsed_by_whatwg_parser = parser.is_a?(URI::WhatwgParser)
|
|
8
|
+
unless parser.is_a?(URI::WhatwgParser)
|
|
9
|
+
return super(scheme, userinfo, host, port, registry, path, opaque, query, fragment)
|
|
10
|
+
end
|
|
16
11
|
|
|
17
12
|
@scheme = nil
|
|
18
13
|
@user = nil
|
|
@@ -20,6 +15,7 @@ module URI
|
|
|
20
15
|
@host = nil
|
|
21
16
|
@port = nil
|
|
22
17
|
@path = nil
|
|
18
|
+
@raw_path = nil
|
|
23
19
|
@query = nil
|
|
24
20
|
@opaque = nil
|
|
25
21
|
@fragment = nil
|
|
@@ -32,64 +28,67 @@ module URI
|
|
|
32
28
|
self.set_path(path)
|
|
33
29
|
self.query = query
|
|
34
30
|
self.set_opaque(opaque)
|
|
35
|
-
|
|
31
|
+
@fragment = fragment
|
|
32
|
+
@raw_path = parser&.path
|
|
36
33
|
|
|
37
34
|
self.set_path("") if !@path && !@opaque
|
|
38
|
-
|
|
35
|
+
parser.parse(to_s) if arg_check
|
|
39
36
|
|
|
40
37
|
@scheme&.freeze
|
|
41
38
|
self.set_port(self.default_port) if self.default_port && !@port
|
|
42
39
|
end
|
|
43
40
|
|
|
44
41
|
def merge(oth)
|
|
45
|
-
|
|
42
|
+
return super unless @parsed_by_whatwg_parser
|
|
43
|
+
|
|
44
|
+
parser.join(self.to_s, oth.to_s)
|
|
46
45
|
end
|
|
47
46
|
alias + merge
|
|
48
47
|
|
|
49
48
|
def scheme=(v)
|
|
50
|
-
return super unless
|
|
49
|
+
return super unless @parsed_by_whatwg_parser
|
|
51
50
|
return if v.nil? || v.empty?
|
|
52
51
|
|
|
53
|
-
parse_result =
|
|
52
|
+
parse_result = parser.split("#{v}:", url: self, state_override: :scheme_start_state)
|
|
54
53
|
set_scheme(parse_result[0])
|
|
55
54
|
set_port(parse_result[3])
|
|
56
55
|
end
|
|
57
56
|
|
|
58
57
|
def user=(v)
|
|
59
|
-
return super unless
|
|
58
|
+
return super unless @parsed_by_whatwg_parser
|
|
60
59
|
return v unless v
|
|
61
60
|
|
|
62
61
|
if host.nil? || host.empty? || scheme == "file"
|
|
63
62
|
raise InvalidURIError, "cannot set user when host is nil or file schme"
|
|
64
63
|
end
|
|
65
|
-
set_user(
|
|
64
|
+
set_user(parser.utf8_percent_encode_string(v, URI::WhatwgParser::USERINFO_PERCENT_ENCODE_SET))
|
|
66
65
|
end
|
|
67
66
|
|
|
68
67
|
def password=(v)
|
|
69
|
-
return super unless
|
|
68
|
+
return super unless @parsed_by_whatwg_parser
|
|
70
69
|
return v unless v
|
|
71
70
|
|
|
72
71
|
if host.nil? || host.empty? || scheme == "file"
|
|
73
72
|
raise InvalidURIError, "cannot set password when host is nil or file schme"
|
|
74
73
|
end
|
|
75
|
-
set_password(
|
|
74
|
+
set_password(parser.utf8_percent_encode_string(v, URI::WhatwgParser::USERINFO_PERCENT_ENCODE_SET))
|
|
76
75
|
end
|
|
77
76
|
|
|
78
77
|
def host=(v)
|
|
79
|
-
return super unless
|
|
78
|
+
return super unless @parsed_by_whatwg_parser
|
|
80
79
|
return if v.nil?
|
|
81
80
|
|
|
82
81
|
if @opaque
|
|
83
|
-
raise InvalidURIError, "cannot set host with
|
|
82
|
+
raise InvalidURIError, "cannot set host with opaque"
|
|
84
83
|
end
|
|
85
84
|
|
|
86
|
-
parse_result =
|
|
85
|
+
parse_result = parser.split(v.to_s, url: self, state_override: :host_state)
|
|
87
86
|
set_host(parse_result[2])
|
|
88
87
|
set_port(parse_result[3])
|
|
89
88
|
end
|
|
90
89
|
|
|
91
90
|
def port=(v)
|
|
92
|
-
return super unless
|
|
91
|
+
return super unless @parsed_by_whatwg_parser
|
|
93
92
|
return if v.nil?
|
|
94
93
|
|
|
95
94
|
if v.to_s.empty?
|
|
@@ -101,24 +100,55 @@ module URI
|
|
|
101
100
|
raise InvalidURIError, "cannot set port when host is nil or scheme is file"
|
|
102
101
|
end
|
|
103
102
|
|
|
104
|
-
parse_result =
|
|
103
|
+
parse_result = parser.split("#{v}:", url: self, state_override: :port_state)
|
|
105
104
|
set_port(parse_result[3])
|
|
106
105
|
end
|
|
107
106
|
|
|
108
107
|
def path=(v)
|
|
109
|
-
return super unless
|
|
108
|
+
return super unless @parsed_by_whatwg_parser
|
|
110
109
|
return if v.nil?
|
|
111
110
|
|
|
112
111
|
if @opaque
|
|
113
112
|
raise InvalidURIError, "path conflicts with opaque"
|
|
114
113
|
end
|
|
115
114
|
|
|
116
|
-
parse_result =
|
|
115
|
+
parse_result = parser.split(v.to_s, url: self, state_override: :path_start_state)
|
|
116
|
+
@raw_path = parser.path
|
|
117
117
|
set_path(parse_result[5])
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
+
def query=(v)
|
|
121
|
+
return super unless @parsed_by_whatwg_parser
|
|
122
|
+
|
|
123
|
+
if v.nil? || v.empty?
|
|
124
|
+
@query = nil
|
|
125
|
+
return
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
v = v.start_with?("?") ? v[1..-1] : v
|
|
129
|
+
@query = +""
|
|
130
|
+
|
|
131
|
+
parse_result = parser.split(v, url: self, state_override: :query_state)
|
|
132
|
+
@query = parse_result[7].to_s
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def fragment=(v)
|
|
136
|
+
return super unless @parsed_by_whatwg_parser
|
|
137
|
+
|
|
138
|
+
if v.nil? || v.empty?
|
|
139
|
+
@fragment = nil
|
|
140
|
+
return
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
v = v.start_with?("#") ? v[1..-1] : v
|
|
144
|
+
@fragment = +""
|
|
145
|
+
|
|
146
|
+
parse_result = parser.split(v, url: self, state_override: :fragment_state)
|
|
147
|
+
@fragment = parse_result[8].to_s
|
|
148
|
+
end
|
|
149
|
+
|
|
120
150
|
def userinfo=(userinfo)
|
|
121
|
-
return super unless
|
|
151
|
+
return super unless @parsed_by_whatwg_parser
|
|
122
152
|
|
|
123
153
|
user, password = split_userinfo(userinfo)
|
|
124
154
|
self.user = user
|
|
@@ -126,17 +156,59 @@ module URI
|
|
|
126
156
|
end
|
|
127
157
|
|
|
128
158
|
def check_opaque(v)
|
|
129
|
-
return super unless
|
|
159
|
+
return super unless @parsed_by_whatwg_parser
|
|
160
|
+
|
|
130
161
|
return v unless v
|
|
131
162
|
|
|
132
|
-
if @host || @port || @user
|
|
133
|
-
raise InvalidURIError, "cannot set opaque with host, port,
|
|
163
|
+
if @host || @port || @user
|
|
164
|
+
raise InvalidURIError, "cannot set opaque with host, port, or userinfo"
|
|
134
165
|
end
|
|
135
166
|
|
|
136
167
|
self.set_opaque(v)
|
|
137
|
-
|
|
168
|
+
# NOTE: WHATWG URL Living Standard doesn't define "opaque" setter. So parse a URL whole.
|
|
169
|
+
parser.parse(to_s)
|
|
138
170
|
true
|
|
139
171
|
end
|
|
172
|
+
|
|
173
|
+
def to_s
|
|
174
|
+
return super unless @parsed_by_whatwg_parser
|
|
175
|
+
|
|
176
|
+
str = "".dup
|
|
177
|
+
if @scheme
|
|
178
|
+
str << @scheme
|
|
179
|
+
str << ":"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
if @host || %w[file postgres].include?(@scheme)
|
|
183
|
+
str << "//"
|
|
184
|
+
end
|
|
185
|
+
if self.userinfo
|
|
186
|
+
str << self.userinfo
|
|
187
|
+
str << "@"
|
|
188
|
+
end
|
|
189
|
+
if @host
|
|
190
|
+
str << @host
|
|
191
|
+
end
|
|
192
|
+
if @port && @port != self.default_port
|
|
193
|
+
str << ":"
|
|
194
|
+
str << @port.to_s
|
|
195
|
+
end
|
|
196
|
+
if @host.nil? && @opaque.nil? && @raw_path && @raw_path.length > 1 && @raw_path[0] == ""
|
|
197
|
+
str << "/."
|
|
198
|
+
end
|
|
199
|
+
str << @path if @path
|
|
200
|
+
str << @opaque if @opaque
|
|
201
|
+
if @query
|
|
202
|
+
str << "?"
|
|
203
|
+
str << @query
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if @fragment
|
|
207
|
+
str << "#"
|
|
208
|
+
str << @fragment
|
|
209
|
+
end
|
|
210
|
+
str
|
|
211
|
+
end
|
|
140
212
|
end
|
|
141
213
|
end
|
|
142
214
|
end
|
data/lib/uri/whatwg_parser.rb
CHANGED
|
@@ -36,6 +36,8 @@ module URI
|
|
|
36
36
|
ASCII_ALPHA_UPPERCASE = Set.new(("A".."Z").to_a)
|
|
37
37
|
ASCII_DIGIT = Set.new(("0".."9").to_a)
|
|
38
38
|
|
|
39
|
+
attr_reader :path
|
|
40
|
+
|
|
39
41
|
def initialize
|
|
40
42
|
reset
|
|
41
43
|
@host_parser = HostParser.new
|
|
@@ -46,7 +48,7 @@ module URI
|
|
|
46
48
|
end
|
|
47
49
|
|
|
48
50
|
def parse(input, base: nil, url: nil, state_override: nil) # :nodoc:
|
|
49
|
-
URI.for(*self.split(input, base: base, url: url, state_override: state_override))
|
|
51
|
+
URI.for(*self.split(input, base: base, url: url, state_override: state_override), self)
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
def split(input, base: nil, url: nil, state_override: nil) # :nodoc:
|
|
@@ -54,8 +56,8 @@ module URI
|
|
|
54
56
|
@base = nil
|
|
55
57
|
if base != nil
|
|
56
58
|
ary = split(base, base: nil)
|
|
57
|
-
@base = { scheme: ary[0], userinfo: ary[1], host: ary[2], port: ary[3],
|
|
58
|
-
@
|
|
59
|
+
@base = { scheme: ary[0], userinfo: ary[1], host: ary[2], port: ary[3], query: ary[7], fragment: ary[8]}
|
|
60
|
+
@base_path = @path
|
|
59
61
|
reset
|
|
60
62
|
end
|
|
61
63
|
|
|
@@ -95,8 +97,14 @@ module URI
|
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
userinfo = [@username, @password].compact.reject(&:empty?).join(":")
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
if @path
|
|
101
|
+
if @path.is_a?(Array)
|
|
102
|
+
path = "/#{@path.join("/")}"
|
|
103
|
+
else
|
|
104
|
+
opaque = @path
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
[@parse_result[:scheme], userinfo, @parse_result[:host], @parse_result[:port], nil, path, opaque, @parse_result[:query], @parse_result[:fragment]]
|
|
100
108
|
end
|
|
101
109
|
|
|
102
110
|
def join(*uris)
|
|
@@ -143,10 +151,10 @@ module URI
|
|
|
143
151
|
@at_sign_seen = nil
|
|
144
152
|
@password_token_seen = nil
|
|
145
153
|
@inside_brackets = nil
|
|
146
|
-
@
|
|
154
|
+
@path = nil
|
|
147
155
|
@username = nil
|
|
148
156
|
@password = nil
|
|
149
|
-
@parse_result = {
|
|
157
|
+
@parse_result = {}
|
|
150
158
|
@state_override = nil
|
|
151
159
|
@state = :scheme_start_state
|
|
152
160
|
@special_url = nil
|
|
@@ -207,7 +215,7 @@ module URI
|
|
|
207
215
|
@state = :path_or_authority_state
|
|
208
216
|
@pos += 1
|
|
209
217
|
else
|
|
210
|
-
@
|
|
218
|
+
@path = +""
|
|
211
219
|
@state = :opaque_path_state
|
|
212
220
|
end
|
|
213
221
|
elsif @state_override.nil?
|
|
@@ -220,12 +228,12 @@ module URI
|
|
|
220
228
|
end
|
|
221
229
|
|
|
222
230
|
def no_scheme_state(c)
|
|
223
|
-
raise ParseError, "scheme is missing" if @base.nil? || (
|
|
231
|
+
raise ParseError, "scheme is missing" if @base.nil? || (has_opaque_path?(@base_path) && c != "#")
|
|
224
232
|
|
|
225
|
-
if
|
|
233
|
+
if has_opaque_path?(@base_path) && c == "#"
|
|
226
234
|
@parse_result[:scheme] = @base[:scheme]
|
|
227
235
|
@special_url = special_url?(@base[:scheme])
|
|
228
|
-
@
|
|
236
|
+
@path = @base_path
|
|
229
237
|
@parse_result[:query] = @base[:query]
|
|
230
238
|
@parse_result[:fragment] = nil
|
|
231
239
|
@state = :fragment_state
|
|
@@ -268,7 +276,7 @@ module URI
|
|
|
268
276
|
@username, @password = @base[:userinfo].split(":") if @base[:userinfo]
|
|
269
277
|
@parse_result[:host] = @base[:host]
|
|
270
278
|
@parse_result[:port] = @base[:port]
|
|
271
|
-
@
|
|
279
|
+
@path = @base_path
|
|
272
280
|
@parse_result[:query] = @base[:query]
|
|
273
281
|
|
|
274
282
|
if c == "?"
|
|
@@ -430,7 +438,7 @@ module URI
|
|
|
430
438
|
if !starts_with_windows_drive_letter?(rest)
|
|
431
439
|
shorten_url_path
|
|
432
440
|
else
|
|
433
|
-
@
|
|
441
|
+
@path = nil
|
|
434
442
|
end
|
|
435
443
|
@state = :path_state
|
|
436
444
|
@pos -= 1
|
|
@@ -447,10 +455,10 @@ module URI
|
|
|
447
455
|
else
|
|
448
456
|
if !@base.nil? && @base[:scheme] == "file"
|
|
449
457
|
@parse_result[:host] = @base[:host]
|
|
450
|
-
if !starts_with_windows_drive_letter?(rest) && @
|
|
451
|
-
if @
|
|
452
|
-
@
|
|
453
|
-
@
|
|
458
|
+
if !starts_with_windows_drive_letter?(rest) && @base_path && normalized_windows_drive_letter?(@base_path[0])
|
|
459
|
+
if @path.nil?
|
|
460
|
+
@path ||= []
|
|
461
|
+
@path[0] = @base_path[0]
|
|
454
462
|
end
|
|
455
463
|
end
|
|
456
464
|
end
|
|
@@ -500,29 +508,29 @@ module URI
|
|
|
500
508
|
@pos -= 1 if c != "/"
|
|
501
509
|
@state = :path_state
|
|
502
510
|
elsif @state_override && @parse_result[:host].nil?
|
|
503
|
-
@
|
|
504
|
-
@
|
|
511
|
+
@path ||= []
|
|
512
|
+
@path << ""
|
|
505
513
|
end
|
|
506
514
|
end
|
|
507
515
|
|
|
508
516
|
def path_state(c)
|
|
509
|
-
@
|
|
517
|
+
@path ||= []
|
|
510
518
|
|
|
511
519
|
if (c.nil? || c == "/") || (@special_url && c == "\\") || (!@state_override && (c == "?" || c == "#"))
|
|
512
520
|
if double_dot_path_segments?(@buffer)
|
|
513
521
|
shorten_url_path
|
|
514
522
|
|
|
515
523
|
if c != "/" && !(@special_url && c == "\\")
|
|
516
|
-
@
|
|
524
|
+
@path << ""
|
|
517
525
|
end
|
|
518
526
|
elsif single_dot_path_segments?(@buffer) && c != "/" && !((@special_url && c == "\\"))
|
|
519
|
-
@
|
|
527
|
+
@path << ""
|
|
520
528
|
elsif !single_dot_path_segments?(@buffer)
|
|
521
|
-
if @parse_result[:scheme] == "file" && @
|
|
529
|
+
if @parse_result[:scheme] == "file" && @path.empty? && windows_drive_letter?(@buffer)
|
|
522
530
|
@buffer[1] = ":"
|
|
523
531
|
end
|
|
524
532
|
|
|
525
|
-
@
|
|
533
|
+
@path << @buffer
|
|
526
534
|
end
|
|
527
535
|
|
|
528
536
|
@buffer = +""
|
|
@@ -531,7 +539,7 @@ module URI
|
|
|
531
539
|
@parse_result[:query] = nil
|
|
532
540
|
@state = :query_state
|
|
533
541
|
elsif c == "#"
|
|
534
|
-
@parse_result[:
|
|
542
|
+
@parse_result[:fragment] = nil
|
|
535
543
|
@state = :fragment_state
|
|
536
544
|
end
|
|
537
545
|
else
|
|
@@ -549,12 +557,12 @@ module URI
|
|
|
549
557
|
elsif c == " "
|
|
550
558
|
first_of_rest = @input_chars[@pos + 1]
|
|
551
559
|
if first_of_rest == "?" || first_of_rest == "#"
|
|
552
|
-
@
|
|
560
|
+
@path += "%20"
|
|
553
561
|
else
|
|
554
|
-
@
|
|
562
|
+
@path += " "
|
|
555
563
|
end
|
|
556
564
|
elsif !c.nil?
|
|
557
|
-
@
|
|
565
|
+
@path += utf8_percent_encode(c, C0_CONTROL_PERCENT_ENCODE_SET)
|
|
558
566
|
end
|
|
559
567
|
end
|
|
560
568
|
|
|
@@ -564,7 +572,10 @@ module URI
|
|
|
564
572
|
# TODO: We need to consider encoding here.
|
|
565
573
|
@parse_result[:query] = utf8_percent_encode_string(@buffer, query_percent_encode_set)
|
|
566
574
|
@buffer.clear
|
|
567
|
-
|
|
575
|
+
if c == "#"
|
|
576
|
+
@parse_result[:fragment] = +""
|
|
577
|
+
@state = :fragment_state
|
|
578
|
+
end
|
|
568
579
|
elsif !c.nil?
|
|
569
580
|
@buffer << c
|
|
570
581
|
end
|
|
@@ -600,9 +611,9 @@ module URI
|
|
|
600
611
|
end
|
|
601
612
|
|
|
602
613
|
def shorten_url_path
|
|
603
|
-
return if @
|
|
604
|
-
return if @parse_result[:scheme] == "file" && @
|
|
605
|
-
@
|
|
614
|
+
return if @path.nil? || @path.is_a?(String)
|
|
615
|
+
return if @parse_result[:scheme] == "file" && @path.length == 1 && normalized_windows_drive_letter?(@path.first)
|
|
616
|
+
@path.pop
|
|
606
617
|
end
|
|
607
618
|
|
|
608
619
|
def includes_credentials?
|
|
@@ -638,6 +649,10 @@ module URI
|
|
|
638
649
|
end
|
|
639
650
|
end
|
|
640
651
|
end
|
|
652
|
+
|
|
653
|
+
def has_opaque_path?(path)
|
|
654
|
+
path.is_a?(String)
|
|
655
|
+
end
|
|
641
656
|
end
|
|
642
657
|
|
|
643
658
|
WHATWG_PARSER = URI::WhatwgParser.new
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: uri-whatwg_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yuji Yaginuma
|
|
@@ -66,14 +66,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
66
66
|
requirements:
|
|
67
67
|
- - ">="
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: 3.
|
|
69
|
+
version: 3.0.0
|
|
70
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - ">="
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
74
|
version: '0'
|
|
75
75
|
requirements: []
|
|
76
|
-
rubygems_version: 4.0.
|
|
76
|
+
rubygems_version: 4.0.10
|
|
77
77
|
specification_version: 4
|
|
78
78
|
summary: Ruby implementation of the WHATWG URL Living Standard
|
|
79
79
|
test_files: []
|