webmention 2.2.0 → 3.0.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/.rubocop.yml +1 -0
- data/CHANGELOG.md +5 -0
- data/lib/webmention.rb +17 -8
- data/lib/webmention/client.rb +17 -0
- data/lib/webmention/parsers/base_parser.rb +0 -4
- data/lib/webmention/parsers/html_parser.rb +39 -21
- data/lib/webmention/version.rb +1 -1
- metadata +3 -4
- data/lib/webmention/services/node_parser_service.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39599574ee4962a000832e7a47c48fd78d58797181a12a554ca26065b2d860c1
|
4
|
+
data.tar.gz: aaf047a87adf3b2c171622725aabb9a5f5fc64267a98077c7f2eb8b8e5db0c55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db45f488f6e2f527b075764ad580817294ac8971248365270102ee244820c04a7f044612eebe6b7ebc52dbc1fe754b7b997e0da01f2a7b9994d4d51a77e92f82
|
7
|
+
data.tar.gz: 254fe4bda676161657ff674d75a0866f7711dca89d5f7b5f0f961178efbbd9915a3b89ac94497442906b73ee572ababc90fedf3909c85b8e39c2ed53b897689b
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v3.0.0 / 2020-05-19
|
4
|
+
|
5
|
+
- Reject "internal" URLs when sending webmentions (#24) (ccc82c8)
|
6
|
+
- Select only HTTP/HTTPS URLs when sending webmentions (#22) (39e5852)
|
7
|
+
|
3
8
|
## 2.2.0 / 2020-05-18
|
4
9
|
|
5
10
|
- Update absolutely and indieweb-endpoints gems (350d2ed)
|
data/lib/webmention.rb
CHANGED
@@ -14,16 +14,25 @@ require 'webmention/parsers/base_parser'
|
|
14
14
|
require 'webmention/parsers/html_parser'
|
15
15
|
|
16
16
|
require 'webmention/services/http_request_service'
|
17
|
-
require 'webmention/services/node_parser_service'
|
18
17
|
|
19
18
|
module Webmention
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
# Create a new Webmention::Client
|
20
|
+
# Convenience method for Webmention::Client.new
|
21
|
+
#
|
22
|
+
# client = Webmention.client('https://source.example.com/post/100')
|
23
|
+
#
|
24
|
+
# @param source [String] An absolute URL representing the source document
|
25
|
+
# @return [Webmention::Client]
|
26
|
+
def self.client(source)
|
27
|
+
Client.new(source)
|
28
|
+
end
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
30
|
+
# Send a webmention from the source URL to the target URL
|
31
|
+
#
|
32
|
+
# @param source [String] An absolute URL representing the source document
|
33
|
+
# @param target [String] An absolute URL representing the target document
|
34
|
+
# @return [HTTP::Response, nil]
|
35
|
+
def self.send_mention(source, target)
|
36
|
+
client(source).send_mention(target)
|
28
37
|
end
|
29
38
|
end
|
data/lib/webmention/client.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module Webmention
|
2
2
|
class Client
|
3
|
+
# Create a new Webmention::Client
|
4
|
+
#
|
5
|
+
# client = Webmention::Client.new('https://source.example.com/post/100')
|
6
|
+
#
|
7
|
+
# @param source [String] An absolute URL representing the source document
|
3
8
|
def initialize(source)
|
4
9
|
raise ArgumentError, "source must be a String (given #{source.class.name})" unless source.is_a?(String)
|
5
10
|
|
@@ -8,16 +13,28 @@ module Webmention
|
|
8
13
|
raise ArgumentError, 'source must be an absolute URL (e.g. https://example.com)' unless source_uri.absolute?
|
9
14
|
end
|
10
15
|
|
16
|
+
# Send webmentions to all mentioned URLs in this client's source document
|
17
|
+
#
|
18
|
+
# @return [Hash{String => HTTP::Response, nil}]
|
11
19
|
def send_all_mentions
|
12
20
|
mentioned_urls.each_with_object({}) { |url, hash| hash[url] = send_mention(url) }
|
13
21
|
end
|
14
22
|
|
23
|
+
# Extract mentioned URLs from this client's source document
|
24
|
+
#
|
25
|
+
# @return [Array<String>]
|
26
|
+
# @raise [Webmention::UnsupportedMimeTypeError]
|
15
27
|
def mentioned_urls
|
16
28
|
raise UnsupportedMimeTypeError, "Unsupported MIME Type: #{source_response.mime_type}" unless parser_for_mime_type
|
17
29
|
|
18
30
|
@mentioned_urls ||= parser_for_mime_type.new(source_response).results
|
19
31
|
end
|
20
32
|
|
33
|
+
# Send a webmention from this client's source URL to the target URL
|
34
|
+
#
|
35
|
+
# @param target [String] An absolute URL representing the target document
|
36
|
+
# @return [HTTP::Response, nil]
|
37
|
+
# @raise [Webmention::ArgumentError, Webmention::ConnectionError, Webmention::InvalidURIError, Webmention::TimeoutError, Webmention::TooManyRedirectsError]
|
21
38
|
def send_mention(target)
|
22
39
|
endpoint = IndieWeb::Endpoints.get(target).webmention
|
23
40
|
|
@@ -13,10 +13,6 @@ module Webmention
|
|
13
13
|
raise UnsupportedMimeTypeError, "Unsupported MIME Type: #{response.mime_type}" unless self.class.mime_types.include?(response.mime_type)
|
14
14
|
end
|
15
15
|
|
16
|
-
def results
|
17
|
-
@results ||= parse_response_body
|
18
|
-
end
|
19
|
-
|
20
16
|
private
|
21
17
|
|
22
18
|
def response_body
|
@@ -5,17 +5,22 @@ module Webmention
|
|
5
5
|
|
6
6
|
Parsers.register(self)
|
7
7
|
|
8
|
-
|
9
|
-
cite
|
10
|
-
data
|
11
|
-
href
|
12
|
-
poster
|
13
|
-
src
|
14
|
-
srcset
|
8
|
+
HTML_ATTRIBUTES_MAP = {
|
9
|
+
'cite' => %w[blockquote del ins q],
|
10
|
+
'data' => %w[object],
|
11
|
+
'href' => %w[a area],
|
12
|
+
'poster' => %w[video],
|
13
|
+
'src' => %w[audio embed img source track video],
|
14
|
+
'srcset' => %w[img source]
|
15
15
|
}.freeze
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
CSS_SELECTORS_ARRAY = HTML_ATTRIBUTES_MAP.flat_map { |attribute, names| names.map { |name| "#{name}[#{attribute}]" } }.freeze
|
18
|
+
|
19
|
+
# Parse an HTML string for URLs
|
20
|
+
#
|
21
|
+
# @return [Array<String>] Unique external URLs whose scheme matches http/https
|
22
|
+
def results
|
23
|
+
@results ||= resolved_urls.uniq.select { |url| url.match?(%r{https?://}) }.reject { |url| url.match(/^#{response_url}(?:#.*)?$/) }
|
19
24
|
end
|
20
25
|
|
21
26
|
private
|
@@ -24,23 +29,36 @@ module Webmention
|
|
24
29
|
@doc ||= Nokogiri::HTML(response_body)
|
25
30
|
end
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
# @return [Array] the URLs
|
30
|
-
def parse_response_body
|
31
|
-
CSS_SELECTORS_MAP
|
32
|
-
.each_with_object([]) { |(*args), array| array << search_node(*args) }
|
33
|
-
.flatten
|
34
|
-
.map { |url| Absolutely.to_abs(base: response_url, relative: url) }
|
35
|
-
.uniq
|
32
|
+
def resolved_urls
|
33
|
+
UrlAttributesParser.parse(*url_attributes).map { |url| Absolutely.to_abs(base: response_url, relative: url) }
|
36
34
|
end
|
37
35
|
|
38
36
|
def root_node
|
39
|
-
|
37
|
+
doc.at_css('.h-entry .e-content', '.h-entry') || doc.css('body')
|
40
38
|
end
|
41
39
|
|
42
|
-
def
|
43
|
-
|
40
|
+
def url_attributes
|
41
|
+
url_nodes.flat_map(&:attribute_nodes).select { |attribute| HTML_ATTRIBUTES_MAP.key?(attribute.name) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def url_nodes
|
45
|
+
root_node.css(*CSS_SELECTORS_ARRAY)
|
46
|
+
end
|
47
|
+
|
48
|
+
module UrlAttributesParser
|
49
|
+
# @param attributes [Array<Nokogiri::XML::Attr>]
|
50
|
+
# @return [Array<String>]
|
51
|
+
def self.parse(*attributes)
|
52
|
+
attributes.flat_map { |attribute| value_from(attribute) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param attribute [Nokogiri::XML::Attr]
|
56
|
+
# @return [String, Array<String>]
|
57
|
+
def self.value_from(attribute)
|
58
|
+
return attribute.value unless attribute.name == 'srcset'
|
59
|
+
|
60
|
+
attribute.value.split(',').map { |value| value.strip.match(/^\S+/).to_s }
|
61
|
+
end
|
44
62
|
end
|
45
63
|
end
|
46
64
|
end
|
data/lib/webmention/version.rb
CHANGED
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:
|
4
|
+
version: 3.0.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-05-
|
12
|
+
date: 2020-05-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: absolutely
|
@@ -109,7 +109,6 @@ files:
|
|
109
109
|
- lib/webmention/parsers/base_parser.rb
|
110
110
|
- lib/webmention/parsers/html_parser.rb
|
111
111
|
- lib/webmention/services/http_request_service.rb
|
112
|
-
- lib/webmention/services/node_parser_service.rb
|
113
112
|
- lib/webmention/version.rb
|
114
113
|
- webmention.gemspec
|
115
114
|
homepage: https://github.com/indieweb/webmention-client-ruby
|
@@ -117,7 +116,7 @@ licenses:
|
|
117
116
|
- Apache-2.0
|
118
117
|
metadata:
|
119
118
|
bug_tracker_uri: https://github.com/indieweb/webmention-client-ruby/issues
|
120
|
-
changelog_uri: https://github.com/indieweb/webmention-client-ruby/blob/
|
119
|
+
changelog_uri: https://github.com/indieweb/webmention-client-ruby/blob/v3.0.0/CHANGELOG.md
|
121
120
|
post_install_message:
|
122
121
|
rdoc_options: []
|
123
122
|
require_paths:
|
@@ -1,25 +0,0 @@
|
|
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
|