import { getPage, readLinksBulk, getProject } from "../scrapbox-userscript-std/rest.ts"; import { Page, UnixTime } from "../scrapbox-jp%2Ftypes/rest.ts"; import { useStatusBar } from "../scrapbox-userscript-std/mod.ts"; import { pool, Result, sort } from "../async-lib/mod.ts"; export type ExportPage = Pick; export interface ExportData { name: string; displayName: string; exported: UnixTime; pages: ExportPage[]; } export const createExport = async ( project: string, threshold = 100, ): Promise => { const { render, dispose } = useStatusBar(); render( { type: "spinner"}, { type: "text", text: `Loading pages from "${project}"` }, ); try { const result = await getProject(project); if (!result.ok) throw result.value; const { name, displayName } = result.value; const reader = await readLinksBulk(project); if ("name" in reader) throw reader; const pages: ExportPage[] = []; const { render, dispose } = useStatusBar(); try { for await (const titles of reader) { const reader = sort([...pool( threshold, titles, async (page) => { const result = await getPage(project, page.title); if (!result.ok) { console.error(result.value); throw result.value; } const { id, title, created, updated, lines } = result.value; pages.push({ id, title, created, updated, lines }); return `[${pages.length}] ${title}`; }, )]); let animationId: number | undefined; for await (const result of reader) { if (!result.success) continue; if (animationId !== undefined) cancelAnimationFrame(animationId); animationId = requestAnimationFrame( () => render({ type: "text", text: result.value }) ); } } } finally { dispose(); } const exported = (new Date()).getTime() / 1000; render( { type: "check-circle" }, { type: "text", text: `Exported ${pages.length} pages from /${name}`} ); return { name, displayName, exported, pages }; } catch(e) { render( { type: "exclamation-triangle" }, { type: "text", text: typeof e === "object" && "name" in e && "message" in e ? `${e.name} ${e.message}` : "Unexpected error! (see developer console)", }, ); throw e; } finally { setTimeout(() => dispose(), 1000); } };