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