schema_dot_org 2.4.0 → 2.5.1
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 +7 -0
- data/CLAUDE.md +91 -0
- data/Gemfile.lock +47 -34
- data/README.md +67 -35
- data/lib/schema_dot_org/discussion_forum_posting.rb +3 -4
- data/lib/schema_dot_org/organization.rb +2 -0
- data/lib/schema_dot_org/place.rb +3 -1
- data/lib/schema_dot_org/postal_address.rb +34 -0
- data/lib/schema_dot_org/url_validator.rb +37 -0
- data/lib/schema_dot_org.rb +35 -2
- data/schema_dot_org.gemspec +5 -3
- metadata +37 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51ce5547733a21842002c07e64f087879b748fc0aca5f38be3b1719050b44eb8
|
4
|
+
data.tar.gz: 847aa9795b17a6903e6a8380ad24e11ae74f14db46225c6bf78965ec585c67a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5b6d909e5edd6999ee5051f1df5b0b8c5f5274172b1f602be3c17e2a5c0fcad9c0499e930e9a757c5c42d62597af4b2e8c89898c534008f63172567113cb53f
|
7
|
+
data.tar.gz: 04e8ef548d8dcf6dfb2e077fc759a472d29fe0da8a28a28b69b23e79b900daeebaa192d1e55c645dee169381252c20bba14930f2d6f4ecd8a42b93bb127e3aab
|
data/CHANGELOG.md
ADDED
data/CLAUDE.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# CLAUDE.md
|
2
|
+
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
This is a Ruby gem that generates structured data (JSON-LD) for Schema.org types. It provides strongly-typed Ruby classes that validate their attributes and output valid Schema.org markup for SEO and search enhancement.
|
8
|
+
|
9
|
+
## Development Commands
|
10
|
+
|
11
|
+
### Testing
|
12
|
+
- `bundle exec rake spec` or `bundle exec rspec` - Run all RSpec tests
|
13
|
+
- `bundle exec rspec spec/schema_dot_org/[type]_spec.rb` - Run tests for a specific Schema.org type
|
14
|
+
- `bundle exec rake` - Run default task (runs tests)
|
15
|
+
|
16
|
+
### Gem Management
|
17
|
+
- `gem build schema_dot_org.gemspec` - Build the gem locally
|
18
|
+
- `gem install ./schema_dot_org-[version].gem` - Install built gem locally
|
19
|
+
- `bundle install` - Install dependencies
|
20
|
+
|
21
|
+
### Interactive Development
|
22
|
+
- `bundle exec pry` - Start Pry REPL with gem loaded for interactive testing
|
23
|
+
|
24
|
+
## Architecture
|
25
|
+
|
26
|
+
### Core Components
|
27
|
+
|
28
|
+
**SchemaType Base Class** (`lib/schema_dot_org.rb`):
|
29
|
+
- Abstract base class for all Schema.org types
|
30
|
+
- Handles JSON-LD generation with `to_json_ld()` and `to_s()` methods
|
31
|
+
- Converts snake_case Ruby attributes to camelCase JSON-LD
|
32
|
+
- Provides validation through ValidatedObject gem integration
|
33
|
+
- Automatically adds `@context` and `@type` fields
|
34
|
+
|
35
|
+
**Schema.org Type Classes** (`lib/schema_dot_org/*.rb`):
|
36
|
+
- Each file represents one Schema.org type (Organization, Person, BreadcrumbList, etc.)
|
37
|
+
- Classes inherit from SchemaType and use `validated_attr` for type-safe attributes
|
38
|
+
- Follow pattern: `validated_attr :attribute_name, type: [Type], allow_nil: true/false`
|
39
|
+
|
40
|
+
**URL Validation** (`lib/schema_dot_org/url_validator.rb`):
|
41
|
+
- Validates URLs used in structured data
|
42
|
+
- Used by convenience methods like `make_breadcrumbs`
|
43
|
+
|
44
|
+
### Design Patterns
|
45
|
+
|
46
|
+
**Validation-First Approach**:
|
47
|
+
- All attributes are validated at object creation time
|
48
|
+
- Invalid data causes immediate ArgumentError/NoMethodError rather than silent failures
|
49
|
+
- Uses ActiveRecord-style validations via ValidatedObject gem
|
50
|
+
|
51
|
+
**Declarative Attribute Definition**:
|
52
|
+
```ruby
|
53
|
+
class Product < SchemaType
|
54
|
+
validated_attr :name, type: String
|
55
|
+
validated_attr :description, type: String, allow_nil: true
|
56
|
+
validated_attr :offers, type: SchemaDotOrg::AggregateOffer
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
**Nested Schema Types**:
|
61
|
+
- Schema types can reference other schema types as attributes
|
62
|
+
- Automatic JSON-LD nesting handled by base class
|
63
|
+
- Example: Organization can have Person founder, Place founding_location
|
64
|
+
|
65
|
+
### Key Files Structure
|
66
|
+
|
67
|
+
- `lib/schema_dot_org.rb` - Main module, base SchemaType class, convenience methods
|
68
|
+
- `lib/schema_dot_org/[type].rb` - Individual Schema.org type implementations
|
69
|
+
- `spec/schema_dot_org/[type]_spec.rb` - RSpec tests for each type
|
70
|
+
- `spec/spec_helper.rb` - RSpec configuration with doctest2 integration
|
71
|
+
|
72
|
+
### Testing Patterns
|
73
|
+
|
74
|
+
- Each Schema.org type has corresponding RSpec test file
|
75
|
+
- Tests validate both successful creation and error conditions
|
76
|
+
- Tests verify correct JSON-LD output format
|
77
|
+
- Uses doctest2-rspec for testing code examples in comments
|
78
|
+
|
79
|
+
## Adding New Schema.org Types
|
80
|
+
|
81
|
+
1. Create new file `lib/schema_dot_org/new_type.rb`
|
82
|
+
2. Define class inheriting from SchemaType with validated_attr declarations
|
83
|
+
3. Add require statement to main `lib/schema_dot_org.rb` file
|
84
|
+
4. Create corresponding test file `spec/schema_dot_org/new_type_spec.rb`
|
85
|
+
5. Follow existing patterns for validation and JSON-LD output testing
|
86
|
+
|
87
|
+
## Dependencies
|
88
|
+
|
89
|
+
- **validated_object (~> 2.3)** - Provides ActiveRecord-style validations
|
90
|
+
- **rspec (~> 3.12)** - Testing framework
|
91
|
+
- **doctest2-rspec (~> 0.9.2)** - Tests code examples in documentation
|
data/Gemfile.lock
CHANGED
@@ -1,62 +1,75 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
schema_dot_org (2.
|
5
|
-
validated_object (~> 2.3)
|
4
|
+
schema_dot_org (2.5.1)
|
5
|
+
validated_object (~> 2.3.4)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (
|
11
|
-
activesupport (=
|
12
|
-
activesupport (
|
10
|
+
activemodel (8.0.2.1)
|
11
|
+
activesupport (= 8.0.2.1)
|
12
|
+
activesupport (8.0.2.1)
|
13
13
|
base64
|
14
|
+
benchmark (>= 0.3)
|
14
15
|
bigdecimal
|
15
|
-
concurrent-ruby (~> 1.0, >= 1.
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
16
17
|
connection_pool (>= 2.2.5)
|
17
18
|
drb
|
18
19
|
i18n (>= 1.6, < 2)
|
20
|
+
logger (>= 1.4.2)
|
19
21
|
minitest (>= 5.1)
|
20
|
-
|
21
|
-
tzinfo (~> 2.0)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
securerandom (>= 0.3)
|
23
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
24
|
+
uri (>= 0.13.1)
|
25
|
+
base64 (0.3.0)
|
26
|
+
benchmark (0.4.1)
|
27
|
+
bigdecimal (3.2.2)
|
28
|
+
coderay (1.1.3)
|
29
|
+
concurrent-ruby (1.3.5)
|
30
|
+
connection_pool (2.5.3)
|
31
|
+
diff-lcs (1.6.2)
|
32
|
+
doctest2-core (0.9.3)
|
33
|
+
doctest2-rspec (0.9.2)
|
34
|
+
doctest2-core (~> 0.9.0)
|
35
|
+
rspec (~> 3.0)
|
36
|
+
drb (2.2.3)
|
37
|
+
i18n (1.14.7)
|
30
38
|
concurrent-ruby (~> 1.0)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
rspec
|
39
|
-
rspec-
|
40
|
-
|
39
|
+
logger (1.7.0)
|
40
|
+
method_source (1.1.0)
|
41
|
+
minitest (5.25.5)
|
42
|
+
pry (0.15.2)
|
43
|
+
coderay (~> 1.1)
|
44
|
+
method_source (~> 1.0)
|
45
|
+
rake (13.3.0)
|
46
|
+
rspec (3.13.1)
|
47
|
+
rspec-core (~> 3.13.0)
|
48
|
+
rspec-expectations (~> 3.13.0)
|
49
|
+
rspec-mocks (~> 3.13.0)
|
50
|
+
rspec-core (3.13.5)
|
51
|
+
rspec-support (~> 3.13.0)
|
52
|
+
rspec-expectations (3.13.5)
|
41
53
|
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
-
rspec-support (~> 3.
|
43
|
-
rspec-mocks (3.
|
54
|
+
rspec-support (~> 3.13.0)
|
55
|
+
rspec-mocks (3.13.5)
|
44
56
|
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
-
rspec-support (~> 3.
|
46
|
-
rspec-support (3.
|
47
|
-
|
48
|
-
sorbet-runtime (0.5.11072)
|
57
|
+
rspec-support (~> 3.13.0)
|
58
|
+
rspec-support (3.13.5)
|
59
|
+
securerandom (0.4.1)
|
49
60
|
tzinfo (2.0.6)
|
50
61
|
concurrent-ruby (~> 1.0)
|
51
|
-
|
62
|
+
uri (1.0.3)
|
63
|
+
validated_object (2.3.4)
|
52
64
|
activemodel (>= 3.2.21)
|
53
|
-
sorbet-runtime (>= 0.5.5890)
|
54
65
|
|
55
66
|
PLATFORMS
|
56
67
|
arm64-darwin-24
|
57
68
|
|
58
69
|
DEPENDENCIES
|
59
70
|
bundler (~> 2.4)
|
71
|
+
doctest2-rspec (~> 0.9.2)
|
72
|
+
pry (> 0.0.0)
|
60
73
|
rake (~> 13.0)
|
61
74
|
rspec (~> 3.12)
|
62
75
|
schema_dot_org!
|
data/README.md
CHANGED
@@ -1,19 +1,17 @@
|
|
1
|
-
[](https://badge.fury.io/rb/schema_dot_org)
|
2
|
-
|
3
1
|
## Table of Contents
|
4
2
|
|
5
3
|
- [SchemaDotOrg](#schemadotorg)
|
6
|
-
- [Usage](#usage)
|
7
|
-
|
8
|
-
|
9
|
-
- [Supported Schema.org Types](#supported-schemaorg-types)
|
10
|
-
- [Examples](#examples)
|
11
|
-
|
12
|
-
|
13
|
-
- [Installation](#installation)
|
14
|
-
- [Development](#development)
|
15
|
-
- [Contributing](#contributing)
|
16
|
-
- [License](#license)
|
4
|
+
- [Usage](#usage)
|
5
|
+
- [Principle: No silent failures](#principle-no-silent-failures)
|
6
|
+
- [You are prevented from creating invalid markup](#you-are-prevented-from-creating-invalid-markup)
|
7
|
+
- [Supported Schema.org Types](#supported-schemaorg-types)
|
8
|
+
- [Examples](#examples)
|
9
|
+
- [BreadcrumbList](#breadcrumblist)
|
10
|
+
- [WebSite](#website)
|
11
|
+
- [Installation](#installation)
|
12
|
+
- [Development](#development)
|
13
|
+
- [Contributing](#contributing)
|
14
|
+
- [License](#license)
|
17
15
|
|
18
16
|
# SchemaDotOrg
|
19
17
|
|
@@ -98,7 +96,7 @@ Etc., etc.
|
|
98
96
|
|
99
97
|
### You are prevented from creating invalid markup
|
100
98
|
|
101
|
-
I make mistakes. So I wanted to know that if my page loads, the markup is good.
|
99
|
+
I make mistakes. So I wanted to know that if my page loads, the markup is good. I hate "silent failures".
|
102
100
|
|
103
101
|
If you use the wrong type or try to set an unknown attribute, SchemaDotOrg will
|
104
102
|
refuse to create the incorrect JSON-LD. Instead, you'll get a message explaining
|
@@ -142,13 +140,67 @@ See each type's RSpec for an example of how to use it.
|
|
142
140
|
| Organization | [Schema.org](https://schema.org/Organization) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/organization_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/organization.rb) |
|
143
141
|
| Person | [Schema.org](https://schema.org/Person) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/person_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/person.rb) |
|
144
142
|
| Place | [Schema.org](https://schema.org/Place) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/place_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/place.rb) |
|
143
|
+
| PostalAddress | [Schema.org](https://schema.org/PostalAddress) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/postal_address_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/postal_address.rb) |
|
145
144
|
| Product | [Schema.org](https://schema.org/Product) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/product_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/product.rb) |
|
146
145
|
| SearchAction | [Schema.org](https://schema.org/SearchAction) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/search_action_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/search_action.rb) |
|
147
146
|
| WebSite | [Schema.org](https://schema.org/WebSite) | [RSpec](https://github.com/public-law/schema-dot-org/blob/master/spec/schema_dot_org/web_site_spec.rb) | [Source](https://github.com/public-law/schema-dot-org/blob/master/lib/schema_dot_org/web_site.rb) |
|
148
147
|
|
149
148
|
## Examples
|
150
149
|
|
151
|
-
|
150
|
+
### BreadcrumbList
|
151
|
+
|
152
|
+
The `make_breadcrumbs` convenience method creates a BreadcrumbList from a simple array of hashes:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
links = [
|
156
|
+
{ name: 'Home', url: 'https://example.com' },
|
157
|
+
{ name: 'Books', url: 'https://example.com/books' },
|
158
|
+
{ name: 'Science Fiction', url: 'https://example.com/books/sci-fi' },
|
159
|
+
{ name: 'Award Winners' } # Last item typically has no URL
|
160
|
+
]
|
161
|
+
|
162
|
+
SchemaDotOrg
|
163
|
+
.make_breadcrumbs(links)
|
164
|
+
.to_s
|
165
|
+
```
|
166
|
+
|
167
|
+
produces:
|
168
|
+
|
169
|
+
```html
|
170
|
+
<script type="application/ld+json">
|
171
|
+
{
|
172
|
+
"@context": "https://schema.org",
|
173
|
+
"@type": "BreadcrumbList",
|
174
|
+
"itemListElement": [
|
175
|
+
{
|
176
|
+
"@type": "ListItem",
|
177
|
+
"position": 1,
|
178
|
+
"name": "Home",
|
179
|
+
"item": "https://example.com"
|
180
|
+
},
|
181
|
+
{
|
182
|
+
"@type": "ListItem",
|
183
|
+
"position": 2,
|
184
|
+
"name": "Books",
|
185
|
+
"item": "https://example.com/books"
|
186
|
+
},
|
187
|
+
{
|
188
|
+
"@type": "ListItem",
|
189
|
+
"position": 3,
|
190
|
+
"name": "Science Fiction",
|
191
|
+
"item": "https://example.com/books/sci-fi"
|
192
|
+
},
|
193
|
+
{
|
194
|
+
"@type": "ListItem",
|
195
|
+
"position": 4,
|
196
|
+
"name": "Award Winners"
|
197
|
+
}
|
198
|
+
]
|
199
|
+
}
|
200
|
+
</script>
|
201
|
+
```
|
202
|
+
|
203
|
+
URLs are automatically validated - invalid URLs will raise an `ArgumentError` with a descriptive message.
|
152
204
|
|
153
205
|
### WebSite
|
154
206
|
|
@@ -174,26 +226,6 @@ WebSite.new(
|
|
174
226
|
)
|
175
227
|
```
|
176
228
|
|
177
|
-
### Organization
|
178
|
-
|
179
|
-
Example:
|
180
|
-
|
181
|
-
```ruby
|
182
|
-
Organization.new(
|
183
|
-
name: 'Public.Law',
|
184
|
-
founder: Person.new(name: 'Robb Shecter'),
|
185
|
-
founding_date: Date.new(2009, 3, 6),
|
186
|
-
founding_location: Place.new(address: 'Portland, OR'),
|
187
|
-
email: 'say_hi@public.law',
|
188
|
-
url: 'https://www.public.law',
|
189
|
-
logo: 'https://www.public.law/favicon-196x196.png',
|
190
|
-
same_as: [
|
191
|
-
'https://twitter.com/law_is_code',
|
192
|
-
'https://www.facebook.com/PublicDotLaw'
|
193
|
-
]
|
194
|
-
)
|
195
|
-
```
|
196
|
-
|
197
229
|
|
198
230
|
## Installation
|
199
231
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'date'
|
4
4
|
require_relative 'person'
|
5
|
+
require_relative 'organization'
|
5
6
|
|
6
7
|
#
|
7
8
|
# Model the Schema.org `Thing > CreativeWork > Article > SocialMediaPosting > DiscussionForumPosting`.
|
@@ -9,10 +10,8 @@ require_relative 'person'
|
|
9
10
|
#
|
10
11
|
module SchemaDotOrg
|
11
12
|
class DiscussionForumPosting < SchemaType
|
12
|
-
|
13
|
-
validated_attr :
|
14
|
-
# TODO: Allow for type Date or DateTime
|
15
|
-
validated_attr :datePublished, type: Date, presence: true
|
13
|
+
validated_attr :author, type: union(Person, Organization), presence: true
|
14
|
+
validated_attr :datePublished, type: union(Date, Time), presence: true
|
16
15
|
|
17
16
|
validated_attr :comment, type: Array, allow_nil: true
|
18
17
|
validated_attr :commentCount, type: Integer, allow_nil: true
|
@@ -4,12 +4,14 @@ require 'date'
|
|
4
4
|
|
5
5
|
require_relative 'person'
|
6
6
|
require_relative 'place'
|
7
|
+
require_relative 'postal_address'
|
7
8
|
|
8
9
|
# Google allows `url` to be a string:
|
9
10
|
# https://developers.google.com/search/docs/appearance/structured-data/logo
|
10
11
|
|
11
12
|
module SchemaDotOrg
|
12
13
|
class Organization < SchemaType
|
14
|
+
validated_attr :address, type: SchemaDotOrg::PostalAddress, allow_nil: true
|
13
15
|
validated_attr :contact_points, type: Array, allow_nil: true
|
14
16
|
validated_attr :email, type: String, allow_nil: true
|
15
17
|
validated_attr :founder, type: SchemaDotOrg::Person, allow_nil: true
|
data/lib/schema_dot_org/place.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'postal_address'
|
4
|
+
|
3
5
|
|
4
6
|
#
|
5
7
|
# Model the Schema.org `Thing > Place`. See http://schema.org/Place
|
6
8
|
#
|
7
9
|
module SchemaDotOrg
|
8
10
|
class Place < SchemaType
|
9
|
-
validated_attr :address, type: String, presence: true
|
11
|
+
validated_attr :address, type: union(String, SchemaDotOrg::PostalAddress), presence: true
|
10
12
|
end
|
11
13
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Model the Schema.org `Thing > Intangible > StructuredValue > ContactPoint > PostalAddress`.
|
5
|
+
# See https://schema.org/PostalAddress
|
6
|
+
#
|
7
|
+
module SchemaDotOrg
|
8
|
+
class PostalAddress < SchemaType
|
9
|
+
|
10
|
+
# AddressCountry: The country. Recommended to be in 2-letter ISO 3166-1 alpha-2
|
11
|
+
# format, for example "US". For backward compatibility, a 3-letter ISO 3166-1 alpha-3
|
12
|
+
# country code such as "SGP" or a full country name such as "Singapore" can also be
|
13
|
+
# used.
|
14
|
+
validated_attr :addressCountry, type: String, allow_nil: true
|
15
|
+
|
16
|
+
# AddressLocality: The locality in which the street address is,
|
17
|
+
# and which is in the region. For example, Mountain View.
|
18
|
+
validated_attr :addressLocality, type: String, allow_nil: true
|
19
|
+
|
20
|
+
# AddressRegion: The region in which the locality is, and which is in the country.
|
21
|
+
# For example, California or another appropriate first-level Administrative division.
|
22
|
+
validated_attr :addressRegion, type: String, allow_nil: true
|
23
|
+
|
24
|
+
# ExtendedAddress: An address extension such as an apartment number, C/O or
|
25
|
+
# alternative name.
|
26
|
+
validated_attr :extendedAddress, type: String, allow_nil: true
|
27
|
+
|
28
|
+
# PostalCode: The postal code. For example, 94043.
|
29
|
+
validated_attr :postalCode, type: String, allow_nil: true
|
30
|
+
|
31
|
+
# StreetAddress: The street address. For example, 1600 Amphitheatre Parkway.
|
32
|
+
validated_attr :streetAddress, type: String, allow_nil: true
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module SchemaDotOrg
|
6
|
+
# Utility module for URL validation
|
7
|
+
module UrlValidator
|
8
|
+
# Validates that a string is a proper web URL (HTTP/HTTPS with a host)
|
9
|
+
#
|
10
|
+
# @param url [String] The URL string to validate
|
11
|
+
# @return [Boolean] true if the URL is valid, false otherwise
|
12
|
+
#
|
13
|
+
# Doc Tests:
|
14
|
+
# >> SchemaDotOrg::UrlValidator.valid_web_url?('https://example.com') #=> true
|
15
|
+
# >> SchemaDotOrg::UrlValidator.valid_web_url?('http://example.com/path') #=> true
|
16
|
+
# >> SchemaDotOrg::UrlValidator.valid_web_url?('ftp://example.com') #=> false
|
17
|
+
# >> SchemaDotOrg::UrlValidator.valid_web_url?('not-a-url') #=> false
|
18
|
+
# >> SchemaDotOrg::UrlValidator.valid_web_url?('') #=> false
|
19
|
+
# >> SchemaDotOrg::UrlValidator.valid_web_url?(nil) #=> false
|
20
|
+
#
|
21
|
+
def self.valid_web_url?(url)
|
22
|
+
return false if url.nil? || url.to_s.strip.empty?
|
23
|
+
|
24
|
+
uri = URI.parse(url.to_s)
|
25
|
+
|
26
|
+
# Check for valid HTTP/HTTPS scheme
|
27
|
+
return false unless %w[http https].include?(uri.scheme)
|
28
|
+
|
29
|
+
# Check for a host
|
30
|
+
return false if uri.host.nil? || uri.host.strip.empty?
|
31
|
+
|
32
|
+
true
|
33
|
+
rescue URI::InvalidURIError
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/schema_dot_org.rb
CHANGED
@@ -2,11 +2,42 @@
|
|
2
2
|
require 'json'
|
3
3
|
require 'validated_object'
|
4
4
|
|
5
|
+
|
6
|
+
module SchemaDotOrg
|
7
|
+
##
|
8
|
+
# Make a BreadcrumbList from an array of links. This is a convenience
|
9
|
+
# method for creating a BreadcrumbList and its ListItems.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# SchemaDotOrg.make_breadcrumbs([
|
13
|
+
# { name: 'Home', url: 'https://example.com' },
|
14
|
+
# { name: 'Books', url: 'https://example.com/books' },
|
15
|
+
# { name: 'Science Fiction' },
|
16
|
+
# ])
|
17
|
+
#
|
18
|
+
# @param links [Array<Hash>] An array of links. Each link is a hash with
|
19
|
+
# a `:url` and `:name` key. The `:url` is optional.
|
20
|
+
# @return [BreadcrumbList] A BreadcrumbList object.
|
21
|
+
# @raise [ArgumentError] If any URL is invalid.
|
22
|
+
#
|
23
|
+
def self.make_breadcrumbs(links)
|
24
|
+
BreadcrumbList.new(itemListElement: links.map.with_index(1) do |link, index|
|
25
|
+
url = link[:url]
|
26
|
+
name = link[:name]
|
27
|
+
|
28
|
+
if !url.nil? && !UrlValidator.valid_web_url?(url)
|
29
|
+
raise ArgumentError, "URL is not a valid web URL: #{url}"
|
30
|
+
end
|
31
|
+
|
32
|
+
ListItem.new(position: index, item: url, name: name)
|
33
|
+
end)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
5
37
|
#
|
6
38
|
# Abstract base class for all the Schema.org types.
|
7
39
|
#
|
8
|
-
|
9
|
-
class SchemaType < ValidatedObject::Base
|
40
|
+
class SchemaType < ValidatedObject::Base
|
10
41
|
EXCLUDED_INSTANCE_VARIABLES = %i[@context_for_validation @validation_context @errors].freeze
|
11
42
|
ROOT_ATTR = { "@context" => "https://schema.org" }.freeze
|
12
43
|
UNQUALIFIED_CLASS_NAME_REGEX = /([^:]+)$/
|
@@ -128,7 +159,9 @@ require 'schema_dot_org/list_item'
|
|
128
159
|
require 'schema_dot_org/organization'
|
129
160
|
require 'schema_dot_org/person'
|
130
161
|
require 'schema_dot_org/place'
|
162
|
+
require 'schema_dot_org/postal_address'
|
131
163
|
require 'schema_dot_org/product'
|
132
164
|
require 'schema_dot_org/offer'
|
133
165
|
require 'schema_dot_org/search_action'
|
166
|
+
require 'schema_dot_org/url_validator'
|
134
167
|
require 'schema_dot_org/web_site'
|
data/schema_dot_org.gemspec
CHANGED
@@ -5,9 +5,9 @@ lib = File.expand_path('lib', __dir__)
|
|
5
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.required_ruby_version = '>= 3.
|
8
|
+
spec.required_ruby_version = '>= 3.1'
|
9
9
|
spec.name = 'schema_dot_org'
|
10
|
-
spec.version = '2.
|
10
|
+
spec.version = '2.5.1'
|
11
11
|
spec.authors = ['Robert Shecter']
|
12
12
|
spec.email = ['robert@public.law']
|
13
13
|
|
@@ -25,9 +25,11 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
26
|
spec.require_paths = ['lib']
|
27
27
|
|
28
|
-
spec.add_dependency 'validated_object', '~> 2.3'
|
28
|
+
spec.add_dependency 'validated_object', '~> 2.3.4'
|
29
29
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 2.4"
|
31
31
|
spec.add_development_dependency "rake", "~> 13.0"
|
32
32
|
spec.add_development_dependency "rspec", "~> 3.12"
|
33
|
+
spec.add_development_dependency "doctest2-rspec", "~> 0.9.2"
|
34
|
+
spec.add_development_dependency "pry", "> 0.0.0"
|
33
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schema_dot_org
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Shecter
|
@@ -15,14 +15,14 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version:
|
18
|
+
version: 2.3.4
|
19
19
|
type: :runtime
|
20
20
|
prerelease: false
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
22
22
|
requirements:
|
23
23
|
- - "~>"
|
24
24
|
- !ruby/object:Gem::Version
|
25
|
-
version:
|
25
|
+
version: 2.3.4
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: bundler
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -65,6 +65,34 @@ dependencies:
|
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
67
|
version: '3.12'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: doctest2-rspec
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.9.2
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.9.2
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: pry
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.0.0
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 0.0.0
|
68
96
|
description: Creates well-formed website metadata with strongly typed Ruby.
|
69
97
|
email:
|
70
98
|
- robert@public.law
|
@@ -75,6 +103,8 @@ files:
|
|
75
103
|
- ".gitignore"
|
76
104
|
- ".rspec"
|
77
105
|
- ".travis.yml"
|
106
|
+
- CHANGELOG.md
|
107
|
+
- CLAUDE.md
|
78
108
|
- Gemfile
|
79
109
|
- Gemfile.lock
|
80
110
|
- LICENSE.txt
|
@@ -98,8 +128,10 @@ files:
|
|
98
128
|
- lib/schema_dot_org/organization.rb
|
99
129
|
- lib/schema_dot_org/person.rb
|
100
130
|
- lib/schema_dot_org/place.rb
|
131
|
+
- lib/schema_dot_org/postal_address.rb
|
101
132
|
- lib/schema_dot_org/product.rb
|
102
133
|
- lib/schema_dot_org/search_action.rb
|
134
|
+
- lib/schema_dot_org/url_validator.rb
|
103
135
|
- lib/schema_dot_org/web_site.rb
|
104
136
|
- schema_dot_org.gemspec
|
105
137
|
- test-script.rb
|
@@ -114,14 +146,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
146
|
requirements:
|
115
147
|
- - ">="
|
116
148
|
- !ruby/object:Gem::Version
|
117
|
-
version: '3.
|
149
|
+
version: '3.1'
|
118
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
151
|
requirements:
|
120
152
|
- - ">="
|
121
153
|
- !ruby/object:Gem::Version
|
122
154
|
version: '0'
|
123
155
|
requirements: []
|
124
|
-
rubygems_version: 3.
|
156
|
+
rubygems_version: 3.7.1
|
125
157
|
specification_version: 4
|
126
158
|
summary: JSON-LD generator for Schema.org vocabulary
|
127
159
|
test_files: []
|