@unhead/schema-org 0.0.2

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/dist/index.cjs ADDED
@@ -0,0 +1,1387 @@
1
+ 'use strict';
2
+
3
+ const ohash = require('ohash');
4
+ const defu = require('defu');
5
+ const ufo = require('ufo');
6
+ const unhead = require('unhead');
7
+
8
+ function defineSchemaOrgResolver(schema) {
9
+ return schema;
10
+ }
11
+
12
+ const idReference = (node) => ({
13
+ "@id": typeof node !== "string" ? node["@id"] : node
14
+ });
15
+ const resolvableDateToDate = (val) => {
16
+ try {
17
+ const date = val instanceof Date ? val : new Date(Date.parse(val));
18
+ return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
19
+ } catch (e) {
20
+ }
21
+ return typeof val === "string" ? val : val.toString();
22
+ };
23
+ const resolvableDateToIso = (val) => {
24
+ if (!val)
25
+ return val;
26
+ try {
27
+ if (val instanceof Date)
28
+ return val.toISOString();
29
+ else
30
+ return new Date(Date.parse(val)).toISOString();
31
+ } catch (e) {
32
+ }
33
+ return typeof val === "string" ? val : val.toString();
34
+ };
35
+ const IdentityId = "#identity";
36
+ const setIfEmpty = (node, field, value) => {
37
+ if (!node?.[field] && value)
38
+ node[field] = value;
39
+ };
40
+ const asArray = (input) => Array.isArray(input) ? input : [input];
41
+ const dedupeMerge = (node, field, value) => {
42
+ const dedupeMerge2 = [];
43
+ const input = asArray(node[field]);
44
+ dedupeMerge2.push(...input);
45
+ const data = new Set(dedupeMerge2);
46
+ data.add(value);
47
+ node[field] = [...data.values()].filter(Boolean);
48
+ };
49
+ const prefixId = (url, id) => {
50
+ if (ufo.hasProtocol(id))
51
+ return url;
52
+ if (!id.startsWith("#"))
53
+ id = `#${id}`;
54
+ return ufo.joinURL(url, id);
55
+ };
56
+ const trimLength = (val, length) => {
57
+ if (!val)
58
+ return val;
59
+ if (val.length > length) {
60
+ const trimmedString = val.substring(0, length);
61
+ return trimmedString.substring(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")));
62
+ }
63
+ return val;
64
+ };
65
+ const resolveDefaultType = (node, defaultType) => {
66
+ const val = node["@type"];
67
+ if (val === defaultType)
68
+ return;
69
+ const types = /* @__PURE__ */ new Set([
70
+ ...asArray(defaultType),
71
+ ...asArray(val)
72
+ ]);
73
+ node["@type"] = types.size === 1 ? val : [...types.values()];
74
+ };
75
+ const resolveWithBase = (base, urlOrPath) => {
76
+ if (!urlOrPath || ufo.hasProtocol(urlOrPath) || !urlOrPath.startsWith("/") && !urlOrPath.startsWith("#"))
77
+ return urlOrPath;
78
+ return ufo.withBase(urlOrPath, base);
79
+ };
80
+ const resolveAsGraphKey = (key) => {
81
+ if (!key)
82
+ return key;
83
+ return key.substring(key.lastIndexOf("#"));
84
+ };
85
+ const stripEmptyProperties = (obj) => {
86
+ Object.keys(obj).forEach((k) => {
87
+ if (obj[k] && typeof obj[k] === "object") {
88
+ if (obj[k].__v_isReadonly || obj[k].__v_isRef)
89
+ return;
90
+ stripEmptyProperties(obj[k]);
91
+ return;
92
+ }
93
+ if (obj[k] === "" || obj[k] === null || typeof obj[k] === "undefined")
94
+ delete obj[k];
95
+ });
96
+ return obj;
97
+ };
98
+
99
+ const offerResolver = defineSchemaOrgResolver({
100
+ cast(node) {
101
+ if (typeof node === "number" || typeof node === "string") {
102
+ return {
103
+ price: node
104
+ };
105
+ }
106
+ return node;
107
+ },
108
+ defaults: {
109
+ "@type": "Offer",
110
+ "availability": "InStock"
111
+ },
112
+ resolve(node, ctx) {
113
+ setIfEmpty(node, "priceCurrency", ctx.meta.currency);
114
+ setIfEmpty(node, "priceValidUntil", new Date(Date.UTC(new Date().getFullYear() + 1, 12, -1, 0, 0, 0)));
115
+ if (node.url)
116
+ resolveWithBase(ctx.meta.host, node.url);
117
+ if (node.availability)
118
+ node.availability = ufo.withBase(node.availability, "https://schema.org/");
119
+ if (node.priceValidUntil)
120
+ node.priceValidUntil = resolvableDateToIso(node.priceValidUntil);
121
+ return node;
122
+ }
123
+ });
124
+
125
+ const aggregateOfferResolver = defineSchemaOrgResolver({
126
+ defaults: {
127
+ "@type": "AggregateOffer"
128
+ },
129
+ inheritMeta: [
130
+ { meta: "currency", key: "priceCurrency" }
131
+ ],
132
+ resolve(node, ctx) {
133
+ node.offers = resolveRelation(node.offers, ctx, offerResolver);
134
+ if (node.offers)
135
+ setIfEmpty(node, "offerCount", asArray(node.offers).length);
136
+ return node;
137
+ }
138
+ });
139
+
140
+ const aggregateRatingResolver = defineSchemaOrgResolver({
141
+ defaults: {
142
+ "@type": "AggregateRating"
143
+ }
144
+ });
145
+
146
+ const searchActionResolver = defineSchemaOrgResolver({
147
+ defaults: {
148
+ "@type": "SearchAction",
149
+ "target": {
150
+ "@type": "EntryPoint"
151
+ },
152
+ "query-input": {
153
+ "@type": "PropertyValueSpecification",
154
+ "valueRequired": true,
155
+ "valueName": "search_term_string"
156
+ }
157
+ },
158
+ resolve(node, ctx) {
159
+ if (typeof node.target === "string") {
160
+ node.target = {
161
+ "@type": "EntryPoint",
162
+ "urlTemplate": resolveWithBase(ctx.meta.host, node.target)
163
+ };
164
+ }
165
+ return node;
166
+ }
167
+ });
168
+
169
+ const PrimaryWebSiteId = "#website";
170
+ const webSiteResolver = defineSchemaOrgResolver({
171
+ defaults: {
172
+ "@type": "WebSite"
173
+ },
174
+ inheritMeta: [
175
+ "inLanguage",
176
+ { meta: "host", key: "url" }
177
+ ],
178
+ idPrefix: ["host", PrimaryWebSiteId],
179
+ resolve(node, ctx) {
180
+ node.potentialAction = resolveRelation(node.potentialAction, ctx, searchActionResolver, {
181
+ array: true
182
+ });
183
+ node.publisher = resolveRelation(node.publisher, ctx);
184
+ return node;
185
+ },
186
+ resolveRootNode(node, { find }) {
187
+ if (resolveAsGraphKey(node["@id"]) === PrimaryWebSiteId) {
188
+ const identity = find(IdentityId);
189
+ if (identity)
190
+ setIfEmpty(node, "publisher", idReference(identity));
191
+ const webPage = find(PrimaryWebPageId);
192
+ if (webPage)
193
+ setIfEmpty(webPage, "isPartOf", idReference(node));
194
+ }
195
+ return node;
196
+ }
197
+ });
198
+
199
+ const resolveListItem = defineSchemaOrgResolver({
200
+ cast(node) {
201
+ if (typeof node === "string") {
202
+ node = {
203
+ name: node
204
+ };
205
+ }
206
+ return node;
207
+ },
208
+ defaults: {
209
+ "@type": "ListItem"
210
+ },
211
+ resolve(node, ctx) {
212
+ if (typeof node.item === "string")
213
+ node.item = resolveWithBase(ctx.meta.host, node.item);
214
+ return node;
215
+ }
216
+ });
217
+
218
+ const PrimaryBreadcrumbId = "#breadcrumb";
219
+ const breadcrumbResolver = defineSchemaOrgResolver({
220
+ defaults: {
221
+ "@type": "BreadcrumbList"
222
+ },
223
+ idPrefix: ["url", PrimaryBreadcrumbId],
224
+ resolve(breadcrumb, ctx) {
225
+ if (breadcrumb.itemListElement) {
226
+ let index = 1;
227
+ breadcrumb.itemListElement = resolveRelation(breadcrumb.itemListElement, ctx, resolveListItem, {
228
+ array: true,
229
+ afterResolve(node) {
230
+ setIfEmpty(node, "position", index++);
231
+ }
232
+ });
233
+ }
234
+ return breadcrumb;
235
+ },
236
+ resolveRootNode(node, { find }) {
237
+ const webPage = find(PrimaryWebPageId);
238
+ if (webPage)
239
+ setIfEmpty(webPage, "breadcrumb", idReference(node));
240
+ }
241
+ });
242
+
243
+ const imageResolver = defineSchemaOrgResolver({
244
+ alias: "image",
245
+ cast(input) {
246
+ if (typeof input === "string") {
247
+ input = {
248
+ url: input
249
+ };
250
+ }
251
+ return input;
252
+ },
253
+ defaults: {
254
+ "@type": "ImageObject"
255
+ },
256
+ inheritMeta: [
257
+ "inLanguage"
258
+ ],
259
+ idPrefix: "host",
260
+ resolve(image, { meta }) {
261
+ image.url = resolveWithBase(meta.host, image.url);
262
+ setIfEmpty(image, "contentUrl", image.url);
263
+ if (image.height && !image.width)
264
+ delete image.height;
265
+ if (image.width && !image.height)
266
+ delete image.width;
267
+ return image;
268
+ }
269
+ });
270
+
271
+ const addressResolver = defineSchemaOrgResolver({
272
+ defaults: {
273
+ "@type": "PostalAddress"
274
+ }
275
+ });
276
+
277
+ const organizationResolver = defineSchemaOrgResolver({
278
+ defaults: {
279
+ "@type": "Organization"
280
+ },
281
+ idPrefix: ["host", IdentityId],
282
+ inheritMeta: [
283
+ { meta: "host", key: "url" }
284
+ ],
285
+ resolve(node, ctx) {
286
+ resolveDefaultType(node, "Organization");
287
+ node.address = resolveRelation(node.address, ctx, addressResolver);
288
+ return node;
289
+ },
290
+ resolveRootNode(node, ctx) {
291
+ const isIdentity = resolveAsGraphKey(node["@id"]) === IdentityId;
292
+ const webPage = ctx.find(PrimaryWebPageId);
293
+ if (node.logo) {
294
+ node.logo = resolveRelation(node.logo, ctx, imageResolver, {
295
+ root: true,
296
+ afterResolve(logo) {
297
+ if (isIdentity)
298
+ logo["@id"] = prefixId(ctx.meta.host, "#logo");
299
+ setIfEmpty(logo, "caption", node.name);
300
+ }
301
+ });
302
+ if (webPage)
303
+ setIfEmpty(webPage, "primaryImageOfPage", idReference(node.logo));
304
+ }
305
+ if (isIdentity && webPage)
306
+ setIfEmpty(webPage, "about", idReference(node));
307
+ const webSite = ctx.find(PrimaryWebSiteId);
308
+ if (webSite)
309
+ setIfEmpty(webSite, "publisher", idReference(node));
310
+ }
311
+ });
312
+
313
+ const personResolver = defineSchemaOrgResolver({
314
+ cast(node) {
315
+ if (typeof node === "string") {
316
+ return {
317
+ name: node
318
+ };
319
+ }
320
+ return node;
321
+ },
322
+ defaults: {
323
+ "@type": "Person"
324
+ },
325
+ idPrefix: ["host", IdentityId],
326
+ resolveRootNode(node, { find, meta }) {
327
+ if (resolveAsGraphKey(node["@id"]) === IdentityId) {
328
+ setIfEmpty(node, "url", meta.host);
329
+ const webPage = find(PrimaryWebPageId);
330
+ if (webPage)
331
+ setIfEmpty(webPage, "about", idReference(node));
332
+ const webSite = find(PrimaryWebSiteId);
333
+ if (webSite)
334
+ setIfEmpty(webSite, "publisher", idReference(node));
335
+ }
336
+ const article = find(PrimaryArticleId);
337
+ if (article)
338
+ setIfEmpty(article, "author", idReference(node));
339
+ }
340
+ });
341
+
342
+ const readActionResolver = defineSchemaOrgResolver({
343
+ defaults: {
344
+ "@type": "ReadAction"
345
+ },
346
+ resolve(node, ctx) {
347
+ if (!node.target.includes(ctx.meta.url))
348
+ node.target.unshift(ctx.meta.url);
349
+ return node;
350
+ }
351
+ });
352
+
353
+ const PrimaryWebPageId = "#webpage";
354
+ const webPageResolver = defineSchemaOrgResolver({
355
+ defaults({ meta }) {
356
+ const endPath = ufo.withoutTrailingSlash(meta.url.substring(meta.url.lastIndexOf("/") + 1));
357
+ let type = "WebPage";
358
+ switch (endPath) {
359
+ case "about":
360
+ case "about-us":
361
+ type = "AboutPage";
362
+ break;
363
+ case "search":
364
+ type = "SearchResultsPage";
365
+ break;
366
+ case "checkout":
367
+ type = "CheckoutPage";
368
+ break;
369
+ case "contact":
370
+ case "get-in-touch":
371
+ case "contact-us":
372
+ type = "ContactPage";
373
+ break;
374
+ case "faq":
375
+ type = "FAQPage";
376
+ break;
377
+ }
378
+ const defaults = {
379
+ "@type": type
380
+ };
381
+ return defaults;
382
+ },
383
+ idPrefix: ["url", PrimaryWebPageId],
384
+ inheritMeta: [
385
+ { meta: "title", key: "name" },
386
+ "description",
387
+ "datePublished",
388
+ "dateModified",
389
+ "url"
390
+ ],
391
+ resolve(node, ctx) {
392
+ node.dateModified = resolvableDateToIso(node.dateModified);
393
+ node.datePublished = resolvableDateToIso(node.datePublished);
394
+ resolveDefaultType(node, "WebPage");
395
+ node.about = resolveRelation(node.about, ctx, organizationResolver);
396
+ node.breadcrumb = resolveRelation(node.breadcrumb, ctx, breadcrumbResolver);
397
+ node.author = resolveRelation(node.author, ctx, personResolver);
398
+ node.primaryImageOfPage = resolveRelation(node.primaryImageOfPage, ctx, imageResolver);
399
+ node.potentialAction = resolveRelation(node.potentialAction, ctx, readActionResolver);
400
+ if (node["@type"] === "WebPage") {
401
+ setIfEmpty(node, "potentialAction", [
402
+ {
403
+ "@type": "ReadAction",
404
+ "target": [ctx.meta.url]
405
+ }
406
+ ]);
407
+ }
408
+ return node;
409
+ },
410
+ resolveRootNode(webPage, { find, meta }) {
411
+ const identity = find(IdentityId);
412
+ const webSite = find(PrimaryWebSiteId);
413
+ const logo = find("#logo");
414
+ if (identity && meta.url === meta.host)
415
+ setIfEmpty(webPage, "about", idReference(identity));
416
+ if (logo)
417
+ setIfEmpty(webPage, "primaryImageOfPage", idReference(logo));
418
+ if (webSite)
419
+ setIfEmpty(webPage, "isPartOf", idReference(webSite));
420
+ const breadcrumb = find(PrimaryBreadcrumbId);
421
+ if (breadcrumb)
422
+ setIfEmpty(webPage, "breadcrumb", idReference(breadcrumb));
423
+ return webPage;
424
+ }
425
+ });
426
+
427
+ const PrimaryArticleId = "#article";
428
+ const articleResolver = defineSchemaOrgResolver({
429
+ defaults: {
430
+ "@type": "Article"
431
+ },
432
+ inheritMeta: [
433
+ "inLanguage",
434
+ "description",
435
+ "image",
436
+ "dateModified",
437
+ "datePublished",
438
+ { meta: "title", key: "headline" }
439
+ ],
440
+ idPrefix: ["url", PrimaryArticleId],
441
+ resolve(node, ctx) {
442
+ node.author = resolveRelation(node.author, ctx, personResolver, {
443
+ root: true
444
+ });
445
+ node.publisher = resolveRelation(node.publisher, ctx);
446
+ node.dateModified = resolvableDateToIso(node.dateModified);
447
+ node.datePublished = resolvableDateToIso(node.datePublished);
448
+ resolveDefaultType(node, "Article");
449
+ node.headline = trimLength(node.headline, 110);
450
+ return node;
451
+ },
452
+ resolveRootNode(node, { find, meta }) {
453
+ const webPage = find(PrimaryWebPageId);
454
+ const identity = find(IdentityId);
455
+ if (node.image && !node.thumbnailUrl) {
456
+ const firstImage = asArray(node.image)[0];
457
+ if (typeof firstImage === "string")
458
+ setIfEmpty(node, "thumbnailUrl", resolveWithBase(meta.host, firstImage));
459
+ else if (firstImage?.["@id"])
460
+ setIfEmpty(node, "thumbnailUrl", find(firstImage["@id"])?.url);
461
+ }
462
+ if (identity) {
463
+ setIfEmpty(node, "publisher", idReference(identity));
464
+ setIfEmpty(node, "author", idReference(identity));
465
+ }
466
+ if (webPage) {
467
+ setIfEmpty(node, "isPartOf", idReference(webPage));
468
+ setIfEmpty(node, "mainEntityOfPage", idReference(webPage));
469
+ setIfEmpty(webPage, "potentialAction", [
470
+ {
471
+ "@type": "ReadAction",
472
+ "target": [meta.url]
473
+ }
474
+ ]);
475
+ setIfEmpty(webPage, "dateModified", node.dateModified);
476
+ setIfEmpty(webPage, "datePublished", node.datePublished);
477
+ }
478
+ return node;
479
+ }
480
+ });
481
+
482
+ const bookEditionResolver = defineSchemaOrgResolver({
483
+ defaults: {
484
+ "@type": "Book"
485
+ },
486
+ inheritMeta: [
487
+ "inLanguage"
488
+ ],
489
+ resolve(node, ctx) {
490
+ if (node.bookFormat)
491
+ node.bookFormat = ufo.withBase(node.bookFormat, "https://schema.org/");
492
+ if (node.datePublished)
493
+ node.datePublished = resolvableDateToDate(node.datePublished);
494
+ node.author = resolveRelation(node.author, ctx);
495
+ return node;
496
+ },
497
+ resolveRootNode(node, { find }) {
498
+ const identity = find(IdentityId);
499
+ if (identity)
500
+ setIfEmpty(node, "provider", idReference(identity));
501
+ return node;
502
+ }
503
+ });
504
+ const PrimaryBookId = "#book";
505
+ const bookResolver = defineSchemaOrgResolver({
506
+ defaults: {
507
+ "@type": "Book"
508
+ },
509
+ inheritMeta: [
510
+ "description",
511
+ "url",
512
+ { meta: "title", key: "name" }
513
+ ],
514
+ idPrefix: ["url", PrimaryBookId],
515
+ resolve(node, ctx) {
516
+ node.workExample = resolveRelation(node.workExample, ctx, bookEditionResolver);
517
+ node.author = resolveRelation(node.author, ctx);
518
+ if (node.url)
519
+ ufo.withBase(node.url, ctx.meta.host);
520
+ return node;
521
+ },
522
+ resolveRootNode(node, { find }) {
523
+ const identity = find(IdentityId);
524
+ if (identity)
525
+ setIfEmpty(node, "author", idReference(identity));
526
+ return node;
527
+ }
528
+ });
529
+
530
+ const commentResolver = defineSchemaOrgResolver({
531
+ defaults: {
532
+ "@type": "Comment"
533
+ },
534
+ idPrefix: "url",
535
+ resolve(node, ctx) {
536
+ node.author = resolveRelation(node.author, ctx, personResolver, {
537
+ root: true
538
+ });
539
+ return node;
540
+ },
541
+ resolveRootNode(node, { find }) {
542
+ const article = find(PrimaryArticleId);
543
+ if (article)
544
+ setIfEmpty(node, "about", idReference(article));
545
+ }
546
+ });
547
+
548
+ const courseResolver = defineSchemaOrgResolver({
549
+ defaults: {
550
+ "@type": "Course"
551
+ },
552
+ resolve(node, ctx) {
553
+ node.provider = resolveRelation(node.provider, ctx, organizationResolver, {
554
+ root: true
555
+ });
556
+ return node;
557
+ },
558
+ resolveRootNode(node, { find }) {
559
+ const identity = find(IdentityId);
560
+ if (identity)
561
+ setIfEmpty(node, "provider", idReference(identity));
562
+ return node;
563
+ }
564
+ });
565
+
566
+ const placeResolver = defineSchemaOrgResolver({
567
+ defaults: {
568
+ "@type": "Place"
569
+ },
570
+ resolve(node, ctx) {
571
+ node.address = resolveRelation(node.address, ctx, addressResolver);
572
+ return node;
573
+ }
574
+ });
575
+
576
+ const virtualLocationResolver = defineSchemaOrgResolver({
577
+ cast(node) {
578
+ if (typeof node === "string") {
579
+ return {
580
+ url: node
581
+ };
582
+ }
583
+ return node;
584
+ },
585
+ defaults: {
586
+ "@type": "VirtualLocation"
587
+ }
588
+ });
589
+
590
+ const PrimaryEventId = "#event";
591
+ const eventResolver = defineSchemaOrgResolver({
592
+ defaults: {
593
+ "@type": "Event"
594
+ },
595
+ inheritMeta: [
596
+ "inLanguage",
597
+ "description",
598
+ "image",
599
+ { meta: "title", key: "name" }
600
+ ],
601
+ idPrefix: ["url", PrimaryEventId],
602
+ resolve(node, ctx) {
603
+ if (node.location) {
604
+ const isVirtual = node.location === "string" || node.location?.url !== "undefined";
605
+ node.location = resolveRelation(node.location, ctx, isVirtual ? virtualLocationResolver : placeResolver);
606
+ }
607
+ node.performer = resolveRelation(node.performer, ctx, personResolver, {
608
+ root: true
609
+ });
610
+ node.organizer = resolveRelation(node.organizer, ctx, organizationResolver, {
611
+ root: true
612
+ });
613
+ node.offers = resolveRelation(node.offers, ctx, offerResolver);
614
+ if (node.eventAttendanceMode)
615
+ node.eventAttendanceMode = ufo.withBase(node.eventAttendanceMode, "https://schema.org/");
616
+ if (node.eventStatus)
617
+ node.eventStatus = ufo.withBase(node.eventStatus, "https://schema.org/");
618
+ const isOnline = node.eventStatus === "https://schema.org/EventMovedOnline";
619
+ const dates = ["startDate", "previousStartDate", "endDate"];
620
+ dates.forEach((date) => {
621
+ if (!isOnline) {
622
+ if (node[date] instanceof Date && node[date].getHours() === 0 && node[date].getMinutes() === 0)
623
+ node[date] = resolvableDateToDate(node[date]);
624
+ } else {
625
+ node[date] = resolvableDateToIso(node[date]);
626
+ }
627
+ });
628
+ setIfEmpty(node, "endDate", node.startDate);
629
+ return node;
630
+ },
631
+ resolveRootNode(node, { find }) {
632
+ const identity = find(IdentityId);
633
+ if (identity)
634
+ setIfEmpty(node, "organizer", idReference(identity));
635
+ }
636
+ });
637
+
638
+ const howToStepDirectionResolver = defineSchemaOrgResolver({
639
+ cast(node) {
640
+ if (typeof node === "string") {
641
+ return {
642
+ text: node
643
+ };
644
+ }
645
+ return node;
646
+ },
647
+ defaults: {
648
+ "@type": "HowToDirection"
649
+ }
650
+ });
651
+
652
+ const howToStepResolver = defineSchemaOrgResolver({
653
+ cast(node) {
654
+ if (typeof node === "string") {
655
+ return {
656
+ text: node
657
+ };
658
+ }
659
+ return node;
660
+ },
661
+ defaults: {
662
+ "@type": "HowToStep"
663
+ },
664
+ resolve(step, ctx) {
665
+ if (step.url)
666
+ step.url = resolveWithBase(ctx.meta.url, step.url);
667
+ if (step.image) {
668
+ step.image = resolveRelation(step.image, ctx, imageResolver, {
669
+ root: true
670
+ });
671
+ }
672
+ if (step.itemListElement)
673
+ step.itemListElement = resolveRelation(step.itemListElement, ctx, howToStepDirectionResolver);
674
+ return step;
675
+ }
676
+ });
677
+
678
+ const HowToId = "#howto";
679
+ const howToResolver = defineSchemaOrgResolver({
680
+ defaults: {
681
+ "@type": "HowTo"
682
+ },
683
+ inheritMeta: [
684
+ "description",
685
+ "image",
686
+ "inLanguage",
687
+ { meta: "title", key: "name" }
688
+ ],
689
+ idPrefix: ["url", HowToId],
690
+ resolve(node, ctx) {
691
+ node.step = resolveRelation(node.step, ctx, howToStepResolver);
692
+ return node;
693
+ },
694
+ resolveRootNode(node, { find }) {
695
+ const webPage = find(PrimaryWebPageId);
696
+ if (webPage)
697
+ setIfEmpty(node, "mainEntityOfPage", idReference(webPage));
698
+ }
699
+ });
700
+
701
+ const itemListResolver = defineSchemaOrgResolver({
702
+ defaults: {
703
+ "@type": "ItemList"
704
+ },
705
+ resolve(node, ctx) {
706
+ if (node.itemListElement) {
707
+ let index = 1;
708
+ node.itemListElement = resolveRelation(node.itemListElement, ctx, resolveListItem, {
709
+ array: true,
710
+ afterResolve(node2) {
711
+ setIfEmpty(node2, "position", index++);
712
+ }
713
+ });
714
+ }
715
+ return node;
716
+ }
717
+ });
718
+
719
+ const openingHoursResolver = defineSchemaOrgResolver({
720
+ defaults: {
721
+ "@type": "OpeningHoursSpecification",
722
+ "opens": "00:00",
723
+ "closes": "23:59"
724
+ }
725
+ });
726
+
727
+ const localBusinessResolver = defineSchemaOrgResolver({
728
+ defaults: {
729
+ "@type": ["Organization", "LocalBusiness"]
730
+ },
731
+ inheritMeta: [
732
+ { key: "url", meta: "host" },
733
+ { key: "currenciesAccepted", meta: "currency" }
734
+ ],
735
+ idPrefix: ["host", IdentityId],
736
+ resolve(node, ctx) {
737
+ resolveDefaultType(node, ["Organization", "LocalBusiness"]);
738
+ node.address = resolveRelation(node.address, ctx, addressResolver);
739
+ node.openingHoursSpecification = resolveRelation(node.openingHoursSpecification, ctx, openingHoursResolver);
740
+ node.logo = resolveRelation(node.logo, ctx, imageResolver, {
741
+ afterResolve(logo) {
742
+ const hasLogo = !!ctx.find("#logo");
743
+ if (!hasLogo)
744
+ logo["@id"] = prefixId(ctx.meta.host, "#logo");
745
+ setIfEmpty(logo, "caption", node.name);
746
+ }
747
+ });
748
+ return node;
749
+ }
750
+ });
751
+
752
+ const ratingResolver = defineSchemaOrgResolver({
753
+ cast(node) {
754
+ if (node === "number") {
755
+ return {
756
+ ratingValue: node
757
+ };
758
+ }
759
+ return node;
760
+ },
761
+ defaults: {
762
+ "@type": "Rating",
763
+ "bestRating": 5,
764
+ "worstRating": 1
765
+ }
766
+ });
767
+
768
+ const reviewResolver = defineSchemaOrgResolver({
769
+ defaults: {
770
+ "@type": "Review"
771
+ },
772
+ inheritMeta: [
773
+ "inLanguage"
774
+ ],
775
+ resolve(review, ctx) {
776
+ review.reviewRating = resolveRelation(review.reviewRating, ctx, ratingResolver);
777
+ review.author = resolveRelation(review.author, ctx, personResolver);
778
+ return review;
779
+ }
780
+ });
781
+
782
+ const movieResolver = defineSchemaOrgResolver({
783
+ defaults: {
784
+ "@type": "Movie"
785
+ },
786
+ resolve(node, ctx) {
787
+ node.aggregateRating = resolveRelation(node.aggregateRating, ctx, aggregateRatingResolver);
788
+ node.review = resolveRelation(node.review, ctx, reviewResolver);
789
+ node.director = resolveRelation(node.director, ctx, personResolver);
790
+ if (node.dateCreated)
791
+ node.dateCreated = resolvableDateToDate(node.dateCreated);
792
+ return node;
793
+ }
794
+ });
795
+
796
+ const ProductId = "#product";
797
+ const productResolver = defineSchemaOrgResolver({
798
+ defaults: {
799
+ "@type": "Product"
800
+ },
801
+ inheritMeta: [
802
+ "description",
803
+ "image",
804
+ { meta: "title", key: "name" }
805
+ ],
806
+ idPrefix: ["url", ProductId],
807
+ resolve(node, ctx) {
808
+ setIfEmpty(node, "sku", ohash.hash(node.name));
809
+ node.aggregateOffer = resolveRelation(node.aggregateOffer, ctx, aggregateOfferResolver);
810
+ node.aggregateRating = resolveRelation(node.aggregateRating, ctx, aggregateRatingResolver);
811
+ node.offers = resolveRelation(node.offers, ctx, offerResolver);
812
+ node.review = resolveRelation(node.review, ctx, reviewResolver);
813
+ return node;
814
+ },
815
+ resolveRootNode(product, { find }) {
816
+ const webPage = find(PrimaryWebPageId);
817
+ const identity = find(IdentityId);
818
+ if (identity)
819
+ setIfEmpty(product, "brand", idReference(identity));
820
+ if (webPage)
821
+ setIfEmpty(product, "mainEntityOfPage", idReference(webPage));
822
+ return product;
823
+ }
824
+ });
825
+
826
+ const answerResolver = defineSchemaOrgResolver({
827
+ cast(node) {
828
+ if (typeof node === "string") {
829
+ return {
830
+ text: node
831
+ };
832
+ }
833
+ return node;
834
+ },
835
+ defaults: {
836
+ "@type": "Answer"
837
+ }
838
+ });
839
+
840
+ const questionResolver = defineSchemaOrgResolver({
841
+ defaults: {
842
+ "@type": "Question"
843
+ },
844
+ inheritMeta: [
845
+ "inLanguage"
846
+ ],
847
+ idPrefix: "url",
848
+ resolve(question, ctx) {
849
+ if (question.question)
850
+ question.name = question.question;
851
+ if (question.answer)
852
+ question.acceptedAnswer = question.answer;
853
+ question.acceptedAnswer = resolveRelation(question.acceptedAnswer, ctx, answerResolver);
854
+ return question;
855
+ },
856
+ resolveRootNode(question, { find }) {
857
+ const webPage = find(PrimaryWebPageId);
858
+ if (webPage && asArray(webPage["@type"]).includes("FAQPage"))
859
+ dedupeMerge(webPage, "mainEntity", idReference(question));
860
+ }
861
+ });
862
+
863
+ const RecipeId = "#recipe";
864
+ const recipeResolver = defineSchemaOrgResolver({
865
+ defaults: {
866
+ "@type": "Recipe"
867
+ },
868
+ inheritMeta: [
869
+ { meta: "title", key: "name" },
870
+ "description",
871
+ "image",
872
+ "datePublished"
873
+ ],
874
+ idPrefix: ["url", RecipeId],
875
+ resolve(node, ctx) {
876
+ node.recipeInstructions = resolveRelation(node.recipeInstructions, ctx, howToStepResolver);
877
+ return node;
878
+ },
879
+ resolveRootNode(node, { find }) {
880
+ const article = find(PrimaryArticleId);
881
+ const webPage = find(PrimaryWebPageId);
882
+ if (article)
883
+ setIfEmpty(node, "mainEntityOfPage", idReference(article));
884
+ else if (webPage)
885
+ setIfEmpty(node, "mainEntityOfPage", idReference(webPage));
886
+ if (article?.author)
887
+ setIfEmpty(node, "author", article.author);
888
+ return node;
889
+ }
890
+ });
891
+
892
+ const softwareAppResolver = defineSchemaOrgResolver({
893
+ defaults: {
894
+ "@type": "SoftwareApplication"
895
+ },
896
+ resolve(node, ctx) {
897
+ resolveDefaultType(node, "SoftwareApplication");
898
+ node.offers = resolveRelation(node.offers, ctx, offerResolver);
899
+ node.aggregateRating = resolveRelation(node.aggregateRating, ctx, aggregateRatingResolver);
900
+ node.review = resolveRelation(node.review, ctx, reviewResolver);
901
+ return node;
902
+ }
903
+ });
904
+
905
+ const videoResolver = defineSchemaOrgResolver({
906
+ cast(input) {
907
+ if (typeof input === "string") {
908
+ input = {
909
+ url: input
910
+ };
911
+ }
912
+ return input;
913
+ },
914
+ alias: "video",
915
+ defaults: {
916
+ "@type": "VideoObject"
917
+ },
918
+ inheritMeta: [
919
+ { meta: "title", key: "name" },
920
+ "description",
921
+ "image",
922
+ "inLanguage",
923
+ { meta: "datePublished", key: "uploadDate" }
924
+ ],
925
+ idPrefix: "host",
926
+ resolve(video, ctx) {
927
+ if (video.uploadDate)
928
+ video.uploadDate = resolvableDateToIso(video.uploadDate);
929
+ video.url = resolveWithBase(ctx.meta.host, video.url);
930
+ if (video.caption && !video.description)
931
+ video.description = video.caption;
932
+ if (!video.description)
933
+ video.description = "No description";
934
+ if (video.thumbnailUrl)
935
+ video.thumbnailUrl = resolveRelation(video.thumbnailUrl, ctx, imageResolver);
936
+ return video;
937
+ },
938
+ resolveRootNode(video, { find }) {
939
+ if (video.image && !video.thumbnailUrl) {
940
+ const firstImage = asArray(video.image)[0];
941
+ setIfEmpty(video, "thumbnailUrl", find(firstImage["@id"])?.url);
942
+ }
943
+ }
944
+ });
945
+
946
+ function loadResolver(resolver) {
947
+ switch (resolver) {
948
+ case "address":
949
+ return addressResolver;
950
+ case "aggregateOffer":
951
+ return aggregateOfferResolver;
952
+ case "aggregateRating":
953
+ return aggregateRatingResolver;
954
+ case "article":
955
+ return articleResolver;
956
+ case "breadcrumb":
957
+ return breadcrumbResolver;
958
+ case "comment":
959
+ return commentResolver;
960
+ case "event":
961
+ return eventResolver;
962
+ case "virtualLocation":
963
+ return virtualLocationResolver;
964
+ case "place":
965
+ return placeResolver;
966
+ case "howTo":
967
+ return howToResolver;
968
+ case "howToStep":
969
+ return howToStepResolver;
970
+ case "image":
971
+ return imageResolver;
972
+ case "localBusiness":
973
+ return localBusinessResolver;
974
+ case "offer":
975
+ return offerResolver;
976
+ case "openingHours":
977
+ return openingHoursResolver;
978
+ case "organization":
979
+ return organizationResolver;
980
+ case "person":
981
+ return personResolver;
982
+ case "product":
983
+ return productResolver;
984
+ case "question":
985
+ return questionResolver;
986
+ case "recipe":
987
+ return recipeResolver;
988
+ case "review":
989
+ return reviewResolver;
990
+ case "video":
991
+ return videoResolver;
992
+ case "webPage":
993
+ return webPageResolver;
994
+ case "webSite":
995
+ return webSiteResolver;
996
+ case "book":
997
+ return bookResolver;
998
+ case "course":
999
+ return courseResolver;
1000
+ case "itemList":
1001
+ return itemListResolver;
1002
+ case "movie":
1003
+ return movieResolver;
1004
+ case "searchAction":
1005
+ return searchActionResolver;
1006
+ case "readAction":
1007
+ return readActionResolver;
1008
+ case "softwareApp":
1009
+ return softwareAppResolver;
1010
+ case "bookEdition":
1011
+ return bookEditionResolver;
1012
+ }
1013
+ return null;
1014
+ }
1015
+
1016
+ const resolver = {
1017
+ __proto__: null,
1018
+ loadResolver: loadResolver
1019
+ };
1020
+
1021
+ const resolveMeta = (meta) => {
1022
+ if (!meta.host && meta.canonicalHost)
1023
+ meta.host = meta.canonicalHost;
1024
+ if (!meta.tagPosition && meta.position)
1025
+ meta.tagPosition = meta.position;
1026
+ if (!meta.currency && meta.defaultCurrency)
1027
+ meta.currency = meta.defaultCurrency;
1028
+ if (!meta.inLanguage && meta.defaultLanguage)
1029
+ meta.inLanguage = meta.defaultLanguage;
1030
+ if (!meta.path)
1031
+ meta.path = "/";
1032
+ if (!meta.host && typeof document !== "undefined")
1033
+ meta.host = document.location.host;
1034
+ if (!meta.url && meta.canonicalUrl)
1035
+ meta.url = meta.canonicalUrl;
1036
+ meta.url = ufo.joinURL(meta.host, meta.path);
1037
+ return {
1038
+ host: meta.host,
1039
+ url: meta.url,
1040
+ currency: meta.currency,
1041
+ image: meta.image,
1042
+ inLanguage: meta.inLanguage,
1043
+ title: meta.title,
1044
+ description: meta.description,
1045
+ datePublished: meta.datePublished,
1046
+ dateModified: meta.dateModified
1047
+ };
1048
+ };
1049
+ const resolveNode = (node, ctx, resolver) => {
1050
+ if (resolver?.cast)
1051
+ node = resolver.cast(node, ctx);
1052
+ if (resolver?.defaults) {
1053
+ let defaults = resolver.defaults || {};
1054
+ if (typeof defaults === "function")
1055
+ defaults = defaults(ctx);
1056
+ node = defu.defu(node, defaults);
1057
+ }
1058
+ resolver.inheritMeta?.forEach((entry) => {
1059
+ if (typeof entry === "string")
1060
+ setIfEmpty(node, entry, ctx.meta[entry]);
1061
+ else
1062
+ setIfEmpty(node, entry.key, ctx.meta[entry.meta]);
1063
+ });
1064
+ if (resolver?.resolve)
1065
+ node = resolver.resolve(node, ctx);
1066
+ for (const k in node) {
1067
+ const v = node[k];
1068
+ if (typeof v === "object" && v?._resolver)
1069
+ node[k] = resolveRelation(v, ctx, v._resolver);
1070
+ }
1071
+ stripEmptyProperties(node);
1072
+ return node;
1073
+ };
1074
+ const resolveNodeId = (node, ctx, resolver, resolveAsRoot = false) => {
1075
+ const prefix = Array.isArray(resolver.idPrefix) ? resolver.idPrefix[0] : resolver.idPrefix;
1076
+ if (!prefix)
1077
+ return node;
1078
+ if (node["@id"] && !node["@id"].startsWith(ctx.meta.host)) {
1079
+ node["@id"] = prefixId(ctx.meta[prefix], node["@id"]);
1080
+ return node;
1081
+ }
1082
+ const rootId = Array.isArray(resolver.idPrefix) ? resolver.idPrefix?.[1] : void 0;
1083
+ if (resolveAsRoot && rootId) {
1084
+ node["@id"] = prefixId(ctx.meta[prefix], rootId);
1085
+ }
1086
+ if (!node["@id"]) {
1087
+ let alias = resolver?.alias;
1088
+ if (!alias) {
1089
+ const type = asArray(node["@type"])?.[0] || "";
1090
+ alias = type.toLowerCase();
1091
+ }
1092
+ const hashNodeData = {};
1093
+ Object.entries(node).forEach(([key, val]) => {
1094
+ if (!key.startsWith("_"))
1095
+ hashNodeData[key] = val;
1096
+ });
1097
+ node["@id"] = prefixId(ctx.meta[prefix], `#/schema/${alias}/${ohash.hash(hashNodeData)}`);
1098
+ }
1099
+ return node;
1100
+ };
1101
+ function resolveRelation(input, ctx, fallbackResolver, options = {}) {
1102
+ if (!input)
1103
+ return input;
1104
+ const ids = asArray(input).map((a) => {
1105
+ if (Object.keys(a).length === 1 && a["@id"])
1106
+ return a;
1107
+ let resolver = fallbackResolver;
1108
+ if (a._resolver) {
1109
+ resolver = a._resolver;
1110
+ if (typeof resolver === "string")
1111
+ resolver = loadResolver(resolver);
1112
+ delete a._resolver;
1113
+ }
1114
+ if (!resolver)
1115
+ return a;
1116
+ let node = resolveNode(a, ctx, resolver);
1117
+ if (options.afterResolve)
1118
+ options.afterResolve(node);
1119
+ if (options.generateId || options.root)
1120
+ node = resolveNodeId(node, ctx, resolver, false);
1121
+ if (options.root) {
1122
+ if (resolver.resolveRootNode)
1123
+ resolver.resolveRootNode(node, ctx);
1124
+ ctx.push(node);
1125
+ return idReference(node["@id"]);
1126
+ }
1127
+ return node;
1128
+ });
1129
+ if (!options.array && ids.length === 1)
1130
+ return ids[0];
1131
+ return ids;
1132
+ }
1133
+
1134
+ const groupBy = (array, predicate) => array.reduce((acc, value, index, array2) => {
1135
+ const key = predicate(value, index, array2);
1136
+ if (!acc[key])
1137
+ acc[key] = [];
1138
+ acc[key].push(value);
1139
+ return acc;
1140
+ }, {});
1141
+ const dedupeNodes = (nodes) => {
1142
+ const sortedNodeKeys = nodes.keys();
1143
+ const dedupedNodes = {};
1144
+ for (const key of sortedNodeKeys) {
1145
+ const n = nodes[key];
1146
+ const nodeKey = resolveAsGraphKey(n["@id"] || ohash.hash(n));
1147
+ const groupedKeys = groupBy(Object.keys(n), (key2) => {
1148
+ const val = n[key2];
1149
+ if (key2.startsWith("_"))
1150
+ return "ignored";
1151
+ if (Array.isArray(val) || typeof val === "object")
1152
+ return "relations";
1153
+ return "primitives";
1154
+ });
1155
+ const keys = [
1156
+ ...(groupedKeys.primitives || []).sort(),
1157
+ ...(groupedKeys.relations || []).sort()
1158
+ ];
1159
+ const newNode = {};
1160
+ for (const key2 of keys)
1161
+ newNode[key2] = n[key2];
1162
+ dedupedNodes[nodeKey] = newNode;
1163
+ }
1164
+ return Object.values(dedupedNodes);
1165
+ };
1166
+
1167
+ const createSchemaOrgGraph = () => {
1168
+ const ctx = {
1169
+ find(id) {
1170
+ const key = resolveAsGraphKey(id);
1171
+ return ctx.nodes.filter((n) => !!n["@id"]).find((n) => resolveAsGraphKey(n["@id"]) === key);
1172
+ },
1173
+ push(input) {
1174
+ asArray(input).forEach((node) => {
1175
+ const registeredNode = node;
1176
+ ctx.nodes.push(registeredNode);
1177
+ });
1178
+ },
1179
+ resolveGraph(meta) {
1180
+ ctx.meta = resolveMeta({ ...meta });
1181
+ ctx.nodes.forEach((node, key) => {
1182
+ const resolver = node._resolver;
1183
+ if (resolver) {
1184
+ node = resolveNode(node, ctx, resolver);
1185
+ node = resolveNodeId(node, ctx, resolver, true);
1186
+ }
1187
+ ctx.nodes[key] = node;
1188
+ });
1189
+ ctx.nodes.forEach((node) => {
1190
+ if (node.image && typeof node.image === "string") {
1191
+ node.image = resolveRelation(node.image, ctx, imageResolver, {
1192
+ root: true
1193
+ });
1194
+ }
1195
+ if (node._resolver?.resolveRootNode)
1196
+ node._resolver.resolveRootNode(node, ctx);
1197
+ delete node._resolver;
1198
+ });
1199
+ return dedupeNodes(ctx.nodes);
1200
+ },
1201
+ nodes: [],
1202
+ meta: {}
1203
+ };
1204
+ return ctx;
1205
+ };
1206
+
1207
+ function SchemaOrgUnheadPlugin(config, meta) {
1208
+ config = resolveMeta({ ...config });
1209
+ let graph;
1210
+ const resolvedMeta = {};
1211
+ return {
1212
+ hooks: {
1213
+ "entries:resolve": function() {
1214
+ graph = createSchemaOrgGraph();
1215
+ },
1216
+ "tag:normalise": async function({ tag }) {
1217
+ if (tag.key === "schema-org-graph") {
1218
+ const { loadResolver } = await Promise.resolve().then(function () { return resolver; });
1219
+ const nodes = await tag.props.nodes;
1220
+ for (const node of Array.isArray(nodes) ? nodes : [nodes]) {
1221
+ const newNode = {
1222
+ ...node,
1223
+ _resolver: loadResolver(await node._resolver)
1224
+ };
1225
+ graph.push(newNode);
1226
+ }
1227
+ tag.tagPosition = config.tagPosition === "head" ? "head" : "bodyClose";
1228
+ }
1229
+ if (tag.tag === "title")
1230
+ resolvedMeta.title = tag.children;
1231
+ else if (tag.tag === "meta" && tag.props.name === "description")
1232
+ resolvedMeta.description = tag.props.content;
1233
+ else if (tag.tag === "link" && tag.props.rel === "canonical")
1234
+ resolvedMeta.url = tag.props.href;
1235
+ else if (tag.tag === "meta" && tag.props.property === "og:image")
1236
+ resolvedMeta.image = tag.props.content;
1237
+ },
1238
+ "tags:resolve": async function(ctx) {
1239
+ for (const tag of ctx.tags) {
1240
+ if (tag.tag === "script" && tag.key === "schema-org-graph") {
1241
+ tag.children = JSON.stringify({
1242
+ "@context": "https://schema.org",
1243
+ "@graph": graph.resolveGraph({ ...config, ...resolvedMeta, ...await meta() })
1244
+ }, null, 2);
1245
+ delete tag.props.nodes;
1246
+ }
1247
+ }
1248
+ }
1249
+ }
1250
+ };
1251
+ }
1252
+
1253
+ const provideResolver = (input, resolver) => {
1254
+ if (!input)
1255
+ input = {};
1256
+ input._resolver = resolver;
1257
+ return input;
1258
+ };
1259
+ const defineAddress = (input) => provideResolver(input, "address");
1260
+ const defineAggregateOffer = (input) => provideResolver(input, "aggregateOffer");
1261
+ const defineAggregateRating = (input) => provideResolver(input, "aggregateRating");
1262
+ const defineArticle = (input) => provideResolver(input, "article");
1263
+ const defineBreadcrumb = (input) => provideResolver(input, "breadcrumb");
1264
+ const defineComment = (input) => provideResolver(input, "comment");
1265
+ const defineEvent = (input) => provideResolver(input, "event");
1266
+ const defineVirtualLocation = (input) => provideResolver(input, "virtualLocation");
1267
+ const definePlace = (input) => provideResolver(input, "place");
1268
+ const defineHowTo = (input) => provideResolver(input, "howTo");
1269
+ const defineHowToStep = (input) => provideResolver(input, "howToStep");
1270
+ const defineImage = (input) => provideResolver(input, "image");
1271
+ const defineLocalBusiness = (input) => provideResolver(input, "localBusiness");
1272
+ const defineOffer = (input) => provideResolver(input, "offer");
1273
+ const defineOpeningHours = (input) => provideResolver(input, "openingHours");
1274
+ const defineOrganization = (input) => provideResolver(input, "organization");
1275
+ const definePerson = (input) => provideResolver(input, "person");
1276
+ const defineProduct = (input) => provideResolver(input, "product");
1277
+ const defineQuestion = (input) => provideResolver(input, "question");
1278
+ const defineRecipe = (input) => provideResolver(input, "recipe");
1279
+ const defineReview = (input) => provideResolver(input, "review");
1280
+ const defineVideo = (input) => provideResolver(input, "video");
1281
+ const defineWebPage = (input) => provideResolver(input, "webPage");
1282
+ const defineWebSite = (input) => provideResolver(input, "webSite");
1283
+ const defineBook = (input) => provideResolver(input, "book");
1284
+ const defineCourse = (input) => provideResolver(input, "course");
1285
+ const defineItemList = (input) => provideResolver(input, "itemList");
1286
+ const defineMovie = (input) => provideResolver(input, "movie");
1287
+ const defineSearchAction = (input) => provideResolver(input, "searchAction");
1288
+ const defineReadAction = (input) => provideResolver(input, "readAction");
1289
+ const defineSoftwareApp = (input) => provideResolver(input, "softwareApp");
1290
+ const defineBookEdition = (input) => provideResolver(input, "bookEdition");
1291
+ function useSchemaOrg(input) {
1292
+ return unhead.useHead({
1293
+ script: [
1294
+ {
1295
+ type: "application/ld+json",
1296
+ key: "schema-org-graph",
1297
+ nodes: input
1298
+ }
1299
+ ]
1300
+ }, { mode: process.env.NODE_ENV === "development" ? "all" : "server" });
1301
+ }
1302
+
1303
+ exports.HowToId = HowToId;
1304
+ exports.PrimaryArticleId = PrimaryArticleId;
1305
+ exports.PrimaryBookId = PrimaryBookId;
1306
+ exports.PrimaryBreadcrumbId = PrimaryBreadcrumbId;
1307
+ exports.PrimaryEventId = PrimaryEventId;
1308
+ exports.PrimaryWebPageId = PrimaryWebPageId;
1309
+ exports.PrimaryWebSiteId = PrimaryWebSiteId;
1310
+ exports.ProductId = ProductId;
1311
+ exports.RecipeId = RecipeId;
1312
+ exports.SchemaOrgUnheadPlugin = SchemaOrgUnheadPlugin;
1313
+ exports.addressResolver = addressResolver;
1314
+ exports.aggregateOfferResolver = aggregateOfferResolver;
1315
+ exports.aggregateRatingResolver = aggregateRatingResolver;
1316
+ exports.articleResolver = articleResolver;
1317
+ exports.bookEditionResolver = bookEditionResolver;
1318
+ exports.bookResolver = bookResolver;
1319
+ exports.breadcrumbResolver = breadcrumbResolver;
1320
+ exports.commentResolver = commentResolver;
1321
+ exports.courseResolver = courseResolver;
1322
+ exports.createSchemaOrgGraph = createSchemaOrgGraph;
1323
+ exports.dedupeNodes = dedupeNodes;
1324
+ exports.defineAddress = defineAddress;
1325
+ exports.defineAggregateOffer = defineAggregateOffer;
1326
+ exports.defineAggregateRating = defineAggregateRating;
1327
+ exports.defineArticle = defineArticle;
1328
+ exports.defineBook = defineBook;
1329
+ exports.defineBookEdition = defineBookEdition;
1330
+ exports.defineBreadcrumb = defineBreadcrumb;
1331
+ exports.defineComment = defineComment;
1332
+ exports.defineCourse = defineCourse;
1333
+ exports.defineEvent = defineEvent;
1334
+ exports.defineHowTo = defineHowTo;
1335
+ exports.defineHowToStep = defineHowToStep;
1336
+ exports.defineImage = defineImage;
1337
+ exports.defineItemList = defineItemList;
1338
+ exports.defineLocalBusiness = defineLocalBusiness;
1339
+ exports.defineMovie = defineMovie;
1340
+ exports.defineOffer = defineOffer;
1341
+ exports.defineOpeningHours = defineOpeningHours;
1342
+ exports.defineOrganization = defineOrganization;
1343
+ exports.definePerson = definePerson;
1344
+ exports.definePlace = definePlace;
1345
+ exports.defineProduct = defineProduct;
1346
+ exports.defineQuestion = defineQuestion;
1347
+ exports.defineReadAction = defineReadAction;
1348
+ exports.defineRecipe = defineRecipe;
1349
+ exports.defineReview = defineReview;
1350
+ exports.defineSchemaOrgResolver = defineSchemaOrgResolver;
1351
+ exports.defineSearchAction = defineSearchAction;
1352
+ exports.defineSoftwareApp = defineSoftwareApp;
1353
+ exports.defineVideo = defineVideo;
1354
+ exports.defineVirtualLocation = defineVirtualLocation;
1355
+ exports.defineWebPage = defineWebPage;
1356
+ exports.defineWebSite = defineWebSite;
1357
+ exports.eventResolver = eventResolver;
1358
+ exports.howToResolver = howToResolver;
1359
+ exports.howToStepDirectionResolver = howToStepDirectionResolver;
1360
+ exports.howToStepResolver = howToStepResolver;
1361
+ exports.imageResolver = imageResolver;
1362
+ exports.itemListResolver = itemListResolver;
1363
+ exports.localBusinessResolver = localBusinessResolver;
1364
+ exports.movieResolver = movieResolver;
1365
+ exports.offerResolver = offerResolver;
1366
+ exports.openingHoursResolver = openingHoursResolver;
1367
+ exports.organizationResolver = organizationResolver;
1368
+ exports.personResolver = personResolver;
1369
+ exports.placeResolver = placeResolver;
1370
+ exports.productResolver = productResolver;
1371
+ exports.questionResolver = questionResolver;
1372
+ exports.ratingResolver = ratingResolver;
1373
+ exports.readActionResolver = readActionResolver;
1374
+ exports.recipeResolver = recipeResolver;
1375
+ exports.resolveListItem = resolveListItem;
1376
+ exports.resolveMeta = resolveMeta;
1377
+ exports.resolveNode = resolveNode;
1378
+ exports.resolveNodeId = resolveNodeId;
1379
+ exports.resolveRelation = resolveRelation;
1380
+ exports.reviewResolver = reviewResolver;
1381
+ exports.searchActionResolver = searchActionResolver;
1382
+ exports.softwareAppResolver = softwareAppResolver;
1383
+ exports.useSchemaOrg = useSchemaOrg;
1384
+ exports.videoResolver = videoResolver;
1385
+ exports.virtualLocationResolver = virtualLocationResolver;
1386
+ exports.webPageResolver = webPageResolver;
1387
+ exports.webSiteResolver = webSiteResolver;