html2canvas-pro 2.0.1 → 2.0.2

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 2.0.1 <https://yorickshan.github.io/html2canvas-pro/>
2
+ * html2canvas-pro 2.0.2 <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
  */
@@ -6591,36 +6591,50 @@ class DocumentCloner {
6591
6591
  * */
6592
6592
  const baseUri = documentClone.baseURI;
6593
6593
  documentClone.open();
6594
+ const rawHTML = serializeDoctype(document.doctype) + '<html></html>';
6594
6595
  try {
6595
- // fixing "This document requires 'TrustedHTML' assignment. The action has been blocked." error
6596
- // @ts-ignore
6597
- const policy = trustedTypes.createPolicy('my-policy', {
6598
- createHTML: (string) => string
6599
- });
6600
- const rawHTML = serializeDoctype(document.doctype) + '<html></html>';
6601
- const trustedHTML = policy.createHTML(rawHTML);
6602
- documentClone.write(trustedHTML);
6596
+ // Fixing "This document requires 'TrustedHTML' assignment. The action has been blocked." error.
6597
+ // Reuse existing policy when present (e.g. second html2canvas call) to avoid createPolicy duplicate-name throw.
6598
+ const ownerWindow = this.referenceElement.ownerDocument?.defaultView;
6599
+ const trustedTypesFactory = ownerWindow && ownerWindow.trustedTypes;
6600
+ let policy = trustedTypesFactory?.getPolicy?.('html2canvas-pro');
6601
+ if (!policy && trustedTypesFactory) {
6602
+ policy = trustedTypesFactory.createPolicy('html2canvas-pro', {
6603
+ createHTML: (string) => string
6604
+ });
6605
+ }
6606
+ if (policy) {
6607
+ documentClone.write(policy.createHTML(rawHTML));
6608
+ }
6609
+ else {
6610
+ documentClone.write(rawHTML);
6611
+ }
6603
6612
  }
6604
- catch (e) {
6605
- // if browser does not support trustedTypes
6606
- documentClone.write(serializeDoctype(document.doctype) + '<html></html>');
6613
+ catch (_e) {
6614
+ documentClone.write(rawHTML);
6607
6615
  }
6608
6616
  // Chrome scrolls the parent document for some reason after the write to the cloned window???
6609
6617
  restoreOwnerScroll(this.referenceElement.ownerDocument, scrollX, scrollY);
6610
6618
  /**
6611
- * Note: adoptNode() should be called AFTER documentClone.open() and close()
6619
+ * IMPORTANT: documentClone.close() MUST be called BEFORE adoptNode().
6612
6620
  *
6613
- * In Chrome, calling adoptNode() before or during open/write may cause
6614
- * styles with uppercase characters in class names (e.g. ".MyClass") to not apply correctly.
6621
+ * In Chrome, calling adoptNode() while the document is still "open"
6622
+ * (between document.open() and document.close()) causes CSS rules with
6623
+ * uppercase characters in class names (e.g. ".MyClass") to not match
6624
+ * correctly. Chrome's CSS engine only enters a fully-resolved matching
6625
+ * mode once the document is closed.
6615
6626
  *
6616
- * Fix:
6617
- * - Make sure adoptNode() is called after documentClone.open() and close()
6618
- * - This allows Chrome to properly match and apply all CSS rules including mixed-case class selectors.
6619
- * */
6627
+ * Correct order: open() → write() → close() → adoptNode() → replaceChild()
6628
+ *
6629
+ * Timing: close() queues the iframe 'load' event; because JS is single-threaded,
6630
+ * the synchronous adoptNode() and replaceChild() below complete before that
6631
+ * event is dispatched. iframeLoader's setInterval will therefore see the body
6632
+ * already populated on its first tick.
6633
+ */
6634
+ documentClone.close();
6620
6635
  const adoptedNode = documentClone.adoptNode(this.documentElement);
6621
6636
  addBase(adoptedNode, baseUri);
6622
6637
  documentClone.replaceChild(adoptedNode, documentClone.documentElement);
6623
- documentClone.close();
6624
6638
  return iframeLoad;
6625
6639
  }
6626
6640
  createElementClone(node) {
@@ -7149,13 +7163,16 @@ const serializeDoctype = (doctype) => {
7149
7163
  str += doctype.name;
7150
7164
  }
7151
7165
  if (doctype.internalSubset) {
7152
- str += doctype.internalSubset;
7166
+ str += ' ' + doctype.internalSubset.replace(/"/g, '&quot;').replace(/>/g, '&gt;');
7153
7167
  }
7154
7168
  if (doctype.publicId) {
7155
- str += `"${doctype.publicId}"`;
7169
+ str += ' PUBLIC "' + doctype.publicId.replace(/"/g, '&quot;') + '"';
7170
+ if (doctype.systemId) {
7171
+ str += ' "' + doctype.systemId.replace(/"/g, '&quot;') + '"';
7172
+ }
7156
7173
  }
7157
- if (doctype.systemId) {
7158
- str += `"${doctype.systemId}"`;
7174
+ else if (doctype.systemId) {
7175
+ str += ' SYSTEM "' + doctype.systemId.replace(/"/g, '&quot;') + '"';
7159
7176
  }
7160
7177
  str += '>';
7161
7178
  }