scrivito_rich_snippet_widget 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +129 -0
- data/Rakefile +35 -0
- data/app/assets/images/widgets/scrivito_rich_snippet_widget.png +0 -0
- data/app/assets/javascripts/scrivito_rich_snippet_widget.js +41 -0
- data/app/models/rich_snippet/creative_work.rb +88 -0
- data/app/models/rich_snippet/event.rb +70 -0
- data/app/models/rich_snippet/job_posting.rb +47 -0
- data/app/models/rich_snippet/offer.rb +41 -0
- data/app/models/rich_snippet/organization.rb +33 -0
- data/app/models/rich_snippet/person.rb +70 -0
- data/app/models/rich_snippet/postal_address.rb +33 -0
- data/app/models/rich_snippet/product.rb +40 -0
- data/app/models/rich_snippet/recipe.rb +69 -0
- data/app/models/rich_snippet/thing.rb +43 -0
- data/app/models/rich_snippet_widget.rb +20 -0
- data/app/views/rich_snippet/creative_work/_details.html.erb +136 -0
- data/app/views/rich_snippet/creative_work/details.html.erb +1 -0
- data/app/views/rich_snippet/event/_details.html.erb +39 -0
- data/app/views/rich_snippet/event/details.html.erb +1 -0
- data/app/views/rich_snippet/job_posting/_details.html.erb +59 -0
- data/app/views/rich_snippet/job_posting/details.html.erb +1 -0
- data/app/views/rich_snippet/offer/_details.html.erb +35 -0
- data/app/views/rich_snippet/offer/details.html.erb +1 -0
- data/app/views/rich_snippet/organization/_details.html.erb +39 -0
- data/app/views/rich_snippet/organization/details.html.erb +1 -0
- data/app/views/rich_snippet/person/_details.html.erb +79 -0
- data/app/views/rich_snippet/person/details.html.erb +1 -0
- data/app/views/rich_snippet/postal_address/_details.html.erb +39 -0
- data/app/views/rich_snippet/postal_address/details.html.erb +1 -0
- data/app/views/rich_snippet/product/_details.html.erb +55 -0
- data/app/views/rich_snippet/product/details.html.erb +1 -0
- data/app/views/rich_snippet/recipe/_details.html.erb +91 -0
- data/app/views/rich_snippet/recipe/details.html.erb +1 -0
- data/app/views/rich_snippet/thing/_details.html.erb +17 -0
- data/app/views/rich_snippet_widget/details.html.erb +11 -0
- data/app/views/rich_snippet_widget/show.html.erb +21 -0
- data/app/views/rich_snippet_widget/thumbnail.html.erb +3 -0
- data/config/routes.rb +2 -0
- data/lib/scrivito_rich_snippet_widget.rb +5 -0
- data/lib/scrivito_rich_snippet_widget/engine.rb +5 -0
- data/lib/scrivito_rich_snippet_widget/version.rb +3 -0
- data/lib/tasks/scrivito_rich_snippet_widget_tasks.rake +4 -0
- metadata +100 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module RichSnippet
|
2
|
+
class Organization < Thing
|
3
|
+
attribute :address, :reference
|
4
|
+
attribute :founder, :reference
|
5
|
+
attribute :founding_date, :date
|
6
|
+
attribute :legal_name, :string
|
7
|
+
attribute :logo, :reference
|
8
|
+
attribute :number_of_employees, :integer
|
9
|
+
attribute :parent_organization, :reference
|
10
|
+
attribute :sub_organizations, :referencelist
|
11
|
+
attribute :telephone, :string
|
12
|
+
|
13
|
+
def to_json(render_childs = false)
|
14
|
+
{
|
15
|
+
"@context": "http://schema.org",
|
16
|
+
"@type": "Organization",
|
17
|
+
name: name,
|
18
|
+
description: description,
|
19
|
+
image: image ? image.binary_url : '',
|
20
|
+
url: url,
|
21
|
+
address: address ? address.to_json : nil,
|
22
|
+
founder: founder ? founder.to_json : nil,
|
23
|
+
foundingDate: founding_date,
|
24
|
+
legalName: legal_name,
|
25
|
+
logo: logo ? logo.binary_url : nil,
|
26
|
+
numberOfEmployees: number_of_employees,
|
27
|
+
parentOrganization: parent_organization ? parent_organization.to_json : nil,
|
28
|
+
subOrganizations: array_json(sub_organizations),
|
29
|
+
telephone: telephone
|
30
|
+
}.delete_if { |k, v| !v.present? }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module RichSnippet
|
2
|
+
class Person < Thing
|
3
|
+
attribute :given_name, :string
|
4
|
+
attribute :additional_name, :string
|
5
|
+
attribute :family_name, :string
|
6
|
+
attribute :address, :reference
|
7
|
+
attribute :birth_date, :date
|
8
|
+
attribute :birth_place, :reference
|
9
|
+
attribute :death_date, :date
|
10
|
+
attribute :death_place, :reference
|
11
|
+
attribute :childs, :referencelist
|
12
|
+
attribute :email, :string
|
13
|
+
attribute :gender, :string
|
14
|
+
attribute :height, :float
|
15
|
+
attribute :nationality, :string
|
16
|
+
attribute :mother, :reference
|
17
|
+
attribute :father, :reference
|
18
|
+
attribute :siblings, :referencelist
|
19
|
+
attribute :telephone, :string
|
20
|
+
attribute :weight, :float
|
21
|
+
attribute :work_location, :reference
|
22
|
+
attribute :works_for, :reference
|
23
|
+
|
24
|
+
def to_json(render_childs = false)
|
25
|
+
json = {
|
26
|
+
"@context": "http://schema.org",
|
27
|
+
"@type": "Person",
|
28
|
+
name: name,
|
29
|
+
description: description,
|
30
|
+
image: image ? image.binary_url : nil,
|
31
|
+
url: url,
|
32
|
+
givenName: given_name,
|
33
|
+
additionalName: additional_name,
|
34
|
+
familyName: family_name,
|
35
|
+
address: address ? address.to_json : nil,
|
36
|
+
birthDate: birth_date,
|
37
|
+
birthPlace: {
|
38
|
+
"@context": "http://schema.org",
|
39
|
+
"@type": "Place",
|
40
|
+
address: birth_place ? birth_place.to_json : nil
|
41
|
+
},
|
42
|
+
deathDate: death_date,
|
43
|
+
"deathPlace": {
|
44
|
+
"@context": "http://schema.org",
|
45
|
+
"@type": "Place",
|
46
|
+
address: death_place ? death_place.to_json : nil
|
47
|
+
},
|
48
|
+
email: email,
|
49
|
+
gender: gender,
|
50
|
+
height: height,
|
51
|
+
nationality: nationality,
|
52
|
+
workLocation: work_location ? work_location.to_json : nil,
|
53
|
+
worksFor: works_for ? works_for.to_json : nil,
|
54
|
+
telephone: telephone,
|
55
|
+
weight: weight
|
56
|
+
}
|
57
|
+
|
58
|
+
if(render_childs)
|
59
|
+
json[:children] = array_json(children)
|
60
|
+
json[:siblings] = array_json(siblings)
|
61
|
+
json[:parents] = [
|
62
|
+
mother.to_json,
|
63
|
+
father.to_json
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
return json.delete_if { |k, v| !v.present? }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RichSnippet
|
2
|
+
class PostalAddress < Thing
|
3
|
+
attribute :address_country, :string
|
4
|
+
attribute :address_locality, :string
|
5
|
+
attribute :address_region, :string
|
6
|
+
attribute :post_office_box_number, :string
|
7
|
+
attribute :postal_code, :string
|
8
|
+
attribute :street_address, :string
|
9
|
+
attribute :email, :string
|
10
|
+
attribute :telephone, :string
|
11
|
+
attribute :fax_number, :string
|
12
|
+
|
13
|
+
def to_json(render_childs = false)
|
14
|
+
{
|
15
|
+
"@context": "http://schema.org",
|
16
|
+
"@type": "PostalAddress",
|
17
|
+
name: name,
|
18
|
+
description: description,
|
19
|
+
image: image ? image.binary_url : '',
|
20
|
+
url: url,
|
21
|
+
addressCountry: address_country,
|
22
|
+
addressLocality: address_locality,
|
23
|
+
addressRegion: address_region,
|
24
|
+
postOfficeBoxNumber: post_office_box_number,
|
25
|
+
postalCode: postal_code,
|
26
|
+
streetAddress: street_address,
|
27
|
+
email: email,
|
28
|
+
telephone: telephone,
|
29
|
+
faxNumber: fax_number
|
30
|
+
}.delete_if { |k, v| !v.present? }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RichSnippet
|
2
|
+
class Product < Thing
|
3
|
+
attribute :mpn, :string
|
4
|
+
attribute :brand, :reference
|
5
|
+
attribute :offers, :referencelist
|
6
|
+
attribute :awards, :stringlist
|
7
|
+
attribute :category, :string
|
8
|
+
attribute :color, :string
|
9
|
+
attribute :height, :float
|
10
|
+
attribute :width, :float
|
11
|
+
attribute :depth, :float
|
12
|
+
attribute :weight, :float
|
13
|
+
attribute :item_condition, :enum, values: ['Damaged','New','Refurbished','Used']
|
14
|
+
attribute :manufacturer, :reference
|
15
|
+
attribute :release_date, :date
|
16
|
+
|
17
|
+
def to_json(render_childs = false)
|
18
|
+
{
|
19
|
+
"@context": "http://schema.org/",
|
20
|
+
"@type": "Product",
|
21
|
+
name: name,
|
22
|
+
image: image,
|
23
|
+
description: description,
|
24
|
+
mpn: mpn,
|
25
|
+
award: awards,
|
26
|
+
brand: brand ? brand.to_json : nil,
|
27
|
+
offers: array_json(offers),
|
28
|
+
itemCondition: "https://schema.org/#{item_condition}Condition",
|
29
|
+
category: category,
|
30
|
+
color: color,
|
31
|
+
height: height,
|
32
|
+
width: width,
|
33
|
+
depth: depth,
|
34
|
+
weight: weight,
|
35
|
+
manufacturer: manufacturer ? manufacturer.to_json : nil,
|
36
|
+
releaseDate: release_date
|
37
|
+
}.delete_if { |k, v| !v.present? }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module RichSnippet
|
2
|
+
class Recipe < Thing
|
3
|
+
attribute :prep_time, :integer
|
4
|
+
attribute :total_time, :integer
|
5
|
+
attribute :cook_time, :integer
|
6
|
+
attribute :cooking_method, :string
|
7
|
+
attribute :recipe_yield, :integer
|
8
|
+
attribute :recipe_ingredients, :stringlist
|
9
|
+
attribute :recipe_cuisine, :string
|
10
|
+
attribute :recipe_category, :string
|
11
|
+
attribute :suitable_for_diet, :string
|
12
|
+
attribute :recipe_instructions, :stringlist
|
13
|
+
attribute :author, :reference
|
14
|
+
|
15
|
+
attribute :calories, :integer
|
16
|
+
attribute :fat_content, :integer
|
17
|
+
attribute :carbohydrate_content, :integer
|
18
|
+
attribute :cholesterol_content, :integer
|
19
|
+
attribute :fiber_content, :integer
|
20
|
+
attribute :protein_content, :integer
|
21
|
+
attribute :saturated_fat_content, :integer
|
22
|
+
attribute :serving_size, :integer
|
23
|
+
attribute :sodium_content, :integer
|
24
|
+
attribute :sugar_content, :integer
|
25
|
+
attribute :trans_fat_content, :integer
|
26
|
+
|
27
|
+
|
28
|
+
def to_json(render_childs = false)
|
29
|
+
{
|
30
|
+
"@context": "http://schema.org",
|
31
|
+
"@type": "Recipe",
|
32
|
+
name: name,
|
33
|
+
description: description,
|
34
|
+
image: image ? image.binary_url : '',
|
35
|
+
url: url,
|
36
|
+
author: author ? author.to_json : nil,
|
37
|
+
prepTime: "PT#{prep_time}M",
|
38
|
+
totalTime: "PT#{total_time}M",
|
39
|
+
cookTime: "PT#{cook_time}M",
|
40
|
+
cookingMethod: cooking_method,
|
41
|
+
recipeYield: recipe_yield,
|
42
|
+
recipeIngredient: recipe_ingredients.split(','),
|
43
|
+
recipeCuisine: recipe_cuisine,
|
44
|
+
recipeCategory: recipe_category,
|
45
|
+
recipeInstructions: recipe_instructions,
|
46
|
+
nutrition: {
|
47
|
+
"@context": "http://schema.org",
|
48
|
+
"@type": "NutritionInformation",
|
49
|
+
calories: "#{calories} calories",
|
50
|
+
fatContent: "#{fat_content} g",
|
51
|
+
carbohydrateContent: "#{carbohydrate_content} g",
|
52
|
+
cholesterolContent: "#{cholesterol_content} mg",
|
53
|
+
fiberContent: "#{fiber_content} g",
|
54
|
+
proteinContent: "#{protein_content} g",
|
55
|
+
saturatedFatContent: "#{saturated_fat_content} g",
|
56
|
+
servingSize: "#{serving_size} #{serving_size == 1 ? 'Serving' : 'Servings'}",
|
57
|
+
sodiumContent: "#{sodium_content} g",
|
58
|
+
sugarContent: "#{sugar_content} g",
|
59
|
+
transFatContent: "#{trans_fat_content} g"
|
60
|
+
},
|
61
|
+
suitableForDiet: {
|
62
|
+
"@context": "http://schema.org",
|
63
|
+
"@type": "RestrictedDiet",
|
64
|
+
description: suitable_for_diet
|
65
|
+
}
|
66
|
+
}.delete_if { |k, v| !v.present? }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module RichSnippet
|
2
|
+
class Thing < Obj
|
3
|
+
attribute :description, :string
|
4
|
+
attribute :image, :reference
|
5
|
+
attribute :title, :string
|
6
|
+
attribute :url, :string
|
7
|
+
|
8
|
+
def name
|
9
|
+
self.title
|
10
|
+
end
|
11
|
+
|
12
|
+
def module
|
13
|
+
self.class.name.demodulize.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
self.class.name.underscore
|
18
|
+
end
|
19
|
+
|
20
|
+
def array_json(attribute)
|
21
|
+
o = []
|
22
|
+
attribute.each do |elem|
|
23
|
+
o << elem.to_json
|
24
|
+
end
|
25
|
+
return o
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_json(render_childs = false)
|
29
|
+
{
|
30
|
+
"@context": "http://schema.org",
|
31
|
+
"@type": "Thing",
|
32
|
+
name: name,
|
33
|
+
description: description,
|
34
|
+
image: image ? image.binary_url : '',
|
35
|
+
url: url
|
36
|
+
}.delete_if { |k, v| !v.present? }
|
37
|
+
end
|
38
|
+
|
39
|
+
def warnings
|
40
|
+
[]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class RichSnippetWidget < Widget
|
2
|
+
attribute :snippet, :reference
|
3
|
+
|
4
|
+
def type
|
5
|
+
self.snippet.type
|
6
|
+
end
|
7
|
+
|
8
|
+
def module
|
9
|
+
self.snippet.module
|
10
|
+
end
|
11
|
+
|
12
|
+
def warnings
|
13
|
+
return ['No snippet selected'] if snippet.blank?
|
14
|
+
snippet.warnings
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_json
|
18
|
+
snippet.to_json(true).to_json
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
<%= render 'rich_snippet/thing/details', obj: obj, url_is_mandatory: false %>
|
2
|
+
|
3
|
+
<%= scrivito_details_for "Event attributes" do %>
|
4
|
+
<%= scrivito_details_for 'Type' do %>
|
5
|
+
<%= scrivito_tag :div, obj, :work_type, data: {scrivito_editors_reload: true} %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%= scrivito_details_for 'about' do %>
|
9
|
+
<%= scrivito_tag :div, obj, :about %>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= scrivito_details_for 'author' do %>
|
13
|
+
<%= scrivito_tag :div, obj, :author, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person', 'Organizazion']}} %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<%= scrivito_details_for 'contributor' do %>
|
17
|
+
<%= scrivito_tag :div, obj, :contributor, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person', 'Organization']}} %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= scrivito_details_for 'copyright_holder' do %>
|
21
|
+
<%= scrivito_tag :div, obj, :copyright_holder, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person', 'Organization']}} %>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<%= scrivito_details_for 'copyright_year' do %>
|
25
|
+
<%= scrivito_tag :div, obj, :copyright_year %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<%= scrivito_details_for 'date_created' do %>
|
29
|
+
<%= scrivito_tag :div, obj, :date_created %>
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<%= scrivito_details_for 'date_published' do %>
|
33
|
+
<%= scrivito_tag :div, obj, :date_published %>
|
34
|
+
<% end %>
|
35
|
+
|
36
|
+
<%= scrivito_details_for 'genre' do %>
|
37
|
+
<%= scrivito_tag :div, obj, :genre %>
|
38
|
+
<% end %>
|
39
|
+
|
40
|
+
<%= scrivito_details_for 'in_language' do %>
|
41
|
+
<%= scrivito_tag :div, obj, :in_language %>
|
42
|
+
<% end %>
|
43
|
+
|
44
|
+
<%= scrivito_details_for 'is_accessible_for_free' do %>
|
45
|
+
<%= scrivito_tag :div, obj, :is_accessible_for_free %>
|
46
|
+
<% end %>
|
47
|
+
|
48
|
+
<%= scrivito_details_for 'is_based_on' do %>
|
49
|
+
<%= scrivito_tag :div, obj, :is_based_on, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['CreativeWork']}} %>
|
50
|
+
<% end %>
|
51
|
+
|
52
|
+
<%= scrivito_details_for 'is_family_friendly' do %>
|
53
|
+
<%= scrivito_tag :div, obj, :is_family_friendly %>
|
54
|
+
<% end %>
|
55
|
+
|
56
|
+
<%= scrivito_details_for 'license' do %>
|
57
|
+
<%= scrivito_tag :div, obj, :license %>
|
58
|
+
<% end %>
|
59
|
+
|
60
|
+
<%= scrivito_details_for 'offers' do %>
|
61
|
+
<%= scrivito_tag :div, obj, :offers, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Offer']}} %>
|
62
|
+
<% end %>
|
63
|
+
|
64
|
+
<%= scrivito_details_for 'position' do %>
|
65
|
+
<%= scrivito_tag :div, obj, :position %>
|
66
|
+
<% end %>
|
67
|
+
|
68
|
+
<%= scrivito_details_for 'publisher' do %>
|
69
|
+
<%= scrivito_tag :div, obj, :publisher, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person', 'Organization']}} %>
|
70
|
+
<% end %>
|
71
|
+
|
72
|
+
<%= scrivito_details_for 'thumbnail_url' do %>
|
73
|
+
<%= scrivito_tag :div, obj, :thumbnail_url %>
|
74
|
+
<% end %>
|
75
|
+
|
76
|
+
<%= scrivito_details_for 'typical_age_range' do %>
|
77
|
+
<%= scrivito_tag :div, obj, :typical_age_range %>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
<% if obj.work_type == 'Book' %>
|
81
|
+
<%= scrivito_details_for "Event attributes" do %>
|
82
|
+
<%= scrivito_details_for 'illustrator' do %>
|
83
|
+
<%= scrivito_tag :div, obj, :illustrator, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person', 'Organization']}} %>
|
84
|
+
<% end %>
|
85
|
+
|
86
|
+
<%= scrivito_details_for 'isbn' do %>
|
87
|
+
<%= scrivito_tag :div, obj, :isbn %>
|
88
|
+
<% end %>
|
89
|
+
|
90
|
+
<%= scrivito_details_for 'number_of_page' do %>
|
91
|
+
<%= scrivito_tag :div, obj, :number_of_page %>
|
92
|
+
<% end %>
|
93
|
+
<% end %>
|
94
|
+
<% end %>
|
95
|
+
|
96
|
+
<% if obj.work_type == 'Movie' %>
|
97
|
+
<%= scrivito_details_for "Event attributes" do %>
|
98
|
+
<%= scrivito_details_for 'actors' do %>
|
99
|
+
<%= scrivito_tag :div, obj, :actors, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person']}} %>
|
100
|
+
<% end %>
|
101
|
+
|
102
|
+
<%= scrivito_details_for 'director' do %>
|
103
|
+
<%= scrivito_tag :div, obj, :director, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person']}} %>
|
104
|
+
<% end %>
|
105
|
+
|
106
|
+
<%= scrivito_details_for 'duration' do %>
|
107
|
+
<%= scrivito_tag :div, obj, :duration %>
|
108
|
+
<% end %>
|
109
|
+
<% end %>
|
110
|
+
<% end %>
|
111
|
+
|
112
|
+
<% if obj.work_type == 'WebPage' %>
|
113
|
+
<%= scrivito_details_for "Event attributes" do %>
|
114
|
+
<%= scrivito_details_for 'breadcrumb' do %>
|
115
|
+
<%= scrivito_tag :div, obj, :breadcrumb %>
|
116
|
+
<% end %>
|
117
|
+
<% end %>
|
118
|
+
<% end %>
|
119
|
+
|
120
|
+
<% if obj.work_type == 'MusicComposition' %>
|
121
|
+
<%= scrivito_details_for "Event attributes" do %>
|
122
|
+
<%= scrivito_details_for 'composer' do %>
|
123
|
+
<%= scrivito_tag :div, obj, :composer, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person', 'Organization']}} %>
|
124
|
+
<% end %>
|
125
|
+
|
126
|
+
<%= scrivito_details_for 'lyricist' do %>
|
127
|
+
<%= scrivito_tag :div, obj, :lyricist, data: {scrivito_editors_filter_context: {rich_snippet_filter: ['Person']}} %>
|
128
|
+
<% end %>
|
129
|
+
|
130
|
+
<%= scrivito_details_for 'lyrics' do %>
|
131
|
+
<%= scrivito_tag :div, obj, :lyrics %>
|
132
|
+
<% end %>
|
133
|
+
<% end %>
|
134
|
+
<% end %>
|
135
|
+
|
136
|
+
<% end %>
|