html2rss 0.32.4 → 0.33.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/lib/html2rss/article/enclosure.rb +2 -6
- data/lib/html2rss/auto_source/cleanup.rb +1 -3
- data/lib/html2rss/auto_source/scraper/html.rb +2 -8
- data/lib/html2rss/auto_source/scraper/json_document.rb +2 -3
- data/lib/html2rss/auto_source/scraper/json_state/article_normalizer.rb +128 -128
- data/lib/html2rss/auto_source/scraper/json_state/candidate_detector.rb +37 -37
- data/lib/html2rss/auto_source/scraper/json_state/document_scanner.rb +123 -123
- data/lib/html2rss/auto_source/scraper/json_state/value_finder.rb +34 -34
- data/lib/html2rss/auto_source/scraper/json_state.rb +2 -6
- data/lib/html2rss/auto_source/scraper/meta_oembed.rb +32 -2
- data/lib/html2rss/auto_source/scraper/microdata.rb +228 -245
- data/lib/html2rss/auto_source/scraper/microformats2.rb +9 -1
- data/lib/html2rss/auto_source/scraper/native_feed.rb +1 -1
- data/lib/html2rss/auto_source/scraper/schema/category_extractor.rb +7 -2
- data/lib/html2rss/auto_source/scraper/schema/item_list.rb +2 -2
- data/lib/html2rss/auto_source/scraper/schema/thing.rb +98 -21
- data/lib/html2rss/auto_source/scraper/schema.rb +49 -2
- data/lib/html2rss/auto_source/scraper/semantic_html.rb +12 -16
- data/lib/html2rss/auto_source/scraper/sitemap/parser.rb +1 -4
- data/lib/html2rss/auto_source/scraper/sitemap.rb +3 -11
- data/lib/html2rss/auto_source/scraper/wordpress_api/page_scope.rb +2 -2
- data/lib/html2rss/auto_source/scraper/wordpress_api/posts_endpoint.rb +1 -3
- data/lib/html2rss/auto_source/scraper/wordpress_api.rb +4 -4
- data/lib/html2rss/auto_source/scraper/xhr_articles.rb +1 -1
- data/lib/html2rss/auto_source/scraper.rb +0 -11
- data/lib/html2rss/auto_source/segmenter/cluster.rb +5 -11
- data/lib/html2rss/auto_source/segmenter/list.rb +25 -57
- data/lib/html2rss/auto_source/segmenter/semantic.rb +6 -13
- data/lib/html2rss/auto_source.rb +1 -1
- data/lib/html2rss/batch.rb +22 -32
- data/lib/html2rss/capture/README.md +1 -1
- data/lib/html2rss/capture.rb +7 -27
- data/lib/html2rss/cli/render.rb +97 -96
- data/lib/html2rss/cli/validate.rb +2 -4
- data/lib/html2rss/cli.rb +33 -27
- data/lib/html2rss/config/request_controls.rb +10 -2
- data/lib/html2rss/config/schema.rb +8 -10
- data/lib/html2rss/config/selectors_validator.rb +1 -0
- data/lib/html2rss/config/validator.rb +3 -3
- data/lib/html2rss/config.rb +1 -1
- data/lib/html2rss/defaults.rb +5 -16
- data/lib/html2rss/doctor/botasaurus.rb +11 -19
- data/lib/html2rss/error.rb +7 -3
- data/lib/html2rss/feed_builder/rss.rb +1 -1
- data/lib/html2rss/feed_pipeline/auto_fallback.rb +3 -3
- data/lib/html2rss/feed_resolution/candidate_generator.rb +3 -4
- data/lib/html2rss/feed_resolution/options.rb +3 -7
- data/lib/html2rss/feed_resolution/policy.rb +29 -33
- data/lib/html2rss/feed_resolution/probe.rb +3 -3
- data/lib/html2rss/feed_resolution/scorer.rb +29 -29
- data/lib/html2rss/feed_resolution.rb +5 -9
- data/lib/html2rss/feed_result.rb +4 -3
- data/lib/html2rss/hash_util.rb +91 -90
- data/lib/html2rss/html/article_extractor/category_extractor.rb +6 -9
- data/lib/html2rss/html/article_extractor/date_extractor.rb +1 -1
- data/lib/html2rss/html/article_extractor/enclosure_extractor.rb +1 -3
- data/lib/html2rss/html/article_extractor/id_generator.rb +1 -1
- data/lib/html2rss/html/probe.rb +51 -51
- data/lib/html2rss/link_destination/path_classifier.rb +11 -33
- data/lib/html2rss/mcp/config_argument.rb +9 -2
- data/lib/html2rss/mcp/contract.rb +7 -5
- data/lib/html2rss/mcp/outcome.rb +4 -5
- data/lib/html2rss/mcp/runtime.rb +17 -24
- data/lib/html2rss/mcp/server/tools.rb +9 -9
- data/lib/html2rss/option.rb +48 -0
- data/lib/html2rss/page_recon/diagnostics.rb +7 -9
- data/lib/html2rss/page_recon.rb +0 -4
- data/lib/html2rss/recon.rb +10 -12
- data/lib/html2rss/request_service/blocked_surface.rb +3 -7
- data/lib/html2rss/request_service/botasaurus_strategy.rb +2 -2
- data/lib/html2rss/request_service/budget.rb +3 -24
- data/lib/html2rss/request_service/compressed_body.rb +36 -48
- data/lib/html2rss/request_service/context.rb +1 -3
- data/lib/html2rss/request_service/local_file_strategy.rb +0 -1
- data/lib/html2rss/request_service/network_guard.rb +3 -2
- data/lib/html2rss/request_service/policy.rb +8 -26
- data/lib/html2rss/request_service/response.rb +3 -6
- data/lib/html2rss/request_session/pager/base.rb +3 -3
- data/lib/html2rss/request_session/pager/custom_selector.rb +4 -4
- data/lib/html2rss/request_session/pager/offset.rb +1 -7
- data/lib/html2rss/request_session/pager/rel_next.rb +1 -1
- data/lib/html2rss/request_session/pager/url_template.rb +1 -7
- data/lib/html2rss/scoring/engine.rb +4 -32
- data/lib/html2rss/scoring/link_resolver.rb +2 -7
- data/lib/html2rss/selectors/extractors/href.rb +2 -4
- data/lib/html2rss/selectors/json_xml.rb +33 -34
- data/lib/html2rss/selectors/post_processors/gsub.rb +2 -3
- data/lib/html2rss/selectors/post_processors/parse_time.rb +4 -5
- data/lib/html2rss/selectors/schema_export.rb +60 -60
- data/lib/html2rss/selectors.rb +14 -18
- data/lib/html2rss/sst/node.rb +9 -3
- data/lib/html2rss/sst/normalizer.rb +25 -24
- data/lib/html2rss/sst/text.rb +53 -57
- data/lib/html2rss/status.rb +23 -30
- data/lib/html2rss/syndication/alternate_links.rb +39 -0
- data/lib/html2rss/syndication/discovery.rb +117 -187
- data/lib/html2rss/syndication/parser.rb +92 -115
- data/lib/html2rss/test/enhance_audit.rb +13 -15
- data/lib/html2rss/test/policy.rb +9 -11
- data/lib/html2rss/test.rb +29 -48
- data/lib/html2rss/url.rb +53 -53
- data/lib/html2rss/version.rb +1 -1
- data/lib/html2rss.rb +2 -1
- metadata +4 -2
data/lib/html2rss/url.rb
CHANGED
|
@@ -26,6 +26,9 @@ module Html2rss
|
|
|
26
26
|
class Url
|
|
27
27
|
include Comparable
|
|
28
28
|
|
|
29
|
+
# Raised when a string cannot be parsed or resolved to a valid URL.
|
|
30
|
+
class InvalidUrlError < Html2rss::Error; end
|
|
31
|
+
|
|
29
32
|
# Regular expression for basic URI format validation
|
|
30
33
|
URI_REGEXP = Addressable::URI::URIREGEX
|
|
31
34
|
# Schemes accepted by channel URL validation.
|
|
@@ -37,22 +40,21 @@ module Html2rss
|
|
|
37
40
|
# @param relative_url [String, Html2rss::Url] the relative URL to resolve
|
|
38
41
|
# @param base_url [String, Html2rss::Url] the base URL to resolve against
|
|
39
42
|
# @return [Url] the resolved absolute URL
|
|
40
|
-
# @raise [
|
|
43
|
+
# @raise [InvalidUrlError] if the URL cannot be parsed
|
|
41
44
|
def self.from_relative(relative_url, base_url)
|
|
42
45
|
url = Addressable::URI.parse(relative_url.to_s.strip)
|
|
43
46
|
return new(url) if url.absolute?
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
join_parsed_base(base_url, url)
|
|
46
49
|
rescue Addressable::URI::InvalidURIError
|
|
47
|
-
raise
|
|
50
|
+
raise InvalidUrlError, 'URL could not be parsed'
|
|
48
51
|
end
|
|
49
52
|
|
|
50
|
-
# @param base_url [String]
|
|
53
|
+
# @param base_url [String, Url]
|
|
51
54
|
# @param url [Addressable::URI]
|
|
52
55
|
# @return [Url]
|
|
53
56
|
def self.join_parsed_base(base_url, url)
|
|
54
57
|
uri = Addressable::URI.parse(base_url.to_s)
|
|
55
|
-
uri.path = '/' if uri.path.empty?
|
|
56
58
|
new(uri.join(url).normalize)
|
|
57
59
|
end
|
|
58
60
|
private_class_method :join_parsed_base
|
|
@@ -64,10 +66,10 @@ module Html2rss
|
|
|
64
66
|
# @param raw_url [String] the raw URL string to sanitize
|
|
65
67
|
# @return [Url, nil] the sanitized URL, or nil if no valid URL found
|
|
66
68
|
def self.sanitize(raw_url)
|
|
67
|
-
match = raw_url.to_s.match(%r{(?:(?:https?|ftp
|
|
69
|
+
match = raw_url.to_s.match(%r{(?:(?:https?|ftp)://|mailto:)[^\s<>"]+})
|
|
68
70
|
return unless match
|
|
69
71
|
|
|
70
|
-
new(Addressable::URI.parse(match[0]
|
|
72
|
+
new(Addressable::URI.parse(match[0]).normalize)
|
|
71
73
|
end
|
|
72
74
|
|
|
73
75
|
##
|
|
@@ -75,15 +77,15 @@ module Html2rss
|
|
|
75
77
|
#
|
|
76
78
|
# @param url_string [String, Html2rss::Url] the absolute URL to parse
|
|
77
79
|
# @return [Url] the parsed and normalized URL
|
|
78
|
-
# @raise [
|
|
80
|
+
# @raise [InvalidUrlError] if the URL is not absolute or cannot be parsed
|
|
79
81
|
def self.from_absolute(url_string)
|
|
80
82
|
return url_string if url_string.is_a?(self)
|
|
81
83
|
|
|
82
|
-
new(Addressable::URI.parse(url_string.to_s.
|
|
83
|
-
raise
|
|
84
|
+
new(Addressable::URI.parse(url_string.to_s.lstrip).normalize).tap do |url|
|
|
85
|
+
raise InvalidUrlError, 'URL must be absolute' unless url.absolute?
|
|
84
86
|
end
|
|
85
87
|
rescue Addressable::URI::InvalidURIError
|
|
86
|
-
raise
|
|
88
|
+
raise InvalidUrlError, 'URL must be absolute'
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
##
|
|
@@ -92,20 +94,30 @@ module Html2rss
|
|
|
92
94
|
#
|
|
93
95
|
# @param url_string [String] the URL string to validate and parse
|
|
94
96
|
# @return [Url] the validated and parsed URL
|
|
95
|
-
# @raise [
|
|
97
|
+
# @raise [InvalidUrlError] if the URL doesn't meet channel requirements
|
|
96
98
|
# @example Creating a channel URL
|
|
97
99
|
# Url.for_channel('https://example.com')
|
|
98
100
|
# # => #<Html2rss::Url:... @uri=#<Addressable::URI:... URI:https://example.com>>
|
|
99
101
|
# @example Invalid channel URL
|
|
100
102
|
# Url.for_channel('/relative/path')
|
|
101
|
-
# # => raises
|
|
103
|
+
# # => raises InvalidUrlError: "URL must be absolute"
|
|
102
104
|
def self.for_channel(url_string)
|
|
103
|
-
stripped = url_string.to_s.
|
|
105
|
+
stripped = url_string.to_s.lstrip
|
|
104
106
|
return nil if stripped.empty?
|
|
105
107
|
|
|
106
108
|
from_absolute(stripped).tap { validate_channel_url(_1) }
|
|
107
109
|
end
|
|
108
110
|
|
|
111
|
+
##
|
|
112
|
+
# Creates an absolute http(s) URL, for example for a channel image.
|
|
113
|
+
#
|
|
114
|
+
# @param url_string [String, Html2rss::Url] the URL to validate and parse
|
|
115
|
+
# @return [Url] the validated and parsed URL
|
|
116
|
+
# @raise [InvalidUrlError] if the URL is not absolute or not http(s)
|
|
117
|
+
def self.from_absolute_web(url_string)
|
|
118
|
+
from_absolute(url_string).tap { validate_scheme(_1) }
|
|
119
|
+
end
|
|
120
|
+
|
|
109
121
|
##
|
|
110
122
|
# Extracts a base URL from HTML metadata tags.
|
|
111
123
|
#
|
|
@@ -116,10 +128,10 @@ module Html2rss
|
|
|
116
128
|
tags = { 'link[rel="canonical"]' => 'href', 'meta[property="og:url"]' => 'content',
|
|
117
129
|
'meta[name="twitter:url"]' => 'content', 'base[href]' => 'href' }
|
|
118
130
|
tags.each do |sel, attr|
|
|
119
|
-
val = doc.at_css(sel)&.[](attr)
|
|
120
|
-
return from_absolute(val)
|
|
121
|
-
rescue
|
|
122
|
-
|
|
131
|
+
val = doc.at_css(sel)&.[](attr)
|
|
132
|
+
return from_absolute(val)
|
|
133
|
+
rescue InvalidUrlError
|
|
134
|
+
nil
|
|
123
135
|
end
|
|
124
136
|
nil
|
|
125
137
|
end
|
|
@@ -128,31 +140,32 @@ module Html2rss
|
|
|
128
140
|
# Validates that a URL meets channel requirements.
|
|
129
141
|
#
|
|
130
142
|
# @param url [Url] the URL to validate
|
|
131
|
-
# @raise [
|
|
143
|
+
# @raise [InvalidUrlError] if the URL doesn't meet channel requirements
|
|
132
144
|
def self.validate_channel_url(url)
|
|
133
|
-
|
|
145
|
+
has_forbidden_at = url.user
|
|
146
|
+
has_forbidden_at ||= [url.query, url.fragment].compact.any? { |value| value.include?('@') }
|
|
147
|
+
raise InvalidUrlError, 'URL must not contain an @ character' if has_forbidden_at
|
|
134
148
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
has_forbidden_at ||= [uri.query, uri.fragment].compact.any? { |value| value.include?('@') }
|
|
138
|
-
raise ArgumentError, 'URL must not contain an @ character' if has_forbidden_at
|
|
149
|
+
validate_scheme(url)
|
|
150
|
+
end
|
|
139
151
|
|
|
152
|
+
def self.validate_scheme(url)
|
|
140
153
|
scheme = url.scheme
|
|
141
|
-
raise
|
|
154
|
+
raise InvalidUrlError, "URL scheme '#{scheme}' is not supported" unless SUPPORTED_SCHEMES.include?(scheme)
|
|
142
155
|
end
|
|
143
156
|
|
|
144
|
-
private_class_method :validate_channel_url
|
|
157
|
+
private_class_method :validate_channel_url, :validate_scheme
|
|
145
158
|
|
|
146
159
|
##
|
|
147
160
|
# @param uri [Addressable::URI] the underlying Addressable::URI object (internal use only)
|
|
148
161
|
def initialize(uri)
|
|
149
162
|
@uri = uri.freeze
|
|
150
|
-
@path_segments =
|
|
163
|
+
@path_segments = path.split('/').reject(&:empty?).freeze
|
|
151
164
|
freeze
|
|
152
165
|
end
|
|
153
166
|
|
|
154
167
|
# @return [String] normalized URL string
|
|
155
|
-
def to_s = @uri.
|
|
168
|
+
def to_s = @uri.to_str
|
|
156
169
|
|
|
157
170
|
# @return [String, nil] URI scheme, for example `http` or `https`
|
|
158
171
|
def scheme = @uri.scheme
|
|
@@ -160,6 +173,9 @@ module Html2rss
|
|
|
160
173
|
# @return [String, nil] URI host component
|
|
161
174
|
def host = @uri.host
|
|
162
175
|
|
|
176
|
+
# @return [String, nil] userinfo user, without the password
|
|
177
|
+
def user = @uri.user
|
|
178
|
+
|
|
163
179
|
# Registrable domain (eTLD+1). Same-site hosts like www.wp.pl and wiadomosci.wp.pl
|
|
164
180
|
# share `wp.pl`. IP literals stay the host so 1.2.3.4 is not treated as `3.4`.
|
|
165
181
|
#
|
|
@@ -189,7 +205,7 @@ module Html2rss
|
|
|
189
205
|
# Returns the URL query string as a hash of string keys and values.
|
|
190
206
|
#
|
|
191
207
|
# @return [Hash{String => String}] normalized query parameters
|
|
192
|
-
def query_values = @uri.query_values
|
|
208
|
+
def query_values = @uri.query_values || {}
|
|
193
209
|
|
|
194
210
|
##
|
|
195
211
|
# Returns the URL path split into non-empty segments.
|
|
@@ -205,7 +221,7 @@ module Html2rss
|
|
|
205
221
|
def with_path(path)
|
|
206
222
|
uri = @uri.dup
|
|
207
223
|
uri.path = path
|
|
208
|
-
self.class.from_absolute(uri
|
|
224
|
+
self.class.from_absolute(uri)
|
|
209
225
|
end
|
|
210
226
|
|
|
211
227
|
##
|
|
@@ -213,7 +229,7 @@ module Html2rss
|
|
|
213
229
|
#
|
|
214
230
|
# @return [Url] this URL when already fragment-free; otherwise a new URL
|
|
215
231
|
def without_fragment
|
|
216
|
-
|
|
232
|
+
fragment ? self.class.from_absolute(@uri.omit(:fragment)) : self
|
|
217
233
|
end
|
|
218
234
|
|
|
219
235
|
##
|
|
@@ -224,7 +240,7 @@ module Html2rss
|
|
|
224
240
|
def with_query_values(values)
|
|
225
241
|
uri = @uri.dup
|
|
226
242
|
uri.query_values = values.transform_keys(&:to_s).transform_values(&:to_s)
|
|
227
|
-
self.class.from_absolute(uri
|
|
243
|
+
self.class.from_absolute(uri)
|
|
228
244
|
end
|
|
229
245
|
|
|
230
246
|
##
|
|
@@ -240,15 +256,7 @@ module Html2rss
|
|
|
240
256
|
# url = Url.from_absolute('https://example.com/hello%20world/article.html')
|
|
241
257
|
# url.titleized # => "Hello World Article"
|
|
242
258
|
def titleized
|
|
243
|
-
|
|
244
|
-
return '' if path.empty?
|
|
245
|
-
|
|
246
|
-
nicer_path = CGI.unescapeURIComponent(path)
|
|
247
|
-
.split('/')
|
|
248
|
-
.flat_map do |part|
|
|
249
|
-
part.gsub(/[^a-zA-Z0-9.]/, ' ').gsub(/\s+/, ' ').split
|
|
250
|
-
end
|
|
251
|
-
|
|
259
|
+
nicer_path = CGI.unescapeURIComponent(path).gsub(/[^a-zA-Z0-9.]/, ' ').split
|
|
252
260
|
nicer_path.map!(&:capitalize)
|
|
253
261
|
File.basename(nicer_path.join(' '), '.*')
|
|
254
262
|
end
|
|
@@ -266,8 +274,7 @@ module Html2rss
|
|
|
266
274
|
# url = Url.from_absolute('https://example.com')
|
|
267
275
|
# url.channel_titleized # => "example.com"
|
|
268
276
|
def channel_titleized
|
|
269
|
-
nicer_path = CGI.unescapeURIComponent(
|
|
270
|
-
host = @uri.host
|
|
277
|
+
nicer_path = CGI.unescapeURIComponent(path).split('/').reject(&:empty?)
|
|
271
278
|
|
|
272
279
|
nicer_path.any? ? "#{host}: #{nicer_path.map(&:capitalize).join(' ')}" : host
|
|
273
280
|
end
|
|
@@ -318,12 +325,7 @@ module Html2rss
|
|
|
318
325
|
# @param relative_uri [Addressable::URI]
|
|
319
326
|
# @return [Url]
|
|
320
327
|
def join_uri(relative_uri)
|
|
321
|
-
|
|
322
|
-
if base.path.empty?
|
|
323
|
-
base = base.dup
|
|
324
|
-
base.path = '/'
|
|
325
|
-
end
|
|
326
|
-
self.class.new(base.join(relative_uri).normalize)
|
|
328
|
+
self.class.new(@uri.join(relative_uri).normalize)
|
|
327
329
|
end
|
|
328
330
|
|
|
329
331
|
protected
|
|
@@ -332,15 +334,13 @@ module Html2rss
|
|
|
332
334
|
#
|
|
333
335
|
# @return [String]
|
|
334
336
|
def document_identity
|
|
335
|
-
|
|
336
|
-
"#{uri.scheme}\0#{uri.authority}\0#{uri.path.to_s.chomp('/')}\0#{uri.query}"
|
|
337
|
+
"#{scheme}\0#{@uri.authority}\0#{path.chomp('/')}\0#{query}"
|
|
337
338
|
end
|
|
338
339
|
|
|
339
340
|
private
|
|
340
341
|
|
|
341
342
|
def ip_address_host?
|
|
342
|
-
IPAddr.new(host.
|
|
343
|
-
true
|
|
343
|
+
!IPAddr.new(host).nil?
|
|
344
344
|
rescue IPAddr::Error
|
|
345
345
|
false
|
|
346
346
|
end
|
data/lib/html2rss/version.rb
CHANGED
data/lib/html2rss.rb
CHANGED
|
@@ -101,7 +101,7 @@ module Html2rss # rubocop:disable Metrics/ModuleLength
|
|
|
101
101
|
#
|
|
102
102
|
# @param config_input [Hash, String] config hash, YAML string, or file path
|
|
103
103
|
# @param feed_name [String, nil] optional feed name in multi-feed file
|
|
104
|
-
# @param min_items [Integer] minimum required items (default: 1)
|
|
104
|
+
# @param min_items [Integer] minimum required items, >= 0 (default: 1)
|
|
105
105
|
# @param params [Hash] dynamic feed params
|
|
106
106
|
# @param strategy [Symbol, nil] optional strategy override
|
|
107
107
|
# @param strict_quality [Boolean] when true, fail on ship-quality audit thresholds
|
|
@@ -109,6 +109,7 @@ module Html2rss # rubocop:disable Metrics/ModuleLength
|
|
|
109
109
|
# @return [Html2rss::Test::Result]
|
|
110
110
|
def self.test(config_input, feed_name = nil, min_items: 1, params: {}, strategy: nil, strict_quality: false, # rubocop:disable Metrics/ParameterLists
|
|
111
111
|
compare_enhance: false)
|
|
112
|
+
Option.integer(:min_items, min_items, min: 0)
|
|
112
113
|
Test.call(config_input, feed_name, min_items:, params:, strategy:, strict_quality:, compare_enhance:)
|
|
113
114
|
end
|
|
114
115
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: html2rss
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.33.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gil Desmarais
|
|
@@ -391,6 +391,7 @@ files:
|
|
|
391
391
|
- lib/html2rss/mcp/runtime.rb
|
|
392
392
|
- lib/html2rss/mcp/server.rb
|
|
393
393
|
- lib/html2rss/mcp/server/tools.rb
|
|
394
|
+
- lib/html2rss/option.rb
|
|
394
395
|
- lib/html2rss/page_recon.rb
|
|
395
396
|
- lib/html2rss/page_recon/README.md
|
|
396
397
|
- lib/html2rss/page_recon/diagnostics.rb
|
|
@@ -463,6 +464,7 @@ files:
|
|
|
463
464
|
- lib/html2rss/surface_category.rb
|
|
464
465
|
- lib/html2rss/syndication.rb
|
|
465
466
|
- lib/html2rss/syndication/README.md
|
|
467
|
+
- lib/html2rss/syndication/alternate_links.rb
|
|
466
468
|
- lib/html2rss/syndication/candidate_catalog.rb
|
|
467
469
|
- lib/html2rss/syndication/discovery.rb
|
|
468
470
|
- lib/html2rss/syndication/parser.rb
|
|
@@ -478,7 +480,7 @@ licenses:
|
|
|
478
480
|
- MIT
|
|
479
481
|
metadata:
|
|
480
482
|
allowed_push_host: https://rubygems.org
|
|
481
|
-
changelog_uri: https://github.com/html2rss/html2rss/releases/tag/v0.
|
|
483
|
+
changelog_uri: https://github.com/html2rss/html2rss/releases/tag/v0.33.0
|
|
482
484
|
rubygems_mfa_required: 'true'
|
|
483
485
|
rdoc_options: []
|
|
484
486
|
require_paths:
|