page_structured_data 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +14 -3
- data/app/src/page_structured_data/breadcrumbs.rb +17 -12
- data/app/src/page_structured_data/page.rb +8 -3
- data/app/src/page_structured_data/page_types/article.rb +50 -0
- data/app/src/page_structured_data/page_types/blog_posting.rb +4 -36
- data/app/src/page_structured_data/page_types/news_article.rb +4 -36
- data/lib/page_structured_data/version.rb +1 -1
- data/lib/page_structured_data.rb +7 -0
- metadata +9 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3158329319534cff0f6011223d8ae6d16f6979742ded26e443633f45f2a9aaaf
|
|
4
|
+
data.tar.gz: 9dc54a0d21f0e8567b1957e69fc86220771c4e0eeee04bdcb21238fb56c579b0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6f7dd3da1c510fea597608fc15473d9f79970f827de8a53576ae9574a3bd0f6aef8c6e015b03406aa0b7d48ac1c9fc65f1de6288fe520e8a673fc2bc357cf1f8
|
|
7
|
+
data.tar.gz: bfaa6dc28249dcf07cebeb8c8faf4c42af521f181030fd2712c0520abf922092eda33c0cccd598c8a00bd15485bee9247d321d9f10855768ecc8d8bcc4d7325f
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 1.0.6 - 2026-05-06
|
|
8
|
+
|
|
9
|
+
- Add tests for HTML escaping in rendered meta tags.
|
|
10
|
+
- Add tests for script-breaking content in JSON-LD output.
|
|
11
|
+
- Add broader JSON-LD escaping coverage for breadcrumbs and article data.
|
|
12
|
+
- Extract shared article JSON-LD behavior for `BlogPosting` and `NewsArticle`.
|
|
13
|
+
- Add `to_h` schema hash APIs for breadcrumbs and article page types.
|
|
14
|
+
- Add tests for pages that render both breadcrumb and page type JSON-LD.
|
|
15
|
+
- Align the gemspec Ruby requirement with the Rails 7 baseline.
|
|
16
|
+
- Add GitHub Actions CI for tests, require verification, and gem build verification.
|
|
17
|
+
- Constrain the Rails dependency to Rails 7.x, matching the tested support baseline.
|
|
18
|
+
- Add `render_default_breadcrumb_json_ld` config to opt out of current-page-only breadcrumb JSON-LD.
|
|
19
|
+
- Add CI coverage for Rails 7.0, 7.1, 7.2, 8.0, and 8.1.
|
|
20
|
+
- Widen the Rails dependency to support Rails 7.x and 8.x.
|
|
21
|
+
|
|
22
|
+
## 1.0.5 - 2026-05-06
|
|
23
|
+
|
|
24
|
+
- Previous public release.
|
|
25
|
+
|
|
7
26
|
## 1.0.4 - 2026-05-06
|
|
8
27
|
|
|
9
28
|
- Replace the bundled Slim meta tags partial with ERB so applications are not required to use Slim.
|
data/README.md
CHANGED
|
@@ -17,8 +17,10 @@ It helps Rails applications render:
|
|
|
17
17
|
|
|
18
18
|
## Requirements
|
|
19
19
|
|
|
20
|
-
- Rails 7.
|
|
21
|
-
-
|
|
20
|
+
- Rails 7.x or 8.x
|
|
21
|
+
- Ruby 2.7 or newer
|
|
22
|
+
|
|
23
|
+
Rails 7.0 requires Ruby 2.7 or newer, so this gem follows that same baseline. Rails 8 requires Ruby 3.2 or newer, so Rails 8 applications must use a Ruby version supported by Rails 8.
|
|
22
24
|
|
|
23
25
|
## Installation
|
|
24
26
|
|
|
@@ -43,12 +45,15 @@ Configure application-wide defaults in an initializer:
|
|
|
43
45
|
Rails.application.config.after_initialize do
|
|
44
46
|
PageStructuredData.config do |config|
|
|
45
47
|
config.base_app_name = "AwesomestApp"
|
|
48
|
+
config.render_default_breadcrumb_json_ld = true
|
|
46
49
|
end
|
|
47
50
|
end
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
`base_app_name` is appended to generated page titles.
|
|
51
54
|
|
|
55
|
+
`render_default_breadcrumb_json_ld` controls whether pages without an explicit breadcrumb render current-page-only breadcrumb JSON-LD. It defaults to `true` for backward compatibility. Set it to `false` if you only want breadcrumb JSON-LD when a `PageStructuredData::Breadcrumbs` object is passed to the page.
|
|
56
|
+
|
|
52
57
|
For example:
|
|
53
58
|
|
|
54
59
|
```ruby
|
|
@@ -125,7 +130,7 @@ Pass the breadcrumbs into the page object:
|
|
|
125
130
|
|
|
126
131
|
This renders `BreadcrumbList` JSON-LD similar to Google's breadcrumb structured data format.
|
|
127
132
|
|
|
128
|
-
Current compatibility note: when no breadcrumb object is passed, `PageStructuredData::Page`
|
|
133
|
+
Current compatibility note: when no breadcrumb object is passed, `PageStructuredData::Page` renders current-page-only breadcrumb JSON-LD by default. To opt out, set `config.render_default_breadcrumb_json_ld = false`.
|
|
129
134
|
|
|
130
135
|
## Article Page Types
|
|
131
136
|
|
|
@@ -196,6 +201,7 @@ PageStructuredData::Breadcrumbs.new(
|
|
|
196
201
|
Important methods:
|
|
197
202
|
|
|
198
203
|
- `titles`: returns breadcrumb titles.
|
|
204
|
+
- `to_h(current_page_title:)`: returns a structured hash for `BreadcrumbList` JSON-LD.
|
|
199
205
|
- `json_ld(current_page_title:)`: returns a `BreadcrumbList` JSON-LD script tag.
|
|
200
206
|
|
|
201
207
|
### Article Page Types
|
|
@@ -222,6 +228,11 @@ PageStructuredData::PageTypes::NewsArticle.new(
|
|
|
222
228
|
|
|
223
229
|
`authors` should be an array of hashes with `:name` and `:url` keys.
|
|
224
230
|
|
|
231
|
+
Important methods:
|
|
232
|
+
|
|
233
|
+
- `to_h`: returns a structured hash for article JSON-LD.
|
|
234
|
+
- `json_ld`: returns an article JSON-LD script tag.
|
|
235
|
+
|
|
225
236
|
## Development
|
|
226
237
|
|
|
227
238
|
Run the test suite:
|
|
@@ -13,15 +13,28 @@ module PageStructuredData
|
|
|
13
13
|
hierarchy.pluck(:title)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def
|
|
17
|
-
|
|
16
|
+
def to_h(current_page_title:) # rubocop:disable Metrics/MethodLength
|
|
17
|
+
{
|
|
18
18
|
'@context': 'https://schema.org',
|
|
19
19
|
'@type': 'BreadcrumbList',
|
|
20
|
-
'itemListElement':
|
|
21
|
-
}
|
|
20
|
+
'itemListElement': item_list_elements(current_page_title: current_page_title),
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def json_ld(current_page_title:)
|
|
25
|
+
%(
|
|
26
|
+
<script type="application/ld+json">
|
|
27
|
+
#{to_h(current_page_title: current_page_title).to_json}
|
|
28
|
+
</script>
|
|
29
|
+
)
|
|
30
|
+
end
|
|
22
31
|
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def item_list_elements(current_page_title:)
|
|
23
35
|
items = []
|
|
24
36
|
count = 0
|
|
37
|
+
|
|
25
38
|
@hierarchy.each do |page|
|
|
26
39
|
items << {
|
|
27
40
|
'@type': 'ListItem',
|
|
@@ -36,14 +49,6 @@ module PageStructuredData
|
|
|
36
49
|
position: (count += 1),
|
|
37
50
|
name: current_page_title,
|
|
38
51
|
}
|
|
39
|
-
|
|
40
|
-
node['itemListElement'] = items
|
|
41
|
-
|
|
42
|
-
%(
|
|
43
|
-
<script type="application/ld+json">
|
|
44
|
-
#{node.to_json}
|
|
45
|
-
</script>
|
|
46
|
-
)
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
54
|
end
|
|
@@ -13,8 +13,6 @@ module PageStructuredData
|
|
|
13
13
|
@extra_title = extra_title
|
|
14
14
|
@breadcrumb = breadcrumb
|
|
15
15
|
@page_type = page_type
|
|
16
|
-
|
|
17
|
-
@breadcrumb = Breadcrumbs.new if breadcrumb.blank?
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def title_with_hierarchies
|
|
@@ -33,13 +31,20 @@ module PageStructuredData
|
|
|
33
31
|
|
|
34
32
|
def json_lds
|
|
35
33
|
output = []
|
|
36
|
-
output <<
|
|
34
|
+
output << breadcrumb_json_ld if (breadcrumb_json_ld = self.breadcrumb_json_ld).present?
|
|
37
35
|
output << page_type.json_ld if page_type.present?
|
|
38
36
|
output.join
|
|
39
37
|
end
|
|
40
38
|
|
|
41
39
|
private
|
|
42
40
|
|
|
41
|
+
def breadcrumb_json_ld
|
|
42
|
+
return breadcrumb.json_ld(current_page_title: title) if breadcrumb.present?
|
|
43
|
+
return unless PageStructuredData.render_default_breadcrumb_json_ld
|
|
44
|
+
|
|
45
|
+
Breadcrumbs.new.json_ld(current_page_title: title)
|
|
46
|
+
end
|
|
47
|
+
|
|
43
48
|
def base_app_name
|
|
44
49
|
PageStructuredData.base_app_name
|
|
45
50
|
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PageStructuredData
|
|
4
|
+
module PageTypes
|
|
5
|
+
# Shared structured data for schema.org article-like page types.
|
|
6
|
+
class Article
|
|
7
|
+
attr_reader :headline, :images, :published_at, :updated_at, :authors
|
|
8
|
+
|
|
9
|
+
def initialize(headline:, published_at:, updated_at:, images: [], authors: [])
|
|
10
|
+
@headline = headline
|
|
11
|
+
@images = images
|
|
12
|
+
@published_at = published_at
|
|
13
|
+
@updated_at = updated_at
|
|
14
|
+
@authors = authors
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_h
|
|
18
|
+
{
|
|
19
|
+
'@context': 'https://schema.org',
|
|
20
|
+
'@type': schema_type,
|
|
21
|
+
headline: headline,
|
|
22
|
+
image: images,
|
|
23
|
+
datePublished: published_at,
|
|
24
|
+
dateModified: updated_at,
|
|
25
|
+
author: authors.map do |author|
|
|
26
|
+
{
|
|
27
|
+
'@type': 'Person',
|
|
28
|
+
name: author[:name],
|
|
29
|
+
url: author[:url],
|
|
30
|
+
}
|
|
31
|
+
end,
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def json_ld
|
|
36
|
+
%(
|
|
37
|
+
<script type="application/ld+json">
|
|
38
|
+
#{to_h.to_json}
|
|
39
|
+
</script>
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def schema_type
|
|
46
|
+
raise NotImplementedError, "#{self.class.name} must define #schema_type"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -3,43 +3,11 @@
|
|
|
3
3
|
module PageStructuredData
|
|
4
4
|
module PageTypes
|
|
5
5
|
# Basic page metadata for any page
|
|
6
|
-
class BlogPosting
|
|
7
|
-
|
|
6
|
+
class BlogPosting < Article
|
|
7
|
+
private
|
|
8
8
|
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
@images = images
|
|
12
|
-
@published_at = published_at
|
|
13
|
-
@updated_at = updated_at
|
|
14
|
-
@authors = authors
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def json_ld # rubocop:disable Metrics/MethodLength
|
|
18
|
-
node = {
|
|
19
|
-
'@context': 'https://schema.org',
|
|
20
|
-
'@type': 'BlogPosting',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
node[:headline] = headline
|
|
24
|
-
node[:image] = images
|
|
25
|
-
node[:datePublished] = published_at
|
|
26
|
-
node[:dateModified] = updated_at
|
|
27
|
-
|
|
28
|
-
author_hash = authors.map do |author|
|
|
29
|
-
{
|
|
30
|
-
'@type': 'Person',
|
|
31
|
-
name: author[:name],
|
|
32
|
-
url: author[:url],
|
|
33
|
-
}
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
node[:author] = author_hash
|
|
37
|
-
|
|
38
|
-
%(
|
|
39
|
-
<script type="application/ld+json">
|
|
40
|
-
#{node.to_json}
|
|
41
|
-
</script>
|
|
42
|
-
)
|
|
9
|
+
def schema_type
|
|
10
|
+
'BlogPosting'
|
|
43
11
|
end
|
|
44
12
|
end
|
|
45
13
|
end
|
|
@@ -3,43 +3,11 @@
|
|
|
3
3
|
module PageStructuredData
|
|
4
4
|
module PageTypes
|
|
5
5
|
# Basic page metadata for any page
|
|
6
|
-
class NewsArticle
|
|
7
|
-
|
|
6
|
+
class NewsArticle < Article
|
|
7
|
+
private
|
|
8
8
|
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
@images = images
|
|
12
|
-
@published_at = published_at
|
|
13
|
-
@updated_at = updated_at
|
|
14
|
-
@authors = authors
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def json_ld # rubocop:disable Metrics/MethodLength
|
|
18
|
-
node = {
|
|
19
|
-
'@context': 'https://schema.org',
|
|
20
|
-
'@type': 'NewsArticle',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
node[:headline] = headline
|
|
24
|
-
node[:image] = images
|
|
25
|
-
node[:datePublished] = published_at
|
|
26
|
-
node[:dateModified] = updated_at
|
|
27
|
-
|
|
28
|
-
author_hash = authors.map do |author|
|
|
29
|
-
{
|
|
30
|
-
'@type': 'Person',
|
|
31
|
-
name: author[:name],
|
|
32
|
-
url: author[:url],
|
|
33
|
-
}
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
node[:author] = author_hash
|
|
37
|
-
|
|
38
|
-
%(
|
|
39
|
-
<script type="application/ld+json">
|
|
40
|
-
#{node.to_json}
|
|
41
|
-
</script>
|
|
42
|
-
)
|
|
9
|
+
def schema_type
|
|
10
|
+
'NewsArticle'
|
|
43
11
|
end
|
|
44
12
|
end
|
|
45
13
|
end
|
data/lib/page_structured_data.rb
CHANGED
|
@@ -4,9 +4,16 @@ require "page_structured_data/engine"
|
|
|
4
4
|
module PageStructuredData
|
|
5
5
|
class << self
|
|
6
6
|
attr_accessor :base_app_name
|
|
7
|
+
attr_writer :render_default_breadcrumb_json_ld
|
|
7
8
|
|
|
8
9
|
def config
|
|
9
10
|
yield self
|
|
10
11
|
end
|
|
12
|
+
|
|
13
|
+
def render_default_breadcrumb_json_ld
|
|
14
|
+
return true if @render_default_breadcrumb_json_ld.nil?
|
|
15
|
+
|
|
16
|
+
@render_default_breadcrumb_json_ld
|
|
17
|
+
end
|
|
11
18
|
end
|
|
12
19
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: page_structured_data
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jey Geethan
|
|
@@ -17,6 +17,9 @@ dependencies:
|
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: 7.0.0
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '9.0'
|
|
20
23
|
type: :runtime
|
|
21
24
|
prerelease: false
|
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -24,6 +27,9 @@ dependencies:
|
|
|
24
27
|
- - ">="
|
|
25
28
|
- !ruby/object:Gem::Version
|
|
26
29
|
version: 7.0.0
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '9.0'
|
|
27
33
|
description: PageStructuredData gives Rails applications a small page object and view
|
|
28
34
|
partial for rendering page titles, basic meta tags, Open Graph tags, Twitter card
|
|
29
35
|
tags, breadcrumb JSON-LD, and article JSON-LD.
|
|
@@ -47,6 +53,7 @@ files:
|
|
|
47
53
|
- app/src/page_structured_data/anchors.rb
|
|
48
54
|
- app/src/page_structured_data/breadcrumbs.rb
|
|
49
55
|
- app/src/page_structured_data/page.rb
|
|
56
|
+
- app/src/page_structured_data/page_types/article.rb
|
|
50
57
|
- app/src/page_structured_data/page_types/blog_posting.rb
|
|
51
58
|
- app/src/page_structured_data/page_types/news_article.rb
|
|
52
59
|
- app/views/layouts/page_structured_data/application.html.erb
|
|
@@ -75,7 +82,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
75
82
|
requirements:
|
|
76
83
|
- - ">="
|
|
77
84
|
- !ruby/object:Gem::Version
|
|
78
|
-
version: 2.
|
|
85
|
+
version: 2.7.0
|
|
79
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
87
|
requirements:
|
|
81
88
|
- - ">="
|