indieweb-authorship 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b71984e99aeca13f5754a3c35a571d6c67bef092e5bc95d5fe8a9cdb3cb8619a
4
+ data.tar.gz: ad55b917bc0b0c38a02255fe7441b737dff97656b131cf7d7754e5cf08917f4d
5
+ SHA512:
6
+ metadata.gz: 0a635d08bb9e1989d3800e28fe142297ddf9aeb170ea0ff18d168763f28a63d2108fe415df350c0b16cb4e97a41b06f7a922d6752d964306119b01f490063e06
7
+ data.tar.gz: 0ebacadded5c1ad1b0d43d552ccf8129b80250da37d65fd8527ba1b1c0efca68c7a20fda9781f78cad6eb15ce25b196c9f9bde2ffa52557b67a5057d458fd130
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2019-10-15
10
+
11
+ ### Added
12
+ - Initial release.
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at coc+authorship@deeden.co.uk. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in indieweb-authorship.gemspec
6
+ gemspec
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ indieweb-authorship (0.1.0)
5
+ microformats (~> 4.0, >= 4.1.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.3)
11
+ json (2.2.0)
12
+ microformats (4.1.0)
13
+ json (~> 2.1)
14
+ nokogiri (~> 1.8, >= 1.8.3)
15
+ mini_portile2 (2.4.0)
16
+ nokogiri (1.10.4)
17
+ mini_portile2 (~> 2.4.0)
18
+ rake (12.3.1)
19
+ rspec (3.7.0)
20
+ rspec-core (~> 3.7.0)
21
+ rspec-expectations (~> 3.7.0)
22
+ rspec-mocks (~> 3.7.0)
23
+ rspec-core (3.7.1)
24
+ rspec-support (~> 3.7.0)
25
+ rspec-expectations (3.7.0)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.7.0)
28
+ rspec-mocks (3.7.0)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.7.0)
31
+ rspec-support (3.7.1)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ bundler (~> 1.16)
38
+ indieweb-authorship!
39
+ rake (~> 12.3)
40
+ rspec (~> 3.0)
41
+
42
+ BUNDLED WITH
43
+ 1.17.3
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Stephen Rushe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ # Indieweb::Authorship
2
+
3
+ Indieweb::Authorship is a Ruby gem for identifying the author of an IndieWeb post using the [authorship algorithm](http://indieweb.org/authorship#How_to_determine).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'indieweb-authorship'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install indieweb-authorship
20
+
21
+ ## Usage
22
+
23
+ ### From a URL
24
+
25
+ You can simply provide a URL and the page will be retrieved before authorship is determined.
26
+
27
+ ```ruby
28
+ author = Indieweb::Authorship.identify(url)
29
+ ```
30
+
31
+ ### With pre-downloaded html (from a URL)
32
+
33
+ It is also possible to provide the html directly, along with the URL, in cases where you already have the page.
34
+
35
+ ```ruby
36
+ author = Indieweb::Authorship.identify(url, html)
37
+ ```
38
+
39
+ ## Output
40
+
41
+ If an author is identified then the output will be a hash containing the fields `name` (for the name of the author), `photo` (with a url for a photo of the author), and `url` (with a url for the page of the author). Some of these may be `nil`, but all will still be provided. If no author can be identified then the output will simply be a `nil`.
42
+
43
+ ## Contributing
44
+
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/srushe/indieweb-authorship.
46
+
47
+ ## License
48
+
49
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
50
+
51
+ ## Code of Conduct
52
+
53
+ Everyone interacting in the Indieweb::Authorship project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/srushe/indieweb-authorship/blob/master/CODE_OF_CONDUCT.md).
54
+
55
+ ## Credits
56
+
57
+ A number of the spec example files are from...
58
+
59
+ * https://github.com/aaronpk/XRay/tree/master/tests/data/author.example.com
60
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "indieweb/authorship"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,36 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "indieweb/authorship/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "indieweb-authorship"
7
+ spec.version = Indieweb::Authorship::VERSION
8
+ spec.authors = ["Stephen Rushe"]
9
+ spec.email = ["steve+authorship@deeden.co.uk"]
10
+
11
+ spec.summary = 'Identify the author of an IndieWeb post'
12
+ spec.description = 'Identify the author of an IndieWeb post using the Authorship algorithm'
13
+ spec.homepage = "https://github.com/srushe/indieweb-authorship"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/srushe/indieweb-authorship/issues',
18
+ 'changelog_uri' => 'https://github.com/srushe/indieweb-authorship/blob/master/CHANGELOG.md',
19
+ 'homepage_uri' => 'https://github.com/srushe/indieweb-authorship/'
20
+ }
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_runtime_dependency "microformats", "~> 4.0", ">= 4.1.0"
32
+
33
+ spec.add_development_dependency "bundler", "~> 1.16"
34
+ spec.add_development_dependency "rake", "~> 12.3"
35
+ spec.add_development_dependency "rspec", "~> 3.0"
36
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'indieweb/authorship/version'
4
+ require 'microformats'
5
+ require 'net/http'
6
+
7
+ module Indieweb
8
+ module Authorship
9
+ def self.identify(url, html = nil)
10
+ collection = microformats_from(html: html, url: url)
11
+
12
+ # 1. start with a particular h-entry to determine authorship for, and
13
+ # no author. if no h-entry, then there's no post to find authorship
14
+ # for, abort.
15
+ h_entry = hentry_from(collection['items'])
16
+ return if h_entry.nil?
17
+
18
+ # 3. if the h-entry has an author property, use that
19
+ if h_entry['properties'].key?('author')
20
+ author_data = h_entry['properties']['author']
21
+ end
22
+
23
+ # 4. otherwise if the h-entry has a parent h-feed with author property
24
+ # use that - TODO
25
+ if author_data.nil?
26
+ author_data = h_feed_author_for(h_entry, items: collection['items'])
27
+ end
28
+
29
+ # 5. if an author property was found
30
+ unless author_data.nil?
31
+ hcard = author_data.find { |entry| hcard?(entry) }
32
+
33
+ # 5.1. if it has an h-card, use it, exit.
34
+ if !hcard.nil?
35
+ return hcard_data_for(
36
+ URI.join(url, hcard['properties']['url'][0]).to_s,
37
+ hcard['properties']['name'][0],
38
+ URI.join(url, hcard['properties']['photo'][0]).to_s
39
+ )
40
+
41
+ # 5.2. otherwise if author property is an http(s) URL, let the
42
+ # author-page have that URL
43
+ elsif author_data[0].start_with?('http://', 'https://')
44
+ return find_author_from(url: author_data[0],
45
+ original_page_items: collection['items'])
46
+
47
+ # 5.3. otherwise use the author property as the author name, exit
48
+ else
49
+ return hcard_data_for(nil, author_data[0], nil)
50
+ end
51
+ end
52
+
53
+ # 6. if there is no author-page and the h-entry's page is a permalink
54
+ # page, then
55
+ # 6.1. if the page has a rel-author link, let the author-page's URL
56
+ # be the href of the rel-author link
57
+
58
+ # 7. if there is an author-page URL
59
+ return unless collection['rels'].key?('author')
60
+
61
+ find_author_from(url: collection['rels']['author'][0],
62
+ original_page_items: collection['items'])
63
+ end
64
+
65
+ def self.microformats_from(html: nil, url:)
66
+ html ||= Net::HTTP.get(URI(url))
67
+ ::Microformats.parse(html, base: url)
68
+ end
69
+ private_class_method :microformats_from
70
+
71
+ def self.hcard?(data)
72
+ data.is_a?(Hash) && data.key?('type') &&
73
+ data['type'].is_a?(Array) && data['type'].include?('h-card')
74
+ end
75
+ private_class_method :hcard?
76
+
77
+ def self.hentry_from(source)
78
+ h_entry = source.find { |item| item['type'][0] == 'h-entry' }
79
+ return h_entry unless h_entry.nil?
80
+ source.each do |item|
81
+ if item['type'][0] == 'h-feed' && item.key?('children') && item['children'][0]['type'][0] == 'h-entry'
82
+ return item['children'][0]
83
+ end
84
+ end
85
+
86
+ nil
87
+ end
88
+ private_class_method :hentry_from
89
+
90
+ def self.hcards_from(source)
91
+ source.select { |entry| hcard?(entry) }
92
+ end
93
+ private_class_method :hcards_from
94
+
95
+ def self.h_feed_author_for(h_entry, items:)
96
+ h_feed = items.find do |item|
97
+ item['type'][0] == 'h-feed' && item['children'].include?(h_entry)
98
+ end
99
+ return if h_feed.nil?
100
+
101
+ h_feed['properties']['author']
102
+ end
103
+ private_class_method :h_feed_author_for
104
+
105
+ def self.hcard_data_for(url, name, photo)
106
+ {
107
+ 'url' => url,
108
+ 'name' => name,
109
+ 'photo' => photo
110
+ }
111
+ end
112
+ private_class_method :hcard_data_for
113
+
114
+ def self.find_author_from(url:, original_page_items:)
115
+ # 7.1. get the author-page from that URL and parse it for microformats2
116
+ collection = microformats_from(url: url)
117
+
118
+ hcards = hcards_from(collection['items'])
119
+
120
+ # 7.2, 7.3, and 7.4
121
+ hcard_matching_url_uid_and_author_page(hcards, url) ||
122
+ hcard_matching_rel_me_link(hcards, url, collection['rels']) ||
123
+ hcard_matching_url_and_author_page_url(original_page_items, url)
124
+ end
125
+ private_class_method :find_author_from
126
+
127
+ # 7.2. if author-page has 1+ h-card with url == uid == author-page's
128
+ # URL, then use first such h-card, exit.
129
+ def self.cards_with_matching_url_and_uid(hcards)
130
+ hcards = hcards.collect { |card| card['properties'] }
131
+ hcards.select do |card|
132
+ card.key?('url') && card.key?('uid') &&
133
+ card['url'] == card['uid']
134
+ end
135
+ end
136
+ private_class_method :cards_with_matching_url_and_uid
137
+
138
+ def self.hcard_matching_url_uid_and_author_page(hcards = [], author_page)
139
+ return if hcards.empty? || author_page.nil?
140
+
141
+ cards_with_matching_url_and_uid = cards_with_matching_url_and_uid(hcards)
142
+ hcard = cards_with_matching_url_and_uid.find do |card|
143
+ card['url'].include?(author_page)
144
+ end
145
+ return if hcard.nil?
146
+
147
+ hcard_data_for(author_page, hcard['name'][0], hcard['photo'][0])
148
+ end
149
+ private_class_method :hcard_matching_url_uid_and_author_page
150
+
151
+ # 7.3. else if author-page has 1+ h-card with url property which
152
+ # matches the href of a rel-me link on the author-page (perhaps
153
+ # the same hyperlink element as the u-url, though not required
154
+ # to be), use first such h-card, exit.
155
+ def self.card_with_matching_rel_me_link(hcards, rels_me)
156
+ return if rels_me.nil?
157
+
158
+ hcards.find do |card|
159
+ !(card['properties']['url'] & rels_me).empty?
160
+ end
161
+ end
162
+ private_class_method :card_with_matching_rel_me_link
163
+
164
+ def self.hcard_matching_rel_me_link(hcards, url, rels = {})
165
+ hcard = card_with_matching_rel_me_link(hcards, rels['me'])
166
+ return if hcard.nil?
167
+
168
+ hcard_data_for(url,
169
+ hcard['properties']['name'][0],
170
+ hcard['properties']['photo'][0])
171
+ end
172
+ private_class_method :hcard_matching_rel_me_link
173
+
174
+ # 7.4. if the h-entry's page has 1+ h-card with url == author-page URL,
175
+ # use first such h-card, exit.
176
+ def self.hcard_matching_url_and_author_page_url(items, url)
177
+ hcard = hcards_from(items).find do |card|
178
+ card['properties']['url'].include?(url)
179
+ end
180
+
181
+ hcard_data_for(url,
182
+ hcard['properties']['name'][0],
183
+ hcard['properties']['photo'][0])
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,5 @@
1
+ module Indieweb
2
+ module Authorship
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: indieweb-authorship
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Rushe
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-10-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: microformats
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.1.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.1.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.16'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.16'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '12.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '12.3'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
75
+ description: Identify the author of an IndieWeb post using the Authorship algorithm
76
+ email:
77
+ - steve+authorship@deeden.co.uk
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".gitignore"
83
+ - ".rspec"
84
+ - CHANGELOG.md
85
+ - CODE_OF_CONDUCT.md
86
+ - Gemfile
87
+ - Gemfile.lock
88
+ - LICENSE.txt
89
+ - README.md
90
+ - Rakefile
91
+ - bin/console
92
+ - bin/setup
93
+ - indieweb-authorship.gemspec
94
+ - lib/indieweb/authorship.rb
95
+ - lib/indieweb/authorship/version.rb
96
+ homepage: https://github.com/srushe/indieweb-authorship
97
+ licenses:
98
+ - MIT
99
+ metadata:
100
+ bug_tracker_uri: https://github.com/srushe/indieweb-authorship/issues
101
+ changelog_uri: https://github.com/srushe/indieweb-authorship/blob/master/CHANGELOG.md
102
+ homepage_uri: https://github.com/srushe/indieweb-authorship/
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubygems_version: 3.0.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Identify the author of an IndieWeb post
122
+ test_files: []