import { RefObject } from 'preact' import { assert } from './assert' const head = `<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">` const notFound = 'svg element not found' function getSVGOuterHTML(view: RefObject<HTMLDivElement>) { const svgElement = view.current?.querySelector('svg') assert(svgElement, notFound) const outerHTML = svgElement.outerHTML.replace(/ /g, ' ') return { svgElement, outerHTML, } } /** * generate svg content * @param view * @returns * @example * const { content } = toSVG(instance.current.view) * download(content, 'remind.svg') */ function toSVG(view: RefObject<HTMLDivElement>): { content: string } & DOMRect { const { svgElement, outerHTML } = getSVGOuterHTML(view) const svg = URL.createObjectURL(new Blob([head + outerHTML])) return { content: svg, ...svgElement.getBBox(), } } /** * generate PNG content * @param view * @returns * @example * const content = await toPNG(instance.current.view) * download(content, 'remind.png') */ async function toPNG(view: RefObject<HTMLDivElement>): Promise<string> { return new Promise((resolve) => { const { svgElement, outerHTML } = getSVGOuterHTML(view) const { width, height } = svgElement.getBBox() const img = new Image() img.src = URL.createObjectURL( new Blob([outerHTML], { type: 'image/svg+xml;charset=utf-8' }), ) img.addEventListener('load', () => { const canvas = document.createElement('canvas') canvas.width = width canvas.height = height const ctx = canvas.getContext('2d') ctx?.drawImage(img, 0, 0, width, height) const imgURL = canvas.toDataURL() resolve(imgURL) canvas.remove() }) }) } function download(href: string, download: string) { const a = document.createElement('a') a.href = href a.download = download a.click() } export { toSVG, toPNG, download }