webmention 2.0.0 → 2.1.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: b40b0711592d5a14c2d9dc53b638e697ce1278ed3d3a851e559d6eb51752c7d4
4
- data.tar.gz: 8a5a3f9508a6f071cdcdb7fe5126909678538b20c1bf043110e0e06ea56e75d1
3
+ metadata.gz: 2939ada02eb29818ba6b84da3c64e7ce9f363cddc0299ddb423c60343fc202fc
4
+ data.tar.gz: 40e715d3602cebc2ef45261141b3cbf06de12661918ba746723e1785d689095e
5
5
  SHA512:
6
- metadata.gz: 8eb087999adce5389f37333598e1edaee18e96e748b9b11eee41f5bbb1ecc6cb511e0951eeba831df62d210972e296d0d5090adf6e25a3666eb182b503454d7e
7
- data.tar.gz: ccb4e243d5c050d6e912a47a4a1fa0ee02594211192e81737011db1ded8a88eac4bfd11f32749ffba7dea1b08a50d326ed446d0688bb1ce406095bbbc1f57a58
6
+ metadata.gz: c16e1234ec404e226d0c6f50362f0c53286416a2155094b372055f0f57e39d7ac8502d937ff101a835d7dcfe9be9fcd4716274af0acc521b7a7896dffa78753a
7
+ data.tar.gz: 620ed9d6bc592f1fe9174da42bc330592d459760e07e82a4b8f2b6361a3d377ab5c575d1de3a782c099e76b9c4b06ddaf65b2f08b8185897df91d963ed9bfb2a
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.1.0 / 2020-04-06
4
+
5
+ - Refactor `BaseParser` class and remove `Registerable` module (b706229)
6
+ - Refactor `HttpRequest` and `NodeParser` classes into Service Objects (f29c073 and 7456bf1)
7
+
3
8
  ## 2.0.0 / 2020-01-25
4
9
 
5
10
  - Add Ruby 2.7 to list of supported Ruby versions (c67ed14)
@@ -8,12 +8,14 @@ require 'webmention/version'
8
8
  require 'webmention/exceptions'
9
9
 
10
10
  require 'webmention/client'
11
- require 'webmention/http_request'
12
- require 'webmention/registerable'
13
11
 
14
12
  require 'webmention/parsers'
13
+ require 'webmention/parsers/base_parser'
15
14
  require 'webmention/parsers/html_parser'
16
15
 
16
+ require 'webmention/services/http_request_service'
17
+ require 'webmention/services/node_parser_service'
18
+
17
19
  module Webmention
18
20
  class << self
19
21
  def client(source)
@@ -23,7 +23,7 @@ module Webmention
23
23
 
24
24
  return unless endpoint
25
25
 
26
- HttpRequest.post(Addressable::URI.parse(endpoint), source: @source, target: target)
26
+ Services::HttpRequestService.post(Addressable::URI.parse(endpoint), source: @source, target: target)
27
27
  rescue IndieWeb::Endpoints::IndieWebEndpointsError => exception
28
28
  raise Webmention.const_get(exception.class.name.split('::').last), exception
29
29
  end
@@ -35,7 +35,7 @@ module Webmention
35
35
  end
36
36
 
37
37
  def source_response
38
- @source_response ||= HttpRequest.get(source_uri)
38
+ @source_response ||= Services::HttpRequestService.get(source_uri)
39
39
  end
40
40
 
41
41
  def source_uri
@@ -1,29 +1,11 @@
1
1
  module Webmention
2
2
  module Parsers
3
- extend Registerable
4
-
5
- class BaseParser
6
- def initialize(response)
7
- raise ArgumentError, "response must be an HTTP::Response (given #{response.class.name})" unless response.is_a?(HTTP::Response)
8
-
9
- @response = response
10
-
11
- raise UnsupportedMimeTypeError, "Unsupported MIME Type: #{response.mime_type}" unless self.class.mime_types.include?(response.mime_type)
12
- end
13
-
14
- def results
15
- @results ||= parse_response_body
16
- end
17
-
18
- private
19
-
20
- def response_body
21
- @response_body ||= @response.body.to_s
22
- end
3
+ def self.register(klass)
4
+ klass.mime_types.each { |mime_type| registered[mime_type] = klass }
5
+ end
23
6
 
24
- def response_url
25
- @response_url ||= @response.uri.to_s
26
- end
7
+ def self.registered
8
+ @registered ||= {}
27
9
  end
28
10
  end
29
11
  end
@@ -0,0 +1,31 @@
1
+ module Webmention
2
+ module Parsers
3
+ class BaseParser
4
+ class << self
5
+ attr_reader :mime_types
6
+ end
7
+
8
+ def initialize(response)
9
+ raise ArgumentError, "response must be an HTTP::Response (given #{response.class.name})" unless response.is_a?(HTTP::Response)
10
+
11
+ @response = response
12
+
13
+ raise UnsupportedMimeTypeError, "Unsupported MIME Type: #{response.mime_type}" unless self.class.mime_types.include?(response.mime_type)
14
+ end
15
+
16
+ def results
17
+ @results ||= parse_response_body
18
+ end
19
+
20
+ private
21
+
22
+ def response_body
23
+ @response_body ||= @response.body.to_s
24
+ end
25
+
26
+ def response_url
27
+ @response_url ||= @response.uri.to_s
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,9 +1,7 @@
1
1
  module Webmention
2
2
  module Parsers
3
3
  class HtmlParser < BaseParser
4
- def self.mime_types
5
- ['text/html']
6
- end
4
+ @mime_types = ['text/html']
7
5
 
8
6
  Parsers.register(self)
9
7
 
@@ -38,35 +36,11 @@ module Webmention
38
36
  end
39
37
 
40
38
  def root_node
41
- @root_node ||= doc.css('.h-entry .e-content').first || doc.css('.h-entry').first || doc.css('body')
39
+ @root_node ||= doc.at_css('.h-entry .e-content') || doc.at_css('.h-entry') || doc.css('body')
42
40
  end
43
41
 
44
42
  def search_node(attribute, selectors)
45
- NodeParser.nodes_from(root_node, selectors).map { |node| NodeParser.values_from(node, attribute) }.reject(&:empty?)
46
- end
47
-
48
- module NodeParser
49
- class << self
50
- # Search a node for matching elements
51
- #
52
- # @param node [Nokogiri::XML::Element]
53
- # @param selectors [Array]
54
- # @return [Nokogiri::XML::NodeSet]
55
- def nodes_from(node, selectors)
56
- node.css(*selectors)
57
- end
58
-
59
- # Derive attribute values from a single node
60
- #
61
- # @param node [Nokogiri::XML::Element]
62
- # @param attribute [Symbol]
63
- # @return [Array] the HTML attribute values
64
- def values_from(node, attribute)
65
- return Array(node[attribute]) unless attribute == :srcset
66
-
67
- node[attribute].split(',').map { |value| value.strip.match(/^\S+/).to_s }
68
- end
69
- end
43
+ Services::NodeParserService.nodes_from(root_node, selectors).map { |node| Services::NodeParserService.values_from(node, attribute) }.reject(&:empty?)
70
44
  end
71
45
  end
72
46
  end
@@ -0,0 +1,47 @@
1
+ module Webmention
2
+ module Services
3
+ module HttpRequestService
4
+ # Defaults derived from Webmention specification examples
5
+ # https://www.w3.org/TR/webmention/#limits-on-get-requests
6
+ # rubocop:disable Layout/HashAlignment
7
+ HTTP_CLIENT_OPTS = {
8
+ follow: {
9
+ max_hops: 20
10
+ },
11
+ headers: {
12
+ accept: '*/*',
13
+ user_agent: 'Webmention Client (https://rubygems.org/gems/webmention)'
14
+ },
15
+ timeout_options: {
16
+ connect_timeout: 5,
17
+ read_timeout: 5
18
+ }
19
+ }.freeze
20
+ # rubocop:enable Layout/HashAlignment
21
+
22
+ class << self
23
+ def get(uri)
24
+ request(:get, uri)
25
+ end
26
+
27
+ def post(uri, **options)
28
+ request(:post, uri, form: options)
29
+ end
30
+
31
+ private
32
+
33
+ def client
34
+ @client ||= HTTP::Client.new(HTTP_CLIENT_OPTS)
35
+ end
36
+
37
+ def request(method, uri, **options)
38
+ client.request(method, uri, options)
39
+ rescue HTTP::ConnectionError,
40
+ HTTP::TimeoutError,
41
+ HTTP::Redirector::TooManyRedirectsError => exception
42
+ raise Webmention.const_get(exception.class.name.split('::').last), exception
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,25 @@
1
+ module Webmention
2
+ module Services
3
+ module NodeParserService
4
+ # Search a node for matching elements
5
+ #
6
+ # @param node [Nokogiri::XML::Element]
7
+ # @param selectors [Array]
8
+ # @return [Nokogiri::XML::NodeSet]
9
+ def self.nodes_from(node, selectors)
10
+ node.css(*selectors)
11
+ end
12
+
13
+ # Derive attribute values from a single node
14
+ #
15
+ # @param node [Nokogiri::XML::Element]
16
+ # @param attribute [Symbol]
17
+ # @return [Array] the HTML attribute values
18
+ def self.values_from(node, attribute)
19
+ return Array(node[attribute]) unless attribute == :srcset
20
+
21
+ node[attribute].split(',').map { |value| value.strip.match(/^\S+/).to_s }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module Webmention
2
- VERSION = '2.0.0'.freeze
2
+ VERSION = '2.1.0'.freeze
3
3
  end
@@ -28,16 +28,16 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency 'minitest', '~> 5.14'
29
29
  spec.add_development_dependency 'minitest-reporters', '~> 1.4'
30
30
  spec.add_development_dependency 'rake', '~> 13.0'
31
- spec.add_development_dependency 'reek', '~> 5.6'
32
- spec.add_development_dependency 'rubocop', '~> 0.79.0'
31
+ spec.add_development_dependency 'reek', '~> 6.0'
32
+ spec.add_development_dependency 'rubocop', '~> 0.81.0'
33
33
  spec.add_development_dependency 'rubocop-performance', '~> 1.5'
34
- spec.add_development_dependency 'simplecov', '~> 0.17.1'
35
- spec.add_development_dependency 'simplecov-console', '~> 0.6.0'
34
+ spec.add_development_dependency 'simplecov', '~> 0.18.5'
35
+ spec.add_development_dependency 'simplecov-console', '~> 0.7.2'
36
36
  spec.add_development_dependency 'webmock', '~> 3.8'
37
37
 
38
38
  spec.add_runtime_dependency 'absolutely', '~> 3.1'
39
39
  spec.add_runtime_dependency 'addressable', '~> 2.7'
40
- spec.add_runtime_dependency 'http', '~> 4.3'
40
+ spec.add_runtime_dependency 'http', '~> 4.4'
41
41
  spec.add_runtime_dependency 'indieweb-endpoints', '~> 2.0'
42
42
  spec.add_runtime_dependency 'nokogiri', '~> 1.10'
43
43
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webmention
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Parecki
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-01-25 00:00:00.000000000 Z
12
+ date: 2020-04-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -59,28 +59,28 @@ dependencies:
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '5.6'
62
+ version: '6.0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '5.6'
69
+ version: '6.0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: rubocop
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: 0.79.0
76
+ version: 0.81.0
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: 0.79.0
83
+ version: 0.81.0
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: rubocop-performance
86
86
  requirement: !ruby/object:Gem::Requirement
@@ -101,28 +101,28 @@ dependencies:
101
101
  requirements:
102
102
  - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: 0.17.1
104
+ version: 0.18.5
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - "~>"
110
110
  - !ruby/object:Gem::Version
111
- version: 0.17.1
111
+ version: 0.18.5
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: simplecov-console
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - "~>"
117
117
  - !ruby/object:Gem::Version
118
- version: 0.6.0
118
+ version: 0.7.2
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - "~>"
124
124
  - !ruby/object:Gem::Version
125
- version: 0.6.0
125
+ version: 0.7.2
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: webmock
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -171,14 +171,14 @@ dependencies:
171
171
  requirements:
172
172
  - - "~>"
173
173
  - !ruby/object:Gem::Version
174
- version: '4.3'
174
+ version: '4.4'
175
175
  type: :runtime
176
176
  prerelease: false
177
177
  version_requirements: !ruby/object:Gem::Requirement
178
178
  requirements:
179
179
  - - "~>"
180
180
  - !ruby/object:Gem::Version
181
- version: '4.3'
181
+ version: '4.4'
182
182
  - !ruby/object:Gem::Dependency
183
183
  name: indieweb-endpoints
184
184
  requirement: !ruby/object:Gem::Requirement
@@ -231,10 +231,11 @@ files:
231
231
  - lib/webmention.rb
232
232
  - lib/webmention/client.rb
233
233
  - lib/webmention/exceptions.rb
234
- - lib/webmention/http_request.rb
235
234
  - lib/webmention/parsers.rb
235
+ - lib/webmention/parsers/base_parser.rb
236
236
  - lib/webmention/parsers/html_parser.rb
237
- - lib/webmention/registerable.rb
237
+ - lib/webmention/services/http_request_service.rb
238
+ - lib/webmention/services/node_parser_service.rb
238
239
  - lib/webmention/version.rb
239
240
  - webmention.gemspec
240
241
  homepage: https://github.com/indieweb/webmention-client-ruby
@@ -242,7 +243,7 @@ licenses:
242
243
  - Apache-2.0
243
244
  metadata:
244
245
  bug_tracker_uri: https://github.com/indieweb/webmention-client-ruby/issues
245
- changelog_uri: https://github.com/indieweb/webmention-client-ruby/blob/v2.0.0/CHANGELOG.md
246
+ changelog_uri: https://github.com/indieweb/webmention-client-ruby/blob/v2.1.0/CHANGELOG.md
246
247
  post_install_message:
247
248
  rdoc_options: []
248
249
  require_paths:
@@ -261,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
262
  - !ruby/object:Gem::Version
262
263
  version: '0'
263
264
  requirements: []
264
- rubygems_version: 3.0.6
265
+ rubygems_version: 3.1.2
265
266
  signing_key:
266
267
  specification_version: 4
267
268
  summary: Webmention notification client
@@ -1,41 +0,0 @@
1
- module Webmention
2
- class HttpRequest
3
- # Defaults derived from Webmention specification examples
4
- # https://www.w3.org/TR/webmention/#limits-on-get-requests
5
- # rubocop:disable Layout/HashAlignment
6
- HTTP_CLIENT_OPTS = {
7
- follow: {
8
- max_hops: 20
9
- },
10
- headers: {
11
- accept: '*/*',
12
- user_agent: 'Webmention Client (https://rubygems.org/gems/webmention)'
13
- },
14
- timeout_options: {
15
- connect_timeout: 5,
16
- read_timeout: 5
17
- }
18
- }.freeze
19
- # rubocop:enable Layout/HashAlignment
20
-
21
- class << self
22
- def get(uri)
23
- request(:get, uri)
24
- end
25
-
26
- def post(uri, **options)
27
- request(:post, uri, form: options)
28
- end
29
-
30
- private
31
-
32
- def request(method, uri, **options)
33
- HTTP::Client.new(HTTP_CLIENT_OPTS).request(method, uri, options)
34
- rescue HTTP::ConnectionError,
35
- HTTP::TimeoutError,
36
- HTTP::Redirector::TooManyRedirectsError => exception
37
- raise Webmention.const_get(exception.class.name.split('::').last), exception
38
- end
39
- end
40
- end
41
- end
@@ -1,11 +0,0 @@
1
- module Webmention
2
- module Registerable
3
- def register(klass)
4
- klass.mime_types.each { |mime_type| registered[mime_type] = klass }
5
- end
6
-
7
- def registered
8
- @registered ||= {}
9
- end
10
- end
11
- end