| |
| |
| |
| |
| |
|
|
| import { vfs } from '@/lib/vfs'; |
| import { VirtualServer } from '@/lib/preview/virtual-server'; |
| import { captureIframeScreenshot } from './screenshot'; |
|
|
| export async function captureProjectScreenshot(projectId: string): Promise<string | null> { |
| await vfs.init(); |
|
|
| const project = await vfs.getProject(projectId); |
| const server = new VirtualServer(vfs, projectId, { runtime: project?.settings?.runtime }); |
| let compiled; |
| try { |
| compiled = await server.compileProject(); |
| } catch { |
| server.cleanupBlobUrls(); |
| return null; |
| } |
|
|
| const indexFile = compiled.files.find(f => f.path === '/index.html'); |
| if (!indexFile) { |
| server.cleanupBlobUrls(); |
| return null; |
| } |
|
|
| let html = typeof indexFile.content === 'string' |
| ? indexFile.content |
| : new TextDecoder().decode(indexFile.content as ArrayBuffer); |
|
|
| |
| html = html.replace(/href="([^"]+\.css)"/g, (match, href) => { |
| if (href.startsWith('http') || href.startsWith('//')) return match; |
| const path = href.startsWith('/') ? href : '/' + href; |
| const blobUrl = compiled.blobUrls.get(path); |
| return blobUrl ? `href="${blobUrl}"` : match; |
| }); |
|
|
| |
| html = html.replace(/src="([^"]+\.js)"/g, (match, src) => { |
| if (src.startsWith('http') || src.startsWith('//')) return match; |
| const path = src.startsWith('/') ? src : '/' + src; |
| const blobUrl = compiled.blobUrls.get(path); |
| return blobUrl ? `src="${blobUrl}"` : match; |
| }); |
|
|
| |
| html = html.replace(/src="([^"]+\.(png|jpg|jpeg|gif|svg|webp))"/gi, (match, imgPath) => { |
| const path = imgPath.startsWith('/') ? imgPath : '/' + imgPath; |
| const blobUrl = compiled.blobUrls.get(path); |
| return blobUrl ? `src="${blobUrl}"` : match; |
| }); |
|
|
| const iframe = document.createElement('iframe'); |
| iframe.style.position = 'fixed'; |
| iframe.style.top = '-10000px'; |
| iframe.style.left = '-10000px'; |
| iframe.style.width = '1280px'; |
| iframe.style.height = '720px'; |
| iframe.style.border = 'none'; |
|
|
| document.body.appendChild(iframe); |
|
|
| try { |
| await new Promise<void>((resolve) => { |
| iframe.onload = () => resolve(); |
| iframe.srcdoc = html; |
| }); |
|
|
| |
| await new Promise(r => setTimeout(r, 1500)); |
|
|
| return await captureIframeScreenshot(iframe, 1280, 720, 640, 360, 0.8, false); |
| } finally { |
| if (iframe.parentElement) document.body.removeChild(iframe); |
| server.cleanupBlobUrls(); |
| } |
| } |
|
|