@@ -9,34 +9,46 @@ import { XMLNS } from "./lib";
9
9
*/
10
10
async function inlineAllImages ( clone ) {
11
11
const imgEls = clone . querySelectorAll ( 'img' ) ;
12
- const promises = [ ] ;
13
- imgEls . forEach ( imgEl => {
14
- if ( imgEl . src && ! imgEl . src . startsWith ( 'data:' ) ) {
15
- promises . push (
16
- new Promise ( resolve => {
17
- const image = new window . Image ( ) ;
18
- image . crossOrigin = 'anonymous' ; // Try CORS
19
- image . onload = function ( ) {
20
- try {
21
- const canvas = document . createElement ( 'canvas' ) ;
22
- canvas . width = image . naturalWidth ;
23
- canvas . height = image . naturalHeight ;
24
- canvas . getContext ( '2d' ) . drawImage ( image , 0 , 0 ) ;
25
- imgEl . src = canvas . toDataURL ( ) ;
26
- } catch ( e ) {
27
- // it's tainted
28
- }
29
- resolve ( ) ;
30
- } ;
31
- image . onerror = function ( ) { resolve ( ) ; } ;
32
- image . src = imgEl . src ;
33
- } )
34
- ) ;
35
- }
12
+ const promises = Array . from ( imgEls ) . map ( imgEl => {
13
+ return new Promise ( resolve => {
14
+ if ( ! imgEl . src || imgEl . src . startsWith ( 'data:' ) ) return resolve ( ) ;
15
+
16
+ if ( imgEl . complete && imgEl . naturalWidth !== 0 ) {
17
+ try {
18
+ const canvas = document . createElement ( 'canvas' ) ;
19
+ canvas . width = imgEl . naturalWidth ;
20
+ canvas . height = imgEl . naturalHeight ;
21
+ canvas . getContext ( '2d' ) . drawImage ( imgEl , 0 , 0 ) ;
22
+ imgEl . src = canvas . toDataURL ( ) ;
23
+ } catch ( e ) {
24
+ // tainted
25
+ }
26
+ return resolve ( ) ;
27
+ }
28
+
29
+ const image = new window . Image ( ) ;
30
+ image . crossOrigin = 'anonymous' ;
31
+ image . onload = function ( ) {
32
+ try {
33
+ const canvas = document . createElement ( 'canvas' ) ;
34
+ canvas . width = image . naturalWidth ;
35
+ canvas . height = image . naturalHeight ;
36
+ canvas . getContext ( '2d' ) . drawImage ( image , 0 , 0 ) ;
37
+ imgEl . src = canvas . toDataURL ( ) ;
38
+ } catch ( e ) {
39
+ // tainted
40
+ }
41
+ resolve ( ) ;
42
+ } ;
43
+ image . onerror = function ( ) { resolve ( ) ; } ;
44
+ image . src = imgEl . src ;
45
+ } ) ;
36
46
} ) ;
47
+
37
48
await Promise . all ( promises ) ;
38
49
}
39
50
51
+
40
52
/**
41
53
* Removes all elements in the given DOM subtree that have the data-dom-to-png-ignore attribute.
42
54
* @param {HTMLElement } root - The root of the cloned DOM tree.
@@ -384,6 +396,23 @@ function walkAllAndApply(cloneNode, liveNode) {
384
396
}
385
397
}
386
398
399
+ function forceInlineImageStyles ( clone , original ) {
400
+ const originalImgs = Array . from ( original . querySelectorAll ( 'img' ) ) ;
401
+ clone . querySelectorAll ( 'img' ) . forEach ( img => {
402
+ const src = img . getAttribute ( 'src' ) ;
403
+ const match = originalImgs . find ( oimg => oimg . getAttribute ( 'src' ) === src ) ;
404
+ if ( match ) {
405
+ const computedStyle = window . getComputedStyle ( match ) ;
406
+ let styleString = '' ;
407
+ for ( let j = 0 ; j < computedStyle . length ; j ++ ) {
408
+ const property = computedStyle [ j ] ;
409
+ styleString += `${ property } :${ computedStyle . getPropertyValue ( property ) } ;` ;
410
+ }
411
+ img . setAttribute ( 'style' , styleString ) ;
412
+ }
413
+ } ) ;
414
+ }
415
+
387
416
/**
388
417
* Converts a DOM element (including HTML, SVG, and canvas) into a high-resolution PNG data URL.
389
418
*
@@ -446,6 +475,9 @@ async function domToPng({ container, scale = 2 }) {
446
475
inlineForeignObjectHTMLComputedStyles ( cloneSvg , liveSvg ) ;
447
476
applyAllSvgComputedStylesInline ( cloneSvg ) ;
448
477
setFontFamilyOnAllSvgTextElements ( cloneSvg , containerFontFamily ) ;
478
+ forceInlineImageStyles ( cloneSvg , liveSvg ) ;
479
+
480
+ await inlineAllImages ( cloneSvg ) ;
449
481
450
482
const bbox = liveSvg . getBoundingClientRect ( ) ;
451
483
const svgWidth = bbox . width ;
@@ -464,6 +496,7 @@ async function domToPng({ container, scale = 2 }) {
464
496
}
465
497
466
498
applyAllComputedStylesDeep ( clone , container , containerFontFamily ) ;
499
+ forceInlineImageStyles ( clone , container ) ;
467
500
removeIgnoredElements ( clone ) ;
468
501
await inlineAllImages ( clone ) ;
469
502
0 commit comments