micromicro 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.simplecov +2 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +5 -5
- data/README.md +44 -9
- data/lib/micro_micro/collectible.rb +13 -0
- data/lib/micro_micro/collections/base_collection.rb +11 -12
- data/lib/micro_micro/collections/items_collection.rb +5 -0
- data/lib/micro_micro/collections/properties_collection.rb +9 -7
- data/lib/micro_micro/collections/{relations_collection.rb → relationships_collection.rb} +14 -5
- data/lib/micro_micro/document.rb +94 -14
- data/lib/micro_micro/item.rb +40 -7
- data/lib/micro_micro/parsers/base_property_parser.rb +17 -14
- data/lib/micro_micro/parsers/date_time_parser.rb +1 -7
- data/lib/micro_micro/parsers/date_time_property_parser.rb +17 -27
- data/lib/micro_micro/parsers/embedded_markup_property_parser.rb +4 -15
- data/lib/micro_micro/parsers/implied_name_property_parser.rb +17 -56
- data/lib/micro_micro/parsers/implied_photo_property_parser.rb +5 -9
- data/lib/micro_micro/parsers/implied_url_property_parser.rb +3 -13
- data/lib/micro_micro/parsers/plain_text_property_parser.rb +9 -18
- data/lib/micro_micro/parsers/url_property_parser.rb +11 -27
- data/lib/micro_micro/parsers/value_class_pattern_parser.rb +1 -12
- data/lib/micro_micro/property.rb +16 -23
- data/lib/micro_micro/{relation.rb → relationship.rb} +6 -5
- data/lib/micro_micro/version.rb +1 -1
- data/lib/micromicro.rb +13 -3
- data/micromicro.gemspec +1 -1
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c5c3cb23e1c8338fef3d7cca36c47e4dcc834f3819525c01bd7ce6dab314971
|
4
|
+
data.tar.gz: 27794eaac80a6701c7910f4e31200a4bc999d0b8082b3ca1d2dd5a87a0bdaa82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d59f245021fb8bec36e1e319cffce3c3a6168ea763952efc8759bda7cb7a7bf13420632cdcfd2b988d72524a348f5a1238ff206cfd3aa75bfb5a57621f4f3b8c
|
7
|
+
data.tar.gz: 9355a25a3b65fe72828abf95d4dcec2829e46772904487b030a906cd95708f4bc946570f507bae326df2a3e8066e3de1c332799977cf8db749269e095bba413b
|
data/.simplecov
CHANGED
@@ -2,9 +2,11 @@ require 'simplecov-console'
|
|
2
2
|
|
3
3
|
formatters = [SimpleCov::Formatter::HTMLFormatter]
|
4
4
|
|
5
|
+
# rubocop:disable Style/IfUnlessModifier
|
5
6
|
if RSpec.configuration.files_to_run.length > 1
|
6
7
|
formatters << SimpleCov::Formatter::Console
|
7
8
|
end
|
9
|
+
# rubocop:enable Style/IfUnlessModifier
|
8
10
|
|
9
11
|
SimpleCov.start do
|
10
12
|
formatter SimpleCov::Formatter::MultiFormatter.new(formatters)
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.0.0 / 2020-11-08
|
4
|
+
|
5
|
+
- Add `MicroMicro::Item#plain_text_properties` and `MicroMicro::Item#url_properties` methods (351e1f1)
|
6
|
+
- Add `MicroMicro::Collections::RelationshipsCollection#rels` and `MicroMicro::Collections::RelationshipsCollection#urls` methods(c0e5665)
|
7
|
+
- Add `MicroMicro::Collections::PropertiesCollection#names` and `MicroMicro::Collections::PropertiesCollection#values` methods (65486bc)
|
8
|
+
- Add `MicroMicro::Collections::ItemsCollection#types` method (6b53a81)
|
9
|
+
- Update absolutely dependency (4e67bb2)
|
10
|
+
- Add `Collectible` concern and refactor using Composite design pattern (82503b8)
|
11
|
+
- Update absolutely dependency (4578fb4)
|
12
|
+
|
3
13
|
## 0.1.0 / 2020-05-06
|
4
14
|
|
5
15
|
- Initial release!
|
data/Gemfile
CHANGED
@@ -6,9 +6,9 @@ gemspec
|
|
6
6
|
gem 'pry-byebug', '~> 3.9'
|
7
7
|
gem 'rake', '~> 13.0'
|
8
8
|
gem 'reek', '~> 6.0'
|
9
|
-
gem 'rspec', '~> 3.
|
10
|
-
gem 'rubocop', '~>
|
11
|
-
gem 'rubocop-performance', '~> 1.
|
12
|
-
gem 'rubocop-rspec', '~>
|
13
|
-
gem 'simplecov', '~> 0.
|
9
|
+
gem 'rspec', '~> 3.10'
|
10
|
+
gem 'rubocop', '~> 1.2'
|
11
|
+
gem 'rubocop-performance', '~> 1.8'
|
12
|
+
gem 'rubocop-rspec', '~> 2.0'
|
13
|
+
gem 'simplecov', '~> 0.19.1'
|
14
14
|
gem 'simplecov-console', '~> 0.7.2'
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ An example using a simple `String` of HTML as input:
|
|
53
53
|
require 'micromicro'
|
54
54
|
|
55
55
|
doc = MicroMicro.parse('<div class="h-card">Jason Garber</div>', 'https://sixtwothree.org')
|
56
|
-
#=> #<MicroMicro::Document items: #<MicroMicro::Collections::ItemsCollection count: 1, members: [#<MicroMicro::Item types: ["h-card"], properties: 1, children: 0>]>,
|
56
|
+
#=> #<MicroMicro::Document items: #<MicroMicro::Collections::ItemsCollection count: 1, members: [#<MicroMicro::Item types: ["h-card"], properties: 1, children: 0>]>, relationships: #<MicroMicro::Collections::RelationshipsCollection count: 0, members: []>>
|
57
57
|
|
58
58
|
doc.to_h
|
59
59
|
#=> { :items => [{ :type => ["h-card"], :properties => { :name => ["Jason Garber"] } }], :rels => {}, :"rel-urls" => {} }
|
@@ -71,7 +71,7 @@ url = "https://tantek.com"
|
|
71
71
|
rsp = Net::HTTP.get(URI.parse(url))
|
72
72
|
|
73
73
|
doc = MicroMicro.parse(rsp, url)
|
74
|
-
#=> #<MicroMicro::Document items: #<MicroMicro::Collections::ItemsCollection count: 1, members: […]>,
|
74
|
+
#=> #<MicroMicro::Document items: #<MicroMicro::Collections::ItemsCollection count: 1, members: […]>, relationships: #<MicroMicro::Collections::RelationshipsCollection count: 31, members: […]>>
|
75
75
|
|
76
76
|
doc.to_h
|
77
77
|
#=> { :items => [{ :type => ["h-card"], :properties => {…}, :children => […]}], :rels => {…}, :'rel-urls' => {…} }
|
@@ -81,30 +81,65 @@ doc.to_h
|
|
81
81
|
|
82
82
|
Building on the example above, a MicroMicro-parsed document is navigable and manipulable using a familiar `Enumerable`-esque interface.
|
83
83
|
|
84
|
+
#### Items
|
85
|
+
|
84
86
|
```ruby
|
85
87
|
doc.items.first
|
86
88
|
#=> #<MicroMicro::Item types: ["h-card"], properties: 42, children: 6>
|
87
89
|
|
90
|
+
# 🆕 in v1.0.0
|
91
|
+
doc.items.types
|
92
|
+
#=> ["h-card"]
|
93
|
+
|
94
|
+
doc.items.first.children
|
95
|
+
#=> #<MicroMicro::Collections::ItemsCollection count: 6, members: […]>
|
96
|
+
```
|
97
|
+
|
98
|
+
#### Properties
|
99
|
+
|
100
|
+
```ruby
|
88
101
|
doc.items.first.properties
|
89
102
|
#=> #<MicroMicro::Collections::PropertiesCollection count: 42, members: […]>
|
90
103
|
|
104
|
+
# 🆕 in v1.0.0
|
105
|
+
doc.items.first.plain_text_properties
|
106
|
+
#=> #<MicroMicro::Collections::PropertiesCollection count: 34, members: […]>
|
107
|
+
|
108
|
+
# 🆕 in v1.0.0
|
109
|
+
doc.items.first.url_properties
|
110
|
+
#=> #<MicroMicro::Collections::PropertiesCollection count: 11, members: […]>
|
111
|
+
|
112
|
+
# 🆕 in v1.0.0
|
113
|
+
doc.items.first.properties.names
|
114
|
+
#=> ["category", "name", "note", "org", "photo", "pronoun", "pronouns", "role", "uid", "url"]
|
115
|
+
|
116
|
+
# 🆕 in v1.0.0
|
117
|
+
doc.items.first.properties.values
|
118
|
+
#=> [{:value=>"https://tantek.com/photo.jpg", :alt=>""}, "https://tantek.com/", "Tantek Çelik", "Inventor, writer, teacher, runner, coder, more.", "Inventor", "writer", "teacher", "runner", "coder", …]
|
119
|
+
|
91
120
|
doc.items.first.properties[7]
|
92
121
|
#=> #<MicroMicro::Property name: "category", prefix: "p", value: "teacher">
|
93
122
|
|
94
123
|
doc.items.first.properties.take(5).map { |property| [property.name, property.value] }
|
95
124
|
#=> [["photo", { :value => "https://tantek.com/photo.jpg", :alt => "" }], ["url", "https://tantek.com/"], ["uid", "https://tantek.com/"], ["name", "Tantek Çelik"], ["role", "Inventor, writer, teacher, runner, coder, more."]]
|
125
|
+
```
|
96
126
|
|
97
|
-
|
98
|
-
#=> #<MicroMicro::Collections::ItemsCollection count: 6, members: […]>
|
127
|
+
#### Relationships
|
99
128
|
|
100
|
-
|
101
|
-
|
129
|
+
```ruby
|
130
|
+
doc.relationships.first
|
131
|
+
#=> #<MicroMicro::Relationship href: "https://tantek.com/", rels: ["canonical"]>
|
102
132
|
|
103
|
-
|
133
|
+
# 🆕 in v1.0.0
|
134
|
+
doc.relationships.rels
|
104
135
|
#=> ["alternate", "apple-touch-icon-precomposed", "author", "authorization_endpoint", "bookmark", "canonical", "hub", "icon", "me", "microsub", …]
|
105
136
|
|
106
|
-
|
107
|
-
|
137
|
+
# 🆕 in v1.0.0
|
138
|
+
doc.relationships.urls
|
139
|
+
#=> ["http://dribbble.com/tantek/", "http://last.fm/user/tantekc", "https://aperture.p3k.io/microsub/277", "https://en.wikipedia.org/wiki/User:Tantek", "https://github.com/tantek", "https://indieauth.com/auth", "https://indieauth.com/openid", "https://micro.blog/t", "https://pubsubhubbub.superfeedr.com/", "https://tantek.com/", …]
|
140
|
+
|
141
|
+
doc.relationships.find { |relationship| relationship.rels.include?('webmention') }
|
142
|
+
# => #<MicroMicro::Relationship href: "https://webmention.io/tantek.com/webmention", rels: ["webmention"]>
|
108
143
|
```
|
109
144
|
|
110
145
|
## Contributing
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module MicroMicro
|
2
2
|
module Collections
|
3
3
|
class BaseCollection
|
4
|
+
extend Forwardable
|
5
|
+
|
4
6
|
include Enumerable
|
5
7
|
|
6
|
-
|
8
|
+
def_delegators :members, :[], :each, :last, :length, :split
|
7
9
|
|
8
|
-
# @param members [Array<MicroMicro::Item, MicroMicro::Property, MicroMicro::
|
10
|
+
# @param members [Array<MicroMicro::Item, MicroMicro::Property, MicroMicro::Relationship>]
|
9
11
|
def initialize(members = [])
|
10
|
-
|
11
|
-
|
12
|
-
decorate_members if respond_to?(:decorate_members, true)
|
12
|
+
members.each { |member| push(member) }
|
13
13
|
end
|
14
14
|
|
15
15
|
# @return [String]
|
@@ -17,21 +17,20 @@ module MicroMicro
|
|
17
17
|
format(%(#<#{self.class.name}:%#0x count: #{count}, members: #{members.inspect}>), object_id)
|
18
18
|
end
|
19
19
|
|
20
|
-
# @param member [MicroMicro::Item, MicroMicro::Property, MicroMicro::
|
21
|
-
# @return [self]
|
20
|
+
# @param member [MicroMicro::Item, MicroMicro::Property, MicroMicro::Relationship]
|
22
21
|
def push(member)
|
23
|
-
members
|
22
|
+
members << member
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
self
|
24
|
+
member.collection = self
|
28
25
|
end
|
29
26
|
|
30
27
|
alias << push
|
31
28
|
|
32
29
|
private
|
33
30
|
|
34
|
-
|
31
|
+
def members
|
32
|
+
@members ||= []
|
33
|
+
end
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
@@ -1,17 +1,19 @@
|
|
1
1
|
module MicroMicro
|
2
2
|
module Collections
|
3
3
|
class PropertiesCollection < BaseCollection
|
4
|
+
# @return [Array<String>]
|
5
|
+
def names
|
6
|
+
@names ||= map(&:name).uniq.sort
|
7
|
+
end
|
8
|
+
|
4
9
|
# @return [Hash{Symbol => Array<String, Hash>}]
|
5
10
|
def to_h
|
6
|
-
group_by(&:name).symbolize_keys.deep_transform_values
|
7
|
-
property.item_node? ? property.value.to_h : property.value
|
8
|
-
end
|
11
|
+
group_by(&:name).symbolize_keys.deep_transform_values(&:value)
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
each { |member| member.collection = self }
|
14
|
+
# @return [Array<String, Hash>]
|
15
|
+
def values
|
16
|
+
@values ||= map(&:value).uniq
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -1,23 +1,32 @@
|
|
1
1
|
module MicroMicro
|
2
2
|
module Collections
|
3
|
-
class
|
4
|
-
# @see microformats2 Parsing Specification section 1.4
|
3
|
+
class RelationshipsCollection < BaseCollection
|
5
4
|
# @see http://microformats.org/wiki/microformats2-parsing#parse_a_hyperlink_element_for_rel_microformats
|
6
5
|
#
|
7
|
-
# @return [Hash{
|
6
|
+
# @return [Hash{Symbol => Hash{Symbol => Array, String}}]
|
8
7
|
def group_by_url
|
9
|
-
group_by(&:href).symbolize_keys.transform_values { |
|
8
|
+
group_by(&:href).symbolize_keys.transform_values { |relationships| relationships.first.to_h.slice!(:href) }
|
10
9
|
end
|
11
10
|
|
12
|
-
# @see microformats2 Parsing Specification section 1.4
|
13
11
|
# @see http://microformats.org/wiki/microformats2-parsing#parse_a_hyperlink_element_for_rel_microformats
|
14
12
|
#
|
15
13
|
# @return [Hash{Symbol => Array<String>}]
|
16
14
|
def group_by_rel
|
15
|
+
# flat_map { |member| member.rels.map { |rel| [rel, member.href] } }.group_by(&:shift).symbolize_keys.transform_values(&:flatten).transform_values(&:uniq)
|
17
16
|
each_with_object(Hash.new { |hash, key| hash[key] = [] }) do |member, hash|
|
18
17
|
member.rels.each { |rel| hash[rel] << member.href }
|
19
18
|
end.symbolize_keys.transform_values(&:uniq)
|
20
19
|
end
|
20
|
+
|
21
|
+
# @return [Array<String>]
|
22
|
+
def rels
|
23
|
+
@rels ||= map(&:rels).flatten.uniq.sort
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Array<String>]
|
27
|
+
def urls
|
28
|
+
@urls ||= map(&:href).uniq.sort
|
29
|
+
end
|
21
30
|
end
|
22
31
|
end
|
23
32
|
end
|
data/lib/micro_micro/document.rb
CHANGED
@@ -1,57 +1,117 @@
|
|
1
1
|
module MicroMicro
|
2
2
|
class Document
|
3
|
-
#
|
4
|
-
#
|
3
|
+
# A map of HTML `srcset` attributes and their associated element names
|
4
|
+
#
|
5
|
+
# @see https://html.spec.whatwg.org/#srcset-attributes
|
6
|
+
# @see https://html.spec.whatwg.org/#attributes-3
|
7
|
+
HTML_IMAGE_CANDIDATE_STRINGS_ATTRIBUTES_MAP = {
|
8
|
+
'imagesrcset' => %w[link],
|
9
|
+
'srcset' => %w[img source]
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
# A map of HTML URL attributes and their associated element names
|
13
|
+
#
|
14
|
+
# @see https://html.spec.whatwg.org/#attributes-3
|
15
|
+
HTML_URL_ATTRIBUTES_MAP = {
|
16
|
+
'action' => %w[form],
|
17
|
+
'cite' => %w[blockquote del ins q],
|
18
|
+
'data' => %w[object],
|
19
|
+
'formaction' => %w[button input],
|
20
|
+
'href' => %w[a area base link],
|
21
|
+
'manifest' => %w[html],
|
22
|
+
'ping' => %w[a area],
|
23
|
+
'poster' => %w[video],
|
24
|
+
'src' => %w[audio embed iframe img input script source track video]
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
# Parse a string of HTML for microformats2-encoded data.
|
28
|
+
#
|
29
|
+
# MicroMicro::Document.new('<a href="/" class="h-card" rel="me">Jason Garber</a>', 'https://sixtwothree.org')
|
30
|
+
#
|
31
|
+
# Or, pull the source HTML of a page on the Web:
|
32
|
+
#
|
33
|
+
# url = 'https://tantek.com'
|
34
|
+
# markup = Net::HTTP.get(URI.parse(url))
|
35
|
+
#
|
36
|
+
# doc = MicroMicro::Document.new(markup, url)
|
37
|
+
#
|
38
|
+
# @param markup [String] The HTML to parse for microformats2-encoded data.
|
39
|
+
# @param base_url [String] The URL associated with markup. Used for relative URL resolution.
|
5
40
|
def initialize(markup, base_url)
|
6
41
|
@markup = markup
|
7
42
|
@base_url = base_url
|
43
|
+
|
44
|
+
resolve_relative_urls
|
8
45
|
end
|
9
46
|
|
10
47
|
# @return [String]
|
11
48
|
def inspect
|
12
|
-
format(%(#<#{self.class.name}:%#0x items: #{items.inspect},
|
49
|
+
format(%(#<#{self.class.name}:%#0x items: #{items.inspect}, relationships: #{relationships.inspect}>), object_id)
|
13
50
|
end
|
14
51
|
|
52
|
+
# A collection of items parsed from the provided markup.
|
53
|
+
#
|
15
54
|
# @return [MicroMicro::Collections::ItemsCollection]
|
16
55
|
def items
|
17
56
|
@items ||= Collections::ItemsCollection.new(Item.items_from(document))
|
18
57
|
end
|
19
58
|
|
20
|
-
#
|
21
|
-
|
22
|
-
|
59
|
+
# A collection of relationships parsed from the provided markup.
|
60
|
+
#
|
61
|
+
# @return [MicroMicro::Collections::RelationshipsCollection]
|
62
|
+
def relationships
|
63
|
+
@relationships ||= Collections::RelationshipsCollection.new(Relationship.relationships_from(document))
|
23
64
|
end
|
24
65
|
|
25
|
-
#
|
66
|
+
# Return the parsed document as a Hash.
|
67
|
+
#
|
26
68
|
# @see http://microformats.org/wiki/microformats2-parsing#parse_a_document_for_microformats
|
27
69
|
#
|
28
|
-
# @return [Hash]
|
70
|
+
# @return [Hash{Symbol => Array, Hash}]
|
29
71
|
def to_h
|
30
72
|
{
|
31
73
|
items: items.to_a,
|
32
|
-
rels:
|
33
|
-
'rel-urls':
|
74
|
+
rels: relationships.group_by_rel,
|
75
|
+
'rel-urls': relationships.group_by_url
|
34
76
|
}
|
35
77
|
end
|
36
78
|
|
79
|
+
# Ignore this node?
|
80
|
+
#
|
37
81
|
# @param node [Nokogiri::XML::Element]
|
38
82
|
# @return [Boolean]
|
39
83
|
def self.ignore_node?(node)
|
40
84
|
ignored_node_names.include?(node.name)
|
41
85
|
end
|
42
86
|
|
87
|
+
# A list of HTML element names the parser should ignore.
|
88
|
+
#
|
43
89
|
# @return [Array<String>]
|
44
90
|
def self.ignored_node_names
|
45
91
|
%w[script style template]
|
46
92
|
end
|
47
93
|
|
94
|
+
# @see http://microformats.org/wiki/microformats2-parsing#parse_an_element_for_properties
|
95
|
+
# @see http://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
|
96
|
+
#
|
97
|
+
# @param context [Nokogiri::HTML::Document, Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
|
98
|
+
# @yield [context]
|
99
|
+
# @return [String]
|
100
|
+
def self.text_content_from(context)
|
101
|
+
context.css(*ignored_node_names).unlink
|
102
|
+
|
103
|
+
yield(context) if block_given?
|
104
|
+
|
105
|
+
context.text.strip
|
106
|
+
end
|
107
|
+
|
48
108
|
private
|
49
109
|
|
50
110
|
attr_reader :base_url, :markup
|
51
111
|
|
52
112
|
# @return [Nokogiri::XML::Element, nil]
|
53
113
|
def base_element
|
54
|
-
@base_element ||= Nokogiri::HTML(markup).
|
114
|
+
@base_element ||= Nokogiri::HTML(markup).at('//base[@href]')
|
55
115
|
end
|
56
116
|
|
57
117
|
# @return [Nokogiri::HTML::Document]
|
@@ -59,12 +119,32 @@ module MicroMicro
|
|
59
119
|
@document ||= Nokogiri::HTML(markup, resolved_base_url)
|
60
120
|
end
|
61
121
|
|
122
|
+
def resolve_relative_urls
|
123
|
+
HTML_URL_ATTRIBUTES_MAP.each do |attribute, names|
|
124
|
+
document.xpath(*names.map { |name| "//#{name}[@#{attribute}]" }).each do |node|
|
125
|
+
node[attribute] = Absolutely.to_abs(base: resolved_base_url, relative: node[attribute].strip)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
HTML_IMAGE_CANDIDATE_STRINGS_ATTRIBUTES_MAP.each do |attribute, names|
|
130
|
+
document.xpath(*names.map { |name| "//#{name}[@#{attribute}]" }).each do |node|
|
131
|
+
candidates = node[attribute].split(',').map(&:strip).map { |candidate| candidate.match(/^(?<url>.+?)(?<descriptor>\s+.+)?$/) }
|
132
|
+
|
133
|
+
node[attribute] = candidates.map { |candidate| "#{Absolutely.to_abs(base: resolved_base_url, relative: candidate[:url])}#{candidate[:descriptor]}" }.join(', ')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
self
|
138
|
+
end
|
139
|
+
|
62
140
|
# @return [String]
|
63
141
|
def resolved_base_url
|
64
142
|
@resolved_base_url ||= begin
|
65
|
-
|
66
|
-
|
67
|
-
|
143
|
+
if base_element
|
144
|
+
Absolutely.to_abs(base: base_url, relative: base_element['href'].strip)
|
145
|
+
else
|
146
|
+
base_url
|
147
|
+
end
|
68
148
|
end
|
69
149
|
end
|
70
150
|
end
|