feat: 实现 Web 与 Desktop DOCX 导出交互

This commit is contained in:
SkyJourney
2026-07-30 16:05:45 +08:00
parent bf43433d38
commit f2dfc6ef72
28 changed files with 2110 additions and 57 deletions
+1
View File
@@ -154,6 +154,7 @@ export const docxExportErrorCodeSchema = z.enum([
"INVALID_EXPORT_CONFIG",
"INVALID_FILE_NAME",
"INVALID_MARKDOWN",
"INVALID_FRONT_MATTER",
"MARKDOWN_TOO_LARGE",
"INVALID_IMAGE_RESOURCES",
"IMAGE_RESOURCES_TOO_LARGE",
+10 -8
View File
@@ -77,6 +77,7 @@ export interface PandocDocxConversionResult {
export interface PandocDocxConverterOptions {
runtime: PandocRuntimeProvider | PandocRuntime;
luaFilterUrl?: URL;
runner?: PandocProcessRunner;
environment?: NodeJS.ProcessEnv;
temporaryRoot?: string;
@@ -102,13 +103,6 @@ export class PandocDocxConversionError extends Error {
}
}
let luaFilterContent: Promise<Uint8Array> | undefined;
function loadLuaFilter() {
luaFilterContent ??= readFile(luaFilterUrl);
return luaFilterContent;
}
function ensureOutputLimit(value: number | undefined) {
const limit = value ?? MAXIMUM_DOCX_OUTPUT_BYTES;
if (
@@ -179,6 +173,7 @@ function pandocArguments(paths: {
}
export class PandocDocxConverter {
private luaFilterContent: Promise<Uint8Array> | undefined;
private readonly runner: PandocProcessRunner;
private readonly timeoutMs: number;
private readonly maximumOutputBytes: number;
@@ -205,6 +200,13 @@ export class PandocDocxConverter {
}
}
private loadLuaFilter() {
this.luaFilterContent ??= readFile(
this.options.luaFilterUrl ?? luaFilterUrl
);
return this.luaFilterContent;
}
async convert(
input: PandocDocxConversionInput,
signal?: AbortSignal
@@ -232,7 +234,7 @@ export class PandocDocxConverter {
await Promise.all([
this.options.runtime.getExecutablePath(),
this.options.runtime.getDefaultReferenceDocx(),
loadLuaFilter()
this.loadLuaFilter()
]);
const reference = this.getOrCreateReference(baseline, input);
const referenceMs = performance.now() - referenceStarted;