@treely/strapi-slices 7.9.0 → 7.11.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.
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ import { Article, BlogPosting, Brand, BreadcrumbList, Event, FAQPage, HowTo, LocalBusiness, Offer, Organization, Person, Product, Service, WebPage, WithContext } from 'schema-dts';
3
+ type SupportedSchemaType = Article | BlogPosting | Brand | BreadcrumbList | Event | FAQPage | HowTo | LocalBusiness | Offer | Organization | Person | Product | Service | WebPage;
2
4
  interface SEOTagsProps {
3
5
  title: string;
4
6
  description: string;
@@ -9,6 +11,14 @@ interface SEOTagsProps {
9
11
  metaTitleSuffix?: string;
10
12
  favicon?: string;
11
13
  domain?: string;
14
+ /**
15
+ * Structured data for SEO purposes, following the schema.org standard.
16
+ * This can be a single schema object or an array of schema objects.
17
+ * Each object must include an `@context` property set to "https://schema.org"
18
+ * and an `@type` property indicating the type of schema (e.g., Article, Product).
19
+ * The schema falls back to the default schema if it is invalid.
20
+ */
21
+ schemaMarkup?: WithContext<SupportedSchemaType> | WithContext<SupportedSchemaType>[];
12
22
  }
13
23
  export declare const SEOTags: React.FC<SEOTagsProps>;
14
24
  export {};
@@ -903,6 +903,86 @@ var PreviewAlert = function PreviewAlert() {
903
903
  }));
904
904
  };
905
905
 
906
+ // Helper function to convert SchemaValue to string
907
+ var getTextValue = function getTextValue(value) {
908
+ if (typeof value === 'string') return value;
909
+ if (typeof value === 'object' && value !== null && 'text' in value) {
910
+ return value.text;
911
+ }
912
+ return '';
913
+ };
914
+ // Helper function to safely access properties from a schema
915
+ var getSchemaProperty = function getSchemaProperty(schema, property) {
916
+ return getTextValue(schema[property]) || '';
917
+ };
918
+ // Helper function to get a unique identifier from a schema
919
+ var getSchemaIdentifier = function getSchemaIdentifier(schema) {
920
+ var _offer$price;
921
+ var type = schema['@type'];
922
+ switch (type) {
923
+ case 'Organization':
924
+ return getSchemaProperty(schema, 'name') || 'default';
925
+ case 'Article':
926
+ case 'BlogPosting':
927
+ return getSchemaProperty(schema, 'headline') || 'untitled-article';
928
+ case 'Product':
929
+ return getSchemaProperty(schema, 'name') || 'untitled-product';
930
+ case 'Person':
931
+ return getSchemaProperty(schema, 'name') || 'unnamed-person';
932
+ case 'Event':
933
+ return getSchemaProperty(schema, 'name') || 'untitled-event';
934
+ case 'LocalBusiness':
935
+ return getSchemaProperty(schema, 'name') || 'unnamed-business';
936
+ case 'Service':
937
+ return getSchemaProperty(schema, 'name') || 'unnamed-service';
938
+ case 'Brand':
939
+ return getSchemaProperty(schema, 'name') || 'unnamed-brand';
940
+ case 'FAQPage':
941
+ return 'faq-page';
942
+ case 'HowTo':
943
+ return getSchemaProperty(schema, 'name') || 'untitled-howto';
944
+ case 'BreadcrumbList':
945
+ return 'breadcrumbs';
946
+ case 'Offer':
947
+ var offer = schema;
948
+ return "offer-" + ((_offer$price = offer.price) != null ? _offer$price : 'unknown-price');
949
+ case 'WebPage':
950
+ return getSchemaProperty(schema, 'name') || 'untitled-page';
951
+ default:
952
+ return 'unknown-schema';
953
+ }
954
+ };
955
+ var validateSchema = function validateSchema(schema) {
956
+ if (Array.isArray(schema)) {
957
+ return schema.every(function (item) {
958
+ return item['@context'] === 'https://schema.org' && '@type' in item;
959
+ });
960
+ }
961
+ return schema['@context'] === 'https://schema.org' && '@type' in schema;
962
+ };
963
+ var DEFAULT_SCHEMA = {
964
+ '@context': 'https://schema.org',
965
+ '@type': 'Organization',
966
+ name: 'Tree.ly',
967
+ url: 'https://tree.ly',
968
+ logo: 'https://cdn.tree.ly/logo.png',
969
+ address: {
970
+ '@type': 'PostalAddress',
971
+ streetAddress: 'Littengasse 2b/c',
972
+ addressLocality: 'Dornbirn',
973
+ postalCode: '6850',
974
+ addressRegion: 'Vorarlberg',
975
+ addressCountry: 'AT'
976
+ },
977
+ contactPoint: {
978
+ '@type': 'ContactPoint',
979
+ telephone: '+43-5572-432015',
980
+ contactType: 'Customer Service',
981
+ areaServed: 'AT',
982
+ availableLanguage: ['English', 'German']
983
+ },
984
+ sameAs: ['https://www.linkedin.com/company/tree-ly', 'https://www.facebook.com/treely', 'https://www.instagram.com/treely']
985
+ };
906
986
  var SEOTags = function SEOTags(_ref) {
907
987
  var _shareImage$url, _shareImage$alt;
908
988
  var title = _ref.title,
@@ -913,9 +993,24 @@ var SEOTags = function SEOTags(_ref) {
913
993
  _ref$favicon = _ref.favicon,
914
994
  favicon = _ref$favicon === void 0 ? 'https://cdn.tree.ly/favicon.ico' : _ref$favicon,
915
995
  _ref$domain = _ref.domain,
916
- domain = _ref$domain === void 0 ? 'tree.ly' : _ref$domain;
996
+ domain = _ref$domain === void 0 ? 'tree.ly' : _ref$domain,
997
+ schemaMarkup = _ref.schemaMarkup;
917
998
  var shareImageUrl = (_shareImage$url = shareImage == null ? void 0 : shareImage.url) != null ? _shareImage$url : DEFAULT_SHARE_IMAGE;
918
999
  var shareImageAlt = (_shareImage$alt = shareImage == null ? void 0 : shareImage.alt) != null ? _shareImage$alt : DEFAULT_SHARE_ALT;
1000
+ var schemas = schemaMarkup || DEFAULT_SCHEMA;
1001
+ var isValidSchema = validateSchema(schemas);
1002
+ if (schemaMarkup && !isValidSchema) {
1003
+ console.warn('Invalid schema markup provided to SEOTags component. Falling back to default schema.', schemaMarkup);
1004
+ schemas = DEFAULT_SCHEMA;
1005
+ isValidSchema = true;
1006
+ }
1007
+ var schemaArray = Array.isArray(schemas) ? schemas : [schemas];
1008
+ var getSchemaKey = function getSchemaKey(schema, index) {
1009
+ var type = schema['@type'];
1010
+ var identifier = getSchemaIdentifier(schema);
1011
+ // Add index to ensure uniqueness, especially for fallback identifiers
1012
+ return type + "-" + identifier + "-" + index;
1013
+ };
919
1014
  return React__default.default.createElement(Head__default.default, null, React__default.default.createElement("title", null, title + " - " + metaTitleSuffix), React__default.default.createElement("meta", {
920
1015
  name: "description",
921
1016
  content: description
@@ -961,6 +1056,14 @@ var SEOTags = function SEOTags(_ref) {
961
1056
  }), React__default.default.createElement("meta", {
962
1057
  name: "twitter:image:alt",
963
1058
  content: shareImageAlt
1059
+ }), isValidSchema && schemaArray.map(function (schema, index) {
1060
+ return React__default.default.createElement("script", {
1061
+ key: getSchemaKey(schema, index),
1062
+ type: "application/ld+json",
1063
+ dangerouslySetInnerHTML: {
1064
+ __html: JSON.stringify(schema)
1065
+ }
1066
+ });
964
1067
  }));
965
1068
  };
966
1069
 
@@ -3681,7 +3784,7 @@ var ProjectsMap = function ProjectsMap(_ref) {
3681
3784
  client.createRoot(ref.current).render(React__default.default.createElement(MinimalProviders, {
3682
3785
  locale: locale
3683
3786
  }, React__default.default.createElement(MapMarker, {
3684
- title: project.title,
3787
+ title: project.friendlyName || project.title,
3685
3788
  isPublic: project.isPublic,
3686
3789
  portfolioHost: project.portfolioHost,
3687
3790
  slug: project.slug,