import fs from 'node:fs/promises'; import path from 'node:path'; import {chromium} from '@playwright/test'; import {boxes} from '../demo/trial-demo-data.mjs'; // Fictional fixtures, isolated browser, blocked external requests. No customer writes. const phase=process.argv[2]||'final'; const root=path.resolve('..','caterium-six-proposals-20260918'); const out=path.join(root,phase==='final'?'output/pdf':'tmp/pdfs/'+phase); const assets=path.join(root,'tmp','pdfs',phase); await fs.mkdir(out,{recursive:true}); await fs.mkdir(assets,{recursive:true}); const browser=await chromium.launch(); const page=await browser.newPage(); await page.route('https://**',r=>r.abort()); await page.goto('http://127.0.0.1:4182/index.html',{waitUntil:'domcontentloaded'}); await page.waitForFunction(()=>Boolean(window.sunClientOfferDebugPdfPages)); const image=async file=>'data:image/'+({'.png':'png','.webp':'webp'}[path.extname(file)]||'jpeg')+';base64,'+(await fs.readFile(path.resolve('public',file))).toString('base64'); const items=await Promise.all(boxes.slice(0,8).map(async(b,i)=>({...b,categoryId:0,categoryName:'Фуршетные боксы',qty:i===0?2:1,unitPrice:b.price,sum:b.price*(i===0?2:1),photoData:await image(b.photo)}))); const base=items.reduce((n,i)=>n+i.sum,0); const logo=await page.evaluate(async()=>{ await CateriumProposalPDF.ready(); const c=document.createElement('canvas');c.width=1400;c.height=500;const x=c.getContext('2d'); x.fillStyle='#234734';x.font='500 150px "Caterium Playfair"';x.fillText('ЛИСТ',250,270); x.font='600 38px "Caterium Manrope"';x.fillText('К Е Й Т Е Р И Н Г',260,340); return c.toDataURL('image/png'); }); const snapshot={brandName:'Лист · кейтеринг',brandCity:'Санкт-Петербург',brandContacts:'Пример оформления · Данные вымышлены',logo,client:'Анна и Михаил',event:'Вечер в кругу друзей',date:'2026-10-24',time:'18:00',guests:20,items,pricing:{base,manual:1500,promo:0,discount:1500,itemsTotal:base-1500,delivery:1500,total:base},foodGrams:9200,foodPieces:156,controlLines:['Согласуем время и адрес доставки','Подготовим заказ к началу вашего события'],extraServices:['Сервировка стола — по согласованию','Обслуживание — по отдельному расчёту'],finalGallery:[await image('offer-gallery/001.jpg'),await image('offer-gallery/002.jpg')],pdfSettings:{texts:{heroNote:'Сезонные вкусы, любимые сочетания и красивые детали вашего вечера.'}}}; await page.evaluate(s=>window.__pdfFixture=s,snapshot); let choices=await page.evaluate(()=>CateriumProposalPDF.templates); if(phase==='first-four')choices=choices.slice(0,4); const report=[]; for(const [index,{id,name}] of choices.entries()){ const result=await page.evaluate(async id=>{ const s={...window.__pdfFixture,offerTemplateId:id}; const pages=await sunClientOfferDebugPdfPages(s); const jpg=pages.map(c=>({width:c.width,height:c.height,bytes:Uint8Array.from(atob(c.toDataURL('image/jpeg',.94).split(',')[1]),c=>c.charCodeAt(0))})); const blob=SunPdfEngine.fromJpegs(jpg); const pdf=await new Promise(resolve=>{const r=new FileReader();r.onload=()=>resolve(r.result.split(',')[1]);r.readAsDataURL(blob)}); const thumb=document.createElement('canvas');thumb.width=420;thumb.height=594;thumb.getContext('2d').drawImage(pages[0],0,0,420,594); const thumbnail=thumb.toDataURL('image/jpeg',.9).split(',')[1]; const info={id,pages:pages.length,width:pages[0].width,layout:pages.map(p=>p.__proposalLayout),images:pages.map(p=>p.__proposalImages||[])}; pages.forEach(c=>{c.width=0;c.height=0});return {pdf,info,thumbnail}; },id); const filename=`${String(index+1).padStart(2,'0')}-${id}.pdf`; await fs.writeFile(path.join(out,filename),Buffer.from(result.pdf,'base64')); await fs.writeFile(path.join(assets,id+'-cover.jpg'),Buffer.from(result.thumbnail,'base64')); if(phase==='final'){ // Thumbnails in the app are brand-neutral; actual PDFs use the customer's PNG. const thumb=await page.evaluate(async id=>{const pages=await CateriumProposalPDF.renderPages({...window.__pdfFixture,offerTemplateId:id,brandName:'Ваша компания',brandCity:'',brandContacts:'',logo:''});const c=document.createElement('canvas');c.width=420;c.height=594;c.getContext('2d').drawImage(pages[0],0,0,420,594);const data=c.toDataURL('image/jpeg',.9).split(',')[1];pages.forEach(p=>{p.width=0;p.height=0});return data},id); await fs.writeFile(path.resolve('public','offer-templates','quality-'+id+'.jpg'),Buffer.from(thumb,'base64')); } report.push({...result.info,name,filename});console.log(name,result.info.pages,'pages'); } await fs.writeFile(path.join(assets,'report.json'),JSON.stringify(report,null,2)); await browser.close();