forked from decidim/decidim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add schema.org Event serializer for Breadcrumb (decidim#13522)
* Add schema.org Event serializer for Breadcrumb * Skip empty items * Add name to BreadcrumbList schema * Fix rubocop offense * Fix specs
- Loading branch information
1 parent
39fbb94
commit 543f6f4
Showing
6 changed files
with
201 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
decidim-core/app/serializers/decidim/schema_org_breadcrumb_list_serializer.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# frozen_string_literal: true | ||
|
||
require "uri" | ||
|
||
module Decidim | ||
class SchemaOrgBreadcrumbListSerializer < Decidim::Exporters::Serializer | ||
include Decidim::SanitizeHelper | ||
|
||
# Public: Initializes the serializer with a list of breadcrumb items. | ||
def initialize(options) | ||
@breadcrumb_items = options[:breadcrumb_items] | ||
@base_url = options[:base_url] | ||
@organization_name = options[:organization_name] | ||
end | ||
|
||
# Serializes a breadcrumb items list for the Schema.org BreadcrumbList type | ||
# | ||
# @see https://schema.org/BreadcrumbList | ||
# @see https://developers.google.com/search/docs/appearance/structured-data/breadcrumb?hl=en | ||
def serialize | ||
return {} if breadcrumb_items.none? { |item| item.has_key?(:url) } | ||
|
||
{ | ||
"@context": "https://schema.org", | ||
"@type": "BreadcrumbList", | ||
name: "#{organization_name} breadcrumb", | ||
itemListElement: breadcrumb_items_serialized | ||
} | ||
end | ||
|
||
private | ||
|
||
attr_reader :breadcrumb_items, :base_url, :organization_name | ||
|
||
def breadcrumb_items_serialized | ||
all_items = [] | ||
|
||
breadcrumb_items.each_with_index do |item, index| | ||
next if item.empty? | ||
|
||
all_items << { | ||
"@type": "ListItem", | ||
position: index + 1, | ||
name: decidim_sanitize_translated(item[:label]), | ||
item: URI.join(base_url, item[:url]).to_s | ||
} | ||
end | ||
|
||
all_items | ||
end | ||
end | ||
end |
3 changes: 3 additions & 0 deletions
3
decidim-core/app/views/layouts/decidim/_schema_org_breadcrumb_list.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<script type="application/ld+json"> | ||
<%== render_schema_org_breadcrumb_list(breadcrumb_items) %> | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
decidim-core/spec/helpers/decidim/breadcrumb_helper_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# frozen_string_literal: true | ||
|
||
require "spec_helper" | ||
|
||
module Decidim | ||
describe BreadcrumbHelper do | ||
describe "#render_schema_org_breadcrumb_list" do | ||
subject { helper.render_schema_org_breadcrumb_list(breadcrumb_items) } | ||
|
||
let(:breadcrumb_items) do | ||
[ | ||
{ | ||
label: "Processes", | ||
url: "/processes", | ||
active: true | ||
}, | ||
{ | ||
label: { ca: "Hola mon", es: "Hola mundo", en: "Hello world" }, | ||
url: "/processes/hello-world", | ||
dropdown_cell: "decidim/participatory_processes/process_dropdown_metadata", | ||
resource: participatory_process | ||
} | ||
|
||
] | ||
end | ||
|
||
let(:participatory_process) { create(:participatory_process) } | ||
|
||
before do | ||
allow(helper).to receive(:current_organization).and_return(participatory_process.organization) | ||
end | ||
|
||
it "renders a schema.org event" do | ||
keys = JSON.parse(subject).keys | ||
expect(keys).to include("@context") | ||
expect(keys).to include("@type") | ||
expect(keys).to include("itemListElement") | ||
end | ||
end | ||
end | ||
end |
97 changes: 97 additions & 0 deletions
97
decidim-core/spec/serializers/decidim/schema_org_breadcrumb_list_serializer_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# frozen_string_literal: true | ||
|
||
require "spec_helper" | ||
|
||
module Decidim | ||
describe SchemaOrgBreadcrumbListSerializer do | ||
subject do | ||
described_class.new({ breadcrumb_items:, base_url:, organization_name: }) | ||
end | ||
|
||
let(:breadcrumb_items) do | ||
[ | ||
{ | ||
label: "Processes", | ||
url: "/processes", | ||
active: true | ||
}, | ||
{ | ||
label: { ca: "Hola mon", es: "Hola mundo", en: "Hello world" }, | ||
url: "/processes/hello-world", | ||
dropdown_cell: "decidim/participatory_processes/process_dropdown_metadata", | ||
resource: participatory_process | ||
} | ||
] | ||
end | ||
|
||
let(:base_url) { "https://example.org" } | ||
let(:participatory_process) { create(:participatory_process) } | ||
let(:organization_name) { "ACME Corp" } | ||
|
||
describe "#serialize" do | ||
let(:serialized) { subject.serialize } | ||
|
||
it "serializes the @context" do | ||
expect(serialized[:@context]).to eq("https://schema.org") | ||
end | ||
|
||
it "serializes the @type" do | ||
expect(serialized[:@type]).to eq("BreadcrumbList") | ||
end | ||
|
||
it "serializes the name" do | ||
expect(serialized[:name]).to eq("ACME Corp breadcrumb") | ||
end | ||
|
||
it "serializes the breadcrumb items" do | ||
expected_items_elements = [ | ||
{ "@type": "ListItem", position: 1, name: "Processes", item: "https://example.org/processes" }, | ||
{ "@type": "ListItem", position: 2, name: "Hello world", item: "https://example.org/processes/hello-world" } | ||
] | ||
expect(serialized[:itemListElement]).to eq(expected_items_elements) | ||
end | ||
|
||
context "when there are empty items" do | ||
let(:breadcrumb_items) do | ||
[ | ||
{ | ||
label: "Processes", | ||
url: "/processes", | ||
active: true | ||
}, | ||
{ | ||
label: { ca: "Hola mon", es: "Hola mundo", en: "Hello world" }, | ||
url: "/processes/hello-world", | ||
dropdown_cell: "decidim/participatory_processes/process_dropdown_metadata", | ||
resource: participatory_process | ||
}, | ||
{} | ||
] | ||
end | ||
|
||
it "ignores them" do | ||
expected_items_elements = [ | ||
{ "@type": "ListItem", position: 1, name: "Processes", item: "https://example.org/processes" }, | ||
{ "@type": "ListItem", position: 2, name: "Hello world", item: "https://example.org/processes/hello-world" } | ||
] | ||
expect(serialized[:itemListElement]).to eq(expected_items_elements) | ||
end | ||
end | ||
|
||
context "when there are only items without URLs" do | ||
let(:breadcrumb_items) do | ||
[ | ||
{ | ||
label: "Profile", | ||
active: true | ||
} | ||
] | ||
end | ||
|
||
it "returns an empty JSON" do | ||
expect(serialized).to eq({}) | ||
end | ||
end | ||
end | ||
end | ||
end |