mod.tsimport { 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<Page, "id" | "title" | "created" | "updated" | "lines">;
export interface ExportData {
name: string;
displayName: string;
exported: UnixTime;
pages: ExportPage[];
}
export const createExport = async (
project: string,
threshold = 100,
): Promise<ExportData> => {
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);
}
};