// scripts/bridge/generate-pdf.js // ๐ŸŒ‰ ๆกฅๆŽฅยทMarkdown โ†’ PDF ็”Ÿๆˆ // // ่ฏปๅ– data/broadcasts/pdf/ ไธ‹็š„ Markdown ๆ–‡ไปถ๏ผŒ // ไฝฟ็”จ md-to-pdf ่ฝฌๆขไธบ PDF๏ผŒๅฅ—็”จๅ…‰ๆน–ๅนฟๆ’ญๆจกๆฟ // // ็Žฏๅขƒๅ˜้‡๏ผš // MANIFEST_FILE fetch-broadcast.js ็”Ÿๆˆ็š„ๆธ…ๅ•ๆ–‡ไปถ่ทฏๅพ„ 'use strict'; const fs = require('fs'); const path = require('path'); const OUTPUT_DIR = path.join('data', 'broadcasts', 'pdf'); // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // PDF ๆ ทๅผๆจกๆฟ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• const PDF_CSS = ` body { font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif; font-size: 14px; line-height: 1.8; color: #333; padding: 40px; } h1 { font-size: 24px; border-bottom: 2px solid #1a73e8; padding-bottom: 10px; margin-bottom: 20px; } h2 { font-size: 20px; margin-top: 30px; } h3 { font-size: 16px; margin-top: 20px; } blockquote { border-left: 4px solid #1a73e8; padding: 10px 20px; margin: 15px 0; background: #f8f9fa; color: #555; } code { background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-size: 13px; } pre code { display: block; padding: 15px; overflow-x: auto; } hr { border: none; border-top: 1px solid #ddd; margin: 20px 0; } @page { margin: 20mm; @top-center { content: "ๅ…‰ๆน–ๅนฟๆ’ญ ยท guanghulab.com"; font-size: 10px; color: #999; } @bottom-center { content: counter(page) " / " counter(pages); font-size: 10px; color: #999; } } `; // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // ไธป้€ป่พ‘ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• async function main() { const manifestFile = process.env.MANIFEST_FILE || path.join(OUTPUT_DIR, 'manifest.json'); if (!fs.existsSync(manifestFile)) { console.log('๐Ÿ“ญ ๆ—  manifest.json๏ผŒ่ทณ่ฟ‡ PDF ็”Ÿๆˆ'); process.exit(0); } const manifest = JSON.parse(fs.readFileSync(manifestFile, 'utf8')); if (manifest.length === 0) { console.log('๐Ÿ“ญ ๆธ…ๅ•ไธบ็ฉบ๏ผŒ่ทณ่ฟ‡ PDF ็”Ÿๆˆ'); process.exit(0); } // ๅŠจๆ€ๅŠ ่ฝฝ md-to-pdf๏ผˆๅœจ workflow ไธญๅฎ‰่ฃ…๏ผ‰ let mdToPdf; try { mdToPdf = require('md-to-pdf').mdToPdf; } catch (e) { console.error('โŒ md-to-pdf ๆœชๅฎ‰่ฃ…๏ผŒ่ฏทๅ…ˆ่ฟ่กŒ: npm install md-to-pdf'); console.log('โš ๏ธ ๅ›ž้€€ๅˆฐ็บฏๆ–‡ๆœฌ PDF ๆจกๅผ๏ผˆๅฐ† Markdown ๅŽŸๆ–‡ไฟ็•™๏ผ‰'); // ๅ›ž้€€๏ผšไป…ไฟ็•™ .md ๆ–‡ไปถ๏ผŒๆ ‡่ฎฐไธบๅพ…ๅค„็† for (const item of manifest) { if (fs.existsSync(item.file)) { const pdfPath = item.file.replace(/\.md$/, '.pdf.pending'); fs.copyFileSync(item.file, pdfPath); console.log(` ๐Ÿ“ ${pdfPath} (ๅพ…่ฝฌๆข)`); } } return; } console.log(`๐Ÿ“„ ๅผ€ๅง‹็”Ÿๆˆ ${manifest.length} ไปฝ PDFโ€ฆ`); let ok = 0, failed = 0; const pdfFiles = []; for (const item of manifest) { if (!fs.existsSync(item.file)) { console.log(` โš ๏ธ ๆ–‡ไปถไธๅญ˜ๅœจ: ${item.file}`); failed++; continue; } try { const pdfPath = item.file.replace(/\.md$/, '.pdf'); const result = await mdToPdf( { path: path.resolve(item.file) }, { stylesheet: [], css: PDF_CSS, pdf_options: { format: 'A4', margin: { top: '25mm', bottom: '25mm', left: '20mm', right: '20mm' }, printBackground: true, }, launch_options: { args: ['--no-sandbox', '--disable-setuid-sandbox'] }, } ); if (result && result.content) { fs.writeFileSync(pdfPath, result.content); pdfFiles.push({ ...item, pdf: pdfPath }); console.log(` โœ… ${pdfPath}`); ok++; } else { console.error(` โŒ PDF ๅ†…ๅฎนไธบ็ฉบ: ${item.file}`); failed++; } } catch (e) { console.error(` โŒ PDF ็”Ÿๆˆๅคฑ่ดฅ: ${item.file}: ${e.message}`); failed++; } } console.log(`\nโœ… PDF ็”ŸๆˆๅฎŒๆˆ ยท ๆˆๅŠŸ ${ok} ไปฝ ยท ๅคฑ่ดฅ ${failed} ไปฝ`); // ๆ›ดๆ–ฐ manifest ๅŒ…ๅซ PDF ่ทฏๅพ„ const pdfManifest = path.join(OUTPUT_DIR, 'pdf-manifest.json'); fs.writeFileSync(pdfManifest, JSON.stringify(pdfFiles, null, 2)); console.log(`๐Ÿ“ PDF ๆธ…ๅ•: ${pdfManifest}`); if (process.env.GITHUB_OUTPUT) { fs.appendFileSync(process.env.GITHUB_OUTPUT, `pdf_count=${ok}\npdf_manifest=${pdfManifest}\n` ); } } main().catch(e => { console.error(e); process.exit(1); });