protocol-url 0.3.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12a81d3a05c932207c77a583df784431d7120f3f1f9ee68c9ea593a47c666831
4
- data.tar.gz: 3307c15e0d16d4907259cd186c0483d46d78358e0b1bfee99e3cf3186a1c74d2
3
+ metadata.gz: fb5e51237375afb74dda311e130ad550240453d53c42c5c0c05ddc532231261f
4
+ data.tar.gz: fbcf705936fedf9e967af1eb66ef2d901f68448bfe9e47d3ffd21156486207f0
5
5
  SHA512:
6
- metadata.gz: 8e948fff9470b6676b5b28638af7fdc64eaa31e3565c980071a539eadbf3651b8c10037ed1bcec70b43360a30fbb595f14bf965898e6ab4f1b4e8baf1e942491
7
- data.tar.gz: 86de1d30699c4c3f7c85878ca3c0edf45da61991593d4600bfc83be2b667525ccc8bb01ea5a51ddf82248045933b49a3ef8879947100a5ac88d67d94a2947786
6
+ metadata.gz: c49c2bc6639b2b0777ae93c3b8ee34bd7c496831deb32da8af725ebc4f873d2666a47b68bc6aa031d7b1dbee522488927011c1d5ceb9b81140e4ea3c4ae2e575
7
+ data.tar.gz: 05c41426fdc297a5bae0a59d6ef4ca31e88a0cc592769038474c28b948b7615b5cecae17943d6263fe8bd02b079f178d427b2cdc7c4ea1393a5e28da8ccaa55f
checksums.yaml.gz.sig CHANGED
Binary file
@@ -10,6 +10,13 @@ module Protocol
10
10
  # Represents an absolute URL with scheme and/or authority.
11
11
  # Examples: "https://example.com/path", "//cdn.example.com/lib.js", "http://localhost/"
12
12
  class Absolute < Relative
13
+ # Initialize a new absolute URL.
14
+ #
15
+ # @parameter scheme [String] The URL scheme (e.g., "https", "http").
16
+ # @parameter authority [String] The authority component (e.g., "example.com", "user@host:port").
17
+ # @parameter path [String] The path component (defaults to "/").
18
+ # @parameter query [String, nil] The query string.
19
+ # @parameter fragment [String, nil] The fragment identifier.
13
20
  def initialize(scheme, authority, path = "/", query = nil, fragment = nil)
14
21
  @scheme = scheme
15
22
  @authority = authority
@@ -18,13 +25,22 @@ module Protocol
18
25
  super(path, query, fragment)
19
26
  end
20
27
 
28
+ # @attribute [String] The URL scheme.
21
29
  attr :scheme
30
+
31
+ # @attribute [String] The authority component.
22
32
  attr :authority
23
33
 
34
+ # Check if the URL has a non-empty scheme.
35
+ #
36
+ # @returns [Boolean] True if a scheme is present and non-empty.
24
37
  def scheme?
25
38
  @scheme and !@scheme.empty?
26
39
  end
27
40
 
41
+ # Check if the URL has a non-empty authority.
42
+ #
43
+ # @returns [Boolean] True if an authority is present and non-empty.
28
44
  def authority?
29
45
  @authority and !@authority.empty?
30
46
  end
@@ -93,8 +109,6 @@ module Protocol
93
109
  super(buffer)
94
110
  end
95
111
 
96
- UNSPECIFIED = Object.new
97
-
98
112
  # Create a new Absolute URL with modified components.
99
113
  #
100
114
  # @parameter scheme [String, nil] The scheme to use (nil to remove scheme).
@@ -118,14 +132,24 @@ module Protocol
118
132
  self.class.new(scheme, authority, Path.expand(@path, path, pop), query, fragment)
119
133
  end
120
134
 
135
+ # Convert the URL to an array representation.
136
+ #
137
+ # @returns [Array] An array of `[scheme, authority, path, query, fragment]`.
121
138
  def to_ary
122
139
  [@scheme, @authority, @path, @query, @fragment]
123
140
  end
124
141
 
142
+ # Compare this URL with another for sorting purposes.
143
+ #
144
+ # @parameter other [Absolute] The URL to compare with.
145
+ # @returns [Integer] -1, 0, or 1 based on component-wise comparison.
125
146
  def <=>(other)
126
147
  to_ary <=> other.to_ary
127
148
  end
128
149
 
150
+ # Convert the URL to its string representation.
151
+ #
152
+ # @returns [String] The formatted absolute URL string.
129
153
  def to_s
130
154
  append
131
155
  end
@@ -233,6 +233,17 @@ module Protocol
233
233
 
234
234
  return parameters
235
235
  end
236
+
237
+ # Decode an `application/x-www-form-urlencoded` string into a hash.
238
+ # In addition to percent encoding, this format represents spaces using `+`.
239
+ #
240
+ # @parameter string [String] The form-encoded string to decode.
241
+ # @parameter maximum [Integer] The maximum number of keys in a path.
242
+ # @parameter symbolize_keys [Boolean] Whether to symbolize keys.
243
+ # @returns [Hash] The decoded form values.
244
+ def self.decode_www_form(string, maximum = 8, symbolize_keys: false)
245
+ return self.decode(string.gsub("+", "%20"), maximum, symbolize_keys: symbolize_keys)
246
+ end
236
247
  end
237
248
  end
238
249
  end
@@ -17,6 +17,35 @@ module Protocol
17
17
  class Reference < Relative
18
18
  include Comparable
19
19
 
20
+ # Coerce a value into a {Reference} instance.
21
+ #
22
+ # This method provides flexible conversion from various types into a {Reference}.
23
+ # When given a {String}, it parses the URL-encoded path, query, and fragment components
24
+ # and unescapes them for internal storage. When given a {Relative}, it converts the
25
+ # encoded values to unescaped form suitable for {Reference} instances.
26
+ #
27
+ # @parameter value [String | Relative | Nil] The value to coerce.
28
+ # @parameter parameters [Hash | Nil] Optional user-supplied parameters to append to the query string.
29
+ #
30
+ # @returns [Reference | Nil] A new reference instance, or `nil` if the input is `nil`.
31
+ #
32
+ # @raises [ArgumentError] If the string contains whitespace or control characters.
33
+ # @raises [ArgumentError] If the value cannot be coerced to a {Reference}.
34
+ #
35
+ # @example Coerce a string with path, query, and fragment.
36
+ # reference = Reference["/search?q=ruby#results"]
37
+ # reference.path # => "/search"
38
+ # reference.query # => "q=ruby"
39
+ # reference.fragment # => "results"
40
+ #
41
+ # @example Coerce with additional parameters.
42
+ # reference = Reference["/search", {"limit" => "10"}]
43
+ # reference.to_s # => "/search?limit=10"
44
+ #
45
+ # @example Coerce a Relative instance.
46
+ # relative = Relative.new("/path%20with%20spaces", nil, "top")
47
+ # reference = Reference[relative]
48
+ # reference.path # => "/path with spaces"
20
49
  def self.[](value, parameters = nil)
21
50
  case value
22
51
  when String
@@ -25,7 +54,7 @@ module Protocol
25
54
  query = match[:query]
26
55
  fragment = match[:fragment]
27
56
 
28
- # Unescape path and fragment for user-friendly internal storage
57
+ # Unescape path and fragment for user-friendly internal storage:
29
58
  # Query strings are kept as-is since they contain = and & syntax
30
59
  path = Encoding.unescape(path) if path && !path.empty?
31
60
  fragment = Encoding.unescape(fragment) if fragment
@@ -35,7 +64,7 @@ module Protocol
35
64
  raise ArgumentError, "Invalid URL (contains whitespace or control characters): #{value.inspect}"
36
65
  end
37
66
  when Relative
38
- # Relative stores encoded values, so we need to unescape them for Reference
67
+ # Relative stores encoded values, so we need to unescape them for Reference:
39
68
  path = value.path
40
69
  fragment = value.fragment
41
70
 
@@ -95,14 +124,6 @@ module Protocol
95
124
  [@path, @query, @fragment, @parameters]
96
125
  end
97
126
 
98
- # Compare two references.
99
- #
100
- # @parameter other [Reference] The other reference to compare.
101
- # @returns [Integer] -1, 0, 1 if the reference is less than, equal to, or greater than the other reference.
102
- def <=> other
103
- to_ary <=> other.to_ary
104
- end
105
-
106
127
  # @returns [Boolean] Whether the reference has parameters.
107
128
  def parameters?
108
129
  @parameters and !@parameters.empty?
@@ -12,16 +12,29 @@ module Protocol
12
12
  class Relative
13
13
  include Comparable
14
14
 
15
+ # Initialize a new relative URL.
16
+ #
17
+ # @parameter path [String] The path component.
18
+ # @parameter query [String, nil] The query string.
19
+ # @parameter fragment [String, nil] The fragment identifier.
15
20
  def initialize(path, query = nil, fragment = nil)
16
21
  @path = path.to_s
17
22
  @query = query
18
23
  @fragment = fragment
19
24
  end
20
25
 
26
+ # @attribute [String] The path component of the URL.
21
27
  attr :path
28
+
29
+ # @attribute [String, nil] The query string component.
22
30
  attr :query
31
+
32
+ # @attribute [String, nil] The fragment identifier.
23
33
  attr :fragment
24
34
 
35
+ # Convert the URL path to a local filesystem path.
36
+ #
37
+ # @returns [String] The local filesystem path.
25
38
  def to_local_path
26
39
  Path.to_local_path(@path)
27
40
  end
@@ -131,18 +144,76 @@ module Protocol
131
144
  return buffer
132
145
  end
133
146
 
147
+ # Convert the URL to an array representation.
148
+ #
149
+ # @returns [Array] An array of `[path, query, fragment]`.
134
150
  def to_ary
135
151
  [@path, @query, @fragment]
136
152
  end
137
153
 
154
+ # Compute a hash value for the URL based on its components.
155
+ #
156
+ # @returns [Integer] The hash value.
157
+ def hash
158
+ to_ary.hash
159
+ end
160
+
161
+ # Check if this URL is equal to another URL by comparing components.
162
+ #
163
+ # @parameter other [Relative] The URL to compare with.
164
+ # @returns [Boolean] True if the URLs have identical components.
165
+ def equal?(other)
166
+ to_ary == other.to_ary
167
+ end
168
+
169
+ # Compare this URL with another for sorting purposes.
170
+ #
171
+ # @parameter other [Relative] The URL to compare with.
172
+ # @returns [Integer] -1, 0, or 1 based on component-wise comparison.
138
173
  def <=>(other)
139
174
  to_ary <=> other.to_ary
140
175
  end
141
176
 
177
+ # Check structural equality by comparing components.
178
+ #
179
+ # @parameter other [Relative] The URL to compare with.
180
+ # @returns [Boolean] True if the URLs have identical components.
181
+ def ==(other)
182
+ to_ary == other.to_ary
183
+ end
184
+
185
+ # Check string equality, useful for case statements.
186
+ #
187
+ # @parameter other [String, Relative] The value to compare with.
188
+ # @returns [Boolean] True if the string representations match.
189
+ def ===(other)
190
+ to_s === other
191
+ end
192
+
193
+ # Convert the URL to its string representation.
194
+ #
195
+ # @returns [String] The formatted URL string.
142
196
  def to_s
143
197
  append
144
198
  end
145
199
 
200
+ # Convert the URL to a JSON-compatible representation.
201
+ #
202
+ # @returns [String] The URL as a string.
203
+ def as_json(...)
204
+ to_s
205
+ end
206
+
207
+ # Convert the URL to JSON.
208
+ #
209
+ # @returns [String] The JSON-encoded URL.
210
+ def to_json(...)
211
+ as_json.to_json(...)
212
+ end
213
+
214
+ # Generate a human-readable representation for debugging.
215
+ #
216
+ # @returns [String] A string like `#<Protocol::URL::Relative /path?query#fragment>`.
146
217
  def inspect
147
218
  "#<#{self.class} #{to_s}>"
148
219
  end
@@ -7,6 +7,6 @@
7
7
  module Protocol
8
8
  # @namespace
9
9
  module URL
10
- VERSION = "0.3.0"
10
+ VERSION = "0.5.0"
11
11
  end
12
12
  end
data/readme.md CHANGED
@@ -6,11 +6,11 @@ Provides abstractions for working with URLs.
6
6
 
7
7
  ## Usage
8
8
 
9
- Please see the [project documentation](https://github.com/socketry/protocol-url) for more details.
9
+ Please see the [project documentation](https://socketry.github.io/protocol-url/) for more details.
10
10
 
11
- - [Getting Started](https://github.com/socketry/protocol-urlguides/getting-started/index) - This guide explains how to get started with `protocol-url` for parsing, manipulating, and constructing URLs in Ruby.
11
+ - [Getting Started](https://socketry.github.io/protocol-url/guides/getting-started/index) - This guide explains how to get started with `protocol-url` for parsing, manipulating, and constructing URLs in Ruby.
12
12
 
13
- - [Working with References](https://github.com/socketry/protocol-urlguides/working-with-references/index) - This guide explains how to use <code class="language-ruby">Protocol::URL::Reference</code> for managing URLs with query parameters and fragments.
13
+ - [Working with References](https://socketry.github.io/protocol-url/guides/working-with-references/index) - This guide explains how to use <code class="language-ruby">Protocol::URL::Reference</code> for managing URLs with query parameters and fragments.
14
14
 
15
15
  ## Contributing
16
16
 
@@ -32,7 +32,23 @@ This project is best served by a collaborative and respectful environment. Treat
32
32
 
33
33
  ## Releases
34
34
 
35
- Please see the [project releases](https://github.com/socketry/protocol-urlreleases/index) for all releases.
35
+ Please see the [project releases](https://socketry.github.io/protocol-url/releases/index) for all releases.
36
+
37
+ ### v0.5.0
38
+
39
+ - Add `Protocol::URL::Encoding.decode_www_form` for decoding HTML form data where `+` represents a space.
40
+
41
+ ### v0.4.0
42
+
43
+ - Add comparison methods to `Protocol::URL::Relative` (and by inheritance to `Protocol::URL::Absolute`):
44
+ - `#==` for structural equality comparison (compares path, query, fragment components).
45
+ - `#===` for string equality comparison (enables case statement matching).
46
+ - `#<=>` for ordering and sorting.
47
+ - `#hash` for hash key support.
48
+ - `#equal?` for component-based equality checking.
49
+ - Add JSON serialization support to `Protocol::URL::Relative`:
50
+ - `#as_json` returns the string representation.
51
+ - `#to_json` returns a JSON-encoded string.
36
52
 
37
53
  ### v0.3.0
38
54
 
data/releases.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Releases
2
2
 
3
+ ## v0.5.0
4
+
5
+ - Add `Protocol::URL::Encoding.decode_www_form` for decoding HTML form data where `+` represents a space.
6
+
7
+ ## v0.4.0
8
+
9
+ - Add comparison methods to `Protocol::URL::Relative` (and by inheritance to `Protocol::URL::Absolute`):
10
+ - `#==` for structural equality comparison (compares path, query, fragment components).
11
+ - `#===` for string equality comparison (enables case statement matching).
12
+ - `#<=>` for ordering and sorting.
13
+ - `#hash` for hash key support.
14
+ - `#equal?` for component-based equality checking.
15
+ - Add JSON serialization support to `Protocol::URL::Relative`:
16
+ - `#as_json` returns the string representation.
17
+ - `#to_json` returns a JSON-encoded string.
18
+
3
19
  ## v0.3.0
4
20
 
5
21
  - Add `relative(target, from)` for computing relative paths between URLs.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-url
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -58,6 +58,7 @@ licenses:
58
58
  - MIT
59
59
  metadata:
60
60
  source_code_uri: https://github.com/socketry/protocol-url.git
61
+ documentation_uri: https://socketry.github.io/protocol-url/
61
62
  rdoc_options: []
62
63
  require_paths:
63
64
  - lib
@@ -72,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
73
  - !ruby/object:Gem::Version
73
74
  version: '0'
74
75
  requirements: []
75
- rubygems_version: 3.7.2
76
+ rubygems_version: 4.0.10
76
77
  specification_version: 4
77
78
  summary: Provides abstractions for working with URLs.
78
79
  test_files: []
metadata.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- 4���:U���F���}��M����GL��������+���$�����!�┋M#jh ��}�_:���x�ǂ��K���@���sڼ�j��4�qЎI�Ɇ+�-�C�r�e�<��u����_�!Qn �(�-䊍=0�������x����4=�Jۈ�W�͡�|�*�L��3��[�𹢶�[�[��d���fRᾉ�����3���N�C�e)ݔ�m���ҋ�k�G!�LO;
2
- nL�B���<�u`����5OPĭK�:��qX�)��UF��Dɿ[y�P��W��ڰ���\�%RqֻNz
1
+ s��Ѽ�2=�p���
2
+ �_|�xy-ꡨ]A=�q��L������,h��H�*��m�DR�oM��A���C�u���1���ϻ���T���r���IA���eK��5`}���E͎5����j�;�,����\��2����0��m��*�v#��r�=s�Z�@K^�N�Lw�`��TOS"�K ���� k|wN(� 0��r�g�FmM���3�T$8��_z�}6
3
+ HH���bX !��r�����U�v����dDN���EP�ۛ�<�Z�wx8��{��`��J?6��֩��S0ڲ����,1g�Sľ���P������ Fq{13�X�?c�.p. ��,�N�3!��