Spaces:
Sleeping
Sleeping
File size: 1,685 Bytes
43370b3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import { spawn } from 'node:child_process'
import { promises as fs } from 'node:fs'
import os from 'node:os'
import path from 'node:path'
export type ExportFormat = 'pdf' | 'pptx' | 'html'
export const MIME: Record<ExportFormat, string> = {
pdf: 'application/pdf',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
html: 'text/html',
}
/**
* Render markdown to a file with marp-cli. PDF/PPTX need headless Chrome (provided in
* the Docker image via CHROME_PATH + CHROME_NO_SANDBOX); HTML needs nothing.
*/
export async function exportDeck(markdown: string, format: ExportFormat): Promise<Buffer> {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'marp-'))
const input = path.join(dir, 'deck.md')
const output = path.join(dir, `deck.${format}`)
await fs.writeFile(input, markdown, 'utf8')
try {
const args = [input, '-o', output, '--allow-local-files']
if (format === 'pdf') args.push('--pdf')
else if (format === 'pptx') args.push('--pptx')
// html is inferred from the .html output extension
await runMarp(args)
return await fs.readFile(output)
} finally {
await fs.rm(dir, { recursive: true, force: true })
}
}
function runMarp(args: string[]): Promise<void> {
return new Promise((resolve, reject) => {
const bin = path.resolve('node_modules/.bin/marp')
const child = spawn(bin, args, { stdio: ['ignore', 'ignore', 'pipe'] })
let err = ''
child.stderr.on('data', (d) => {
err += d.toString()
})
child.on('error', reject)
child.on('close', (code) =>
code === 0 ? resolve() : reject(new Error(`marp exited ${code}: ${err.slice(-600)}`)),
)
})
}
|