10
10
* governing permissions and limitations under the License.
11
11
*/
12
12
13
+ /* eslint-disable class-methods-use-this */
14
+
13
15
import { findProductImage , pruneUndefined } from '../../utils/product.js' ;
14
16
15
17
export class JSONTemplate {
@@ -80,6 +82,58 @@ export class JSONTemplate {
80
82
} ;
81
83
}
82
84
85
+ renderOffers ( ) {
86
+ const image = this . product . images ?. [ 0 ] ?. url
87
+ ?? findProductImage ( this . product , this . variants ) ?. url ;
88
+ const configurableProduct = this . variants ?. length > 0 ;
89
+ const offers = configurableProduct ? this . variants : [ this . product ] ;
90
+ return {
91
+ offers : [
92
+ ...offers . map ( ( v ) => {
93
+ const offerUrl = this . constructProductURL ( configurableProduct ? v : undefined ) ;
94
+ const { prices : variantPrices } = v ;
95
+ const finalPrice = variantPrices ?. final ?. amount ;
96
+ const regularPrice = variantPrices ?. regular ?. amount ;
97
+ const offer = {
98
+ '@type' : 'Offer' ,
99
+ sku : v . sku ,
100
+ url : offerUrl ,
101
+ image : v . images ?. [ 0 ] ?. url ?? image ,
102
+ availability : v . inStock ? 'InStock' : 'OutOfStock' ,
103
+ price : finalPrice ,
104
+ priceCurrency : variantPrices . final ?. currency ,
105
+ } ;
106
+
107
+ if ( finalPrice < regularPrice ) {
108
+ offer . priceSpecification = this . renderOffersPriceSpecification ( v ) ;
109
+ }
110
+
111
+ if ( v . gtin ) {
112
+ offer . gtin = v . gtin ;
113
+ }
114
+
115
+ if ( v . specialToDate ) {
116
+ offer . priceValidUntil = v . specialToDate ;
117
+ }
118
+
119
+ return offer ;
120
+ } ) . filter ( Boolean ) ,
121
+ ] ,
122
+ } ;
123
+ }
124
+
125
+ renderOffersPriceSpecification ( variant ) {
126
+ const { prices } = variant ;
127
+ const { regular } = prices ;
128
+ const { amount, currency } = regular ;
129
+ return {
130
+ '@type' : 'UnitPriceSpecification' ,
131
+ priceType : 'https://schema.org/ListPrice' ,
132
+ price : amount ,
133
+ priceCurrency : currency ,
134
+ } ;
135
+ }
136
+
83
137
render ( ) {
84
138
const {
85
139
sku,
@@ -88,8 +142,6 @@ export class JSONTemplate {
88
142
images,
89
143
reviewCount,
90
144
ratingValue,
91
- inStock,
92
- prices,
93
145
} = this . product ;
94
146
95
147
const productUrl = this . constructProductURL ( ) ;
@@ -103,35 +155,7 @@ export class JSONTemplate {
103
155
description : metaDescription ,
104
156
image,
105
157
productID : sku ,
106
- offers : [
107
- prices ? ( {
108
- '@type' : 'Offer' ,
109
- sku,
110
- url : productUrl ,
111
- image,
112
- availability : inStock ? 'InStock' : 'OutOfStock' ,
113
- price : prices ?. final ?. amount ,
114
- priceCurrency : prices ?. final ?. currency ,
115
- } ) : undefined ,
116
- ...this . variants . map ( ( v ) => {
117
- const offerUrl = this . constructProductURL ( v ) ;
118
- const offer = {
119
- '@type' : 'Offer' ,
120
- sku : v . sku ,
121
- url : offerUrl ,
122
- image : v . images ?. [ 0 ] ?. url ?? image ,
123
- availability : v . inStock ? 'InStock' : 'OutOfStock' ,
124
- price : v . prices ?. final ?. amount ,
125
- priceCurrency : v . prices ?. final ?. currency ,
126
- } ;
127
-
128
- if ( v . gtin ) {
129
- offer . gtin = v . gtin ;
130
- }
131
-
132
- return offer ;
133
- } ) . filter ( Boolean ) ,
134
- ] ,
158
+ ...this . renderOffers ( ) ,
135
159
...( this . renderBrand ( ) ?? { } ) ,
136
160
...( typeof reviewCount === 'number'
137
161
&& typeof ratingValue === 'number'
0 commit comments