@speedkit/cli 3.9.1 → 3.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.
@@ -4,20 +4,21 @@
4
4
  */
5
5
  window.dynamicBlockConfig = {
6
6
  dynamicScriptExecution: true,
7
- {{#if addPreRendering}}
8
- // ssr container
9
- prerendered: [{ selector: "body > .speed-kit-shadow-app-root" }],
10
- {{/if}}
11
- {{#if addUADetection}}
12
- detectDevice: (doc) => {
13
- // TODO adjust condition to your needs
14
- return doc.querySelector('<mobile-specific-element>') ? "mobile" : "desktop";
15
- },
7
+ {{#if addDeviceDetection}}
8
+ {{#unless addSSR}}
9
+ detectDevice: (doc) => {
10
+ // keep only if you need to check the DOM – for screen width checks the SK config's detectDevice is sufficient
11
+
12
+ // TODO: adjust condition to your needs
13
+ return doc.querySelector('<mobile-specific-element>') ? "mobile" : "desktop";
14
+ },
15
+ {{/unless}}
16
16
  {{/if}}
17
17
  blocks: [
18
18
  // TODO: adjust/replace this exemplary list
19
19
  {
20
20
  selector: "body",
21
+ {{#unless addSSR}}
21
22
  detectChanges: [
22
23
  // Main Headline:
23
24
  {
@@ -56,12 +57,14 @@
56
57
  compare: ["src"],
57
58
  },
58
59
  ],
60
+ {{/unless}}
59
61
  },
60
62
  {{#if isShopify}}
63
+
61
64
  // Shopify specific:
62
65
  {
63
66
  selector: "#shopify-section-announcement-bar",
64
- {{#unless addPreRendering}}
67
+ {{#unless addSSR}}
65
68
  merge: false, // TODO: remove if body is not the main block
66
69
  {{/unless}}
67
70
  detectChanges: [{
@@ -110,31 +113,55 @@
110
113
  { selector: 'meta[property]', idAttribute: "property"},
111
114
  { selector: 'script[type="application/ld+json"]'},
112
115
  ],
113
- {{#if addPreRendering}}
116
+ {{#if addSSR}}
117
+
118
+ // SSR specific:
119
+ prerendered: [{ selector: "body > sk-shadow-app-root" }],
114
120
  preRenderedRootConfig: [
115
121
  // TODO: adjust/replace this exemplary list
116
122
  {
117
- selector: ".prerendered-top-level-element",
118
- detectChanges: [
119
- {
120
- // header area
121
- find: "#page-root > div > .aem-container > div:nth-of-type(1)",
122
- detectChanges: [
123
- // main categories
124
- {
125
- find: 'button[id^="menu-button"] p',
126
- compare: ["text"],
127
- },
128
- // logo
129
- {
130
- find: "img[src]",
131
- compare: ["src"],
132
- },
133
- ],
134
- },
123
+ selector: "sk-body",
124
+ remoteSelector: "body",
125
+ detectChanges: [
126
+ // Main Headline:
127
+ {
128
+ find: "h1",
129
+ compare: ["text"],
130
+ },
131
+
132
+ // Top Banner:
133
+ {
134
+ find: ".header .top-banner",
135
+ compare: ["text"],
136
+ },
137
+
138
+ // First-Level Items of Header/Main Navigation:
139
+ {
140
+ find: ".header .main-navigation .first-level-item",
141
+ compare: ["text"],
142
+ },
143
+
144
+ // Stage Teaser:
145
+ {
146
+ find: ".stage-teaser source",
147
+ compare: ["srcset"],
148
+ },
149
+
150
+ // PLP Items:
151
+ {
152
+ find: ".product-grid .product img",
153
+ limit: 9, // only compare the first 9 products
154
+ compare: ["src"],
155
+ },
156
+
157
+ // PDP Hero Image:
158
+ {
159
+ find: ".product-detail .slide.main img",
160
+ compare: ["src"],
161
+ },
135
162
  ],
136
163
  },
137
- ],
138
- {{/if}}
164
+ ],
165
+ {{/if}}
139
166
  };
140
167
  })();
@@ -24,20 +24,36 @@
24
24
  background-position: calc(100% + 400px) 0;
25
25
  }
26
26
  }
27
+ {{#if addSSR}}
28
+
29
+ /* SSR specific – positioning for pre-rendered container */
30
+ .speed-kit-pre-rendered sk-shadow-app-root {
31
+ position: absolute;
32
+ top: 0;
33
+ width: 100%;
34
+ left: 0;
35
+ right: 0;
36
+ z-index: 99999;
37
+ background: #fff;
38
+ }
39
+
40
+ /*
41
+ SSR specific:
42
+ remember to use sk-html/sk-body as additional selectors if you reference html/body to also cover the SSR case
43
+ */
44
+ {{/if}}
27
45
  {{#if withGoogleOptimize}}
28
46
 
29
47
  /* Google Optimize Flicker Fix: */
48
+ {{#if addSSR}}
49
+ sk-html > sk-body,
50
+ {{/if}}
30
51
  html > body {
31
52
  opacity: 1 !important;
32
53
  }
33
54
  {{/if}}
34
55
 
35
56
  .speed-kit-dynamic-loading {
36
- {{#if addPreRendering}}
37
- /* TODO: use the following wrapping selector if you want to apply those styles to the pre-rendered block instead: */
38
- /* .speed-kit-pre-rendered-block-added */
39
- {{/if}}
40
-
41
57
  .dummy-price-class,
42
58
  .dummy-availability-class {
43
59
  visibility: hidden;
@@ -75,7 +91,6 @@ html > body {
75
91
  }
76
92
  }
77
93
 
78
-
79
94
  /* Prevent Add2Cart clicks: */
80
95
  .dummy-add2cart-class {
81
96
  pointer-events: none !important;
@@ -111,16 +126,3 @@ html > body {
111
126
  mask-repeat: no-repeat;
112
127
  }
113
128
  }
114
- {{#if addPreRendering}}
115
-
116
- /* Positioning for pre-rendered containers */
117
- html.speed-kit-pre-rendered body > .speed-kit-shadow-app-root {
118
- position: absolute;
119
- top: 0;
120
- width: 100%;
121
- left: 0;
122
- right: 0;
123
- z-index: 99999;
124
- background: #fff;
125
- }
126
- {{/if}}
@@ -1,6 +1,6 @@
1
1
  import { BaseBundle } from 'rum/BaseBundle';
2
2
  {{#if hasSoftNavigations}}
3
- import { HistoryApiPlugin } from 'rum/HistoryApiPlugin';
3
+ import { SpaBundle } from 'rum/SpaBundle';
4
4
  {{/if}}
5
5
  {{#if useGATracking}}
6
6
  import { GAEcommerceTrackingPlugin } from 'rum/GAEcommerceTrackingPlugin';
@@ -16,12 +16,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
16
16
  if (window !== window.top) {
17
17
  return;
18
18
  }
19
- {{#if hasSoftNavigations}}
20
-
21
- // Soft Navigation Handling:
22
- var softLcpPending = false;
23
- var latestUrl = location.href;
24
- {{/if}}
25
19
  {{#if isOxid}}
26
20
 
27
21
  var pageTypeSent = false;
@@ -52,7 +46,7 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
52
46
  }
53
47
  {{/if}}),
54
48
  {{#if hasSoftNavigations}}
55
- new HistoryApiPlugin(), // Soft Navigation Tracking using History API
49
+ new SpaBundle(), // Soft Navigation Tracking using History API
56
50
  {{/if}}
57
51
  {{#if useGATracking}}
58
52
  new GAEcommerceTrackingPlugin({
@@ -67,9 +61,27 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
67
61
  new UserFrictionPlugin(),
68
62
  new ClickPlugin(),
69
63
  {{/if}}
64
+ {{#if isShopify}}
65
+ {
66
+ key: "loggedIn",
67
+ type: "PiDimension",
68
+ on: "window.ShopifyAnalytics",
69
+ set: function () {
70
+ return !!window.ShopifyAnalytics?.meta?.page?.customerId;
71
+ },
72
+ },
73
+ {
74
+ key: "pageType",
75
+ type: "PiDimension",
76
+ on: "window.ShopifyAnalytics",
77
+ set: function () {
78
+ return window.ShopifyAnalytics?.meta?.page?.pageType;
79
+ },
80
+ },
81
+ {{else}}
70
82
  {
71
83
  key: 'loggedIn',
72
- type: 'SessionDimension',
84
+ type: 'PiDimension',
73
85
  {{#if useGATracking}}
74
86
  on: 'dataLayer',
75
87
  set: function(pushedEvent) {
@@ -85,24 +97,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
85
97
  {
86
98
  key: 'pageType',
87
99
  type: 'PiDimension',
88
- {{#if isShopify}}
89
- on: 'window.ShopifyAnalytics',
90
- set: function() {
91
- var pathname = window.location.pathname;
92
- // TODO: verify pathname patterns
93
- if (pathname.indexOf('/checkouts/') > -1) {
94
- return 'checkout';
95
- } if (pathname.indexOf('/account/login') > -1) {
96
- return 'login';
97
- } if (pathname.indexOf('/account/register') > -1) {
98
- return 'register';
99
- } if (pathname.indexOf('/account') > -1) {
100
- return 'account';
101
- } else {
102
- return window.ShopifyAnalytics?.meta?.page?.pageType;
103
- }
104
- },
105
- {{else}}
106
100
  {{#if useGATracking}}
107
101
  on: 'dataLayer',
108
102
  set: function (pushedEvent) {
@@ -131,7 +125,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
131
125
  {{/if}}
132
126
  },
133
127
  {{/if}}
134
- {{/if}}
135
128
  },
136
129
  {{#if isOxid}}
137
130
  // OXID eShop specific fallback tracking for page type using URL:
@@ -160,6 +153,7 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
160
153
  },
161
154
  },
162
155
  {{/if}}
156
+ {{/if}}
163
157
  {{#if useGATracking}}
164
158
 
165
159
  // TODO: remove or adapt if events are not properly covered by GAEcommerceTrackingPlugin
@@ -218,36 +212,25 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
218
212
  // },
219
213
  {{else}}
220
214
  {{#if isShopify}}
221
-
222
- // {
223
- // key: 'ecAddToCart',
224
- // on: onAddToCartClick,
225
- // append: function () {
226
- // if (window.ShopifyAnalytics?.lib) {
227
- // var shopifyData = window.ShopifyAnalytics.lib;
228
- // var product;
229
- //
230
- // if (shopifyData && shopifyData.length) {
231
- // shopifyData.forEach(item => {
232
- // if (item[1] === "Viewed Product Variant") {
233
- // if(item.length > 2){
234
- // product = item[2];
235
- // }
236
- // }
237
- // });
238
- //
239
- // if (product) {
240
- // return {
241
- // id: product.productId + '_' + product.variantId, // optional – remove if no id is available
242
- // price: Number(product.price),
243
- // currencyCode: product.currency || defaultCurrency,
244
- // quantity: 1,
245
- // }
246
- // }
247
- // }
248
- // }
249
- // },
250
- // },
215
+ {
216
+ key: "ecAddToCart",
217
+ // TODO depending on the used theme different events are in use variant:added, product-ajax:added, product:added
218
+ // TODO the correct event can easily spotted by search for the initiator of the /cart/add request after doing a addToCart
219
+ on: (callback) => document.addEventListener("product-ajax:added", callback),
220
+ append: function (event) {
221
+ // TODO depending on the used event the product is exposed under a different property
222
+ var product = event.detail.product;
223
+
224
+ if (product) {
225
+ return {
226
+ id: product.product_id,
227
+ price: (product.discounted_price ?? product.price) / 100, // price is in cents
228
+ currencyCode: window.Shopify?.currency?.active || defaultCurrency,
229
+ quantity: product.quantity,
230
+ };
231
+ }
232
+ },
233
+ },
251
234
 
252
235
  // No custom ecConversion tracking event as it is already handled by the Speed Kit Extension for Shopify
253
236
  {{else}}
@@ -286,106 +269,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
286
269
  },
287
270
  {{/if}}
288
271
  {{/if}}
289
- {{#if hasSoftNavigations}}
290
- {
291
- on: "softNavigation",
292
- track: (controller) => {
293
- var onlyHashChanged =
294
- latestUrl.split("#")[0] === location.href.split("#")[0];
295
- latestUrl = location.href;
296
-
297
- if (onlyHashChanged) {
298
- controller.trackCustomEvent("hashChanged", location.href, Date.now());
299
- return;
300
- }
301
-
302
- controller.trackCustomEvent("softNav", location.href, Date.now());
303
-
304
- // Only capture soft LCP on following pages/page types:
305
- // TODO: update to match the resp. page types to capture
306
- var isProduct = location.href.indexOf("/p/") !== -1;
307
- var isCategory = location.href.indexOf("/c/") !== -1;
308
-
309
- if (!isCategory && !isProduct) return;
310
-
311
- var navStartMark = "soft-nav_" + location.pathname;
312
- performance.mark(navStartMark);
313
-
314
- softLcpPending = true;
315
-
316
- var softNavigationPerformanceObserver = new PerformanceObserver(
317
- (entries, observer) => {
318
- // TODO: update exemplary selectors within this block
319
-
320
- // Wait for product image resources to be loaded:
321
- var imageEntries = Array.from(entries.getEntries()).filter(
322
- (item) => item.name.indexOf("/product/image/") !== -1,
323
- );
324
-
325
- // Ensure product images can be found in requested resources list:
326
- if (!imageEntries || imageEntries.length < 1) {
327
- return;
328
- }
329
-
330
- // Wait for product hero image / first product image in list to be referenced in DOM:
331
- var imageElementSelector = isProduct
332
- ? ".product-details .slick-slide.slick-active img" // PDP hero image
333
- : ".product-list .product-image img"; // PLP list image(s)
334
-
335
- var imageElement = document.querySelector(imageElementSelector);
336
-
337
- // Ensure image element can be found in document:
338
- if (!imageElement) {
339
- return;
340
- }
341
- var imageUrl = imageElement.currentSrc || imageElement.srcset || "";
342
-
343
- var imageMatchingRequestedResource = imageEntries.filter(
344
- (entry) => {
345
- var urlObj = new URL(entry.name);
346
- return imageUrl.indexOf(urlObj.pathname) > -1;
347
- },
348
- )[0];
349
-
350
- // Ensure the resp. image source referenced in the document can be found in requested resources list:
351
- if (!imageMatchingRequestedResource) {
352
- return;
353
- }
354
-
355
- // Ensure Soft LCP is still pending:
356
- if (!softLcpPending) {
357
- return;
358
- }
359
-
360
- var measure = performance.measure("lcp_" + location.pathname, {
361
- start: navStartMark,
362
- end: imageMatchingRequestedResource.responseEnd,
363
- });
364
-
365
- var timing = {
366
- start: measure.startTime,
367
- duration: measure.duration,
368
- image: imageMatchingRequestedResource.name,
369
- url: window.location.href,
370
- };
371
- controller.trackCustomEvent(
372
- "softNavLcp",
373
- JSON.stringify(timing),
374
- Date.now(),
375
- );
376
-
377
- softNavigationPerformanceObserver.disconnect();
378
- softLcpPending = false;
379
- },
380
- );
381
-
382
- softNavigationPerformanceObserver.observe({
383
- buffered: true,
384
- type: "resource",
385
- });
386
- },
387
- },
388
- {{/if}}
389
272
  {{#if isPlentymarkets}}
390
273
  {
391
274
  on: "domInteractive",
@@ -396,20 +279,6 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
396
279
  },
397
280
  {{/if}}
398
281
  );
399
- {{#if isShopify}}
400
- // Shopify specific:
401
-
402
- // function onAddToCartClick(cb, controller) {
403
- // controller.onDOMInteractive(function() {
404
- // var addToCartBtn = document.querySelector('.button--add-to-cart');
405
- // if(addToCartBtn) {
406
- // addToCartBtn.addEventListener('click', function (t) {
407
- // cb(controller);
408
- // }, true);
409
- // }
410
- // })
411
- // }
412
- {{/if}}
413
282
  {{#if isPlentymarkets}}
414
283
 
415
284
  /* ==== */
@@ -4,7 +4,7 @@ exports.ExecutableValidator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  // import CLI from puppeteer to use function as sames as `npx puppeteer browsers install`
6
6
  const browsers_1 = require("@puppeteer/browsers");
7
- const version_js_1 = require("puppeteer-core/internal/generated/version.js");
7
+ const version_js_1 = require("puppeteer-core/lib/cjs/puppeteer/util/version.js");
8
8
  const node_fs_1 = require("node:fs");
9
9
  const application_error_1 = tslib_1.__importDefault(require("../../../error-handling/error/application-error"));
10
10
  const browsers_2 = require("@puppeteer/browsers");
@@ -732,5 +732,5 @@
732
732
  ]
733
733
  }
734
734
  },
735
- "version": "3.9.1"
735
+ "version": "3.11.0"
736
736
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "3.9.1",
4
+ "version": "3.11.0",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"
@@ -95,7 +95,7 @@
95
95
  "nypm": "^0.6.2",
96
96
  "parse5": "7.1",
97
97
  "parse5-htmlparser2-tree-adapter": "7.0.0",
98
- "puppeteer": "^24.16.0",
98
+ "puppeteer": "^24.25.0",
99
99
  "puppeteer-extra": "^3.3.6",
100
100
  "semver": "^7.6.3",
101
101
  "strip-comments": "^2.0.1",