use ruby to generate json-ld

This commit is contained in:
Ben Balter 2017-04-08 14:20:21 -04:00
parent 337bffa3bc
commit 66aff234ca
No known key found for this signature in database
GPG Key ID: DBB67C246AD356C4
7 changed files with 206 additions and 80 deletions

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -19,8 +19,8 @@
{% endif %}
{% if site.url %}
<link rel="canonical" href="{{ page.url | replace:'/index.html','/' | absolute_url }}" />
<meta property="og:url" content="{{ page.url | replace:'/index.html','/' | absolute_url }}" />
<link rel="canonical" href="{{ seo_tag.canonical_url }}" />
<meta property="og:url" content="{{ seo_tag.canonical_url }}" />
{% endif %}
{% if seo_tag.site_title %}
@ -99,70 +99,7 @@
<script type="application/ld+json">
{
"@context": "http://schema.org",
{% if seo_tag.type %}
"@type": {{ seo_tag.type | jsonify }},
{% endif %}
{% if seo_tag.name %}
"name": {{ seo_tag.name | jsonify }},
{% endif %}
{% if seo_tag.page_title %}
"headline": {{ seo_tag.page_title | jsonify }},
{% endif %}
{% if seo_tag.author %}
"author": {
"@type": "Person",
"name": {{ seo_tag.author.name | jsonify }}
},
{% endif %}
{% if seo_tag.image %}
"image": {{ seo_tag.image.path | jsonify }},
{% endif %}
{% if page.date %}
"datePublished": {{ page.date | date_to_xmlschema | jsonify }},
{% endif %}
{% if seo_tag.date_modified %}
"dateModified": {{ seo_tag.date_modified | date_to_xmlschema | jsonify }},
{% endif %}
{% if seo_tag.description %}
"description": {{ seo_tag.description | jsonify }},
{% endif %}
{% if seo_tag.logo %}
"publisher": {
"@type": "Organization",
{% if seo_tag.author %}
"name": {{ seo_tag.author.name | jsonify }},
{% endif %}
"logo": {
"@type": "ImageObject",
"url": {{ seo_tag.logo | jsonify }}
}
},
{% endif %}
{% if seo_tag.type == "BlogPosting" or seo_tag.type == "CreativeWork"%}
"mainEntityOfPage": {
"@type": "WebPage",
"@id": {{ page.url | replace:'/index.html','/' | absolute_url | jsonify }}
},
{% endif %}
{% if seo_tag.links %}
"sameAs": {{ seo_tag.links | jsonify }},
{% endif %}
"url": {{ page.url | replace:'/index.html','/' | absolute_url | jsonify }}
}
{{ seo_tag.json_ld | jsonify }}
</script>
<!-- End Jekyll SEO tag -->

View File

@ -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

View File

@ -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

View File

@ -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