UNPKG

@css-doodle/cli

Version:

Command-line tool for css-doodle to preview and generate images/videos

128 lines (107 loc) 3.54 kB
import fs from 'node:fs/promises'; import crypto from 'node:crypto'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import process from 'node:process'; import { spawn } from 'node:child_process'; import puppeteer from 'puppeteer-core'; import { defaultAppArgs, previewServerPath } from '../static.js'; import { resolveBrowser } from '../browser.js'; import { log } from '../utils.js'; const SIZE = '600,628'; let isCleaningUp = false; function cleanup(serverProcess, tempFile) { if (isCleaningUp) return; isCleaningUp = true; if (serverProcess && !serverProcess.killed) { serverProcess.kill(); } if (tempFile) { fs.unlink(tempFile).catch(() => {}); } } export async function preview(sourceFile, title, options = {}) { const source = sourceFile; let tempFile = null; if (options.fromStdin) { tempFile = join(tmpdir(), crypto.randomUUID()); sourceFile = tempFile; try { await fs.writeFile(tempFile, source); } catch (_e) { log.error('failed to create temporary file for preview'); process.exit(1); } } const serverProcess = spawn('node', [previewServerPath, sourceFile], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'], }); // Ensure cleanup on parent exit const doCleanup = () => cleanup(serverProcess, tempFile); process.on('exit', doCleanup); process.on('SIGINT', doCleanup); process.on('SIGTERM', doCleanup); process.on('uncaughtException', (err) => { log.error(err.message); doCleanup(); process.exit(1); }); serverProcess.on('message', async (message) => { if (message.info) { console.log(message.info); } if (message.url) { const params = new URLSearchParams(); params.set('title', title); params.set('instance', crypto.randomUUID()); if (options.fullscreen) { params.set('fullscreen', '1'); } const args = [ `--window-size=${SIZE}`, `--app=${message.url}?${params.toString()}`, ]; if (options.fullscreen) { args.push('--start-fullscreen'); } if (options.showFpsCounter) { args.push('--show-fps-counter'); } if (options.showPaintRects) { args.push('--show-paint-rects'); } const executablePath = await resolveBrowser(options.quiet); const settings = { headless: false, waitForInitialPage: false, ignoreDefaultArgs: ['--enable-automation'], executablePath, args: [ ...args, ...defaultAppArgs, ], }; puppeteer.launch(settings) .catch((e) => { log.error(e.message); doCleanup(); process.exit(1); }); } if (message.exit) { doCleanup(); process.exit(0); } }); serverProcess.on('error', (e) => { log.error(`server process error: ${e.message}`); doCleanup(); process.exit(1); }); serverProcess.on('exit', (code) => { if (code !== 0) { log.error(`server process exited with code ${code}`); } doCleanup(); }); }