/** * Code snapshot rendering & export utilities (CodeSnap-style). * * Flow: selected code text -> shiki re-render (reusing the AI highlighter * singleton) -> CodeSnap-like shell DOM (traffic lights / title / line * numbers / background) -> PNG export either to the system clipboard * (Tauri `writeImage`) or to a file (dialog + fs, with a browser-download * fallback for web mode). * * The rendered snapshot DOM is fully self-contained: it embeds its own * `` + `
` + bar + `
${body}
` + `
` ); } /** Convert a snapshot DOM element into a PNG data URL. */ export async function snapshotElementToPng(element: HTMLElement): Promise { const domtoimage = (await import("dom-to-image-more")).default; return domtoimage.toPng(element, { quality: 1, width: element.offsetWidth, height: element.offsetHeight, // Preserve text sharpness on high-DPI displays without letting a large // selected block allocate an unbounded export canvas. pixelRatio: Math.min(MAX_EXPORT_PIXEL_RATIO, Math.max(1, typeof window === "undefined" ? 1 : window.devicePixelRatio || 1)), }); } async function dataUrlToBlob(dataUrl: string): Promise { return await (await fetch(dataUrl)).blob(); } /** * Copy a PNG data URL to the system clipboard. Uses the Tauri * clipboard-manager `writeImage` on desktop and falls back to the Web * Clipboard API (`ClipboardItem`) for web mode. */ export async function copyPngDataUrlToClipboard(dataUrl: string): Promise { const blob = await dataUrlToBlob(dataUrl); if (isTauriRuntime()) { const { writeImage } = await import("@tauri-apps/plugin-clipboard-manager"); await writeImage(new Uint8Array(await blob.arrayBuffer())); return; } if (typeof ClipboardItem !== "undefined" && navigator.clipboard?.write) { await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]); return; } throw new Error("Clipboard image write is not supported in this environment"); } /** * Save a PNG data URL to a file. On desktop this opens the native save * dialog; on web it downloads the image. Returns false when the user * cancels the native save dialog. */ export async function savePngDataUrlToFile(dataUrl: string, defaultName: string): Promise { const blob = await dataUrlToBlob(dataUrl); if (isTauriRuntime()) { const { save } = await import("@tauri-apps/plugin-dialog"); const { writeFile } = await import("@tauri-apps/plugin-fs"); const path = await save({ defaultPath: defaultName, filters: [{ name: "PNG", extensions: ["png"] }], }); if (!path) return false; // Native write errors must reach the caller so the UI never claims the // user-selected path was saved when the filesystem rejected it. await writeFile(path, new Uint8Array(await blob.arrayBuffer())); return true; } const url = URL.createObjectURL(blob); try { const a = document.createElement("a"); a.href = url; a.download = defaultName; a.click(); } finally { URL.revokeObjectURL(url); } return true; }