page_structured_data 1.0.9 → 1.0.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53bab1f6112cc7060c86d1eedc6096770ea5a6363a9d4e9939094f3576a417cf
4
- data.tar.gz: ecea9e6efd8b44bf45565ec1a790905b55e7794579a91d2b157dec1325ad89c5
3
+ metadata.gz: 9ffd04020a9a4ba900bb7d4bbdac9dd827d48535073a30c657865469df9e1988
4
+ data.tar.gz: 4b560fee8a434599acd2ae619fdc7e4a0973f29aa77f8b95191a270047767931
5
5
  SHA512:
6
- metadata.gz: fda27db244422de502060211a86f759ca0fe7249a8a370fb7d3f7a89ed2f732181eff65d7c8b19ab48a61cc9be4168dae18c14edb1016d2ba7d97941b343c50b
7
- data.tar.gz: 78dcbcefc064a3806f41c8f8d83f1943181e05c260501a207cff31ff425f5ad68e2fcf6d436351e4a58ded9c2c4ee12b4768d0f1f27c822951bde8682b4f381d
6
+ metadata.gz: '08329eddfdf9f7e3682a6016ca84d25b1867e4ce8ebca4c4e7654536b4dff59b8d825351b4489b69342c42d2cc52ab41d96bba1f3cc8adf5a1f8180330d660ba'
7
+ data.tar.gz: 270c98e7c0071b9e09e75482a5d766ec685f8a7da103c3ddb15f4df03e895b98fcc52d57e50b93cbfddd992de7d0fbdf6d5de9542b07fec52d0eab977da2903f
data/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ All notable changes to this project are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 1.0.11 - 2026-05-06
8
+
9
+ - Add optional `description` and `founder` support to organization page types.
10
+
11
+ ## 1.0.10 - 2026-05-06
12
+
13
+ - Add JSON-LD escaping coverage for organization page types.
14
+ - Add `PageStructuredData::PageTypes::WebSite` for schema.org WebSite JSON-LD.
15
+ - Add `page_types:` support for rendering multiple page type JSON-LD scripts.
16
+ - Add `canonical_url` and `fallback_image` options to `Page`.
17
+
7
18
  ## 1.0.9 - 2026-05-06
8
19
 
9
20
  - Add release preparation script and release checklist documentation.
data/README.md CHANGED
@@ -14,7 +14,7 @@ It helps Rails applications render:
14
14
  - Google-compatible JSON-LD structured data
15
15
  - Breadcrumb structured data
16
16
  - Article structured data for `BlogPosting` and `NewsArticle`
17
- - Organization structured data
17
+ - Organization and WebSite structured data
18
18
 
19
19
  ## Requirements
20
20
 
@@ -93,7 +93,9 @@ Set `@page_meta` in the controller or view before the layout renders:
93
93
  title: "Home",
94
94
  extra_title: "Official Page",
95
95
  description: "Welcome to my page",
96
- image: image_url("social/home.png")
96
+ image: image_url("social/home.png"),
97
+ canonical_url: home_url,
98
+ fallback_image: image_url("social/default.png")
97
99
  )
98
100
  ```
99
101
 
@@ -133,13 +135,14 @@ This renders `BreadcrumbList` JSON-LD similar to Google's breadcrumb structured
133
135
 
134
136
  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`.
135
137
 
136
- ## Article Page Types
138
+ ## Structured Page Types
137
139
 
138
140
  PageStructuredData includes page types for:
139
141
 
140
142
  - [`BlogPosting`](https://schema.org/BlogPosting)
141
143
  - [`NewsArticle`](https://schema.org/NewsArticle)
142
144
  - [`Organization`](https://schema.org/Organization)
145
+ - [`WebSite`](https://schema.org/WebSite)
143
146
 
144
147
  Use a page type when the current page represents an article:
145
148
 
@@ -176,8 +179,14 @@ Use `Organization` when the current page represents an organization:
176
179
  organization_page_type = PageStructuredData::PageTypes::Organization.new(
177
180
  name: "RocketApex",
178
181
  url: "https://rocketapex.com",
182
+ description: "Open source projects from RocketApex",
179
183
  logo: "https://rocketapex.com/logo.png",
180
184
  same_as: ["https://github.com/RocketApex"],
185
+ founder: {
186
+ "@type": "Person",
187
+ name: "Jane Doe",
188
+ url: "https://example.com/jane"
189
+ },
181
190
  parent_organization: {
182
191
  name: "Parent Org",
183
192
  url: "https://parent.example"
@@ -191,6 +200,30 @@ organization_page_type = PageStructuredData::PageTypes::Organization.new(
191
200
  )
192
201
  ```
193
202
 
203
+ Use `WebSite` with `Organization` when the current page represents a site or homepage:
204
+
205
+ ```ruby
206
+ organization_page_type = PageStructuredData::PageTypes::Organization.new(
207
+ name: "RocketApex",
208
+ url: "https://rocketapex.com",
209
+ logo: "https://rocketapex.com/logo.png"
210
+ )
211
+
212
+ website_page_type = PageStructuredData::PageTypes::WebSite.new(
213
+ name: "RocketApex",
214
+ url: "https://rocketapex.com",
215
+ description: "Open source projects from RocketApex",
216
+ publisher: organization_page_type
217
+ )
218
+
219
+ @page_meta = PageStructuredData::Page.new(
220
+ title: "RocketApex",
221
+ description: "Open source projects from RocketApex",
222
+ canonical_url: "https://rocketapex.com",
223
+ page_types: [organization_page_type, website_page_type]
224
+ )
225
+ ```
226
+
194
227
  ## API Reference
195
228
 
196
229
  ### `PageStructuredData::Page`
@@ -202,7 +235,10 @@ PageStructuredData::Page.new(
202
235
  image: nil,
203
236
  extra_title: "",
204
237
  breadcrumb: nil,
205
- page_type: nil
238
+ page_type: nil,
239
+ page_types: nil,
240
+ canonical_url: nil,
241
+ fallback_image: nil
206
242
  )
207
243
  ```
208
244
 
@@ -210,6 +246,7 @@ Important methods:
210
246
 
211
247
  - `page_title`: returns the composed page title.
212
248
  - `json_lds`: returns the JSON-LD script tags for breadcrumbs and page type data.
249
+ - `resolved_image`: returns `image` or `fallback_image`.
213
250
 
214
251
  ### `PageStructuredData::Breadcrumbs`
215
252
 
@@ -262,19 +299,41 @@ Important methods:
262
299
  PageStructuredData::PageTypes::Organization.new(
263
300
  name:,
264
301
  url:,
302
+ description: nil,
265
303
  logo: nil,
266
304
  same_as: [],
267
- parent_organization: nil
305
+ parent_organization: nil,
306
+ founder: nil
268
307
  )
269
308
  ```
270
309
 
271
310
  `parent_organization` should be a hash with `:name` and `:url` keys.
311
+ `founder` should be a hash or another object that responds to `to_h`.
272
312
 
273
313
  Important methods:
274
314
 
275
315
  - `to_h`: returns a structured hash for organization JSON-LD.
276
316
  - `json_ld`: returns an organization JSON-LD script tag.
277
317
 
318
+ ### WebSite Page Type
319
+
320
+ ```ruby
321
+ PageStructuredData::PageTypes::WebSite.new(
322
+ name:,
323
+ url:,
324
+ description: nil,
325
+ publisher: nil,
326
+ potential_action: nil
327
+ )
328
+ ```
329
+
330
+ `publisher` can be a hash or another page type that responds to `to_h`, such as `PageStructuredData::PageTypes::Organization`.
331
+
332
+ Important methods:
333
+
334
+ - `to_h`: returns a structured hash for WebSite JSON-LD.
335
+ - `json_ld`: returns a WebSite JSON-LD script tag.
336
+
278
337
  ## Development
279
338
 
280
339
  Run the test suite:
@@ -3,16 +3,21 @@
3
3
  module PageStructuredData
4
4
  # Basic page metadata for any page
5
5
  class Page
6
- attr_reader :title, :description, :image, :extra_title, :breadcrumb, :page_type
6
+ attr_reader :title, :description, :image, :extra_title, :breadcrumb, :page_type, :page_types, :canonical_url,
7
+ :fallback_image
7
8
 
8
9
  def initialize(title:, description: nil, image: nil, # rubocop:disable Metrics/ParameterLists
9
- extra_title: '', breadcrumb: nil, page_type: nil)
10
+ extra_title: '', breadcrumb: nil, page_type: nil, page_types: nil, canonical_url: nil,
11
+ fallback_image: nil)
10
12
  @title = title
11
13
  @description = description
12
14
  @image = image
13
15
  @extra_title = extra_title
14
16
  @breadcrumb = breadcrumb
15
17
  @page_type = page_type
18
+ @page_types = page_types
19
+ @canonical_url = canonical_url
20
+ @fallback_image = fallback_image
16
21
  end
17
22
 
18
23
  def title_with_hierarchies
@@ -32,12 +37,20 @@ module PageStructuredData
32
37
  def json_lds
33
38
  output = []
34
39
  output << breadcrumb_json_ld if (breadcrumb_json_ld = self.breadcrumb_json_ld).present?
35
- output << page_type.json_ld if page_type.present?
40
+ resolved_page_types.each { |resolved_page_type| output << resolved_page_type.json_ld }
36
41
  output.join
37
42
  end
38
43
 
44
+ def resolved_image
45
+ image || fallback_image
46
+ end
47
+
39
48
  private
40
49
 
50
+ def resolved_page_types
51
+ Array.wrap(page_types.presence || page_type).compact
52
+ end
53
+
41
54
  def breadcrumb_json_ld
42
55
  return breadcrumb.json_ld(current_page_title: title) if breadcrumb.present?
43
56
  return unless PageStructuredData.render_default_breadcrumb_json_ld
@@ -4,14 +4,16 @@ module PageStructuredData
4
4
  module PageTypes
5
5
  # Organization structured data for a page
6
6
  class Organization
7
- attr_reader :name, :url, :logo, :same_as, :parent_organization
7
+ attr_reader :name, :url, :description, :logo, :same_as, :parent_organization, :founder
8
8
 
9
- def initialize(name:, url:, logo: nil, same_as: [], parent_organization: nil)
9
+ def initialize(name:, url:, description: nil, logo: nil, same_as: [], parent_organization: nil, founder: nil)
10
10
  @name = name
11
11
  @url = url
12
+ @description = description
12
13
  @logo = logo
13
14
  @same_as = same_as
14
15
  @parent_organization = parent_organization
16
+ @founder = founder
15
17
  end
16
18
 
17
19
  def to_h # rubocop:disable Metrics/MethodLength
@@ -22,8 +24,10 @@ module PageStructuredData
22
24
 
23
25
  node[:name] = name
24
26
  node[:url] = url
27
+ node[:description] = description if description.present?
25
28
  node[:logo] = logo if logo.present?
26
29
  node[:sameAs] = same_as if same_as.present?
30
+ node[:founder] = founder_to_h if founder.present?
27
31
 
28
32
  if parent_organization.present?
29
33
  node[:parentOrganization] = {
@@ -43,6 +47,14 @@ module PageStructuredData
43
47
  </script>
44
48
  )
45
49
  end
50
+
51
+ private
52
+
53
+ def founder_to_h
54
+ return founder.to_h if founder.respond_to?(:to_h)
55
+
56
+ founder
57
+ end
46
58
  end
47
59
  end
48
60
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PageStructuredData
4
+ module PageTypes
5
+ # WebSite structured data for a page
6
+ class WebSite
7
+ attr_reader :name, :url, :description, :publisher, :potential_action
8
+
9
+ def initialize(name:, url:, description: nil, publisher: nil, potential_action: nil)
10
+ @name = name
11
+ @url = url
12
+ @description = description
13
+ @publisher = publisher
14
+ @potential_action = potential_action
15
+ end
16
+
17
+ def to_h
18
+ node = {
19
+ '@context': 'https://schema.org',
20
+ '@type': 'WebSite',
21
+ name: name,
22
+ url: url,
23
+ }
24
+
25
+ node[:description] = description if description.present?
26
+ node[:publisher] = publisher_to_h if publisher.present?
27
+ node[:potentialAction] = potential_action if potential_action.present?
28
+
29
+ node
30
+ end
31
+
32
+ def json_ld
33
+ %(
34
+ <script type="application/ld+json">
35
+ #{to_h.to_json}
36
+ </script>
37
+ )
38
+ end
39
+
40
+ private
41
+
42
+ def publisher_to_h
43
+ return publisher.to_h if publisher.respond_to?(:to_h)
44
+
45
+ publisher
46
+ end
47
+ end
48
+ end
49
+ end
@@ -2,9 +2,13 @@
2
2
 
3
3
  <% title = page&.page_title %>
4
4
  <% description = page&.description %>
5
- <% image = page&.image || default_image_url || nil %>
5
+ <% image = page&.resolved_image || default_image_url || nil %>
6
+ <% canonical_url = page&.canonical_url %>
6
7
 
7
8
  <title><%= title %></title>
9
+ <% if canonical_url.present? %>
10
+ <link rel="canonical" href="<%= canonical_url %>">
11
+ <% end %>
8
12
 
9
13
  <meta name="title" content="<%= title %>">
10
14
  <meta name="description" content="<%= description %>">
@@ -1,3 +1,3 @@
1
1
  module PageStructuredData
2
- VERSION = "1.0.9"
2
+ VERSION = "1.0.11"
3
3
  end
@@ -6,6 +6,7 @@ require_relative "../app/src/page_structured_data/page_types/article"
6
6
  require_relative "../app/src/page_structured_data/page_types/blog_posting"
7
7
  require_relative "../app/src/page_structured_data/page_types/news_article"
8
8
  require_relative "../app/src/page_structured_data/page_types/organization"
9
+ require_relative "../app/src/page_structured_data/page_types/web_site"
9
10
  require_relative "../app/src/page_structured_data/page"
10
11
 
11
12
  module PageStructuredData
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.9
4
+ version: 1.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jey Geethan
@@ -50,6 +50,7 @@ files:
50
50
  - app/src/page_structured_data/page_types/blog_posting.rb
51
51
  - app/src/page_structured_data/page_types/news_article.rb
52
52
  - app/src/page_structured_data/page_types/organization.rb
53
+ - app/src/page_structured_data/page_types/web_site.rb
53
54
  - app/views/page_structured_data/_meta_tags.html.erb
54
55
  - config/routes.rb
55
56
  - lib/page_structured_data.rb