micromicro 2.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []