psslides/src/code-to-element.ts

48 lines
1.5 KiB
TypeScript

import { domToSvgDataUrl } from './dom-to-image'
export interface CodeToElementOptions {
title?: string
allowScripts?: boolean
styles?: string[]
}
export function codeToElement(
code: string,
options: CodeToElementOptions = {}
): HTMLIFrameElement {
const iframe = document.createElement('iframe')
const sandbox = new Set<string>(['allow-same-origin'])
if (options.allowScripts) {
sandbox.add('allow-scripts')
}
iframe.title = options.title ?? 'Rendered code'
iframe.setAttribute('sandbox', Array.from(sandbox).join(' '))
iframe.srcdoc = `<!doctype html><html><head><meta charset="UTF-8"><style>html,body{margin:0;min-height:100%;}</style>${(options.styles ?? []).join('\n')}</head><body>${code}</body></html>`
return iframe
}
export async function createCodeThumbnail(
code: string,
options: CodeToElementOptions = {}
): Promise<HTMLImageElement> {
const iframe = codeToElement(code, { title: 'Code thumbnail', ...options })
iframe.style.width = '640px'
iframe.style.height = '360px'
iframe.style.position = 'fixed'
iframe.style.left = '-10000px'
iframe.style.border = '0'
document.body.appendChild(iframe)
await new Promise<void>((resolve) => iframe.addEventListener('load', () => resolve(), { once: true }))
const content = iframe.contentDocument?.body
const thumbnail = document.createElement('img')
if (content) {
thumbnail.src = domToSvgDataUrl(content, { width: 640, height: 360 })
}
iframe.remove()
return thumbnail
}