micromicro 2.0.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9c965d277e7c87c68de6ce7a12aff28da257d813573de2519bfe36943df1f4f
4
- data.tar.gz: a62d02a8fe962b060c36a9c615445f586fe76ea1c570d71f05175d140d631d32
3
+ metadata.gz: 6734c4d9cbd071d3288a5f8c72de07095fc6db2915224f97684a0577362bcdb0
4
+ data.tar.gz: 9225043ef91161f2a92fa338bc874771dc55d9e81ffe969fe7b005c9dbc28403
5
5
  SHA512:
6
- metadata.gz: 8ee19e4ca072c36137746dd54e435405a9a749761c9b735d75ff9f97a5c28f8e5367f79c3a7ad45c83039eb8cb54f1043cac2dd7ddcd1bfd2d4fbbad0d218ad6
7
- data.tar.gz: f5f88370b3fc92e2d467c8e358798c6266b5fb9dbfe50fb13e74b2235572e9adfbfeb4f171b1df3d5bf474cc549bac7adfe3fa7c2a59b6830d2bacc3cab3d500
6
+ metadata.gz: 58824c1699a2aff5e22d906cbb449f95f55a665d7374ba62e26ddfa3fd6986ae952e22965446e4bbe973d2e17a1f05cba32e74f7d30e1e327fbc262ebce7b1f1
7
+ data.tar.gz: aa9db8c15e10ecc08fa65db0cf6964914681ef72b552a300c4b95899b4a837835c1c69baff9b8e48586df34eefb7bb4156e55a5c81582deda4a9948554224f48
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## v3.0.0 / 2022-08-28
4
+
5
+ - Improved YARD documentation
6
+ - New `Item` instance methods (8105d6f):
7
+ - `MicroMicro::Item#children?`
8
+ - `MicroMicro::Item#id?`
9
+ - **Breaking change:** Remove property-centric methods from `MicroMicro::Item` (926dedb):
10
+ - `MicroMicro::Item#plain_text_properties`
11
+ - `MicroMicro::Item#url_properties`
12
+ - Add predicate methods to `MicroMicro::Collections::PropertiesCollection` (82e91c8):
13
+ - `MicroMicro::Collections::PropertiesCollection#plain_text_properties?`
14
+ - `MicroMicro::Collections::PropertiesCollection#url_properties?`
15
+ - Add collections search methods `#where` and `#find_by` (847cb77)
16
+ - **Breaking change:** Refactor `.node_set_from` class methods into private classes (b18a714)
17
+
3
18
  ## 2.0.1 / 2022-08-20
4
19
 
5
20
  - Use ruby/debug instead of pry-byebug (2965b2e)
data/README.md CHANGED
@@ -18,15 +18,9 @@
18
18
 
19
19
  <small>¹ …with some exceptions until [this pull request](https://github.com/microformats/tests/pull/112) is merged.</small>
20
20
 
21
- ## Getting Started
22
-
23
- Before installing and using MicroMicro, you'll want to have [Ruby](https://www.ruby-lang.org) 2.7 (or newer) installed. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm).
24
-
25
- MicroMicro is developed using Ruby 2.7.6 and is additionally tested against Ruby 3.0 and 3.1 using [GitHub Actions](https://github.com/jgarber623/micromicro/actions).
26
-
27
21
  ## Installation
28
22
 
29
- If you're using [Bundler](https://bundler.io) to manage gem dependencies, add MicroMicro to your project's Gemfile:
23
+ Before installing and using MicroMicro, you'll want to have [Ruby](https://www.ruby-lang.org) 2.7 (or newer) installed. If you're using [Bundler](https://bundler.io) to manage gem dependencies, add MicroMicro to your project's Gemfile:
30
24
 
31
25
  ```ruby
32
26
  gem 'micromicro'
@@ -42,13 +36,7 @@ gem install micromicro
42
36
 
43
37
  ## Usage
44
38
 
45
- ### Basic Usage
46
-
47
- MicroMicro's `parse` method accepts two arguments: a `String` of markup and a `String` representing the URL associated with that markup.
48
-
49
- The markup (typically HTML) can be retrieved from the Web using a library of your choosing or provided inline as a simple `String` (e.g. `<div class="h-card">Jason Garber</div>`) The URL provided is used to resolve relative URLs in accordance with the document's language rules.
50
-
51
- An example using a simple `String` of HTML as input:
39
+ MicroMicro's `parse` method accepts two arguments: a `String` of markup and a `String` representing the URL associated with that markup. The resulting `MicroMicro::Document` may be converted to a `Hash` which may be further manipulated using conventional Ruby tooling.
52
40
 
53
41
  ```ruby
54
42
  require 'micromicro'
@@ -60,88 +48,7 @@ doc.to_h
60
48
  #=> { :items => [{ :type => ["h-card"], :properties => { :name => ["Jason Garber"] } }], :rels => {}, :"rel-urls" => {} }
61
49
  ```
62
50
 
63
- The `Hash` produced by calling `doc.to_h` may be converted to JSON (e.g. `doc.to_h.to_json`) for storage, additional manipulation, or use with other tools.
64
-
65
- Another example pulling the source HTML from [Tantek](https://tantek.com)'s website:
66
-
67
- ```ruby
68
- require 'net/http'
69
- require 'micromicro'
70
-
71
- url = 'https://tantek.com'
72
- rsp = Net::HTTP.get(URI.parse(url))
73
-
74
- doc = MicroMicro.parse(rsp, url)
75
- #=> #<MicroMicro::Document items: #<MicroMicro::Collections::ItemsCollection count: 1, members: […]>, relationships: #<MicroMicro::Collections::RelationshipsCollection count: 31, members: […]>>
76
-
77
- doc.to_h
78
- #=> { :items => [{ :type => ["h-card"], :properties => {…}, :children => […]}], :rels => {…}, :'rel-urls' => {…} }
79
- ```
80
-
81
- ### Advanced Usage
82
-
83
- Building on the example above, a MicroMicro-parsed document is navigable and manipulable using a familiar `Enumerable`-esque interface.
84
-
85
- #### Items
86
-
87
- ```ruby
88
- doc.items.first
89
- #=> #<MicroMicro::Item types: ["h-card"], properties: 42, children: 6>
90
-
91
- # 🆕 in v1.0.0
92
- doc.items.types
93
- #=> ["h-card"]
94
-
95
- doc.items.first.children
96
- #=> #<MicroMicro::Collections::ItemsCollection count: 6, members: […]>
97
- ```
98
-
99
- #### Properties
100
-
101
- ```ruby
102
- doc.items.first.properties
103
- #=> #<MicroMicro::Collections::PropertiesCollection count: 42, members: […]>
104
-
105
- # 🆕 in v1.0.0
106
- doc.items.first.plain_text_properties
107
- #=> #<MicroMicro::Collections::PropertiesCollection count: 34, members: […]>
108
-
109
- # 🆕 in v1.0.0
110
- doc.items.first.url_properties
111
- #=> #<MicroMicro::Collections::PropertiesCollection count: 11, members: […]>
112
-
113
- # 🆕 in v1.0.0
114
- doc.items.first.properties.names
115
- #=> ["category", "name", "note", "org", "photo", "pronoun", "pronouns", "role", "uid", "url"]
116
-
117
- # 🆕 in v1.0.0
118
- doc.items.first.properties.values
119
- #=> [{:value=>"https://tantek.com/photo.jpg", :alt=>""}, "https://tantek.com/", "Tantek Çelik", "Inventor, writer, teacher, runner, coder, more.", "Inventor", "writer", "teacher", "runner", "coder", …]
120
-
121
- doc.items.first.properties[7]
122
- #=> #<MicroMicro::Property name: "category", prefix: "p", value: "teacher">
123
-
124
- doc.items.first.properties.take(5).map { |property| [property.name, property.value] }
125
- #=> [["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."]]
126
- ```
127
-
128
- #### Relationships
129
-
130
- ```ruby
131
- doc.relationships.first
132
- #=> #<MicroMicro::Relationship href: "https://tantek.com/", rels: ["canonical"]>
133
-
134
- # 🆕 in v1.0.0
135
- doc.relationships.rels
136
- #=> ["alternate", "apple-touch-icon-precomposed", "author", "authorization_endpoint", "bookmark", "canonical", "hub", "icon", "me", "microsub", …]
137
-
138
- # 🆕 in v1.0.0
139
- doc.relationships.urls
140
- #=> ["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/", …]
141
-
142
- doc.relationships.find { |relationship| relationship.rels.include?('webmention') }
143
- # => #<MicroMicro::Relationship href: "https://webmention.io/tantek.com/webmention", rels: ["webmention"]>
144
- ```
51
+ See [USAGE.md](https://github.com/jgarber623/micromicro/blob/main/USAGE.md) for detailed examples of MicroMicro's features.
145
52
 
146
53
  ## Contributing
147
54
 
@@ -14,8 +14,9 @@ module MicroMicro
14
14
  members.each { |member| push(member) }
15
15
  end
16
16
 
17
- # :nocov:
18
17
  # @return [String]
18
+ #
19
+ # :nocov:
19
20
  def inspect
20
21
  "#<#{self.class}:#{format('%#0x', object_id)} " \
21
22
  "count: #{count}, " \
@@ -3,15 +3,96 @@
3
3
  module MicroMicro
4
4
  module Collections
5
5
  class ItemsCollection < BaseCollection
6
+ class ItemsCollectionSearch
7
+ attr_reader :results
8
+
9
+ def initialize
10
+ @results = []
11
+ end
12
+
13
+ def search(items, **args, &block)
14
+ items.each do |item|
15
+ results << item if item_matches_conditions?(item, **args, &block)
16
+
17
+ search(item.properties.filter_map { |property| property.item if property.item_node? }, **args, &block)
18
+ search(item.children, **args, &block)
19
+ end
20
+
21
+ results
22
+ end
23
+
24
+ private
25
+
26
+ def item_matches_conditions?(item, **args)
27
+ return yield(item) if args.none?
28
+
29
+ args.all? { |key, value| (Array(item.public_send(key.to_sym)) & Array(value)).any? }
30
+ end
31
+ end
32
+
33
+ private_constant :ItemsCollectionSearch
34
+
35
+ # Return the first {MicroMicro::Item} from a search.
36
+ #
37
+ # @see #where
38
+ #
39
+ # @param (see #where)
40
+ # @yieldparam (see #where))
41
+ # @return [MicroMicro::Item, nil]
42
+ def find_by(**args, &block)
43
+ where(**args, &block).first
44
+ end
45
+
46
+ # Return an Array of this collection's {MicroMicro::Item}s as Hashes.
47
+ #
48
+ # @see MicroMicro::Item#to_h
49
+ #
6
50
  # @return [Array<Hash{Symbol => Array<String, Hash>}>]
7
51
  def to_a
8
52
  map(&:to_h)
9
53
  end
10
54
 
55
+ # Retrieve an Array of this collection's unique {MicroMicro::Item} types.
56
+ #
57
+ # @see MicroMicro::Item#types
58
+ #
11
59
  # @return [Array<String>]
12
60
  def types
13
61
  @types ||= flat_map(&:types).uniq.sort
14
62
  end
63
+
64
+ # Recursively search this collection for {MicroMicro::Item}s matching the
65
+ # given conditions.
66
+ #
67
+ # If a Hash is supplied, the returned collection will include
68
+ # {MicroMicro::Item}s matching _all_ conditions. Keys must be Symbols
69
+ # matching an instance method on {MicroMicro::Item} and values may be
70
+ # either a String or an Array of Strings.
71
+ #
72
+ # @example Search using a Hash with a String value
73
+ # MicroMicro.parse(markup, url).items.where(types: 'h-card')
74
+ #
75
+ # @example Search using a Hash with an Array value
76
+ # MicroMicro.parse(markup, url).items.where(types: ['h-card', 'h-entry'])
77
+ #
78
+ # When passing a block, each {MicroMicro::Item} in this collection is
79
+ # yielded to the block and the returned collection will include
80
+ # {MicroMicro::Item}s that cause the block to return a value other than
81
+ # +false+ or +nil+.
82
+ #
83
+ # @example Search using a block
84
+ # MicroMicro.parse(markup, url).items.where do |item|
85
+ # item.properties.names.include?('email')
86
+ # end
87
+ #
88
+ # @param args [Hash{Symbol => String, Array<String>}]
89
+ # @yieldparam item [MicroMicro::Item]
90
+ # @return [MicroMicro::Collections::ItemsCollection]
91
+ def where(**args, &block)
92
+ return self if args.none? && !block
93
+
94
+ self.class.new(ItemsCollectionSearch.new.search(self, **args, &block))
95
+ end
15
96
  end
16
97
  end
17
98
  end
@@ -3,30 +3,129 @@
3
3
  module MicroMicro
4
4
  module Collections
5
5
  class PropertiesCollection < BaseCollection
6
+ class PropertiesCollectionSearch
7
+ def search(properties, **args, &block)
8
+ properties.select { |property| property_matches_conditions?(property, **args, &block) }
9
+ end
10
+
11
+ private
12
+
13
+ def property_matches_conditions?(property, **args)
14
+ return yield(property) if args.none?
15
+
16
+ args.all? { |key, value| (Array(property.public_send(key.to_sym)) & Array(value)).any? }
17
+ end
18
+ end
19
+
20
+ private_constant :PropertiesCollectionSearch
21
+
22
+ # Return the first {MicroMicro::Property} from a search.
23
+ #
24
+ # @see #where
25
+ #
26
+ # @param (see #where)
27
+ # @yieldparam (see #where))
28
+ # @return [MicroMicro::Property, nil]
29
+ def find_by(**args, &block)
30
+ where(**args, &block).first
31
+ end
32
+
33
+ # Retrieve an Array of this collection's unique {MicroMicro::Property}
34
+ # names.
35
+ #
36
+ # @see MicroMicro::Property#name
37
+ #
6
38
  # @return [Array<String>]
7
39
  def names
8
40
  @names ||= map(&:name).uniq.sort
9
41
  end
10
42
 
43
+ # A collection of plain text {MicroMicro::Property}s parsed from the node.
44
+ #
45
+ # @see MicroMicro::Property#plain_text_property?
46
+ #
11
47
  # @return [MicroMicro::Collections::PropertiesCollection]
12
48
  def plain_text_properties
13
- self.class.new(select(&:plain_text_property?))
49
+ @plain_text_properties ||= self.class.new(select(&:plain_text_property?))
14
50
  end
15
51
 
52
+ # Does this {MicroMicro::Collections::PropertiesCollection} include any
53
+ # plain text {MicroMicro::Property}s?
54
+ #
55
+ # @return [Boolean]
56
+ def plain_text_properties?
57
+ plain_text_properties.any?
58
+ end
59
+
60
+ # Return a Hash of this collection's {MicroMicro::Property}s as Arrays.
61
+ #
62
+ # @see MicroMicro::Property#name
63
+ # @see MicroMicro::Property#value
64
+ #
16
65
  # @return [Hash{Symbol => Array<String, Hash>}]
17
66
  def to_h
18
67
  group_by(&:name).symbolize_keys.deep_transform_values(&:value)
19
68
  end
20
69
 
70
+ # A collection of url {MicroMicro::Property}s parsed from the node.
71
+ #
72
+ # @see MicroMicro::Property#url_property?
73
+ #
21
74
  # @return [MicroMicro::Collections::PropertiesCollection]
22
75
  def url_properties
23
- self.class.new(select(&:url_property?))
76
+ @url_properties ||= self.class.new(select(&:url_property?))
77
+ end
78
+
79
+ # Does this {MicroMicro::Collections::PropertiesCollection} include any
80
+ # url {MicroMicro::Property}s?
81
+ #
82
+ # @return [Boolean]
83
+ def url_properties?
84
+ url_properties.any?
24
85
  end
25
86
 
87
+ # Return an Array of this collection's unique {MicroMicro::Property}
88
+ # values.
89
+ #
90
+ # @see MicroMicro::Property#value
91
+ #
26
92
  # @return [Array<String, Hash>]
27
93
  def values
28
94
  @values ||= map(&:value).uniq
29
95
  end
96
+
97
+ # Search this collection for {MicroMicro::Property}s matching the given
98
+ # conditions.
99
+ #
100
+ # If a Hash is supplied, the returned collection will include
101
+ # {MicroMicro::Property}s matching _all_ conditions. Keys must be Symbols
102
+ # matching an instance method on {MicroMicro::Property} and values may be
103
+ # either a String or an Array of Strings.
104
+ #
105
+ # @example Search using a Hash with a String value
106
+ # MicroMicro.parse(markup, url).properties.where(name: 'url')
107
+ #
108
+ # @example Search using a Hash with an Array value
109
+ # MicroMicro.parse(markup, url).properties.where(name: ['name', 'url'])
110
+ #
111
+ # When passing a block, each {MicroMicro::Property} in this collection
112
+ # is yielded to the block and the returned collection will include
113
+ # {MicroMicro::Property}s that cause the block to return a value other
114
+ # than +false+ or +nil+.
115
+ #
116
+ # @example Search using a block
117
+ # MicroMicro.parse(markup, url).properties.where do |property|
118
+ # property.value.is_a?(Hash)
119
+ # end
120
+ #
121
+ # @param args [Hash{Symbol => String, Array<String>}]
122
+ # @yieldparam property [MicroMicro::Property]
123
+ # @return [MicroMicro::Collections::PropertiesCollection]
124
+ def where(**args, &block)
125
+ return self if args.none? && !block
126
+
127
+ self.class.new(PropertiesCollectionSearch.new.search(self, **args, &block))
128
+ end
30
129
  end
31
130
  end
32
131
  end
@@ -3,7 +3,38 @@
3
3
  module MicroMicro
4
4
  module Collections
5
5
  class RelationshipsCollection < BaseCollection
6
+ class RelationshipsCollectionSearch
7
+ def search(relationships, **args, &block)
8
+ relationships.select { |relationship| relationship_matches_conditions?(relationship, **args, &block) }
9
+ end
10
+
11
+ private
12
+
13
+ def relationship_matches_conditions?(relationship, **args)
14
+ return yield(relationship) if args.none?
15
+
16
+ args.all? { |key, value| (Array(relationship.public_send(key.to_sym)) & Array(value)).any? }
17
+ end
18
+ end
19
+
20
+ private_constant :RelationshipsCollectionSearch
21
+
22
+ # Return the first {MicroMicro::Relationship} from a search.
23
+ #
24
+ # @see #where
25
+ #
26
+ # @param (see #where)
27
+ # @yieldparam (see #where))
28
+ # @return [MicroMicro::Relationship, nil]
29
+ def find_by(**args, &block)
30
+ where(**args, &block).first
31
+ end
32
+
33
+ # Return a Hash of this collection's {MicroMicro::Relationship}s grouped
34
+ # by their +rel+ attribute value.
35
+ #
6
36
  # @see https://microformats.org/wiki/microformats2-parsing#parse_a_hyperlink_element_for_rel_microformats
37
+ # microformats.org: microformats2 parsing specification § Parse a hyperlink element for rel microformats
7
38
  #
8
39
  # @return [Hash{Symbol => Array<String>}]
9
40
  def group_by_rel
@@ -12,22 +43,69 @@ module MicroMicro
12
43
  end.symbolize_keys.transform_values(&:uniq)
13
44
  end
14
45
 
46
+ # Return a Hash of this collection's {MicroMicro::Relationship}s grouped
47
+ # by their +href+ attribute value.
48
+ #
15
49
  # @see https://microformats.org/wiki/microformats2-parsing#parse_a_hyperlink_element_for_rel_microformats
50
+ # microformats.org: microformats2 parsing specification § Parse a hyperlink element for rel microformats
16
51
  #
17
52
  # @return [Hash{Symbol => Hash{Symbol => Array, String}}]
18
53
  def group_by_url
19
54
  group_by(&:href).symbolize_keys.transform_values { |relationships| relationships.first.to_h.slice!(:href) }
20
55
  end
21
56
 
57
+ # Retrieve an Array of this collection's unique {MicroMicro::Relationship}
58
+ # +rel+ attrivute values.
59
+ #
60
+ # @see MicroMicro::Relationship#rels
61
+ #
22
62
  # @return [Array<String>]
23
63
  def rels
24
64
  @rels ||= flat_map(&:rels).uniq.sort
25
65
  end
26
66
 
67
+ # Retrieve an Array of this collection's unique {MicroMicro::Relationship}
68
+ # +href+ attribute values.
69
+ #
70
+ # @see MicroMicro::Relationship#urls
71
+ #
27
72
  # @return [Array<String>]
28
73
  def urls
29
74
  @urls ||= map(&:href).uniq.sort
30
75
  end
76
+
77
+ # Search this collection for {MicroMicro::Relationship}s matching the
78
+ # given conditions.
79
+ #
80
+ # If a Hash is supplied, the returned collection will include
81
+ # {MicroMicro::Relationship}s matching _all_ conditions. Keys must be
82
+ # Symbols matching an instance method on {MicroMicro::Relationship} and
83
+ # values may be either a String or an Array of Strings.
84
+ #
85
+ # @example Search using a Hash with a String value
86
+ # MicroMicro.parse(markup, url).relationships.where(rels: 'webmention')
87
+ #
88
+ # @example Search using a Hash with an Array value
89
+ # MicroMicro.parse(markup, url).relationships.where(rels: ['me', 'webmention'])
90
+ #
91
+ # When passing a block, each {MicroMicro::Relationship} in this collection
92
+ # is yielded to the block and the returned collection will include
93
+ # {MicroMicro::Relationship}s that cause the block to return a value other
94
+ # than +false+ or +nil+.
95
+ #
96
+ # @example Search using a block
97
+ # MicroMicro.parse(markup, url).relationships.where do |relationship|
98
+ # relationship.href.match?(%r{https://webmention.io/.+})
99
+ # end
100
+ #
101
+ # @param args [Hash{Symbol => String, Array<String>}]
102
+ # @yieldparam relationship [MicroMicro::Relationship]
103
+ # @return [MicroMicro::Collections::RelationshipsCollection]
104
+ def where(**args, &block)
105
+ return self if args.none? && !block
106
+
107
+ self.class.new(RelationshipsCollectionSearch.new.search(self, **args, &block))
108
+ end
31
109
  end
32
110
  end
33
111
  end
@@ -4,10 +4,10 @@ module MicroMicro
4
4
  class Document
5
5
  # Parse a string of HTML for microformats2-encoded data.
6
6
  #
7
+ # @example Parse a String of markup
7
8
  # MicroMicro::Document.new('<a href="/" class="h-card" rel="me">Jason Garber</a>', 'https://sixtwothree.org')
8
9
  #
9
- # Or, pull the source HTML of a page on the Web:
10
- #
10
+ # @example Parse a String of markup from a URL
11
11
  # url = 'https://tantek.com'
12
12
  # markup = Net::HTTP.get(URI.parse(url))
13
13
  #
@@ -19,8 +19,9 @@ module MicroMicro
19
19
  @document = Nokogiri::HTML(markup, base_url).resolve_relative_urls!
20
20
  end
21
21
 
22
- # :nocov:
23
22
  # @return [String]
23
+ #
24
+ # :nocov:
24
25
  def inspect
25
26
  "#<#{self.class}:#{format('%#0x', object_id)} " \
26
27
  "items: #{items.inspect}, " \
@@ -28,23 +29,28 @@ module MicroMicro
28
29
  end
29
30
  # :nocov:
30
31
 
31
- # A collection of items parsed from the provided markup.
32
+ # A collection of {MicroMicro::Item}s parsed from the provided markup.
32
33
  #
33
34
  # @return [MicroMicro::Collections::ItemsCollection]
34
35
  def items
35
36
  @items ||= Collections::ItemsCollection.new(Item.from_context(document.element_children))
36
37
  end
37
38
 
38
- # A collection of relationships parsed from the provided markup.
39
+ # A collection of {MicroMicro::Relationship}s parsed from the provided markup.
39
40
  #
40
41
  # @return [MicroMicro::Collections::RelationshipsCollection]
41
42
  def relationships
42
- @relationships ||= Collections::RelationshipsCollection.new(Relationship.relationships_from(document))
43
+ @relationships ||= Collections::RelationshipsCollection.new(Relationship.from_context(document))
43
44
  end
44
45
 
45
46
  # Return the parsed document as a Hash.
46
47
  #
47
48
  # @see https://microformats.org/wiki/microformats2-parsing#parse_a_document_for_microformats
49
+ # microformats.org: Parse a document for microformats
50
+ #
51
+ # @see MicroMicro::Collections::ItemsCollection#to_a
52
+ # @see MicroMicro::Collections::RelationshipsCollection#group_by_rel
53
+ # @see MicroMicro::Collections::RelationshipsCollection#group_by_url
48
54
  #
49
55
  # @return [Hash{Symbol => Array, Hash}]
50
56
  def to_h
@@ -4,6 +4,8 @@ module MicroMicro
4
4
  module Helpers
5
5
  IGNORED_NODE_NAMES = %w[script style template].freeze
6
6
 
7
+ private_constant :IGNORED_NODE_NAMES
8
+
7
9
  # @param node [Nokogiri::XML::Element]
8
10
  # @param attributes_map [Hash{String => Array}]
9
11
  # @return [String, nil]
@@ -56,7 +58,9 @@ module MicroMicro
56
58
  end
57
59
 
58
60
  # @see https://microformats.org/wiki/microformats2-parsing#parse_an_element_for_properties
61
+ # microformats.org: microformats2 parsing specification § Parse an element for properties
59
62
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
63
+ # microformats.org: microformats2 parsing specification § Parsing for implied properties
60
64
  #
61
65
  # @param context [Nokogiri::HTML::Document, Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
62
66
  # @yield [context]
@@ -70,6 +74,7 @@ module MicroMicro
70
74
  end
71
75
 
72
76
  # @see https://microformats.org/wiki/value-class-pattern#Basic_Parsing
77
+ # microformats.org: Value Class Pattern § Basic Parsing
73
78
  #
74
79
  # @param node [Nokogiri::XML::Element]
75
80
  # @return [Boolean]
@@ -78,6 +83,7 @@ module MicroMicro
78
83
  end
79
84
 
80
85
  # @see https://microformats.org/wiki/value-class-pattern#Parsing_value_from_a_title_attribute
86
+ # microformats.org: Value Class Pattern § Parsing value from a title attribute
81
87
  #
82
88
  # @param node [Nokogiri::XML::Element]
83
89
  # @return [Boolean]
@@ -8,11 +8,24 @@ module MicroMicro
8
8
  'url' => Parsers::ImpliedUrlPropertyParser
9
9
  }.freeze
10
10
 
11
+ private_constant :IMPLIED_PROPERTY_PARSERS_MAP
12
+
13
+ # Always return +true+ when asked if this {MicroMicro::ImpliedProperty} is
14
+ # an implied property.
15
+ #
16
+ # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
17
+ # microformats.org: microformats2 parsing specification § Parsing for implied properties
18
+ #
19
+ # @see MicroMicro::Property#implied?
20
+ #
11
21
  # @return [Boolean]
12
22
  def implied?
13
23
  true
14
24
  end
15
25
 
26
+ # Always return +false+ when asked if this {MicroMicro::ImpliedProperty} is
27
+ # a {MicroMicro::Item} node.
28
+ #
16
29
  # @return [Boolean]
17
30
  def item_node?
18
31
  false
@@ -4,38 +4,47 @@ module MicroMicro
4
4
  class Item
5
5
  include Collectible
6
6
 
7
- # Extract items from a context.
8
- #
9
- # @param context [Nokogiri::HTML::Document, Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
10
- # @return [Array<MicroMicro::Item>]
11
- def self.from_context(context)
12
- node_set_from(context).map { |node| new(node) }
13
- end
7
+ class ItemNodeSearch
8
+ attr_reader :node_set
14
9
 
15
- # Extract item nodes from a context.
16
- #
17
- # @param context [Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
18
- # @param node_set [Nokogiri::XML::NodeSet]
19
- # @return [Nokogiri::XML::NodeSet]
20
- # rubocop:disable Metrics
21
- def self.node_set_from(context, node_set = Nokogiri::XML::NodeSet.new(context.document, []))
22
- context.each { |node| node_set_from(node, node_set) } if context.is_a?(Nokogiri::XML::NodeSet)
23
-
24
- if context.is_a?(Nokogiri::XML::Element) && !Helpers.ignore_node?(context)
25
- if Helpers.item_node?(context)
26
- node_set << context unless Helpers.item_nodes?(context.ancestors) && Helpers.property_node?(context)
27
- else
28
- node_set_from(context.element_children, node_set)
10
+ def initialize(document)
11
+ @node_set = Nokogiri::XML::NodeSet.new(document, [])
12
+ end
13
+
14
+ # rubocop:disable Metrics
15
+ def search(context)
16
+ context.each { |node| search(node) } if context.is_a?(Nokogiri::XML::NodeSet)
17
+
18
+ if context.is_a?(Nokogiri::XML::Element) && !Helpers.ignore_node?(context)
19
+ if Helpers.item_node?(context)
20
+ node_set << context unless Helpers.item_nodes?(context.ancestors) && Helpers.property_node?(context)
21
+ else
22
+ search(context.element_children)
23
+ end
29
24
  end
25
+
26
+ node_set
30
27
  end
28
+ # rubocop:enable Metrics
29
+ end
30
+
31
+ private_constant :ItemNodeSearch
31
32
 
32
- node_set
33
+ # Extract {MicroMicro::Item}s from a context.
34
+ #
35
+ # @param context [Nokogiri::HTML::Document, Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
36
+ # @return [Array<MicroMicro::Item>]
37
+ def self.from_context(context)
38
+ ItemNodeSearch
39
+ .new(context.document)
40
+ .search(context)
41
+ .map { |node| new(node) }
33
42
  end
34
- # rubocop:enable Metrics
35
43
 
36
44
  # Parse a node for microformats2-encoded data.
37
45
  #
38
46
  # @param node [Nokogiri::XML::Element]
47
+ # @return [MicroMicro::Item]
39
48
  def initialize(node)
40
49
  @node = node
41
50
 
@@ -44,24 +53,40 @@ module MicroMicro
44
53
  properties << implied_url if implied_url?
45
54
  end
46
55
 
47
- # A collection of child items parsed from the node.
56
+ # A collection of child {MicroMicro::Item}s parsed from the node.
48
57
  #
49
58
  # @see https://microformats.org/wiki/microformats2-parsing#parse_an_element_for_class_microformats
59
+ # microformats.org: microformats2 parsing specification § Parse an element for class microformats
50
60
  #
51
61
  # @return [MicroMicro::Collections::ItemsCollection]
52
62
  def children
53
63
  @children ||= Collections::ItemsCollection.new(self.class.from_context(node.element_children))
54
64
  end
55
65
 
56
- # The value of the node's `id` attribute, if present.
66
+ # Does this {MicroMicro::Item} contain any child {MicroMicro::Item}s?
67
+ #
68
+ # @return [Boolean]
69
+ def children?
70
+ children.any?
71
+ end
72
+
73
+ # The value of the node's +id+ attribute, if present.
57
74
  #
58
75
  # @return [String, nil]
59
76
  def id
60
77
  @id ||= node['id']&.strip
61
78
  end
62
79
 
63
- # :nocov:
80
+ # Does this {MicroMicro::Item} have an +id+ attribute value?
81
+ #
82
+ # @return [Boolean]
83
+ def id?
84
+ id.present?
85
+ end
86
+
64
87
  # @return [String]
88
+ #
89
+ # :nocov:
65
90
  def inspect
66
91
  "#<#{self.class}:#{format('%#0x', object_id)} " \
67
92
  "types: #{types.inspect}, " \
@@ -70,23 +95,23 @@ module MicroMicro
70
95
  end
71
96
  # :nocov:
72
97
 
73
- # A collection of plain text properties parsed from the node.
74
- #
75
- # @return [MicroMicro::Collections::PropertiesCollection]
76
- def plain_text_properties
77
- @plain_text_properties ||= properties.plain_text_properties
78
- end
79
-
80
- # A collection of properties parsed from the node.
98
+ # A collection of {MicroMicro::Property}s parsed from the node.
81
99
  #
82
100
  # @return [MicroMicro::Collections::PropertiesCollection]
83
101
  def properties
84
102
  @properties ||= Collections::PropertiesCollection.new(Property.from_context(node.element_children))
85
103
  end
86
104
 
87
- # Return the parsed item as a Hash.
105
+ # Return the parsed {MicroMicro::Item} as a Hash.
88
106
  #
89
107
  # @see https://microformats.org/wiki/microformats2-parsing#parse_an_element_for_class_microformats
108
+ # microformats.org: microformats2 parsing specification § Parse an element for class microformats
109
+ #
110
+ # @see MicroMicro::Item#children
111
+ # @see MicroMicro::Item#id
112
+ # @see MicroMicro::Item#properties
113
+ # @see MicroMicro::Item#types
114
+ # @see MicroMicro::Collections::PropertiesCollection#to_h
90
115
  #
91
116
  # @return [Hash]
92
117
  def to_h
@@ -95,28 +120,22 @@ module MicroMicro
95
120
  properties: properties.to_h
96
121
  }
97
122
 
98
- hash[:id] = id if id.present?
99
- hash[:children] = children.to_a if children.any?
123
+ hash[:id] = id if id?
124
+ hash[:children] = children.to_a if children?
100
125
 
101
126
  hash
102
127
  end
103
128
 
104
- # An array of root class names parsed from the node's `class` attribute.
129
+ # An Array of root class names parsed from the node's +class+ attribute.
105
130
  #
106
131
  # @return [Array<String>]
107
132
  def types
108
133
  @types ||= Helpers.root_class_names_from(node)
109
134
  end
110
135
 
111
- # A collection of url properties parsed from the node.
112
- #
113
- # @return [MicroMicro::Collections::PropertiesCollection]
114
- def url_properties
115
- @url_properties ||= properties.url_properties
116
- end
117
-
118
136
  private
119
137
 
138
+ # @return [Nokogiri::XML::Element]
120
139
  attr_reader :node
121
140
 
122
141
  # @return [MicroMicro::ImpliedProperty]
@@ -173,7 +192,7 @@ module MicroMicro
173
192
 
174
193
  # @return [Boolean]
175
194
  def nested_items?
176
- @nested_items ||= properties.find(&:item_node?) || children.any?
195
+ @nested_items ||= properties.find(&:item_node?) || children?
177
196
  end
178
197
  end
179
198
  end
@@ -10,7 +10,9 @@ module MicroMicro
10
10
  end
11
11
 
12
12
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_p-_property
13
+ # microformats.org: microformats2 parsing specification § Parsing a +p-+ property
13
14
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_an_e-_property
15
+ # microformats.org: microformats2 parsing specification § Parsing an +e-+ property
14
16
  #
15
17
  # @return [String]
16
18
  def value
@@ -30,6 +30,7 @@ module MicroMicro
30
30
  # Value Class Pattern date and time parsing specification.
31
31
  #
32
32
  # @see https://microformats.org/wiki/value-class-pattern#Date_and_time_parsing
33
+ # microformats.org: Value Class Pattern § Date and time parsing
33
34
  #
34
35
  # @param string [String, #to_s]
35
36
  def initialize(string)
@@ -10,6 +10,7 @@ module MicroMicro
10
10
  }.freeze
11
11
 
12
12
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_dt-_property
13
+ # microformats.org: microformats2 parsing specification § Parsing a +dt-+ property
13
14
  #
14
15
  # @return [String]
15
16
  def value
@@ -19,6 +20,7 @@ module MicroMicro
19
20
  private
20
21
 
21
22
  # @see https://microformats.org/wiki/value-class-pattern#microformats2_parsers_implied_date
23
+ # microformats.org: Value Class Pattern § microformats2 parsers implied date
22
24
  #
23
25
  # @return [MicroMicro::Parsers::DateTimeParser, nil]
24
26
  def adopted_date_time_parser
@@ -39,6 +41,7 @@ module MicroMicro
39
41
  end
40
42
 
41
43
  # @see https://microformats.org/wiki/value-class-pattern#microformats2_parsers_implied_date
44
+ # microformats.org: Value Class Pattern § microformats2 parsers implied date
42
45
  #
43
46
  # @return [Boolean]
44
47
  def imply_date?
@@ -4,6 +4,7 @@ module MicroMicro
4
4
  module Parsers
5
5
  class EmbeddedMarkupPropertyParser < BasePropertyParser
6
6
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_an_e-_property
7
+ # microformats.org: microformats2 parsing specification § Parsing an +e-+ property
7
8
  #
8
9
  # @return [Hash{Symbol => String}]
9
10
  def value
@@ -10,6 +10,7 @@ module MicroMicro
10
10
  }.freeze
11
11
 
12
12
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
13
+ # microformats.org: microformats2 parsing specification § Parsing for implied properties
13
14
  #
14
15
  # @return [String]
15
16
  def value
@@ -11,7 +11,9 @@ module MicroMicro
11
11
  }.freeze
12
12
 
13
13
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
14
+ # microformats.org: microformats2 parsing specification § Parsing for implied properties
14
15
  # @see https://microformats.org/wiki/microformats2-parsing#parse_an_img_element_for_src_and_alt
16
+ # microformats.org: microformats2 parsing specification § Parse an img element for src and alt
15
17
  #
16
18
  # @return [String, Hash{Symbol => String}, nil]
17
19
  def value
@@ -11,6 +11,7 @@ module MicroMicro
11
11
  }.freeze
12
12
 
13
13
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
14
+ # microformats.org: microformats2 parsing specification § Parsing for implied properties
14
15
  #
15
16
  # @return [String, nil]
16
17
  def value
@@ -10,6 +10,7 @@ module MicroMicro
10
10
  }.freeze
11
11
 
12
12
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_p-_property
13
+ # microformats.org: microformats2 parsing specification § Parsing a +p-+ property
13
14
  #
14
15
  # @return [String]
15
16
  def value
@@ -16,7 +16,9 @@ module MicroMicro
16
16
  }.freeze
17
17
 
18
18
  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_u-_property
19
+ # microformats.org: microformats2 parsing specification § Parsing a +u-+ property
19
20
  # @see https://microformats.org/wiki/microformats2-parsing#parse_an_img_element_for_src_and_alt
21
+ # microformats.org: microformats2 parsing specification § Parse an img element for src and alt
20
22
  #
21
23
  # @return [String, Hash{Symbol => String}]
22
24
  def value
@@ -4,7 +4,9 @@ module MicroMicro
4
4
  module Parsers
5
5
  class ValueClassPatternParser
6
6
  # @see https://microformats.org/wiki/value-class-pattern#Basic_Parsing
7
+ # microformats.org: Value Class Pattern § Basic Parsing
7
8
  # @see https://microformats.org/wiki/value-class-pattern#Date_and_time_values
9
+ # microformats.org: Value Class Pattern § Date and time values
8
10
  HTML_ATTRIBUTES_MAP = {
9
11
  'alt' => %w[area img],
10
12
  'value' => %w[data],
@@ -37,7 +39,7 @@ module MicroMicro
37
39
  Helpers.attribute_value_from(node, HTML_ATTRIBUTES_MAP) || node.text
38
40
  end
39
41
 
40
- # @param context [Nokogiri::XML::Element]
42
+ # @param node [Nokogiri::XML::Element]
41
43
  # @param separator [String]
42
44
  def initialize(node, separator = '')
43
45
  @node = node
@@ -11,55 +11,95 @@ module MicroMicro
11
11
  'u' => Parsers::UrlPropertyParser
12
12
  }.freeze
13
13
 
14
- attr_reader :name, :node, :prefix
14
+ private_constant :PROPERTY_PARSERS_MAP
15
15
 
16
- # @param context [Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
17
- # @return [Array<MicroMicro::Property>]
18
- def self.from_context(context)
19
- node_set_from(context).flat_map do |node|
20
- Helpers.property_class_names_from(node).map { |token| new(node, token) }
16
+ class PropertyNodeSearch
17
+ attr_reader :node_set
18
+
19
+ def initialize(document)
20
+ @node_set = Nokogiri::XML::NodeSet.new(document, [])
21
21
  end
22
- end
23
22
 
24
- # @param context [Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
25
- # @param node_set [Nokogiri::XML::NodeSet]
26
- # @return [Nokogiri::XML::NodeSet]
27
- def self.node_set_from(context, node_set = Nokogiri::XML::NodeSet.new(context.document, []))
28
- context.each { |node| node_set_from(node, node_set) } if context.is_a?(Nokogiri::XML::NodeSet)
23
+ def search(context)
24
+ context.each { |node| search(node) } if context.is_a?(Nokogiri::XML::NodeSet)
25
+
26
+ if context.is_a?(Nokogiri::XML::Element) && !Helpers.ignore_node?(context)
27
+ node_set << context if Helpers.property_node?(context)
29
28
 
30
- if context.is_a?(Nokogiri::XML::Element) && !Helpers.ignore_node?(context)
31
- node_set << context if Helpers.property_node?(context)
29
+ search(context.element_children) unless Helpers.item_node?(context)
30
+ end
32
31
 
33
- node_set_from(context.element_children, node_set) unless Helpers.item_node?(context)
32
+ node_set
34
33
  end
34
+ end
35
+
36
+ private_constant :PropertyNodeSearch
35
37
 
36
- node_set
38
+ # This {MicroMicro::Property}'s +name+ value.
39
+ #
40
+ # @return [String]
41
+ attr_reader :name
42
+
43
+ # This {MicroMicro::Property}'s node.
44
+ #
45
+ # @return [Nokogiri::XML::Element]
46
+ attr_reader :node
47
+
48
+ # This {MicroMicro::Property}'s +prefix+ value.
49
+ #
50
+ # @return [String] One of +dt+, +e+, +p+, or +u+.
51
+ attr_reader :prefix
52
+
53
+ # Extract {MicroMicro::Property}s from a context.
54
+ #
55
+ # @param context [Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
56
+ # @return [Array<MicroMicro::Property>]
57
+ def self.from_context(context)
58
+ PropertyNodeSearch
59
+ .new(context.document)
60
+ .search(context)
61
+ .flat_map do |node|
62
+ Helpers.property_class_names_from(node).map { |token| new(node, token) }
63
+ end
37
64
  end
38
65
 
66
+ # Parse a node for property data.
67
+ #
39
68
  # @param node [Nokogiri::XML::Element]
40
- # @param token [String]
69
+ # @param token [String] A hyphen-separated token representing a microformats2
70
+ # property value (e.g. +p-name+, +u-url+).
41
71
  def initialize(node, token)
42
72
  @node = node
43
73
  @prefix, @name = token.split(/-/, 2)
44
74
  end
45
75
 
76
+ # Is this {MicroMicro::Property} a datetime property?
77
+ #
46
78
  # @return [Boolean]
47
79
  def date_time_property?
48
80
  prefix == 'dt'
49
81
  end
50
82
 
83
+ # Is this {MicroMicro::Property} an embedded markup property?
84
+ #
51
85
  # @return [Boolean]
52
86
  def embedded_markup_property?
53
87
  prefix == 'e'
54
88
  end
55
89
 
90
+ # Always return +false+ when asked if this {MicroMicro::Property} is an
91
+ # implied property.
92
+ #
93
+ # @see MicroMicro::ImpliedProperty#implied?
94
+ #
56
95
  # @return [Boolean]
57
96
  def implied?
58
97
  false
59
98
  end
60
99
 
61
- # :nocov:
62
100
  # @return [String]
101
+ #
102
+ # :nocov:
63
103
  def inspect
64
104
  "#<#{self.class}:#{format('%#0x', object_id)} " \
65
105
  "name: #{name.inspect}, " \
@@ -68,27 +108,42 @@ module MicroMicro
68
108
  end
69
109
  # :nocov:
70
110
 
111
+ # Parse this {MicroMicro::Property}'s node as a {MicroMicro::Item}, if
112
+ # applicable.
113
+ #
71
114
  # @return [MicroMicro::Item, nil]
72
115
  def item
73
116
  @item ||= Item.new(node) if item_node?
74
117
  end
75
118
 
119
+ # Should this {MicroMicro::Property}'s node be parsed as a
120
+ # {MicroMicro::Item}?
121
+ #
122
+ # @see MicroMicro::Helpers.item_node?
123
+ #
76
124
  # @return [Boolean]
77
125
  def item_node?
78
126
  @item_node ||= Helpers.item_node?(node)
79
127
  end
80
128
 
129
+ # Is this {MicroMicro::Property} a plain text property?
130
+ #
81
131
  # @return [Boolean]
82
132
  def plain_text_property?
83
133
  prefix == 'p'
84
134
  end
85
135
 
136
+ # Is this {MicroMicro::Property} a url property?
137
+ #
86
138
  # @return [Boolean]
87
139
  def url_property?
88
140
  prefix == 'u'
89
141
  end
90
142
 
143
+ # Return this {MicroMicro::Property}'s parsed value.
144
+ #
91
145
  # @return [String, Hash]
146
+ #
92
147
  # rubocop:disable Metrics
93
148
  def value
94
149
  @value ||=
@@ -107,6 +162,9 @@ module MicroMicro
107
162
  end
108
163
  # rubocop:enable Metrics
109
164
 
165
+ # Returns +true+ if this {MicroMicro::Property}'s +value+ is anything other
166
+ # than blank or +nil+.
167
+ #
110
168
  # @return [Boolean]
111
169
  def value?
112
170
  value.present?
@@ -4,31 +4,41 @@ module MicroMicro
4
4
  class Relationship
5
5
  include Collectible
6
6
 
7
+ # Extract {MicroMicro::Relationship}s from a context.
8
+ #
7
9
  # @param context [Nokogiri::HTML::Document, Nokogiri::XML::Element]
8
10
  # @return [Array<MicroMicro::Relationship>]
9
- def self.relationships_from(context)
11
+ def self.from_context(context)
10
12
  context.css('[href][rel]:not([rel=""])')
11
13
  .reject { |node| Helpers.ignore_nodes?(node.ancestors) }
12
14
  .map { |node| new(node) }
13
15
  end
14
16
 
17
+ # Parse a node for relationship data.
18
+ #
15
19
  # @param node [Nokogiri::XML::Element]
20
+ # @return [MicroMicro::Relationship]
16
21
  def initialize(node)
17
22
  @node = node
18
23
  end
19
24
 
25
+ # The value of the node's +href+ attribute.
26
+ #
20
27
  # @return [String]
21
28
  def href
22
29
  @href ||= node['href']
23
30
  end
24
31
 
32
+ # The value of the node's +hreflang+ attribute, if present.
33
+ #
25
34
  # @return [String, nil]
26
35
  def hreflang
27
36
  @hreflang ||= node['hreflang']&.strip
28
37
  end
29
38
 
30
- # :nocov:
31
39
  # @return [String]
40
+ #
41
+ # :nocov:
32
42
  def inspect
33
43
  "#<#{self.class}:#{format('%#0x', object_id)} " \
34
44
  "href: #{href.inspect}, " \
@@ -36,11 +46,15 @@ module MicroMicro
36
46
  end
37
47
  # :nocov:
38
48
 
49
+ # The value of the node's +media+ attribute, if present.
50
+ #
39
51
  # @return [String, nil]
40
52
  def media
41
53
  @media ||= node['media']&.strip
42
54
  end
43
55
 
56
+ # Return the parsed {MicroMicro::Relationship} as a Hash.
57
+ #
44
58
  # @return [Hash{Symbol => String}]
45
59
  def to_h
46
60
  {
@@ -54,21 +68,29 @@ module MicroMicro
54
68
  }.select { |_, value| value.present? }
55
69
  end
56
70
 
71
+ # An Array of unique values from node's +rel+ attribute.
72
+ #
57
73
  # @return [Array<String>]
58
74
  def rels
59
75
  @rels ||= node['rel'].split.uniq.sort
60
76
  end
61
77
 
78
+ # The node's text content.
79
+ #
62
80
  # @return [String]
63
81
  def text
64
82
  @text ||= node.text
65
83
  end
66
84
 
85
+ # The value of the node's +title+ attribute, if present.
86
+ #
67
87
  # @return [String, nil]
68
88
  def title
69
89
  @title ||= node['title']&.strip
70
90
  end
71
91
 
92
+ # The value of the node's +type+ attribute, if present.
93
+ #
72
94
  # @return [String, nil]
73
95
  def type
74
96
  @type ||= node['type']&.strip
@@ -76,6 +98,7 @@ module MicroMicro
76
98
 
77
99
  private
78
100
 
101
+ # @return [Nokogiri::XML::Element]
79
102
  attr_reader :node
80
103
  end
81
104
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MicroMicro
4
- VERSION = '2.0.1'
4
+ VERSION = '3.0.0'
5
5
  end
data/lib/micromicro.rb CHANGED
@@ -41,13 +41,14 @@ require_relative 'micro_micro/collections/relationships_collection'
41
41
 
42
42
  module MicroMicro
43
43
  # Parse a string of HTML for microformats2-encoded data.
44
- # Convenience method for MicroMicro::Document.new.
45
44
  #
45
+ # Convenience method for {MicroMicro::Document#initialize}.
46
+ #
47
+ # @example
46
48
  # MicroMicro.parse('<a href="/" class="h-card" rel="me">Jason Garber</a>', 'https://sixtwothree.org')
47
49
  #
48
- # @param markup [String] The HTML to parse for microformats2-encoded data.
49
- # @param base_url [String] The URL associated with markup. Used for relative URL resolution.
50
- # @return [MicroMicro::Document]
50
+ # @param (see MicroMicro::Document#initialize)
51
+ # @return (see MicroMicro::Document#initialize)
51
52
  def self.parse(markup, base_url)
52
53
  Document.new(markup, base_url)
53
54
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: micromicro
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Garber
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-21 00:00:00.000000000 Z
11
+ date: 2022-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -93,7 +93,7 @@ licenses:
93
93
  - MIT
94
94
  metadata:
95
95
  bug_tracker_uri: https://github.com/jgarber623/micromicro/issues
96
- changelog_uri: https://github.com/jgarber623/micromicro/blob/v2.0.1/CHANGELOG.md
96
+ changelog_uri: https://github.com/jgarber623/micromicro/blob/v3.0.0/CHANGELOG.md
97
97
  rubygems_mfa_required: 'true'
98
98
  post_install_message:
99
99
  rdoc_options: []