html2canvas-pro 1.6.6 → 1.6.7

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * html2canvas-pro 1.6.6 <https://yorickshan.github.io/html2canvas-pro/>
2
+ * html2canvas-pro 1.6.7 <https://yorickshan.github.io/html2canvas-pro/>
3
3
  * Copyright (c) 2024-present yorickshan and html2canvas-pro contributors
4
4
  * Released under MIT License
5
5
  */
@@ -6382,20 +6382,161 @@ class DocumentCloner {
6382
6382
  }
6383
6383
  }
6384
6384
  }
6385
- cloneChildNodes(node, clone, copyStyles) {
6386
- // Clone shadow DOM content if it exists
6387
- if (node.shadowRoot && clone.shadowRoot) {
6388
- for (let child = node.shadowRoot.firstChild; child; child = child.nextSibling) {
6389
- // Clone all shadow DOM children including <slot> elements
6390
- // The browser will automatically handle slot assignment
6391
- clone.shadowRoot.appendChild(this.cloneNode(child, copyStyles));
6385
+ /**
6386
+ * Check if a child node should be cloned based on filtering rules
6387
+ * Filters out: scripts, ignored elements, and optionally styles
6388
+ */
6389
+ shouldCloneChild(child) {
6390
+ return (!isElementNode(child) ||
6391
+ (!isScriptElement(child) &&
6392
+ !child.hasAttribute(IGNORE_ATTRIBUTE) &&
6393
+ (typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child))));
6394
+ }
6395
+ /**
6396
+ * Check if a style element should be cloned based on copyStyles option
6397
+ */
6398
+ shouldCloneStyleElement(child) {
6399
+ return !this.options.copyStyles || !isElementNode(child) || !isStyleElement(child);
6400
+ }
6401
+ /**
6402
+ * Safely append a cloned child to a target, applying all filtering rules
6403
+ */
6404
+ safeAppendClonedChild(target, child, copyStyles) {
6405
+ if (this.shouldCloneChild(child) && this.shouldCloneStyleElement(child)) {
6406
+ target.appendChild(this.cloneNode(child, copyStyles));
6407
+ }
6408
+ }
6409
+ /**
6410
+ * Clone assigned nodes from a slot element to the target
6411
+ */
6412
+ cloneAssignedNodes(assignedNodes, target, copyStyles) {
6413
+ assignedNodes.forEach((node) => {
6414
+ this.safeAppendClonedChild(target, node, copyStyles);
6415
+ });
6416
+ }
6417
+ /**
6418
+ * Clone fallback content from a slot element when no nodes are assigned
6419
+ */
6420
+ cloneSlotFallbackContent(slot, target, copyStyles) {
6421
+ for (let child = slot.firstChild; child; child = child.nextSibling) {
6422
+ this.safeAppendClonedChild(target, child, copyStyles);
6423
+ }
6424
+ }
6425
+ /**
6426
+ * Handle cloning of a slot element, including assigned nodes or fallback content
6427
+ */
6428
+ cloneSlotElement(slot, targetShadowRoot, copyStyles) {
6429
+ if (!isSlotElement(slot)) {
6430
+ return;
6431
+ }
6432
+ const slotElement = slot;
6433
+ // Defensive check: ensure assignedNodes method exists
6434
+ if (typeof slotElement.assignedNodes !== 'function') {
6435
+ this.context.logger.warn('HTMLSlotElement.assignedNodes is not available', slot);
6436
+ this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
6437
+ return;
6438
+ }
6439
+ const assignedNodes = slotElement.assignedNodes();
6440
+ // Defensive check: ensure assignedNodes returns an array
6441
+ if (!assignedNodes || !Array.isArray(assignedNodes)) {
6442
+ this.context.logger.warn('assignedNodes() did not return a valid array', slot);
6443
+ this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
6444
+ return;
6445
+ }
6446
+ if (assignedNodes.length > 0) {
6447
+ // Clone assigned nodes
6448
+ this.cloneAssignedNodes(assignedNodes, targetShadowRoot, copyStyles);
6449
+ }
6450
+ else {
6451
+ // Clone fallback content
6452
+ this.cloneSlotFallbackContent(slot, targetShadowRoot, copyStyles);
6453
+ }
6454
+ }
6455
+ /**
6456
+ * Clone shadow DOM children to the target shadow root
6457
+ */
6458
+ cloneShadowDOMChildren(shadowRoot, targetShadowRoot, copyStyles) {
6459
+ for (let child = shadowRoot.firstChild; child; child = child.nextSibling) {
6460
+ if (isElementNode(child) && isSlotElement(child)) {
6461
+ // Handle slot elements specially
6462
+ this.cloneSlotElement(child, targetShadowRoot, copyStyles);
6463
+ }
6464
+ else {
6465
+ // Clone regular elements
6466
+ this.safeAppendClonedChild(targetShadowRoot, child, copyStyles);
6392
6467
  }
6393
6468
  }
6394
- // Clone light DOM content (always, even if shadow DOM exists)
6469
+ }
6470
+ /**
6471
+ * Clone light DOM children to the target element
6472
+ */
6473
+ cloneLightDOMChildren(node, clone, copyStyles) {
6395
6474
  for (let child = node.firstChild; child; child = child.nextSibling) {
6396
6475
  this.appendChildNode(clone, child, copyStyles);
6397
6476
  }
6398
6477
  }
6478
+ /**
6479
+ * Clone slot element as light DOM when shadow root creation failed
6480
+ */
6481
+ cloneSlotElementAsLightDOM(slot, clone, copyStyles) {
6482
+ if (!isSlotElement(slot)) {
6483
+ return;
6484
+ }
6485
+ const slotElement = slot;
6486
+ if (typeof slotElement.assignedNodes !== 'function') {
6487
+ // Fallback: clone slot's children
6488
+ for (let child = slot.firstChild; child; child = child.nextSibling) {
6489
+ this.appendChildNode(clone, child, copyStyles);
6490
+ }
6491
+ return;
6492
+ }
6493
+ const assignedNodes = slotElement.assignedNodes();
6494
+ if (assignedNodes && Array.isArray(assignedNodes) && assignedNodes.length > 0) {
6495
+ // Clone assigned nodes as light DOM
6496
+ assignedNodes.forEach((node) => this.appendChildNode(clone, node, copyStyles));
6497
+ }
6498
+ else {
6499
+ // Clone fallback content as light DOM
6500
+ for (let child = slot.firstChild; child; child = child.nextSibling) {
6501
+ this.appendChildNode(clone, child, copyStyles);
6502
+ }
6503
+ }
6504
+ }
6505
+ /**
6506
+ * Clone shadow DOM content as light DOM when shadow root creation failed
6507
+ * This is a fallback mechanism to ensure content is not lost
6508
+ */
6509
+ cloneShadowDOMAsLightDOM(shadowRoot, clone, copyStyles) {
6510
+ for (let child = shadowRoot.firstChild; child; child = child.nextSibling) {
6511
+ if (isElementNode(child) && isSlotElement(child)) {
6512
+ this.cloneSlotElementAsLightDOM(child, clone, copyStyles);
6513
+ }
6514
+ else {
6515
+ this.appendChildNode(clone, child, copyStyles);
6516
+ }
6517
+ }
6518
+ }
6519
+ /**
6520
+ * Clone child nodes from source element to clone element
6521
+ * Handles shadow DOM, slots, and light DOM appropriately
6522
+ */
6523
+ cloneChildNodes(node, clone, copyStyles) {
6524
+ if (node.shadowRoot && clone.shadowRoot) {
6525
+ // Both original and clone have shadow roots - clone shadow DOM content
6526
+ this.cloneShadowDOMChildren(node.shadowRoot, clone.shadowRoot, copyStyles);
6527
+ // Also clone light DOM (slot content sources)
6528
+ this.cloneLightDOMChildren(node, clone, copyStyles);
6529
+ }
6530
+ else if (node.shadowRoot && !clone.shadowRoot) {
6531
+ // Original has shadow root but clone doesn't (creation failed)
6532
+ // Fallback: clone shadow DOM content as light DOM to preserve content
6533
+ this.cloneShadowDOMAsLightDOM(node.shadowRoot, clone, copyStyles);
6534
+ }
6535
+ else {
6536
+ // No shadow DOM - just clone light DOM children
6537
+ this.cloneLightDOMChildren(node, clone, copyStyles);
6538
+ }
6539
+ }
6399
6540
  cloneNode(node, copyStyles) {
6400
6541
  if (isTextNode(node)) {
6401
6542
  return document.createTextNode(node.data);