1- import { chromium } from "playwright-core" ;
1+ // Use dynamic import for playwright-core to avoid bundling issues
2+ // This allows playwright-core to be loaded at runtime from node_modules
23import type { Page } from "playwright-core" ;
34
45export interface HtmlToImageOptions {
@@ -11,12 +12,53 @@ export interface HtmlToImageOptions {
1112 executablePath ?: string | null ;
1213}
1314
15+ /**
16+ * Dynamically loads playwright-core at runtime
17+ * due to dynamic imports and native dependencies
18+ */
19+ async function loadPlaywright ( ) {
20+ const path = await import ( "node:path" ) ;
21+ const fs = await import ( "node:fs" ) ;
22+
23+ // For compiled binaries, playwright-core should be in node_modules relative to the executable
24+ // Try bundled location first (for production builds)
25+ if ( process . execPath ) {
26+ const execDir = path . dirname ( process . execPath ) ;
27+ const bundledPath = path . join ( execDir , "node_modules" , "playwright-core" ) ;
28+
29+ if ( fs . existsSync ( bundledPath ) ) {
30+ try {
31+ // Use file:// URL for absolute path import
32+ const playwright = await import ( path . resolve ( bundledPath ) ) ;
33+ return playwright . chromium ;
34+ } catch ( error ) {
35+ // Fall through to standard import
36+ }
37+ }
38+ }
39+
40+ // Try standard import (works for development and if node_modules is in module resolution path)
41+ try {
42+ const playwright = await import ( "playwright-core" ) ;
43+ return playwright . chromium ;
44+ } catch ( error ) {
45+ throw new Error (
46+ `Failed to load playwright-core: ${
47+ error instanceof Error ? error . message : String ( error )
48+ } . ` +
49+ "Make sure playwright-core is installed or bundled with the application in node_modules/playwright-core." ,
50+ ) ;
51+ }
52+ }
53+
1454/**
1555 * Converts HTML to an image using Playwright.
1656 * @param options - Configuration options for the image generation
1757 * @returns Buffer containing the image data
1858 */
19- export async function htmlToImage ( options : HtmlToImageOptions ) : Promise < Buffer > {
59+ export async function htmlToImage (
60+ options : HtmlToImageOptions ,
61+ ) : Promise < Buffer > {
2062 const {
2163 html,
2264 output,
@@ -27,10 +69,18 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
2769 executablePath,
2870 } = options ;
2971
72+ // Dynamically load playwright-core
73+ const chromium = await loadPlaywright ( ) ;
74+
3075 // Launch browser with appropriate settings
3176 const launchOptions : Parameters < typeof chromium . launch > [ 0 ] = {
3277 headless : true ,
33- args : [ "--no-sandbox" , "--disable-setuid-sandbox" , "--disable-dev-shm-usage" , "--disable-gpu" ] ,
78+ args : [
79+ "--no-sandbox" ,
80+ "--disable-setuid-sandbox" ,
81+ "--disable-dev-shm-usage" ,
82+ "--disable-gpu" ,
83+ ] ,
3484 } ;
3585
3686 // If executable path is provided, use it explicitly
@@ -45,7 +95,11 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
4595
4696 // Set content with HTML
4797 await page . setContent ( html , {
48- waitUntil : waitUntil as "load" | "domcontentloaded" | "networkidle" | "commit" ,
98+ waitUntil : waitUntil as
99+ | "load"
100+ | "domcontentloaded"
101+ | "networkidle"
102+ | "commit" ,
49103 } ) ;
50104
51105 // Measure the actual rendered content width to respect max-width constraints
@@ -60,7 +114,11 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
60114
61115 // Use body dimensions which respect max-width constraints
62116 const width = bodyRect . width ;
63- const height = Math . max ( body . scrollHeight , document . documentElement . scrollHeight , bodyRect . height ) ;
117+ const height = Math . max (
118+ body . scrollHeight ,
119+ document . documentElement . scrollHeight ,
120+ bodyRect . height ,
121+ ) ;
64122
65123 return {
66124 width : Math . ceil ( width ) ,
@@ -98,7 +156,9 @@ export async function htmlToImage(options: HtmlToImageOptions): Promise<Buffer>
98156 } ) ;
99157
100158 // Convert to Buffer if needed
101- const buffer = screenshotBuffer instanceof Buffer ? screenshotBuffer : Buffer . from ( screenshotBuffer ) ;
159+ const buffer = screenshotBuffer instanceof Buffer
160+ ? screenshotBuffer
161+ : Buffer . from ( screenshotBuffer ) ;
102162
103163 return buffer ;
104164 } finally {
0 commit comments