uri-whatwg_parser 0.1.4 → 0.1.5

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: 2061d819a10365a97f389d9cb70325c87b75c390c4145897ed640c3e4cc85f70
4
- data.tar.gz: 905ec3bdd174039fc91ce433f84a079fe12ff93f9ac999f420b08760b3fcee53
3
+ metadata.gz: 9fbee32c52de5146f74c7ca4bdc26914ba2d0b83de26cbc6880354961ed447c9
4
+ data.tar.gz: 0a5b14a90fe61b3647edde05f0aba209b56ecdc043f5a4bff77c894edbe73391
5
5
  SHA512:
6
- metadata.gz: fc4a0d83fb46e959feb1f7990fa1f119428764447c6d4d455ec5287d5823b19eec845ef4b8912ceeffd6233266b3142859a837c7a26e47e20315d64bb5660006
7
- data.tar.gz: bd36808311ae2330cd897ba824219d82cff0497d75531441b3679def9ff5ea1969297ccfcbb8cd02b83909a2f7a5c0de7f0d505bb79e1117494544dd3d4b3cfa
6
+ metadata.gz: e55b7d27284b8772179a4047081def6b28ce4ab0b9923d08fd7b7a27fdebe5f18eb356535fd70498f76f02e5f1c27817906d19104420bb34cf57b47c5791f0cd
7
+ data.tar.gz: 46efa3674cf7814d5500b07f7ea272e46aeeedbcea02077ff95e3ebd4fee5be73c9e3ebba2885a9a3e421f87dbf13be4214b0da9bcbfdad24df9f9cf75a9f182
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.5
2
+
3
+ * Remove `ipaddr` dependency
4
+
1
5
  ## 0.1.4
2
6
 
3
7
  * Support passing `encoding` option
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "uri/idna"
4
- require "ipaddr"
5
4
  require_relative "parser_helper"
6
5
 
7
6
  class URI::WhatwgParser
@@ -66,26 +65,128 @@ class URI::WhatwgParser
66
65
  output.join(".")
67
66
  end
68
67
 
69
- def parse_ipv6(host)
70
- addr = IPAddr.new(host)
71
- # NOTE: URL Standard doesn't support `zone_id`.
72
- raise ParseError, "invalid IPv6 format" unless addr.zone_id.nil?
73
- formatted_addr = (("%.32x" % addr).gsub(/.{4}(?!$)/, '\&:'))
74
- "[#{compress_ipv6(formatted_addr)}]"
75
- rescue IPAddr::InvalidAddressError
76
- raise ParseError, "invalid IPv6 format"
68
+ def parse_ipv6(input)
69
+ input = input[1..-2] if input.start_with?("[") && input.end_with?("]")
70
+ address = Array.new(8, 0)
71
+ piece_index = 0
72
+ compress = nil
73
+ chars = input.chars
74
+ i = 0
75
+
76
+ if chars[i] == ":"
77
+ raise ParseError, "invalid IPv6 format" unless chars[i + 1] == ":"
78
+ i += 2
79
+ compress = piece_index
80
+ end
81
+
82
+ while i < chars.length
83
+ raise ParseError, "invalid IPv6 format" if piece_index == 8
84
+
85
+ if chars[i] == ":"
86
+ raise ParseError, "invalid IPv6 format" if compress
87
+ i += 1
88
+ compress = piece_index
89
+ next
90
+ end
91
+
92
+ value = 0
93
+ length = 0
94
+ while length < 4 && i < chars.length && chars[i].match?(/[0-9A-Fa-f]/)
95
+ value = value * 16 + chars[i].to_i(16)
96
+ i += 1
97
+ length += 1
98
+ end
99
+
100
+ if chars[i] == "."
101
+ # IPv4-mapped address must be valid and complete, no trailing dot
102
+ ipv4_piece = chars[i - length, chars.length - (i - length)].join
103
+ parts = ipv4_piece.split(".")
104
+ if parts.length != 4 || parts.any? { |p| p.empty? } || ipv4_piece.end_with?(".")
105
+ raise ParseError, "invalid IPv6 format"
106
+ end
107
+
108
+ ipv4 = parse_ipv4(ipv4_piece)
109
+ address[piece_index] = (ipv4 >> 16) & 0xFFFF
110
+ address[piece_index + 1] = ipv4 & 0xFFFF
111
+ piece_index += 2
112
+ i = chars.length
113
+ break
114
+ end
115
+
116
+ raise ParseError, "invalid IPv6 format" if length == 0
117
+
118
+ address[piece_index] = value
119
+ piece_index += 1
120
+
121
+ if i < chars.length
122
+ if chars[i] == ":"
123
+ i += 1
124
+ elsif chars[i] != nil
125
+ raise ParseError, "invalid IPv6 format"
126
+ end
127
+ end
128
+ end
129
+
130
+ if compress
131
+ swaps = piece_index - compress
132
+ (0...swaps).each do |j|
133
+ address[7 - j] = address[compress + swaps - 1 - j]
134
+ address[compress + swaps - 1 - j] = 0
135
+ end
136
+ elsif piece_index != 8
137
+ raise ParseError, "invalid IPv6 format"
138
+ end
139
+
140
+ compress_ipv6(address)
77
141
  end
78
142
 
79
- def compress_ipv6(ip)
80
- output = ip.split(":").map { |term| term.sub(/\A0+/, "").empty? ? "0" : term.sub(/\A0+/, "") }.join(":")
81
- zeros = output.scan(/:?(?:0+:?){2,}/)
143
+ def compress_ipv6(address)
144
+ # Find the longest run of zeros for '::' compression
145
+ best_base = nil
146
+ best_len = 0
147
+ base = nil
148
+ len = 0
149
+
150
+ 8.times do |idx|
151
+ if address[idx] == 0
152
+ base = idx if base.nil?
153
+ len += 1
154
+ else
155
+ if len > best_len
156
+ best_base = base
157
+ best_len = len
158
+ end
159
+ base = nil
160
+ len = 0
161
+ end
162
+ end
163
+
164
+ if len > best_len
165
+ best_base = base
166
+ best_len = len
167
+ end
168
+
169
+ # Only compress if the run is at least two 0s
170
+ if best_len < 2
171
+ best_base = nil
172
+ end
82
173
 
83
- unless zeros.empty?
84
- max = zeros.max_by { |item| item.gsub(":", "").length }
85
- output = output.sub(max, "::")
174
+ # Build the string with '::' for the longest zero run
175
+ result = []
176
+ idx = 0
177
+ while idx < 8
178
+ if best_base == idx
179
+ result << "" if idx == 0
180
+ result << ""
181
+ idx += best_len
182
+ result << "" if idx == 8
183
+ next
184
+ end
185
+ result << address[idx].to_s(16)
186
+ idx += 1
86
187
  end
87
188
 
88
- output
189
+ "[#{result.join(":").gsub(/:{3,}/, "::")}]"
89
190
  end
90
191
 
91
192
  def parse_opaque_host(host)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module URI
4
4
  class WhatwgParser
5
- VERSION = "0.1.4"
5
+ VERSION = "0.1.5"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uri-whatwg_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Yaginuma
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-06-12 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: uri
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubygems_version: 3.6.2
89
+ rubygems_version: 3.6.7
90
90
  specification_version: 4
91
91
  summary: Ruby implementation of the WHATWG URL Living Standard
92
92
  test_files: []