opengraphplus 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d81eea129294b32cf86234cd7b7b5eab27f232a3782244561417740602fd6916
4
- data.tar.gz: 8a3c69fef1a8a1c208c966c30694b0f72e5bb51e24f6ad8f1a8dfa1feedece5a
3
+ metadata.gz: 8dd205094f9939db4ce18af7cae036bf08dbee2a31405a1b862fb7660974a68e
4
+ data.tar.gz: 258cc8781b405cb3b396123889a1a2c2b86bf913d12ad14081b2eae1e1ee3e95
5
5
  SHA512:
6
- metadata.gz: e4ea90d61ea5ac1af6dbbadff329d2a07f3d1cbc4e25507aa8bec00107cb8d836e3af1643e22c1d1ff47df0d31b703289d51fe1336419eee35343c91e752feab
7
- data.tar.gz: 5b83e6a271762efd1eaf8ca32eaa18ccfbc1c0d89dec33ef2602b9ad1663feba4ee46bbe43eb106a8e1150ceab6020b2f9cf26097a95183f0b8328e4fcb0199a
6
+ metadata.gz: f932e0b431882a31941d22ca4b30cfbf01ecec4ee7facd177d1e3009995b29ce866944fc549671e156ae4d1986762e35d11fb06af63738f2e5de627ea4e988fe
7
+ data.tar.gz: 1a1d51479377852b0794ef4e6884700fcec16662034574db964df7cfa74da90d048019b7b4a8cce21095b12ca45f156dc1ef7d3447a2bedb108c075ce8fd63ed
data/README.md CHANGED
@@ -28,7 +28,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
28
28
 
29
29
  ## Contributing
30
30
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/opengraphplus/gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/opengraphplus/gem/blob/main/CODE_OF_CONDUCT.md).
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/opengraphplus/ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/opengraphplus/ruby/blob/main/CODE_OF_CONDUCT.md).
32
32
 
33
33
  ## License
34
34
 
@@ -36,4 +36,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
36
36
 
37
37
  ## Code of Conduct
38
38
 
39
- Everyone interacting in the OpenGraphPlus project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/opengraphplus/gem/blob/main/CODE_OF_CONDUCT.md).
39
+ Everyone interacting in the OpenGraphPlus project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/opengraphplus/ruby/blob/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Opengraphplus
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Creates an OpenGraphPlus initializer file and adds default Open Graph tags to ApplicationController"
11
+
12
+ def copy_initializer
13
+ template "initializer.rb", "config/initializers/opengraphplus.rb"
14
+ end
15
+
16
+ def inject_into_application_controller
17
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController", <<-RUBY
18
+
19
+ open_graph do |og|
20
+ og.type = "website"
21
+ og.url = request.original_url
22
+ og.site_name = Rails.application.class.module_parent_name.titleize
23
+ end
24
+ RUBY
25
+ end
26
+
27
+ def show_readme
28
+ readme "README" if behavior == :invoke
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+
2
+ OpenGraphPlus has been installed!
3
+
4
+ Next steps:
5
+
6
+ 1. Add your API key to config/initializers/opengraphplus.rb
7
+ Get your API key at: https://opengraphplus.com/dashboard
8
+
9
+ 2. Add the helper to your layout file (e.g., app/views/layouts/application.html.erb):
10
+
11
+ <head>
12
+ <%%= open_graph_meta_tags %>
13
+ </head>
14
+
15
+ 3. Customize the default Open Graph tags in ApplicationController:
16
+
17
+ class ApplicationController < ActionController::Base
18
+ open_graph do |og|
19
+ og.type = "website"
20
+ og.url = request.original_url
21
+ og.site_name = "Your Site Name"
22
+ end
23
+ end
24
+
25
+ 4. Override tags in specific controllers (inherits from parent):
26
+
27
+ class ArticlesController < ApplicationController
28
+ before_action { @article = Article.find(params[:id]) }
29
+
30
+ open_graph do |og|
31
+ og.title = @article.title
32
+ og.description = @article.excerpt
33
+ og.type = "article"
34
+ end
35
+ end
36
+
37
+ 5. Set tags in views:
38
+
39
+ <%% open_graph do |og|
40
+ og.title = "My Page Title"
41
+ og.description = "My Page Description"
42
+ end %>
43
+
44
+ 6. Verify it works by checking your page source for og:image meta tags,
45
+ or use the preview tool at: https://opengraphplus.com/previews/new
46
+
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ OpenGraphPlus.configure do |config|
4
+ # Get your API key at https://opengraphplus.com/dashboard
5
+ config.api_key = Rails.application.credentials.opengraphplus_api_key
6
+ # Or use ENV:
7
+ # config.api_key = ENV["OPENGRAPHPLUS_API_KEY"]
8
+ end
@@ -1,8 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "open_graph_plus/version"
4
-
5
- module OpenGraphPlus
6
- class Error < StandardError; end
7
- # Your code goes here...
8
- end
3
+ require_relative "opengraphplus"
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+ require "json"
5
+ require "securerandom"
6
+
7
+ module OpenGraphPlus
8
+ class APIKey
9
+ NAMESPACE = "ogp"
10
+ PUBLIC_KEY_BYTES = 16 # 22 characters when base64 encoded
11
+ SECRET_KEY_BYTES = 32 # 43 characters when base64 encoded
12
+
13
+ attr_reader :public_key, :secret_key, :environment
14
+
15
+ def initialize(public_key:, secret_key:, environment: :live)
16
+ @public_key = public_key
17
+ @secret_key = secret_key
18
+ @environment = environment.to_sym
19
+ end
20
+
21
+ def to_s
22
+ { pk: public_key, sk: secret_key }
23
+ .to_json
24
+ .then { |json| Base64.urlsafe_encode64(json, padding: false) }
25
+ .then { |payload| [NAMESPACE, environment, payload].join("_") }
26
+ end
27
+
28
+ def live?
29
+ environment == :live
30
+ end
31
+
32
+ def test?
33
+ environment == :test
34
+ end
35
+
36
+ class << self
37
+ def generate(environment: :live)
38
+ new(
39
+ public_key: SecureRandom.urlsafe_base64(PUBLIC_KEY_BYTES),
40
+ secret_key: SecureRandom.urlsafe_base64(SECRET_KEY_BYTES),
41
+ environment: environment
42
+ )
43
+ end
44
+
45
+ def parse(encoded_key)
46
+ return nil unless encoded_key.is_a?(String)
47
+
48
+ case encoded_key.split("_", 3)
49
+ in [NAMESPACE, env, payload]
50
+ payload
51
+ .then { |p| Base64.urlsafe_decode64(p) }
52
+ .then { |json| JSON.parse(json) }
53
+ .then { |data| new(public_key: data["pk"], secret_key: data["sk"], environment: env) }
54
+ else
55
+ nil
56
+ end
57
+ rescue ArgumentError, JSON::ParserError
58
+ nil
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ class Configuration
5
+ attr_reader :api_key
6
+
7
+ def initialize
8
+ @api_key = nil
9
+ end
10
+
11
+ def api_key=(value)
12
+ @api_key = value.is_a?(APIKey) ? value : APIKey.parse(value)
13
+ end
14
+ end
15
+
16
+ class << self
17
+ def configuration
18
+ @configuration ||= Configuration.new
19
+ end
20
+
21
+ def configure
22
+ yield(configuration)
23
+ end
24
+
25
+ def reset_configuration!
26
+ @configuration = Configuration.new
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ class ImageGenerator
5
+ attr_reader :request
6
+
7
+ def initialize(request)
8
+ @request = request
9
+ @signature_url = Signature::URL.new
10
+ end
11
+
12
+ def url
13
+ @signature_url.build("/opengraph", url: request.original_url)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Rails
5
+ module Controller
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ helper_method :open_graph, :open_graph_tags, :open_graph_meta_tags
10
+ append_before_action :set_default_open_graph_image
11
+ end
12
+
13
+ class_methods do
14
+ def open_graph(&block)
15
+ before_action { instance_exec(open_graph, &block) }
16
+ end
17
+ end
18
+
19
+ def open_graph_image_generator
20
+ ImageGenerator.new(request)
21
+ end
22
+
23
+ private
24
+
25
+ def set_default_open_graph_image
26
+ return if open_graph.image.url
27
+
28
+ generated_url = open_graph_image_generator.url
29
+ open_graph.image.url = generated_url if generated_url
30
+ end
31
+
32
+ include Helper
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Rails
5
+ module Helper
6
+ def open_graph(**kwargs)
7
+ @open_graph_root ||= Tags::Root.new
8
+ @open_graph_root.update(**kwargs) if kwargs.any?
9
+ yield(@open_graph_root) if block_given?
10
+ @open_graph_root
11
+ end
12
+
13
+ def open_graph_tags
14
+ root = @open_graph_root || Tags::Root.new
15
+ Tags::Renderer.new(root).tags
16
+ end
17
+
18
+ def open_graph_meta_tags
19
+ result = open_graph_tags.map(&:to_s).join("\n")
20
+ result.respond_to?(:html_safe) ? result.html_safe : result
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/railtie"
4
+
5
+ module OpenGraphPlus
6
+ module Rails
7
+ class Railtie < ::Rails::Railtie
8
+ initializer "opengraphplus.helpers" do
9
+ ActiveSupport.on_load(:action_controller) do
10
+ include OpenGraphPlus::Rails::Controller
11
+ end
12
+
13
+ ActiveSupport.on_load(:action_view) do
14
+ include OpenGraphPlus::Rails::Helper
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Rails
5
+ module Signature
6
+ module Routes
7
+ extend ActiveSupport::Concern
8
+
9
+ # Access the signature verifier set up by Signature::Scope
10
+ #
11
+ # Usage:
12
+ # class ScreenshotsController < ApplicationController
13
+ # include OpenGraphPlus::Rails::Signature::Routes
14
+ #
15
+ # def show
16
+ # if signature_verifier&.public_key
17
+ # api_key = ApiKey.find_by(public_key: signature_verifier.public_key)
18
+ # if api_key && signature_verifier.valid?(api_key.secret_key)
19
+ # # success
20
+ # else
21
+ # # invalid signature
22
+ # end
23
+ # else
24
+ # # malformed signature
25
+ # end
26
+ # end
27
+ # end
28
+
29
+ def signature_verifier
30
+ request.env[ENV_KEY]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Rails
5
+ module Signature
6
+ class Scope
7
+ # Rails route constraint that sets up signature verification
8
+ # for controller to handle. Always matches so controller can
9
+ # decide how to handle errors (e.g., show fallback image).
10
+ #
11
+ # Usage in routes.rb:
12
+ # scope "signed/:signature", constraints: OpenGraphPlus::Rails::Signature::Scope.new do
13
+ # get "opengraph", to: "screenshots#show"
14
+ # end
15
+ #
16
+ # Then in controller:
17
+ # verifier = request.env["opengraphplus.verifier"]
18
+ # if verifier&.public_key
19
+ # api_key = ApiKey.find_by(public_key: verifier.public_key)
20
+ # if api_key && verifier.valid?(api_key.secret_key)
21
+ # # success
22
+ # else
23
+ # # invalid signature
24
+ # end
25
+ # else
26
+ # # malformed signature
27
+ # end
28
+
29
+ def initialize(param: :signature)
30
+ @param = param
31
+ end
32
+
33
+ def matches?(request)
34
+ signature = request.params[@param]
35
+ return true unless signature
36
+
37
+ path_and_query = build_path_and_query(request, signature)
38
+ verifier = OpenGraphPlus::Signature::Verifier.new(signature: signature, path_and_query: path_and_query)
39
+
40
+ request.env[ENV_KEY] = verifier
41
+
42
+ true
43
+ end
44
+
45
+ private
46
+
47
+ def build_path_and_query(request, signature)
48
+ # Find signature in path and take everything after it
49
+ request.path
50
+ .split(signature, 2)
51
+ .last
52
+ .then { |path| path.empty? ? "/" : path }
53
+ .then { |path| request.query_string.empty? ? path : "#{path}?#{request.query_string}" }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Rails
5
+ module Signature
6
+ ENV_KEY = "opengraphplus.verifier"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rails/helper"
4
+ require_relative "rails/controller"
5
+ require_relative "rails/signature"
6
+ require_relative "rails/signature/scope"
7
+ require_relative "rails/signature/routes"
8
+ require_relative "rails/railtie"
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "base64"
5
+
6
+ module OpenGraphPlus
7
+ module Signature
8
+ class Generator
9
+ attr_reader :api_key
10
+
11
+ def initialize(api_key)
12
+ @api_key = api_key
13
+ end
14
+
15
+ def generate(path_and_query)
16
+ path_and_query
17
+ .then { |data| OpenSSL::HMAC.digest(DIGEST_ALGORITHM, api_key.secret_key, data) }
18
+ .then { |hmac| hmac.byteslice(0, HMAC_BYTES) }
19
+ .then { |truncated| "#{api_key.public_key}:#{truncated}" }
20
+ .then { |payload| Base64.urlsafe_encode64(payload, padding: false) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module OpenGraphPlus
6
+ module Signature
7
+ class URL
8
+ DEFAULT_BASE_URL = "https://opengraphplus.com"
9
+ DEFAULT_PATH_PREFIX = "/v2/:signature"
10
+
11
+ attr_reader :base_uri, :path_prefix
12
+
13
+ def initialize(api_key: nil, generator: nil, base_url: nil, path_prefix: DEFAULT_PATH_PREFIX)
14
+ @api_key = api_key
15
+ @generator = generator
16
+ @base_uri = URI.parse(base_url || ENV.fetch("OPENGRAPHPLUS_URL", DEFAULT_BASE_URL))
17
+ @path_prefix = path_prefix
18
+ end
19
+
20
+ def build(path, **params)
21
+ return nil unless generator
22
+
23
+ path_and_query = build_path_and_query(path, params)
24
+ signature = generator.generate(path_and_query)
25
+
26
+ base_uri.dup.tap do |uri|
27
+ uri.path = signed_path(signature, path)
28
+ uri.query = URI.encode_www_form(params) unless params.empty?
29
+ end.to_s
30
+ end
31
+
32
+ def generator
33
+ @generator ||= begin
34
+ api_key = @api_key || OpenGraphPlus.configuration.api_key
35
+ if api_key
36
+ Generator.new(api_key)
37
+ else
38
+ warn_missing_api_key
39
+ nil
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def build_path_and_query(path, params)
47
+ normalized_path = File.join("/", path)
48
+ params.empty? ? normalized_path : "#{normalized_path}?#{URI.encode_www_form(params)}"
49
+ end
50
+
51
+ def signed_path(signature, path)
52
+ File.join(path_prefix.gsub(":signature", signature), path)
53
+ end
54
+
55
+ def warn_missing_api_key
56
+ return if @warned
57
+
58
+ warn "[OpenGraphPlus] API key not configured. Set OpenGraphPlus.configuration.api_key to enable automatic Open Graph image generation."
59
+ @warned = true
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "base64"
5
+
6
+ module OpenGraphPlus
7
+ module Signature
8
+ class Verifier
9
+ attr_reader :signature, :path_and_query
10
+
11
+ def initialize(signature:, path_and_query:)
12
+ @signature = signature
13
+ @path_and_query = path_and_query
14
+ end
15
+
16
+ def public_key
17
+ parsed[:public_key]
18
+ end
19
+
20
+ def valid?(secret_key)
21
+ expected_hmac = OpenSSL::HMAC.digest(DIGEST_ALGORITHM, secret_key, path_and_query)
22
+ truncated_expected = expected_hmac.byteslice(0, HMAC_BYTES)
23
+ actual_hmac = parsed[:hmac]
24
+
25
+ secure_compare(truncated_expected, actual_hmac)
26
+ end
27
+
28
+ private
29
+
30
+ def parsed
31
+ @parsed ||= signature
32
+ .then { |sig| Base64.urlsafe_decode64(sig) }
33
+ .then { |decoded| decoded.split(":", 2) }
34
+ .then { |public_key, hmac| { public_key: public_key, hmac: hmac } }
35
+ rescue ArgumentError
36
+ { public_key: nil, hmac: nil }
37
+ end
38
+
39
+ def secure_compare(a, b)
40
+ return false if a.nil? || b.nil?
41
+ return false if a.bytesize != b.bytesize
42
+
43
+ OpenSSL.fixed_length_secure_compare(a, b)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Signature
5
+ DIGEST_ALGORITHM = "SHA256"
6
+ HMAC_BYTES = 16 # Truncated HMAC length for shorter URLs
7
+ end
8
+ end
9
+
10
+ require_relative "signature/generator"
11
+ require_relative "signature/verifier"
12
+ require_relative "signature/url"
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+
5
+ module OpenGraphPlus
6
+ class Tag
7
+ attr_reader :property, :content
8
+
9
+ def initialize(property, content)
10
+ @property = property
11
+ @content = content
12
+ end
13
+
14
+ def meta
15
+ %(<meta property="#{escape property}" content="#{escape content}">)
16
+ end
17
+
18
+ def render_in(view_context = nil)
19
+ result = meta
20
+ if view_context.respond_to?(:raw)
21
+ view_context.raw(result)
22
+ elsif result.respond_to?(:html_safe)
23
+ result.html_safe
24
+ else
25
+ result
26
+ end
27
+ end
28
+
29
+ def to_s
30
+ meta
31
+ end
32
+
33
+ private
34
+
35
+ def escape(content)
36
+ CGI.escapeHTML(content.to_s)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenGraphPlus
4
+ module Tags
5
+ class Renderer
6
+ attr_reader :root
7
+
8
+ def initialize(root)
9
+ @root = root
10
+ end
11
+
12
+ def tags
13
+ [*og_tags, *twitter_tags].compact
14
+ end
15
+
16
+ private
17
+
18
+ def og
19
+ root.og
20
+ end
21
+
22
+ def twitter
23
+ root.twitter
24
+ end
25
+
26
+ def tag(property, content)
27
+ return nil if content.nil?
28
+
29
+ Tag.new(property, content)
30
+ end
31
+
32
+ def og_tags
33
+ [
34
+ tag("og:title", og.title),
35
+ tag("og:description", og.description),
36
+ tag("og:url", og.url),
37
+ tag("og:type", og.type),
38
+ tag("og:site_name", og.site_name),
39
+ tag("og:locale", og.locale),
40
+ tag("og:determiner", og.determiner),
41
+ tag("og:audio", og.audio),
42
+ tag("og:video", og.video),
43
+ *og_image_tags
44
+ ]
45
+ end
46
+
47
+ def og_image_tags
48
+ return [] unless og.image
49
+
50
+ image = og.image
51
+ [
52
+ tag("og:image", image.url),
53
+ tag("og:image:secure_url", image.secure_url),
54
+ tag("og:image:type", image.type),
55
+ tag("og:image:width", image.width),
56
+ tag("og:image:height", image.height),
57
+ tag("og:image:alt", image.alt)
58
+ ]
59
+ end
60
+
61
+ def twitter_tags
62
+ [
63
+ tag("twitter:card", twitter.card),
64
+ tag("twitter:site", twitter.site),
65
+ tag("twitter:creator", twitter.creator),
66
+ tag("twitter:title", twitter.title || og.title),
67
+ tag("twitter:description", twitter.description || og.description),
68
+ tag("twitter:image", twitter_image_url),
69
+ tag("twitter:image:alt", twitter.image_alt || og.image&.alt)
70
+ ]
71
+ end
72
+
73
+ def twitter_image_url
74
+ twitter.image || og.image&.url
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module OpenGraphPlus
6
+ module Tags
7
+ class Base
8
+ def update(**kwargs)
9
+ kwargs.each { |key, value| public_send(:"#{key}=", value) }
10
+ self
11
+ end
12
+ end
13
+
14
+ class Image < Base
15
+ attr_accessor :url, :width, :height, :type, :alt, :secure_url
16
+ end
17
+
18
+ class Twitter < Base
19
+ attr_accessor :card, :site, :creator, :title, :description, :image, :image_alt
20
+
21
+ def initialize
22
+ @card = "summary_large_image"
23
+ end
24
+ end
25
+
26
+ class OpenGraph < Base
27
+ attr_accessor :title, :description, :url, :type, :site_name, :locale, :determiner, :audio, :video
28
+ attr_reader :image
29
+
30
+ def initialize
31
+ @type = "website"
32
+ @image = Image.new
33
+ end
34
+
35
+ def image_url=(url)
36
+ @image.url = url
37
+ @image.secure_url = url
38
+ end
39
+ end
40
+
41
+ class Root < Base
42
+ extend Forwardable
43
+
44
+ attr_reader :og, :twitter
45
+
46
+ def_delegators :@og,
47
+ :title, :title=,
48
+ :description, :description=,
49
+ :url, :url=,
50
+ :type, :type=,
51
+ :site_name, :site_name=,
52
+ :locale, :locale=,
53
+ :determiner, :determiner=,
54
+ :audio, :audio=,
55
+ :video, :video=,
56
+ :image, :image_url=
57
+
58
+ def initialize
59
+ @og = OpenGraph.new
60
+ @twitter = Twitter.new
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenGraphPlus
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/opengraphplus.rb CHANGED
@@ -1,3 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "open_graph_plus"
3
+ require_relative "opengraphplus/version"
4
+ require_relative "opengraphplus/api_key"
5
+ require_relative "opengraphplus/configuration"
6
+ require_relative "opengraphplus/signature"
7
+ require_relative "opengraphplus/tag"
8
+ require_relative "opengraphplus/tags"
9
+ require_relative "opengraphplus/tags/renderer"
10
+ require_relative "opengraphplus/image_generator"
11
+
12
+ module OpenGraphPlus
13
+ class Error < StandardError; end
14
+ end
15
+
16
+ require_relative "opengraphplus/rails" if defined?(::Rails::Railtie)
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opengraphplus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brad Gessler
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-12-11 00:00:00.000000000 Z
11
- dependencies: []
10
+ date: 2025-12-17 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: activesupport
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.0'
12
26
  description: Add Open Graph meta tags to your Rails application
13
27
  email:
14
28
  - brad@opengraphplus.com
@@ -20,9 +34,29 @@ files:
20
34
  - LICENSE.txt
21
35
  - README.md
22
36
  - Rakefile
37
+ - lib/generators/opengraphplus/install/install_generator.rb
38
+ - lib/generators/opengraphplus/install/templates/README
39
+ - lib/generators/opengraphplus/install/templates/initializer.rb
23
40
  - lib/open_graph_plus.rb
24
- - lib/open_graph_plus/version.rb
25
41
  - lib/opengraphplus.rb
42
+ - lib/opengraphplus/api_key.rb
43
+ - lib/opengraphplus/configuration.rb
44
+ - lib/opengraphplus/image_generator.rb
45
+ - lib/opengraphplus/rails.rb
46
+ - lib/opengraphplus/rails/controller.rb
47
+ - lib/opengraphplus/rails/helper.rb
48
+ - lib/opengraphplus/rails/railtie.rb
49
+ - lib/opengraphplus/rails/signature.rb
50
+ - lib/opengraphplus/rails/signature/routes.rb
51
+ - lib/opengraphplus/rails/signature/scope.rb
52
+ - lib/opengraphplus/signature.rb
53
+ - lib/opengraphplus/signature/generator.rb
54
+ - lib/opengraphplus/signature/url.rb
55
+ - lib/opengraphplus/signature/verifier.rb
56
+ - lib/opengraphplus/tag.rb
57
+ - lib/opengraphplus/tags.rb
58
+ - lib/opengraphplus/tags/renderer.rb
59
+ - lib/opengraphplus/version.rb
26
60
  - sig/open_graph_plus.rbs
27
61
  homepage: https://opengraphplus.com/ruby
28
62
  licenses:
@@ -30,7 +64,7 @@ licenses:
30
64
  metadata:
31
65
  allowed_push_host: https://rubygems.org
32
66
  homepage_uri: https://opengraphplus.com/ruby
33
- source_code_uri: https://github.com/opengraphplus/gem
67
+ source_code_uri: https://github.com/opengraphplus/ruby
34
68
  rdoc_options: []
35
69
  require_paths:
36
70
  - lib