micromicro 4.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +2 -8
- data/lib/micro_micro/collections/items_collection.rb +4 -4
- data/lib/micro_micro/collections/properties_collection.rb +4 -4
- data/lib/micro_micro/collections/relationships_collection.rb +8 -7
- data/lib/micro_micro/document.rb +3 -3
- data/lib/micro_micro/helpers.rb +6 -6
- data/lib/micro_micro/implied_property.rb +3 -3
- data/lib/micro_micro/item.rb +12 -9
- data/lib/micro_micro/parsers/base_implied_property_parser.rb +4 -3
- data/lib/micro_micro/parsers/base_property_parser.rb +1 -1
- data/lib/micro_micro/parsers/date_time_parser.rb +7 -11
- data/lib/micro_micro/parsers/date_time_property_parser.rb +11 -7
- data/lib/micro_micro/parsers/image_element_parser.rb +6 -9
- data/lib/micro_micro/parsers/implied_name_property_parser.rb +7 -7
- data/lib/micro_micro/parsers/implied_photo_property_parser.rb +5 -5
- data/lib/micro_micro/parsers/implied_url_property_parser.rb +4 -4
- data/lib/micro_micro/parsers/plain_text_property_parser.rb +3 -3
- data/lib/micro_micro/parsers/url_property_parser.rb +7 -7
- data/lib/micro_micro/parsers/value_class_pattern_parser.rb +11 -10
- data/lib/micro_micro/property.rb +17 -13
- data/lib/micro_micro/relationship.rb +14 -10
- data/lib/micro_micro/version.rb +1 -1
- data/lib/micromicro.rb +38 -40
- data/micromicro.gemspec +17 -17
- metadata +5 -10
- data/CONTRIBUTING.md +0 -37
- data/lib/micro_micro/collectible.rb +0 -15
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0da58d9d4ae907a7a85ef964bcf30bb185e12023a6206a31ec41d53c38740fc1
         | 
| 4 | 
            +
              data.tar.gz: 4672c50b4dc4e5975599bd81feed4a10e5e7ebd25f786ea6d1a1a22c35647528
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 93c205bc429bc5b9bf76add264e131dd8e7fb4bb83fe9960eb94399cebfe52c04ffe71e6859770b216450cb52b0cdf604b8a3dff78745901900e860354cd1a2e
         | 
| 7 | 
            +
              data.tar.gz: ceee04c5ead6017a402f7c025f813e3d30b9b70c033966b14122f64897199a6e60c1b2dc89a47ed5798884ac2960d24055ed341b2e6bc85f877eb46a388745b4
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,27 @@ | |
| 1 1 | 
             
            # Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 5.0.0 / 2023-12-11
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            - Remove upper version constraint (#79) (86f09d8)
         | 
| 6 | 
            +
            - Miscellaneous cleanup (#78) (4023177)
         | 
| 7 | 
            +
              - **Breaking change:** remove `Collectible` module (`next_all` and `prev_all`
         | 
| 8 | 
            +
                no longer mixed in to various collection classes)
         | 
| 9 | 
            +
              - reduce reliance on ActiveSupport
         | 
| 10 | 
            +
            - Address RuboCop Performance warnings (#77) (2d5d0c2)
         | 
| 11 | 
            +
            - RuboCop formatting fixes (#76) (9ab491e)
         | 
| 12 | 
            +
            - RuboCop: Single quotes within interpolated string (#75) (37f66c0)
         | 
| 13 | 
            +
            - RuboCop: `Style/StringLiterals` (#74) (918b58a)
         | 
| 14 | 
            +
            - Address RuboCop `Style/StringLiterals` warnings' (#73) (3fb3cf4)
         | 
| 15 | 
            +
            - Add IRB config file (#72) (1ce9fab)
         | 
| 16 | 
            +
            - Update project files (#71) (85a5dd4)
         | 
| 17 | 
            +
            - Remove CodeClimate references (#70) (0b86c34)
         | 
| 18 | 
            +
            - RuboCop: `Style/PerlBackrefs` (a360af0)
         | 
| 19 | 
            +
            - RuboCop: `Lint/RedundantDirGlobSort` (15c8aca)
         | 
| 20 | 
            +
            - RuboCop: `Style/RedundantRegexpArgument` (8c93eb7)
         | 
| 21 | 
            +
            - RuboCop: `Style/RedundantFreeze` (feaee51)
         | 
| 22 | 
            +
            - **Breaking change:** Set minimum supported Ruby to 3.0 (f39dbef)
         | 
| 23 | 
            +
            - **Breaking change:** Update development Ruby to v3.0.6 (6869e22)
         | 
| 24 | 
            +
             | 
| 3 25 | 
             
            ## 4.0.0 / 2023-03-14
         | 
| 4 26 |  | 
| 5 27 | 
             
            - Parse HTML with `Nokogiri::HTML5::Document.parse` (330a2d1, 0de40d7)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -5,14 +5,12 @@ | |
| 5 5 | 
             
            [](https://rubygems.org/gems/micromicro)
         | 
| 6 6 | 
             
            [](https://rubygems.org/gems/micromicro)
         | 
| 7 7 | 
             
            [](https://github.com/jgarber623/micromicro/actions/workflows/ci.yml)
         | 
| 8 | 
            -
            [](https://codeclimate.com/github/jgarber623/micromicro)
         | 
| 9 | 
            -
            [](https://codeclimate.com/github/jgarber623/micromicro/code)
         | 
| 10 8 |  | 
| 11 9 | 
             
            ## Key Features
         | 
| 12 10 |  | 
| 13 11 | 
             
            - Parses microformats2-encoded HTML documents according to the [microformats2 parsing specification](https://microformats.org/wiki/microformats2-parsing)
         | 
| 14 12 | 
             
            - Passes all microformats2 tests from [the official test suite](https://github.com/microformats/tests)¹
         | 
| 15 | 
            -
            - Supports Ruby  | 
| 13 | 
            +
            - Supports Ruby 3.0 and newer
         | 
| 16 14 |  | 
| 17 15 | 
             
            **Note:** MicroMicro **does not** parse [Classic Microformats](https://microformats.org/wiki/Main_Page#Classic_Microformats) (referred to in [the parsing specification](https://microformats.org/wiki/microformats2-parsing#note_backward_compatibility_details) as "backcompat root classes" and "backcompat properties" and in vocabulary specifications in the "Parser Compatibility" sections [e.g. [h-entry](https://microformats.org/wiki/h-entry#Parser_Compatibility)]). To parse documents marked up with Classic Microformats, consider using [the official microformats-ruby parser](https://github.com/microformats/microformats-ruby).
         | 
| 18 16 |  | 
| @@ -20,7 +18,7 @@ | |
| 20 18 |  | 
| 21 19 | 
             
            ## Installation
         | 
| 22 20 |  | 
| 23 | 
            -
            Before installing and using MicroMicro, you'll want to have [Ruby](https://www.ruby-lang.org)  | 
| 21 | 
            +
            Before installing and using MicroMicro, you'll want to have [Ruby](https://www.ruby-lang.org) 3.0 (or newer) installed. If you're using [Bundler](https://bundler.io) to manage gem dependencies, add MicroMicro to your project's Gemfile:
         | 
| 24 22 |  | 
| 25 23 | 
             
            ```ruby
         | 
| 26 24 | 
             
            gem 'micromicro'
         | 
| @@ -50,10 +48,6 @@ doc.to_h | |
| 50 48 |  | 
| 51 49 | 
             
            See [USAGE.md](https://github.com/jgarber623/micromicro/blob/main/USAGE.md) for detailed examples of MicroMicro's features. Additional structured documentation is available on [RubyDoc.info](https://rubydoc.info/gems/micromicro).
         | 
| 52 50 |  | 
| 53 | 
            -
            ## Contributing
         | 
| 54 | 
            -
             | 
| 55 | 
            -
            Interested in helping improve MicroMicro? Awesome! Your help is greatly appreciated. See [CONTRIBUTING.md](https://github.com/jgarber623/micromicro/blob/main/CONTRIBUTING.md) for details.
         | 
| 56 | 
            -
             | 
| 57 51 | 
             
            ## Acknowledgments
         | 
| 58 52 |  | 
| 59 53 | 
             
            MicroMicro wouldn't exist without the hard work of everyone involved in the [microformats](https://microformats.org) community. Additionally, the comprehensive [microformats test suite](https://github.com/microformats/tests) was invaluable in the development of this Ruby gem.
         | 
| @@ -58,7 +58,7 @@ module MicroMicro | |
| 58 58 | 
             
                  #
         | 
| 59 59 | 
             
                  # @return [Array<String>]
         | 
| 60 60 | 
             
                  def types
         | 
| 61 | 
            -
                    @types ||= flat_map(&:types). | 
| 61 | 
            +
                    @types ||= Set[*flat_map(&:types)].to_a.sort
         | 
| 62 62 | 
             
                  end
         | 
| 63 63 |  | 
| 64 64 | 
             
                  # Recursively search this collection for {MicroMicro::Item}s matching the
         | 
| @@ -70,10 +70,10 @@ module MicroMicro | |
| 70 70 | 
             
                  # either a String or an Array of Strings.
         | 
| 71 71 | 
             
                  #
         | 
| 72 72 | 
             
                  # @example Search using a Hash with a String value
         | 
| 73 | 
            -
                  #   MicroMicro.parse(markup, url).items.where(types:  | 
| 73 | 
            +
                  #   MicroMicro.parse(markup, url).items.where(types: "h-card")
         | 
| 74 74 | 
             
                  #
         | 
| 75 75 | 
             
                  # @example Search using a Hash with an Array value
         | 
| 76 | 
            -
                  #   MicroMicro.parse(markup, url).items.where(types: [ | 
| 76 | 
            +
                  #   MicroMicro.parse(markup, url).items.where(types: ["h-card", "h-entry"])
         | 
| 77 77 | 
             
                  #
         | 
| 78 78 | 
             
                  # When passing a block, each {MicroMicro::Item} in this collection is
         | 
| 79 79 | 
             
                  # yielded to the block and the returned collection will include
         | 
| @@ -82,7 +82,7 @@ module MicroMicro | |
| 82 82 | 
             
                  #
         | 
| 83 83 | 
             
                  # @example Search using a block
         | 
| 84 84 | 
             
                  #   MicroMicro.parse(markup, url).items.where do |item|
         | 
| 85 | 
            -
                  #     item.properties.names.include?( | 
| 85 | 
            +
                  #     item.properties.names.include?("email")
         | 
| 86 86 | 
             
                  #   end
         | 
| 87 87 | 
             
                  #
         | 
| 88 88 | 
             
                  # @param args [Hash{Symbol => String, Array<String>}]
         | 
| @@ -37,7 +37,7 @@ module MicroMicro | |
| 37 37 | 
             
                  #
         | 
| 38 38 | 
             
                  # @return [Array<String>]
         | 
| 39 39 | 
             
                  def names
         | 
| 40 | 
            -
                    @names ||= map(&:name). | 
| 40 | 
            +
                    @names ||= Set[*map(&:name)].to_a.sort
         | 
| 41 41 | 
             
                  end
         | 
| 42 42 |  | 
| 43 43 | 
             
                  # A collection of plain text {MicroMicro::Property}s parsed from the node.
         | 
| @@ -91,7 +91,7 @@ module MicroMicro | |
| 91 91 | 
             
                  #
         | 
| 92 92 | 
             
                  # @return [Array<String, Hash>]
         | 
| 93 93 | 
             
                  def values
         | 
| 94 | 
            -
                    @values ||= map(&:value). | 
| 94 | 
            +
                    @values ||= Set[*map(&:value)].to_a
         | 
| 95 95 | 
             
                  end
         | 
| 96 96 |  | 
| 97 97 | 
             
                  # Search this collection for {MicroMicro::Property}s matching the given
         | 
| @@ -103,10 +103,10 @@ module MicroMicro | |
| 103 103 | 
             
                  # either a String or an Array of Strings.
         | 
| 104 104 | 
             
                  #
         | 
| 105 105 | 
             
                  # @example Search using a Hash with a String value
         | 
| 106 | 
            -
                  #   MicroMicro.parse(markup, url).properties.where(name:  | 
| 106 | 
            +
                  #   MicroMicro.parse(markup, url).properties.where(name: "url")
         | 
| 107 107 | 
             
                  #
         | 
| 108 108 | 
             
                  # @example Search using a Hash with an Array value
         | 
| 109 | 
            -
                  #   MicroMicro.parse(markup, url).properties.where(name: [ | 
| 109 | 
            +
                  #   MicroMicro.parse(markup, url).properties.where(name: ["name", "url"])
         | 
| 110 110 | 
             
                  #
         | 
| 111 111 | 
             
                  # When passing a block, each {MicroMicro::Property} in this collection
         | 
| 112 112 | 
             
                  # is yielded to the block and the returned collection will include
         | 
| @@ -38,9 +38,10 @@ module MicroMicro | |
| 38 38 | 
             
                  #
         | 
| 39 39 | 
             
                  # @return [Hash{Symbol => Array<String>}]
         | 
| 40 40 | 
             
                  def group_by_rel
         | 
| 41 | 
            -
                     | 
| 42 | 
            -
             | 
| 43 | 
            -
                     | 
| 41 | 
            +
                    obj = Hash.new { |hash, key| hash[key] = Set.new }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    each_with_object(obj) { |member, hash| member.rels.each { |rel| hash[rel.to_sym] << member.href } }
         | 
| 44 | 
            +
                      .transform_values(&:to_a)
         | 
| 44 45 | 
             
                  end
         | 
| 45 46 |  | 
| 46 47 | 
             
                  # Return a Hash of this collection's {MicroMicro::Relationship}s grouped
         | 
| @@ -61,7 +62,7 @@ module MicroMicro | |
| 61 62 | 
             
                  #
         | 
| 62 63 | 
             
                  # @return [Array<String>]
         | 
| 63 64 | 
             
                  def rels
         | 
| 64 | 
            -
                    @rels ||= flat_map(&:rels). | 
| 65 | 
            +
                    @rels ||= Set[*flat_map(&:rels)].to_a.sort
         | 
| 65 66 | 
             
                  end
         | 
| 66 67 |  | 
| 67 68 | 
             
                  # Retrieve an Array of this collection's unique {MicroMicro::Relationship}
         | 
| @@ -71,7 +72,7 @@ module MicroMicro | |
| 71 72 | 
             
                  #
         | 
| 72 73 | 
             
                  # @return [Array<String>]
         | 
| 73 74 | 
             
                  def urls
         | 
| 74 | 
            -
                    @urls ||= map(&:href). | 
| 75 | 
            +
                    @urls ||= Set[*map(&:href)].to_a.sort
         | 
| 75 76 | 
             
                  end
         | 
| 76 77 |  | 
| 77 78 | 
             
                  # Search this collection for {MicroMicro::Relationship}s matching the
         | 
| @@ -83,10 +84,10 @@ module MicroMicro | |
| 83 84 | 
             
                  # values may be either a String or an Array of Strings.
         | 
| 84 85 | 
             
                  #
         | 
| 85 86 | 
             
                  # @example Search using a Hash with a String value
         | 
| 86 | 
            -
                  #   MicroMicro.parse(markup, url).relationships.where(rels:  | 
| 87 | 
            +
                  #   MicroMicro.parse(markup, url).relationships.where(rels: "webmention")
         | 
| 87 88 | 
             
                  #
         | 
| 88 89 | 
             
                  # @example Search using a Hash with an Array value
         | 
| 89 | 
            -
                  #   MicroMicro.parse(markup, url).relationships.where(rels: [ | 
| 90 | 
            +
                  #   MicroMicro.parse(markup, url).relationships.where(rels: ["me", "webmention"])
         | 
| 90 91 | 
             
                  #
         | 
| 91 92 | 
             
                  # When passing a block, each {MicroMicro::Relationship} in this collection
         | 
| 92 93 | 
             
                  # is yielded to the block and the returned collection will include
         | 
    
        data/lib/micro_micro/document.rb
    CHANGED
    
    | @@ -5,10 +5,10 @@ module MicroMicro | |
| 5 5 | 
             
                # Parse a string of HTML for microformats2-encoded data.
         | 
| 6 6 | 
             
                #
         | 
| 7 7 | 
             
                # @example Parse a String of markup
         | 
| 8 | 
            -
                #   MicroMicro::Document.new( | 
| 8 | 
            +
                #   MicroMicro::Document.new(%(<a href="/" class="h-card" rel="me">Jason Garber</a>), "https://sixtwothree.org")
         | 
| 9 9 | 
             
                #
         | 
| 10 10 | 
             
                # @example Parse a String of markup from a URL
         | 
| 11 | 
            -
                #   url =  | 
| 11 | 
            +
                #   url = "https://tantek.com"
         | 
| 12 12 | 
             
                #   markup = Net::HTTP.get(URI.parse(url))
         | 
| 13 13 | 
             
                #
         | 
| 14 14 | 
             
                #   doc = MicroMicro::Document.new(markup, url)
         | 
| @@ -57,7 +57,7 @@ module MicroMicro | |
| 57 57 | 
             
                  {
         | 
| 58 58 | 
             
                    items: items.to_a,
         | 
| 59 59 | 
             
                    rels: relationships.group_by_rel,
         | 
| 60 | 
            -
                     | 
| 60 | 
            +
                    "rel-urls": relationships.group_by_url
         | 
| 61 61 | 
             
                  }
         | 
| 62 62 | 
             
                end
         | 
| 63 63 |  | 
    
        data/lib/micro_micro/helpers.rb
    CHANGED
    
    | @@ -10,9 +10,9 @@ module MicroMicro | |
| 10 10 | 
             
                # @param attributes_map [Hash{String => Array}]
         | 
| 11 11 | 
             
                # @return [String, nil]
         | 
| 12 12 | 
             
                def self.attribute_value_from(node, attributes_map)
         | 
| 13 | 
            -
                  attributes_map | 
| 14 | 
            -
                    node[attribute] if names.include?(node.name) && node[attribute]
         | 
| 15 | 
            -
             | 
| 13 | 
            +
                  attributes_map
         | 
| 14 | 
            +
                    .filter_map { |attribute, names| node[attribute] if names.include?(node.name) && node[attribute] }
         | 
| 15 | 
            +
                    .first
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 18 | 
             
                # @param node [Nokogiri::XML::Element]
         | 
| @@ -54,7 +54,7 @@ module MicroMicro | |
| 54 54 | 
             
                # @param node [Nokogiri::XML::Element]
         | 
| 55 55 | 
             
                # @return [Array<String>]
         | 
| 56 56 | 
             
                def self.root_class_names_from(node)
         | 
| 57 | 
            -
                  node.classes.grep(/^h(?:-[0-9a-z]+)?(?:-[a-z]+)+$/). | 
| 57 | 
            +
                  Set[*node.classes.grep(/^h(?:-[0-9a-z]+)?(?:-[a-z]+)+$/)].to_a.sort
         | 
| 58 58 | 
             
                end
         | 
| 59 59 |  | 
| 60 60 | 
             
                # @see https://microformats.org/wiki/microformats2-parsing#parse_an_element_for_properties
         | 
| @@ -79,7 +79,7 @@ module MicroMicro | |
| 79 79 | 
             
                # @param node [Nokogiri::XML::Element]
         | 
| 80 80 | 
             
                # @return [Boolean]
         | 
| 81 81 | 
             
                def self.value_class_node?(node)
         | 
| 82 | 
            -
                  node.classes.include?( | 
| 82 | 
            +
                  node.classes.include?("value")
         | 
| 83 83 | 
             
                end
         | 
| 84 84 |  | 
| 85 85 | 
             
                # @see https://microformats.org/wiki/value-class-pattern#Parsing_value_from_a_title_attribute
         | 
| @@ -88,7 +88,7 @@ module MicroMicro | |
| 88 88 | 
             
                # @param node [Nokogiri::XML::Element]
         | 
| 89 89 | 
             
                # @return [Boolean]
         | 
| 90 90 | 
             
                def self.value_title_node?(node)
         | 
| 91 | 
            -
                  node.classes.include?( | 
| 91 | 
            +
                  node.classes.include?("value-title")
         | 
| 92 92 | 
             
                end
         | 
| 93 93 | 
             
              end
         | 
| 94 94 | 
             
            end
         | 
| @@ -3,9 +3,9 @@ | |
| 3 3 | 
             
            module MicroMicro
         | 
| 4 4 | 
             
              class ImpliedProperty < Property
         | 
| 5 5 | 
             
                IMPLIED_PROPERTY_PARSERS_MAP = {
         | 
| 6 | 
            -
                   | 
| 7 | 
            -
                   | 
| 8 | 
            -
                   | 
| 6 | 
            +
                  "name"  => Parsers::ImpliedNamePropertyParser,
         | 
| 7 | 
            +
                  "photo" => Parsers::ImpliedPhotoPropertyParser,
         | 
| 8 | 
            +
                  "url"   => Parsers::ImpliedUrlPropertyParser
         | 
| 9 9 | 
             
                }.freeze
         | 
| 10 10 |  | 
| 11 11 | 
             
                private_constant :IMPLIED_PROPERTY_PARSERS_MAP
         | 
    
        data/lib/micro_micro/item.rb
    CHANGED
    
    | @@ -2,8 +2,6 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module MicroMicro
         | 
| 4 4 | 
             
              class Item
         | 
| 5 | 
            -
                include Collectible
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
                class ItemNodeSearch
         | 
| 8 6 | 
             
                  attr_reader :node_set
         | 
| 9 7 |  | 
| @@ -30,6 +28,11 @@ module MicroMicro | |
| 30 28 |  | 
| 31 29 | 
             
                private_constant :ItemNodeSearch
         | 
| 32 30 |  | 
| 31 | 
            +
                # The {MicroMicro::ItemsCollection} to which this {MicroMicro::Item} belongs.
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # @return [MicroMicro::PropertiesCollection]
         | 
| 34 | 
            +
                attr_accessor :collection
         | 
| 35 | 
            +
             | 
| 33 36 | 
             
                # Extract {MicroMicro::Item}s from a context.
         | 
| 34 37 | 
             
                #
         | 
| 35 38 | 
             
                # @param context [Nokogiri::HTML5::Document, Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
         | 
| @@ -74,7 +77,7 @@ module MicroMicro | |
| 74 77 | 
             
                #
         | 
| 75 78 | 
             
                # @return [String, nil]
         | 
| 76 79 | 
             
                def id
         | 
| 77 | 
            -
                  @id ||= node[ | 
| 80 | 
            +
                  @id ||= node["id"]&.strip
         | 
| 78 81 | 
             
                end
         | 
| 79 82 |  | 
| 80 83 | 
             
                # Does this {MicroMicro::Item} have an +id+ attribute value?
         | 
| @@ -140,7 +143,7 @@ module MicroMicro | |
| 140 143 |  | 
| 141 144 | 
             
                # @return [MicroMicro::ImpliedProperty]
         | 
| 142 145 | 
             
                def implied_name
         | 
| 143 | 
            -
                  @implied_name ||= ImpliedProperty.new(node,  | 
| 146 | 
            +
                  @implied_name ||= ImpliedProperty.new(node, "p-name")
         | 
| 144 147 | 
             
                end
         | 
| 145 148 |  | 
| 146 149 | 
             
                # @return [Boolean]
         | 
| @@ -150,7 +153,7 @@ module MicroMicro | |
| 150 153 |  | 
| 151 154 | 
             
                # @return [MicroMicro::ImpliedProperty]
         | 
| 152 155 | 
             
                def implied_photo
         | 
| 153 | 
            -
                  @implied_photo ||= ImpliedProperty.new(node,  | 
| 156 | 
            +
                  @implied_photo ||= ImpliedProperty.new(node, "u-photo")
         | 
| 154 157 | 
             
                end
         | 
| 155 158 |  | 
| 156 159 | 
             
                # @return [Boolean]
         | 
| @@ -160,7 +163,7 @@ module MicroMicro | |
| 160 163 |  | 
| 161 164 | 
             
                # @return [MicroMicro::ImpliedProperty]
         | 
| 162 165 | 
             
                def implied_url
         | 
| 163 | 
            -
                  @implied_url ||= ImpliedProperty.new(node,  | 
| 166 | 
            +
                  @implied_url ||= ImpliedProperty.new(node, "u-url")
         | 
| 164 167 | 
             
                end
         | 
| 165 168 |  | 
| 166 169 | 
             
                # @return [Boolean]
         | 
| @@ -170,7 +173,7 @@ module MicroMicro | |
| 170 173 |  | 
| 171 174 | 
             
                # @return [Boolean]
         | 
| 172 175 | 
             
                def imply_name?
         | 
| 173 | 
            -
                  properties.names.none?( | 
| 176 | 
            +
                  properties.names.none?("name") &&
         | 
| 174 177 | 
             
                    properties.none?(&:embedded_markup_property?) &&
         | 
| 175 178 | 
             
                    properties.none?(&:plain_text_property?) &&
         | 
| 176 179 | 
             
                    !nested_items?
         | 
| @@ -178,14 +181,14 @@ module MicroMicro | |
| 178 181 |  | 
| 179 182 | 
             
                # @return [Boolean]
         | 
| 180 183 | 
             
                def imply_photo?
         | 
| 181 | 
            -
                  properties.names.none?( | 
| 184 | 
            +
                  properties.names.none?("photo") &&
         | 
| 182 185 | 
             
                    properties.reject(&:implied?).none?(&:url_property?) &&
         | 
| 183 186 | 
             
                    !nested_items?
         | 
| 184 187 | 
             
                end
         | 
| 185 188 |  | 
| 186 189 | 
             
                # @return [Boolean]
         | 
| 187 190 | 
             
                def imply_url?
         | 
| 188 | 
            -
                  properties.names.none?( | 
| 191 | 
            +
                  properties.names.none?("url") &&
         | 
| 189 192 | 
             
                    properties.reject(&:implied?).none?(&:url_property?) &&
         | 
| 190 193 | 
             
                    !nested_items?
         | 
| 191 194 | 
             
                end
         | 
| @@ -14,9 +14,10 @@ module MicroMicro | |
| 14 14 | 
             
                  def candidate_node
         | 
| 15 15 | 
             
                    @candidate_node ||=
         | 
| 16 16 | 
             
                      candidate_nodes.find do |node|
         | 
| 17 | 
            -
                        self | 
| 18 | 
            -
                           | 
| 19 | 
            -
             | 
| 17 | 
            +
                        self
         | 
| 18 | 
            +
                          .class::HTML_ELEMENTS_MAP
         | 
| 19 | 
            +
                          .filter_map { |name, attribute| node if name == node.name && node[attribute] }
         | 
| 20 | 
            +
                          .any?
         | 
| 20 21 | 
             
                      end
         | 
| 21 22 | 
             
                  end
         | 
| 22 23 |  | 
| @@ -18,7 +18,7 @@ module MicroMicro | |
| 18 18 | 
             
                  def value
         | 
| 19 19 | 
             
                    @value ||=
         | 
| 20 20 | 
             
                      Helpers.text_content_from(node) do |context|
         | 
| 21 | 
            -
                        context.css( | 
| 21 | 
            +
                        context.css("img").each { |img| img.content = " #{img['alt'] || img['src']} " }
         | 
| 22 22 | 
             
                      end
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 |  | 
| @@ -24,7 +24,7 @@ module MicroMicro | |
| 24 24 | 
             
                    (?:#{DATE_REGEXP_PATTERN})?
         | 
| 25 25 | 
             
                    (?:\s?#{TIME_REGEXP_PATTERN}(?:#{TIMEZONE_REGEXP_PATTERN})?)?
         | 
| 26 26 | 
             
                    \z
         | 
| 27 | 
            -
                  /x | 
| 27 | 
            +
                  /x
         | 
| 28 28 |  | 
| 29 29 | 
             
                  # Parse a string for date and/or time values according to the Microformats
         | 
| 30 30 | 
             
                  # Value Class Pattern date and time parsing specification.
         | 
| @@ -39,11 +39,7 @@ module MicroMicro | |
| 39 39 |  | 
| 40 40 | 
             
                  # Define getter and predicate methods for all possible named captures
         | 
| 41 41 | 
             
                  # returned by the DATE_TIME_TIMEZONE_REGEXP regular expression.
         | 
| 42 | 
            -
                  [
         | 
| 43 | 
            -
                    :year, :ordinal, :month, :day,
         | 
| 44 | 
            -
                    :hours, :minutes, :seconds,
         | 
| 45 | 
            -
                    :abbreviation, :zulu, :offset
         | 
| 46 | 
            -
                  ].each do |name|
         | 
| 42 | 
            +
                  %i[year ordinal month day hours minutes seconds abbreviation zulu offset].each do |name|
         | 
| 47 43 | 
             
                    define_method(name) { values[name] }
         | 
| 48 44 | 
             
                    define_method("#{name}?") { public_send(name).present? }
         | 
| 49 45 | 
             
                  end
         | 
| @@ -62,15 +58,15 @@ module MicroMicro | |
| 62 58 | 
             
                  def normalized_hours
         | 
| 63 59 | 
             
                    @normalized_hours ||=
         | 
| 64 60 | 
             
                      if hours?
         | 
| 65 | 
            -
                        return (hours.to_i + 12).to_s if abbreviation&.tr( | 
| 61 | 
            +
                        return (hours.to_i + 12).to_s if abbreviation&.tr(".", "")&.downcase == "pm"
         | 
| 66 62 |  | 
| 67 | 
            -
                        format( | 
| 63 | 
            +
                        format("%<hours>02d", hours: hours)
         | 
| 68 64 | 
             
                      end
         | 
| 69 65 | 
             
                  end
         | 
| 70 66 |  | 
| 71 67 | 
             
                  # @return [String]
         | 
| 72 68 | 
             
                  def normalized_minutes
         | 
| 73 | 
            -
                    @normalized_minutes ||= minutes ||  | 
| 69 | 
            +
                    @normalized_minutes ||= minutes || "00"
         | 
| 74 70 | 
             
                  end
         | 
| 75 71 |  | 
| 76 72 | 
             
                  # @return [String, nil]
         | 
| @@ -80,12 +76,12 @@ module MicroMicro | |
| 80 76 |  | 
| 81 77 | 
             
                  # @return [String, nil]
         | 
| 82 78 | 
             
                  def normalized_time
         | 
| 83 | 
            -
                    @normalized_time ||= [normalized_hours, normalized_minutes, seconds].compact.join( | 
| 79 | 
            +
                    @normalized_time ||= [normalized_hours, normalized_minutes, seconds].compact.join(":") if normalized_hours
         | 
| 84 80 | 
             
                  end
         | 
| 85 81 |  | 
| 86 82 | 
             
                  # @return [String, nil]
         | 
| 87 83 | 
             
                  def normalized_timezone
         | 
| 88 | 
            -
                    @normalized_timezone ||= zulu || offset&.tr( | 
| 84 | 
            +
                    @normalized_timezone ||= zulu || offset&.tr(":", "")
         | 
| 89 85 | 
             
                  end
         | 
| 90 86 |  | 
| 91 87 | 
             
                  # @return [String, nil]
         | 
| @@ -4,9 +4,9 @@ module MicroMicro | |
| 4 4 | 
             
              module Parsers
         | 
| 5 5 | 
             
                class DateTimePropertyParser < BasePropertyParser
         | 
| 6 6 | 
             
                  HTML_ATTRIBUTES_MAP = {
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                     | 
| 9 | 
            -
                     | 
| 7 | 
            +
                    "datetime" => %w[del ins time],
         | 
| 8 | 
            +
                    "title"    => %w[abbr],
         | 
| 9 | 
            +
                    "value"    => %w[data input]
         | 
| 10 10 | 
             
                  }.freeze
         | 
| 11 11 |  | 
| 12 12 | 
             
                  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_dt-_property
         | 
| @@ -25,9 +25,13 @@ module MicroMicro | |
| 25 25 | 
             
                  # @return [MicroMicro::Parsers::DateTimeParser, nil]
         | 
| 26 26 | 
             
                  def adopted_date_time_parser
         | 
| 27 27 | 
             
                    @adopted_date_time_parser ||=
         | 
| 28 | 
            -
                       | 
| 29 | 
            -
                         | 
| 30 | 
            -
             | 
| 28 | 
            +
                      begin
         | 
| 29 | 
            +
                        head, tail = property.collection.split(property)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                        (head.reverse + tail)
         | 
| 32 | 
            +
                          .filter_map { |prop| DateTimeParser.new(prop.value) if prop.date_time_property? }
         | 
| 33 | 
            +
                          .find(&:normalized_date)
         | 
| 34 | 
            +
                      end
         | 
| 31 35 | 
             
                  end
         | 
| 32 36 |  | 
| 33 37 | 
             
                  # @return [String, nil]
         | 
| @@ -37,7 +41,7 @@ module MicroMicro | |
| 37 41 |  | 
| 38 42 | 
             
                  # @return [MicroMicro::Parsers::DateTimeParser]
         | 
| 39 43 | 
             
                  def date_time_parser
         | 
| 40 | 
            -
                    @date_time_parser ||= DateTimeParser.new(ValueClassPatternParser.new(node,  | 
| 44 | 
            +
                    @date_time_parser ||= DateTimeParser.new(ValueClassPatternParser.new(node, " ").value)
         | 
| 41 45 | 
             
                  end
         | 
| 42 46 |  | 
| 43 47 | 
             
                  # @see https://microformats.org/wiki/value-class-pattern#microformats2_parsers_implied_date
         | 
| @@ -15,7 +15,7 @@ module MicroMicro | |
| 15 15 |  | 
| 16 16 | 
             
                  # @return [String, nil]
         | 
| 17 17 | 
             
                  def alt
         | 
| 18 | 
            -
                    @alt ||= node[ | 
| 18 | 
            +
                    @alt ||= node["alt"]&.strip
         | 
| 19 19 | 
             
                  end
         | 
| 20 20 |  | 
| 21 21 | 
             
                  # @return [Boolean]
         | 
| @@ -25,7 +25,7 @@ module MicroMicro | |
| 25 25 |  | 
| 26 26 | 
             
                  # @return [Hash{Symbol => String}, nil]
         | 
| 27 27 | 
             
                  def srcset
         | 
| 28 | 
            -
                    @srcset ||= image_candidates if node[ | 
| 28 | 
            +
                    @srcset ||= image_candidates if node["srcset"]
         | 
| 29 29 | 
             
                  end
         | 
| 30 30 |  | 
| 31 31 | 
             
                  # @return [Boolean]
         | 
| @@ -49,20 +49,17 @@ module MicroMicro | |
| 49 49 | 
             
                  attr_reader :node
         | 
| 50 50 |  | 
| 51 51 | 
             
                  # @return [Hash{Symbol => String}]
         | 
| 52 | 
            -
                  #
         | 
| 53 | 
            -
                  # rubocop:disable Style/PerlBackrefs
         | 
| 54 52 | 
             
                  def image_candidates
         | 
| 55 | 
            -
                    node[ | 
| 56 | 
            -
                      .split( | 
| 53 | 
            +
                    node["srcset"]
         | 
| 54 | 
            +
                      .split(",")
         | 
| 57 55 | 
             
                      .each_with_object({}) do |candidate, hash|
         | 
| 58 56 | 
             
                        candidate.strip.match(/^(.+?)(\s+.+)?$/) do
         | 
| 59 | 
            -
                          key = ( | 
| 57 | 
            +
                          key = (Regexp.last_match(2) || "1x").strip.to_sym
         | 
| 60 58 |  | 
| 61 | 
            -
                          hash[key] =  | 
| 59 | 
            +
                          hash[key] = Regexp.last_match(1) unless hash[key]
         | 
| 62 60 | 
             
                        end
         | 
| 63 61 | 
             
                      end
         | 
| 64 62 | 
             
                  end
         | 
| 65 | 
            -
                  # rubocop:enable Style/PerlBackrefs
         | 
| 66 63 | 
             
                end
         | 
| 67 64 | 
             
              end
         | 
| 68 65 | 
             
            end
         | 
| @@ -4,9 +4,9 @@ module MicroMicro | |
| 4 4 | 
             
              module Parsers
         | 
| 5 5 | 
             
                class ImpliedNamePropertyParser < BaseImpliedPropertyParser
         | 
| 6 6 | 
             
                  HTML_ELEMENTS_MAP = {
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                     | 
| 9 | 
            -
                     | 
| 7 | 
            +
                    "img"  => "alt",
         | 
| 8 | 
            +
                    "area" => "alt",
         | 
| 9 | 
            +
                    "abbr" => "title"
         | 
| 10 10 | 
             
                  }.freeze
         | 
| 11 11 |  | 
| 12 12 | 
             
                  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
         | 
| @@ -22,15 +22,15 @@ module MicroMicro | |
| 22 22 | 
             
                  # @return [Array]
         | 
| 23 23 | 
             
                  def child_nodes
         | 
| 24 24 | 
             
                    [
         | 
| 25 | 
            -
                      node.at_css( | 
| 26 | 
            -
                      node.at_css( | 
| 27 | 
            -
                    ]. | 
| 25 | 
            +
                      node.at_css("> :only-child"),
         | 
| 26 | 
            +
                      node.at_css("> :only-child > :only-child")
         | 
| 27 | 
            +
                    ].delete_if { |child_node| child_node.nil? || Helpers.item_node?(child_node) }
         | 
| 28 28 | 
             
                  end
         | 
| 29 29 |  | 
| 30 30 | 
             
                  # @return [String]
         | 
| 31 31 | 
             
                  def text_content
         | 
| 32 32 | 
             
                    Helpers.text_content_from(node) do |context|
         | 
| 33 | 
            -
                      context.css( | 
| 33 | 
            +
                      context.css("img").each { |img| img.content = img["alt"] }
         | 
| 34 34 | 
             
                    end
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 | 
             
                end
         | 
| @@ -3,11 +3,11 @@ | |
| 3 3 | 
             
            module MicroMicro
         | 
| 4 4 | 
             
              module Parsers
         | 
| 5 5 | 
             
                class ImpliedPhotoPropertyParser < BaseImpliedPropertyParser
         | 
| 6 | 
            -
                  CSS_SELECTORS_ARRAY = [ | 
| 6 | 
            +
                  CSS_SELECTORS_ARRAY = ["> img[src]:only-of-type", "> object[data]:only-of-type"].freeze
         | 
| 7 7 |  | 
| 8 8 | 
             
                  HTML_ELEMENTS_MAP = {
         | 
| 9 | 
            -
                     | 
| 10 | 
            -
                     | 
| 9 | 
            +
                    "img"    => "src",
         | 
| 10 | 
            +
                    "object" => "data"
         | 
| 11 11 | 
             
                  }.freeze
         | 
| 12 12 |  | 
| 13 13 | 
             
                  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
         | 
| @@ -19,7 +19,7 @@ module MicroMicro | |
| 19 19 | 
             
                  def value
         | 
| 20 20 | 
             
                    @value ||=
         | 
| 21 21 | 
             
                      if attribute_value
         | 
| 22 | 
            -
                        if candidate_node.matches?( | 
| 22 | 
            +
                        if candidate_node.matches?("img[alt], img[srcset]")
         | 
| 23 23 | 
             
                          ImageElementParser.new(candidate_node, attribute_value).to_h
         | 
| 24 24 | 
             
                        else
         | 
| 25 25 | 
             
                          attribute_value
         | 
| @@ -35,7 +35,7 @@ module MicroMicro | |
| 35 35 |  | 
| 36 36 | 
             
                    nodes << node.first_element_child.at_css(*CSS_SELECTORS_ARRAY) if node.element_children.one?
         | 
| 37 37 |  | 
| 38 | 
            -
                    nodes. | 
| 38 | 
            +
                    nodes.delete_if { |child_node| child_node.nil? || Helpers.item_node?(child_node) }
         | 
| 39 39 | 
             
                  end
         | 
| 40 40 | 
             
                end
         | 
| 41 41 | 
             
              end
         | 
| @@ -3,11 +3,11 @@ | |
| 3 3 | 
             
            module MicroMicro
         | 
| 4 4 | 
             
              module Parsers
         | 
| 5 5 | 
             
                class ImpliedUrlPropertyParser < BaseImpliedPropertyParser
         | 
| 6 | 
            -
                  CSS_SELECTORS_ARRAY = [ | 
| 6 | 
            +
                  CSS_SELECTORS_ARRAY = ["> a[href]:only-of-type", "> area[href]:only-of-type"].freeze
         | 
| 7 7 |  | 
| 8 8 | 
             
                  HTML_ELEMENTS_MAP = {
         | 
| 9 | 
            -
                     | 
| 10 | 
            -
                     | 
| 9 | 
            +
                    "a"    => "href",
         | 
| 10 | 
            +
                    "area" => "href"
         | 
| 11 11 | 
             
                  }.freeze
         | 
| 12 12 |  | 
| 13 13 | 
             
                  # @see https://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties
         | 
| @@ -26,7 +26,7 @@ module MicroMicro | |
| 26 26 |  | 
| 27 27 | 
             
                    nodes << node.first_element_child.at_css(*CSS_SELECTORS_ARRAY) if node.element_children.one?
         | 
| 28 28 |  | 
| 29 | 
            -
                    nodes. | 
| 29 | 
            +
                    nodes.delete_if { |child_node| child_node.nil? || Helpers.item_node?(child_node) }
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 | 
             
                end
         | 
| 32 32 | 
             
              end
         | 
| @@ -4,9 +4,9 @@ module MicroMicro | |
| 4 4 | 
             
              module Parsers
         | 
| 5 5 | 
             
                class PlainTextPropertyParser < BasePropertyParser
         | 
| 6 6 | 
             
                  HTML_ATTRIBUTES_MAP = {
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                     | 
| 9 | 
            -
                     | 
| 7 | 
            +
                    "title" => %w[abbr link],
         | 
| 8 | 
            +
                    "value" => %w[data input],
         | 
| 9 | 
            +
                    "alt"   => %w[area img]
         | 
| 10 10 | 
             
                  }.freeze
         | 
| 11 11 |  | 
| 12 12 | 
             
                  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_p-_property
         | 
| @@ -4,15 +4,15 @@ module MicroMicro | |
| 4 4 | 
             
              module Parsers
         | 
| 5 5 | 
             
                class UrlPropertyParser < BasePropertyParser
         | 
| 6 6 | 
             
                  HTML_ATTRIBUTES_MAP = {
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                     | 
| 9 | 
            -
                     | 
| 10 | 
            -
                     | 
| 7 | 
            +
                    "href"   => %w[a area link],
         | 
| 8 | 
            +
                    "src"    => %w[audio iframe img source video],
         | 
| 9 | 
            +
                    "poster" => %w[video],
         | 
| 10 | 
            +
                    "data"   => %w[object]
         | 
| 11 11 | 
             
                  }.freeze
         | 
| 12 12 |  | 
| 13 13 | 
             
                  EXTENDED_HTML_ATTRIBUTES_MAP = {
         | 
| 14 | 
            -
                     | 
| 15 | 
            -
                     | 
| 14 | 
            +
                    "title" => %w[abbr],
         | 
| 15 | 
            +
                    "value" => %w[data input]
         | 
| 16 16 | 
             
                  }.freeze
         | 
| 17 17 |  | 
| 18 18 | 
             
                  # @see https://microformats.org/wiki/microformats2-parsing#parsing_a_u-_property
         | 
| @@ -23,7 +23,7 @@ module MicroMicro | |
| 23 23 | 
             
                  # @return [String, Hash{Symbol => String}]
         | 
| 24 24 | 
             
                  def value
         | 
| 25 25 | 
             
                    @value ||=
         | 
| 26 | 
            -
                      if node.matches?( | 
| 26 | 
            +
                      if node.matches?("img[alt], img[srcset]")
         | 
| 27 27 | 
             
                        ImageElementParser.new(node, resolved_value).to_h
         | 
| 28 28 | 
             
                      else
         | 
| 29 29 | 
             
                        resolved_value
         | 
| @@ -8,10 +8,10 @@ module MicroMicro | |
| 8 8 | 
             
                  # @see https://microformats.org/wiki/value-class-pattern#Date_and_time_values
         | 
| 9 9 | 
             
                  #   microformats.org: Value Class Pattern § Date and time values
         | 
| 10 10 | 
             
                  HTML_ATTRIBUTES_MAP = {
         | 
| 11 | 
            -
                     | 
| 12 | 
            -
                     | 
| 13 | 
            -
                     | 
| 14 | 
            -
                     | 
| 11 | 
            +
                    "alt"      => %w[area img],
         | 
| 12 | 
            +
                    "value"    => %w[data],
         | 
| 13 | 
            +
                    "title"    => %w[abbr],
         | 
| 14 | 
            +
                    "datetime" => %w[del ins time]
         | 
| 15 15 | 
             
                  }.freeze
         | 
| 16 16 |  | 
| 17 17 | 
             
                  # @param context [Nokogiri::XML::NodeSet, Nokogiri::XML::Element]
         | 
| @@ -34,14 +34,14 @@ module MicroMicro | |
| 34 34 | 
             
                  # @param node [Nokogiri::XML::Element]
         | 
| 35 35 | 
             
                  # @return [String, nil]
         | 
| 36 36 | 
             
                  def self.value_from(node)
         | 
| 37 | 
            -
                    return node[ | 
| 37 | 
            +
                    return node["title"] if Helpers.value_title_node?(node)
         | 
| 38 38 |  | 
| 39 39 | 
             
                    Helpers.attribute_value_from(node, HTML_ATTRIBUTES_MAP) || node.text
         | 
| 40 40 | 
             
                  end
         | 
| 41 41 |  | 
| 42 42 | 
             
                  # @param node [Nokogiri::XML::Element]
         | 
| 43 43 | 
             
                  # @param separator [String]
         | 
| 44 | 
            -
                  def initialize(node, separator =  | 
| 44 | 
            +
                  def initialize(node, separator = "")
         | 
| 45 45 | 
             
                    @node = node
         | 
| 46 46 | 
             
                    @separator = separator
         | 
| 47 47 | 
             
                  end
         | 
| @@ -54,10 +54,11 @@ module MicroMicro | |
| 54 54 | 
             
                  # @return [Array<String>]
         | 
| 55 55 | 
             
                  def values
         | 
| 56 56 | 
             
                    @values ||=
         | 
| 57 | 
            -
                      self | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 57 | 
            +
                      self
         | 
| 58 | 
            +
                        .class
         | 
| 59 | 
            +
                        .node_set_from(node)
         | 
| 60 | 
            +
                        .map { |value_node| self.class.value_from(value_node) }
         | 
| 61 | 
            +
                        .compact_blank!
         | 
| 61 62 | 
             
                  end
         | 
| 62 63 |  | 
| 63 64 | 
             
                  private
         | 
    
        data/lib/micro_micro/property.rb
    CHANGED
    
    | @@ -2,13 +2,11 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module MicroMicro
         | 
| 4 4 | 
             
              class Property
         | 
| 5 | 
            -
                include Collectible
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
                PROPERTY_PARSERS_MAP = {
         | 
| 8 | 
            -
                   | 
| 9 | 
            -
                   | 
| 10 | 
            -
                   | 
| 11 | 
            -
                   | 
| 6 | 
            +
                  "dt" => Parsers::DateTimePropertyParser,
         | 
| 7 | 
            +
                  "e"  => Parsers::EmbeddedMarkupPropertyParser,
         | 
| 8 | 
            +
                  "p"  => Parsers::PlainTextPropertyParser,
         | 
| 9 | 
            +
                  "u"  => Parsers::UrlPropertyParser
         | 
| 12 10 | 
             
                }.freeze
         | 
| 13 11 |  | 
| 14 12 | 
             
                private_constant :PROPERTY_PARSERS_MAP
         | 
| @@ -35,6 +33,12 @@ module MicroMicro | |
| 35 33 |  | 
| 36 34 | 
             
                private_constant :PropertyNodeSearch
         | 
| 37 35 |  | 
| 36 | 
            +
                # The {MicroMicro::PropertiesCollection} to which this
         | 
| 37 | 
            +
                # {MicroMicro::Property} belongs.
         | 
| 38 | 
            +
                #
         | 
| 39 | 
            +
                # @return [MicroMicro::PropertiesCollection]
         | 
| 40 | 
            +
                attr_accessor :collection
         | 
| 41 | 
            +
             | 
| 38 42 | 
             
                # This {MicroMicro::Property}'s +name+ value.
         | 
| 39 43 | 
             
                #
         | 
| 40 44 | 
             
                # @return [String]
         | 
| @@ -70,21 +74,21 @@ module MicroMicro | |
| 70 74 | 
             
                #   property value (e.g. +p-name+, +u-url+).
         | 
| 71 75 | 
             
                def initialize(node, token)
         | 
| 72 76 | 
             
                  @node = node
         | 
| 73 | 
            -
                  @prefix, @name = token.split( | 
| 77 | 
            +
                  @prefix, @name = token.split("-", 2)
         | 
| 74 78 | 
             
                end
         | 
| 75 79 |  | 
| 76 80 | 
             
                # Is this {MicroMicro::Property} a datetime property?
         | 
| 77 81 | 
             
                #
         | 
| 78 82 | 
             
                # @return [Boolean]
         | 
| 79 83 | 
             
                def date_time_property?
         | 
| 80 | 
            -
                  prefix ==  | 
| 84 | 
            +
                  prefix == "dt"
         | 
| 81 85 | 
             
                end
         | 
| 82 86 |  | 
| 83 87 | 
             
                # Is this {MicroMicro::Property} an embedded markup property?
         | 
| 84 88 | 
             
                #
         | 
| 85 89 | 
             
                # @return [Boolean]
         | 
| 86 90 | 
             
                def embedded_markup_property?
         | 
| 87 | 
            -
                  prefix ==  | 
| 91 | 
            +
                  prefix == "e"
         | 
| 88 92 | 
             
                end
         | 
| 89 93 |  | 
| 90 94 | 
             
                # Always return +false+ when asked if this {MicroMicro::Property} is an
         | 
| @@ -130,14 +134,14 @@ module MicroMicro | |
| 130 134 | 
             
                #
         | 
| 131 135 | 
             
                # @return [Boolean]
         | 
| 132 136 | 
             
                def plain_text_property?
         | 
| 133 | 
            -
                  prefix ==  | 
| 137 | 
            +
                  prefix == "p"
         | 
| 134 138 | 
             
                end
         | 
| 135 139 |  | 
| 136 140 | 
             
                # Is this {MicroMicro::Property} a url property?
         | 
| 137 141 | 
             
                #
         | 
| 138 142 | 
             
                # @return [Boolean]
         | 
| 139 143 | 
             
                def url_property?
         | 
| 140 | 
            -
                  prefix ==  | 
| 144 | 
            +
                  prefix == "u"
         | 
| 141 145 | 
             
                end
         | 
| 142 146 |  | 
| 143 147 | 
             
                # Return this {MicroMicro::Property}'s parsed value.
         | 
| @@ -152,8 +156,8 @@ module MicroMicro | |
| 152 156 |  | 
| 153 157 | 
             
                      return hash.merge(parser.value) if embedded_markup_property?
         | 
| 154 158 |  | 
| 155 | 
            -
                      p_property = item.properties.find_by(name:  | 
| 156 | 
            -
                      u_property = item.properties.find_by(name:  | 
| 159 | 
            +
                      p_property = item.properties.find_by(name: "name") if plain_text_property?
         | 
| 160 | 
            +
                      u_property = item.properties.find_by(name: "url") if url_property?
         | 
| 157 161 |  | 
| 158 162 | 
             
                      hash.merge(value: (p_property || u_property || parser).value)
         | 
| 159 163 | 
             
                    else
         | 
| @@ -2,16 +2,20 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module MicroMicro
         | 
| 4 4 | 
             
              class Relationship
         | 
| 5 | 
            -
                 | 
| 5 | 
            +
                # The {MicroMicro::RelationshipsCollection} to which this
         | 
| 6 | 
            +
                # {MicroMicro::Relationship} belongs.
         | 
| 7 | 
            +
                #
         | 
| 8 | 
            +
                # @return [MicroMicro::RelationshipsCollection]
         | 
| 9 | 
            +
                attr_accessor :collection
         | 
| 6 10 |  | 
| 7 11 | 
             
                # Extract {MicroMicro::Relationship}s from a context.
         | 
| 8 12 | 
             
                #
         | 
| 9 13 | 
             
                # @param context [Nokogiri::HTML5::Document, Nokogiri::XML::Element]
         | 
| 10 14 | 
             
                # @return [Array<MicroMicro::Relationship>]
         | 
| 11 15 | 
             
                def self.from_context(context)
         | 
| 12 | 
            -
                  context | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 16 | 
            +
                  context
         | 
| 17 | 
            +
                    .css(%([href][rel]:not([rel=""])))
         | 
| 18 | 
            +
                    .filter_map { |node| new(node) unless Helpers.ignore_nodes?(node.ancestors) }
         | 
| 15 19 | 
             
                end
         | 
| 16 20 |  | 
| 17 21 | 
             
                # Parse a node for relationship data.
         | 
| @@ -26,14 +30,14 @@ module MicroMicro | |
| 26 30 | 
             
                #
         | 
| 27 31 | 
             
                # @return [String]
         | 
| 28 32 | 
             
                def href
         | 
| 29 | 
            -
                  @href ||= node[ | 
| 33 | 
            +
                  @href ||= node["href"]
         | 
| 30 34 | 
             
                end
         | 
| 31 35 |  | 
| 32 36 | 
             
                # The value of the node's +hreflang+ attribute, if present.
         | 
| 33 37 | 
             
                #
         | 
| 34 38 | 
             
                # @return [String, nil]
         | 
| 35 39 | 
             
                def hreflang
         | 
| 36 | 
            -
                  @hreflang ||= node[ | 
| 40 | 
            +
                  @hreflang ||= node["hreflang"]&.strip
         | 
| 37 41 | 
             
                end
         | 
| 38 42 |  | 
| 39 43 | 
             
                # @return [String]
         | 
| @@ -50,7 +54,7 @@ module MicroMicro | |
| 50 54 | 
             
                #
         | 
| 51 55 | 
             
                # @return [String, nil]
         | 
| 52 56 | 
             
                def media
         | 
| 53 | 
            -
                  @media ||= node[ | 
| 57 | 
            +
                  @media ||= node["media"]&.strip
         | 
| 54 58 | 
             
                end
         | 
| 55 59 |  | 
| 56 60 | 
             
                # Return the parsed {MicroMicro::Relationship} as a Hash.
         | 
| @@ -72,7 +76,7 @@ module MicroMicro | |
| 72 76 | 
             
                #
         | 
| 73 77 | 
             
                # @return [Array<String>]
         | 
| 74 78 | 
             
                def rels
         | 
| 75 | 
            -
                  @rels ||= node[ | 
| 79 | 
            +
                  @rels ||= Set[*node["rel"].split].to_a.sort
         | 
| 76 80 | 
             
                end
         | 
| 77 81 |  | 
| 78 82 | 
             
                # The node's text content.
         | 
| @@ -86,14 +90,14 @@ module MicroMicro | |
| 86 90 | 
             
                #
         | 
| 87 91 | 
             
                # @return [String, nil]
         | 
| 88 92 | 
             
                def title
         | 
| 89 | 
            -
                  @title ||= node[ | 
| 93 | 
            +
                  @title ||= node["title"]&.strip
         | 
| 90 94 | 
             
                end
         | 
| 91 95 |  | 
| 92 96 | 
             
                # The value of the node's +type+ attribute, if present.
         | 
| 93 97 | 
             
                #
         | 
| 94 98 | 
             
                # @return [String, nil]
         | 
| 95 99 | 
             
                def type
         | 
| 96 | 
            -
                  @type ||= node[ | 
| 100 | 
            +
                  @type ||= node["type"]&.strip
         | 
| 97 101 | 
             
                end
         | 
| 98 102 |  | 
| 99 103 | 
             
                private
         | 
    
        data/lib/micro_micro/version.rb
    CHANGED
    
    
    
        data/lib/micromicro.rb
    CHANGED
    
    | @@ -1,44 +1,42 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 4 | 
            -
             | 
| 5 | 
            -
            require  | 
| 6 | 
            -
            require  | 
| 7 | 
            -
            require  | 
| 8 | 
            -
            require  | 
| 9 | 
            -
            require  | 
| 10 | 
            -
            require  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
            require_relative  | 
| 14 | 
            -
             | 
| 15 | 
            -
            require_relative  | 
| 16 | 
            -
             | 
| 17 | 
            -
            require_relative  | 
| 18 | 
            -
             | 
| 19 | 
            -
            require_relative  | 
| 20 | 
            -
             | 
| 21 | 
            -
            require_relative  | 
| 22 | 
            -
            require_relative  | 
| 23 | 
            -
            require_relative  | 
| 24 | 
            -
             | 
| 25 | 
            -
            require_relative  | 
| 26 | 
            -
             | 
| 27 | 
            -
            require_relative  | 
| 28 | 
            -
            require_relative  | 
| 29 | 
            -
             | 
| 30 | 
            -
            require_relative  | 
| 31 | 
            -
             | 
| 32 | 
            -
            require_relative  | 
| 33 | 
            -
            require_relative  | 
| 34 | 
            -
            require_relative  | 
| 35 | 
            -
             | 
| 36 | 
            -
            require_relative  | 
| 37 | 
            -
             | 
| 38 | 
            -
            require_relative  | 
| 39 | 
            -
            require_relative  | 
| 40 | 
            -
            require_relative 'micro_micro/collections/properties_collection'
         | 
| 41 | 
            -
            require_relative 'micro_micro/collections/relationships_collection'
         | 
| 3 | 
            +
            require "forwardable"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "active_support/core_ext/array/grouping"
         | 
| 6 | 
            +
            require "active_support/core_ext/enumerable"
         | 
| 7 | 
            +
            require "active_support/core_ext/hash/deep_transform_values"
         | 
| 8 | 
            +
            require "active_support/core_ext/object/blank"
         | 
| 9 | 
            +
            require "nokogiri"
         | 
| 10 | 
            +
            require "nokogiri/html-ext"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require_relative "micro_micro/version"
         | 
| 13 | 
            +
            require_relative "micro_micro/helpers"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            require_relative "micro_micro/parsers/date_time_parser"
         | 
| 16 | 
            +
            require_relative "micro_micro/parsers/image_element_parser"
         | 
| 17 | 
            +
            require_relative "micro_micro/parsers/value_class_pattern_parser"
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            require_relative "micro_micro/parsers/base_property_parser"
         | 
| 20 | 
            +
            require_relative "micro_micro/parsers/date_time_property_parser"
         | 
| 21 | 
            +
            require_relative "micro_micro/parsers/embedded_markup_property_parser"
         | 
| 22 | 
            +
            require_relative "micro_micro/parsers/plain_text_property_parser"
         | 
| 23 | 
            +
            require_relative "micro_micro/parsers/url_property_parser"
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            require_relative "micro_micro/parsers/base_implied_property_parser"
         | 
| 26 | 
            +
            require_relative "micro_micro/parsers/implied_name_property_parser"
         | 
| 27 | 
            +
            require_relative "micro_micro/parsers/implied_photo_property_parser"
         | 
| 28 | 
            +
            require_relative "micro_micro/parsers/implied_url_property_parser"
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            require_relative "micro_micro/document"
         | 
| 31 | 
            +
            require_relative "micro_micro/item"
         | 
| 32 | 
            +
            require_relative "micro_micro/property"
         | 
| 33 | 
            +
            require_relative "micro_micro/implied_property"
         | 
| 34 | 
            +
            require_relative "micro_micro/relationship"
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            require_relative "micro_micro/collections/base_collection"
         | 
| 37 | 
            +
            require_relative "micro_micro/collections/items_collection"
         | 
| 38 | 
            +
            require_relative "micro_micro/collections/properties_collection"
         | 
| 39 | 
            +
            require_relative "micro_micro/collections/relationships_collection"
         | 
| 42 40 |  | 
| 43 41 | 
             
            module MicroMicro
         | 
| 44 42 | 
             
              # Parse a string of HTML for microformats2-encoded data.
         | 
| @@ -46,7 +44,7 @@ module MicroMicro | |
| 46 44 | 
             
              # Convenience method for {MicroMicro::Document#initialize}.
         | 
| 47 45 | 
             
              #
         | 
| 48 46 | 
             
              # @example
         | 
| 49 | 
            -
              #   MicroMicro.parse( | 
| 47 | 
            +
              #   MicroMicro.parse(%(<a href="/" class="h-card" rel="me">Jason Garber</a>), "https://sixtwothree.org")
         | 
| 50 48 | 
             
              #
         | 
| 51 49 | 
             
              # @param (see MicroMicro::Document#initialize)
         | 
| 52 50 | 
             
              # @return (see MicroMicro::Document#initialize)
         | 
    
        data/micromicro.gemspec
    CHANGED
    
    | @@ -1,33 +1,33 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require_relative  | 
| 3 | 
            +
            require_relative "lib/micro_micro/version"
         | 
| 4 4 |  | 
| 5 5 | 
             
            Gem::Specification.new do |spec|
         | 
| 6 | 
            -
              spec.required_ruby_version =  | 
| 6 | 
            +
              spec.required_ruby_version = ">= 3.0"
         | 
| 7 7 |  | 
| 8 | 
            -
              spec.name          =  | 
| 8 | 
            +
              spec.name          = "micromicro"
         | 
| 9 9 | 
             
              spec.version       = MicroMicro::VERSION
         | 
| 10 | 
            -
              spec.authors       = [ | 
| 11 | 
            -
              spec.email         = [ | 
| 10 | 
            +
              spec.authors       = ["Jason Garber"]
         | 
| 11 | 
            +
              spec.email         = ["jason@sixtwothree.org"]
         | 
| 12 12 |  | 
| 13 | 
            -
              spec.summary       =  | 
| 13 | 
            +
              spec.summary       = "Extract microformats2-encoded data from HTML documents."
         | 
| 14 14 | 
             
              spec.description   = spec.summary
         | 
| 15 | 
            -
              spec.homepage      =  | 
| 16 | 
            -
              spec.license       =  | 
| 15 | 
            +
              spec.homepage      = "https://github.com/jgarber623/micromicro"
         | 
| 16 | 
            +
              spec.license       = "MIT"
         | 
| 17 17 |  | 
| 18 | 
            -
              spec.files         = Dir[ | 
| 19 | 
            -
              spec.files        += %w[LICENSE CHANGELOG.md  | 
| 18 | 
            +
              spec.files         = Dir["lib/**/*"].reject { |f| File.directory?(f) }
         | 
| 19 | 
            +
              spec.files        += %w[LICENSE CHANGELOG.md README.md]
         | 
| 20 20 | 
             
              spec.files        += %w[micromicro.gemspec]
         | 
| 21 21 |  | 
| 22 | 
            -
              spec.require_paths = [ | 
| 22 | 
            +
              spec.require_paths = ["lib"]
         | 
| 23 23 |  | 
| 24 24 | 
             
              spec.metadata = {
         | 
| 25 | 
            -
                 | 
| 26 | 
            -
                 | 
| 27 | 
            -
                 | 
| 25 | 
            +
                "bug_tracker_uri"       => "#{spec.homepage}/issues",
         | 
| 26 | 
            +
                "changelog_uri"         => "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md",
         | 
| 27 | 
            +
                "rubygems_mfa_required" => "true"
         | 
| 28 28 | 
             
              }
         | 
| 29 29 |  | 
| 30 | 
            -
              spec.add_runtime_dependency  | 
| 31 | 
            -
              spec.add_runtime_dependency  | 
| 32 | 
            -
              spec.add_runtime_dependency  | 
| 30 | 
            +
              spec.add_runtime_dependency "activesupport", "~> 7.0"
         | 
| 31 | 
            +
              spec.add_runtime_dependency "nokogiri", ">= 1.14"
         | 
| 32 | 
            +
              spec.add_runtime_dependency "nokogiri-html-ext", "~> 0.4.0"
         | 
| 33 33 | 
             
            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:  | 
| 4 | 
            +
              version: 5.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: 2023- | 
| 11 | 
            +
            date: 2023-12-12 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -60,10 +60,8 @@ extensions: [] | |
| 60 60 | 
             
            extra_rdoc_files: []
         | 
| 61 61 | 
             
            files:
         | 
| 62 62 | 
             
            - CHANGELOG.md
         | 
| 63 | 
            -
            - CONTRIBUTING.md
         | 
| 64 63 | 
             
            - LICENSE
         | 
| 65 64 | 
             
            - README.md
         | 
| 66 | 
            -
            - lib/micro_micro/collectible.rb
         | 
| 67 65 | 
             
            - lib/micro_micro/collections/base_collection.rb
         | 
| 68 66 | 
             
            - lib/micro_micro/collections/items_collection.rb
         | 
| 69 67 | 
             
            - lib/micro_micro/collections/properties_collection.rb
         | 
| @@ -94,7 +92,7 @@ licenses: | |
| 94 92 | 
             
            - MIT
         | 
| 95 93 | 
             
            metadata:
         | 
| 96 94 | 
             
              bug_tracker_uri: https://github.com/jgarber623/micromicro/issues
         | 
| 97 | 
            -
              changelog_uri: https://github.com/jgarber623/micromicro/blob/ | 
| 95 | 
            +
              changelog_uri: https://github.com/jgarber623/micromicro/blob/v5.0.0/CHANGELOG.md
         | 
| 98 96 | 
             
              rubygems_mfa_required: 'true'
         | 
| 99 97 | 
             
            post_install_message: 
         | 
| 100 98 | 
             
            rdoc_options: []
         | 
| @@ -104,17 +102,14 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 104 102 | 
             
              requirements:
         | 
| 105 103 | 
             
              - - ">="
         | 
| 106 104 | 
             
                - !ruby/object:Gem::Version
         | 
| 107 | 
            -
                  version: ' | 
| 108 | 
            -
              - - "<"
         | 
| 109 | 
            -
                - !ruby/object:Gem::Version
         | 
| 110 | 
            -
                  version: '4'
         | 
| 105 | 
            +
                  version: '3.0'
         | 
| 111 106 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 112 107 | 
             
              requirements:
         | 
| 113 108 | 
             
              - - ">="
         | 
| 114 109 | 
             
                - !ruby/object:Gem::Version
         | 
| 115 110 | 
             
                  version: '0'
         | 
| 116 111 | 
             
            requirements: []
         | 
| 117 | 
            -
            rubygems_version: 3. | 
| 112 | 
            +
            rubygems_version: 3.2.33
         | 
| 118 113 | 
             
            signing_key: 
         | 
| 119 114 | 
             
            specification_version: 4
         | 
| 120 115 | 
             
            summary: Extract microformats2-encoded data from HTML documents.
         | 
    
        data/CONTRIBUTING.md
    DELETED
    
    | @@ -1,37 +0,0 @@ | |
| 1 | 
            -
            # Contributing to MicroMicro
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            There are a couple ways you can help improve MicroMicro:
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            1. Fix an existing [issue][issues] and submit a [pull request][pulls].
         | 
| 6 | 
            -
            1. Review open [pull requests][pulls].
         | 
| 7 | 
            -
            1. Report a new [issue][issues]. _Only do this after you've made sure the behavior or problem you're observing isn't already documented in an open issue._
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            ## Getting Started
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            MicroMicro is developed using Ruby 2.7.7 and is additionally tested against Ruby 3.0, 3.1, and 3.2 using [GitHub Actions](https://github.com/jgarber623/micromicro/actions).
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            Before making changes to MicroMicro, you'll want to install Ruby 2.7.7. 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). Once you've installed Ruby 2.7.7 using your method of choice, install the project's gems by running:
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            ```sh
         | 
| 16 | 
            -
            bundle install
         | 
| 17 | 
            -
            ```
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            ## Making Changes
         | 
| 20 | 
            -
             | 
| 21 | 
            -
            1. Fork and clone the project's repo.
         | 
| 22 | 
            -
            1. Install development dependencies as outlined above.
         | 
| 23 | 
            -
            1. Create a feature branch for the code changes you're looking to make: `git checkout -b my-new-feature`.
         | 
| 24 | 
            -
            1. _Write some code!_
         | 
| 25 | 
            -
            1. If your changes would benefit from testing, add the necessary tests and verify everything passes by running `bundle exec rspec`.
         | 
| 26 | 
            -
            1. Commit your changes: `git commit -am 'Add some new feature or fix some issue'`. _(See [this excellent article](https://chris.beams.io/posts/git-commit/) for tips on writing useful Git commit messages.)_
         | 
| 27 | 
            -
            1. Push the branch to your fork: `git push -u origin my-new-feature`.
         | 
| 28 | 
            -
            1. Create a new [pull request][pulls] and we'll review your changes.
         | 
| 29 | 
            -
             | 
| 30 | 
            -
            ## Code Style
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            Code formatting conventions are defined in the `.editorconfig` file which uses the [EditorConfig](http://editorconfig.org) syntax. There are [plugins for a variety of editors](http://editorconfig.org/#download) that utilize the settings in the `.editorconfig` file. We recommended you install the EditorConfig plugin for your editor of choice.
         | 
| 33 | 
            -
             | 
| 34 | 
            -
            Your bug fix or feature addition won't be rejected if it runs afoul of any (or all) of these guidelines, but following the guidelines will definitely make everyone's lives a little easier.
         | 
| 35 | 
            -
             | 
| 36 | 
            -
            [issues]: https://github.com/jgarber623/micromicro/issues
         | 
| 37 | 
            -
            [pulls]: https://github.com/jgarber623/micromicro/pulls
         |