mirror of https://github.com/VERT-sh/VERT.git
97 lines
2.4 KiB
TypeScript
97 lines
2.4 KiB
TypeScript
import { VertFile } from "$lib/types";
|
|
import { Converter, FormatInfo } from "./converter.svelte";
|
|
import { browser } from "$app/environment";
|
|
import PandocWorker from "$lib/workers/pandoc?worker&url";
|
|
|
|
export class PandocConverter extends Converter {
|
|
public name = "pandoc";
|
|
public ready = $state(false);
|
|
public wasm: ArrayBuffer = null!;
|
|
|
|
constructor() {
|
|
super();
|
|
if (!browser) return;
|
|
(async () => {
|
|
this.wasm = await fetch("/pandoc.wasm").then((r) =>
|
|
r.arrayBuffer(),
|
|
);
|
|
this.ready = true;
|
|
})();
|
|
}
|
|
|
|
public async convert(input: VertFile, to: string): Promise<VertFile> {
|
|
const worker = new Worker(PandocWorker, {
|
|
type: "module",
|
|
});
|
|
worker.postMessage({ type: "load", wasm: this.wasm });
|
|
await waitForMessage(worker, "loaded");
|
|
worker.postMessage({
|
|
type: "convert",
|
|
to,
|
|
file: input.file,
|
|
});
|
|
const result = await waitForMessage(worker);
|
|
if (result.type === "error") {
|
|
worker.terminate();
|
|
// throw new Error(result.error);
|
|
switch (result.errorKind) {
|
|
case "PandocUnknownReaderError": {
|
|
throw new Error(
|
|
`${input.from} is not a supported input format for documents.`,
|
|
);
|
|
}
|
|
|
|
case "PandocUnknownWriterError": {
|
|
throw new Error(
|
|
`${to} is not a supported output format for documents.`,
|
|
);
|
|
}
|
|
|
|
default:
|
|
if (result.errorKind)
|
|
throw new Error(
|
|
`[${result.errorKind}] ${result.error}`,
|
|
);
|
|
else throw new Error(result.error);
|
|
}
|
|
}
|
|
worker.terminate();
|
|
if (!to.startsWith(".")) to = `.${to}`;
|
|
return new VertFile(
|
|
new File([result.output], input.name),
|
|
result.isZip ? ".zip" : to,
|
|
);
|
|
}
|
|
|
|
public supportedFormats = [
|
|
new FormatInfo("docx"),
|
|
new FormatInfo("doc"),
|
|
new FormatInfo("md"),
|
|
new FormatInfo("html"),
|
|
new FormatInfo("rtf"),
|
|
new FormatInfo("csv"),
|
|
new FormatInfo("tsv"),
|
|
new FormatInfo("json"),
|
|
new FormatInfo("rst"),
|
|
new FormatInfo("epub"),
|
|
new FormatInfo("odt"),
|
|
new FormatInfo("docbook"),
|
|
];
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
function waitForMessage(worker: Worker, type?: string): Promise<any> {
|
|
return new Promise((resolve) => {
|
|
const onMessage = (e: MessageEvent) => {
|
|
if (type && e.data.type === type) {
|
|
worker.removeEventListener("message", onMessage);
|
|
resolve(e.data);
|
|
} else {
|
|
worker.removeEventListener("message", onMessage);
|
|
resolve(e.data);
|
|
}
|
|
};
|
|
worker.addEventListener("message", onMessage);
|
|
});
|
|
}
|