@react-pakistan/util-functions 1.25.11 → 1.25.13

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.
Files changed (73) hide show
  1. package/constants/cache-time.d.ts +2 -0
  2. package/constants/cache-time.js +3 -1
  3. package/general/generate-article-schema.d.ts +49 -0
  4. package/general/generate-article-schema.js +100 -0
  5. package/general/generate-blog-schema.d.ts +7 -5
  6. package/general/generate-blog-schema.js +7 -5
  7. package/general/generate-book-schema.d.ts +57 -0
  8. package/general/generate-book-schema.js +109 -0
  9. package/general/generate-breadcrumb-schema.d.ts +22 -6
  10. package/general/generate-breadcrumb-schema.js +15 -4
  11. package/general/generate-carousel-schema.d.ts +51 -0
  12. package/general/generate-carousel-schema.js +172 -0
  13. package/general/generate-course-schema.d.ts +52 -0
  14. package/general/generate-course-schema.js +124 -0
  15. package/general/generate-dataset-schema.d.ts +64 -0
  16. package/general/generate-dataset-schema.js +156 -0
  17. package/general/generate-discussion-forum-schema.d.ts +38 -0
  18. package/general/generate-discussion-forum-schema.js +67 -0
  19. package/general/generate-education-schema.d.ts +67 -0
  20. package/general/generate-education-schema.js +137 -0
  21. package/general/generate-employer-aggregate-rating-schema.d.ts +28 -0
  22. package/general/generate-employer-aggregate-rating-schema.js +64 -0
  23. package/general/generate-event-schema.d.ts +62 -0
  24. package/general/generate-event-schema.js +214 -0
  25. package/general/generate-faq-schema.d.ts +15 -11
  26. package/general/generate-faq-schema.js +18 -6
  27. package/general/generate-image-metadata-schema.d.ts +35 -0
  28. package/general/generate-image-metadata-schema.js +73 -0
  29. package/general/generate-job-posting-schema.d.ts +48 -0
  30. package/general/generate-job-posting-schema.js +120 -0
  31. package/general/generate-local-business-schema.d.ts +41 -0
  32. package/general/generate-local-business-schema.js +75 -0
  33. package/general/generate-math-solver-schema.d.ts +44 -0
  34. package/general/generate-math-solver-schema.js +83 -0
  35. package/general/generate-movie-carousel-schema.d.ts +50 -0
  36. package/general/generate-movie-carousel-schema.js +160 -0
  37. package/general/generate-organization-schema.d.ts +9 -5
  38. package/general/generate-organization-schema.js +9 -5
  39. package/general/generate-profile-page-schema.d.ts +36 -0
  40. package/general/generate-profile-page-schema.js +82 -0
  41. package/general/generate-qa-page-schema.d.ts +33 -0
  42. package/general/generate-qa-page-schema.js +67 -0
  43. package/general/generate-recipe-schema.d.ts +48 -0
  44. package/general/generate-recipe-schema.js +104 -0
  45. package/general/generate-review-snippet-schema.d.ts +51 -0
  46. package/general/generate-review-snippet-schema.js +137 -0
  47. package/general/generate-shopping-loyalty-program-schema.d.ts +37 -0
  48. package/general/generate-shopping-loyalty-program-schema.js +59 -0
  49. package/general/generate-shopping-merchant-listing-schema.d.ts +52 -0
  50. package/general/generate-shopping-merchant-listing-schema.js +153 -0
  51. package/general/generate-shopping-merchant-return-policy-schema.d.ts +31 -0
  52. package/general/generate-shopping-merchant-return-policy-schema.js +68 -0
  53. package/general/generate-shopping-merchant-shipping-policy-schema.d.ts +35 -0
  54. package/general/generate-shopping-merchant-shipping-policy-schema.js +74 -0
  55. package/general/generate-shopping-overview-schema.d.ts +51 -0
  56. package/general/generate-shopping-overview-schema.js +157 -0
  57. package/general/generate-shopping-product-snippet-schema.d.ts +56 -0
  58. package/general/generate-shopping-product-snippet-schema.js +167 -0
  59. package/general/generate-shopping-variants-schema.d.ts +45 -0
  60. package/general/generate-shopping-variants-schema.js +143 -0
  61. package/general/generate-software-app-schema.d.ts +61 -0
  62. package/general/generate-software-app-schema.js +143 -0
  63. package/general/generate-speakable-schema.d.ts +63 -0
  64. package/general/generate-speakable-schema.js +139 -0
  65. package/general/generate-subscription-schema.d.ts +59 -0
  66. package/general/generate-subscription-schema.js +133 -0
  67. package/general/generate-vacation-rental-schema.d.ts +66 -0
  68. package/general/generate-vacation-rental-schema.js +135 -0
  69. package/general/generate-video-schema.d.ts +74 -0
  70. package/general/generate-video-schema.js +163 -0
  71. package/general/index.d.ts +30 -0
  72. package/general/index.js +30 -0
  73. package/package.json +1 -1
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * Create schema.org structured data for a single `Product` with optional
4
+ * `Review` and `Offer` entries.
5
+ *
6
+ * Supports brand and seller references, image normalization, review
7
+ * formatting and simple availability/price handling. Use
8
+ * `skipInvalidCurrency` to avoid throwing on bad currency codes.
9
+ *
10
+ * See `ProductSnippetOptions` for accepted fields.
11
+ * @returns A JSON-LD compatible `Product` object
12
+ */
13
+ var __assign = (this && this.__assign) || function () {
14
+ __assign = Object.assign || function(t) {
15
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
16
+ s = arguments[i];
17
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
18
+ t[p] = s[p];
19
+ }
20
+ return t;
21
+ };
22
+ return __assign.apply(this, arguments);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.generateShoppingProductSnippetSchema = void 0;
26
+ var formatImage = function (image) {
27
+ if (!image)
28
+ return undefined;
29
+ if (typeof image === 'string')
30
+ return image;
31
+ return __assign(__assign({ '@type': 'ImageObject', url: image.url }, (image.width && { width: image.width })), (image.height && { height: image.height }));
32
+ };
33
+ var formatBrand = function (b) {
34
+ if (!b)
35
+ return undefined;
36
+ if (typeof b === 'string')
37
+ return { '@type': 'Brand', name: b };
38
+ return __assign({ '@type': 'Brand', name: b.name }, (b.url && { url: b.url }));
39
+ };
40
+ var isValidCurrency = function (code) {
41
+ if (!code)
42
+ return false;
43
+ return /^[A-Z]{3}$/.test(code);
44
+ };
45
+ var AVAILABILITIES = [
46
+ 'InStock',
47
+ 'OutOfStock',
48
+ 'PreOrder',
49
+ 'PreSale',
50
+ 'Discontinued',
51
+ 'OnlineOnly',
52
+ 'InStoreOnly',
53
+ 'LimitedAvailability',
54
+ 'BackOrder',
55
+ ];
56
+ var normalizeAvailability = function (val) {
57
+ if (!val)
58
+ return undefined;
59
+ try {
60
+ var asUrl = String(val);
61
+ if (asUrl.startsWith('http')) {
62
+ var token = asUrl.replace(/https?:\/\/schema\.org\//i, '');
63
+ if (AVAILABILITIES.includes(token))
64
+ return "https://schema.org/".concat(token);
65
+ return undefined;
66
+ }
67
+ if (AVAILABILITIES.includes(asUrl))
68
+ return "https://schema.org/".concat(asUrl);
69
+ return undefined;
70
+ }
71
+ catch (_a) {
72
+ return undefined;
73
+ }
74
+ };
75
+ var generateShoppingProductSnippetSchema = function (_a) {
76
+ var name = _a.name, description = _a.description, image = _a.image, sku = _a.sku, brand = _a.brand, reviews = _a.reviews, offers = _a.offers, _b = _a.skipInvalidCurrency, skipInvalidCurrency = _b === void 0 ? false : _b;
77
+ var product = {
78
+ '@context': 'https://schema.org',
79
+ '@type': 'Product',
80
+ name: name,
81
+ };
82
+ if (description)
83
+ product.description = description;
84
+ var img = formatImage(image);
85
+ if (img)
86
+ product.image = img;
87
+ if (sku)
88
+ product.sku = sku;
89
+ var b = formatBrand(brand);
90
+ if (b)
91
+ product.brand = b;
92
+ // Reviews -> Review entries + aggregateRating if possible
93
+ if (reviews && reviews.length > 0) {
94
+ var mapped = reviews.map(function (r) {
95
+ var out = { '@type': 'Review' };
96
+ if (r.author) {
97
+ out.author =
98
+ typeof r.author === 'string'
99
+ ? { '@type': 'Person', name: r.author }
100
+ : { '@type': 'Person', name: r.author.name };
101
+ }
102
+ if (r.datePublished)
103
+ out.datePublished = r.datePublished;
104
+ if (r.reviewBody)
105
+ out.reviewBody = r.reviewBody;
106
+ if (r.reviewRating) {
107
+ out.reviewRating = __assign({ '@type': 'Rating', ratingValue: r.reviewRating.ratingValue }, (r.reviewRating.bestRating != null && {
108
+ bestRating: r.reviewRating.bestRating,
109
+ }));
110
+ }
111
+ return out;
112
+ });
113
+ product.review = mapped;
114
+ // compute aggregate rating if ratings present
115
+ var ratings = reviews
116
+ .map(function (r) { return (r.reviewRating ? Number(r.reviewRating.ratingValue) : NaN); })
117
+ .filter(function (n) { return !Number.isNaN(n); });
118
+ if (ratings.length > 0) {
119
+ var sum = ratings.reduce(function (a, b) { return a + b; }, 0);
120
+ product.aggregateRating = {
121
+ '@type': 'AggregateRating',
122
+ ratingValue: sum / ratings.length,
123
+ reviewCount: reviews.length,
124
+ };
125
+ }
126
+ }
127
+ // Offers
128
+ if (offers) {
129
+ var offs = Array.isArray(offers) ? offers : [offers];
130
+ var mapped = offs
131
+ .map(function (o) {
132
+ if (o.priceCurrency && !isValidCurrency(o.priceCurrency))
133
+ return { __invalidCurrency: o.priceCurrency };
134
+ var of = { '@type': 'Offer' };
135
+ if (o.price != null)
136
+ of.price = o.price;
137
+ if (o.priceCurrency)
138
+ of.priceCurrency = o.priceCurrency;
139
+ if (o.availability) {
140
+ var n = normalizeAvailability(o.availability);
141
+ if (n)
142
+ of.availability = n;
143
+ }
144
+ if (o.url)
145
+ of.url = o.url;
146
+ if (o.seller)
147
+ of.seller = __assign(__assign({ '@type': 'Organization' }, (o.seller.name && { name: o.seller.name })), (o.seller.url && { url: o.seller.url }));
148
+ if (o.priceValidUntil)
149
+ of.priceValidUntil = o.priceValidUntil;
150
+ if (o.itemCondition)
151
+ of.itemCondition = o.itemCondition;
152
+ return of;
153
+ })
154
+ .filter(function (x) { return x && !('__invalidCurrency' in x); });
155
+ var hadInvalid = offs.some(function (o) { return o.priceCurrency && !isValidCurrency(o.priceCurrency); });
156
+ if (hadInvalid && !skipInvalidCurrency) {
157
+ var bad = offs.find(function (o) { return o.priceCurrency && !isValidCurrency(o.priceCurrency); });
158
+ throw new Error("Invalid currency code: ".concat(bad === null || bad === void 0 ? void 0 : bad.priceCurrency));
159
+ }
160
+ if (mapped.length === 1)
161
+ product.offers = mapped[0];
162
+ else if (mapped.length > 1)
163
+ product.offers = mapped;
164
+ }
165
+ return product;
166
+ };
167
+ exports.generateShoppingProductSnippetSchema = generateShoppingProductSnippetSchema;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Generate schema.org `ProductGroup` (variants) and its `Product` variants
3
+ * JSON-LD.
4
+ *
5
+ * Accepts a parent group name and a list of variant `Product` entries with
6
+ * optional offers. Images and brand references are normalized into the
7
+ * appropriate schema.org objects.
8
+ *
9
+ * See `VariantsOptions` and `VariantProduct` for accepted fields.
10
+ * @returns A JSON-LD compatible `ProductGroup` object
11
+ */
12
+ interface BrandRef {
13
+ name: string;
14
+ url?: string;
15
+ }
16
+ interface OfferItem {
17
+ price?: string | number;
18
+ priceCurrency?: string;
19
+ availability?: string;
20
+ url?: string;
21
+ priceValidUntil?: string;
22
+ itemCondition?: string;
23
+ }
24
+ interface VariantProduct {
25
+ id?: string;
26
+ name: string;
27
+ sku?: string;
28
+ url?: string;
29
+ image?: string | {
30
+ url: string;
31
+ width?: number;
32
+ height?: number;
33
+ };
34
+ description?: string;
35
+ brand?: string | BrandRef;
36
+ offers?: OfferItem | OfferItem[];
37
+ }
38
+ interface VariantsOptions {
39
+ name: string;
40
+ productGroupId?: string;
41
+ variants: VariantProduct[];
42
+ skipInvalidCurrency?: boolean;
43
+ }
44
+ export declare const generateShoppingVariantsSchema: ({ name, productGroupId, variants, skipInvalidCurrency, }: VariantsOptions) => any;
45
+ export {};
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ /**
3
+ * Generate schema.org `ProductGroup` (variants) and its `Product` variants
4
+ * JSON-LD.
5
+ *
6
+ * Accepts a parent group name and a list of variant `Product` entries with
7
+ * optional offers. Images and brand references are normalized into the
8
+ * appropriate schema.org objects.
9
+ *
10
+ * See `VariantsOptions` and `VariantProduct` for accepted fields.
11
+ * @returns A JSON-LD compatible `ProductGroup` object
12
+ */
13
+ var __assign = (this && this.__assign) || function () {
14
+ __assign = Object.assign || function(t) {
15
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
16
+ s = arguments[i];
17
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
18
+ t[p] = s[p];
19
+ }
20
+ return t;
21
+ };
22
+ return __assign.apply(this, arguments);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.generateShoppingVariantsSchema = void 0;
26
+ var formatImage = function (image) {
27
+ if (!image)
28
+ return undefined;
29
+ if (typeof image === 'string')
30
+ return image;
31
+ return __assign(__assign({ '@type': 'ImageObject', url: image.url }, (image.width && { width: image.width })), (image.height && { height: image.height }));
32
+ };
33
+ var formatBrand = function (b) {
34
+ if (!b)
35
+ return undefined;
36
+ if (typeof b === 'string')
37
+ return { '@type': 'Brand', name: b };
38
+ return __assign({ '@type': 'Brand', name: b.name }, (b.url && { url: b.url }));
39
+ };
40
+ var isValidCurrency = function (code) {
41
+ if (!code)
42
+ return false;
43
+ return /^[A-Z]{3}$/.test(code);
44
+ };
45
+ var AVAILABILITIES = [
46
+ 'InStock',
47
+ 'OutOfStock',
48
+ 'PreOrder',
49
+ 'PreSale',
50
+ 'Discontinued',
51
+ 'OnlineOnly',
52
+ 'InStoreOnly',
53
+ 'LimitedAvailability',
54
+ 'BackOrder',
55
+ ];
56
+ var normalizeAvailability = function (val) {
57
+ if (!val)
58
+ return undefined;
59
+ try {
60
+ var asUrl = String(val);
61
+ if (asUrl.startsWith('http')) {
62
+ var token = asUrl.replace(/https?:\/\/schema\.org\//i, '');
63
+ if (AVAILABILITIES.includes(token))
64
+ return "https://schema.org/".concat(token);
65
+ return undefined;
66
+ }
67
+ if (AVAILABILITIES.includes(asUrl))
68
+ return "https://schema.org/".concat(asUrl);
69
+ return undefined;
70
+ }
71
+ catch (_a) {
72
+ return undefined;
73
+ }
74
+ };
75
+ var generateShoppingVariantsSchema = function (_a) {
76
+ var name = _a.name, productGroupId = _a.productGroupId, variants = _a.variants, _b = _a.skipInvalidCurrency, skipInvalidCurrency = _b === void 0 ? false : _b;
77
+ var mappedVariants = variants.map(function (v) {
78
+ var product = {
79
+ '@type': 'Product',
80
+ name: v.name,
81
+ };
82
+ if (v.id)
83
+ product['@id'] = v.id;
84
+ if (v.url)
85
+ product.url = v.url;
86
+ if (v.sku)
87
+ product.sku = v.sku;
88
+ if (v.description)
89
+ product.description = v.description;
90
+ var img = formatImage(v.image);
91
+ if (img)
92
+ product.image = img;
93
+ var b = formatBrand(v.brand);
94
+ if (b)
95
+ product.brand = b;
96
+ if (v.offers) {
97
+ var offs = Array.isArray(v.offers) ? v.offers : [v.offers];
98
+ var mapped = offs
99
+ .map(function (o) {
100
+ if (o.priceCurrency && !isValidCurrency(o.priceCurrency))
101
+ return { __invalidCurrency: o.priceCurrency };
102
+ var of = { '@type': 'Offer' };
103
+ if (o.price != null)
104
+ of.price = o.price;
105
+ if (o.priceCurrency)
106
+ of.priceCurrency = o.priceCurrency;
107
+ if (o.availability) {
108
+ var n = normalizeAvailability(o.availability);
109
+ if (n)
110
+ of.availability = n;
111
+ }
112
+ if (o.url)
113
+ of.url = o.url;
114
+ if (o.priceValidUntil)
115
+ of.priceValidUntil = o.priceValidUntil;
116
+ if (o.itemCondition)
117
+ of.itemCondition = o.itemCondition;
118
+ return of;
119
+ })
120
+ .filter(function (x) { return x && !('__invalidCurrency' in x); });
121
+ var hadInvalid = offs.some(function (o) { return o.priceCurrency && !isValidCurrency(o.priceCurrency); });
122
+ if (hadInvalid && !skipInvalidCurrency) {
123
+ var bad = offs.find(function (o) { return o.priceCurrency && !isValidCurrency(o.priceCurrency); });
124
+ throw new Error("Invalid currency code: ".concat(bad === null || bad === void 0 ? void 0 : bad.priceCurrency));
125
+ }
126
+ if (mapped.length === 1)
127
+ product.offers = mapped[0];
128
+ else if (mapped.length > 1)
129
+ product.offers = mapped;
130
+ }
131
+ return product;
132
+ });
133
+ var schema = {
134
+ '@context': 'https://schema.org',
135
+ '@type': 'ProductGroup',
136
+ name: name,
137
+ hasVariant: mappedVariants,
138
+ };
139
+ if (productGroupId)
140
+ schema['@id'] = productGroupId;
141
+ return schema;
142
+ };
143
+ exports.generateShoppingVariantsSchema = generateShoppingVariantsSchema;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Generate schema.org `SoftwareApplication` JSON-LD, optionally including
3
+ * `Review` and `AggregateRating` data.
4
+ *
5
+ * Accepts application metadata (platforms, versions, downloads), images,
6
+ * author/publisher references, reviews and an aggregate rating. Only
7
+ * provided fields are emitted in the returned object.
8
+ *
9
+ * See `SoftwareAppOptions` below for the input shape.
10
+ * @returns A JSON-LD compatible `SoftwareApplication` object
11
+ */
12
+ interface ImageRef {
13
+ url: string;
14
+ width?: number;
15
+ height?: number;
16
+ }
17
+ interface PersonRef {
18
+ name: string;
19
+ url?: string;
20
+ }
21
+ interface OrgRef {
22
+ name: string;
23
+ url?: string;
24
+ }
25
+ interface RatingItem {
26
+ ratingValue: number | string;
27
+ bestRating?: number | string;
28
+ worstRating?: number | string;
29
+ }
30
+ interface ReviewItem {
31
+ author?: string | PersonRef;
32
+ datePublished?: string;
33
+ reviewBody?: string;
34
+ reviewRating?: RatingItem;
35
+ name?: string;
36
+ url?: string;
37
+ publisher?: string | OrgRef;
38
+ }
39
+ interface AggregateRatingOptions {
40
+ ratingValue: number | string;
41
+ reviewCount?: number;
42
+ ratingCount?: number;
43
+ bestRating?: number | string;
44
+ worstRating?: number | string;
45
+ }
46
+ interface SoftwareAppOptions {
47
+ name: string;
48
+ description?: string;
49
+ image?: string | ImageRef;
50
+ url?: string;
51
+ softwareVersion?: string;
52
+ operatingSystem?: string | string[];
53
+ applicationCategory?: string | string[];
54
+ downloadUrl?: string;
55
+ author?: string | PersonRef;
56
+ publisher?: string | OrgRef;
57
+ reviews?: ReviewItem[];
58
+ aggregateRating?: AggregateRatingOptions;
59
+ }
60
+ export declare const generateSoftwareAppSchema: ({ name, description, image, url, softwareVersion, operatingSystem, applicationCategory, downloadUrl, author, publisher, reviews, aggregateRating, }: SoftwareAppOptions) => any;
61
+ export default generateSoftwareAppSchema;
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ /**
3
+ * Generate schema.org `SoftwareApplication` JSON-LD, optionally including
4
+ * `Review` and `AggregateRating` data.
5
+ *
6
+ * Accepts application metadata (platforms, versions, downloads), images,
7
+ * author/publisher references, reviews and an aggregate rating. Only
8
+ * provided fields are emitted in the returned object.
9
+ *
10
+ * See `SoftwareAppOptions` below for the input shape.
11
+ * @returns A JSON-LD compatible `SoftwareApplication` object
12
+ */
13
+ var __assign = (this && this.__assign) || function () {
14
+ __assign = Object.assign || function(t) {
15
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
16
+ s = arguments[i];
17
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
18
+ t[p] = s[p];
19
+ }
20
+ return t;
21
+ };
22
+ return __assign.apply(this, arguments);
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.generateSoftwareAppSchema = void 0;
26
+ var formatImage = function (image) {
27
+ if (!image)
28
+ return undefined;
29
+ if (typeof image === 'string')
30
+ return image;
31
+ return __assign(__assign({ '@type': 'ImageObject', url: image.url }, (image.width && { width: image.width })), (image.height && { height: image.height }));
32
+ };
33
+ var formatPerson = function (p) {
34
+ if (!p)
35
+ return undefined;
36
+ if (typeof p === 'string')
37
+ return { '@type': 'Person', name: p };
38
+ var out = { '@type': 'Person', name: p.name };
39
+ if (p.url)
40
+ out.url = p.url;
41
+ return out;
42
+ };
43
+ var formatOrganization = function (o) {
44
+ if (!o)
45
+ return undefined;
46
+ if (typeof o === 'string')
47
+ return { '@type': 'Organization', name: o };
48
+ var out = { '@type': 'Organization', name: o.name };
49
+ if (o.url)
50
+ out.url = o.url;
51
+ return out;
52
+ };
53
+ var formatReview = function (r) {
54
+ var out = { '@type': 'Review' };
55
+ if (r.author)
56
+ out.author = formatPerson(r.author);
57
+ if (r.datePublished)
58
+ out.datePublished = r.datePublished;
59
+ if (r.reviewBody)
60
+ out.reviewBody = r.reviewBody;
61
+ if (r.name)
62
+ out.name = r.name;
63
+ if (r.url)
64
+ out.url = r.url;
65
+ if (r.publisher)
66
+ out.publisher = formatOrganization(r.publisher);
67
+ if (r.reviewRating) {
68
+ out.reviewRating = __assign(__assign({ '@type': 'Rating', ratingValue: r.reviewRating.ratingValue }, (r.reviewRating.bestRating != null && {
69
+ bestRating: r.reviewRating.bestRating,
70
+ })), (r.reviewRating.worstRating != null && {
71
+ worstRating: r.reviewRating.worstRating,
72
+ }));
73
+ }
74
+ return out;
75
+ };
76
+ var generateSoftwareAppSchema = function (_a) {
77
+ var name = _a.name, description = _a.description, image = _a.image, url = _a.url, softwareVersion = _a.softwareVersion, operatingSystem = _a.operatingSystem, applicationCategory = _a.applicationCategory, downloadUrl = _a.downloadUrl, author = _a.author, publisher = _a.publisher, reviews = _a.reviews, aggregateRating = _a.aggregateRating;
78
+ var schema = {
79
+ '@context': 'https://schema.org',
80
+ '@type': 'SoftwareApplication',
81
+ name: name,
82
+ };
83
+ if (description)
84
+ schema.description = description;
85
+ var img = formatImage(image);
86
+ if (img)
87
+ schema.image = img;
88
+ if (url)
89
+ schema.url = url;
90
+ if (softwareVersion)
91
+ schema.softwareVersion = softwareVersion;
92
+ if (operatingSystem)
93
+ schema.operatingSystem = Array.isArray(operatingSystem)
94
+ ? operatingSystem.join(', ')
95
+ : operatingSystem;
96
+ if (applicationCategory)
97
+ schema.applicationCategory = Array.isArray(applicationCategory)
98
+ ? applicationCategory.join(', ')
99
+ : applicationCategory;
100
+ if (downloadUrl)
101
+ schema.downloadUrl = downloadUrl;
102
+ var a = formatPerson(author);
103
+ if (a)
104
+ schema.author = a;
105
+ var p = formatOrganization(publisher);
106
+ if (p)
107
+ schema.publisher = p;
108
+ // Reviews
109
+ if (reviews && reviews.length > 0) {
110
+ var mapped = reviews.map(formatReview);
111
+ schema.review = mapped;
112
+ // compute aggregate rating if not explicitly provided
113
+ if (!aggregateRating) {
114
+ var ratings = reviews
115
+ .map(function (r) { return (r.reviewRating ? Number(r.reviewRating.ratingValue) : NaN); })
116
+ .filter(function (n) { return !Number.isNaN(n); });
117
+ if (ratings.length > 0) {
118
+ var sum = ratings.reduce(function (a, b) { return a + b; }, 0);
119
+ schema.aggregateRating = {
120
+ '@type': 'AggregateRating',
121
+ ratingValue: sum / ratings.length,
122
+ reviewCount: reviews.length,
123
+ ratingCount: ratings.length,
124
+ };
125
+ }
126
+ }
127
+ }
128
+ // explicit aggregateRating provided
129
+ if (aggregateRating) {
130
+ schema.aggregateRating = __assign(__assign(__assign(__assign({ '@type': 'AggregateRating', ratingValue: aggregateRating.ratingValue }, (aggregateRating.reviewCount != null && {
131
+ reviewCount: aggregateRating.reviewCount,
132
+ })), (aggregateRating.ratingCount != null && {
133
+ ratingCount: aggregateRating.ratingCount,
134
+ })), (aggregateRating.bestRating != null && {
135
+ bestRating: aggregateRating.bestRating,
136
+ })), (aggregateRating.worstRating != null && {
137
+ worstRating: aggregateRating.worstRating,
138
+ }));
139
+ }
140
+ return schema;
141
+ };
142
+ exports.generateSoftwareAppSchema = generateSoftwareAppSchema;
143
+ exports.default = exports.generateSoftwareAppSchema;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Generate schema.org structured data for an `Article` or `WebPage` with a
3
+ * `SpeakableSpecification`.
4
+ *
5
+ * The `speakable` input may be an array of XPaths/CSS selectors or an
6
+ * object with `xpath`/`cssSelector` arrays. The helper will produce a
7
+ * `SpeakableSpecification` and attach it to the chosen page type.
8
+ *
9
+ * See `SpeakableOptions` for full details.
10
+ * @returns A JSON-LD compatible Article/WebPage object with `speakable`
11
+ * specification when provided.
12
+ */
13
+ type SpeakableInput = string[] | {
14
+ xpath?: string[];
15
+ cssSelector?: string[];
16
+ };
17
+ type PageType = 'Article' | 'WebPage';
18
+ interface PersonRef {
19
+ name: string;
20
+ url?: string;
21
+ }
22
+ interface PublisherRef {
23
+ name: string;
24
+ url?: string;
25
+ logo?: {
26
+ url: string;
27
+ width?: number;
28
+ height?: number;
29
+ };
30
+ }
31
+ interface RatingItem {
32
+ ratingValue: number | string;
33
+ bestRating?: number | string;
34
+ worstRating?: number | string;
35
+ }
36
+ interface ReviewItem {
37
+ author?: string | PersonRef;
38
+ datePublished?: string;
39
+ reviewBody?: string;
40
+ reviewRating?: RatingItem;
41
+ }
42
+ interface AggregateRatingOptions {
43
+ ratingValue: number | string;
44
+ reviewCount?: number;
45
+ ratingCount?: number;
46
+ bestRating?: number | string;
47
+ worstRating?: number | string;
48
+ }
49
+ interface SpeakableOptions {
50
+ type?: PageType;
51
+ headline?: string;
52
+ name?: string;
53
+ description?: string;
54
+ url?: string;
55
+ author?: string | PersonRef;
56
+ publisher?: PublisherRef;
57
+ speakable?: SpeakableInput;
58
+ reviews?: ReviewItem[];
59
+ aggregateRating?: AggregateRatingOptions;
60
+ keywords?: string[];
61
+ }
62
+ export declare const generateSpeakableSchema: ({ type, headline, name, description, url, author, publisher, speakable, reviews, aggregateRating, keywords, }: SpeakableOptions) => any;
63
+ export default generateSpeakableSchema;