@lambdatest/smartui-cli 1.0.3 → 2.0.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.
@@ -0,0 +1,601 @@
1
+ (function() {
2
+ (function (exports) {
3
+ 'use strict';
4
+
5
+ // Translates JavaScript properties of inputs into DOM attributes.
6
+ function serializeInputElements(_ref) {
7
+ let {
8
+ dom,
9
+ clone,
10
+ warnings
11
+ } = _ref;
12
+ for (let elem of dom.querySelectorAll('input, textarea, select')) {
13
+ let inputId = elem.getAttribute('data-smartui-element-id');
14
+ let cloneEl = clone.querySelector(`[data-smartui-element-id="${inputId}"]`);
15
+ switch (elem.type) {
16
+ case 'checkbox':
17
+ case 'radio':
18
+ if (elem.checked) {
19
+ cloneEl.setAttribute('checked', '');
20
+ }
21
+ break;
22
+ case 'select-one':
23
+ if (elem.selectedIndex !== -1) {
24
+ cloneEl.options[elem.selectedIndex].setAttribute('selected', 'true');
25
+ }
26
+ break;
27
+ case 'select-multiple':
28
+ for (let option of elem.selectedOptions) {
29
+ cloneEl.options[option.index].setAttribute('selected', 'true');
30
+ }
31
+ break;
32
+ case 'textarea':
33
+ cloneEl.innerHTML = elem.value;
34
+ break;
35
+ default:
36
+ cloneEl.setAttribute('value', elem.value);
37
+ }
38
+ }
39
+ }
40
+
41
+ // Adds a `<base>` element to the serialized iframe's `<head>`. This is necessary when
42
+ // embedded documents are serialized and their contents become root-relative.
43
+ function setBaseURI(dom) {
44
+ /* istanbul ignore if: sanity check */
45
+ if (!new URL(dom.baseURI).hostname) return;
46
+ let $base = document.createElement('base');
47
+ $base.href = dom.baseURI;
48
+ dom.querySelector('head').prepend($base);
49
+ }
50
+
51
+ // Recursively serializes iframe documents into srcdoc attributes.
52
+ function serializeFrames(_ref) {
53
+ let {
54
+ dom,
55
+ clone,
56
+ warnings,
57
+ resources,
58
+ enableJavaScript,
59
+ disableShadowDOM
60
+ } = _ref;
61
+ for (let frame of dom.querySelectorAll('iframe')) {
62
+ var _clone$head;
63
+ let smartuiElementId = frame.getAttribute('data-smartui-element-id');
64
+ let cloneEl = clone.querySelector(`[data-smartui-element-id="${smartuiElementId}"]`);
65
+ let builtWithJs = !frame.srcdoc && (!frame.src || frame.src.split(':')[0] === 'javascript');
66
+
67
+ // delete frames within the head since they usually break pages when
68
+ // rerendered and do not effect the visuals of a page
69
+ if ((_clone$head = clone.head) !== null && _clone$head !== void 0 && _clone$head.contains(cloneEl)) {
70
+ cloneEl.remove();
71
+
72
+ // if the frame document is accessible and not empty, we can serialize it
73
+ } else if (frame.contentDocument && frame.contentDocument.documentElement) {
74
+ // js is enabled and this frame was built with js, don't serialize it
75
+ if (enableJavaScript && builtWithJs) continue;
76
+
77
+ // the frame has yet to load and wasn't built with js, it is unsafe to serialize
78
+ if (!builtWithJs && !frame.contentWindow.performance.timing.loadEventEnd) continue;
79
+
80
+ // recersively serialize contents
81
+ let serialized = serializeDOM({
82
+ domTransformation: setBaseURI,
83
+ dom: frame.contentDocument,
84
+ enableJavaScript,
85
+ disableShadowDOM
86
+ });
87
+
88
+ // append serialized warnings and resources
89
+ /* istanbul ignore next: warnings not implemented yet */
90
+ for (let w of serialized.warnings) warnings.add(w);
91
+ for (let r of serialized.resources) resources.add(r);
92
+
93
+ // assign serialized html to srcdoc and remove src
94
+ cloneEl.setAttribute('srcdoc', serialized.html);
95
+ cloneEl.removeAttribute('src');
96
+
97
+ // delete inaccessible frames built with js when js is disabled because they
98
+ // break asset discovery by creating non-captured requests that hang
99
+ } else if (!enableJavaScript && builtWithJs) {
100
+ cloneEl.remove();
101
+ }
102
+ }
103
+ }
104
+
105
+ // Creates a resource object from an element's unique ID and data URL
106
+ function resourceFromDataURL(uid, dataURL) {
107
+ // split dataURL into desired parts
108
+ let [data, content] = dataURL.split(',');
109
+ let [, mimetype] = data.split(':');
110
+ [mimetype] = mimetype.split(';');
111
+
112
+ // build a URL for the serialized asset
113
+ let [, ext] = mimetype.split('/');
114
+ let path = `/__serialized__/${uid}.${ext}`;
115
+ let url = rewriteLocalhostURL(new URL(path, document.URL).toString());
116
+
117
+ // return the url, base64 content, and mimetype
118
+ return {
119
+ url,
120
+ content,
121
+ mimetype
122
+ };
123
+ }
124
+ function resourceFromText(uid, mimetype, data) {
125
+ // build a URL for the serialized asset
126
+ let [, ext] = mimetype.split('/');
127
+ let path = `/__serialized__/${uid}.${ext}`;
128
+ let url = rewriteLocalhostURL(new URL(path, document.URL).toString());
129
+ // return the url, text content, and mimetype
130
+ return {
131
+ url,
132
+ content: data,
133
+ mimetype
134
+ };
135
+ }
136
+ function styleSheetFromNode(node) {
137
+ /* istanbul ignore if: sanity check */
138
+ if (node.sheet) return node.sheet;
139
+
140
+ // Cloned style nodes don't have a sheet instance unless they are within
141
+ // a document; we get it by temporarily adding the rules to DOM
142
+ const tempStyle = node.cloneNode();
143
+ tempStyle.setAttribute('data-smartui-style-helper', '');
144
+ tempStyle.innerHTML = node.innerHTML;
145
+ const clone = document.cloneNode();
146
+ clone.appendChild(tempStyle);
147
+ const sheet = tempStyle.sheet;
148
+ // Cleanup node
149
+ tempStyle.remove();
150
+ return sheet;
151
+ }
152
+ function rewriteLocalhostURL(url) {
153
+ return url.replace(/(http[s]{0,1}:\/\/)localhost[:\d+]*/, '$1render.smartui.local');
154
+ }
155
+
156
+ // Returns a mostly random uid.
157
+ function uid() {
158
+ return `_${Math.random().toString(36).substr(2, 9)}`;
159
+ }
160
+ function markElement(domElement, disableShadowDOM) {
161
+ var _domElement$tagName;
162
+ // Mark elements that are to be serialized later with a data attribute.
163
+ if (['input', 'textarea', 'select', 'iframe', 'canvas', 'video', 'style'].includes((_domElement$tagName = domElement.tagName) === null || _domElement$tagName === void 0 ? void 0 : _domElement$tagName.toLowerCase())) {
164
+ if (!domElement.getAttribute('data-smartui-element-id')) {
165
+ domElement.setAttribute('data-smartui-element-id', uid());
166
+ }
167
+ }
168
+
169
+ // add special marker for shadow host
170
+ if (!disableShadowDOM && domElement.shadowRoot) {
171
+ domElement.setAttribute('data-smartui-shadow-host', '');
172
+ if (!domElement.getAttribute('data-smartui-element-id')) {
173
+ domElement.setAttribute('data-smartui-element-id', uid());
174
+ }
175
+ }
176
+ }
177
+
178
+ // Returns true if a stylesheet is a CSSOM-based stylesheet.
179
+ function isCSSOM(styleSheet) {
180
+ // no href, has a rulesheet, and has an owner node
181
+ return !styleSheet.href && styleSheet.cssRules && styleSheet.ownerNode;
182
+ }
183
+
184
+ // Returns false if any stylesheet rules do not match between two stylesheets
185
+ function styleSheetsMatch(sheetA, sheetB) {
186
+ for (let i = 0; i < sheetA.cssRules.length; i++) {
187
+ var _sheetB$cssRules$i;
188
+ let ruleA = sheetA.cssRules[i].cssText;
189
+ let ruleB = (_sheetB$cssRules$i = sheetB.cssRules[i]) === null || _sheetB$cssRules$i === void 0 ? void 0 : _sheetB$cssRules$i.cssText;
190
+ if (ruleA !== ruleB) return false;
191
+ }
192
+ return true;
193
+ }
194
+ function createStyleResource(styleSheet) {
195
+ const styles = Array.from(styleSheet.cssRules).map(cssRule => cssRule.cssText).join('\n');
196
+ let resource = resourceFromText(uid(), 'text/css', styles);
197
+ return resource;
198
+ }
199
+ function serializeCSSOM(_ref) {
200
+ let {
201
+ dom,
202
+ clone,
203
+ resources,
204
+ cache,
205
+ warnings
206
+ } = _ref;
207
+ // in-memory CSSOM into their respective DOM nodes.
208
+ for (let styleSheet of dom.styleSheets) {
209
+ var _styleSheet$href;
210
+ if (isCSSOM(styleSheet)) {
211
+ let styleId = styleSheet.ownerNode.getAttribute('data-smartui-element-id');
212
+ let cloneOwnerNode = clone.querySelector(`[data-smartui-element-id="${styleId}"]`);
213
+ if (styleSheetsMatch(styleSheet, styleSheetFromNode(cloneOwnerNode))) continue;
214
+ let style = document.createElement('style');
215
+ style.type = 'text/css';
216
+ style.setAttribute('data-smartui-element-id', styleId);
217
+ style.setAttribute('data-smartui-cssom-serialized', 'true');
218
+ style.innerHTML = Array.from(styleSheet.cssRules).map(cssRule => cssRule.cssText).join('\n');
219
+ cloneOwnerNode.parentNode.insertBefore(style, cloneOwnerNode.nextSibling);
220
+ cloneOwnerNode.remove();
221
+ } else if ((_styleSheet$href = styleSheet.href) !== null && _styleSheet$href !== void 0 && _styleSheet$href.startsWith('blob:')) {
222
+ const styleLink = document.createElement('link');
223
+ styleLink.setAttribute('rel', 'stylesheet');
224
+ let resource = createStyleResource(styleSheet);
225
+ resources.add(resource);
226
+ styleLink.setAttribute('data-smartui-blob-stylesheets-serialized', 'true');
227
+ styleLink.setAttribute('data-smartui-serialized-attribute-href', resource.url);
228
+
229
+ /* istanbul ignore next: tested, but coverage is stripped */
230
+ if (clone.constructor.name === 'HTMLDocument' || clone.constructor.name === 'DocumentFragment') {
231
+ // handle document and iframe
232
+ clone.body.prepend(styleLink);
233
+ } else if (clone.constructor.name === 'ShadowRoot') {
234
+ clone.prepend(styleLink);
235
+ }
236
+ }
237
+ }
238
+
239
+ // clone Adopted Stylesheets
240
+ // Regarding ordering of the adopted stylesheets - https://github.com/WICG/construct-stylesheets/issues/93
241
+ /* istanbul ignore next: tested, but coverage is stripped */
242
+ if (dom.adoptedStyleSheets) {
243
+ for (let sheet of dom.adoptedStyleSheets) {
244
+ const styleLink = document.createElement('link');
245
+ styleLink.setAttribute('rel', 'stylesheet');
246
+ if (!cache.has(sheet)) {
247
+ let resource = createStyleResource(sheet);
248
+ resources.add(resource);
249
+ cache.set(sheet, resource.url);
250
+ }
251
+ styleLink.setAttribute('data-smartui-adopted-stylesheets-serialized', 'true');
252
+ styleLink.setAttribute('data-smartui-serialized-attribute-href', cache.get(sheet));
253
+
254
+ /* istanbul ignore next: tested, but coverage is stripped */
255
+ if (clone.constructor.name === 'HTMLDocument' || clone.constructor.name === 'DocumentFragment') {
256
+ // handle document and iframe
257
+ clone.body.prepend(styleLink);
258
+ } else if (clone.constructor.name === 'ShadowRoot') {
259
+ clone.prepend(styleLink);
260
+ }
261
+ }
262
+ } else {
263
+ warnings.add('Skipping `adoptedStyleSheets` as it is not supported.');
264
+ }
265
+ }
266
+
267
+ // Serialize in-memory canvas elements into images.
268
+ function serializeCanvas(_ref) {
269
+ let {
270
+ dom,
271
+ clone,
272
+ resources
273
+ } = _ref;
274
+ for (let canvas of dom.querySelectorAll('canvas')) {
275
+ // Note: the `.toDataURL` API requires WebGL canvas elements to use
276
+ // `preserveDrawingBuffer: true`. This is because `.toDataURL` uses the
277
+ // drawing buffer, which is cleared after each render for WebGL by default.
278
+ let dataUrl = canvas.toDataURL();
279
+
280
+ // skip empty canvases
281
+ if (!dataUrl || dataUrl === 'data:,') continue;
282
+
283
+ // get the element's smartui id and create a resource for it
284
+ let smartuiElementId = canvas.getAttribute('data-smartui-element-id');
285
+ let resource = resourceFromDataURL(smartuiElementId, dataUrl);
286
+ resources.add(resource);
287
+
288
+ // create an image element in the cloned dom
289
+ let img = document.createElement('img');
290
+ // use a data attribute to avoid making a real request
291
+ img.setAttribute('data-smartui-serialized-attribute-src', resource.url);
292
+
293
+ // copy canvas element attributes to the image element such as style, class,
294
+ // or data attributes that may be targeted by CSS
295
+ for (let {
296
+ name,
297
+ value
298
+ } of canvas.attributes) {
299
+ img.setAttribute(name, value);
300
+ }
301
+
302
+ // mark the image as serialized (can be targeted by CSS)
303
+ img.setAttribute('data-smartui-canvas-serialized', '');
304
+ // set a default max width to account for canvases that might resize with JS
305
+ img.style.maxWidth = img.style.maxWidth || '100%';
306
+
307
+ // insert the image into the cloned DOM and remove the cloned canvas element
308
+ let cloneEl = clone.querySelector(`[data-smartui-element-id=${smartuiElementId}]`);
309
+ // `parentElement` for elements directly under shadow root is `null` -> Incase of Nested Shadow DOM.
310
+ if (cloneEl.parentElement) {
311
+ cloneEl.parentElement.insertBefore(img, cloneEl);
312
+ } else {
313
+ clone.insertBefore(img, cloneEl);
314
+ }
315
+ cloneEl.remove();
316
+ }
317
+ }
318
+
319
+ // Captures the current frame of videos and sets the poster image
320
+ function serializeVideos(_ref) {
321
+ let {
322
+ dom,
323
+ clone,
324
+ resources,
325
+ warnings
326
+ } = _ref;
327
+ for (let video of dom.querySelectorAll('video')) {
328
+ // if the video already has a poster image, no work for us to do
329
+ if (video.getAttribute('poster')) continue;
330
+ let videoId = video.getAttribute('data-smartui-element-id');
331
+ let cloneEl = clone.querySelector(`[data-smartui-element-id="${videoId}"]`);
332
+ let canvas = document.createElement('canvas');
333
+ let width = canvas.width = video.videoWidth;
334
+ let height = canvas.height = video.videoHeight;
335
+ let dataUrl;
336
+ canvas.getContext('2d').drawImage(video, 0, 0, width, height);
337
+ try {
338
+ dataUrl = canvas.toDataURL();
339
+ } catch (e) {
340
+ warnings.add(`data-smartui-element-id="${videoId}" : ${e.toString()}`);
341
+ }
342
+
343
+ // if the canvas produces a blank image, skip
344
+ if (!dataUrl || dataUrl === 'data:,') continue;
345
+
346
+ // create a resource from the serialized data url
347
+ let resource = resourceFromDataURL(videoId, dataUrl);
348
+ resources.add(resource);
349
+
350
+ // use a data attribute to avoid making a real request
351
+ cloneEl.setAttribute('data-smartui-serialized-attribute-poster', resource.url);
352
+ }
353
+ }
354
+
355
+ // Drop loading attribute. We do not scroll page in discovery stage but we want to make sure that
356
+ // all resources are requested, so we drop loading attribute [as it can be set to lazy]
357
+ function dropLoadingAttribute(domElement) {
358
+ var _domElement$tagName;
359
+ if (!['img', 'iframe'].includes((_domElement$tagName = domElement.tagName) === null || _domElement$tagName === void 0 ? void 0 : _domElement$tagName.toLowerCase())) return;
360
+ domElement.removeAttribute('loading');
361
+ }
362
+
363
+ // All transformations that we need to apply for a successful discovery and stable render
364
+ function applyElementTransformations(domElement) {
365
+ dropLoadingAttribute(domElement);
366
+ }
367
+
368
+ /**
369
+ * Custom deep clone function that replaces smartui's current clone behavior.
370
+ * This enables us to capture shadow DOM in snapshots. It takes advantage of `attachShadow`'s mode option set to open
371
+ * https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#parameters
372
+ */
373
+
374
+ /**
375
+ * Deep clone a document while also preserving shadow roots
376
+ * returns document fragment
377
+ */
378
+
379
+ const ignoreTags = ['NOSCRIPT'];
380
+ function cloneNodeAndShadow(_ref) {
381
+ let {
382
+ dom,
383
+ disableShadowDOM
384
+ } = _ref;
385
+ // clones shadow DOM and light DOM for a given node
386
+ let cloneNode = (node, parent) => {
387
+ let walkTree = (nextn, nextp) => {
388
+ while (nextn) {
389
+ if (!ignoreTags.includes(nextn.nodeName)) {
390
+ cloneNode(nextn, nextp);
391
+ }
392
+ nextn = nextn.nextSibling;
393
+ }
394
+ };
395
+
396
+ // mark the node before cloning
397
+ markElement(node, disableShadowDOM);
398
+ let clone = node.cloneNode();
399
+
400
+ // We apply any element transformations here to avoid another treeWalk
401
+ applyElementTransformations(clone);
402
+ parent.appendChild(clone);
403
+
404
+ // shallow clone should not contain children
405
+ if (clone.children) {
406
+ Array.from(clone.children).forEach(child => clone.removeChild(child));
407
+ }
408
+
409
+ // clone shadow DOM
410
+ if (node.shadowRoot && !disableShadowDOM) {
411
+ // create shadowRoot
412
+ if (clone.shadowRoot) {
413
+ // it may be set up in a custom element's constructor
414
+ clone.shadowRoot.innerHTML = '';
415
+ } else {
416
+ clone.attachShadow({
417
+ mode: 'open'
418
+ });
419
+ }
420
+ // clone dom elements
421
+ walkTree(node.shadowRoot.firstChild, clone.shadowRoot);
422
+ }
423
+
424
+ // clone light DOM
425
+ walkTree(node.firstChild, clone);
426
+ };
427
+ let fragment = dom.createDocumentFragment();
428
+ cloneNode(dom.documentElement, fragment);
429
+ fragment.documentElement = fragment.firstChild;
430
+ fragment.head = fragment.querySelector('head');
431
+ fragment.body = fragment.querySelector('body');
432
+ return fragment;
433
+ }
434
+
435
+ /**
436
+ * Use `getInnerHTML()` to serialize shadow dom as <template> tags. `innerHTML` and `outerHTML` don't do this. Buzzword: "declarative shadow dom"
437
+ */
438
+ function getOuterHTML(docElement) {
439
+ // firefox doesn't serialize shadow DOM, we're awaiting API's by firefox to become ready and are not polyfilling it.
440
+ if (!docElement.getInnerHTML) {
441
+ return docElement.outerHTML;
442
+ }
443
+ // chromium gives us declarative shadow DOM serialization API
444
+ let innerHTML = docElement.getInnerHTML({
445
+ includeShadowRoots: true
446
+ });
447
+ docElement.textContent = '';
448
+ // Note: Here we are specifically passing replacer function to avoid any replacements due to
449
+ // special characters in client's dom like $&
450
+ return docElement.outerHTML.replace('</html>', () => `${innerHTML}</html>`);
451
+ }
452
+
453
+ // we inject declarative shadow dom polyfill to allow shadow dom to load in non chromium infrastructure browsers
454
+ // Since only chromium currently supports declarative shadow DOM - https://caniuse.com/declarative-shadow-dom
455
+ function injectDeclarativeShadowDOMPolyfill(ctx) {
456
+ let clone = ctx.clone;
457
+ let scriptEl = document.createElement('script');
458
+ scriptEl.setAttribute('id', '__smartui_shadowdom_helper');
459
+ scriptEl.setAttribute('data-smartui-injected', true);
460
+ scriptEl.innerHTML = `
461
+ function reversePolyFill(root=document){
462
+ root.querySelectorAll('template[shadowroot]').forEach(template => {
463
+ const mode = template.getAttribute('shadowroot');
464
+ const shadowRoot = template.parentNode.attachShadow({ mode });
465
+ shadowRoot.appendChild(template.content);
466
+ template.remove();
467
+ });
468
+
469
+ root.querySelectorAll('[data-smartui-shadow-host]').forEach(shadowHost => reversePolyFill(shadowHost.shadowRoot));
470
+ }
471
+
472
+ if (["interactive", "complete"].includes(document.readyState)) {
473
+ reversePolyFill();
474
+ } else {
475
+ document.addEventListener("DOMContentLoaded", () => reversePolyFill());
476
+ }
477
+ `.replace(/(\n|\s{2}|\t)/g, '');
478
+
479
+ // run polyfill as first thing post dom content is loaded
480
+ clone.head.prepend(scriptEl);
481
+ }
482
+
483
+ // Returns a copy or new doctype for a document.
484
+ function doctype(dom) {
485
+ let {
486
+ name = 'html',
487
+ publicId = '',
488
+ systemId = ''
489
+ } = (dom === null || dom === void 0 ? void 0 : dom.doctype) ?? {};
490
+ let deprecated = '';
491
+ if (publicId && systemId) {
492
+ deprecated = ` PUBLIC "${publicId}" "${systemId}"`;
493
+ } else if (publicId) {
494
+ deprecated = ` PUBLIC "${publicId}"`;
495
+ } else if (systemId) {
496
+ deprecated = ` SYSTEM "${systemId}"`;
497
+ }
498
+ return `<!DOCTYPE ${name}${deprecated}>`;
499
+ }
500
+
501
+ // Serializes and returns the cloned DOM as an HTML string
502
+ function serializeHTML(ctx) {
503
+ let html = getOuterHTML(ctx.clone.documentElement);
504
+ // replace serialized data attributes with real attributes
505
+ html = html.replace(/ data-smartui-serialized-attribute-(\w+?)=/ig, ' $1=');
506
+ // include the doctype with the html string
507
+ return doctype(ctx.dom) + html;
508
+ }
509
+ function serializeElements(ctx) {
510
+ serializeInputElements(ctx);
511
+ serializeFrames(ctx);
512
+ serializeVideos(ctx);
513
+ if (!ctx.enableJavaScript) {
514
+ serializeCSSOM(ctx);
515
+ serializeCanvas(ctx);
516
+ }
517
+ for (const shadowHost of ctx.dom.querySelectorAll('[data-smartui-shadow-host]')) {
518
+ let smartuiElementId = shadowHost.getAttribute('data-smartui-element-id');
519
+ let cloneShadowHost = ctx.clone.querySelector(`[data-smartui-element-id="${smartuiElementId}"]`);
520
+ if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) {
521
+ serializeElements({
522
+ ...ctx,
523
+ dom: shadowHost.shadowRoot,
524
+ clone: cloneShadowHost.shadowRoot
525
+ });
526
+ } else {
527
+ ctx.warnings.add('data-smartui-shadow-host does not have shadowRoot');
528
+ }
529
+ }
530
+ }
531
+
532
+ // Serializes a document and returns the resulting DOM string.
533
+ function serializeDOM(options) {
534
+ let {
535
+ dom = document,
536
+ // allow snake_case or camelCase
537
+ enableJavaScript = options === null || options === void 0 ? void 0 : options.enable_javascript,
538
+ domTransformation = options === null || options === void 0 ? void 0 : options.dom_transformation,
539
+ stringifyResponse = options === null || options === void 0 ? void 0 : options.stringify_response,
540
+ disableShadowDOM = options === null || options === void 0 ? void 0 : options.disable_shadow_dom,
541
+ reshuffleInvalidTags = options === null || options === void 0 ? void 0 : options.reshuffle_invalid_tags
542
+ } = options || {};
543
+
544
+ // keep certain records throughout serialization
545
+ let ctx = {
546
+ resources: new Set(),
547
+ warnings: new Set(),
548
+ hints: new Set(),
549
+ cache: new Map(),
550
+ enableJavaScript,
551
+ disableShadowDOM
552
+ };
553
+ ctx.dom = dom;
554
+ ctx.clone = cloneNodeAndShadow(ctx);
555
+ serializeElements(ctx);
556
+ if (domTransformation) {
557
+ try {
558
+ // eslint-disable-next-line no-eval
559
+ if (typeof domTransformation === 'string') domTransformation = window.eval(domTransformation);
560
+ domTransformation(ctx.clone.documentElement);
561
+ } catch (err) {
562
+ let errorMessage = `Could not transform the dom: ${err.message}`;
563
+ ctx.warnings.add(errorMessage);
564
+ console.error(errorMessage);
565
+ }
566
+ }
567
+ if (!disableShadowDOM) {
568
+ injectDeclarativeShadowDOMPolyfill(ctx);
569
+ }
570
+ if (reshuffleInvalidTags) {
571
+ let clonedBody = ctx.clone.body;
572
+ while (clonedBody.nextSibling) {
573
+ let sibling = clonedBody.nextSibling;
574
+ clonedBody.append(sibling);
575
+ }
576
+ } else if (ctx.clone.body.nextSibling) {
577
+ ctx.hints.add('DOM elements found outside </body>');
578
+ }
579
+ let result = {
580
+ html: serializeHTML(ctx),
581
+ warnings: Array.from(ctx.warnings),
582
+ resources: Array.from(ctx.resources),
583
+ hints: Array.from(ctx.hints)
584
+ };
585
+ return stringifyResponse ? JSON.stringify(result) : result;
586
+ }
587
+
588
+ exports["default"] = serializeDOM;
589
+ exports.serialize = serializeDOM;
590
+ exports.serializeDOM = serializeDOM;
591
+
592
+ Object.defineProperty(exports, '__esModule', { value: true });
593
+
594
+ })(this.SmartUIDOM = this.SmartUIDOM || {});
595
+ }).call(window);
596
+
597
+ if (typeof define === "function" && define.amd) {
598
+ define("@smartui/dom", [], () => window.SmartUIDOM);
599
+ } else if (typeof module === "object" && module.exports) {
600
+ module.exports = window.SmartUIDOM;
601
+ }