furi 0.2.2 → 0.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e47171efdec80d8610e7dea95a1eed17876ea14b
4
- data.tar.gz: 33a2e11ef018c0d5c9d6695ced7c15e9f3dd3fb4
2
+ SHA256:
3
+ metadata.gz: d6c5fd8026d354285814feddc9d26a68be21f33b3aca4c5a34d89da0c0bb2154
4
+ data.tar.gz: fe05d55272141fc548ef1b9812c06ad79acf1883e06faf9ee2dbeb09bfbcf5d9
5
5
  SHA512:
6
- metadata.gz: 7e0c644b931d878b69b6d902aad0772aefa16a5ff4066db3bab871912dbe1e0b4ed91b41d4fb1b921ddfe36119f60293081e6b924cab8747865c1aa1451d3ebe
7
- data.tar.gz: 1bbc865cbe5551b416a28243260e01e01409b600f32fd83b8b3a3da320cc7f9f6ce1bdc82363d92a1b8dd1941de99356e38a4d2903a57ad2f8ef956db4a22f23
6
+ metadata.gz: c97cef41669230f4a87dc03fcbbb28e7027778339111cc9a31907228e69228a64014e489ab73a368fb83b0454e7713f7a7f9ae168701ddf67f15b5cf64b44f78
7
+ data.tar.gz: 908ba0edd3795239a81b7b912acf24bb7733de192f58b46387c34e2cd2d50bea93f82a2441d87449fc3593ed95bfa9d18b223486a1c7d13fe93159afdd1667c1
@@ -0,0 +1,19 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ ruby: [2.4, 2.5, 2.6, 2.7, 3.0]
11
+ name: Ruby ${{ matrix.ruby }}
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - run: bundle exec rake
data/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # v0.2.4
2
+
3
+ * Improved `Furi.update` behavior for `path:` overrides:
4
+
5
+ * Supports **relative path resolution** (`..` and subpaths)
6
+ * Leading slashes in `path` now **replace** the original path
7
+ * `nil` path removes the path portion entirely, leaving only the host
8
+
9
+ **Examples:**
10
+
11
+ ```ruby
12
+ Furi.update("https://www.google.com/maps", path: "place/1.23,3.28")
13
+ # => "https://www.google.com/maps/place/1.23,3.28"
14
+
15
+ Furi.update("https://www.google.com/maps", path: "/account")
16
+ # => "https://www.google.com/account"
17
+
18
+ Furi.update("https://www.google.com/maps", path: "..")
19
+ # => "https://www.google.com/"
20
+
21
+ Furi.update("https://www.google.com/maps", path: nil)
22
+ # => "https://www.google.com"
23
+ ```
24
+
25
+ # v0.2.3
26
+
27
+ * Ruby 3.0 support #2
28
+ * Escaping special characters in anchor
29
+
data/Gemfile CHANGED
@@ -1,4 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in furi.gemspec
4
6
  gemspec
7
+
8
+ gem "pry-byebug", "~> 3.9"
9
+ gem "rake", "~> 13.0"
10
+ gem "rspec", "~> 3.10"
11
+ gem "bump"
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Furi
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/furi.svg)](https://badge.fury.io/rb/furi)
4
+ [![Build Status](https://github.com/bogdan/furi/workflows/CI/badge.svg?branch=master)](https://github.com/bogdan/furi/actions)
5
+ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbogdan%2Ffuri.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fbogdan%2Ffuri?ref=badge_shield)
6
+
3
7
  Furi is a Friendly URI parsing library.
4
8
  Furi's philosophy is to make any operation possible in ONE LINE OF CODE.
5
9
 
@@ -9,7 +13,7 @@ If there is an operation that takes more than one line of code to do with Furi,
9
13
 
10
14
  Add this line to your application's Gemfile:
11
15
 
12
- ```ruby
16
+ ``` ruby
13
17
  gem 'furi'
14
18
  ```
15
19
 
@@ -24,11 +28,10 @@ Or install it yourself as:
24
28
  ## Usage
25
29
 
26
30
  I'll say it again: any operation should take exacly one line of code!
27
- Here are basic:
31
+ Here are basic:
28
32
 
29
33
  ### Utility Methods
30
34
 
31
-
32
35
  Parsing the URI fragments:
33
36
 
34
37
  ``` ruby
@@ -39,31 +42,43 @@ Furi.port!("http://gusiev.com") # => 80
39
42
 
40
43
  Updating the URI parts:
41
44
 
42
- ```
45
+ ``` ruby
43
46
  Furi.update("http://gusiev.com", protocol: '') # => "//gusiev.com"
44
- Furi.update("http://gusiev.com?source=google", query: {email: "a@b.com"})
47
+ Furi.update("http://gusiev.com?source=google", query: {email: "a@b.com"})
45
48
  # => "http://gusiev.com?source=google&email=a@b.com"
46
- Furi.replace("http://gusiev.com?source=google", query: {email: "a@b.com"})
49
+ Furi.replace("http://gusiev.com?source=google", query: {email: "a@b.com"})
47
50
  # => "http://gusiev.com?email=a@b.com"
48
51
 
49
52
  Furi.defaults("http://gusiev.com", subdomain: 'www') # => "http://www.gusiev.com"
50
53
  Furi.defaults("http://blog.gusiev.com", subdomain: 'www') # => "http://blog.gusiev.com"
51
-
52
54
  ```
53
55
 
54
56
  Building an URI from initial parts:
55
57
 
56
58
  ``` ruby
57
-
58
- Furi.build(protocol: '//', host: 'gusiev.com', path: '/assets/application.js')
59
+ Furi.build(protocol: '//', host: 'gusiev.com', path: '/assets/application.js')
59
60
  # => "//gusiev.com/assets/application.js"
61
+
62
+ Furi.build(
63
+ location: 'https://calendar.google.com',
64
+ path: '/calendar/render',
65
+ query: {
66
+ action: 'TEMPLATE',
67
+ text: 'Seven Figure Club Meeting',
68
+ dates: [Time.now + 2.hours, Time.now + 3.hours].map do |t|
69
+ t.strftime("%Y%m%dT%H%M%SZ")
70
+ end.join('/'),
71
+ details: 'Seven Figure Club invites to the discussion with other founders to one of the topics you have expressed your interest to.',
72
+ add: ["bogdan@example.com", "brad@example.com"].join(',')
73
+ }
74
+ )
60
75
  ```
61
76
 
62
77
  ### Working with Object
63
78
 
64
79
  ``` ruby
65
- uri = Furi.parse("gusiev.com")
66
- # => #<Furi::Uri "gusiev.com">
80
+ uri = Furi.parse("gusiev.com")
81
+ # => #<Furi::Uri "gusiev.com">
67
82
 
68
83
  uri.port # => nil
69
84
  uri.port! # => 80
@@ -92,12 +107,12 @@ uri.merge_query(person: {email: 'a@b.com'})
92
107
  ## Reference
93
108
 
94
109
  ```
95
- location resource
96
- | ___|___
97
- _______|_______ / \
98
- / \ / \
99
- / authority request \
100
- / __________|_________ | \
110
+ location resource
111
+ | ___|___
112
+ _______|_______ / \
113
+ / \ / \
114
+ / authority request \
115
+ / __________|_________ | \
101
116
  / / \ ______|______ \
102
117
  / userinfo hostinfo / \ \
103
118
  / __|___ ___|___ / \ \
@@ -109,25 +124,29 @@ uri.merge_query(person: {email: 'a@b.com'})
109
124
  \_/ \_/ \___/ \_/ \__________/\ / \_/
110
125
  | | | | | \___/ |
111
126
  protocol subdomain | domainzone directory | extension
112
- | | filename |
113
- domainname / \_____/
114
- \___/ |
115
- | file
116
- domain
127
+ | | filename |
128
+ domainname / \_____/
129
+ \___/ |
130
+ | file
131
+ domain
117
132
  ```
118
133
 
119
-
120
134
  Originated from [URI.js](http://medialize.github.io/URI.js/about-uris.html) parsing library.
121
135
  Giving credit...
122
136
 
123
-
124
137
  ## TODO
125
138
 
126
- * Improve URI.join algorithm to match the one used in Addressible library
139
+ * Improve URI.join algorithm to match the one used in Addressable library
127
140
  * Implement filename
141
+ * Encoding/Decoding special characters:
142
+ * path
143
+ * query
144
+ * fragment
128
145
 
129
146
  ## Contributing
130
147
 
131
148
  Contribute in the way you want. Branch names and other bla-bla-bla do not matter.
132
149
 
150
+ ## License
133
151
 
152
+ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbogdan%2Ffuri.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fbogdan%2Ffuri?ref=badge_large)
data/Rakefile CHANGED
@@ -1,13 +1,8 @@
1
- require "bundler/gem_tasks"
2
-
1
+ # frozen_string_literal: true
3
2
 
4
- begin
5
- require 'rspec/core/rake_task'
6
- RSpec::Core::RakeTask.new(:spec)
7
- rescue LoadError
8
- end
9
-
10
- task :default => :spec do
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
11
5
 
12
- end
6
+ RSpec::Core::RakeTask.new(:spec)
13
7
 
8
+ task default: :spec
data/furi.gemspec CHANGED
@@ -1,7 +1,6 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'furi/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/furi/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = "furi"
@@ -9,17 +8,17 @@ Gem::Specification.new do |spec|
9
8
  spec.authors = ["Bogdan Gusiev"]
10
9
  spec.email = ["agresso@gmail.com"]
11
10
  spec.summary = %q{Make URI processing as easy as it should be}
12
- spec.description = %q{The phylosophy of this gem is to make any URI modification or parsing operation to take only one line of code and never more}
13
- spec.homepage = ""
11
+ spec.description = %q{The philosophy of this gem is to make any URI modification or parsing operation to take only one line of code and never more}
12
+ spec.homepage = "https://github.com/bogdan/furi"
14
13
  spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
20
19
 
21
- spec.add_development_dependency "bundler", "~> 1.7"
22
- spec.add_development_dependency "rake", "~> 10.0"
23
- spec.add_development_dependency "rspec"
24
- spec.add_development_dependency "pry-byebug"
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
22
+ end
23
+ spec.require_paths = ["lib"]
25
24
  end
data/lib/furi/uri.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+
1
3
  module Furi
2
4
  class Uri
3
5
 
@@ -44,6 +46,12 @@ module Furi
44
46
  case part.to_sym
45
47
  when :query, :query_tokens, :query_string
46
48
  merge_query(value)
49
+ when :path
50
+ if value
51
+ self[part] = Pathname.new(self[part]).join(value).to_s
52
+ else
53
+ self[part] = value
54
+ end
47
55
  else
48
56
  self[part] = value
49
57
  end
@@ -72,7 +80,10 @@ module Furi
72
80
  def merge_query(query)
73
81
  case query
74
82
  when Hash
75
- self.query = self.query.merge(Furi::Utils.stringify_keys(query))
83
+ self.query = Furi::Utils.deep_merge(
84
+ self.query,
85
+ Furi::Utils.stringify_keys(query)
86
+ )
76
87
  when String, Array
77
88
  self.query_tokens += Furi.query_tokens(query)
78
89
  when nil
@@ -135,7 +146,7 @@ module Furi
135
146
  end
136
147
 
137
148
  def hostinfo
138
- return host unless explicit_port?
149
+ return host unless custom_port?
139
150
  if port && !host
140
151
  raise Furi::FormattingError, "can not build URI with port but without host"
141
152
  end
@@ -178,7 +189,7 @@ module Furi
178
189
  result << "?" << query_string
179
190
  end
180
191
  if anchor
181
- result << "#" << anchor
192
+ result << encoded_anchor
182
193
  end
183
194
  result.join
184
195
  end
@@ -238,10 +249,8 @@ module Furi
238
249
  query
239
250
  when String, Array
240
251
  self.query_tokens = value
241
- @query = nil
242
252
  when Hash
243
253
  self.query_tokens = value
244
- @query = value
245
254
  when nil
246
255
  else
247
256
  raise QueryParseError, 'Query can only be Hash or String'
@@ -273,7 +282,7 @@ module Furi
273
282
  end
274
283
 
275
284
  def query_tokens=(tokens)
276
- @query = nil
285
+ @query = tokens.is_a?(Hash) ? tokens : nil
277
286
  @query_tokens = Furi.query_tokens(tokens)
278
287
  end
279
288
 
@@ -420,7 +429,7 @@ module Furi
420
429
 
421
430
  def resource
422
431
  return nil unless request
423
- [request, anchor].compact.join("#")
432
+ request + encoded_anchor
424
433
  end
425
434
 
426
435
  def resource=(value)
@@ -483,6 +492,14 @@ module Furi
483
492
  authority
484
493
  end
485
494
 
495
+ def custom_port?
496
+ port && port != default_port
497
+ end
498
+
499
+ def mailto?
500
+ protocol == "mailto"
501
+ end
502
+
486
503
  protected
487
504
 
488
505
  def file_tokens
@@ -493,10 +510,6 @@ module Furi
493
510
  !!@query
494
511
  end
495
512
 
496
- def explicit_port?
497
- port && port != default_port
498
- end
499
-
500
513
  def parse_uri_string(string)
501
514
  if string.empty?
502
515
  raise Furi::FormattingError, "can not be an empty string"
@@ -531,7 +544,7 @@ module Furi
531
544
  def parse_anchor_and_query(string)
532
545
  string ||= ''
533
546
  string, *anchor = string.split("#")
534
- self.anchor = anchor.join("#")
547
+ self.anchor = ::URI::DEFAULT_PARSER.unescape(anchor.join("#"))
535
548
  if string && string.include?("?")
536
549
  string, query_string = string.split("?", 2)
537
550
  self.query_tokens = query_string
@@ -583,8 +596,9 @@ module Furi
583
596
  end
584
597
  end
585
598
 
586
- def mailto?
587
- protocol == "mailto"
599
+ def encoded_anchor
600
+ return "" unless anchor
601
+ "#" + ::URI::DEFAULT_PARSER.escape(anchor)
588
602
  end
589
603
  end
590
604
  end
data/lib/furi/utils.rb CHANGED
@@ -10,7 +10,17 @@ module Furi
10
10
  end
11
11
  result
12
12
  end
13
+
14
+ def deep_merge(current_hash, other_hash)
15
+ current_hash.merge(other_hash) do |key, this_val, other_val|
16
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
17
+ deep_merge(this_val, other_val)
18
+ else
19
+ other_val
20
+ end
21
+ end
22
+ end
13
23
  end
14
24
  end
15
25
  end
16
-
26
+
data/lib/furi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Furi
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.4"
3
3
  end
data/lib/furi.rb CHANGED
@@ -172,7 +172,9 @@ module Furi
172
172
  def self.join(*uris)
173
173
  uris.map do |uri|
174
174
  Furi.parse(uri)
175
- end.reduce(:join)
175
+ end.reduce do |memo, uri|
176
+ memo.send(:join, uri)
177
+ end
176
178
  end
177
179
 
178
180
  class Error < StandardError
metadata CHANGED
@@ -1,72 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: furi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bogdan Gusiev
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2016-12-20 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.7'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.7'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: pry-byebug
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- description: The phylosophy of this gem is to make any URI modification or parsing
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: The philosophy of this gem is to make any URI modification or parsing
70
13
  operation to take only one line of code and never more
71
14
  email:
72
15
  - agresso@gmail.com
@@ -74,8 +17,10 @@ executables: []
74
17
  extensions: []
75
18
  extra_rdoc_files: []
76
19
  files:
20
+ - ".github/workflows/ci.yml"
77
21
  - ".gitignore"
78
22
  - ".rspec"
23
+ - CHANGELOG.md
79
24
  - Gemfile
80
25
  - LICENSE.txt
81
26
  - README.md
@@ -86,14 +31,13 @@ files:
86
31
  - lib/furi/uri.rb
87
32
  - lib/furi/utils.rb
88
33
  - lib/furi/version.rb
89
- - spec/furi/uri_spec.rb
90
- - spec/furi_spec.rb
91
- - spec/spec_helper.rb
92
- homepage: ''
34
+ homepage: https://github.com/bogdan/furi
93
35
  licenses:
94
36
  - MIT
95
- metadata: {}
96
- post_install_message:
37
+ metadata:
38
+ allowed_push_host: https://rubygems.org
39
+ homepage_uri: https://github.com/bogdan/furi
40
+ source_code_uri: https://github.com/bogdan/furi
97
41
  rdoc_options: []
98
42
  require_paths:
99
43
  - lib
@@ -101,19 +45,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
45
  requirements:
102
46
  - - ">="
103
47
  - !ruby/object:Gem::Version
104
- version: '0'
48
+ version: 2.4.0
105
49
  required_rubygems_version: !ruby/object:Gem::Requirement
106
50
  requirements:
107
51
  - - ">="
108
52
  - !ruby/object:Gem::Version
109
53
  version: '0'
110
54
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 2.6.7
113
- signing_key:
55
+ rubygems_version: 3.6.7
114
56
  specification_version: 4
115
57
  summary: Make URI processing as easy as it should be
116
- test_files:
117
- - spec/furi/uri_spec.rb
118
- - spec/furi_spec.rb
119
- - spec/spec_helper.rb
58
+ test_files: []
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Furi::Uri do
4
-
5
- describe ".rfc3986?" do
6
-
7
- it "works" do
8
- expect(Furi.parse("http://goo gl.com") ).to_not be_rfc
9
- expect(Furi.parse("http://googl.com") ).to be_rfc
10
- end
11
- end
12
- end