@speedkit/cli 4.3.0 → 4.4.1

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 CHANGED
@@ -1,3 +1,20 @@
1
+ ## [4.4.1](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v4.4.0...v4.4.1) (2026-05-13)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **sk-config:** mock methods ([d479dcf](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/d479dcff73b0251ced9c160623b92831cc39648e))
7
+
8
+ # [4.4.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v4.3.0...v4.4.0) (2026-05-13)
9
+
10
+
11
+ ### Features
12
+
13
+ * **wizard:** ssr defaults ([a4443c1](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/a4443c10d33088deda104d352d548399c5a17748))
14
+ * **wizard:** ssr defaults ([e6b8a4d](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/e6b8a4d28cec310e381f25b7da217789ffa4c8f0))
15
+ * **wizard:** templates ([2ee8f80](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/2ee8f80e94b16c00a125886ab4642498fb9c06a9))
16
+ * **wizard:** templates ([8a322e7](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/8a322e70d899827ae43d6bfc2125cb15bbc6150a))
17
+
1
18
  # [4.3.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v4.2.1...v4.3.0) (2026-05-12)
2
19
 
3
20
 
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @speedkit/cli
21
21
  $ sk COMMAND
22
22
  running command...
23
23
  $ sk (--version)
24
- @speedkit/cli/4.3.0 linux-x64 node-v22.22.2
24
+ @speedkit/cli/4.4.1 linux-x64 node-v22.22.2
25
25
  $ sk --help [COMMAND]
26
26
  USAGE
27
27
  $ sk COMMAND
@@ -56,10 +56,18 @@ function buildBrowserMock(origin, app) {
56
56
  serviceWorkerUrl: "",
57
57
  screen: { width: 0, height: 0 },
58
58
  devicePixelRatio: 1,
59
- setTimeout: (callBack, time) => setTimeout(callBack, time),
60
- clearTimeout: () => clearTimeout,
61
- addEventListener: () => addEventListener,
62
- removeEventListener: () => removeEventListener,
59
+ setTimeout: () => {
60
+ /* empty */
61
+ },
62
+ clearTimeout: () => {
63
+ /* empty */
64
+ },
65
+ addEventListener: () => {
66
+ /* empty */
67
+ },
68
+ removeEventListener: () => {
69
+ /* empty */
70
+ },
63
71
  navigator: {
64
72
  userAgent: "",
65
73
  connection: {},
@@ -99,19 +99,14 @@ import { ShopifyPlugin } from "speed-kit-config/ShopifyPlugin";
99
99
  {{#if addDeviceDetection}}
100
100
  {{#unless addSSR}}
101
101
  userAgentDetection: true,
102
- {{/unless}}
103
102
  detectDevice: function(doc) {
104
- {{#if addSSR}}
105
- // SSR specific – identify device based on screen width:
106
- // TODO: adjust devices + breakpoints to your needs
107
- var width = window?.screen?.width || 1024;
108
- if (width < 768) return "mobile";
109
- return "desktop";
110
- {{else}}
111
103
  // TODO: adjust condition to your needs
112
104
  return doc.querySelector('<mobile-specific-element>') ? "mobile" : "desktop";
113
- {{/if}}
114
105
  },
106
+ {{/unless}}
107
+ {{#if addSSR}}
108
+ customDevice: customDevice(),
109
+ {{/if}}
115
110
  {{/if}}
116
111
  {{#if addSSR}}
117
112
  customVariation: [
@@ -440,6 +435,29 @@ import { ShopifyPlugin } from "speed-kit-config/ShopifyPlugin";
440
435
  // Utility Functions
441
436
  //================================================================================
442
437
 
438
+ {{#if addSSR}}
439
+ function customDevice() {
440
+ var width = window.innerWidth || 1025;
441
+ // TODO: adjust devices + breakpoints to your needs
442
+ if (width <= 820) {
443
+ return "mobile";
444
+ }
445
+ return "desktop";
446
+ }
447
+
448
+ // Re-evaluate device on orientation change and push to service worker
449
+ window.addEventListener("orientationchange", function () {
450
+ if (typeof SpeedKit !== "undefined" && SpeedKit.updateDevice) {
451
+ SpeedKit.updateDevice(customDevice());
452
+ }
453
+ });
454
+ window.addEventListener("resize", function () {
455
+ if (typeof SpeedKit !== "undefined" && SpeedKit.updateDevice) {
456
+ SpeedKit.updateDevice(customDevice());
457
+ }
458
+ });
459
+ {{/if}}
460
+
443
461
  function getEnabledHosts(enabledHostsConfigs) {
444
462
  var allHosts = [];
445
463
  enabledHostsConfigs.forEach(function (enabledHostsConfig) {
@@ -87,44 +87,16 @@ const config = {
87
87
  {{/if}}
88
88
  },
89
89
  async preTransform({db, document, variation, url, headers}) {
90
- {{#if addSSR}}
91
- // SSR specific:
92
- generateMainShadowRoot(document);
93
- {{else}}
94
- // do nothing
95
- {{/if}}
90
+ // do nothing
96
91
  },
97
92
  async postTransform({db, document, variation, url, headers}) {
98
93
  {{#if includeServiceWorker}}
99
94
  injectServiceWorkerScript(document, '{{includeServiceWorker}}');
100
95
 
101
96
  {{/if}}
102
- {{#if addSSR}}
103
- // SSR specific:
104
- if (!isPreRendered(document)) return;
105
- createPreloadsForInnerStyleLinks(document);
106
- removeInnerScriptNodes(document);
107
- assignDynamicStylesToShadowDom(document);
108
- addDeclarativeShadowDOMPolyfill(document);
109
- wrapPreRenderedElementsWithCustomRootTags(document);
110
- addPolyFillAfterMainPreRenderTemplate(document);
111
- triggerShadowRendering(document);
112
- {{#if isShopify}}
113
- // Shopify specific: inject scripts into sk-html which set css variables (normally set to html element)
114
- injectCSSVariableScripts(document);
115
- {{/if}}
116
- {{#if addSSRInnerShadowDomSupport}}
117
-
118
- overrideCustomElementDefine(document);
119
- walkPreRenderedElements(document);
120
- {{/if}}
121
- {{else}}
122
- {{#if isShopify}}
123
- // Shopify specific: inject script which sets css variables on the html element
124
- injectCSSVariableScripts(document);
125
- {{else}}
126
- // do nothing
127
- {{/if}}
97
+ {{#if isShopify}}
98
+ // Shopify specific: inject scripts which set css variables{{#if addSSR}} (normally set on the html element, but in SSR mode they have to be set on sk-html inside the shadow DOM){{/if}}
99
+ injectCSSVariableScripts(document);
128
100
  {{/if}}
129
101
  },
130
102
  {{#if isPlentymarkets}}
@@ -159,6 +131,17 @@ const config = {
159
131
 
160
132
  // SSR specific:
161
133
  preRender: {
134
+ // Wraps pre-rendered content in a shadow DOM and runs the standard SSR
135
+ // setup (style preloads, dynamic styles, declarative shadow DOM polyfill,
136
+ // sk-html/sk-body wrapping, render trigger). Pre-rendered fragments are
137
+ // appended to `sk-shadow-app-root > template` by default.
138
+ defaultShadowRoot: true,
139
+ {{#if addSSRInnerShadowDomSupport}}
140
+ // Overrides `customElements.define` so the static SSR DOM is upgraded
141
+ // without invoking custom element constructors (required when the
142
+ // customer ships its own shadow DOMs / web components).
143
+ innerShadowDOMSupport: true,
144
+ {{/if}}
162
145
  elements: [
163
146
  // append all extracted styles to all pre-rendered elements (as they are capsuled in shadow doms)
164
147
  // TODO check if all necessary styles are extracted by this rule
@@ -169,11 +152,10 @@ const config = {
169
152
  "body > style:not([media='print'])",
170
153
  "body > link[rel='stylesheet'][href]:not([media='print'])",
171
154
  ].join(","),
172
- appendTo: "sk-shadow-app-root > template",
173
155
  },
174
156
  // this will be the main element to extract from the rendered DOM
175
157
  // TODO change selector to the main element of your page
176
- { selector: "body > #app", appendTo: "sk-shadow-app-root > template" },
158
+ { selector: "body > #app" },
177
159
  ],
178
160
  guards: [
179
161
  {
@@ -259,420 +241,52 @@ export const post = async (db, req, res) => {
259
241
  document.querySelector("head").appendChild(swScript);
260
242
  }
261
243
  {{/if}}
262
- {{#if addSSR}}
263
-
264
- /**
265
- * Generates the main shadow root for the given DOM.
266
- * This is the parent element of the extracted pre-rendered content.
267
- *
268
- * @param document
269
- */
270
- function generateMainShadowRoot(document) {
271
- const customContainer = document.createElement("sk-shadow-app-root");
272
- customContainer.setAttribute("aria-hidden", "true"); // hide from screen readers
244
+ {{#if addSSRInnerShadowDomSupport}}
273
245
 
274
- const template = document.createElement("template");
275
- template.setAttribute("shadowrootmode", "open");
276
- customContainer.appendChild(template);
277
-
278
- document.querySelector("body").prepend(customContainer);
279
- }
280
-
281
- /**
282
- * Checks if the document is pre-rendered.
283
- *
284
- * @param document
285
- */
286
- function isPreRendered(document) {
287
- return !!document.querySelector("html.speed-kit-pre-rendered");
288
- }
246
+ //================================================================================
247
+ // Puppeteer Callback
248
+ //================================================================================
289
249
 
290
250
  /**
291
- * Creates preloads for inner style links in the given document.
251
+ * Waits for the callback when custom elements are defined on the document.
292
252
  *
293
- * @param {Document} document - The document object to search for inner style links.
294
- * @return {void}
253
+ * @return {Promise} - A promise that resolves when all custom elements are defined, or if a timeout of 5 seconds occurs.
295
254
  */
296
- function createPreloadsForInnerStyleLinks(document) {
297
- const customShadowRoots = getCustomShadowElements(document);
298
- for (const customShadowRoot of customShadowRoots) {
299
- const innerStyleLinks = customShadowRoot.querySelectorAll('link[rel="stylesheet"][href]');
300
-
301
- const head = document.querySelector("head");
302
- innerStyleLinks.forEach((styleLink) => {
303
- const link = document.createElement("link");
304
- link.setAttribute("rel", "preload");
305
- link.setAttribute("as", "stylesheet");
306
- link.setAttribute("href", styleLink.getAttribute("href"));
307
- head.append(link);
308
- });
309
-
310
- // preload fonts by moving font declarations from nested css to the head, as they are not supported in shadow doms
311
- customShadowRoot.querySelectorAll(".speed-kit-font-face-preloads").forEach((fontFaceRules) => {
312
- head.append(fontFaceRules);
255
+ async function waitForCallback() {
256
+ const undefinedElements = document.querySelectorAll(":not(:defined)");
257
+ // need to be defined here as they are sent to the lambda function
258
+ const customElementNames = [
259
+ // TODO add correct custom element names (find them by executing document.querySelectorAll(":not(:defined)"))
260
+ ];
261
+
262
+ const promises = [...undefinedElements]
263
+ .filter((element) => customElementNames.some((name) => element.localName.includes(name)))
264
+ .map((element) => {
265
+ // eslint-disable-next-line no-undef
266
+ return customElements.whenDefined(element.localName);
313
267
  });
314
- }
315
- }
316
-
317
- /**
318
- * Removes all inner script nodes from the given document.
319
- *
320
- * @param {Document} document - The document object from which to remove script nodes.
321
- */
322
- function removeInnerScriptNodes(document) {
323
- // remove all innerShadowDom script, as they would be executed again
324
- const customShadowRoots = getCustomShadowElements(document);
325
- for (const customShadowRoot of customShadowRoots) {
326
- Array.from(customShadowRoot.querySelectorAll("script")).forEach((scriptNode) => scriptNode.remove());
327
- }
328
- }
329
268
 
330
- /**
331
- * Assigns dynamic styles to the Shadow DOM of specified document.
332
- *
333
- * @param {Document} document - The document object to which styles are to be assigned.
334
- * @throws {Abort} Throws an error if `skStyles` is not found.
335
- */
336
- function assignDynamicStylesToShadowDom(document) {
337
- const skStyles = document.querySelector("#speed-kit-df-styles");
338
-
339
- if (!skStyles) {
340
- throw new Abort("#speed-kit-df-styles not found");
341
- }
342
- const clonedStyles = document.createElement("style");
343
- for (const attr of skStyles.attributes) {
344
- clonedStyles.setAttribute(attr.name, attr.value);
345
- }
346
- clonedStyles.textContent = skStyles.textContent;
347
-
348
- const customShadowElements = getCustomShadowElements(document);
349
- customShadowElements.forEach((shadowElement) => {
350
- shadowElement.prepend(clonedStyles);
351
- });
352
- }
353
-
354
- /**
355
- * Helper function to select all template elements.
356
- *
357
- * @param document
358
- * @returns {*}
359
- */
360
- function getCustomShadowElements(document) {
361
- return document.querySelectorAll("sk-shadow-app-root > template");
269
+ return await Promise.race([
270
+ Promise.all(promises),
271
+ new Promise((resolve) => {
272
+ setTimeout(resolve, 5000);
273
+ }),
274
+ ]);
362
275
  }
363
-
364
- /**
365
- * Adds the declarative shadow dom polyfill to the head of the document.
366
- *
367
- * @param document
368
- */
369
- function addDeclarativeShadowDOMPolyfill(document) {
370
- const head = document.querySelector("head");
371
- if (head) {
372
- const script = document.createElement("script");
373
- script.textContent = SKShadowRootsPolyfill.toString();
374
- head.append(script);
375
- }
376
- }
377
-
378
- /**
379
- * Polyfills the creation of Shadow Roots for browsers that do not support Shadow DOM.
380
- * If the browser supports Shadow DOM, this method does nothing.
381
- * https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#polyfill
382
- *
383
- * @param {HTMLTemplateElement} template - The template element to be transformed into a Shadow Root.
384
- * @constructor
385
- */
386
- function SKShadowRootsPolyfill(template) {
387
- // If the browser supports Shadow DOM, do nothing, as template is already transformed to a shadowRoot.
388
- if (!template) {
389
- return;
390
- }
391
- const mode = template.getAttribute("shadowrootmode");
392
- const shadowRoot = template.parentNode.attachShadow({ mode });
393
- shadowRoot.appendChild(template.content);
394
- template.remove();
395
- shadowRoot
396
- .querySelectorAll("template[shadowrootmode]")
397
- .forEach((template) => {
398
- SKShadowRootsPolyfill(template);
399
- });
400
- }
401
-
402
- /**
403
- * Wraps pre-rendered elements with custom sk-html and sk-body tags.
404
- *
405
- * @param document
406
- */
407
- function wrapPreRenderedElementsWithCustomRootTags(document) {
408
- const customShadowRoots = getCustomShadowElements(document);
409
-
410
- function createCustomElement(tagName, sourceSelector) {
411
- const el = document.createElement(tagName);
412
- const source = document.querySelector(sourceSelector);
413
- if (source) {
414
- for (const attr of source.attributes) {
415
- el.setAttribute(attr.name, attr.value);
416
- }
417
- }
418
- return el;
419
- }
420
-
421
- for (const customShadowRoot of customShadowRoots) {
422
- const skHtml = createCustomElement("sk-html", "html");
423
- const skBody = createCustomElement("sk-body", "body");
424
-
425
- // move all children from the shadow root element into sk-body
426
- while (customShadowRoot.firstChild) {
427
- // remove class which is no longer needed
428
- customShadowRoot.firstChild.classList.remove("speed-kit-pre-rendered-block-added");
429
-
430
- // move element to sk-body
431
- skBody.appendChild(customShadowRoot.firstChild);
432
- }
433
-
434
- // append sk-body inside sk-html
435
- skHtml.appendChild(skBody);
436
-
437
- // append sk-html into the shadow root element
438
- customShadowRoot.appendChild(skHtml);
439
- }
440
- }
441
-
442
- /**
443
- * Calls the polyfill for shadowRoots after the main pre-rendered template.
444
- *
445
- * @param document
446
- */
447
- function addPolyFillAfterMainPreRenderTemplate(document) {
448
- const customShadowRoots = getCustomShadowElements(document);
449
- for (const customShadowRoot of customShadowRoots) {
450
- let topLevelPreRenderElements = customShadowRoot.querySelectorAll("sk-body > *");
451
- topLevelPreRenderElements.forEach((element) => {
452
- let topTemplate = element.querySelector('template[shadowrootmode="open"]');
453
- if (!topTemplate) {
454
- return;
455
- }
456
-
457
- // polyfill for shadowRoots
458
- let polyfillScript = document.createElement("script");
459
- polyfillScript.textContent = `SKShadowRootsPolyfill(document?.currentScript?.previousElementSibling)`;
460
- topTemplate.after(polyfillScript);
461
- });
462
- }
463
- }
464
-
465
- /**
466
- * Forces rendering of elements within custom shadow DOMs by briefly toggling
467
- * their visibility via injected style rules.
468
- *
469
- * @param document
470
- */
471
- function triggerShadowRendering(document) {
472
- const customShadowRoots = getCustomShadowElements(document);
473
- for (const customShadowRoot of customShadowRoots) {
474
- const hidingStyle = document.createElement("style");
475
- hidingStyle.textContent = `sk-html{visibility:hidden;}`;
476
- customShadowRoot.prepend(hidingStyle);
477
-
478
- const visibilityStyle = document.createElement("style");
479
- visibilityStyle.textContent = `sk-html{visibility:visible;}`;
480
- customShadowRoot.appendChild(visibilityStyle);
481
- }
482
- }
483
- {{#if addSSRInnerShadowDomSupport}}
484
-
485
- //================================================================================
486
- // Puppeteer Callback
487
- //================================================================================
488
-
489
- /**
490
- * Waits for the callback when custom elements are defined on the document.
491
- *
492
- * @return {Promise} - A promise that resolves when all custom elements are defined, or if a timeout of 5 seconds occurs.
493
- */
494
- async function waitForCallback() {
495
- const undefinedElements = document.querySelectorAll(":not(:defined)");
496
- // need to be defined here as they are sent to the lambda function
497
- const customElementNames = [
498
- // TODO add correct custom element names (find them by executing document.querySelectorAll(":not(:defined)"))
499
- ];
500
-
501
- const promises = [...undefinedElements]
502
- .filter((element) => customElementNames.some((name) => element.localName.includes(name)))
503
- .map((element) => {
504
- // eslint-disable-next-line no-undef
505
- return customElements.whenDefined(element.localName);
506
- });
507
-
508
- return await Promise.race([
509
- Promise.all(promises),
510
- new Promise((resolve) => {
511
- setTimeout(resolve, 5000);
512
- }),
513
- ]);
514
- }
515
-
516
- //================================================================================
517
- // INLINE SCRIPTS
518
- //================================================================================
519
-
520
- /**
521
- * Overrides the window.customElements.define method to add custom code before calling the original function.
522
- */
523
- function overrideDefine() {
524
- /* global HTMLElement, window, customElements */
525
-
526
- // Store the original function
527
- // eslint-disable-next-line no-undef
528
- let originalDefine = window.customElements.define;
529
-
530
- // Create new function
531
- // eslint-disable-next-line no-undef
532
- window.customElements.define = function (e, o, options) {
533
- if (options?.is && options?.is.length > 0) {
534
- // eslint-disable-next-line no-undef
535
- return originalDefine.call(window.customElements, e, o, options);
536
- }
537
-
538
- const lifeCycleCallbacks = [
539
- "connectedCallback",
540
- "disconnectedCallback",
541
- "adoptedCallback",
542
- "connectedMoveCallback",
543
- "attributeChangedCallback",
544
- "formAssociatedCallback",
545
- "formResetCallback",
546
- "formDisabledCallback",
547
- "formStateRestoreCallback",
548
- ];
549
-
550
- let preventInit = false;
551
- let skProxy = function () {
552
- // This constructor is invoked for every custom element.
553
- // However, we can return a new instance in this constructor which is then used for upgrading the element.
554
- // We are using the Reflect.construct method to prevent invoking the original constructor
555
- // initialization code if we are in the static rendered DOM tree of Speed Kit
556
- let instance;
557
- if (preventInit) {
558
- instance = Reflect.construct(HTMLElement, arguments, skProxy);
559
- instance.__skStatic = preventInit;
560
- } else {
561
- instance = Reflect.construct(o, arguments, skProxy);
562
- }
563
-
564
- return instance;
565
- };
566
-
567
- // create a dynamic proxy class which is overwriting all lifecycle hooks of the original class
568
- skProxy.prototype = Object.create(o.prototype, {
569
- constructor: {
570
- value: skProxy,
571
- writable: true,
572
- configurable: true,
573
- },
574
- ...Object.fromEntries(
575
- lifeCycleCallbacks
576
- .map((callbackName) => [callbackName, o.prototype[callbackName]])
577
- .filter(([, hasCallback]) => hasCallback)
578
- .map(([callbackName, callback]) => {
579
- return [
580
- callbackName,
581
- {
582
- value: function () {
583
- if (!this.__skStatic) {
584
- return callback.apply(this, arguments);
585
- }
586
- },
587
- writable: true,
588
- configurable: true,
589
- },
590
- ];
591
- }),
592
- ),
593
- });
594
-
595
- Object.setPrototypeOf(skProxy, o);
596
-
597
- const skContainer = document.querySelector("sk-shadow-app-root");
598
- let skContainerParentNode;
599
- let skContainerNextNode;
600
- if (skContainer) {
601
- skContainerParentNode = skContainer.parentNode;
602
- skContainerNextNode = skContainer.nextSibling;
603
- skContainer.remove();
604
- }
605
-
606
- // Control the upgrade of the sk static dom tree by temporary removing the tree while
607
- // defining the new custom element. Do then a controlled upgrade of the sk dom tree by
608
- // preventing the constructor invocation of the custom element class
609
- originalDefine.call(window.customElements, e, skProxy, options);
610
- if (skContainer) {
611
- preventInit = true;
612
- skContainerParentNode.insertBefore(skContainer, skContainerNextNode);
613
- customElements.upgrade(skContainer);
614
- preventInit = false;
615
- }
616
- };
617
- }
618
-
619
- /**
620
- * Overrides the custom element definition in the given document.
621
- *
622
- * @param {Document} document - The document object where the custom element is defined.
623
- *
624
- * @return {void} - This method does not return anything.
625
- */
626
- function overrideCustomElementDefine(document) {
627
- const script = document.createElement("script");
628
- script.setAttribute("type", "text/javascript");
629
- script.classList.add("sk-shadowroot-extension");
630
- script.textContent = `(${overrideDefine.toString()})()`;
631
- document.querySelector("head").appendChild(script);
632
- }
633
-
634
- /**
635
- * Walks through pre-rendered elements and performs specific actions on each element.
636
- *
637
- * @param {Document} document - The HTML document object.
638
- */
639
- function walkPreRenderedElements(document) {
640
- const customShadowElements = getCustomShadowElements(document);
641
- walkElements(customShadowElements, (element) => {
642
- // TODO extend if shadow-doms should be modified, as access to the shadow dom is not possible via querySelectors from the outside
643
- });
644
- }
645
-
646
- /**
647
- * Recursively walks through a tree of elements and applies a callback function to each element.
648
- *
649
- * @param {Array} elements - The array of elements to walk through. Each element should be an object with a 'children' property.
650
- * @param {Function} callback - The callback function to apply to each element. It should take a single argument, which will be the current element.
651
- *
652
- * @return {undefined}
653
- */
654
- function walkElements(elements, callback) {
655
- elements.forEach((element) => {
656
- callback(element);
657
- if (element.children && element.children.length > 0) {
658
- walkElements(element.children, callback);
659
- }
660
- });
661
- }
662
- {{/if}}
663
276
  {{/if}}
664
277
  {{#if isShopify}}
665
278
 
666
279
  /**
667
- * Injects scripts into sk-html within each shadow root that set CSS custom
280
+ * Injects scripts {{#if addSSR}}into sk-html within each shadow root that set CSS custom
668
281
  * properties (e.g. --window-height, --announcement-bar-height, --header-height)
669
- * on sk-html instead of the document's html element.
282
+ * on sk-html instead of the document's html element.{{else}}that set CSS custom properties
283
+ * (e.g. --window-height, --announcement-bar-height, --header-height) on the html element.{{/if}}
670
284
  *
671
285
  * @param document
672
286
  */
673
287
  function injectCSSVariableScripts(document) {
674
288
  {{#if addSSR}}
675
- const customShadowRoots = getCustomShadowElements(document);
289
+ const customShadowRoots = document.querySelectorAll("sk-shadow-app-root > template");
676
290
  for (const customShadowRoot of customShadowRoots) {
677
291
  const skHtml = customShadowRoot.querySelector("sk-html");
678
292
  if (!skHtml) continue;
@@ -180,6 +180,18 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
180
180
  },
181
181
  {{/if}}
182
182
  {{/if}}
183
+ {{#if addSSR}}
184
+ {
185
+ on: "nextTick",
186
+ track: function (controller) {
187
+ controller.trackCustomEvent(
188
+ "viewportSize",
189
+ JSON.stringify({ innerWidth: window.innerWidth, innerHeight: window.innerHeight }),
190
+ 0,
191
+ );
192
+ },
193
+ },
194
+ {{/if}}
183
195
  {{#if useGATracking}}
184
196
 
185
197
  // TODO: remove or adapt if events are not properly covered by GAEcommerceTrackingPlugin
@@ -237,7 +249,7 @@ import { PredictivePreloading } from 'predictive-preloading/predictivePreloading
237
249
  // },
238
250
  // },
239
251
  {{else}}
240
-
252
+
241
253
  {{#if isShopify}}
242
254
  // No custom ecAddToCart tracking event needed as it is already handled by the speed-kit-config/ShopifyPlugin
243
255
  // No custom ecConversion tracking event as it is already handled by the Speed Kit Extension for Shopify
@@ -751,5 +751,5 @@
751
751
  ]
752
752
  }
753
753
  },
754
- "version": "4.3.0"
754
+ "version": "4.4.1"
755
755
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "4.3.0",
4
+ "version": "4.4.1",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"