Files
margin/src/export/run.ts
T
pj 9eabef9041 feat(export): surface typst warnings and glyph-coverage notice
Typst compile warnings were discarded. Capture them via the Warned
result and emit a pdf-warnings event (only from the export path, not
the live preview) that App shows as a non-fatal toast; the export still
succeeds. Also scan book text before reporting success and warn when it
contains scripts the embedded Latin fonts cannot render (CJK, Arabic,
Hebrew, Devanagari, Thai, emoji).

Claude-Session: https://claude.ai/code/session_01RzTWrLiy4zGuw2hZSQGamk
2026-06-22 13:28:16 -04:00

44 lines
1.3 KiB
TypeScript

import type { Book } from "../model/book";
import { exportEpub, exportPdf } from "./exporters";
import { unsupportedScripts } from "./typst";
import { useBook } from "../store/useBook";
import { isDesktop } from "../ipc";
const DESKTOP_ONLY =
'Export runs in the desktop app only — open the window from "pnpm tauri dev" (you are viewing the browser preview).';
const FORMATS: Record<string, { label: string; run: (book: Book) => Promise<void> }> = {
pdf: { label: "PDF", run: exportPdf },
epub: { label: "EPUB", run: exportEpub },
};
function nextPaint(): Promise<void> {
return new Promise((resolve) =>
requestAnimationFrame(() => requestAnimationFrame(() => resolve()))
);
}
export async function runExport(format: "pdf" | "epub"): Promise<void> {
const { book, setExporting, setNotice } = useBook.getState();
const { label, run } = FORMATS[format];
if (!isDesktop) {
setNotice(DESKTOP_ONLY);
return;
}
if (!book) return;
setExporting(label);
await nextPaint();
try {
await run(book);
if (format === "pdf") {
const scripts = unsupportedScripts(book);
if (scripts.length)
setNotice(`Some ${scripts.join(", ")} characters may not render — the PDF fonts cover Latin scripts only.`);
}
} catch (e) {
setNotice(`${label} export failed: ${e}`);
} finally {
setExporting(null);
}
}