webmention 0.0.1 → 0.1.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.
- data/.gitignore +17 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/README.md +67 -0
- data/Rakefile +10 -0
- data/example.rb +20 -0
- data/lib/webmention.rb +7 -0
- data/lib/webmention/client.rb +170 -0
- data/lib/webmention/version.rb +3 -0
- data/test/data/sample_html.rb +77 -0
- data/test/lib/webmention/crawl_test.rb +23 -0
- data/test/lib/webmention/discovery_test.rb +88 -0
- data/test/lib/webmention/mention_test.rb +38 -0
- data/test/lib/webmention/url_test.rb +31 -0
- data/test/lib/webmention/version_test.rb +9 -0
- data/test/test_helper.rb +5 -0
- data/webmention.gemspec +30 -0
- metadata +92 -4
    
        data/.gitignore
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            Webmention Client
         | 
| 2 | 
            +
            =================
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            A Ruby gem for sending [webmention](http://indiewebcamp.com/webmention) (and [pingback](http://indiewebcamp.com/pingback)) notifications.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            [](https://travis-ci.org/icco/mention-client-ruby)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Installation
         | 
| 9 | 
            +
            ------------
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                gem install webmention
         | 
| 12 | 
            +
             | 
| 13 | 
            +
             | 
| 14 | 
            +
            Usage
         | 
| 15 | 
            +
            -----
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ### Send webmentions to all links on a page
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ```ruby
         | 
| 20 | 
            +
            client = Webmention::Client.new url
         | 
| 21 | 
            +
            sent = client.send_mentions
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            puts "Sent #{sent} mentions"
         | 
| 24 | 
            +
            ```
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            This will find all absolute links on the page at `url` and will attempt to send
         | 
| 27 | 
            +
            mentions to each. This is accomplished by doing a HEAD request and looking at the headers
         | 
| 28 | 
            +
            for supported servers, if none are found, then it searches the body of the page.
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            After finding either webmention or pingback endpoints, the request is sent to each.
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            ### Send webmention to a specific URL
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            ```ruby
         | 
| 35 | 
            +
            # Discover the webmention endpoint of a target and send the mention
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            source = "http://source.example.com/post/100"   # For example, your page
         | 
| 38 | 
            +
            target = "http://indiewebcamp.com/"             # The page you linked to
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            if endpoint = Webmention::Client.supports_webmention?(target)
         | 
| 41 | 
            +
              Webmention::Client.send_mention endpoint, source, target
         | 
| 42 | 
            +
            end
         | 
| 43 | 
            +
            ```
         | 
| 44 | 
            +
             | 
| 45 | 
            +
             | 
| 46 | 
            +
            Webmention
         | 
| 47 | 
            +
            ----------
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            To learn more about Webmention, see [webmention.org](http://webmention.org).
         | 
| 50 | 
            +
             | 
| 51 | 
            +
             | 
| 52 | 
            +
            License
         | 
| 53 | 
            +
            -------
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            Copyright 2013 by Aaron Parecki
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            Licensed under the Apache License, Version 2.0 (the "License");
         | 
| 58 | 
            +
            you may not use this file except in compliance with the License.
         | 
| 59 | 
            +
            You may obtain a copy of the License at
         | 
| 60 | 
            +
             | 
| 61 | 
            +
               http://www.apache.org/licenses/LICENSE-2.0
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            Unless required by applicable law or agreed to in writing, software
         | 
| 64 | 
            +
            distributed under the License is distributed on an "AS IS" BASIS,
         | 
| 65 | 
            +
            WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 66 | 
            +
            See the License for the specific language governing permissions and
         | 
| 67 | 
            +
            limitations under the License.
         | 
    
        data/Rakefile
    ADDED
    
    
    
        data/example.rb
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            require './lib/webmention.rb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Send webmentions to any links on the page that have a webmention endpoint
         | 
| 4 | 
            +
            url = 'http://aaronparecki.com/notes/2013/06/23/1/indiewebcamp'
         | 
| 5 | 
            +
            client = Webmention::Client.new url
         | 
| 6 | 
            +
            sent = client.send_mentions
         | 
| 7 | 
            +
            puts "Sent #{sent} mentions"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 10 | 
            +
            # Discover the webmention endpoint of a target and send the mention
         | 
| 11 | 
            +
            target = "http://indiewebcamp.com/"
         | 
| 12 | 
            +
            endpoint = Webmention::Client.supports_webmention? target
         | 
| 13 | 
            +
            if endpoint 
         | 
| 14 | 
            +
              Webmention::Client.send_mention endpoint, "http://source.example.com/post/100", target
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
             | 
| 18 | 
            +
            # You can also use the client to send to a specific webmention endpoint
         | 
| 19 | 
            +
            Webmention::Client.send_mention "http://webmention.io/example/webmention", "http://source.example.com/post/100", "http://target.example.com/post/100"
         | 
| 20 | 
            +
             | 
    
        data/lib/webmention.rb
    CHANGED
    
    
| @@ -0,0 +1,170 @@ | |
| 1 | 
            +
            module Webmention
         | 
| 2 | 
            +
              class Client
         | 
| 3 | 
            +
                # Public: Returns a URI of the url initialized with.
         | 
| 4 | 
            +
                attr_reader :url
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                # Public: Returns an array of links contained within the url.
         | 
| 7 | 
            +
                attr_reader :links
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                # Public: Create a new client
         | 
| 10 | 
            +
                #
         | 
| 11 | 
            +
                # url - The url you want us to crawl.
         | 
| 12 | 
            +
                def initialize(url)
         | 
| 13 | 
            +
                  @url = URI.parse(url)
         | 
| 14 | 
            +
                  @links ||= Set.new
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  unless Webmention::Client.valid_http_url? @url
         | 
| 17 | 
            +
                    raise ArgumentError.new "#{@url} is not a valid HTTP or HTTPS URI."
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # Public: Crawl the url this client was initialized with.
         | 
| 22 | 
            +
                #
         | 
| 23 | 
            +
                # Returns the number of links found.
         | 
| 24 | 
            +
                def crawl
         | 
| 25 | 
            +
                  @links ||= Set.new
         | 
| 26 | 
            +
                  if @url.nil?
         | 
| 27 | 
            +
                    raise ArgumentError.new "url is nil."
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  Nokogiri::HTML(open(self.url)).css('a').each do |link|
         | 
| 31 | 
            +
                    link = link.attribute('href').to_s
         | 
| 32 | 
            +
                    if Webmention::Client.valid_http_url? link
         | 
| 33 | 
            +
                      @links.add link
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  return @links.count
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                # Public: Sends mentions to each of the links found in the page.
         | 
| 41 | 
            +
                #
         | 
| 42 | 
            +
                # Returns the number of links mentioned.
         | 
| 43 | 
            +
                def send_mentions
         | 
| 44 | 
            +
                  if self.links.nil? or self.links.empty?
         | 
| 45 | 
            +
                    self.crawl
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  cnt = 0
         | 
| 49 | 
            +
                  self.links.each do |link|
         | 
| 50 | 
            +
                    endpoint = Webmention::Client.supports_webmention? link
         | 
| 51 | 
            +
                    if endpoint
         | 
| 52 | 
            +
                      cnt += 1 if Webmention::Client.send_mention endpoint, self.url, link
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  return cnt
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                # Public: Send a mention to an endoint about a link from a link.
         | 
| 60 | 
            +
                #
         | 
| 61 | 
            +
                # endpoint - URL to send mention to.
         | 
| 62 | 
            +
                # source - Source of mention (your page).
         | 
| 63 | 
            +
                # target - The link that was mentioned in the source page.
         | 
| 64 | 
            +
                #
         | 
| 65 | 
            +
                # Returns a boolean.
         | 
| 66 | 
            +
                def self.send_mention endpoint, source, target
         | 
| 67 | 
            +
                  data = {
         | 
| 68 | 
            +
                    :source => source,
         | 
| 69 | 
            +
                    :target => target,
         | 
| 70 | 
            +
                  }
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  uri = URI.parse(endpoint)
         | 
| 73 | 
            +
                  http = Net::HTTP.new(uri.host, uri.port)
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  request = Net::HTTP::Post.new(uri.request_uri)
         | 
| 76 | 
            +
                  request.set_form_data(data)
         | 
| 77 | 
            +
                  request['Content-Type'] = "application/x-www-form-urlencoded"
         | 
| 78 | 
            +
                  request['Accept'] = 'application/json'
         | 
| 79 | 
            +
                  response = http.request(request)
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  return response.code.to_i == 200
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                # Public: Fetch a url and check if it supports webmention
         | 
| 85 | 
            +
                #
         | 
| 86 | 
            +
                # url - URL to check
         | 
| 87 | 
            +
                #
         | 
| 88 | 
            +
                # Returns false if does not support webmention, returns string
         | 
| 89 | 
            +
                # of url to ping if it does.
         | 
| 90 | 
            +
                def self.supports_webmention? url
         | 
| 91 | 
            +
                  return false if !Webmention::Client.valid_http_url? url
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  doc = nil
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  begin
         | 
| 96 | 
            +
                    uri = URI.parse(url)
         | 
| 97 | 
            +
                    http = Net::HTTP.new(uri.host, uri.port)
         | 
| 98 | 
            +
                    http.open_timeout = 3 # in seconds
         | 
| 99 | 
            +
                    http.read_timeout = 3 # in seconds
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    request = Net::HTTP::Get.new(uri.request_uri)
         | 
| 102 | 
            +
                    # Send a user agent like a browser because some sites seem to reject requests made by non-browsers
         | 
| 103 | 
            +
                    request["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36 (https://rubygems.org/gems/webmention)"
         | 
| 104 | 
            +
                    request["Accept"] = "*/*"
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    response = http.request(request)
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                    # First check the HTTP Headers
         | 
| 109 | 
            +
                    if !response['Link'].nil? 
         | 
| 110 | 
            +
                      endpoint = self.discover_webmention_endpoint_from_header response['Link']
         | 
| 111 | 
            +
                      return endpoint if endpoint
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    # Do we support webmention?
         | 
| 115 | 
            +
                    endpoint = self.discover_webmention_endpoint_from_html response.body.to_s
         | 
| 116 | 
            +
                    return endpoint if endpoint
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                    # TODO: Move to supports_pingback? method
         | 
| 119 | 
            +
                    # Last chance, do we support Pingback?
         | 
| 120 | 
            +
                    # if !doc.css('link[rel="pingback"]').empty?
         | 
| 121 | 
            +
                    #   return doc.css('link[rel="pingback"]').attribute("href").value
         | 
| 122 | 
            +
                    # end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                  rescue EOFError
         | 
| 125 | 
            +
                  rescue Errno::ECONNRESET
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  return false
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                def self.discover_webmention_endpoint_from_html html
         | 
| 132 | 
            +
                  doc = Nokogiri::HTML(html)
         | 
| 133 | 
            +
                  if !doc.css('link[rel="webmention"]').empty?
         | 
| 134 | 
            +
                    doc.css('link[rel="webmention"]').attribute("href").value
         | 
| 135 | 
            +
                  elsif !doc.css('link[rel="http://webmention.org/"]').empty?
         | 
| 136 | 
            +
                    doc.css('link[rel="http://webmention.org/"]').attribute("href").value
         | 
| 137 | 
            +
                  elsif !doc.css('link[rel="http://webmention.org"]').empty?
         | 
| 138 | 
            +
                    doc.css('link[rel="http://webmention.org"]').attribute("href").value
         | 
| 139 | 
            +
                  else
         | 
| 140 | 
            +
                    false
         | 
| 141 | 
            +
                  end
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                def self.discover_webmention_endpoint_from_header header
         | 
| 145 | 
            +
                  if matches = header.match(%r{<(https?://[^>]+)>; rel="webmention"})
         | 
| 146 | 
            +
                    return matches[1]
         | 
| 147 | 
            +
                  elsif matches = header.match(%r{rel="webmention"; <(https?://[^>]+)>})
         | 
| 148 | 
            +
                    return matches[1]
         | 
| 149 | 
            +
                  elsif matches = header.match(%r{<(https?://[^>]+)>; rel="http://webmention\.org/?"})
         | 
| 150 | 
            +
                    return matches[1]
         | 
| 151 | 
            +
                  elsif matches = header.match(%r{rel="http://webmention\.org/?"; <(https?://[^>]+)>})
         | 
| 152 | 
            +
                    return matches[1]
         | 
| 153 | 
            +
                  end
         | 
| 154 | 
            +
                  return false
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                # Public: Use URI to parse a url and check if it is HTTP or HTTPS.
         | 
| 158 | 
            +
                #
         | 
| 159 | 
            +
                # url - URL to check
         | 
| 160 | 
            +
                #
         | 
| 161 | 
            +
                # Returns a boolean.
         | 
| 162 | 
            +
                def self.valid_http_url? url
         | 
| 163 | 
            +
                  if url.is_a? String
         | 
| 164 | 
            +
                    url = URI.parse(url)
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                  return (url.is_a? URI::HTTP or url.is_a? URI::HTTPS)
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
              end
         | 
| 170 | 
            +
            end
         | 
| @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            class SampleData
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def self.rel_webmention_href
         | 
| 4 | 
            +
                <<-eos
         | 
| 5 | 
            +
                  <html>
         | 
| 6 | 
            +
                    <head>
         | 
| 7 | 
            +
                      <link rel="webmention" href="http://webmention.io/example/webmention">
         | 
| 8 | 
            +
                    </head>
         | 
| 9 | 
            +
                  </html>
         | 
| 10 | 
            +
                eos
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def self.rel_href_webmention
         | 
| 14 | 
            +
                <<-eos
         | 
| 15 | 
            +
                  <html>
         | 
| 16 | 
            +
                    <head>
         | 
| 17 | 
            +
                      <link href="http://webmention.io/example/webmention" rel="webmention">
         | 
| 18 | 
            +
                    </head>
         | 
| 19 | 
            +
                  </html>
         | 
| 20 | 
            +
                eos
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              def self.rel_webmention_org_href
         | 
| 24 | 
            +
                <<-eos
         | 
| 25 | 
            +
                  <html>
         | 
| 26 | 
            +
                    <head>
         | 
| 27 | 
            +
                      <link rel="http://webmention.org" href="http://webmention.io/example/webmention">
         | 
| 28 | 
            +
                    </head>
         | 
| 29 | 
            +
                  </html>
         | 
| 30 | 
            +
                eos
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def self.rel_href_webmention_org
         | 
| 34 | 
            +
                <<-eos
         | 
| 35 | 
            +
                  <html>
         | 
| 36 | 
            +
                    <head>
         | 
| 37 | 
            +
                      <link href="http://webmention.io/example/webmention" rel="http://webmention.org">
         | 
| 38 | 
            +
                    </head>
         | 
| 39 | 
            +
                  </html>
         | 
| 40 | 
            +
                eos
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def self.rel_webmention_org_slash_href
         | 
| 44 | 
            +
                <<-eos
         | 
| 45 | 
            +
                  <html>
         | 
| 46 | 
            +
                    <head>
         | 
| 47 | 
            +
                      <link rel="http://webmention.org/" href="http://webmention.io/example/webmention">
         | 
| 48 | 
            +
                    </head>
         | 
| 49 | 
            +
                  </html>
         | 
| 50 | 
            +
                eos
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              def self.rel_href_webmention_org_slash
         | 
| 54 | 
            +
                <<-eos
         | 
| 55 | 
            +
                  <html>
         | 
| 56 | 
            +
                    <head>
         | 
| 57 | 
            +
                      <link href="http://webmention.io/example/webmention" rel="http://webmention.org/">
         | 
| 58 | 
            +
                    </head>
         | 
| 59 | 
            +
                  </html>
         | 
| 60 | 
            +
                eos
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              def self.sample_source_post_html
         | 
| 64 | 
            +
                <<-eos
         | 
| 65 | 
            +
                  <html>
         | 
| 66 | 
            +
                    <head>
         | 
| 67 | 
            +
                      <title>Sample Post</title>
         | 
| 68 | 
            +
                    </head>
         | 
| 69 | 
            +
                    <body>
         | 
| 70 | 
            +
                      <p><a href="http://target.example.com/post/4">Link to Target 4</a></p>
         | 
| 71 | 
            +
                      <p><a href="http://target.example.com/post/5">Link to Target 5</a></p>
         | 
| 72 | 
            +
                    </body>
         | 
| 73 | 
            +
                  </html>
         | 
| 74 | 
            +
                eos
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require_relative '../../test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Webmention::Client do
         | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                WebMock.stub_request(:any, 'http://source.example.com/post/100').to_return(
         | 
| 6 | 
            +
                  :status => 200,
         | 
| 7 | 
            +
                  :body => SampleData.sample_source_post_html,
         | 
| 8 | 
            +
                  :headers => {}
         | 
| 9 | 
            +
                )
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                @client = Webmention::Client.new "http://source.example.com/post/100"
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              describe "#crawl" do
         | 
| 15 | 
            +
                describe "when a valid url" do
         | 
| 16 | 
            +
                  it "should return a count and list of links" do
         | 
| 17 | 
            +
                    @client.crawl.must_be :>, 0
         | 
| 18 | 
            +
                    @client.links.must_include 'http://target.example.com/post/4'
         | 
| 19 | 
            +
                    @client.links.must_include 'http://target.example.com/post/5'
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,88 @@ | |
| 1 | 
            +
            require_relative '../../test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Webmention::Client do
         | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                WebMock.stub_request(:any, 'http://example.com/header').to_return(
         | 
| 6 | 
            +
                  :status => 200,
         | 
| 7 | 
            +
                  :body => '<html>example</html>', 
         | 
| 8 | 
            +
                  :headers => {
         | 
| 9 | 
            +
                    'Link' => 'rel="webmention"; <http://webmention.io/example/webmention>'
         | 
| 10 | 
            +
                  }
         | 
| 11 | 
            +
                )
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                WebMock.stub_request(:any, 'http://example.com/html').to_return(
         | 
| 14 | 
            +
                  :status => 200,
         | 
| 15 | 
            +
                  :body => '<html><head><link rel="webmention" href="http://webmention.io/example/webmention"></head><body>example</body></html>'
         | 
| 16 | 
            +
                )
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                WebMock.stub_request(:any, 'http://example.com/none').to_return(
         | 
| 19 | 
            +
                  :status => 200,
         | 
| 20 | 
            +
                  :body => '<html><head></head><body>example</body></html>'
         | 
| 21 | 
            +
                )
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              describe "#discover_webmention_endpoint_from_url" do
         | 
| 25 | 
            +
                it "should find endpoint from html head" do
         | 
| 26 | 
            +
                  Webmention::Client.supports_webmention?("http://example.com/html").must_equal "http://webmention.io/example/webmention"
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                it "should find endpoint from http header" do
         | 
| 30 | 
            +
                  Webmention::Client.supports_webmention?("http://example.com/header").must_equal "http://webmention.io/example/webmention"
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                it "should return false when no endpoint found" do
         | 
| 34 | 
            +
                  Webmention::Client.supports_webmention?("http://example.com/none").must_equal false
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              describe "#discover_webmention_endpoint_from_string" do
         | 
| 39 | 
            +
                it "should find rel=webmention followed by href in header" do
         | 
| 40 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_header('rel="webmention"; <http://webmention.io/example/webmention>').must_equal "http://webmention.io/example/webmention"
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                it "should find href followed by rel=webmention in header" do
         | 
| 44 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_header('<http://webmention.io/example/webmention>; rel="webmention"').must_equal "http://webmention.io/example/webmention"
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                it "should find rel=http://webmention.org followed by href in header" do
         | 
| 48 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_header('rel="http://webmention.org"; <http://webmention.io/example/webmention>').must_equal "http://webmention.io/example/webmention"
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                it "should find href followed by rel=http://webmention.org in header" do
         | 
| 52 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_header('<http://webmention.io/example/webmention>; rel="http://webmention.org"').must_equal "http://webmention.io/example/webmention"
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                it "should find rel=http://webmention.org/ followed by href in header" do
         | 
| 56 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_header('rel="http://webmention.org/"; <http://webmention.io/example/webmention>').must_equal "http://webmention.io/example/webmention"
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                it "should find href followed by rel=http://webmention.org/ in header" do
         | 
| 60 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_header('<http://webmention.io/example/webmention>; rel="http://webmention.org"').must_equal "http://webmention.io/example/webmention"
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                it "should find rel=webmention followed by href in html" do
         | 
| 64 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_href).must_equal "http://webmention.io/example/webmention"
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                it "should find href followed by rel=webmention in html" do
         | 
| 68 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_href_webmention).must_equal "http://webmention.io/example/webmention"
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                it "should find rel=http://webmention.org followed by href in html" do
         | 
| 72 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_org_href).must_equal "http://webmention.io/example/webmention"
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                it "should find href followed by rel=http://webmention.org in html" do
         | 
| 76 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_href_webmention_org).must_equal "http://webmention.io/example/webmention"
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                it "should find rel=http://webmention.org/ followed by href in html" do
         | 
| 80 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_org_slash_href).must_equal "http://webmention.io/example/webmention"
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                it "should find href followed by rel=http://webmention.org/ in html" do
         | 
| 84 | 
            +
                  Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_href_webmention_org_slash).must_equal "http://webmention.io/example/webmention"
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            end
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            require_relative '../../test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Webmention::Client do
         | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                WebMock.stub_request(:any, 'http://source.example.com/post/100').to_return(
         | 
| 6 | 
            +
                  :status => 200,
         | 
| 7 | 
            +
                  :body => SampleData.sample_source_post_html,
         | 
| 8 | 
            +
                  :headers => {}
         | 
| 9 | 
            +
                )
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                WebMock.stub_request(:any, 'http://target.example.com/post/4').to_return(
         | 
| 12 | 
            +
                  :status => 200,
         | 
| 13 | 
            +
                  :body => SampleData.rel_webmention_href,
         | 
| 14 | 
            +
                  :headers => {}
         | 
| 15 | 
            +
                )
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                WebMock.stub_request(:any, 'http://target.example.com/post/5').to_return(
         | 
| 18 | 
            +
                  :status => 200,
         | 
| 19 | 
            +
                  :body => '',
         | 
| 20 | 
            +
                  :headers => {
         | 
| 21 | 
            +
                    'Link' => 'rel="webmention"; <http://webmention.io/example/webmention>'
         | 
| 22 | 
            +
                  }
         | 
| 23 | 
            +
                )
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                WebMock.stub_request(:any, 'http://webmention.io/example/webmention').to_return(
         | 
| 26 | 
            +
                  :status => 200
         | 
| 27 | 
            +
                )
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                @client = Webmention::Client.new "http://source.example.com/post/100"
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              describe "#send_mentions" do
         | 
| 33 | 
            +
                it "should return number of mentions sent" do
         | 
| 34 | 
            +
                  @client = Webmention::Client.new "http://source.example.com/post/100"
         | 
| 35 | 
            +
                  @client.send_mentions.must_equal 2
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require_relative '../../test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Webmention::Client do
         | 
| 4 | 
            +
              describe "#new" do
         | 
| 5 | 
            +
                describe "when a valid url" do
         | 
| 6 | 
            +
                  it "should not throw an error for http" do
         | 
| 7 | 
            +
                    client = Webmention::Client.new "http://google.com"
         | 
| 8 | 
            +
                    client.url.must_equal URI.parse("http://google.com")
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  it "should not throw an error for https" do
         | 
| 12 | 
            +
                    client = Webmention::Client.new "https://google.com"
         | 
| 13 | 
            +
                    client.url.must_equal URI.parse("https://google.com")
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                describe "when an invalid url" do
         | 
| 18 | 
            +
                  it "should raise an error for ftp" do
         | 
| 19 | 
            +
                    lambda do
         | 
| 20 | 
            +
                      Webmention::Client.new "ftp://google.com"
         | 
| 21 | 
            +
                    end.must_raise(ArgumentError)
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  it "should raise an error for no protocol" do
         | 
| 25 | 
            +
                    lambda do
         | 
| 26 | 
            +
                      Webmention::Client.new "google.com"
         | 
| 27 | 
            +
                    end.must_raise(ArgumentError)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
    
        data/test/test_helper.rb
    ADDED
    
    
    
        data/webmention.gemspec
    ADDED
    
    | @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            lib = File.expand_path('../lib', __FILE__)
         | 
| 2 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 3 | 
            +
            require 'webmention/version'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Gem::Specification.new do |s|
         | 
| 6 | 
            +
              s.name          = 'webmention'
         | 
| 7 | 
            +
              s.version       = Webmention::VERSION
         | 
| 8 | 
            +
              s.date          = '2013-09-14'
         | 
| 9 | 
            +
              s.homepage      = 'https://github.com/indieweb/mention-client-ruby'
         | 
| 10 | 
            +
              s.summary       = 'A gem for sending webmention (and pingback) notifications'
         | 
| 11 | 
            +
              s.authors       = [
         | 
| 12 | 
            +
                'Aaron Parecki',
         | 
| 13 | 
            +
                'Nat Welch'
         | 
| 14 | 
            +
              ]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              s.email         = 'aaron@parecki.com'
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              s.files         = `git ls-files`.split($/)
         | 
| 19 | 
            +
              s.executables   = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 20 | 
            +
              s.test_files    = s.files.grep(%r{^(test|spec|features)/})
         | 
| 21 | 
            +
              s.require_paths = ['lib']
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              s.add_dependency 'json'
         | 
| 24 | 
            +
              s.add_dependency 'nokogiri'
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              s.add_development_dependency 'bundler', '~> 1.3'
         | 
| 27 | 
            +
              s.add_development_dependency 'rake'
         | 
| 28 | 
            +
              s.add_development_dependency 'minitest'
         | 
| 29 | 
            +
              s.add_development_dependency 'webmock'
         | 
| 30 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,15 +1,16 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: webmention
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| 8 8 | 
             
            - Aaron Parecki
         | 
| 9 | 
            +
            - Nat Welch
         | 
| 9 10 | 
             
            autorequire: 
         | 
| 10 11 | 
             
            bindir: bin
         | 
| 11 12 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013- | 
| 13 | 
            +
            date: 2013-09-14 00:00:00.000000000 Z
         | 
| 13 14 | 
             
            dependencies:
         | 
| 14 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 16 | 
             
              name: json
         | 
| @@ -28,7 +29,7 @@ dependencies: | |
| 28 29 | 
             
                  - !ruby/object:Gem::Version
         | 
| 29 30 | 
             
                    version: '0'
         | 
| 30 31 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 31 | 
            -
              name:  | 
| 32 | 
            +
              name: nokogiri
         | 
| 32 33 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 33 34 | 
             
                none: false
         | 
| 34 35 | 
             
                requirements:
         | 
| @@ -43,13 +44,93 @@ dependencies: | |
| 43 44 | 
             
                - - ! '>='
         | 
| 44 45 | 
             
                  - !ruby/object:Gem::Version
         | 
| 45 46 | 
             
                    version: '0'
         | 
| 47 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 48 | 
            +
              name: bundler
         | 
| 49 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 50 | 
            +
                none: false
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ~>
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '1.3'
         | 
| 55 | 
            +
              type: :development
         | 
| 56 | 
            +
              prerelease: false
         | 
| 57 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                none: false
         | 
| 59 | 
            +
                requirements:
         | 
| 60 | 
            +
                - - ~>
         | 
| 61 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 62 | 
            +
                    version: '1.3'
         | 
| 63 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 64 | 
            +
              name: rake
         | 
| 65 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 66 | 
            +
                none: false
         | 
| 67 | 
            +
                requirements:
         | 
| 68 | 
            +
                - - ! '>='
         | 
| 69 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 70 | 
            +
                    version: '0'
         | 
| 71 | 
            +
              type: :development
         | 
| 72 | 
            +
              prerelease: false
         | 
| 73 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 74 | 
            +
                none: false
         | 
| 75 | 
            +
                requirements:
         | 
| 76 | 
            +
                - - ! '>='
         | 
| 77 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 78 | 
            +
                    version: '0'
         | 
| 79 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 80 | 
            +
              name: minitest
         | 
| 81 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 82 | 
            +
                none: false
         | 
| 83 | 
            +
                requirements:
         | 
| 84 | 
            +
                - - ! '>='
         | 
| 85 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 86 | 
            +
                    version: '0'
         | 
| 87 | 
            +
              type: :development
         | 
| 88 | 
            +
              prerelease: false
         | 
| 89 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 90 | 
            +
                none: false
         | 
| 91 | 
            +
                requirements:
         | 
| 92 | 
            +
                - - ! '>='
         | 
| 93 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 94 | 
            +
                    version: '0'
         | 
| 95 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 96 | 
            +
              name: webmock
         | 
| 97 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 98 | 
            +
                none: false
         | 
| 99 | 
            +
                requirements:
         | 
| 100 | 
            +
                - - ! '>='
         | 
| 101 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 102 | 
            +
                    version: '0'
         | 
| 103 | 
            +
              type: :development
         | 
| 104 | 
            +
              prerelease: false
         | 
| 105 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 106 | 
            +
                none: false
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - ! '>='
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: '0'
         | 
| 46 111 | 
             
            description: 
         | 
| 47 112 | 
             
            email: aaron@parecki.com
         | 
| 48 113 | 
             
            executables: []
         | 
| 49 114 | 
             
            extensions: []
         | 
| 50 115 | 
             
            extra_rdoc_files: []
         | 
| 51 116 | 
             
            files:
         | 
| 117 | 
            +
            - .gitignore
         | 
| 118 | 
            +
            - .travis.yml
         | 
| 119 | 
            +
            - Gemfile
         | 
| 120 | 
            +
            - README.md
         | 
| 121 | 
            +
            - Rakefile
         | 
| 122 | 
            +
            - example.rb
         | 
| 52 123 | 
             
            - lib/webmention.rb
         | 
| 124 | 
            +
            - lib/webmention/client.rb
         | 
| 125 | 
            +
            - lib/webmention/version.rb
         | 
| 126 | 
            +
            - test/data/sample_html.rb
         | 
| 127 | 
            +
            - test/lib/webmention/crawl_test.rb
         | 
| 128 | 
            +
            - test/lib/webmention/discovery_test.rb
         | 
| 129 | 
            +
            - test/lib/webmention/mention_test.rb
         | 
| 130 | 
            +
            - test/lib/webmention/url_test.rb
         | 
| 131 | 
            +
            - test/lib/webmention/version_test.rb
         | 
| 132 | 
            +
            - test/test_helper.rb
         | 
| 133 | 
            +
            - webmention.gemspec
         | 
| 53 134 | 
             
            homepage: https://github.com/indieweb/mention-client-ruby
         | 
| 54 135 | 
             
            licenses: []
         | 
| 55 136 | 
             
            post_install_message: 
         | 
| @@ -74,5 +155,12 @@ rubygems_version: 1.8.23 | |
| 74 155 | 
             
            signing_key: 
         | 
| 75 156 | 
             
            specification_version: 3
         | 
| 76 157 | 
             
            summary: A gem for sending webmention (and pingback) notifications
         | 
| 77 | 
            -
            test_files: | 
| 158 | 
            +
            test_files:
         | 
| 159 | 
            +
            - test/data/sample_html.rb
         | 
| 160 | 
            +
            - test/lib/webmention/crawl_test.rb
         | 
| 161 | 
            +
            - test/lib/webmention/discovery_test.rb
         | 
| 162 | 
            +
            - test/lib/webmention/mention_test.rb
         | 
| 163 | 
            +
            - test/lib/webmention/url_test.rb
         | 
| 164 | 
            +
            - test/lib/webmention/version_test.rb
         | 
| 165 | 
            +
            - test/test_helper.rb
         | 
| 78 166 | 
             
            has_rdoc: 
         |