@websolutespa/bom-mixer-models 1.8.0 → 1.8.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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +37 -4
- package/dist/index.js +102 -26
- package/dist/index.mjs +98 -26
- package/package.json +1 -1
- package/src/page/page.service.ts +17 -10
- package/src/sitemap/sitemap.service.ts +1 -1
- package/src/structured_data/structured_data.ts +131 -21
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -257,11 +257,14 @@ type StructuredDataAddress = {
|
|
|
257
257
|
streetAddress: string;
|
|
258
258
|
};
|
|
259
259
|
type StructuredDataPlace = {
|
|
260
|
+
'@context'?: 'https://schema.org';
|
|
260
261
|
'@type': 'Place';
|
|
261
262
|
name: string;
|
|
262
263
|
address: StructuredDataAddress;
|
|
264
|
+
url: string;
|
|
263
265
|
};
|
|
264
266
|
type StructuredDataOrganization = {
|
|
267
|
+
'@context'?: 'https://schema.org';
|
|
265
268
|
'@type': 'Organization';
|
|
266
269
|
address?: StructuredDataAddress;
|
|
267
270
|
alumni?: StructuredDataPerson[];
|
|
@@ -270,16 +273,27 @@ type StructuredDataOrganization = {
|
|
|
270
273
|
member?: StructuredDataOrganization[];
|
|
271
274
|
name: string;
|
|
272
275
|
telephone?: string;
|
|
276
|
+
brand?: StructuredDataBrand;
|
|
273
277
|
url?: string;
|
|
274
278
|
};
|
|
279
|
+
type StructuredDataProduct = {
|
|
280
|
+
'@context'?: 'https://schema.org';
|
|
281
|
+
'@type': 'Product';
|
|
282
|
+
name: string;
|
|
283
|
+
description?: string;
|
|
284
|
+
image?: string;
|
|
285
|
+
brand: StructuredDataBrand;
|
|
286
|
+
url: string;
|
|
287
|
+
};
|
|
275
288
|
type StructuredDataArticle = {
|
|
276
|
-
'@context'
|
|
289
|
+
'@context'?: 'https://schema.org';
|
|
277
290
|
'@type': 'Article' | 'BlogPosting' | 'NewsArticle';
|
|
278
291
|
author: (StructuredDataPerson | StructuredDataOrganization)[];
|
|
279
292
|
dateModified: Date | string;
|
|
280
293
|
datePublished: Date | string;
|
|
281
294
|
headline: string;
|
|
282
295
|
image: string[];
|
|
296
|
+
url: string;
|
|
283
297
|
};
|
|
284
298
|
type StructuredDataEvent = {
|
|
285
299
|
'@context': 'https://schema.org';
|
|
@@ -293,11 +307,30 @@ type StructuredDataEvent = {
|
|
|
293
307
|
offers?: StructuredDataOffer;
|
|
294
308
|
performer?: StructuredDataPerformingGroup;
|
|
295
309
|
organizer?: StructuredDataOrganization;
|
|
310
|
+
url: string;
|
|
311
|
+
};
|
|
312
|
+
type StructuredDataBrand = {
|
|
313
|
+
'@context'?: 'https://schema.org';
|
|
314
|
+
'@type': 'Brand';
|
|
315
|
+
name: string;
|
|
316
|
+
description?: string;
|
|
317
|
+
logo?: string;
|
|
318
|
+
url: string;
|
|
319
|
+
};
|
|
320
|
+
type IBrand = {
|
|
321
|
+
name: string;
|
|
322
|
+
description?: string;
|
|
323
|
+
logo?: string;
|
|
324
|
+
url?: string;
|
|
296
325
|
};
|
|
297
|
-
type StructuredDataKeys = 'article';
|
|
326
|
+
type StructuredDataKeys = 'product' | 'article' | 'contact' | 'brand';
|
|
298
327
|
type StructuredDataCollections = Record<StructuredDataKeys, string[]>;
|
|
299
328
|
declare function resolveTemplate(value: any): string | undefined;
|
|
300
329
|
declare function resolveMediaSrc(media: IMedia): string | undefined;
|
|
301
|
-
declare function
|
|
330
|
+
declare function resolveStructuredDataProduct(page: IPage, brand?: IBrand): StructuredDataProduct;
|
|
331
|
+
declare function resolveStructuredDataArticle(page: IPage, brand?: IBrand): StructuredDataArticle;
|
|
332
|
+
declare function resolveStructuredDataOrganization(page: IPage, brand?: IBrand): StructuredDataOrganization;
|
|
333
|
+
declare function resolveStructuredDataBrand(page: IPage, brand?: IBrand): StructuredDataBrand;
|
|
334
|
+
declare function resolveStructuredData(page: IPage, types?: Partial<StructuredDataCollections>, brand?: IBrand): string | undefined;
|
|
302
335
|
|
|
303
|
-
export { IAddress, IAddressOptions, IAppProps, IApplication, IApplicationProps, ICompanyAddress, IFeatureType, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, ILink, IModelStore, INullableLazyableProps, ISiteMap, LAZY_PROPS, NotFound, PartialPageProps, SeoWeight, StaticPath, StructuredDataAddress, StructuredDataArticle, StructuredDataCollections, StructuredDataEvent, StructuredDataKeys, StructuredDataOffer, StructuredDataOrganization, StructuredDataPerformingGroup, StructuredDataPerson, StructuredDataPlace, categoryToRouteLink, findManyPages, findOnePage, getAddressOptions, getBreadcrumbFromSegments, getCaptionsVttProps, getCategories, getCategory, getCountries, getCountry, getDecoratedComponents, getErrorPageLayout, getFeatureType, getFeatureTypes, getLabel, getLabels, getLayout, getLocale, getLocaleFromProps, getLocales, getMarket, getMarkets, getMenu, getMenus, getPage, getPageCategory, getPageProps, getPageRoutes, getPreviewProps, getProvince, getProvinces, getPublicUrl, getRedirect, getRedirects, getRegion, getRegions, getRoute, getRouteLinkTree, getRoutes, getRoutesForSchemas, getRoutesForTemplates, getSegments, getSeoWeight, getSiteMapIndex, getSiteMapIndexProps, getSiteMapXML, getSiteMapXMLProps, getSiteMapXSL, getSiteMapXSLProps, getStaticPathsForSchema, newRouteLink, redirectTo, resolveHref, resolveLabel, resolveMediaSrc, resolveRoute, resolveStructuredData, resolveTemplate, routeInterceptor, routeRevalidateHandler, routeToRouteLink, withLazyProps };
|
|
336
|
+
export { IAddress, IAddressOptions, IAppProps, IApplication, IApplicationProps, IBrand, ICompanyAddress, IFeatureType, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, ILink, IModelStore, INullableLazyableProps, ISiteMap, LAZY_PROPS, NotFound, PartialPageProps, SeoWeight, StaticPath, StructuredDataAddress, StructuredDataArticle, StructuredDataBrand, StructuredDataCollections, StructuredDataEvent, StructuredDataKeys, StructuredDataOffer, StructuredDataOrganization, StructuredDataPerformingGroup, StructuredDataPerson, StructuredDataPlace, StructuredDataProduct, categoryToRouteLink, findManyPages, findOnePage, getAddressOptions, getBreadcrumbFromSegments, getCaptionsVttProps, getCategories, getCategory, getCountries, getCountry, getDecoratedComponents, getErrorPageLayout, getFeatureType, getFeatureTypes, getLabel, getLabels, getLayout, getLocale, getLocaleFromProps, getLocales, getMarket, getMarkets, getMenu, getMenus, getPage, getPageCategory, getPageProps, getPageRoutes, getPreviewProps, getProvince, getProvinces, getPublicUrl, getRedirect, getRedirects, getRegion, getRegions, getRoute, getRouteLinkTree, getRoutes, getRoutesForSchemas, getRoutesForTemplates, getSegments, getSeoWeight, getSiteMapIndex, getSiteMapIndexProps, getSiteMapXML, getSiteMapXMLProps, getSiteMapXSL, getSiteMapXSLProps, getStaticPathsForSchema, newRouteLink, redirectTo, resolveHref, resolveLabel, resolveMediaSrc, resolveRoute, resolveStructuredData, resolveStructuredDataArticle, resolveStructuredDataBrand, resolveStructuredDataOrganization, resolveStructuredDataProduct, resolveTemplate, routeInterceptor, routeRevalidateHandler, routeToRouteLink, withLazyProps };
|
package/dist/index.js
CHANGED
|
@@ -79,6 +79,10 @@ __export(src_exports, {
|
|
|
79
79
|
resolveMediaSrc: () => resolveMediaSrc,
|
|
80
80
|
resolveRoute: () => resolveRoute,
|
|
81
81
|
resolveStructuredData: () => resolveStructuredData,
|
|
82
|
+
resolveStructuredDataArticle: () => resolveStructuredDataArticle,
|
|
83
|
+
resolveStructuredDataBrand: () => resolveStructuredDataBrand,
|
|
84
|
+
resolveStructuredDataOrganization: () => resolveStructuredDataOrganization,
|
|
85
|
+
resolveStructuredDataProduct: () => resolveStructuredDataProduct,
|
|
82
86
|
resolveTemplate: () => resolveTemplate,
|
|
83
87
|
routeInterceptor: () => routeInterceptor,
|
|
84
88
|
routeRevalidateHandler: () => routeRevalidateHandler,
|
|
@@ -621,16 +625,22 @@ async function getErrorPageLayout() {
|
|
|
621
625
|
const layout = await getLayout(import_bom_core3.defaultMarket, import_bom_core3.defaultLocale);
|
|
622
626
|
const title = resolveLabel(layout.labels, "notfound.title");
|
|
623
627
|
const abstract = resolveLabel(layout.labels, "notfound.abstract");
|
|
628
|
+
const category = layout.tree ? {
|
|
629
|
+
id: layout.tree.category,
|
|
630
|
+
title: layout.tree.title,
|
|
631
|
+
href: layout.tree.href,
|
|
632
|
+
slug: ""
|
|
633
|
+
} : {
|
|
634
|
+
id: "homepage",
|
|
635
|
+
title: "Homepage",
|
|
636
|
+
slug: "",
|
|
637
|
+
href: "/"
|
|
638
|
+
};
|
|
624
639
|
const page = {
|
|
625
640
|
abstract,
|
|
626
641
|
alternates: [],
|
|
627
642
|
breadcrumb: [],
|
|
628
|
-
category
|
|
629
|
-
id: "homepage",
|
|
630
|
-
title: "homepage",
|
|
631
|
-
slug: "",
|
|
632
|
-
href: ""
|
|
633
|
-
},
|
|
643
|
+
category,
|
|
634
644
|
slug: "",
|
|
635
645
|
href: "",
|
|
636
646
|
id: "notfound",
|
|
@@ -825,7 +835,7 @@ function getSiteMapXMLLastMod(canonical) {
|
|
|
825
835
|
function getSiteMapXMLImage(canonical) {
|
|
826
836
|
return canonical.media ? `
|
|
827
837
|
<image:image>
|
|
828
|
-
<image:loc>${canonical.media.src}</image:loc>
|
|
838
|
+
<image:loc>${canonical.media.src || canonical.media.url}</image:loc>
|
|
829
839
|
</image:image>` : "";
|
|
830
840
|
}
|
|
831
841
|
function getSiteMapXMLAlternates(origin, canonical) {
|
|
@@ -1091,7 +1101,10 @@ var getSiteMapXSLProps = async (context) => {
|
|
|
1091
1101
|
// src/structured_data/structured_data.ts
|
|
1092
1102
|
var import_bom_core7 = require("@websolutespa/bom-core");
|
|
1093
1103
|
var DefaultStructuredDataCollections = {
|
|
1094
|
-
|
|
1104
|
+
product: ["product_detail"],
|
|
1105
|
+
article: ["news_detail"],
|
|
1106
|
+
contact: ["contact"],
|
|
1107
|
+
brand: ["homepage"]
|
|
1095
1108
|
};
|
|
1096
1109
|
function resolveTemplate(value) {
|
|
1097
1110
|
return (0, import_bom_core7.asEquatableString)(value);
|
|
@@ -1099,28 +1112,87 @@ function resolveTemplate(value) {
|
|
|
1099
1112
|
function resolveMediaSrc(media) {
|
|
1100
1113
|
return resolveHref(media.src || media.url);
|
|
1101
1114
|
}
|
|
1102
|
-
function
|
|
1103
|
-
|
|
1115
|
+
function resolveStructuredDataProduct(page, brand) {
|
|
1116
|
+
const mediaSrc = page.media ? resolveMediaSrc(page.media) : void 0;
|
|
1117
|
+
const schema = {
|
|
1118
|
+
"@context": "https://schema.org",
|
|
1119
|
+
"@type": "Product",
|
|
1120
|
+
name: page.title,
|
|
1121
|
+
image: mediaSrc || "",
|
|
1122
|
+
brand: resolveStructuredDataBrand(page, brand),
|
|
1123
|
+
url: resolveHref(page.href)
|
|
1124
|
+
};
|
|
1125
|
+
return schema;
|
|
1126
|
+
}
|
|
1127
|
+
function resolveStructuredDataArticle(page, brand) {
|
|
1128
|
+
const mediaSrc = page.media ? resolveMediaSrc(page.media) : void 0;
|
|
1129
|
+
const schema = {
|
|
1130
|
+
"@context": "https://schema.org",
|
|
1131
|
+
"@type": "Article",
|
|
1132
|
+
headline: page.title,
|
|
1133
|
+
image: mediaSrc ? [mediaSrc] : [],
|
|
1134
|
+
datePublished: page.createdAt,
|
|
1135
|
+
dateModified: page.updatedAt,
|
|
1136
|
+
author: [
|
|
1137
|
+
resolveStructuredDataOrganization(page, brand)
|
|
1138
|
+
],
|
|
1139
|
+
url: resolveHref(page.href)
|
|
1140
|
+
};
|
|
1141
|
+
return schema;
|
|
1142
|
+
}
|
|
1143
|
+
function resolveStructuredDataOrganization(page, brand = {
|
|
1144
|
+
name: "WebsiteName"
|
|
1145
|
+
}) {
|
|
1146
|
+
const schema = {
|
|
1147
|
+
"@context": "https://schema.org",
|
|
1148
|
+
"@type": "Organization",
|
|
1149
|
+
name: brand.name,
|
|
1150
|
+
brand: resolveStructuredDataBrand(page, brand),
|
|
1151
|
+
url: resolveHref(page.href)
|
|
1152
|
+
};
|
|
1153
|
+
return schema;
|
|
1154
|
+
}
|
|
1155
|
+
function resolveStructuredDataBrand(page, brand = {
|
|
1156
|
+
name: "WebsiteName"
|
|
1157
|
+
}) {
|
|
1158
|
+
const schema = {
|
|
1159
|
+
"@context": "https://schema.org",
|
|
1160
|
+
"@type": "Brand",
|
|
1161
|
+
name: brand.name,
|
|
1162
|
+
url: brand.url || getPublicUrl()
|
|
1163
|
+
};
|
|
1164
|
+
if (brand.description) {
|
|
1165
|
+
schema.description = brand.description;
|
|
1166
|
+
}
|
|
1167
|
+
if (brand.logo) {
|
|
1168
|
+
schema.logo = resolveHref(brand.logo);
|
|
1169
|
+
}
|
|
1170
|
+
return schema;
|
|
1171
|
+
}
|
|
1172
|
+
function resolveStructuredData(page, types, brand) {
|
|
1173
|
+
const structuredDataCollections = {
|
|
1174
|
+
...DefaultStructuredDataCollections,
|
|
1175
|
+
...types
|
|
1176
|
+
};
|
|
1104
1177
|
let pageType = page.schema || "";
|
|
1105
1178
|
if (page.template) {
|
|
1106
1179
|
pageType = (0, import_bom_core7.asEquatableString)(page.template);
|
|
1107
1180
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1181
|
+
const schema = Object.entries(structuredDataCollections).reduce((p, kv) => {
|
|
1182
|
+
if (p) {
|
|
1183
|
+
return p;
|
|
1184
|
+
}
|
|
1185
|
+
switch (kv[0]) {
|
|
1186
|
+
case "product":
|
|
1187
|
+
return kv[1].includes(pageType) ? resolveStructuredDataProduct(page, brand) : null;
|
|
1188
|
+
case "article":
|
|
1189
|
+
return kv[1].includes(pageType) ? resolveStructuredDataArticle(page, brand) : null;
|
|
1190
|
+
case "contact":
|
|
1191
|
+
return kv[1].includes(pageType) ? resolveStructuredDataOrganization(page, brand) : null;
|
|
1192
|
+
default:
|
|
1193
|
+
return resolveStructuredDataBrand(page, brand);
|
|
1194
|
+
}
|
|
1195
|
+
}, null);
|
|
1124
1196
|
if (schema) {
|
|
1125
1197
|
return JSON.stringify(schema);
|
|
1126
1198
|
}
|
|
@@ -1187,6 +1259,10 @@ function resolveStructuredData(page, websiteName = "WebsiteName", types = Defaul
|
|
|
1187
1259
|
resolveMediaSrc,
|
|
1188
1260
|
resolveRoute,
|
|
1189
1261
|
resolveStructuredData,
|
|
1262
|
+
resolveStructuredDataArticle,
|
|
1263
|
+
resolveStructuredDataBrand,
|
|
1264
|
+
resolveStructuredDataOrganization,
|
|
1265
|
+
resolveStructuredDataProduct,
|
|
1190
1266
|
resolveTemplate,
|
|
1191
1267
|
routeInterceptor,
|
|
1192
1268
|
routeRevalidateHandler,
|
package/dist/index.mjs
CHANGED
|
@@ -532,16 +532,22 @@ async function getErrorPageLayout() {
|
|
|
532
532
|
const layout = await getLayout(defaultMarket2, defaultLocale2);
|
|
533
533
|
const title = resolveLabel(layout.labels, "notfound.title");
|
|
534
534
|
const abstract = resolveLabel(layout.labels, "notfound.abstract");
|
|
535
|
+
const category = layout.tree ? {
|
|
536
|
+
id: layout.tree.category,
|
|
537
|
+
title: layout.tree.title,
|
|
538
|
+
href: layout.tree.href,
|
|
539
|
+
slug: ""
|
|
540
|
+
} : {
|
|
541
|
+
id: "homepage",
|
|
542
|
+
title: "Homepage",
|
|
543
|
+
slug: "",
|
|
544
|
+
href: "/"
|
|
545
|
+
};
|
|
535
546
|
const page = {
|
|
536
547
|
abstract,
|
|
537
548
|
alternates: [],
|
|
538
549
|
breadcrumb: [],
|
|
539
|
-
category
|
|
540
|
-
id: "homepage",
|
|
541
|
-
title: "homepage",
|
|
542
|
-
slug: "",
|
|
543
|
-
href: ""
|
|
544
|
-
},
|
|
550
|
+
category,
|
|
545
551
|
slug: "",
|
|
546
552
|
href: "",
|
|
547
553
|
id: "notfound",
|
|
@@ -736,7 +742,7 @@ function getSiteMapXMLLastMod(canonical) {
|
|
|
736
742
|
function getSiteMapXMLImage(canonical) {
|
|
737
743
|
return canonical.media ? `
|
|
738
744
|
<image:image>
|
|
739
|
-
<image:loc>${canonical.media.src}</image:loc>
|
|
745
|
+
<image:loc>${canonical.media.src || canonical.media.url}</image:loc>
|
|
740
746
|
</image:image>` : "";
|
|
741
747
|
}
|
|
742
748
|
function getSiteMapXMLAlternates(origin, canonical) {
|
|
@@ -1002,7 +1008,10 @@ var getSiteMapXSLProps = async (context) => {
|
|
|
1002
1008
|
// src/structured_data/structured_data.ts
|
|
1003
1009
|
import { asEquatableString } from "@websolutespa/bom-core";
|
|
1004
1010
|
var DefaultStructuredDataCollections = {
|
|
1005
|
-
|
|
1011
|
+
product: ["product_detail"],
|
|
1012
|
+
article: ["news_detail"],
|
|
1013
|
+
contact: ["contact"],
|
|
1014
|
+
brand: ["homepage"]
|
|
1006
1015
|
};
|
|
1007
1016
|
function resolveTemplate(value) {
|
|
1008
1017
|
return asEquatableString(value);
|
|
@@ -1010,28 +1019,87 @@ function resolveTemplate(value) {
|
|
|
1010
1019
|
function resolveMediaSrc(media) {
|
|
1011
1020
|
return resolveHref(media.src || media.url);
|
|
1012
1021
|
}
|
|
1013
|
-
function
|
|
1014
|
-
|
|
1022
|
+
function resolveStructuredDataProduct(page, brand) {
|
|
1023
|
+
const mediaSrc = page.media ? resolveMediaSrc(page.media) : void 0;
|
|
1024
|
+
const schema = {
|
|
1025
|
+
"@context": "https://schema.org",
|
|
1026
|
+
"@type": "Product",
|
|
1027
|
+
name: page.title,
|
|
1028
|
+
image: mediaSrc || "",
|
|
1029
|
+
brand: resolveStructuredDataBrand(page, brand),
|
|
1030
|
+
url: resolveHref(page.href)
|
|
1031
|
+
};
|
|
1032
|
+
return schema;
|
|
1033
|
+
}
|
|
1034
|
+
function resolveStructuredDataArticle(page, brand) {
|
|
1035
|
+
const mediaSrc = page.media ? resolveMediaSrc(page.media) : void 0;
|
|
1036
|
+
const schema = {
|
|
1037
|
+
"@context": "https://schema.org",
|
|
1038
|
+
"@type": "Article",
|
|
1039
|
+
headline: page.title,
|
|
1040
|
+
image: mediaSrc ? [mediaSrc] : [],
|
|
1041
|
+
datePublished: page.createdAt,
|
|
1042
|
+
dateModified: page.updatedAt,
|
|
1043
|
+
author: [
|
|
1044
|
+
resolveStructuredDataOrganization(page, brand)
|
|
1045
|
+
],
|
|
1046
|
+
url: resolveHref(page.href)
|
|
1047
|
+
};
|
|
1048
|
+
return schema;
|
|
1049
|
+
}
|
|
1050
|
+
function resolveStructuredDataOrganization(page, brand = {
|
|
1051
|
+
name: "WebsiteName"
|
|
1052
|
+
}) {
|
|
1053
|
+
const schema = {
|
|
1054
|
+
"@context": "https://schema.org",
|
|
1055
|
+
"@type": "Organization",
|
|
1056
|
+
name: brand.name,
|
|
1057
|
+
brand: resolveStructuredDataBrand(page, brand),
|
|
1058
|
+
url: resolveHref(page.href)
|
|
1059
|
+
};
|
|
1060
|
+
return schema;
|
|
1061
|
+
}
|
|
1062
|
+
function resolveStructuredDataBrand(page, brand = {
|
|
1063
|
+
name: "WebsiteName"
|
|
1064
|
+
}) {
|
|
1065
|
+
const schema = {
|
|
1066
|
+
"@context": "https://schema.org",
|
|
1067
|
+
"@type": "Brand",
|
|
1068
|
+
name: brand.name,
|
|
1069
|
+
url: brand.url || getPublicUrl()
|
|
1070
|
+
};
|
|
1071
|
+
if (brand.description) {
|
|
1072
|
+
schema.description = brand.description;
|
|
1073
|
+
}
|
|
1074
|
+
if (brand.logo) {
|
|
1075
|
+
schema.logo = resolveHref(brand.logo);
|
|
1076
|
+
}
|
|
1077
|
+
return schema;
|
|
1078
|
+
}
|
|
1079
|
+
function resolveStructuredData(page, types, brand) {
|
|
1080
|
+
const structuredDataCollections = {
|
|
1081
|
+
...DefaultStructuredDataCollections,
|
|
1082
|
+
...types
|
|
1083
|
+
};
|
|
1015
1084
|
let pageType = page.schema || "";
|
|
1016
1085
|
if (page.template) {
|
|
1017
1086
|
pageType = asEquatableString(page.template);
|
|
1018
1087
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
}
|
|
1088
|
+
const schema = Object.entries(structuredDataCollections).reduce((p, kv) => {
|
|
1089
|
+
if (p) {
|
|
1090
|
+
return p;
|
|
1091
|
+
}
|
|
1092
|
+
switch (kv[0]) {
|
|
1093
|
+
case "product":
|
|
1094
|
+
return kv[1].includes(pageType) ? resolveStructuredDataProduct(page, brand) : null;
|
|
1095
|
+
case "article":
|
|
1096
|
+
return kv[1].includes(pageType) ? resolveStructuredDataArticle(page, brand) : null;
|
|
1097
|
+
case "contact":
|
|
1098
|
+
return kv[1].includes(pageType) ? resolveStructuredDataOrganization(page, brand) : null;
|
|
1099
|
+
default:
|
|
1100
|
+
return resolveStructuredDataBrand(page, brand);
|
|
1101
|
+
}
|
|
1102
|
+
}, null);
|
|
1035
1103
|
if (schema) {
|
|
1036
1104
|
return JSON.stringify(schema);
|
|
1037
1105
|
}
|
|
@@ -1097,6 +1165,10 @@ export {
|
|
|
1097
1165
|
resolveMediaSrc,
|
|
1098
1166
|
resolveRoute,
|
|
1099
1167
|
resolveStructuredData,
|
|
1168
|
+
resolveStructuredDataArticle,
|
|
1169
|
+
resolveStructuredDataBrand,
|
|
1170
|
+
resolveStructuredDataOrganization,
|
|
1171
|
+
resolveStructuredDataProduct,
|
|
1100
1172
|
resolveTemplate,
|
|
1101
1173
|
routeInterceptor,
|
|
1102
1174
|
routeRevalidateHandler,
|
package/package.json
CHANGED
package/src/page/page.service.ts
CHANGED
|
@@ -157,21 +157,28 @@ export async function getPageCategory<T extends ICategorized>(schema: string, pa
|
|
|
157
157
|
|
|
158
158
|
export async function getErrorPageLayout(): Promise<{ layout: ILayout, page: IPage }> {
|
|
159
159
|
const layout = await getLayout(defaultMarket, defaultLocale);
|
|
160
|
-
// console.log('getErrorPageLayout', layout);
|
|
160
|
+
// console.log('getErrorPageLayout', 'layout', layout);
|
|
161
161
|
const title = resolveLabel(layout.labels, 'notfound.title');
|
|
162
|
-
// console.log('title', title);
|
|
162
|
+
// console.log('getErrorPageLayout', 'title', title);
|
|
163
163
|
const abstract = resolveLabel(layout.labels, 'notfound.abstract');
|
|
164
|
-
// console.log('abstract', abstract);
|
|
164
|
+
// console.log('getErrorPageLayout', 'abstract', abstract);
|
|
165
|
+
const category = layout.tree ? {
|
|
166
|
+
id: layout.tree.category,
|
|
167
|
+
title: layout.tree.title,
|
|
168
|
+
href: layout.tree.href,
|
|
169
|
+
slug: '',
|
|
170
|
+
} : {
|
|
171
|
+
id: 'homepage',
|
|
172
|
+
title: 'Homepage',
|
|
173
|
+
slug: '',
|
|
174
|
+
href: '/',
|
|
175
|
+
};
|
|
176
|
+
// console.log('getErrorPageLayout', 'category', category);
|
|
165
177
|
const page: IPage = {
|
|
166
178
|
abstract,
|
|
167
179
|
alternates: [],
|
|
168
180
|
breadcrumb: [],
|
|
169
|
-
category
|
|
170
|
-
id: 'homepage',
|
|
171
|
-
title: 'homepage',
|
|
172
|
-
slug: '',
|
|
173
|
-
href: '',
|
|
174
|
-
},
|
|
181
|
+
category,
|
|
175
182
|
slug: '',
|
|
176
183
|
href: '',
|
|
177
184
|
id: 'notfound',
|
|
@@ -187,7 +194,7 @@ export async function getErrorPageLayout(): Promise<{ layout: ILayout, page: IPa
|
|
|
187
194
|
schema: 'notfound' as SchemaType,
|
|
188
195
|
title,
|
|
189
196
|
};
|
|
190
|
-
// console.log('page', page);
|
|
197
|
+
// console.log('getErrorPageLayout', 'page', page);
|
|
191
198
|
return { layout, page };
|
|
192
199
|
}
|
|
193
200
|
|
|
@@ -46,7 +46,7 @@ function getSiteMapXMLLastMod(canonical: IRouteCanonical): string {
|
|
|
46
46
|
function getSiteMapXMLImage(canonical: IRouteCanonical): string {
|
|
47
47
|
return canonical.media ? `
|
|
48
48
|
<image:image>
|
|
49
|
-
<image:loc>${canonical.media.src}</image:loc>
|
|
49
|
+
<image:loc>${canonical.media.src || canonical.media.url}</image:loc>
|
|
50
50
|
</image:image>` : '';
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -31,12 +31,15 @@ export type StructuredDataAddress = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export type StructuredDataPlace = {
|
|
34
|
+
'@context'?: 'https://schema.org';
|
|
34
35
|
'@type': 'Place';
|
|
35
36
|
name: string;
|
|
36
37
|
address: StructuredDataAddress;
|
|
38
|
+
url: string;
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
export type StructuredDataOrganization = {
|
|
42
|
+
'@context'?: 'https://schema.org';
|
|
40
43
|
'@type': 'Organization';
|
|
41
44
|
address?: StructuredDataAddress;
|
|
42
45
|
alumni?: StructuredDataPerson[];
|
|
@@ -45,17 +48,29 @@ export type StructuredDataOrganization = {
|
|
|
45
48
|
member?: StructuredDataOrganization[];
|
|
46
49
|
name: string;
|
|
47
50
|
telephone?: string;
|
|
51
|
+
brand?: StructuredDataBrand;
|
|
48
52
|
url?: string;
|
|
49
53
|
};
|
|
50
54
|
|
|
55
|
+
export type StructuredDataProduct = {
|
|
56
|
+
'@context'?: 'https://schema.org';
|
|
57
|
+
'@type': 'Product';
|
|
58
|
+
name: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
image?: string;
|
|
61
|
+
brand: StructuredDataBrand;
|
|
62
|
+
url: string;
|
|
63
|
+
};
|
|
64
|
+
|
|
51
65
|
export type StructuredDataArticle = {
|
|
52
|
-
'@context'
|
|
66
|
+
'@context'?: 'https://schema.org';
|
|
53
67
|
'@type': 'Article' | 'BlogPosting' | 'NewsArticle';
|
|
54
68
|
author: (StructuredDataPerson | StructuredDataOrganization)[];
|
|
55
69
|
dateModified: Date | string;
|
|
56
70
|
datePublished: Date | string;
|
|
57
71
|
headline: string;
|
|
58
72
|
image: string[];
|
|
73
|
+
url: string;
|
|
59
74
|
};
|
|
60
75
|
|
|
61
76
|
export type StructuredDataEvent = {
|
|
@@ -74,13 +89,33 @@ export type StructuredDataEvent = {
|
|
|
74
89
|
offers?: StructuredDataOffer,
|
|
75
90
|
performer?: StructuredDataPerformingGroup,
|
|
76
91
|
organizer?: StructuredDataOrganization;
|
|
92
|
+
url: string;
|
|
77
93
|
};
|
|
78
94
|
|
|
79
|
-
export type
|
|
95
|
+
export type StructuredDataBrand = {
|
|
96
|
+
'@context'?: 'https://schema.org';
|
|
97
|
+
'@type': 'Brand';
|
|
98
|
+
name: string;
|
|
99
|
+
description?: string;
|
|
100
|
+
logo?: string;
|
|
101
|
+
url: string;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type IBrand = {
|
|
105
|
+
name: string;
|
|
106
|
+
description?: string;
|
|
107
|
+
logo?: string;
|
|
108
|
+
url?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export type StructuredDataKeys = 'product' | 'article' | 'contact' | 'brand';
|
|
80
112
|
export type StructuredDataCollections = Record<StructuredDataKeys, string[]>;
|
|
81
113
|
|
|
82
114
|
const DefaultStructuredDataCollections: StructuredDataCollections = {
|
|
115
|
+
product: ['product_detail'],
|
|
83
116
|
article: ['news_detail'],
|
|
117
|
+
contact: ['contact'],
|
|
118
|
+
brand: ['homepage'],
|
|
84
119
|
};
|
|
85
120
|
|
|
86
121
|
export function resolveTemplate(value: any): string | undefined {
|
|
@@ -91,32 +126,107 @@ export function resolveMediaSrc(media: IMedia): string | undefined {
|
|
|
91
126
|
return resolveHref(media.src || media.url);
|
|
92
127
|
}
|
|
93
128
|
|
|
129
|
+
export function resolveStructuredDataProduct(
|
|
130
|
+
page: IPage,
|
|
131
|
+
brand?: IBrand
|
|
132
|
+
): StructuredDataProduct {
|
|
133
|
+
const mediaSrc = page.media ? resolveMediaSrc(page.media) : undefined;
|
|
134
|
+
const schema: StructuredDataProduct = {
|
|
135
|
+
'@context': 'https://schema.org',
|
|
136
|
+
'@type': 'Product',
|
|
137
|
+
name: page.title,
|
|
138
|
+
image: mediaSrc || '',
|
|
139
|
+
brand: resolveStructuredDataBrand(page, brand),
|
|
140
|
+
url: resolveHref(page.href),
|
|
141
|
+
};
|
|
142
|
+
return schema;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function resolveStructuredDataArticle(
|
|
146
|
+
page: IPage,
|
|
147
|
+
brand?: IBrand
|
|
148
|
+
): StructuredDataArticle {
|
|
149
|
+
const mediaSrc = page.media ? resolveMediaSrc(page.media) : undefined;
|
|
150
|
+
const schema: StructuredDataArticle = {
|
|
151
|
+
'@context': 'https://schema.org',
|
|
152
|
+
'@type': 'Article',
|
|
153
|
+
headline: page.title,
|
|
154
|
+
image: mediaSrc ? [mediaSrc] : [],
|
|
155
|
+
datePublished: page.createdAt,
|
|
156
|
+
dateModified: page.updatedAt,
|
|
157
|
+
author: [
|
|
158
|
+
resolveStructuredDataOrganization(page, brand),
|
|
159
|
+
],
|
|
160
|
+
url: resolveHref(page.href),
|
|
161
|
+
} as StructuredDataArticle;
|
|
162
|
+
return schema;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function resolveStructuredDataOrganization(
|
|
166
|
+
page: IPage,
|
|
167
|
+
brand: IBrand = {
|
|
168
|
+
name: 'WebsiteName',
|
|
169
|
+
}
|
|
170
|
+
): StructuredDataOrganization {
|
|
171
|
+
const schema: StructuredDataOrganization = {
|
|
172
|
+
'@context': 'https://schema.org',
|
|
173
|
+
'@type': 'Organization',
|
|
174
|
+
name: brand.name,
|
|
175
|
+
brand: resolveStructuredDataBrand(page, brand),
|
|
176
|
+
url: resolveHref(page.href),
|
|
177
|
+
};
|
|
178
|
+
return schema;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function resolveStructuredDataBrand(
|
|
182
|
+
page: IPage,
|
|
183
|
+
brand: IBrand = {
|
|
184
|
+
name: 'WebsiteName',
|
|
185
|
+
}
|
|
186
|
+
): StructuredDataBrand {
|
|
187
|
+
const schema: StructuredDataBrand = {
|
|
188
|
+
'@context': 'https://schema.org',
|
|
189
|
+
'@type': 'Brand',
|
|
190
|
+
name: brand.name,
|
|
191
|
+
url: brand.url || getPublicUrl(),
|
|
192
|
+
};
|
|
193
|
+
if (brand.description) {
|
|
194
|
+
schema.description = brand.description;
|
|
195
|
+
}
|
|
196
|
+
if (brand.logo) {
|
|
197
|
+
schema.logo = resolveHref(brand.logo);
|
|
198
|
+
}
|
|
199
|
+
return schema;
|
|
200
|
+
}
|
|
201
|
+
|
|
94
202
|
export function resolveStructuredData(
|
|
95
203
|
page: IPage,
|
|
96
|
-
|
|
97
|
-
|
|
204
|
+
types?: Partial<StructuredDataCollections>,
|
|
205
|
+
brand?: IBrand
|
|
98
206
|
): string | undefined {
|
|
99
|
-
|
|
207
|
+
const structuredDataCollections: StructuredDataCollections = {
|
|
208
|
+
...DefaultStructuredDataCollections,
|
|
209
|
+
...types,
|
|
210
|
+
};
|
|
100
211
|
let pageType = page.schema || '';
|
|
101
212
|
if (page.template) {
|
|
102
213
|
pageType = asEquatableString(page.template);
|
|
103
214
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
215
|
+
const schema = Object.entries(structuredDataCollections).reduce<null | {}>((p, kv) => {
|
|
216
|
+
if (p) {
|
|
217
|
+
return p;
|
|
218
|
+
}
|
|
219
|
+
switch (kv[0]) {
|
|
220
|
+
case 'product':
|
|
221
|
+
return kv[1].includes(pageType) ? resolveStructuredDataProduct(page, brand) : null;
|
|
222
|
+
case 'article':
|
|
223
|
+
return kv[1].includes(pageType) ? resolveStructuredDataArticle(page, brand) : null;
|
|
224
|
+
case 'contact':
|
|
225
|
+
return kv[1].includes(pageType) ? resolveStructuredDataOrganization(page, brand) : null;
|
|
226
|
+
default:
|
|
227
|
+
return resolveStructuredDataBrand(page, brand);
|
|
228
|
+
}
|
|
229
|
+
}, null);
|
|
120
230
|
if (schema) {
|
|
121
231
|
return JSON.stringify(schema);
|
|
122
232
|
}
|