diff --git a/lib/jekyll-seo-tag.rb b/lib/jekyll-seo-tag.rb
index 9f9b7e2..6d3e4b8 100644
--- a/lib/jekyll-seo-tag.rb
+++ b/lib/jekyll-seo-tag.rb
@@ -3,6 +3,7 @@ require "jekyll-seo-tag/version"
module Jekyll
class SeoTag < Liquid::Tag
+ autoload :JSONLD, "jekyll-seo-tag/json_ld"
autoload :Drop, "jekyll-seo-tag/drop"
autoload :Filters, "jekyll-seo-tag/filters"
diff --git a/lib/jekyll-seo-tag/drop.rb b/lib/jekyll-seo-tag/drop.rb
index 34cec8d..8e07d71 100644
--- a/lib/jekyll-seo-tag/drop.rb
+++ b/lib/jekyll-seo-tag/drop.rb
@@ -1,6 +1,8 @@
module Jekyll
class SeoTag
class Drop < Jekyll::Drops::Drop
+ include Jekyll::SeoTag::JSONLD
+
TITLE_SEPARATOR = " | ".freeze
FORMAT_STRING_METHODS = %i[
markdownify strip_html normalize_whitespace escape_once
@@ -91,10 +93,12 @@ module Jekyll
def date_modified
@date_modified ||= begin
- if page["seo"] && page["seo"]["date_modified"]
- return page["seo"]["date_modified"]
- end
- page["last_modified_at"] || page["date"]
+ date = if page["seo"] && page["seo"]["date_modified"]
+ page["seo"]["date_modified"]
+ else
+ page["last_modified_at"] || page["date"]
+ end
+ filters.date_to_xmlschema(date) if date
end
end
@@ -164,6 +168,10 @@ module Jekyll
@page_lang ||= page["lang"] || site["lang"] || "en_US"
end
+ def canonical_url
+ @canonical_url ||= filters.absolute_url(page["url"]).gsub(%r!/index\.html$!, "/")
+ end
+
private
def filters
diff --git a/lib/jekyll-seo-tag/json_ld.rb b/lib/jekyll-seo-tag/json_ld.rb
new file mode 100644
index 0000000..f4eb9fd
--- /dev/null
+++ b/lib/jekyll-seo-tag/json_ld.rb
@@ -0,0 +1,76 @@
+module Jekyll
+ class SeoTag
+ module JSONLD
+
+ # A hash of instance methods => key in resulting JSON-LD hash
+ METHODS_KEYS = {
+ :json_context => "@context",
+ :type => "@type",
+ :name => "name",
+ :page_title => "headline",
+ :json_author => "author",
+ :image_path => "image",
+ :date_modified => "dateModified",
+ :description => "description",
+ :publisher => "publisher",
+ :main_entity => "mainEntityOfPage",
+ :links => "sameAs",
+ :canonical_url => "url",
+ }.freeze
+
+ def json_ld
+ @json_ld ||= begin
+ output = {}
+ METHODS_KEYS.each do |method, key|
+ value = send(method)
+ output[key] = value unless value.nil?
+ end
+ output
+ end
+ end
+
+ private
+
+ def json_context
+ "http://schema.org"
+ end
+
+ def json_author
+ return unless author
+ {
+ "@type" => "Person",
+ "name" => author["name"],
+ }
+ end
+
+ def image_path
+ image["path"] if image
+ end
+
+ def date
+ filters.date_to_xmlschema(page["date"]) if page["date"]
+ end
+
+ def publisher
+ return unless logo
+ output = {
+ "@type" => "Organization",
+ "logo" => {
+ "@type" => "ImageObject",
+ "url" => logo,
+ },
+ }
+ output["name"] = author["name"] if author
+ output
+ end
+
+ def main_entity
+ return unless %w(BlogPosting CreativeWork).include?(type)
+ {
+ "@type" => "WebPage",
+ "@id" => canonical_url,
+ }
+ end
+ end
+ end
+end
diff --git a/lib/template.html b/lib/template.html
index d05ce92..8a6a7aa 100755
--- a/lib/template.html
+++ b/lib/template.html
@@ -19,8 +19,8 @@
{% endif %}
{% if site.url %}
-
-
+
+
{% endif %}
{% if seo_tag.site_title %}
@@ -99,70 +99,7 @@
diff --git a/spec/jekyll_seo_tag/drop_spec.rb b/spec/jekyll_seo_tag/drop_spec.rb
index 34ef79c..2c8008b 100644
--- a/spec/jekyll_seo_tag/drop_spec.rb
+++ b/spec/jekyll_seo_tag/drop_spec.rb
@@ -244,26 +244,26 @@ RSpec.describe Jekyll::SeoTag::Drop do
context "date modified" do
context "with seo.date_modified" do
- let(:page_meta) { { "seo" => { "date_modified" => "tuesday" } } }
+ let(:page_meta) { { "seo" => { "date_modified" => "2017-01-01" } } }
it "uses seo.date_modified" do
- expect(subject.date_modified).to eql("tuesday")
+ expect(subject.date_modified).to eql("2017-01-01T00:00:00-05:00")
end
end
context "with page.last_modified_at" do
- let(:page_meta) { { "last_modified_at" => "tuesday" } }
+ let(:page_meta) { { "last_modified_at" => "2017-01-01" } }
it "uses page.last_modified_at" do
- expect(subject.date_modified).to eql("tuesday")
+ expect(subject.date_modified).to eql("2017-01-01T00:00:00-05:00")
end
end
context "date" do
- let(:page_meta) { { "date" => "tuesday" } }
+ let(:page_meta) { { "date" => "2017-01-01" } }
it "uses page.date" do
- expect(subject.date_modified).to eql("tuesday")
+ expect(subject.date_modified).to eql("2017-01-01T00:00:00-05:00")
end
end
end
diff --git a/spec/jekyll_seo_tag/json_ld_spec.rb b/spec/jekyll_seo_tag/json_ld_spec.rb
new file mode 100644
index 0000000..68e043f
--- /dev/null
+++ b/spec/jekyll_seo_tag/json_ld_spec.rb
@@ -0,0 +1,106 @@
+RSpec.describe Jekyll::SeoTag::JSONLD do
+ let(:metadata) do
+ {
+ "title" => "title",
+ "author" => "author",
+ "image" => "image",
+ "date" => "2017-01-01",
+ "description" => "description",
+ "seo" => {
+ "name" => "seo name",
+ "date_modified" => "2017-01-01",
+ "links" => %w(a b),
+ },
+ }
+ end
+ let(:config) do
+ {
+ "logo" => "logo",
+ }
+ end
+ let(:page) { make_page(metadata) }
+ let(:site) { make_site(config) }
+ let(:context) { make_context(:page => page, :site => site) }
+ subject { Jekyll::SeoTag::Drop.new("", context).json_ld }
+
+ it "returns the context" do
+ expect(subject).to have_key("@context")
+ expect(subject["@context"]).to eql("http://schema.org")
+ end
+
+ it "returns the type" do
+ expect(subject).to have_key("@type")
+ expect(subject["@type"]).to eql("BlogPosting")
+ end
+
+ it "returns the name" do
+ expect(subject).to have_key("name")
+ expect(subject["name"]).to eql("seo name")
+ end
+
+ it "returns the headline" do
+ expect(subject).to have_key("headline")
+ expect(subject["headline"]).to eql("title")
+ end
+
+ it "returns the author" do
+ expect(subject).to have_key("author")
+ expect(subject["author"]).to be_a(Hash)
+ expect(subject["author"]).to have_key("@type")
+ expect(subject["author"]["@type"]).to eql("Person")
+ expect(subject["author"]).to have_key("name")
+ expect(subject["author"]["name"]).to eql("author")
+ end
+
+ it "returns the image" do
+ expect(subject).to have_key("image")
+ expect(subject["image"]).to eql("/image")
+ end
+
+ it "returns the dateModified" do
+ expect(subject).to have_key("dateModified")
+ expect(subject["dateModified"]).to eql("2017-01-01T00:00:00-05:00")
+ end
+
+ it "returns the description" do
+ expect(subject).to have_key("description")
+ expect(subject["description"]).to eql("description")
+ end
+
+ it "returns the publisher" do
+ expect(subject).to have_key("publisher")
+
+ publisher = subject["publisher"]
+ expect(publisher).to be_a(Hash)
+
+ expect(publisher).to have_key("@type")
+ expect(publisher["@type"]).to eql("Organization")
+ expect(publisher).to have_key("logo")
+
+ logo = publisher["logo"]
+ expect(logo).to have_key("@type")
+ expect(logo["@type"]).to eql("ImageObject")
+ expect(logo).to have_key("url")
+ expect(logo["url"]).to eql("/logo")
+ end
+
+ it "returns the main entity of page" do
+ expect(subject).to have_key("mainEntityOfPage")
+ expect(subject["mainEntityOfPage"]).to be_a(Hash)
+ expect(subject["mainEntityOfPage"]).to have_key("@type")
+ expect(subject["mainEntityOfPage"]["@type"]).to eql("WebPage")
+ expect(subject["mainEntityOfPage"]).to have_key("@id")
+ expect(subject["mainEntityOfPage"]["@id"]).to eql("/page.html")
+ end
+
+ it "returns sameAs" do
+ expect(subject).to have_key("sameAs")
+ expect(subject["sameAs"]).to be_a(Array)
+ expect(subject["sameAs"]).to eql(%w(a b))
+ end
+
+ it "returns the url" do
+ expect(subject).to have_key("url")
+ expect(subject["url"]).to eql("/page.html")
+ end
+end
diff --git a/spec/jekyll_seo_tag_spec.rb b/spec/jekyll_seo_tag_spec.rb
index 9f5d052..bcc5d76 100755
--- a/spec/jekyll_seo_tag_spec.rb
+++ b/spec/jekyll_seo_tag_spec.rb
@@ -331,10 +331,8 @@ EOS
end
it "minifies JSON-LD" do
- expected = <<-EOS
-{"@context": "http://schema.org",
-"@type": "BlogPosting",
-"headline": "post",
+ expected = <<-EOS.strip
+{"@context":"http://schema.org","@type":"BlogPosting","headline":"post",
EOS
expect(output).to match(expected)
end