@@ -5,8 +5,13 @@ const { execSync } = require('child_process');
5
5
6
6
// --- Configuration ---
7
7
const PROJECT_ROOT = process . cwd ( ) ;
8
- const TEMPLATE_PATH = join ( PROJECT_ROOT , 'assets' , 'og-template' , 'template.html' ) ;
9
- const INPUT_JSON_PATH = join ( PROJECT_ROOT , 'tmp' , 'ogImageData.json' ) ;
8
+ const TMP_DIR = join ( PROJECT_ROOT , 'tmp' ) ;
9
+ const BASE_TEMPLATE_PATH = join ( PROJECT_ROOT , 'assets' , 'og-template' , 'base-template.html' ) ;
10
+ const OVERLAY_TEMPLATE_PATH = join ( PROJECT_ROOT , 'assets' , 'og-template' , 'text-overlay-template.html' ) ;
11
+ const INPUT_JSON_PATH = join ( TMP_DIR , 'ogImageData.json' ) ;
12
+
13
+ const BASE_IMAGE_TMP_HTML = join ( TMP_DIR , 'base-og-temp.html' ) ;
14
+ const BASE_IMAGE_OUTPUT_PATH = join ( TMP_DIR , 'base-og.jpg' ) ;
10
15
const OUTPUT_FORMAT = 'jpg' ;
11
16
const JPEG_QUALITY = 95 ;
12
17
@@ -15,18 +20,37 @@ async function pathExists(path) {
15
20
try { await stat ( path ) ; return true ; } catch { return false ; }
16
21
}
17
22
23
+ async function generateBaseImage ( logoUri , backgroundUri ) {
24
+ console . log ( '🖼️ Generating base OG image...' ) ;
25
+ if ( ! ( await pathExists ( BASE_TEMPLATE_PATH ) ) ) {
26
+ throw new Error ( `Base template not found: ${ BASE_TEMPLATE_PATH } ` ) ;
27
+ }
28
+ const baseTemplateContent = await readFile ( BASE_TEMPLATE_PATH , 'utf8' ) ;
29
+
30
+ const htmlContent = baseTemplateContent
31
+ . replace ( 'LOGO_SRC' , logoUri )
32
+ . replace ( 'BACKGROUND_URL' , backgroundUri ) ;
33
+
34
+ await writeFile ( BASE_IMAGE_TMP_HTML , htmlContent ) ;
35
+
36
+ const command = `wkhtmltoimage --enable-local-file-access --quality ${ JPEG_QUALITY } --format ${ OUTPUT_FORMAT } --width 1200 --height 630 "${ BASE_IMAGE_TMP_HTML } " "${ BASE_IMAGE_OUTPUT_PATH } "` ;
37
+ execSync ( command , { stdio : 'pipe' } ) ;
38
+
39
+ await unlink ( BASE_IMAGE_TMP_HTML ) ; // Clean up temp html
40
+ console . log ( `✅ Base OG image created at: ${ BASE_IMAGE_OUTPUT_PATH } ` ) ;
41
+ return `file://${ BASE_IMAGE_OUTPUT_PATH } ` ;
42
+ }
43
+
18
44
// --- Main Image Generation Logic ---
19
45
async function generateImages ( ) {
20
- console . log ( `🖼️ Starting OG image generation...` ) ;
46
+ console . log ( `🖼️ Starting page-specific OG image generation...` ) ;
21
47
22
48
// --- Pre-flight checks ---
23
- if ( ! ( await pathExists ( TEMPLATE_PATH ) ) ) {
24
- console . error ( `❌ Template not found: ${ TEMPLATE_PATH } ` ) ;
25
- process . exit ( 1 ) ;
26
- }
27
49
if ( ! ( await pathExists ( INPUT_JSON_PATH ) ) ) {
28
- console . error ( `❌ Data file not found: ${ INPUT_JSON_PATH } . Run collect script first.` ) ;
29
- process . exit ( 1 ) ;
50
+ throw new Error ( `❌ Data file not found: ${ INPUT_JSON_PATH } . Run collect script first.` ) ;
51
+ }
52
+ if ( ! ( await pathExists ( OVERLAY_TEMPLATE_PATH ) ) ) {
53
+ throw new Error ( `❌ Overlay template not found: ${ OVERLAY_TEMPLATE_PATH } ` ) ;
30
54
}
31
55
try {
32
56
execSync ( 'wkhtmltoimage --version' , { stdio : 'ignore' } ) ;
@@ -36,27 +60,27 @@ async function generateImages() {
36
60
}
37
61
38
62
// --- Read data and template ---
39
- const templateContent = await readFile ( TEMPLATE_PATH , 'utf8' ) ;
63
+ const overlayTemplateContent = await readFile ( OVERLAY_TEMPLATE_PATH , 'utf8' ) ;
40
64
const jsonData = JSON . parse ( await readFile ( INPUT_JSON_PATH , 'utf8' ) ) ;
41
65
42
66
if ( ! jsonData || ! jsonData . pages || jsonData . pages . length === 0 ) {
43
67
console . warn ( '⚠️ No pages to process.' ) ;
44
68
return ;
45
69
}
70
+
71
+ // --- Generate the single base image first ---
72
+ const baseImageFileUrl = await generateBaseImage ( jsonData . logoDataUri , jsonData . backgroundDataUri ) ;
46
73
47
74
let successCount = 0 ;
48
75
let errorCount = 0 ;
49
- const logoDataUri = jsonData . logoDataUri || '' ;
50
- const backgroundDataUri = jsonData . backgroundDataUri || '' ;
51
76
52
- // --- Process each page ---
77
+ // --- Process each page using the base image ---
53
78
for ( const pageData of jsonData . pages ) {
54
79
const { title, description, outputPath, tempHtmlPath } = pageData ;
55
80
56
81
try {
57
- const htmlContent = templateContent
58
- . replace ( 'LOGO_SRC' , logoDataUri )
59
- . replace ( 'BACKGROUND_URL' , backgroundDataUri ) // Using BACKGROUND_URL placeholder now
82
+ const htmlContent = overlayTemplateContent
83
+ . replace ( 'BASE_IMAGE_URL' , baseImageFileUrl )
60
84
. replace ( 'PAGE_TITLE' , title )
61
85
. replace ( 'PAGE_DESCRIPTION' , description ) ;
62
86
0 commit comments