opengraphplus 0.1.6 → 0.1.7
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/README.md +106 -0
- data/lib/opengraphplus/minitest.rb +61 -0
- data/lib/opengraphplus/parser.rb +66 -0
- data/lib/opengraphplus/rspec.rb +75 -0
- data/lib/opengraphplus/verifier.rb +46 -0
- data/lib/opengraphplus/version.rb +1 -1
- data/lib/opengraphplus.rb +7 -4
- data/lib/rails/commands/opengraph/opengraph_command.rb +63 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76feb6f71feac815baf6dc136ba5653801e84048adb3ca77d9dffe59d76004be
|
|
4
|
+
data.tar.gz: a7177af1e7c9f4ec5844ddc66602c75420b07c15a9f3b266e772bfdd093984f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b8be6792864e32d690507fc03afb246e4a0ffa5ddf0caf75289352a9b54070d2de89845ea0236edad762c562174fa68c4b46ebc567d71fa8a223726a9a7af06
|
|
7
|
+
data.tar.gz: 678c88ffc101a8720d29c8dbbc6156f16adf8fb2a28c263b8f025fd431dc61da4167bc5719aa533a87a66412fcff37d26944f9e80c94623f1e48bb4249431efd
|
data/README.md
CHANGED
|
@@ -68,6 +68,112 @@ OpenGraphPlus.configure do |config|
|
|
|
68
68
|
end
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
## Verifying OpenGraph Tags
|
|
72
|
+
|
|
73
|
+
You can verify that your pages have the required OpenGraph tags using the included command:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
rails opengraph:verify http://localhost:3000
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This will fetch the URL and check for required tags (`og:title`, `og:type`, `og:image`, `og:url`), displaying any missing required or recommended tags:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Verifying OpenGraph tags at http://localhost:3000...
|
|
83
|
+
|
|
84
|
+
Found tags:
|
|
85
|
+
og:title → "My Awesome Site"
|
|
86
|
+
og:type → "website"
|
|
87
|
+
og:image → "https://example.com/image.png"
|
|
88
|
+
og:url → "http://localhost:3000"
|
|
89
|
+
|
|
90
|
+
✓ All required OpenGraph tags present
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The command exits with code 0 on success, or 1 if required tags are missing.
|
|
94
|
+
|
|
95
|
+
## Testing
|
|
96
|
+
|
|
97
|
+
OpenGraphPlus provides test helpers for both RSpec and Minitest to verify OpenGraph tags in your test suite.
|
|
98
|
+
|
|
99
|
+
### RSpec
|
|
100
|
+
|
|
101
|
+
Add to your `spec/spec_helper.rb` or `spec/rails_helper.rb`:
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
require 'opengraphplus/rspec'
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Then use the matchers in your specs:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
RSpec.describe "Home page", type: :request do
|
|
111
|
+
it "has all required OpenGraph tags" do
|
|
112
|
+
get "/"
|
|
113
|
+
expect(response.body).to have_open_graph_tags
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "has the correct title" do
|
|
117
|
+
get "/"
|
|
118
|
+
expect(response.body).to have_og_tag("og:title").with_content("My Site")
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "has an og:image tag" do
|
|
122
|
+
get "/"
|
|
123
|
+
expect(response.body).to have_og_tag("og:image")
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Available matchers:
|
|
129
|
+
- `have_open_graph_tags` - Passes if all required OG tags are present
|
|
130
|
+
- `have_og_tag("og:title")` - Passes if the specified tag exists
|
|
131
|
+
- `have_og_tag("og:title").with_content("My Title")` - Passes if the tag has the expected content
|
|
132
|
+
|
|
133
|
+
### Minitest
|
|
134
|
+
|
|
135
|
+
Add to your test helper:
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
require 'opengraphplus/minitest'
|
|
139
|
+
|
|
140
|
+
class ActiveSupport::TestCase
|
|
141
|
+
include OpenGraphPlus::Minitest
|
|
142
|
+
end
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Then use the assertions in your tests:
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
class HomePageTest < ActionDispatch::IntegrationTest
|
|
149
|
+
test "has all required OpenGraph tags" do
|
|
150
|
+
get "/"
|
|
151
|
+
assert_open_graph_tags(response.body)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
test "has the correct title" do
|
|
155
|
+
get "/"
|
|
156
|
+
assert_og_tag(response.body, "og:title", "My Site")
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
test "has an og:image tag" do
|
|
160
|
+
get "/"
|
|
161
|
+
assert_og_tag(response.body, "og:image")
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
test "does not have private tags" do
|
|
165
|
+
get "/"
|
|
166
|
+
refute_og_tag(response.body, "og:private")
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Available assertions:
|
|
172
|
+
- `assert_open_graph_tags(html)` - Passes if all required OG tags are present
|
|
173
|
+
- `assert_og_tag(html, "og:title")` - Passes if the specified tag exists
|
|
174
|
+
- `assert_og_tag(html, "og:title", "My Title")` - Passes if the tag has the expected content
|
|
175
|
+
- `refute_og_tag(html, "og:private")` - Passes if the specified tag does not exist
|
|
176
|
+
|
|
71
177
|
## Development
|
|
72
178
|
|
|
73
179
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "opengraphplus"
|
|
4
|
+
|
|
5
|
+
module OpenGraphPlus
|
|
6
|
+
module Minitest
|
|
7
|
+
# Assert that all required OpenGraph tags are present
|
|
8
|
+
#
|
|
9
|
+
# @param html [String] The HTML to check
|
|
10
|
+
# @param message [String, nil] Custom failure message
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# assert_open_graph_tags(response.body)
|
|
14
|
+
#
|
|
15
|
+
def assert_open_graph_tags(html, message = nil)
|
|
16
|
+
parser = OpenGraphPlus::Parser.new(html)
|
|
17
|
+
message ||= "Expected HTML to have all required OpenGraph tags, but missing: #{parser.errors.join(', ')}"
|
|
18
|
+
assert parser.valid?, message
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Assert that a specific OpenGraph/Twitter tag is present
|
|
22
|
+
#
|
|
23
|
+
# @param html [String] The HTML to check
|
|
24
|
+
# @param property [String] The tag property (e.g., "og:title")
|
|
25
|
+
# @param content [String, nil] Expected content (optional)
|
|
26
|
+
# @param message [String, nil] Custom failure message
|
|
27
|
+
#
|
|
28
|
+
# @example
|
|
29
|
+
# assert_og_tag(response.body, "og:title")
|
|
30
|
+
# assert_og_tag(response.body, "og:title", "My Title")
|
|
31
|
+
#
|
|
32
|
+
def assert_og_tag(html, property, content = nil, message = nil)
|
|
33
|
+
parser = OpenGraphPlus::Parser.new(html)
|
|
34
|
+
actual_content = parser[property]
|
|
35
|
+
|
|
36
|
+
if content.nil?
|
|
37
|
+
message ||= "Expected HTML to have #{property} tag, but it was not found"
|
|
38
|
+
assert !actual_content.nil?, message
|
|
39
|
+
else
|
|
40
|
+
message ||= "Expected #{property} to have content #{content.inspect}, but got #{actual_content.inspect}"
|
|
41
|
+
assert_equal content, actual_content, message
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Assert that a specific OpenGraph/Twitter tag is NOT present
|
|
46
|
+
#
|
|
47
|
+
# @param html [String] The HTML to check
|
|
48
|
+
# @param property [String] The tag property (e.g., "og:title")
|
|
49
|
+
# @param message [String, nil] Custom failure message
|
|
50
|
+
#
|
|
51
|
+
# @example
|
|
52
|
+
# refute_og_tag(response.body, "og:private")
|
|
53
|
+
#
|
|
54
|
+
def refute_og_tag(html, property, message = nil)
|
|
55
|
+
parser = OpenGraphPlus::Parser.new(html)
|
|
56
|
+
actual_content = parser[property]
|
|
57
|
+
message ||= "Expected HTML not to have #{property} tag, but it was found with content #{actual_content.inspect}"
|
|
58
|
+
assert actual_content.nil?, message
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "nokogiri"
|
|
4
|
+
|
|
5
|
+
module OpenGraphPlus
|
|
6
|
+
class Parser
|
|
7
|
+
REQUIRED_TAGS = %w[og:title og:type og:image og:url].freeze
|
|
8
|
+
RECOMMENDED_TAGS = %w[og:description og:site_name twitter:card twitter:title twitter:image].freeze
|
|
9
|
+
|
|
10
|
+
attr_reader :html
|
|
11
|
+
|
|
12
|
+
def initialize(html)
|
|
13
|
+
@html = html.to_s
|
|
14
|
+
@tags = parse_meta_tags
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def og_tags
|
|
18
|
+
@tags.select { |key, _| key.start_with?("og:") }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def twitter_tags
|
|
22
|
+
@tags.select { |key, _| key.start_with?("twitter:") }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def all_tags
|
|
26
|
+
@tags.dup
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def [](property)
|
|
30
|
+
@tags[property]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def valid?
|
|
34
|
+
errors.empty?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def errors
|
|
38
|
+
REQUIRED_TAGS.reject { |tag| @tags.key?(tag) }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def warnings
|
|
42
|
+
RECOMMENDED_TAGS.reject { |tag| @tags.key?(tag) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def parse_meta_tags
|
|
48
|
+
doc = Nokogiri::HTML(@html)
|
|
49
|
+
tags = {}
|
|
50
|
+
|
|
51
|
+
doc.css("meta[property^='og:'], meta[name^='og:']").each do |meta|
|
|
52
|
+
property = meta["property"] || meta["name"]
|
|
53
|
+
content = meta["content"]
|
|
54
|
+
tags[property] = content if property && content
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
doc.css("meta[property^='twitter:'], meta[name^='twitter:']").each do |meta|
|
|
58
|
+
property = meta["property"] || meta["name"]
|
|
59
|
+
content = meta["content"]
|
|
60
|
+
tags[property] = content if property && content
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
tags
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "opengraphplus"
|
|
4
|
+
require "rspec/expectations"
|
|
5
|
+
|
|
6
|
+
module OpenGraphPlus
|
|
7
|
+
module RSpec
|
|
8
|
+
extend ::RSpec::Matchers::DSL
|
|
9
|
+
|
|
10
|
+
# Matches if all required OpenGraph tags are present
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# expect(response.body).to have_open_graph_tags
|
|
14
|
+
#
|
|
15
|
+
matcher :have_open_graph_tags do
|
|
16
|
+
match do |html|
|
|
17
|
+
@parser = OpenGraphPlus::Parser.new(html)
|
|
18
|
+
@parser.valid?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
failure_message do
|
|
22
|
+
"expected HTML to have all required OpenGraph tags, but missing: #{@parser.errors.join(', ')}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
failure_message_when_negated do
|
|
26
|
+
"expected HTML not to have all required OpenGraph tags, but all were present"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Matches if a specific OpenGraph/Twitter tag is present
|
|
31
|
+
#
|
|
32
|
+
# @example
|
|
33
|
+
# expect(response.body).to have_og_tag("og:title")
|
|
34
|
+
# expect(response.body).to have_og_tag("og:title").with_content("My Title")
|
|
35
|
+
#
|
|
36
|
+
matcher :have_og_tag do |property|
|
|
37
|
+
chain :with_content do |expected_content|
|
|
38
|
+
@expected_content = expected_content
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
match do |html|
|
|
42
|
+
@parser = OpenGraphPlus::Parser.new(html)
|
|
43
|
+
@actual_content = @parser[property]
|
|
44
|
+
|
|
45
|
+
if @actual_content.nil?
|
|
46
|
+
false
|
|
47
|
+
elsif @expected_content
|
|
48
|
+
@actual_content == @expected_content
|
|
49
|
+
else
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
failure_message do
|
|
55
|
+
if @actual_content.nil?
|
|
56
|
+
"expected HTML to have #{property} tag, but it was not found"
|
|
57
|
+
else
|
|
58
|
+
"expected #{property} to have content #{@expected_content.inspect}, but got #{@actual_content.inspect}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
failure_message_when_negated do
|
|
63
|
+
if @expected_content
|
|
64
|
+
"expected #{property} not to have content #{@expected_content.inspect}, but it did"
|
|
65
|
+
else
|
|
66
|
+
"expected HTML not to have #{property} tag, but it was found with content #{@actual_content.inspect}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
RSpec.configure do |config|
|
|
74
|
+
config.include OpenGraphPlus::RSpec
|
|
75
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "uri"
|
|
5
|
+
|
|
6
|
+
module OpenGraphPlus
|
|
7
|
+
class Verifier
|
|
8
|
+
class FetchError < Error; end
|
|
9
|
+
|
|
10
|
+
MAX_REDIRECTS = 5
|
|
11
|
+
|
|
12
|
+
attr_reader :url
|
|
13
|
+
|
|
14
|
+
def initialize(url)
|
|
15
|
+
@url = url
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def verify
|
|
19
|
+
html = fetch_html
|
|
20
|
+
Parser.new(html)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def fetch_html(redirect_count = 0)
|
|
26
|
+
raise FetchError, "Too many redirects" if redirect_count > MAX_REDIRECTS
|
|
27
|
+
|
|
28
|
+
uri = URI.parse(@url)
|
|
29
|
+
response = Net::HTTP.get_response(uri)
|
|
30
|
+
|
|
31
|
+
case response
|
|
32
|
+
when Net::HTTPSuccess
|
|
33
|
+
response.body
|
|
34
|
+
when Net::HTTPRedirection
|
|
35
|
+
@url = response["location"]
|
|
36
|
+
fetch_html(redirect_count + 1)
|
|
37
|
+
else
|
|
38
|
+
raise FetchError, "HTTP #{response.code}: #{response.message}"
|
|
39
|
+
end
|
|
40
|
+
rescue URI::InvalidURIError => e
|
|
41
|
+
raise FetchError, "Invalid URL: #{e.message}"
|
|
42
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::ETIMEDOUT => e
|
|
43
|
+
raise FetchError, "Connection failed: #{e.message}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/opengraphplus.rb
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "opengraphplus/version"
|
|
4
|
+
|
|
5
|
+
module OpenGraphPlus
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
end
|
|
8
|
+
|
|
4
9
|
require_relative "opengraphplus/api_key"
|
|
5
10
|
require_relative "opengraphplus/configuration"
|
|
6
11
|
require_relative "opengraphplus/signature"
|
|
7
12
|
require_relative "opengraphplus/tag"
|
|
8
13
|
require_relative "opengraphplus/namespace"
|
|
9
14
|
require_relative "opengraphplus/image_generator"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Error < StandardError; end
|
|
13
|
-
end
|
|
15
|
+
require_relative "opengraphplus/parser"
|
|
16
|
+
require_relative "opengraphplus/verifier"
|
|
14
17
|
|
|
15
18
|
require_relative "opengraphplus/rails" if defined?(::Rails::Railtie)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/command"
|
|
4
|
+
|
|
5
|
+
module Rails
|
|
6
|
+
module Command
|
|
7
|
+
class OpengraphCommand < Base
|
|
8
|
+
namespace "opengraph"
|
|
9
|
+
|
|
10
|
+
desc "verify URL", "Verify OpenGraph tags at a URL"
|
|
11
|
+
def verify(url)
|
|
12
|
+
require "opengraphplus"
|
|
13
|
+
|
|
14
|
+
say "Verifying OpenGraph tags at #{url}..."
|
|
15
|
+
say ""
|
|
16
|
+
|
|
17
|
+
begin
|
|
18
|
+
parser = OpenGraphPlus::Verifier.new(url).verify
|
|
19
|
+
rescue OpenGraphPlus::Verifier::FetchError => e
|
|
20
|
+
say_error e.message
|
|
21
|
+
exit 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
tags = parser.all_tags
|
|
25
|
+
|
|
26
|
+
if tags.any?
|
|
27
|
+
say "Found tags:"
|
|
28
|
+
max_key_length = tags.keys.map(&:length).max
|
|
29
|
+
tags.each do |property, content|
|
|
30
|
+
say " #{property.ljust(max_key_length)} → #{content.inspect}"
|
|
31
|
+
end
|
|
32
|
+
say ""
|
|
33
|
+
else
|
|
34
|
+
say "No OpenGraph or Twitter tags found."
|
|
35
|
+
say ""
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
if parser.errors.any?
|
|
39
|
+
say "Missing required tags:"
|
|
40
|
+
parser.errors.each do |tag|
|
|
41
|
+
say " ✗ #{tag}"
|
|
42
|
+
end
|
|
43
|
+
say ""
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if parser.warnings.any?
|
|
47
|
+
say "Missing recommended tags:"
|
|
48
|
+
parser.warnings.each do |tag|
|
|
49
|
+
say " - #{tag}"
|
|
50
|
+
end
|
|
51
|
+
say ""
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if parser.valid?
|
|
55
|
+
say "✓ All required OpenGraph tags present"
|
|
56
|
+
else
|
|
57
|
+
say "Verification failed: #{parser.errors.length} required tag(s) missing"
|
|
58
|
+
exit 1
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opengraphplus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brad Gessler
|
|
@@ -47,7 +47,9 @@ files:
|
|
|
47
47
|
- lib/opengraphplus/api_key.rb
|
|
48
48
|
- lib/opengraphplus/configuration.rb
|
|
49
49
|
- lib/opengraphplus/image_generator.rb
|
|
50
|
+
- lib/opengraphplus/minitest.rb
|
|
50
51
|
- lib/opengraphplus/namespace.rb
|
|
52
|
+
- lib/opengraphplus/parser.rb
|
|
51
53
|
- lib/opengraphplus/rails.rb
|
|
52
54
|
- lib/opengraphplus/rails/controller.rb
|
|
53
55
|
- lib/opengraphplus/rails/helper.rb
|
|
@@ -55,13 +57,16 @@ files:
|
|
|
55
57
|
- lib/opengraphplus/rails/signature.rb
|
|
56
58
|
- lib/opengraphplus/rails/signature/routes.rb
|
|
57
59
|
- lib/opengraphplus/rails/signature/scope.rb
|
|
60
|
+
- lib/opengraphplus/rspec.rb
|
|
58
61
|
- lib/opengraphplus/signature.rb
|
|
59
62
|
- lib/opengraphplus/signature/generator.rb
|
|
60
63
|
- lib/opengraphplus/signature/url.rb
|
|
61
64
|
- lib/opengraphplus/signature/verifier.rb
|
|
62
65
|
- lib/opengraphplus/tag.rb
|
|
63
66
|
- lib/opengraphplus/tags.rb
|
|
67
|
+
- lib/opengraphplus/verifier.rb
|
|
64
68
|
- lib/opengraphplus/version.rb
|
|
69
|
+
- lib/rails/commands/opengraph/opengraph_command.rb
|
|
65
70
|
- sig/open_graph_plus.rbs
|
|
66
71
|
homepage: https://opengraphplus.com/ruby
|
|
67
72
|
licenses:
|