[READ-ONLY] Mirror of https://github.com/mrgnw/cv.
1import { chromium } from 'playwright';
2import fs from 'fs';
3import path from 'path';
4import http from 'http';
5import { execSync } from 'child_process';
6
7// Import our Node.js compatible version reader functions
8import { getAllVersions, getAllVersionMeta } from './pdf-version-reader.js';
9
10
11// Use our new version reader to get available versions
12const getAvailableVersions = () => {
13 try {
14 return getAllVersions();
15 } catch (error) {
16 console.error('Error getting versions from version reader:', error);
17 // Fallback to empty array
18 return [];
19 }
20};
21
22// const getChangedVersions = () => {
23// try {
24// const modified_versions = execSync('git diff --name-only HEAD HEAD~1').toString();
25
26// return modified_versions
27// .split('\n')
28// .filter(file => file.startsWith('src/lib/versions/') && file.endsWith('.json'))
29// .map(file => path.parse(file).name);
30// } catch (error) {
31// console.error('Error getting changed versions:', error.message);
32// return [];
33// }
34// };
35
36const getVersionNames = (specificVersions) => {
37 const allVersions = getAvailableVersions();
38
39 if (specificVersions?.includes('all')) {
40 return allVersions;
41 }
42
43 // If specific versions are provided, only process those
44 if (specificVersions?.length) {
45 return allVersions.filter(version => specificVersions.includes(version));
46 }
47
48 return allVersions;
49};
50
51/**
52 * Detect which port the preview server is running on
53 */
54const detectServerPort = async () => {
55 const ports = [4173, 4174, 4175, 4176, 4177];
56 const maxAttempts = 15; // 15 seconds total
57
58 for (let attempt = 0; attempt < maxAttempts; attempt++) {
59 for (const port of ports) {
60 const url = `http://localhost:${port}`;
61 try {
62 await new Promise((resolve, reject) => {
63 const req = http.get(url, (res) => {
64 resolve();
65 });
66 req.on('error', reject);
67 req.setTimeout(1000, () => {
68 req.destroy();
69 reject(new Error('Timeout'));
70 });
71 });
72 console.log(`✅ Found preview server on port ${port}`);
73 return url;
74 } catch (error) {
75 // Try next port
76 }
77 }
78
79 // Wait 1 second before trying again
80 if (attempt < maxAttempts - 1) {
81 console.log(`⏳ Waiting for server to start... (${attempt + 1}/${maxAttempts})`);
82 await new Promise(resolve => setTimeout(resolve, 1000));
83 }
84 }
85
86 throw new Error('Preview server not found on any expected port (4173-4177) after 15 seconds');
87};
88
89const waitForServer = (url) => {
90 return new Promise((resolve, reject) => {
91 const timeout = setTimeout(() => {
92 reject(new Error('Server start timeout'));
93 }, 30000);
94
95 const checkServer = () => {
96 http.get(url, (res) => {
97 clearTimeout(timeout);
98 resolve();
99 }).on('error', () => {
100 setTimeout(checkServer, 100);
101 });
102 };
103
104 checkServer();
105 });
106};
107
108async function getPageCount(page) {
109 return await page.evaluate(() => {
110 const height = document.documentElement.scrollHeight;
111 const pageHeight = 1123; // A4 height in pixels at 96 DPI
112 return Math.ceil(height / pageHeight);
113 });
114}
115
116// Helper function to check PDF page count
117async function checkPdfPageCount(page, options) {
118 const pdf = await page.pdf({ ...options });
119 const pageCount = (pdf.toString().match(/\/Page\s*$/gm) || []).length;
120 return pageCount;
121}
122
123export function generatePDF() {
124 // PDF generation disabled for now
125 console.log('PDF generation disabled');
126}
127
128// Configuration option to control sans version generation
129const GENERATE_SANS_VERSION = false; // Set to true to enable sans version generation
130
131// Helper function to generate PDF for a specific version and style
132async function generateVersionPDF(page, serverUrl, version, options, isSansStyle = false) {
133 // Build URL and paths based on style (simplified - no Spanish handling)
134 const stylePrefix = isSansStyle ? '/sans' : '';
135 const url = `${serverUrl}${stylePrefix}/${version}?print`;
136
137 const styleInfix = isSansStyle ? '-sans' : '';
138 const pdfName = version === 'main' ?
139 `morgan-williams${styleInfix}.pdf` :
140 `morgan-williams.${version}${styleInfix}.pdf`;
141
142 const outputDir = isSansStyle ? path.join('static', 'sans') : 'static';
143 const pdfPath = path.join(outputDir, pdfName);
144
145 let projectsToRemove = 0;
146 let pageCount;
147
148 do {
149 await page.goto(`${url}&removeProjects=${projectsToRemove}`, { waitUntil: 'networkidle' });
150 pageCount = await checkPdfPageCount(page, options);
151
152 if (pageCount > 1) {
153 projectsToRemove++;
154 console.log(` - project ${projectsToRemove} (${pageCount} pages)`);
155 }
156 } while (pageCount > 1 && projectsToRemove < 5);
157
158 await page.pdf({ path: pdfPath, ...options });
159 console.log(`🖨️ ${pdfPath}${projectsToRemove > 0 ? ` (removed ${projectsToRemove} projects)` : ''}`);
160}
161
162(async () => {
163 // Get versions from command line args OR get all available versions
164 const specificVersions = process.argv.length > 2 ?
165 process.argv.slice(2) :
166 getAvailableVersions();
167
168 console.log('🔍 Detecting preview server...');
169 let serverUrl;
170 try {
171 serverUrl = await detectServerPort();
172 } catch (error) {
173 console.error('❌', error.message);
174 console.log('💡 Make sure to run `npm run preview` first');
175 process.exit(1);
176 }
177
178 const versions = getVersionNames(specificVersions);
179 if (versions.length === 0) {
180 console.log('No versions to process');
181 process.exit(0);
182 }
183
184 console.log('Generating PDFs for versions:', versions.join(', '));
185 const browser = await chromium.launch();
186 const page = await browser.newPage();
187
188 const pdfOptions = {
189 format: 'A4',
190 printBackground: false,
191 margin: {
192 top: '6mm',
193 bottom: '6mm',
194 left: '8mm',
195 right: '8mm',
196 },
197 };
198
199 // Ensure static directory exists
200 if (!fs.existsSync('static')) {
201 fs.mkdirSync('static');
202 }
203
204 // Ensure sans directory exists if needed
205 if (GENERATE_SANS_VERSION && !fs.existsSync('static/sans')) {
206 fs.mkdirSync('static/sans');
207 }
208
209 // Process each version
210 for (const version of versions) {
211 try {
212 // Generate regular version
213 await generateVersionPDF(page, serverUrl, version, pdfOptions, false);
214
215 // Optionally generate sans version
216 if (GENERATE_SANS_VERSION) {
217 await generateVersionPDF(page, serverUrl, version, pdfOptions, true);
218 }
219 } catch (error) {
220 console.error(`Error generating PDFs for version ${version}:`, error);
221 }
222 }
223
224 await browser.close();
225 console.log('✅ Done');
226 process.exit(0);
227})();