Files
Momento/memento-note/lib/client/excalidraw-export-image.ts

60 lines
1.9 KiB
TypeScript

'use client'
import type { ExcalidrawElement } from '@excalidraw/excalidraw/element/types'
import type { BinaryFiles } from '@excalidraw/excalidraw/types'
/**
* Parses canvas JSON from DB — either a bare elements array or { elements, files }.
* Returns null for PPTX placeholders or invalid JSON.
*/
export function parseExcalidrawSceneFromCanvasData(
dataStr: string
): { elements: readonly ExcalidrawElement[]; files: BinaryFiles | null } | null {
if (!dataStr?.trim()) return null
try {
const parsed = JSON.parse(dataStr)
if (parsed && parsed.type === 'pptx') return null
if (Array.isArray(parsed)) {
return { elements: parsed as ExcalidrawElement[], files: null }
}
if (parsed?.elements && Array.isArray(parsed.elements)) {
const files =
parsed.files && typeof parsed.files === 'object' ? (parsed.files as BinaryFiles) : null
return { elements: parsed.elements as readonly ExcalidrawElement[], files }
}
} catch {
/* ignore */
}
return null
}
/**
* Renders Excali scene to PNG in the browser (uses Excalidraw export helpers).
*/
export async function exportExcalidrawSceneToPngBlob(dataStr: string): Promise<Blob | null> {
const scene = parseExcalidrawSceneFromCanvasData(dataStr)
if (!scene || scene.elements.length === 0) return null
const { exportToBlob, getNonDeletedElements, MIME_TYPES } = await import('@excalidraw/excalidraw')
const elements = getNonDeletedElements(scene.elements as ExcalidrawElement[])
if (!elements.length) return null
try {
return await exportToBlob({
elements,
files: scene.files,
mimeType: MIME_TYPES.png,
exportPadding: 24,
maxWidthOrHeight: 2400,
appState: {
exportBackground: true,
exportWithDarkMode: false,
viewBackgroundColor: '#ffffff',
},
})
} catch (e) {
console.error('[excalidraw-export-image] exportToBlob failed:', e)
return null
}
}