break image logic into its own drop
This commit is contained in:
parent
2e90fc7238
commit
1081a0ebd9
|
@ -5,6 +5,8 @@ module Jekyll
|
|||
class SeoTag < Liquid::Tag
|
||||
autoload :JSONLD, "jekyll-seo-tag/json_ld"
|
||||
autoload :AuthorDrop, "jekyll-seo-tag/author_drop"
|
||||
autoload :ImageDrop, "jekyll-seo-tag/image_drop"
|
||||
autoload :UrlHelper, "jekyll-seo-tag/url_helper"
|
||||
autoload :Drop, "jekyll-seo-tag/drop"
|
||||
autoload :Filters, "jekyll-seo-tag/filters"
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ module Jekyll
|
|||
class SeoTag
|
||||
class Drop < Jekyll::Drops::Drop
|
||||
include Jekyll::SeoTag::JSONLD
|
||||
include Jekyll::SeoTag::UrlHelper
|
||||
|
||||
TITLE_SEPARATOR = " | ".freeze
|
||||
FORMAT_STRING_METHODS = %i[
|
||||
|
@ -129,33 +130,8 @@ module Jekyll
|
|||
end
|
||||
end
|
||||
|
||||
# Returns nil or a hash representing the page image
|
||||
# The image hash will always contain a path, pulled from:
|
||||
#
|
||||
# 1. The `image` key if it's a string
|
||||
# 2. The `image.path` key if it's a hash
|
||||
# 3. The `image.facebook` key
|
||||
# 4. The `image.twitter` key
|
||||
#
|
||||
# The resulting path is always an absolute URL
|
||||
def image
|
||||
return @image if defined?(@image)
|
||||
|
||||
image = page["image"]
|
||||
return @image = nil unless image
|
||||
|
||||
image = { "path" => image } if image.is_a?(String)
|
||||
image["path"] ||= image["facebook"] || image["twitter"]
|
||||
return @image = nil unless image["path"]
|
||||
|
||||
# absolute_url? will return nil for an invalid URL
|
||||
if absolute_url?(image["path"]) == false
|
||||
image["path"] = filters.absolute_url image["path"]
|
||||
end
|
||||
|
||||
image["path"] = filters.uri_escape image["path"]
|
||||
|
||||
@image = image.to_liquid
|
||||
@image ||= ImageDrop.new(:page => page, :context => @context)
|
||||
end
|
||||
|
||||
def page_lang
|
||||
|
@ -196,13 +172,6 @@ module Jekyll
|
|||
@fallback_data ||= {}
|
||||
end
|
||||
|
||||
def absolute_url?(string)
|
||||
return unless string
|
||||
Addressable::URI.parse(string).absolute?
|
||||
rescue Addressable::URI::InvalidURIError
|
||||
nil
|
||||
end
|
||||
|
||||
def format_string(string)
|
||||
string = FORMAT_STRING_METHODS.reduce(string) do |memo, method|
|
||||
filters.public_send(method, memo)
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
module Jekyll
|
||||
class SeoTag
|
||||
# Returns nil or a hash representing the page image
|
||||
# The image hash will always contain a path, pulled from:
|
||||
#
|
||||
# 1. The `image` key if it's a string
|
||||
# 2. The `image.path` key if it's a hash
|
||||
# 3. The `image.facebook` key
|
||||
# 4. The `image.twitter` key
|
||||
#
|
||||
# The resulting path is always an absolute URL
|
||||
class ImageDrop < Jekyll::Drops::Drop
|
||||
include Jekyll::SeoTag::UrlHelper
|
||||
|
||||
# Initialize a new ImageDrop
|
||||
#
|
||||
# page - The page hash (e.g., Page#to_liquid)
|
||||
def initialize(page: nil, context: nil)
|
||||
raise ArgumentError unless page && context
|
||||
@mutations = {}
|
||||
@page = page
|
||||
@context = context
|
||||
end
|
||||
|
||||
def path
|
||||
@path ||= filters.uri_escape(absolute_url) if absolute_url
|
||||
end
|
||||
alias_method :to_s, :path
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :page
|
||||
attr_accessor :context
|
||||
|
||||
def image_hash
|
||||
@image_hash ||= if page["image"].is_a?(Hash)
|
||||
page["image"]
|
||||
elsif page["image"].is_a?(String)
|
||||
{ "path" => page["image"] }
|
||||
else
|
||||
{ "path" => nil }
|
||||
end
|
||||
end
|
||||
alias_method :fallback_data, :image_hash
|
||||
|
||||
def raw_path
|
||||
@raw_path ||= begin
|
||||
image_hash["path"] || image_hash["facebook"] || image_hash["twitter"]
|
||||
end
|
||||
end
|
||||
|
||||
def absolute_url
|
||||
return unless raw_path
|
||||
return @absolute_url if defined? @absolute_url
|
||||
@absolute_url = if raw_path.is_a?(String) && absolute_url?(raw_path) == false
|
||||
filters.absolute_url raw_path
|
||||
else
|
||||
raw_path
|
||||
end
|
||||
end
|
||||
|
||||
def filters
|
||||
@filters ||= Jekyll::SeoTag::Filters.new(context)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -46,9 +46,9 @@ module Jekyll
|
|||
|
||||
def json_image
|
||||
return unless image
|
||||
return image["path"] if image.length == 1
|
||||
return image["path"] if image.keys.length == 1
|
||||
|
||||
hash = image.dup
|
||||
hash = image.to_h
|
||||
hash["url"] = hash.delete("path")
|
||||
hash["@type"] = "imageObject"
|
||||
hash
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
module Jekyll
|
||||
class SeoTag
|
||||
module UrlHelper
|
||||
private
|
||||
|
||||
def absolute_url?(string)
|
||||
return unless string
|
||||
Addressable::URI.parse(string).absolute?
|
||||
rescue Addressable::URI::InvalidURIError
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -27,7 +27,7 @@
|
|||
<meta property="og:site_name" content="{{ seo_tag.site_title }}" />
|
||||
{% endif %}
|
||||
|
||||
{% if seo_tag.image %}
|
||||
{% if seo_tag.image.path %}
|
||||
<meta property="og:image" content="{{ seo_tag.image.path }}" />
|
||||
{% if seo_tag.image.height %}
|
||||
<meta property="og:image:height" content="{{ seo_tag.image.height }}" />
|
||||
|
@ -50,7 +50,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if site.twitter %}
|
||||
{% if seo_tag.image %}
|
||||
{% if seo_tag.image.path %}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
{% else %}
|
||||
<meta name="twitter:card" content="summary" />
|
||||
|
|
|
@ -402,85 +402,15 @@ RSpec.describe Jekyll::SeoTag::Drop do
|
|||
end
|
||||
|
||||
context "image" do
|
||||
let(:image) { "foo.png" }
|
||||
let(:page_meta) { { "image" => image } }
|
||||
|
||||
context "with image as a string" do
|
||||
let(:image) { "image.png" }
|
||||
|
||||
it "returns a hash" do
|
||||
expect(subject.image).to be_a(Hash)
|
||||
end
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject.image["path"]).to eql("/image.png")
|
||||
end
|
||||
|
||||
context "with site.url" do
|
||||
let(:config) { { "url" => "http://example.com" } }
|
||||
|
||||
it "makes the path absolute" do
|
||||
expect(subject.image["path"]).to eql("http://example.com/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with a URL-escaped path" do
|
||||
let(:image) { "some image.png" }
|
||||
|
||||
it "URL-escapes the image" do
|
||||
expect(subject.image["path"]).to eql("/some%20image.png")
|
||||
end
|
||||
end
|
||||
it "returns a Drop" do
|
||||
expect(subject.image).to be_a(Jekyll::SeoTag::ImageDrop)
|
||||
end
|
||||
|
||||
context "with image as a hash" do
|
||||
context "with a path" do
|
||||
let(:image) { { "path" => "image.png" } }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject.image["path"]).to eql("/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with facebook" do
|
||||
let(:image) { { "facebook" => "image.png" } }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject.image["path"]).to eql("/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with twitter" do
|
||||
let(:image) { { "twitter" => "image.png" } }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject.image["path"]).to eql("/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with some random hash" do
|
||||
let(:image) { { "foo" => "bar" } }
|
||||
|
||||
it "returns nil" do
|
||||
expect(subject.image).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "with an invalid path" do
|
||||
let(:image) { ":" }
|
||||
|
||||
it "returns nil" do
|
||||
expect(subject.image["path"]).to eql(":")
|
||||
end
|
||||
end
|
||||
|
||||
context "with height and width" do
|
||||
let(:image) { { "path" => "image.png", "height" => 5, "width" => 10 } }
|
||||
|
||||
it "returns the height and width" do
|
||||
expect(subject.image["height"]).to eql(5)
|
||||
expect(subject.image["width"]).to eql(10)
|
||||
end
|
||||
end
|
||||
it "returns the image" do
|
||||
expect(subject.image["path"]).to eql("/foo.png")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
RSpec.describe Jekyll::SeoTag::ImageDrop do
|
||||
let(:config) { { "title" => "site title" } }
|
||||
let(:image) { nil }
|
||||
let(:page_meta) { { "image" => image } }
|
||||
let(:page) { make_page(page_meta) }
|
||||
let(:site) { make_site(config) }
|
||||
let(:context) { make_context(:page => page, :site => site) }
|
||||
let(:text) { "" }
|
||||
subject { described_class.new(:page => page.to_liquid, :context => context) }
|
||||
|
||||
before do
|
||||
Jekyll.logger.log_level = :error
|
||||
end
|
||||
|
||||
context "with image as a string" do
|
||||
let(:image) { "image.png" }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject["path"]).to eql("/image.png")
|
||||
end
|
||||
|
||||
context "with site.url" do
|
||||
let(:config) { { "url" => "http://example.com" } }
|
||||
|
||||
it "makes the path absolute" do
|
||||
expect(subject["path"]).to eql("http://example.com/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with a URL-escaped path" do
|
||||
let(:image) { "some image.png" }
|
||||
|
||||
it "URL-escapes the image" do
|
||||
expect(subject["path"]).to eql("/some%20image.png")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with image as a hash" do
|
||||
context "with a path" do
|
||||
let(:image) { { "path" => "image.png" } }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject["path"]).to eql("/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with facebook" do
|
||||
let(:image) { { "facebook" => "image.png" } }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject["path"]).to eql("/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with twitter" do
|
||||
let(:image) { { "twitter" => "image.png" } }
|
||||
|
||||
it "returns the image" do
|
||||
expect(subject["path"]).to eql("/image.png")
|
||||
end
|
||||
end
|
||||
|
||||
context "with some random hash" do
|
||||
let(:image) { { "foo" => "bar" } }
|
||||
|
||||
it "returns nil" do
|
||||
expect(subject["path"]).to be_nil
|
||||
end
|
||||
|
||||
it "returns arbitrary values" do
|
||||
expect(subject["foo"]).to eql("bar")
|
||||
end
|
||||
end
|
||||
|
||||
context "with an invalid path" do
|
||||
let(:image) { ":" }
|
||||
|
||||
it "returns the path" do
|
||||
expect(subject["path"]).to eql(":")
|
||||
end
|
||||
end
|
||||
|
||||
context "with height and width" do
|
||||
let(:image) { { "path" => "image.png", "height" => 5, "width" => 10 } }
|
||||
|
||||
it "returns the height and width" do
|
||||
expect(subject["height"]).to eql(5)
|
||||
expect(subject["width"]).to eql(10)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue