uri 0.12.4 → 0.13.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.

Potentially problematic release.


This version of uri might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c43a663680279fb560cd1743d6ddd5c8d856b938381b16c525ca467ca4f53d8
4
- data.tar.gz: 41bf92949944caad1719afe0b2067d5889104430e938e84e183cfd81e2a048c7
3
+ metadata.gz: 8f4eaea3d45b9a860a4a1765dfa211d195929e01ea90e2ff25405fea90948098
4
+ data.tar.gz: 5f962ae3a2b0c56f589df823edf89560420d8c2dced50ac7332e5a6322a772bc
5
5
  SHA512:
6
- metadata.gz: '08c726bbfda93cdeeb7236715ca3c81dfcdaa54dc14084ddd1b61802f819311461973f79845ce410d2e2024ee06ea3921afc5fad3d4323afd9006d5ee2311a06'
7
- data.tar.gz: 60ecac2ccad60019655d96623870256441f8683377ba7f014ea4a6198e3ab9d8387d4a031a1b6e1438cbedcd8f3acd4443b4c48a15c03174fb768aecf4170295
6
+ metadata.gz: 8fb0be9745374a552f34d58d834e206adabc9a81bfc15bc7179c4143b639f0f62dd73ab46637023147e10be72b61ffdb2b18ac32a697d185244026a51560dc54
7
+ data.tar.gz: 6961a3339bfa178cd339a14828cbb4be6d79249fc1d262da0ea7d68095435efe801ef71642866ab0de2e7a5edc759a168e8b54a006f038e446d755c9781dbf49
@@ -0,0 +1,46 @@
1
+ name: Deploy RDoc site to Pages
2
+
3
+ on:
4
+ push:
5
+ branches: [ 'master' ]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ concurrency:
14
+ group: "pages"
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+ - name: Setup Ruby
24
+ uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0
25
+ with:
26
+ ruby-version: '3.2'
27
+ bundler-cache: true
28
+ - name: Setup Pages
29
+ id: pages
30
+ uses: actions/configure-pages@v3
31
+ - name: Build with RDoc
32
+ # Outputs to the './_site' directory by default
33
+ run: bundle exec rake rdoc
34
+ - name: Upload artifact
35
+ uses: actions/upload-pages-artifact@v2
36
+
37
+ deploy:
38
+ environment:
39
+ name: github-pages
40
+ url: ${{ steps.deployment.outputs.page_url }}
41
+ runs-on: ubuntu-latest
42
+ needs: build
43
+ steps:
44
+ - name: Deploy to GitHub Pages
45
+ id: deployment
46
+ uses: actions/deploy-pages@v2
@@ -3,20 +3,21 @@ name: CI
3
3
  on: [push, pull_request]
4
4
 
5
5
  jobs:
6
+ ruby-versions:
7
+ uses: ruby/actions/.github/workflows/ruby_versions.yml@master
8
+ with:
9
+ min_version: 2.5
10
+
6
11
  build:
12
+ needs: ruby-versions
7
13
  name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
14
  strategy:
9
15
  matrix:
10
- ruby: [ 3.1, '3.0', 2.7, 2.6, 2.5, 2.4, head, truffleruby ]
16
+ ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
11
17
  os: [ ubuntu-latest, macos-latest ]
12
- exclude:
13
- - ruby: 2.4
14
- os: macos-latest
15
- - ruby: 2.5
16
- os: macos-latest
17
18
  runs-on: ${{ matrix.os }}
18
19
  steps:
19
- - uses: actions/checkout@v3
20
+ - uses: actions/checkout@v4
20
21
  - name: Set up Ruby
21
22
  uses: ruby/setup-ruby@v1
22
23
  with:
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  Gemfile.lock
10
+ /_site
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # URI
2
2
 
3
3
  [![CI](https://github.com/ruby/uri/actions/workflows/test.yml/badge.svg)](https://github.com/ruby/uri/actions/workflows/test.yml)
4
+ [![Yard Docs](https://img.shields.io/badge/docs-exist-blue.svg)](https://ruby.github.io/uri/)
4
5
 
5
6
  URI is a module providing classes to handle Uniform Resource Identifiers [RFC2396](http://tools.ietf.org/html/rfc2396).
6
7
 
data/Rakefile CHANGED
@@ -7,11 +7,12 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.test_files = FileList["test/**/test_*.rb"]
8
8
  end
9
9
 
10
- task :sync_tool do
11
- require 'fileutils'
12
- FileUtils.cp "../ruby/tool/lib/test/unit/core_assertions.rb", "./test/lib"
13
- FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
14
- FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
10
+ require "rdoc/task"
11
+ RDoc::Task.new do |doc|
12
+ doc.main = "README.md"
13
+ doc.title = "URI - handle Uniform Resource Identifiers"
14
+ doc.rdoc_files = FileList.new %w[lib README.md LICENSE.txt]
15
+ doc.rdoc_dir = "_site" # for github pages
15
16
  end
16
17
 
17
18
  task :default => :test
data/lib/uri/common.rb CHANGED
@@ -19,8 +19,6 @@ module URI
19
19
  Parser = RFC2396_Parser
20
20
  RFC3986_PARSER = RFC3986_Parser.new
21
21
  Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
22
- RFC2396_PARSER = RFC2396_Parser.new
23
- Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
24
22
 
25
23
  # URI::Parser.new
26
24
  DEFAULT_PARSER = Parser.new
@@ -70,16 +68,32 @@ module URI
70
68
  end
71
69
  private_constant :Schemes
72
70
 
71
+ # Registers the given +klass+ as the class to be instantiated
72
+ # when parsing a \URI with the given +scheme+:
73
73
  #
74
- # Register the given +klass+ to be instantiated when parsing URLs with the given +scheme+.
75
- # Note that currently only schemes which after .upcase are valid constant names
76
- # can be registered (no -/+/. allowed).
74
+ # URI.register_scheme('MS_SEARCH', URI::Generic) # => URI::Generic
75
+ # URI.scheme_list['MS_SEARCH'] # => URI::Generic
77
76
  #
77
+ # Note that after calling String#upcase on +scheme+, it must be a valid
78
+ # constant name.
78
79
  def self.register_scheme(scheme, klass)
79
80
  Schemes.const_set(scheme.to_s.upcase, klass)
80
81
  end
81
82
 
82
- # Returns a Hash of the defined schemes.
83
+ # Returns a hash of the defined schemes:
84
+ #
85
+ # URI.scheme_list
86
+ # # =>
87
+ # {"MAILTO"=>URI::MailTo,
88
+ # "LDAPS"=>URI::LDAPS,
89
+ # "WS"=>URI::WS,
90
+ # "HTTP"=>URI::HTTP,
91
+ # "HTTPS"=>URI::HTTPS,
92
+ # "LDAP"=>URI::LDAP,
93
+ # "FILE"=>URI::File,
94
+ # "FTP"=>URI::FTP}
95
+ #
96
+ # Related: URI.register_scheme.
83
97
  def self.scheme_list
84
98
  Schemes.constants.map { |name|
85
99
  [name.to_s.upcase, Schemes.const_get(name)]
@@ -90,9 +104,21 @@ module URI
90
104
  private_constant :INITIAL_SCHEMES
91
105
  Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
92
106
 
107
+ # Returns a new object constructed from the given +scheme+, +arguments+,
108
+ # and +default+:
109
+ #
110
+ # - The new object is an instance of <tt>URI.scheme_list[scheme.upcase]</tt>.
111
+ # - The object is initialized by calling the class initializer
112
+ # using +scheme+ and +arguments+.
113
+ # See URI::Generic.new.
114
+ #
115
+ # Examples:
93
116
  #
94
- # Construct a URI instance, using the scheme to detect the appropriate class
95
- # from +URI.scheme_list+.
117
+ # values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top']
118
+ # URI.for('https', *values)
119
+ # # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
120
+ # URI.for('foo', *values, default: URI::HTTP)
121
+ # # => #<URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
96
122
  #
97
123
  def self.for(scheme, *arguments, default: Generic)
98
124
  const_name = scheme.to_s.upcase
@@ -123,95 +149,49 @@ module URI
123
149
  #
124
150
  class BadURIError < Error; end
125
151
 
126
- #
127
- # == Synopsis
128
- #
129
- # URI::split(uri)
130
- #
131
- # == Args
132
- #
133
- # +uri+::
134
- # String with URI.
135
- #
136
- # == Description
137
- #
138
- # Splits the string on following parts and returns array with result:
139
- #
140
- # * Scheme
141
- # * Userinfo
142
- # * Host
143
- # * Port
144
- # * Registry
145
- # * Path
146
- # * Opaque
147
- # * Query
148
- # * Fragment
149
- #
150
- # == Usage
151
- #
152
- # require 'uri'
153
- #
154
- # URI.split("http://www.ruby-lang.org/")
155
- # # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
152
+ # Returns a 9-element array representing the parts of the \URI
153
+ # formed from the string +uri+;
154
+ # each array element is a string or +nil+:
155
+ #
156
+ # names = %w[scheme userinfo host port registry path opaque query fragment]
157
+ # values = URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
158
+ # names.zip(values)
159
+ # # =>
160
+ # [["scheme", "https"],
161
+ # ["userinfo", "john.doe"],
162
+ # ["host", "www.example.com"],
163
+ # ["port", "123"],
164
+ # ["registry", nil],
165
+ # ["path", "/forum/questions/"],
166
+ # ["opaque", nil],
167
+ # ["query", "tag=networking&order=newest"],
168
+ # ["fragment", "top"]]
156
169
  #
157
170
  def self.split(uri)
158
171
  RFC3986_PARSER.split(uri)
159
172
  end
160
173
 
174
+ # Returns a new \URI object constructed from the given string +uri+:
161
175
  #
162
- # == Synopsis
163
- #
164
- # URI::parse(uri_str)
165
- #
166
- # == Args
167
- #
168
- # +uri_str+::
169
- # String with URI.
170
- #
171
- # == Description
172
- #
173
- # Creates one of the URI's subclasses instance from the string.
174
- #
175
- # == Raises
176
- #
177
- # URI::InvalidURIError::
178
- # Raised if URI given is not a correct one.
176
+ # URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
177
+ # # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
178
+ # URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
179
+ # # => #<URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
179
180
  #
180
- # == Usage
181
- #
182
- # require 'uri'
183
- #
184
- # uri = URI.parse("http://www.ruby-lang.org/")
185
- # # => #<URI::HTTP http://www.ruby-lang.org/>
186
- # uri.scheme
187
- # # => "http"
188
- # uri.host
189
- # # => "www.ruby-lang.org"
190
- #
191
- # It's recommended to first ::escape the provided +uri_str+ if there are any
192
- # invalid URI characters.
181
+ # It's recommended to first ::escape string +uri+
182
+ # if it may contain invalid URI characters.
193
183
  #
194
184
  def self.parse(uri)
195
185
  RFC3986_PARSER.parse(uri)
196
186
  end
197
187
 
188
+ # Merges the given URI strings +str+
189
+ # per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html].
198
190
  #
199
- # == Synopsis
200
- #
201
- # URI::join(str[, str, ...])
191
+ # Each string in +str+ is converted to an
192
+ # {RFC3986 URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged.
202
193
  #
203
- # == Args
204
- #
205
- # +str+::
206
- # String(s) to work with, will be converted to RFC3986 URIs before merging.
207
- #
208
- # == Description
209
- #
210
- # Joins URIs.
211
- #
212
- # == Usage
213
- #
214
- # require 'uri'
194
+ # Examples:
215
195
  #
216
196
  # URI.join("http://example.com/","main.rbx")
217
197
  # # => #<URI::HTTP http://example.com/main.rbx>
@@ -256,7 +236,7 @@ module URI
256
236
  # URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
257
237
  # # => ["http://foo.example.com/bla", "mailto:test@example.com"]
258
238
  #
259
- def self.extract(str, schemes = nil, &block)
239
+ def self.extract(str, schemes = nil, &block) # :nodoc:
260
240
  warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
261
241
  DEFAULT_PARSER.extract(str, schemes, &block)
262
242
  end
@@ -293,7 +273,7 @@ module URI
293
273
  # p $&
294
274
  # end
295
275
  #
296
- def self.regexp(schemes = nil)
276
+ def self.regexp(schemes = nil)# :nodoc:
297
277
  warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
298
278
  DEFAULT_PARSER.make_regexp(schemes)
299
279
  end
@@ -316,40 +296,86 @@ module URI
316
296
  TBLDECWWWCOMP_['+'] = ' '
317
297
  TBLDECWWWCOMP_.freeze
318
298
 
319
- # Encodes given +str+ to URL-encoded form data.
299
+ # Returns a URL-encoded string derived from the given string +str+.
300
+ #
301
+ # The returned string:
302
+ #
303
+ # - Preserves:
304
+ #
305
+ # - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
306
+ # - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
307
+ # and <tt>'0'..'9'</tt>.
308
+ #
309
+ # Example:
320
310
  #
321
- # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
322
- # (ASCII space) to + and converts others to %XX.
311
+ # URI.encode_www_form_component('*.-_azAZ09')
312
+ # # => "*.-_azAZ09"
323
313
  #
324
- # If +enc+ is given, convert +str+ to the encoding before percent encoding.
314
+ # - Converts:
325
315
  #
326
- # This is an implementation of
327
- # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
316
+ # - Character <tt>' '</tt> to character <tt>'+'</tt>.
317
+ # - Any other character to "percent notation";
318
+ # the percent notation for character <i>c</i> is <tt>'%%%X' % c.ord</tt>.
328
319
  #
329
- # See URI.decode_www_form_component, URI.encode_www_form.
320
+ # Example:
321
+ #
322
+ # URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
323
+ # # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
324
+ #
325
+ # Encoding:
326
+ #
327
+ # - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored.
328
+ # - Otherwise +str+ is converted first to Encoding::UTF_8
329
+ # (with suitable character replacements),
330
+ # and then to encoding +enc+.
331
+ #
332
+ # In either case, the returned string has forced encoding Encoding::US_ASCII.
333
+ #
334
+ # Related: URI.encode_uri_component (encodes <tt>' '</tt> as <tt>'%20'</tt>).
330
335
  def self.encode_www_form_component(str, enc=nil)
331
336
  _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
332
337
  end
333
338
 
334
- # Decodes given +str+ of URL-encoded form data.
339
+ # Returns a string decoded from the given \URL-encoded string +str+.
340
+ #
341
+ # The given string is first encoded as Encoding::ASCII-8BIT (using String#b),
342
+ # then decoded (as below), and finally force-encoded to the given encoding +enc+.
343
+ #
344
+ # The returned string:
345
+ #
346
+ # - Preserves:
347
+ #
348
+ # - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
349
+ # - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
350
+ # and <tt>'0'..'9'</tt>.
351
+ #
352
+ # Example:
353
+ #
354
+ # URI.decode_www_form_component('*.-_azAZ09')
355
+ # # => "*.-_azAZ09"
356
+ #
357
+ # - Converts:
358
+ #
359
+ # - Character <tt>'+'</tt> to character <tt>' '</tt>.
360
+ # - Each "percent notation" to an ASCII character.
335
361
  #
336
- # This decodes + to SP.
362
+ # Example:
337
363
  #
338
- # See URI.encode_www_form_component, URI.decode_www_form.
364
+ # URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A')
365
+ # # => "Here are some punctuation characters: ,;?:"
366
+ #
367
+ # Related: URI.decode_uri_component (preserves <tt>'+'</tt>).
339
368
  def self.decode_www_form_component(str, enc=Encoding::UTF_8)
340
369
  _decode_uri_component(/\+|%\h\h/, str, enc)
341
370
  end
342
371
 
343
- # Encodes +str+ using URL encoding
344
- #
345
- # This encodes SP to %20 instead of +.
372
+ # Like URI.encode_www_form_component, except that <tt>' '</tt> (space)
373
+ # is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>).
346
374
  def self.encode_uri_component(str, enc=nil)
347
375
  _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
348
376
  end
349
377
 
350
- # Decodes given +str+ of URL-encoded data.
351
- #
352
- # This does not decode + to SP.
378
+ # Like URI.decode_www_form_component, except that <tt>'+'</tt> is preserved.
353
379
  def self.decode_uri_component(str, enc=Encoding::UTF_8)
354
380
  _decode_uri_component(/%\h\h/, str, enc)
355
381
  end
@@ -374,33 +400,104 @@ module URI
374
400
  end
375
401
  private_class_method :_decode_uri_component
376
402
 
377
- # Generates URL-encoded form data from given +enum+.
403
+ # Returns a URL-encoded string derived from the given
404
+ # {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes]
405
+ # +enum+.
406
+ #
407
+ # The result is suitable for use as form data
408
+ # for an \HTTP request whose <tt>Content-Type</tt> is
409
+ # <tt>'application/x-www-form-urlencoded'</tt>.
410
+ #
411
+ # The returned string consists of the elements of +enum+,
412
+ # each converted to one or more URL-encoded strings,
413
+ # and all joined with character <tt>'&'</tt>.
414
+ #
415
+ # Simple examples:
416
+ #
417
+ # URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]])
418
+ # # => "foo=0&bar=1&baz=2"
419
+ # URI.encode_www_form({foo: 0, bar: 1, baz: 2})
420
+ # # => "foo=0&bar=1&baz=2"
421
+ #
422
+ # The returned string is formed using method URI.encode_www_form_component,
423
+ # which converts certain characters:
424
+ #
425
+ # URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
426
+ # # => "f%23o=%2F&b-r=%24&b+z=%40"
427
+ #
428
+ # When +enum+ is Array-like, each element +ele+ is converted to a field:
429
+ #
430
+ # - If +ele+ is an array of two or more elements,
431
+ # the field is formed from its first two elements
432
+ # (and any additional elements are ignored):
433
+ #
434
+ # name = URI.encode_www_form_component(ele[0], enc)
435
+ # value = URI.encode_www_form_component(ele[1], enc)
436
+ # "#{name}=#{value}"
378
437
  #
379
- # This generates application/x-www-form-urlencoded data defined in HTML5
380
- # from given an Enumerable object.
438
+ # Examples:
381
439
  #
382
- # This internally uses URI.encode_www_form_component(str).
440
+ # URI.encode_www_form([%w[foo bar], %w[baz bat bah]])
441
+ # # => "foo=bar&baz=bat"
442
+ # URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']])
443
+ # # => "foo=0&bar=baz"
383
444
  #
384
- # This method doesn't convert the encoding of given items, so convert them
385
- # before calling this method if you want to send data as other than original
386
- # encoding or mixed encoding data. (Strings which are encoded in an HTML5
387
- # ASCII incompatible encoding are converted to UTF-8.)
445
+ # - If +ele+ is an array of one element,
446
+ # the field is formed from <tt>ele[0]</tt>:
388
447
  #
389
- # This method doesn't handle files. When you send a file, use
390
- # multipart/form-data.
448
+ # URI.encode_www_form_component(ele[0])
391
449
  #
392
- # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer
450
+ # Example:
393
451
  #
394
- # URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
395
- # #=> "q=ruby&lang=en"
396
- # URI.encode_www_form("q" => "ruby", "lang" => "en")
397
- # #=> "q=ruby&lang=en"
398
- # URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
399
- # #=> "q=ruby&q=perl&lang=en"
400
- # URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
401
- # #=> "q=ruby&q=perl&lang=en"
452
+ # URI.encode_www_form([['foo'], [:bar], [0]])
453
+ # # => "foo&bar&0"
454
+ #
455
+ # - Otherwise the field is formed from +ele+:
456
+ #
457
+ # URI.encode_www_form_component(ele)
458
+ #
459
+ # Example:
460
+ #
461
+ # URI.encode_www_form(['foo', :bar, 0])
462
+ # # => "foo&bar&0"
463
+ #
464
+ # The elements of an Array-like +enum+ may be mixture:
465
+ #
466
+ # URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat])
467
+ # # => "foo=0&bar=1&baz&bat"
468
+ #
469
+ # When +enum+ is Hash-like,
470
+ # each +key+/+value+ pair is converted to one or more fields:
471
+ #
472
+ # - If +value+ is
473
+ # {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects],
474
+ # each element +ele+ in +value+ is paired with +key+ to form a field:
475
+ #
476
+ # name = URI.encode_www_form_component(key, enc)
477
+ # value = URI.encode_www_form_component(ele, enc)
478
+ # "#{name}=#{value}"
479
+ #
480
+ # Example:
481
+ #
482
+ # URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]})
483
+ # # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2"
484
+ #
485
+ # - Otherwise, +key+ and +value+ are paired to form a field:
486
+ #
487
+ # name = URI.encode_www_form_component(key, enc)
488
+ # value = URI.encode_www_form_component(value, enc)
489
+ # "#{name}=#{value}"
490
+ #
491
+ # Example:
492
+ #
493
+ # URI.encode_www_form({foo: 0, bar: 1, baz: 2})
494
+ # # => "foo=0&bar=1&baz=2"
495
+ #
496
+ # The elements of a Hash-like +enum+ may be mixture:
497
+ #
498
+ # URI.encode_www_form({foo: [0, 1], bar: 2})
499
+ # # => "foo=0&foo=1&bar=2"
402
500
  #
403
- # See URI.encode_www_form_component, URI.decode_www_form.
404
501
  def self.encode_www_form(enum, enc=nil)
405
502
  enum.map do |k,v|
406
503
  if v.nil?
@@ -421,22 +518,39 @@ module URI
421
518
  end.join('&')
422
519
  end
423
520
 
424
- # Decodes URL-encoded form data from given +str+.
521
+ # Returns name/value pairs derived from the given string +str+,
522
+ # which must be an ASCII string.
523
+ #
524
+ # The method may be used to decode the body of Net::HTTPResponse object +res+
525
+ # for which <tt>res['Content-Type']</tt> is <tt>'application/x-www-form-urlencoded'</tt>.
526
+ #
527
+ # The returned data is an array of 2-element subarrays;
528
+ # each subarray is a name/value pair (both are strings).
529
+ # Each returned string has encoding +enc+,
530
+ # and has had invalid characters removed via
531
+ # {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub].
425
532
  #
426
- # This decodes application/x-www-form-urlencoded data
427
- # and returns an array of key-value arrays.
533
+ # A simple example:
428
534
  #
429
- # This refers http://url.spec.whatwg.org/#concept-urlencoded-parser,
430
- # so this supports only &-separator, and doesn't support ;-separator.
535
+ # URI.decode_www_form('foo=0&bar=1&baz')
536
+ # # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
431
537
  #
432
- # ary = URI.decode_www_form("a=1&a=2&b=3")
433
- # ary #=> [['a', '1'], ['a', '2'], ['b', '3']]
434
- # ary.assoc('a').last #=> '1'
435
- # ary.assoc('b').last #=> '3'
436
- # ary.rassoc('a').last #=> '2'
437
- # Hash[ary] #=> {"a"=>"2", "b"=>"3"}
538
+ # The returned strings have certain conversions,
539
+ # similar to those performed in URI.decode_www_form_component:
540
+ #
541
+ # URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40')
542
+ # # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]]
543
+ #
544
+ # The given string may contain consecutive separators:
545
+ #
546
+ # URI.decode_www_form('foo=0&&bar=1&&baz=2')
547
+ # # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]]
548
+ #
549
+ # A different separator may be specified:
550
+ #
551
+ # URI.decode_www_form('foo=0--bar=1--baz', separator: '--')
552
+ # # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
438
553
  #
439
- # See URI.decode_www_form_component, URI.encode_www_form.
440
554
  def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
441
555
  raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
442
556
  ary = []
@@ -715,7 +829,15 @@ end # module URI
715
829
  module Kernel
716
830
 
717
831
  #
718
- # Returns +uri+ converted to an URI object.
832
+ # Returns a \URI object derived from the given +uri+,
833
+ # which may be a \URI string or an existing \URI object:
834
+ #
835
+ # # Returns a new URI.
836
+ # uri = URI('http://github.com/ruby/ruby')
837
+ # # => #<URI::HTTP http://github.com/ruby/ruby>
838
+ # # Returns the given URI.
839
+ # URI(uri)
840
+ # # => #<URI::HTTP http://github.com/ruby/ruby>
719
841
  #
720
842
  def URI(uri)
721
843
  if uri.is_a?(URI::Generic)
data/lib/uri/generic.rb CHANGED
@@ -1133,16 +1133,17 @@ module URI
1133
1133
  base.fragment=(nil)
1134
1134
 
1135
1135
  # RFC2396, Section 5.2, 4)
1136
- if authority
1137
- base.set_userinfo(rel.userinfo)
1138
- base.set_host(rel.host)
1139
- base.set_port(rel.port || base.default_port)
1140
- base.set_path(rel.path)
1141
- elsif base.path && rel.path
1142
- base.set_path(merge_path(base.path, rel.path))
1136
+ if !authority
1137
+ base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
1138
+ else
1139
+ # RFC2396, Section 5.2, 4)
1140
+ base.set_path(rel.path) if rel.path
1143
1141
  end
1144
1142
 
1145
1143
  # RFC2396, Section 5.2, 7)
1144
+ base.set_userinfo(rel.userinfo) if rel.userinfo
1145
+ base.set_host(rel.host) if rel.host
1146
+ base.set_port(rel.port) if rel.port
1146
1147
  base.query = rel.query if rel.query
1147
1148
  base.fragment=(rel.fragment) if rel.fragment
1148
1149
 
@@ -1375,6 +1376,7 @@ module URI
1375
1376
  end
1376
1377
  str
1377
1378
  end
1379
+ alias to_str to_s
1378
1380
 
1379
1381
  #
1380
1382
  # Compares two URIs.
@@ -1,9 +1,73 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  module URI
3
3
  class RFC3986_Parser # :nodoc:
4
4
  # URI defined in RFC3986
5
- RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*+):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+))(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
6
- RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*+)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h++\.[!$&-.0-;=A-Z_a-z~]++))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])++))?(?::(?<port>\d*+))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*+))*+)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])++)(?:\/\g<segment>)*+)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])++)(?:\/\g<segment>)*+)|(?<path-empty>))(?:\?(?<query>[^#]*+))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*+))?)\z/
5
+ HOST = %r[
6
+ (?<IP-literal>\[(?:
7
+ (?<IPv6address>
8
+ (?:\h{1,4}:){6}
9
+ (?<ls32>\h{1,4}:\h{1,4}
10
+ | (?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)
11
+ \.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>)
12
+ )
13
+ | ::(?:\h{1,4}:){5}\g<ls32>
14
+ | \h{1,4}?::(?:\h{1,4}:){4}\g<ls32>
15
+ | (?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>
16
+ | (?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>
17
+ | (?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>
18
+ | (?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>
19
+ | (?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}
20
+ | (?:(?:\h{1,4}:){,6}\h{1,4})?::
21
+ )
22
+ | (?<IPvFuture>v\h++\.[!$&-.0-9:;=A-Z_a-z~]++)
23
+ )\])
24
+ | \g<IPv4address>
25
+ | (?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+)
26
+ ]x
27
+
28
+ USERINFO = /(?:%\h\h|[!$&-.0-9:;=A-Z_a-z~])*+/
29
+
30
+ SCHEME = %r[[A-Za-z][+\-.0-9A-Za-z]*+].source
31
+ SEG = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/])].source
32
+ SEG_NC = %r[(?:%\h\h|[!$&-.0-9;=@A-Z_a-z~])].source
33
+ FRAGMENT = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+].source
34
+
35
+ RFC3986_URI = %r[\A
36
+ (?<seg>#{SEG}){0}
37
+ (?<URI>
38
+ (?<scheme>#{SCHEME}):
39
+ (?<hier-part>//
40
+ (?<authority>
41
+ (?:(?<userinfo>#{USERINFO.source})@)?
42
+ (?<host>#{HOST.source.delete(" \n")})
43
+ (?::(?<port>\d*+))?
44
+ )
45
+ (?<path-abempty>(?:/\g<seg>*+)?)
46
+ | (?<path-absolute>/((?!/)\g<seg>++)?)
47
+ | (?<path-rootless>(?!/)\g<seg>++)
48
+ | (?<path-empty>)
49
+ )
50
+ (?:\?(?<query>[^\#]*+))?
51
+ (?:\#(?<fragment>#{FRAGMENT}))?
52
+ )\z]x
53
+
54
+ RFC3986_relative_ref = %r[\A
55
+ (?<seg>#{SEG}){0}
56
+ (?<relative-ref>
57
+ (?<relative-part>//
58
+ (?<authority>
59
+ (?:(?<userinfo>#{USERINFO.source})@)?
60
+ (?<host>#{HOST.source.delete(" \n")}(?<!/))?
61
+ (?::(?<port>\d*+))?
62
+ )
63
+ (?<path-abempty>(?:/\g<seg>*+)?)
64
+ | (?<path-absolute>/\g<seg>*+)
65
+ | (?<path-noscheme>#{SEG_NC}++(?:/\g<seg>*+)?)
66
+ | (?<path-empty>)
67
+ )
68
+ (?:\?(?<query>[^#]*+))?
69
+ (?:\#(?<fragment>#{FRAGMENT}))?
70
+ )\z]x
7
71
  attr_reader :regexp
8
72
 
9
73
  def initialize
@@ -19,9 +83,9 @@ module URI
19
83
  uri.ascii_only? or
20
84
  raise InvalidURIError, "URI must be ascii only #{uri.dump}"
21
85
  if m = RFC3986_URI.match(uri)
22
- query = m["query".freeze]
23
- scheme = m["scheme".freeze]
24
- opaque = m["path-rootless".freeze]
86
+ query = m["query"]
87
+ scheme = m["scheme"]
88
+ opaque = m["path-rootless"]
25
89
  if opaque
26
90
  opaque << "?#{query}" if query
27
91
  [ scheme,
@@ -32,35 +96,35 @@ module URI
32
96
  nil, # path
33
97
  opaque,
34
98
  nil, # query
35
- m["fragment".freeze]
99
+ m["fragment"]
36
100
  ]
37
101
  else # normal
38
102
  [ scheme,
39
- m["userinfo".freeze],
40
- m["host".freeze],
41
- m["port".freeze],
103
+ m["userinfo"],
104
+ m["host"],
105
+ m["port"],
42
106
  nil, # registry
43
- (m["path-abempty".freeze] ||
44
- m["path-absolute".freeze] ||
45
- m["path-empty".freeze]),
107
+ (m["path-abempty"] ||
108
+ m["path-absolute"] ||
109
+ m["path-empty"]),
46
110
  nil, # opaque
47
111
  query,
48
- m["fragment".freeze]
112
+ m["fragment"]
49
113
  ]
50
114
  end
51
115
  elsif m = RFC3986_relative_ref.match(uri)
52
116
  [ nil, # scheme
53
- m["userinfo".freeze],
54
- m["host".freeze],
55
- m["port".freeze],
117
+ m["userinfo"],
118
+ m["host"],
119
+ m["port"],
56
120
  nil, # registry,
57
- (m["path-abempty".freeze] ||
58
- m["path-absolute".freeze] ||
59
- m["path-noscheme".freeze] ||
60
- m["path-empty".freeze]),
121
+ (m["path-abempty"] ||
122
+ m["path-absolute"] ||
123
+ m["path-noscheme"] ||
124
+ m["path-empty"]),
61
125
  nil, # opaque
62
- m["query".freeze],
63
- m["fragment".freeze]
126
+ m["query"],
127
+ m["fragment"]
64
128
  ]
65
129
  else
66
130
  raise InvalidURIError, "bad URI(is not URI?): #{uri.inspect}"
@@ -92,14 +156,14 @@ module URI
92
156
 
93
157
  def default_regexp # :nodoc:
94
158
  {
95
- SCHEME: /\A[A-Za-z][A-Za-z0-9+\-.]*\z/,
96
- USERINFO: /\A(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*\z/,
97
- HOST: /\A(?:(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{,4}::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*))\z/,
98
- ABS_PATH: /\A\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*(?:\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*)*\z/,
99
- REL_PATH: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+(?:\/(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*)*\z/,
100
- QUERY: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
101
- FRAGMENT: /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*\z/,
102
- OPAQUE: /\A(?:[^\/].*)?\z/,
159
+ SCHEME: %r[\A#{SCHEME}\z]o,
160
+ USERINFO: %r[\A#{USERINFO}\z]o,
161
+ HOST: %r[\A#{HOST}\z]o,
162
+ ABS_PATH: %r[\A/#{SEG}*+\z]o,
163
+ REL_PATH: %r[\A(?!/)#{SEG}++\z]o,
164
+ QUERY: %r[\A(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+\z],
165
+ FRAGMENT: %r[\A#{FRAGMENT}\z]o,
166
+ OPAQUE: %r[\A(?:[^/].*)?\z],
103
167
  PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
104
168
  }
105
169
  end
data/lib/uri/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module URI
2
2
  # :stopdoc:
3
- VERSION_CODE = '001204'.freeze
3
+ VERSION_CODE = '001300'.freeze
4
4
  VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
5
5
  # :startdoc:
6
6
  end
@@ -0,0 +1,17 @@
1
+ task :sync_tool, [:from] do |t, from: nil|
2
+ from ||= (File.identical?(__dir__, "rakelib") ? "../ruby/tool" : File.dirname(__dir__))
3
+
4
+ require 'fileutils'
5
+
6
+ {
7
+ "rakelib/sync_tool.rake" => "rakelib",
8
+ "lib/core_assertions.rb" => "test/lib",
9
+ "lib/envutil.rb" => "test/lib",
10
+ "lib/find_executable.rb" => "test/lib",
11
+ "lib/helper.rb" => "test/lib",
12
+ }.each do |src, dest|
13
+ FileUtils.mkpath(dest)
14
+ FileUtils.cp "#{from}/#{src}", dest
15
+ rescue Errno::ENOENT
16
+ end
17
+ end
data/uri.gemspec CHANGED
@@ -12,18 +12,26 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = %q{URI is a module providing classes to handle Uniform Resource Identifiers}
14
14
  spec.description = spec.summary
15
- spec.homepage = "https://github.com/ruby/uri"
15
+
16
+ github_link = "https://github.com/ruby/uri"
17
+
18
+ spec.homepage = github_link
16
19
  spec.licenses = ["Ruby", "BSD-2-Clause"]
17
20
 
18
- spec.required_ruby_version = '>= 2.4'
21
+ spec.required_ruby_version = '>= 2.5'
19
22
 
20
- spec.metadata["homepage_uri"] = spec.homepage
21
- spec.metadata["source_code_uri"] = spec.homepage
23
+ spec.metadata = {
24
+ "bug_tracker_uri" => "#{github_link}/issues",
25
+ "changelog_uri" => "#{github_link}/releases",
26
+ "documentation_uri" => "https://ruby.github.io/uri/",
27
+ "homepage_uri" => spec.homepage,
28
+ "source_code_uri" => github_link
29
+ }
22
30
 
23
31
  # Specify which files should be added to the gem when it is released.
24
32
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
33
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
26
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
34
+ `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
35
  end
28
36
  spec.bindir = "exe"
29
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.4
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akira Yamada
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-26 00:00:00.000000000 Z
11
+ date: 2023-11-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: URI is a module providing classes to handle Uniform Resource Identifiers
14
14
  email:
@@ -18,6 +18,7 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - ".github/dependabot.yml"
21
+ - ".github/workflows/gh-pages.yml"
21
22
  - ".github/workflows/test.yml"
22
23
  - ".gitignore"
23
24
  - Gemfile
@@ -41,12 +42,16 @@ files:
41
42
  - lib/uri/version.rb
42
43
  - lib/uri/ws.rb
43
44
  - lib/uri/wss.rb
45
+ - rakelib/sync_tool.rake
44
46
  - uri.gemspec
45
47
  homepage: https://github.com/ruby/uri
46
48
  licenses:
47
49
  - Ruby
48
50
  - BSD-2-Clause
49
51
  metadata:
52
+ bug_tracker_uri: https://github.com/ruby/uri/issues
53
+ changelog_uri: https://github.com/ruby/uri/releases
54
+ documentation_uri: https://ruby.github.io/uri/
50
55
  homepage_uri: https://github.com/ruby/uri
51
56
  source_code_uri: https://github.com/ruby/uri
52
57
  post_install_message:
@@ -57,14 +62,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
62
  requirements:
58
63
  - - ">="
59
64
  - !ruby/object:Gem::Version
60
- version: '2.4'
65
+ version: '2.5'
61
66
  required_rubygems_version: !ruby/object:Gem::Requirement
62
67
  requirements:
63
68
  - - ">="
64
69
  - !ruby/object:Gem::Version
65
70
  version: '0'
66
71
  requirements: []
67
- rubygems_version: 3.4.19
72
+ rubygems_version: 3.5.0.dev
68
73
  signing_key:
69
74
  specification_version: 4
70
75
  summary: URI is a module providing classes to handle Uniform Resource Identifiers