import type { WebContents } from "electron"; import type { DocxMediaCaptureAdapter, DocxMediaCaptureRequest } from "@md-to-pdf/application"; import type { DocxMediaCapturePlan } from "@md-to-pdf/core"; interface CaptureScreenshotResult { data: string; } function createRenderScript(request: DocxMediaCaptureRequest) { const serialized = JSON.stringify(request); return `(async () => { const request = ${serialized}; const renderer = window.__mdToPdfRenderDocxMedia; if (!renderer) { throw new Error("DOCX 媒体渲染运行时不可用"); } return renderer(request.payload, request.dimensions); })()`; } export async function captureDocxMediaWithElectronWebContents( webContents: WebContents, request: DocxMediaCaptureRequest, signal?: AbortSignal ) { signal?.throwIfAborted(); const plan = (await webContents.executeJavaScript( createRenderScript(request), true )) as DocxMediaCapturePlan; signal?.throwIfAborted(); const ownsDebugger = !webContents.debugger.isAttached(); if (ownsDebugger) { webContents.debugger.attach("1.3"); } try { const captures = []; for (const target of plan.targets) { signal?.throwIfAborted(); const result = (await webContents.debugger.sendCommand( "Page.captureScreenshot", { format: "png", fromSurface: true, captureBeyondViewport: true, clip: { x: target.captureX, y: target.captureY, width: target.captureWidthPx, height: target.captureHeightPx, scale: target.rasterScale } } )) as CaptureScreenshotResult; captures.push({ id: target.id, png: Buffer.from(result.data, "base64") }); } signal?.throwIfAborted(); return { plan, captures }; } finally { if (ownsDebugger && webContents.debugger.isAttached()) { webContents.debugger.detach(); } } } export class ElectronDocxMediaCaptureAdapter implements DocxMediaCaptureAdapter { constructor(private readonly webContents: WebContents) {} capture(request: DocxMediaCaptureRequest, signal?: AbortSignal) { return captureDocxMediaWithElectronWebContents( this.webContents, request, signal ); } }