@crawl-me-maybe/schema 0.1.0
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.
- package/README.md +270 -0
- package/dist/build.d.ts +42 -0
- package/dist/builders/about-page.d.ts +3 -0
- package/dist/builders/aggregate-rating.d.ts +3 -0
- package/dist/builders/answer.d.ts +3 -0
- package/dist/builders/article.d.ts +3 -0
- package/dist/builders/breadcrumb-list.d.ts +11 -0
- package/dist/builders/comment.d.ts +3 -0
- package/dist/builders/contact-page.d.ts +3 -0
- package/dist/builders/course.d.ts +3 -0
- package/dist/builders/dataset.d.ts +3 -0
- package/dist/builders/discussion-forum-posting.d.ts +3 -0
- package/dist/builders/event.d.ts +3 -0
- package/dist/builders/faq.d.ts +3 -0
- package/dist/builders/fragments.d.ts +13 -0
- package/dist/builders/index.d.ts +27 -0
- package/dist/builders/internal/slug-to-title.d.ts +1 -0
- package/dist/builders/item-list.d.ts +3 -0
- package/dist/builders/job-posting.d.ts +3 -0
- package/dist/builders/local-business.d.ts +3 -0
- package/dist/builders/movie.d.ts +3 -0
- package/dist/builders/product.d.ts +3 -0
- package/dist/builders/profile-page.d.ts +3 -0
- package/dist/builders/qa-page.d.ts +3 -0
- package/dist/builders/question.d.ts +3 -0
- package/dist/builders/recipe.d.ts +3 -0
- package/dist/builders/review.d.ts +3 -0
- package/dist/builders/software-application.d.ts +3 -0
- package/dist/builders/vacation-rental.d.ts +3 -0
- package/dist/builders/video-object.d.ts +3 -0
- package/dist/builders/webpage.d.ts +3 -0
- package/dist/builders/website.d.ts +3 -0
- package/dist/define-builder.d.ts +8 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +383 -0
- package/dist/index.js.map +41 -0
- package/dist/utils/image.d.ts +8 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# @crawl-me-maybe/schema
|
|
2
|
+
|
|
3
|
+
Schema markup should be generated from your content model, not rebuilt beside it. If editors update the content, the schema should update with it.
|
|
4
|
+
|
|
5
|
+
## Table of contents
|
|
6
|
+
|
|
7
|
+
- [Install](#install)
|
|
8
|
+
- [Features](#features)
|
|
9
|
+
- [Why this exists](#why-this-exists)
|
|
10
|
+
- [What `buildSchemaMarkup` generates](#what-buildschemamarkup-generates)
|
|
11
|
+
- [Quick start](#quick-start)
|
|
12
|
+
- [`mainEntity`](#mainentity)
|
|
13
|
+
- [`@id` and de-duplication](#id-and-de-duplication)
|
|
14
|
+
- [Rendering the graph](#rendering-the-graph)
|
|
15
|
+
- [Supported schemas](#supported-schemas)
|
|
16
|
+
- [With Sanity](#with-sanity)
|
|
17
|
+
- [Core exports](#core-exports)
|
|
18
|
+
- [License](#license)
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @crawl-me-maybe/schema
|
|
24
|
+
pnpm add @crawl-me-maybe/schema
|
|
25
|
+
bun add @crawl-me-maybe/schema
|
|
26
|
+
yarn add @crawl-me-maybe/schema
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- `buildSchemaMarkup` emits a JSON-LD graph for identity, `WebSite`, and `WebPage`
|
|
34
|
+
- Typed builders for common Schema.org nodes, backed by `schema-dts`
|
|
35
|
+
- Entity de-duping by `@id` when nested nodes reference the same entity
|
|
36
|
+
- Identity roots for `Person`, `Organization`, and `LocalBusiness`
|
|
37
|
+
- Utility builders for breadcrumbs, FAQ pages, products, articles, events, and more
|
|
38
|
+
|
|
39
|
+
## Why this exists
|
|
40
|
+
|
|
41
|
+
Schema markup from CMS → frontend is usually handled with a bulk of fields that editors are forced to fill in. This library pushes a bit more work onto developers up front so editors don't have to duplicate content just to satisfy schema markup.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## What `buildSchemaMarkup` generates
|
|
46
|
+
|
|
47
|
+
`buildSchemaMarkup` creates the page-level schema graph for a single URL. It always generates:
|
|
48
|
+
|
|
49
|
+
- a site identity node (`Organization`, `Person`, or `LocalBusiness`)
|
|
50
|
+
- a `WebSite` node
|
|
51
|
+
- a `WebPage` node
|
|
52
|
+
|
|
53
|
+
You can optionally attach additional entities such as:
|
|
54
|
+
|
|
55
|
+
- `Article`
|
|
56
|
+
- `Product`
|
|
57
|
+
- `FAQPage`
|
|
58
|
+
- `Event`
|
|
59
|
+
- `BreadcrumbList`
|
|
60
|
+
|
|
61
|
+
These are linked into the same graph as the page's main entity, breadcrumb trail, or supporting nodes.
|
|
62
|
+
|
|
63
|
+
A typical article page graph looks like:
|
|
64
|
+
|
|
65
|
+
- `Organization` — who owns the site
|
|
66
|
+
- `WebSite` — the site itself
|
|
67
|
+
- `WebPage` — the current page
|
|
68
|
+
- `BreadcrumbList` — optional page hierarchy
|
|
69
|
+
- `Article` — the page's main content entity
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Quick start
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import {
|
|
77
|
+
buildArticle,
|
|
78
|
+
buildBreadcrumbListSchema,
|
|
79
|
+
buildSchemaMarkup,
|
|
80
|
+
} from "@crawl-me-maybe/schema";
|
|
81
|
+
|
|
82
|
+
const schemas = buildSchemaMarkup({
|
|
83
|
+
identity: {
|
|
84
|
+
type: "organization",
|
|
85
|
+
name: "Acme",
|
|
86
|
+
logo: "https://example.com/logo.png",
|
|
87
|
+
},
|
|
88
|
+
siteUrl: "https://example.com",
|
|
89
|
+
siteName: "Acme",
|
|
90
|
+
siteDescription: "Useful things from Acme.",
|
|
91
|
+
pageUrl: "https://example.com/blog/hello-world",
|
|
92
|
+
pageTitle: "Hello world",
|
|
93
|
+
pageDescription: "An intro post from Acme.",
|
|
94
|
+
breadcrumb: buildBreadcrumbListSchema({
|
|
95
|
+
pagePath: "/blog/hello-world",
|
|
96
|
+
pageTitle: "Hello world",
|
|
97
|
+
}),
|
|
98
|
+
mainEntity: buildArticle({
|
|
99
|
+
headline: "Hello world",
|
|
100
|
+
datePublished: "2026-06-23",
|
|
101
|
+
dateModified: "2026-06-23",
|
|
102
|
+
image: "https://example.com/og.jpg",
|
|
103
|
+
}),
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
In this example, `buildSchemaMarkup` creates the site identity, `WebSite`, and `WebPage` nodes automatically, then attaches the breadcrumb and article as part of the same graph.
|
|
108
|
+
|
|
109
|
+
`buildSchemaMarkup` returns a `string[]` of serialized JSON-LD script payloads, ready to render into `<script type="application/ld+json">` tags. No `JSON.stringify` needed.
|
|
110
|
+
|
|
111
|
+
> 🧠 Note: Use `buildSchemaMarkup` to assemble the full page-level graph for a URL. Use the individual `build*` helpers to create entities that are passed into that graph as `mainEntity`, breadcrumbs, or nested supporting nodes.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## `mainEntity`
|
|
116
|
+
|
|
117
|
+
Use `mainEntity` for the primary entity the page is about.
|
|
118
|
+
|
|
119
|
+
Common examples:
|
|
120
|
+
|
|
121
|
+
- blog post → `buildArticle(...)`
|
|
122
|
+
- product page → `buildProduct(...)`
|
|
123
|
+
- event page → `buildEvent(...)`
|
|
124
|
+
- FAQ page → `buildFAQPage(...)`
|
|
125
|
+
|
|
126
|
+
If a page has no clear primary entity, you can omit `mainEntity` and render just the page-level graph.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## `@id` and de-duplication
|
|
131
|
+
|
|
132
|
+
If multiple nodes reference the same entity, give them the same `@id`. The library will collapse duplicates into a single graph node where possible.
|
|
133
|
+
|
|
134
|
+
In most cases, `buildSchemaMarkup` handles page-level identity, `WebSite`, and `WebPage` IDs for you. You'll mainly care about `@id` when composing custom or nested entities manually.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Rendering the graph
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
{schemas.map((schema) => (
|
|
142
|
+
<script
|
|
143
|
+
key={schema}
|
|
144
|
+
type="application/ld+json"
|
|
145
|
+
dangerouslySetInnerHTML={{ __html: schema }}
|
|
146
|
+
/>
|
|
147
|
+
))}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Supported schemas
|
|
153
|
+
|
|
154
|
+
Builders are exported from the package root.
|
|
155
|
+
|
|
156
|
+
### Common page entities
|
|
157
|
+
|
|
158
|
+
| Builder | Schema.org type |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `buildArticle` | `Article` |
|
|
161
|
+
| `buildProduct` | `Product` |
|
|
162
|
+
| `buildEvent` | `Event` |
|
|
163
|
+
| `buildFAQPage` | `FAQPage` |
|
|
164
|
+
| `buildRecipe` | `Recipe` |
|
|
165
|
+
| `buildSoftwareApplication` | `SoftwareApplication` |
|
|
166
|
+
| `buildCourse` | `Course` |
|
|
167
|
+
| `buildDataset` | `Dataset` |
|
|
168
|
+
| `buildMovie` | `Movie` |
|
|
169
|
+
| `buildVacationRental` | `VacationRental` |
|
|
170
|
+
| `buildVideoObject` | `VideoObject` |
|
|
171
|
+
| `buildJobPosting` | `JobPosting` |
|
|
172
|
+
|
|
173
|
+
### Site / structural entities
|
|
174
|
+
|
|
175
|
+
Site identity (`Organization`, `Person`, or `LocalBusiness`) is emitted by `buildSchemaMarkup` via the `identity` option — not a separate builder.
|
|
176
|
+
|
|
177
|
+
| Builder | Schema.org type |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `buildLocalBusiness` | `LocalBusiness` |
|
|
180
|
+
| `buildWebSite` | `WebSite` |
|
|
181
|
+
| `buildWebPage` | `WebPage` |
|
|
182
|
+
| `buildBreadcrumbListSchema` | `BreadcrumbList` |
|
|
183
|
+
| `buildAboutPage` | `AboutPage` |
|
|
184
|
+
| `buildContactPage` | `ContactPage` |
|
|
185
|
+
| `buildProfilePage` | `ProfilePage` |
|
|
186
|
+
|
|
187
|
+
### Supporting / nested entities
|
|
188
|
+
|
|
189
|
+
| Builder | Schema.org type |
|
|
190
|
+
|---|---|
|
|
191
|
+
| `buildAggregateRating` | `AggregateRating` |
|
|
192
|
+
| `buildReview` | `Review` |
|
|
193
|
+
| `buildComment` | `Comment` |
|
|
194
|
+
| `buildQuestion` | `Question` |
|
|
195
|
+
| `buildAnswer` | `Answer` |
|
|
196
|
+
| `buildQAPage` | `QAPage` |
|
|
197
|
+
| `buildDiscussionForumPosting` | `DiscussionForumPosting` |
|
|
198
|
+
| `buildItemList` | `ItemList` |
|
|
199
|
+
|
|
200
|
+
See Google's [structured data gallery](https://developers.google.com/search/docs/appearance/structured-data/search-gallery) for which schema types are eligible for rich results.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## With Sanity
|
|
205
|
+
|
|
206
|
+
This package has no Sanity dependency. You map your GROQ projections to builders in your app.
|
|
207
|
+
|
|
208
|
+
If you use [`@crawl-me-maybe/sanity-plugin-seo`](https://github.com/nathannye/crawl-me-maybe/tree/main/packages/sanity-plugin-seo), `globalSeoSettings.logo` and `globalSeoSettings.siteUrl` are the usual sources for organization identity and absolute page URLs. Pair with [`@crawl-me-maybe/meta`](https://github.com/nathannye/crawl-me-maybe/tree/main/packages/meta) for page titles and descriptions.
|
|
209
|
+
|
|
210
|
+
**Article page example:**
|
|
211
|
+
|
|
212
|
+
```groq
|
|
213
|
+
*[_type == "post" && slug.current == $slug][0]{
|
|
214
|
+
title,
|
|
215
|
+
publishedAt,
|
|
216
|
+
_updatedAt,
|
|
217
|
+
"slug": slug.current,
|
|
218
|
+
"image": mainImage.asset->url,
|
|
219
|
+
"body": body
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import {
|
|
225
|
+
buildArticle,
|
|
226
|
+
buildBreadcrumbListSchema,
|
|
227
|
+
buildSchemaMarkup,
|
|
228
|
+
} from "@crawl-me-maybe/schema";
|
|
229
|
+
|
|
230
|
+
const pageUrl = `${siteUrl}/blog/${post.slug}`;
|
|
231
|
+
const schemas = buildSchemaMarkup({
|
|
232
|
+
identity: {
|
|
233
|
+
type: "organization",
|
|
234
|
+
name: globalSeo.siteTitle,
|
|
235
|
+
logo: globalSeo.logoUrl,
|
|
236
|
+
},
|
|
237
|
+
siteUrl,
|
|
238
|
+
siteName: globalSeo.siteTitle,
|
|
239
|
+
pageUrl,
|
|
240
|
+
pageTitle: post.title,
|
|
241
|
+
breadcrumb: buildBreadcrumbListSchema({
|
|
242
|
+
pagePath: `/blog/${post.slug}`,
|
|
243
|
+
pageTitle: post.title,
|
|
244
|
+
}),
|
|
245
|
+
mainEntity: buildArticle({
|
|
246
|
+
headline: post.title,
|
|
247
|
+
datePublished: post.publishedAt,
|
|
248
|
+
dateModified: post._updatedAt,
|
|
249
|
+
image: post.image,
|
|
250
|
+
}),
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Pick the `build*` helper that matches your document type (`buildProduct`, `buildEvent`, `buildFAQPage`, etc.) and pass it as `mainEntity`. Omit `mainEntity` for generic pages that only need site-level graph nodes.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Core exports
|
|
259
|
+
|
|
260
|
+
- `buildSchemaMarkup` — builds the page-level JSON-LD graph
|
|
261
|
+
- `build*` schema builders — typed builders for individual Schema.org nodes
|
|
262
|
+
- `BuilderInput` — input helper type for builder functions
|
|
263
|
+
- `BuildSchemaMarkupInput` — input type for `buildSchemaMarkup`
|
|
264
|
+
- `Identity`, `PersonIdentity`, `OrganizationIdentity`, `LocalBusinessIdentity` — supported site identity roots
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { BreadcrumbList, OpeningHoursSpecification, PostalAddress, Thing, WithContext } from "schema-dts";
|
|
2
|
+
import { type ImageInput } from "./utils/image";
|
|
3
|
+
type SchemaNode = Record<string, unknown>;
|
|
4
|
+
export type BuildSchemaMarkupInput = {
|
|
5
|
+
identity: Identity;
|
|
6
|
+
siteUrl: string;
|
|
7
|
+
siteName: string;
|
|
8
|
+
siteDescription?: string;
|
|
9
|
+
pageUrl: string;
|
|
10
|
+
pageTitle: string;
|
|
11
|
+
pageDescription?: string;
|
|
12
|
+
breadcrumb?: WithContext<BreadcrumbList>;
|
|
13
|
+
mainEntity?: Thing | SchemaNode;
|
|
14
|
+
};
|
|
15
|
+
export type PersonIdentity = {
|
|
16
|
+
type: "person";
|
|
17
|
+
name: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
image?: ImageInput;
|
|
20
|
+
sameAs?: string[];
|
|
21
|
+
};
|
|
22
|
+
export type OrganizationIdentity = {
|
|
23
|
+
type: "organization";
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
logo?: ImageInput;
|
|
27
|
+
sameAs?: string[];
|
|
28
|
+
};
|
|
29
|
+
export type LocalBusinessIdentity = {
|
|
30
|
+
type: "localBusiness";
|
|
31
|
+
name: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
logo?: ImageInput;
|
|
34
|
+
phone?: string;
|
|
35
|
+
email?: string;
|
|
36
|
+
address?: PostalAddress;
|
|
37
|
+
openingHours?: OpeningHoursSpecification[];
|
|
38
|
+
sameAs?: string[];
|
|
39
|
+
};
|
|
40
|
+
export type Identity = PersonIdentity | OrganizationIdentity | LocalBusinessIdentity;
|
|
41
|
+
export declare const buildSchemaMarkup: (input: BuildSchemaMarkupInput) => string[];
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BreadcrumbList, WithContext } from "schema-dts";
|
|
2
|
+
export type BreadcrumbItemInput = {
|
|
3
|
+
title: string;
|
|
4
|
+
url: string;
|
|
5
|
+
};
|
|
6
|
+
export type BuildBreadcrumbListSchemaInput = {
|
|
7
|
+
pagePath: string;
|
|
8
|
+
pageTitle: string;
|
|
9
|
+
items?: BreadcrumbItemInput[];
|
|
10
|
+
};
|
|
11
|
+
export declare function buildBreadcrumbListSchema({ pagePath, pageTitle, items, }: BuildBreadcrumbListSchemaInput): WithContext<BreadcrumbList>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type IdReference = {
|
|
2
|
+
"@id": string;
|
|
3
|
+
};
|
|
4
|
+
type SchemaIdOptions = {
|
|
5
|
+
kind: string;
|
|
6
|
+
name: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
explicitId?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function normalizeId(name: string): string;
|
|
11
|
+
export declare function createSchemaId({ kind, name, baseUrl, explicitId, }: SchemaIdOptions): string;
|
|
12
|
+
export declare function asIdReference(id: string): IdReference;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from "./about-page";
|
|
2
|
+
export * from "./aggregate-rating";
|
|
3
|
+
export * from "./answer";
|
|
4
|
+
export * from "./article";
|
|
5
|
+
export * from "./breadcrumb-list";
|
|
6
|
+
export * from "./comment";
|
|
7
|
+
export * from "./contact-page";
|
|
8
|
+
export * from "./course";
|
|
9
|
+
export * from "./dataset";
|
|
10
|
+
export * from "./discussion-forum-posting";
|
|
11
|
+
export * from "./event";
|
|
12
|
+
export * from "./faq";
|
|
13
|
+
export * from "./item-list";
|
|
14
|
+
export * from "./job-posting";
|
|
15
|
+
export * from "./local-business";
|
|
16
|
+
export * from "./movie";
|
|
17
|
+
export * from "./product";
|
|
18
|
+
export * from "./profile-page";
|
|
19
|
+
export * from "./qa-page";
|
|
20
|
+
export * from "./question";
|
|
21
|
+
export * from "./recipe";
|
|
22
|
+
export * from "./review";
|
|
23
|
+
export * from "./software-application";
|
|
24
|
+
export * from "./vacation-rental";
|
|
25
|
+
export * from "./video-object";
|
|
26
|
+
export * from "./webpage";
|
|
27
|
+
export * from "./website";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function slugToTitle(segment: string): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Thing, WithContext } from "schema-dts";
|
|
2
|
+
type Simplify<T> = {
|
|
3
|
+
[K in keyof T]: T[K];
|
|
4
|
+
} & {};
|
|
5
|
+
export type BuilderInput<T extends Thing> = Simplify<Omit<T, "@type" | "@context">>;
|
|
6
|
+
export type SchemaBuilder<T extends Thing> = (input: BuilderInput<T>) => WithContext<T>;
|
|
7
|
+
export declare function defineBuilder<T extends Thing>(type: string): SchemaBuilder<T>;
|
|
8
|
+
export {};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
// src/builders/fragments.ts
|
|
2
|
+
function normalizeId(name) {
|
|
3
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
4
|
+
}
|
|
5
|
+
function createSchemaId({
|
|
6
|
+
kind,
|
|
7
|
+
name,
|
|
8
|
+
baseUrl = "",
|
|
9
|
+
explicitId
|
|
10
|
+
}) {
|
|
11
|
+
if (explicitId) {
|
|
12
|
+
return explicitId.startsWith("http") ? explicitId : `${baseUrl}${explicitId}`;
|
|
13
|
+
}
|
|
14
|
+
return `${baseUrl}#${kind}-${normalizeId(name)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/utils/image.ts
|
|
18
|
+
function buildImageObject(input) {
|
|
19
|
+
if (!input) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (typeof input === "string") {
|
|
23
|
+
return {
|
|
24
|
+
"@type": "ImageObject",
|
|
25
|
+
url: input
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
"@type": "ImageObject",
|
|
30
|
+
url: input.url,
|
|
31
|
+
width: input.width,
|
|
32
|
+
height: input.height
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/build.ts
|
|
37
|
+
var TYPE_PRIORITY = [
|
|
38
|
+
"Organization",
|
|
39
|
+
"Person",
|
|
40
|
+
"LocalBusiness",
|
|
41
|
+
"WebSite",
|
|
42
|
+
"WebPage",
|
|
43
|
+
"ProfilePage",
|
|
44
|
+
"QAPage",
|
|
45
|
+
"BreadcrumbList",
|
|
46
|
+
"Article",
|
|
47
|
+
"Course",
|
|
48
|
+
"Dataset",
|
|
49
|
+
"DiscussionForumPosting",
|
|
50
|
+
"JobPosting",
|
|
51
|
+
"Movie",
|
|
52
|
+
"Product",
|
|
53
|
+
"Recipe",
|
|
54
|
+
"SoftwareApplication",
|
|
55
|
+
"VacationRental",
|
|
56
|
+
"VideoObject",
|
|
57
|
+
"Event",
|
|
58
|
+
"ItemList",
|
|
59
|
+
"Question",
|
|
60
|
+
"Answer",
|
|
61
|
+
"Review",
|
|
62
|
+
"Comment",
|
|
63
|
+
"AggregateRating"
|
|
64
|
+
];
|
|
65
|
+
var typeWeight = new Map(TYPE_PRIORITY.map((type, index) => [type, index]));
|
|
66
|
+
var hasObjectShape = (value) => {
|
|
67
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
68
|
+
};
|
|
69
|
+
var hasType = (value) => {
|
|
70
|
+
return typeof value["@type"] === "string";
|
|
71
|
+
};
|
|
72
|
+
var hasId = (value) => {
|
|
73
|
+
return typeof value["@id"] === "string" && value["@id"].length > 0;
|
|
74
|
+
};
|
|
75
|
+
var ensureContext = (node) => {
|
|
76
|
+
if (hasType(node) && node["@context"] === undefined) {
|
|
77
|
+
return {
|
|
78
|
+
"@context": "https://schema.org",
|
|
79
|
+
...node
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return node;
|
|
83
|
+
};
|
|
84
|
+
var assembleNodes = (nodes) => {
|
|
85
|
+
const collected = [];
|
|
86
|
+
const seenIds = new Set;
|
|
87
|
+
const processingIds = new Set;
|
|
88
|
+
let orderCounter = 0;
|
|
89
|
+
const addNode = (node) => {
|
|
90
|
+
const normalized = ensureContext(node);
|
|
91
|
+
if (hasId(normalized)) {
|
|
92
|
+
if (seenIds.has(normalized["@id"]))
|
|
93
|
+
return;
|
|
94
|
+
seenIds.add(normalized["@id"]);
|
|
95
|
+
}
|
|
96
|
+
collected.push({
|
|
97
|
+
node: normalized,
|
|
98
|
+
order: orderCounter++
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const processValue = (value, isRoot = false) => {
|
|
102
|
+
if (Array.isArray(value)) {
|
|
103
|
+
return value.map((item) => processValue(item, false));
|
|
104
|
+
}
|
|
105
|
+
if (!hasObjectShape(value))
|
|
106
|
+
return value;
|
|
107
|
+
if (!isRoot && hasType(value) && hasId(value)) {
|
|
108
|
+
registerEntity(value);
|
|
109
|
+
return { "@id": value["@id"] };
|
|
110
|
+
}
|
|
111
|
+
const output = {};
|
|
112
|
+
for (const [key, child] of Object.entries(value)) {
|
|
113
|
+
output[key] = processValue(child, false);
|
|
114
|
+
}
|
|
115
|
+
return output;
|
|
116
|
+
};
|
|
117
|
+
const registerEntity = (entity) => {
|
|
118
|
+
const id = entity["@id"];
|
|
119
|
+
if (seenIds.has(id) || processingIds.has(id))
|
|
120
|
+
return;
|
|
121
|
+
processingIds.add(id);
|
|
122
|
+
const processedEntity = processValue(entity, true);
|
|
123
|
+
if (hasObjectShape(processedEntity)) {
|
|
124
|
+
addNode(processedEntity);
|
|
125
|
+
}
|
|
126
|
+
processingIds.delete(id);
|
|
127
|
+
};
|
|
128
|
+
for (const node of nodes) {
|
|
129
|
+
if (!node)
|
|
130
|
+
continue;
|
|
131
|
+
const processed = processValue(node, true);
|
|
132
|
+
if (!hasObjectShape(processed))
|
|
133
|
+
continue;
|
|
134
|
+
addNode(processed);
|
|
135
|
+
}
|
|
136
|
+
const ranked = collected.sort((a, b) => {
|
|
137
|
+
const aType = hasType(a.node) ? a.node["@type"] : "";
|
|
138
|
+
const bType = hasType(b.node) ? b.node["@type"] : "";
|
|
139
|
+
const aWeight = typeWeight.get(aType) ?? Number.MAX_SAFE_INTEGER;
|
|
140
|
+
const bWeight = typeWeight.get(bType) ?? Number.MAX_SAFE_INTEGER;
|
|
141
|
+
if (aWeight !== bWeight)
|
|
142
|
+
return aWeight - bWeight;
|
|
143
|
+
return a.order - b.order;
|
|
144
|
+
});
|
|
145
|
+
return ranked.map(({ node }) => JSON.stringify(node));
|
|
146
|
+
};
|
|
147
|
+
var buildIdentityNodes = (identity, siteUrl) => {
|
|
148
|
+
switch (identity.type) {
|
|
149
|
+
case "person": {
|
|
150
|
+
const id = createSchemaId({
|
|
151
|
+
kind: "person",
|
|
152
|
+
name: identity.name,
|
|
153
|
+
baseUrl: siteUrl
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
node: {
|
|
157
|
+
"@type": "Person",
|
|
158
|
+
"@id": id,
|
|
159
|
+
name: identity.name,
|
|
160
|
+
description: identity.description,
|
|
161
|
+
image: buildImageObject(identity.image),
|
|
162
|
+
sameAs: identity.sameAs,
|
|
163
|
+
url: siteUrl
|
|
164
|
+
},
|
|
165
|
+
ref: { "@id": id }
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
case "organization": {
|
|
169
|
+
const id = createSchemaId({
|
|
170
|
+
kind: "organization",
|
|
171
|
+
name: identity.name,
|
|
172
|
+
baseUrl: siteUrl
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
node: {
|
|
176
|
+
"@type": "Organization",
|
|
177
|
+
"@id": id,
|
|
178
|
+
name: identity.name,
|
|
179
|
+
description: identity.description,
|
|
180
|
+
logo: buildImageObject(identity.logo),
|
|
181
|
+
sameAs: identity.sameAs,
|
|
182
|
+
url: siteUrl
|
|
183
|
+
},
|
|
184
|
+
ref: { "@id": id }
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
case "localBusiness": {
|
|
188
|
+
const id = createSchemaId({
|
|
189
|
+
kind: "local-business",
|
|
190
|
+
name: identity.name,
|
|
191
|
+
baseUrl: siteUrl
|
|
192
|
+
});
|
|
193
|
+
return {
|
|
194
|
+
node: {
|
|
195
|
+
"@type": "LocalBusiness",
|
|
196
|
+
"@id": id,
|
|
197
|
+
name: identity.name,
|
|
198
|
+
description: identity.description,
|
|
199
|
+
logo: buildImageObject(identity.logo),
|
|
200
|
+
telephone: identity.phone,
|
|
201
|
+
email: identity.email,
|
|
202
|
+
address: identity.address,
|
|
203
|
+
openingHoursSpecification: identity.openingHours,
|
|
204
|
+
sameAs: identity.sameAs,
|
|
205
|
+
url: siteUrl
|
|
206
|
+
},
|
|
207
|
+
ref: { "@id": id }
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
var buildSchemaMarkup = (input) => {
|
|
213
|
+
const { node: identityNode, ref: identityRef } = buildIdentityNodes(input.identity, input.siteUrl);
|
|
214
|
+
const websiteId = `${input.siteUrl}#website`;
|
|
215
|
+
const websiteNode = {
|
|
216
|
+
"@type": "WebSite",
|
|
217
|
+
"@id": websiteId,
|
|
218
|
+
name: input.siteName,
|
|
219
|
+
url: input.siteUrl,
|
|
220
|
+
description: input.siteDescription,
|
|
221
|
+
publisher: identityRef
|
|
222
|
+
};
|
|
223
|
+
const webpageNode = {
|
|
224
|
+
"@type": "WebPage",
|
|
225
|
+
"@id": `${input.pageUrl}#webpage`,
|
|
226
|
+
url: input.pageUrl,
|
|
227
|
+
name: input.pageTitle,
|
|
228
|
+
description: input.pageDescription,
|
|
229
|
+
isPartOf: { "@id": websiteId },
|
|
230
|
+
breadcrumb: input.breadcrumb,
|
|
231
|
+
mainEntity: input.mainEntity
|
|
232
|
+
};
|
|
233
|
+
return assembleNodes([identityNode, websiteNode, webpageNode]);
|
|
234
|
+
};
|
|
235
|
+
// src/define-builder.ts
|
|
236
|
+
function defineBuilder(type) {
|
|
237
|
+
return (input) => ({
|
|
238
|
+
"@context": "https://schema.org",
|
|
239
|
+
"@type": type,
|
|
240
|
+
...input
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/builders/about-page.ts
|
|
245
|
+
var buildAboutPage = defineBuilder("AboutPage");
|
|
246
|
+
// src/builders/aggregate-rating.ts
|
|
247
|
+
var buildAggregateRating = defineBuilder("AggregateRating");
|
|
248
|
+
// src/builders/answer.ts
|
|
249
|
+
var buildAnswer = defineBuilder("Answer");
|
|
250
|
+
// src/builders/article.ts
|
|
251
|
+
var buildArticle = defineBuilder("Article");
|
|
252
|
+
// src/builders/internal/slug-to-title.ts
|
|
253
|
+
function slugToTitle(segment) {
|
|
254
|
+
const decoded = decodeURIComponent(segment || "");
|
|
255
|
+
const normalized = decoded.replace(/[-_]+/g, " ").replace(/\s+/g, " ").trim();
|
|
256
|
+
if (!normalized)
|
|
257
|
+
return "";
|
|
258
|
+
return normalized.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// src/builders/breadcrumb-list.ts
|
|
262
|
+
function normalizePath(path) {
|
|
263
|
+
if (!path)
|
|
264
|
+
return "/";
|
|
265
|
+
const withoutHash = path.split("#")[0];
|
|
266
|
+
const withoutQuery = withoutHash.split("?")[0];
|
|
267
|
+
const prefixed = withoutQuery.startsWith("/") ? withoutQuery : `/${withoutQuery}`;
|
|
268
|
+
return prefixed.replace(/\/+$/, "") || "/";
|
|
269
|
+
}
|
|
270
|
+
function createDerivedParentItems(pagePath) {
|
|
271
|
+
const normalized = normalizePath(pagePath);
|
|
272
|
+
const segments = normalized.split("/").filter(Boolean);
|
|
273
|
+
if (segments.length <= 1)
|
|
274
|
+
return [];
|
|
275
|
+
return segments.slice(0, -1).map((segment, index) => ({
|
|
276
|
+
title: slugToTitle(segment),
|
|
277
|
+
url: `/${segments.slice(0, index + 1).join("/")}`
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
function toListItems(items) {
|
|
281
|
+
return items.map((item, index) => ({
|
|
282
|
+
"@type": "ListItem",
|
|
283
|
+
position: index + 1,
|
|
284
|
+
name: item.title,
|
|
285
|
+
item: item.url
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
function buildBreadcrumbListSchema({
|
|
289
|
+
pagePath,
|
|
290
|
+
pageTitle,
|
|
291
|
+
items
|
|
292
|
+
}) {
|
|
293
|
+
const parentItems = items?.length ? items : createDerivedParentItems(pagePath);
|
|
294
|
+
const finalItems = [
|
|
295
|
+
...parentItems,
|
|
296
|
+
{
|
|
297
|
+
title: pageTitle,
|
|
298
|
+
url: normalizePath(pagePath)
|
|
299
|
+
}
|
|
300
|
+
];
|
|
301
|
+
return {
|
|
302
|
+
"@context": "https://schema.org",
|
|
303
|
+
"@type": "BreadcrumbList",
|
|
304
|
+
itemListElement: toListItems(finalItems)
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
// src/builders/comment.ts
|
|
308
|
+
var buildComment = defineBuilder("Comment");
|
|
309
|
+
// src/builders/contact-page.ts
|
|
310
|
+
var buildContactPage = defineBuilder("ContactPage");
|
|
311
|
+
// src/builders/course.ts
|
|
312
|
+
var buildCourse = defineBuilder("Course");
|
|
313
|
+
// src/builders/dataset.ts
|
|
314
|
+
var buildDataset = defineBuilder("Dataset");
|
|
315
|
+
// src/builders/discussion-forum-posting.ts
|
|
316
|
+
var buildDiscussionForumPosting = defineBuilder("DiscussionForumPosting");
|
|
317
|
+
// src/builders/event.ts
|
|
318
|
+
var buildEvent = defineBuilder("Event");
|
|
319
|
+
// src/builders/faq.ts
|
|
320
|
+
var buildFAQPage = defineBuilder("FAQPage");
|
|
321
|
+
// src/builders/item-list.ts
|
|
322
|
+
var buildItemList = defineBuilder("ItemList");
|
|
323
|
+
// src/builders/job-posting.ts
|
|
324
|
+
var buildJobPosting = defineBuilder("JobPosting");
|
|
325
|
+
// src/builders/local-business.ts
|
|
326
|
+
var buildLocalBusiness = defineBuilder("LocalBusiness");
|
|
327
|
+
// src/builders/movie.ts
|
|
328
|
+
var buildMovie = defineBuilder("Movie");
|
|
329
|
+
// src/builders/product.ts
|
|
330
|
+
var buildProduct = defineBuilder("Product");
|
|
331
|
+
// src/builders/profile-page.ts
|
|
332
|
+
var buildProfilePage = defineBuilder("ProfilePage");
|
|
333
|
+
// src/builders/qa-page.ts
|
|
334
|
+
var buildQAPage = defineBuilder("QAPage");
|
|
335
|
+
// src/builders/question.ts
|
|
336
|
+
var buildQuestion = defineBuilder("Question");
|
|
337
|
+
// src/builders/recipe.ts
|
|
338
|
+
var buildRecipe = defineBuilder("Recipe");
|
|
339
|
+
// src/builders/review.ts
|
|
340
|
+
var buildReview = defineBuilder("Review");
|
|
341
|
+
// src/builders/software-application.ts
|
|
342
|
+
var buildSoftwareApplication = defineBuilder("SoftwareApplication");
|
|
343
|
+
// src/builders/vacation-rental.ts
|
|
344
|
+
var buildVacationRental = defineBuilder("VacationRental");
|
|
345
|
+
// src/builders/video-object.ts
|
|
346
|
+
var buildVideoObject = defineBuilder("VideoObject");
|
|
347
|
+
// src/builders/webpage.ts
|
|
348
|
+
var buildWebPage = defineBuilder("WebPage");
|
|
349
|
+
// src/builders/website.ts
|
|
350
|
+
var buildWebSite = defineBuilder("WebSite");
|
|
351
|
+
export {
|
|
352
|
+
buildWebSite,
|
|
353
|
+
buildWebPage,
|
|
354
|
+
buildVideoObject,
|
|
355
|
+
buildVacationRental,
|
|
356
|
+
buildSoftwareApplication,
|
|
357
|
+
buildSchemaMarkup,
|
|
358
|
+
buildReview,
|
|
359
|
+
buildRecipe,
|
|
360
|
+
buildQuestion,
|
|
361
|
+
buildQAPage,
|
|
362
|
+
buildProfilePage,
|
|
363
|
+
buildProduct,
|
|
364
|
+
buildMovie,
|
|
365
|
+
buildLocalBusiness,
|
|
366
|
+
buildJobPosting,
|
|
367
|
+
buildItemList,
|
|
368
|
+
buildFAQPage,
|
|
369
|
+
buildEvent,
|
|
370
|
+
buildDiscussionForumPosting,
|
|
371
|
+
buildDataset,
|
|
372
|
+
buildCourse,
|
|
373
|
+
buildContactPage,
|
|
374
|
+
buildComment,
|
|
375
|
+
buildBreadcrumbListSchema,
|
|
376
|
+
buildArticle,
|
|
377
|
+
buildAnswer,
|
|
378
|
+
buildAggregateRating,
|
|
379
|
+
buildAboutPage
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
//# debugId=5F889F4F897E1F2564756E2164756E21
|
|
383
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/builders/fragments.ts", "../src/utils/image.ts", "../src/build.ts", "../src/define-builder.ts", "../src/builders/about-page.ts", "../src/builders/aggregate-rating.ts", "../src/builders/answer.ts", "../src/builders/article.ts", "../src/builders/internal/slug-to-title.ts", "../src/builders/breadcrumb-list.ts", "../src/builders/comment.ts", "../src/builders/contact-page.ts", "../src/builders/course.ts", "../src/builders/dataset.ts", "../src/builders/discussion-forum-posting.ts", "../src/builders/event.ts", "../src/builders/faq.ts", "../src/builders/item-list.ts", "../src/builders/job-posting.ts", "../src/builders/local-business.ts", "../src/builders/movie.ts", "../src/builders/product.ts", "../src/builders/profile-page.ts", "../src/builders/qa-page.ts", "../src/builders/question.ts", "../src/builders/recipe.ts", "../src/builders/review.ts", "../src/builders/software-application.ts", "../src/builders/vacation-rental.ts", "../src/builders/video-object.ts", "../src/builders/webpage.ts", "../src/builders/website.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"type IdReference = { \"@id\": string };\n\ntype SchemaIdOptions = {\n\tkind: string;\n\tname: string;\n\tbaseUrl?: string;\n\texplicitId?: string;\n};\n\nexport function normalizeId(name: string): string {\n\treturn name\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nexport function createSchemaId({\n\tkind,\n\tname,\n\tbaseUrl = \"\",\n\texplicitId,\n}: SchemaIdOptions): string {\n\tif (explicitId) {\n\t\treturn explicitId.startsWith(\"http\")\n\t\t\t? explicitId\n\t\t\t: `${baseUrl}${explicitId}`;\n\t}\n\n\treturn `${baseUrl}#${kind}-${normalizeId(name)}`;\n}\n\nexport function asIdReference(id: string): IdReference {\n\treturn { \"@id\": id };\n}\n",
|
|
6
|
+
"type ImageObjectInput = {\n\turl: string;\n\twidth?: number;\n\theight?: number;\n};\n\nexport type ImageInput = string | ImageObjectInput;\n\nexport function buildImageObject(\n\tinput?: ImageInput,\n): Record<string, unknown> | undefined {\n\tif (!input) {\n\t\treturn undefined;\n\t}\n\n\tif (typeof input === \"string\") {\n\t\treturn {\n\t\t\t\"@type\": \"ImageObject\",\n\t\t\turl: input,\n\t\t};\n\t}\n\n\treturn {\n\t\t\"@type\": \"ImageObject\",\n\t\turl: input.url,\n\t\twidth: input.width,\n\t\theight: input.height,\n\t};\n}\n",
|
|
7
|
+
"import type {\n\tBreadcrumbList,\n\tOpeningHoursSpecification,\n\tPostalAddress,\n\tThing,\n\tWithContext,\n} from \"schema-dts\";\nimport { createSchemaId } from \"./builders/fragments\";\nimport { buildImageObject, type ImageInput } from \"./utils/image\";\n\ntype SchemaNode = Record<string, unknown>;\n\nexport type BuildSchemaMarkupInput = {\n\tidentity: Identity;\n\tsiteUrl: string;\n\tsiteName: string;\n\tsiteDescription?: string;\n\tpageUrl: string;\n\tpageTitle: string;\n\tpageDescription?: string;\n\tbreadcrumb?: WithContext<BreadcrumbList>;\n\tmainEntity?: Thing | SchemaNode;\n};\n\nexport type PersonIdentity = {\n\ttype: \"person\";\n\tname: string;\n\tdescription?: string;\n\timage?: ImageInput;\n\tsameAs?: string[];\n};\n\nexport type OrganizationIdentity = {\n\ttype: \"organization\";\n\tname: string;\n\tdescription?: string;\n\tlogo?: ImageInput;\n\tsameAs?: string[];\n};\n\nexport type LocalBusinessIdentity = {\n\ttype: \"localBusiness\";\n\tname: string;\n\tdescription?: string;\n\tlogo?: ImageInput;\n\tphone?: string;\n\temail?: string;\n\taddress?: PostalAddress;\n\topeningHours?: OpeningHoursSpecification[];\n\tsameAs?: string[];\n};\n\nexport type Identity =\n\t| PersonIdentity\n\t| OrganizationIdentity\n\t| LocalBusinessIdentity;\n\nconst TYPE_PRIORITY = [\n\t\"Organization\",\n\t\"Person\",\n\t\"LocalBusiness\",\n\t\"WebSite\",\n\t\"WebPage\",\n\t\"ProfilePage\",\n\t\"QAPage\",\n\t\"BreadcrumbList\",\n\t\"Article\",\n\t\"Course\",\n\t\"Dataset\",\n\t\"DiscussionForumPosting\",\n\t\"JobPosting\",\n\t\"Movie\",\n\t\"Product\",\n\t\"Recipe\",\n\t\"SoftwareApplication\",\n\t\"VacationRental\",\n\t\"VideoObject\",\n\t\"Event\",\n\t\"ItemList\",\n\t\"Question\",\n\t\"Answer\",\n\t\"Review\",\n\t\"Comment\",\n\t\"AggregateRating\",\n] as const;\n\nconst typeWeight = new Map<string, number>(\n\tTYPE_PRIORITY.map((type, index) => [type, index]),\n);\n\nconst hasObjectShape = (value: unknown): value is SchemaNode => {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst hasType = (value: SchemaNode): value is SchemaNode & { \"@type\": string } => {\n\treturn typeof value[\"@type\"] === \"string\";\n};\n\nconst hasId = (value: SchemaNode): value is SchemaNode & { \"@id\": string } => {\n\treturn typeof value[\"@id\"] === \"string\" && value[\"@id\"].length > 0;\n};\n\nconst ensureContext = (node: SchemaNode): SchemaNode => {\n\tif (hasType(node) && node[\"@context\"] === undefined) {\n\t\treturn {\n\t\t\t\"@context\": \"https://schema.org\",\n\t\t\t...node,\n\t\t};\n\t}\n\n\treturn node;\n};\n\ntype RankedNode = {\n\tnode: SchemaNode;\n\torder: number;\n};\n\nconst assembleNodes = (nodes: Array<Thing | SchemaNode | undefined>): string[] => {\n\tconst collected: RankedNode[] = [];\n\tconst seenIds = new Set<string>();\n\tconst processingIds = new Set<string>();\n\tlet orderCounter = 0;\n\n\tconst addNode = (node: SchemaNode) => {\n\t\tconst normalized = ensureContext(node);\n\t\tif (hasId(normalized)) {\n\t\t\tif (seenIds.has(normalized[\"@id\"])) return;\n\t\t\tseenIds.add(normalized[\"@id\"]);\n\t\t}\n\n\t\tcollected.push({\n\t\t\tnode: normalized,\n\t\t\torder: orderCounter++,\n\t\t});\n\t};\n\n\tconst processValue = (value: unknown, isRoot = false): unknown => {\n\t\tif (Array.isArray(value)) {\n\t\t\treturn value.map((item) => processValue(item, false));\n\t\t}\n\n\t\tif (!hasObjectShape(value)) return value;\n\n\t\tif (!isRoot && hasType(value) && hasId(value)) {\n\t\t\tregisterEntity(value);\n\t\t\treturn { \"@id\": value[\"@id\"] };\n\t\t}\n\n\t\tconst output: SchemaNode = {};\n\t\tfor (const [key, child] of Object.entries(value)) {\n\t\t\toutput[key] = processValue(child, false);\n\t\t}\n\t\treturn output;\n\t};\n\n\tconst registerEntity = (entity: SchemaNode & { \"@id\": string }) => {\n\t\tconst id = entity[\"@id\"];\n\t\tif (seenIds.has(id) || processingIds.has(id)) return;\n\n\t\tprocessingIds.add(id);\n\t\tconst processedEntity = processValue(entity, true);\n\t\tif (hasObjectShape(processedEntity)) {\n\t\t\taddNode(processedEntity);\n\t\t}\n\t\tprocessingIds.delete(id);\n\t};\n\n\tfor (const node of nodes) {\n\t\tif (!node) continue;\n\t\tconst processed = processValue(node, true);\n\t\tif (!hasObjectShape(processed)) continue;\n\t\taddNode(processed);\n\t}\n\n\tconst ranked = collected.sort((a, b) => {\n\t\tconst aType = hasType(a.node) ? a.node[\"@type\"] : \"\";\n\t\tconst bType = hasType(b.node) ? b.node[\"@type\"] : \"\";\n\t\tconst aWeight = typeWeight.get(aType) ?? Number.MAX_SAFE_INTEGER;\n\t\tconst bWeight = typeWeight.get(bType) ?? Number.MAX_SAFE_INTEGER;\n\n\t\tif (aWeight !== bWeight) return aWeight - bWeight;\n\t\treturn a.order - b.order;\n\t});\n\n\treturn ranked.map(({ node }) => JSON.stringify(node));\n};\n\nconst buildIdentityNodes = (\n\tidentity: Identity,\n\tsiteUrl: string,\n): { node: SchemaNode; ref: { \"@id\": string } } => {\n\tswitch (identity.type) {\n\t\tcase \"person\": {\n\t\t\tconst id = createSchemaId({\n\t\t\t\tkind: \"person\",\n\t\t\t\tname: identity.name,\n\t\t\t\tbaseUrl: siteUrl,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tnode: {\n\t\t\t\t\t\"@type\": \"Person\",\n\t\t\t\t\t\"@id\": id,\n\t\t\t\t\tname: identity.name,\n\t\t\t\t\tdescription: identity.description,\n\t\t\t\t\timage: buildImageObject(identity.image),\n\t\t\t\t\tsameAs: identity.sameAs,\n\t\t\t\t\turl: siteUrl,\n\t\t\t\t},\n\t\t\t\tref: { \"@id\": id },\n\t\t\t};\n\t\t}\n\t\tcase \"organization\": {\n\t\t\tconst id = createSchemaId({\n\t\t\t\tkind: \"organization\",\n\t\t\t\tname: identity.name,\n\t\t\t\tbaseUrl: siteUrl,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tnode: {\n\t\t\t\t\t\"@type\": \"Organization\",\n\t\t\t\t\t\"@id\": id,\n\t\t\t\t\tname: identity.name,\n\t\t\t\t\tdescription: identity.description,\n\t\t\t\t\tlogo: buildImageObject(identity.logo),\n\t\t\t\t\tsameAs: identity.sameAs,\n\t\t\t\t\turl: siteUrl,\n\t\t\t\t},\n\t\t\t\tref: { \"@id\": id },\n\t\t\t};\n\t\t}\n\t\tcase \"localBusiness\": {\n\t\t\tconst id = createSchemaId({\n\t\t\t\tkind: \"local-business\",\n\t\t\t\tname: identity.name,\n\t\t\t\tbaseUrl: siteUrl,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tnode: {\n\t\t\t\t\t\"@type\": \"LocalBusiness\",\n\t\t\t\t\t\"@id\": id,\n\t\t\t\t\tname: identity.name,\n\t\t\t\t\tdescription: identity.description,\n\t\t\t\t\tlogo: buildImageObject(identity.logo),\n\t\t\t\t\ttelephone: identity.phone,\n\t\t\t\t\temail: identity.email,\n\t\t\t\t\taddress: identity.address,\n\t\t\t\t\topeningHoursSpecification: identity.openingHours,\n\t\t\t\t\tsameAs: identity.sameAs,\n\t\t\t\t\turl: siteUrl,\n\t\t\t\t},\n\t\t\t\tref: { \"@id\": id },\n\t\t\t};\n\t\t}\n\t}\n};\n\nexport const buildSchemaMarkup = (input: BuildSchemaMarkupInput): string[] => {\n\tconst { node: identityNode, ref: identityRef } = buildIdentityNodes(\n\t\tinput.identity,\n\t\tinput.siteUrl,\n\t);\n\tconst websiteId = `${input.siteUrl}#website`;\n\n\tconst websiteNode: SchemaNode = {\n\t\t\"@type\": \"WebSite\",\n\t\t\"@id\": websiteId,\n\t\tname: input.siteName,\n\t\turl: input.siteUrl,\n\t\tdescription: input.siteDescription,\n\t\tpublisher: identityRef,\n\t};\n\n\tconst webpageNode: SchemaNode = {\n\t\t\"@type\": \"WebPage\",\n\t\t\"@id\": `${input.pageUrl}#webpage`,\n\t\turl: input.pageUrl,\n\t\tname: input.pageTitle,\n\t\tdescription: input.pageDescription,\n\t\tisPartOf: { \"@id\": websiteId },\n\t\tbreadcrumb: input.breadcrumb,\n\t\tmainEntity: input.mainEntity,\n\t};\n\n\treturn assembleNodes([identityNode, websiteNode, webpageNode]);\n};\n",
|
|
8
|
+
"import type { Thing, WithContext } from \"schema-dts\";\n\ntype Simplify<T> = { [K in keyof T]: T[K] } & {};\n\nexport type BuilderInput<T extends Thing> = Simplify<\n\tOmit<T, \"@type\" | \"@context\">\n>;\n\nexport type SchemaBuilder<T extends Thing> = (\n\tinput: BuilderInput<T>,\n) => WithContext<T>;\n\nexport function defineBuilder<T extends Thing>(type: string): SchemaBuilder<T> {\n\treturn (input: BuilderInput<T>) =>\n\t\t({\n\t\t\t\"@context\": \"https://schema.org\",\n\t\t\t\"@type\": type,\n\t\t\t...input,\n\t\t}) as unknown as WithContext<T>;\n}\n",
|
|
9
|
+
"import type { AboutPage } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildAboutPage: SchemaBuilder<AboutPage> =\n\tdefineBuilder<AboutPage>(\"AboutPage\");\n",
|
|
10
|
+
"import type { AggregateRating } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildAggregateRating: SchemaBuilder<AggregateRating> =\n\tdefineBuilder<AggregateRating>(\"AggregateRating\");\n",
|
|
11
|
+
"import type { Answer } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildAnswer: SchemaBuilder<Answer> = defineBuilder<Answer>(\"Answer\");\n",
|
|
12
|
+
"import type { Article } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildArticle: SchemaBuilder<Article> =\n\tdefineBuilder<Article>(\"Article\");\n",
|
|
13
|
+
"export function slugToTitle(segment: string): string {\n\tconst decoded = decodeURIComponent(segment || \"\");\n\tconst normalized = decoded\n\t\t.replace(/[-_]+/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\n\tif (!normalized) return \"\";\n\n\treturn normalized.replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n",
|
|
14
|
+
"import type { BreadcrumbList, ListItem, WithContext } from \"schema-dts\";\nimport { slugToTitle } from \"./internal/slug-to-title\";\n\nexport type BreadcrumbItemInput = {\n\ttitle: string;\n\turl: string;\n};\n\nexport type BuildBreadcrumbListSchemaInput = {\n\tpagePath: string;\n\tpageTitle: string;\n\titems?: BreadcrumbItemInput[];\n};\n\nfunction normalizePath(path: string): string {\n\tif (!path) return \"/\";\n\tconst withoutHash = path.split(\"#\")[0];\n\tconst withoutQuery = withoutHash.split(\"?\")[0];\n\tconst prefixed = withoutQuery.startsWith(\"/\") ? withoutQuery : `/${withoutQuery}`;\n\treturn prefixed.replace(/\\/+$/, \"\") || \"/\";\n}\n\nfunction createDerivedParentItems(pagePath: string): BreadcrumbItemInput[] {\n\tconst normalized = normalizePath(pagePath);\n\tconst segments = normalized.split(\"/\").filter(Boolean);\n\n\tif (segments.length <= 1) return [];\n\n\treturn segments.slice(0, -1).map((segment, index) => ({\n\t\ttitle: slugToTitle(segment),\n\t\turl: `/${segments.slice(0, index + 1).join(\"/\")}`,\n\t}));\n}\n\nfunction toListItems(items: BreadcrumbItemInput[]): ListItem[] {\n\treturn items.map((item, index) => ({\n\t\t\"@type\": \"ListItem\",\n\t\tposition: index + 1,\n\t\tname: item.title,\n\t\titem: item.url,\n\t}));\n}\n\nexport function buildBreadcrumbListSchema({\n\tpagePath,\n\tpageTitle,\n\titems,\n}: BuildBreadcrumbListSchemaInput): WithContext<BreadcrumbList> {\n\tconst parentItems = items?.length ? items : createDerivedParentItems(pagePath);\n\tconst finalItems = [\n\t\t...parentItems,\n\t\t{\n\t\t\ttitle: pageTitle,\n\t\t\turl: normalizePath(pagePath),\n\t\t},\n\t];\n\n\treturn {\n\t\t\"@context\": \"https://schema.org\",\n\t\t\"@type\": \"BreadcrumbList\",\n\t\titemListElement: toListItems(finalItems),\n\t};\n}\n",
|
|
15
|
+
"import type { Comment } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildComment: SchemaBuilder<Comment> =\n\tdefineBuilder<Comment>(\"Comment\");\n",
|
|
16
|
+
"import type { ContactPage } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildContactPage: SchemaBuilder<ContactPage> =\n\tdefineBuilder<ContactPage>(\"ContactPage\");\n",
|
|
17
|
+
"import type { Course } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildCourse: SchemaBuilder<Course> = defineBuilder<Course>(\"Course\");\n",
|
|
18
|
+
"import type { Dataset } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildDataset: SchemaBuilder<Dataset> =\n\tdefineBuilder<Dataset>(\"Dataset\");\n",
|
|
19
|
+
"import type { DiscussionForumPosting } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildDiscussionForumPosting: SchemaBuilder<DiscussionForumPosting> =\n\tdefineBuilder<DiscussionForumPosting>(\"DiscussionForumPosting\");\n",
|
|
20
|
+
"import type { Event } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildEvent: SchemaBuilder<Event> = defineBuilder<Event>(\"Event\");\n",
|
|
21
|
+
"import type { FAQPage } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildFAQPage: SchemaBuilder<FAQPage> =\n\tdefineBuilder<FAQPage>(\"FAQPage\");\n",
|
|
22
|
+
"import type { ItemList } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildItemList: SchemaBuilder<ItemList> =\n\tdefineBuilder<ItemList>(\"ItemList\");\n",
|
|
23
|
+
"import type { JobPosting } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildJobPosting: SchemaBuilder<JobPosting> =\n\tdefineBuilder<JobPosting>(\"JobPosting\");\n",
|
|
24
|
+
"import type { LocalBusiness } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildLocalBusiness: SchemaBuilder<LocalBusiness> =\n\tdefineBuilder<LocalBusiness>(\"LocalBusiness\");\n",
|
|
25
|
+
"import type { Movie } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildMovie: SchemaBuilder<Movie> = defineBuilder<Movie>(\"Movie\");\n",
|
|
26
|
+
"import type { Product } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildProduct: SchemaBuilder<Product> =\n\tdefineBuilder<Product>(\"Product\");\n",
|
|
27
|
+
"import type { ProfilePage } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildProfilePage: SchemaBuilder<ProfilePage> =\n\tdefineBuilder<ProfilePage>(\"ProfilePage\");\n",
|
|
28
|
+
"import type { QAPage } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildQAPage: SchemaBuilder<QAPage> = defineBuilder<QAPage>(\"QAPage\");\n",
|
|
29
|
+
"import type { Question } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildQuestion: SchemaBuilder<Question> =\n\tdefineBuilder<Question>(\"Question\");\n",
|
|
30
|
+
"import type { Recipe } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildRecipe: SchemaBuilder<Recipe> = defineBuilder<Recipe>(\"Recipe\");\n",
|
|
31
|
+
"import type { Review } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildReview: SchemaBuilder<Review> = defineBuilder<Review>(\"Review\");\n",
|
|
32
|
+
"import type { SoftwareApplication } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildSoftwareApplication: SchemaBuilder<SoftwareApplication> =\n\tdefineBuilder<SoftwareApplication>(\"SoftwareApplication\");\n",
|
|
33
|
+
"import type { VacationRental } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildVacationRental: SchemaBuilder<VacationRental> =\n\tdefineBuilder<VacationRental>(\"VacationRental\");\n",
|
|
34
|
+
"import type { VideoObject } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildVideoObject: SchemaBuilder<VideoObject> =\n\tdefineBuilder<VideoObject>(\"VideoObject\");\n",
|
|
35
|
+
"import type { WebPage } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildWebPage: SchemaBuilder<WebPage> =\n\tdefineBuilder<WebPage>(\"WebPage\");\n",
|
|
36
|
+
"import type { WebSite } from \"schema-dts\";\nimport { defineBuilder, type SchemaBuilder } from \"../define-builder\";\n\nexport const buildWebSite: SchemaBuilder<WebSite> =\n\tdefineBuilder<WebSite>(\"WebSite\");\n"
|
|
37
|
+
],
|
|
38
|
+
"mappings": "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",
|
|
39
|
+
"debugId": "5F889F4F897E1F2564756E2164756E21",
|
|
40
|
+
"names": []
|
|
41
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@crawl-me-maybe/schema",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "Nathan Nye <nathan@nye.dev> (https://nye.dev)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"lint": "biome check .",
|
|
23
|
+
"fix": "biome check --write .",
|
|
24
|
+
"build": "rm -rf dist && bun build src/index.ts --outdir dist --format esm --sourcemap --external schema-dts && tsc -p tsconfig.json --declaration --emitDeclarationOnly --declarationDir dist --rootDir src"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"schema-dts": "^1.1.5"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {}
|
|
30
|
+
}
|