feat: 实现 Pandoc DOCX 转换服务

This commit is contained in:
SkyJourney
2026-07-30 15:05:50 +08:00
parent fa159d916f
commit bf43433d38
32 changed files with 2908 additions and 61 deletions
@@ -23,12 +23,15 @@ function createRenderScript(request: DocxMediaCaptureRequest) {
export async function captureDocxMediaWithElectronWebContents(
webContents: WebContents,
request: DocxMediaCaptureRequest
request: DocxMediaCaptureRequest,
signal?: AbortSignal
) {
signal?.throwIfAborted();
const plan = (await webContents.executeJavaScript(
createRenderScript(request),
true
)) as DocxMediaCapturePlan;
signal?.throwIfAborted();
const ownsDebugger = !webContents.debugger.isAttached();
if (ownsDebugger) {
webContents.debugger.attach("1.3");
@@ -37,6 +40,7 @@ export async function captureDocxMediaWithElectronWebContents(
try {
const captures = [];
for (const target of plan.targets) {
signal?.throwIfAborted();
const result = (await webContents.debugger.sendCommand(
"Page.captureScreenshot",
{
@@ -57,6 +61,7 @@ export async function captureDocxMediaWithElectronWebContents(
png: Buffer.from(result.data, "base64")
});
}
signal?.throwIfAborted();
return { plan, captures };
} finally {
if (ownsDebugger && webContents.debugger.isAttached()) {
@@ -70,10 +75,11 @@ export class ElectronDocxMediaCaptureAdapter
{
constructor(private readonly webContents: WebContents) {}
capture(request: DocxMediaCaptureRequest) {
capture(request: DocxMediaCaptureRequest, signal?: AbortSignal) {
return captureDocxMediaWithElectronWebContents(
this.webContents,
request
request,
signal
);
}
}
@@ -34,13 +34,17 @@ async function renderCapturePlan(
export async function captureDocxMediaWithPlaywrightPage(
page: Page,
request: DocxMediaCaptureRequest
request: DocxMediaCaptureRequest,
signal?: AbortSignal
) {
signal?.throwIfAborted();
const plan = await renderCapturePlan(page, request);
signal?.throwIfAborted();
const session = await page.context().newCDPSession(page);
try {
const captures = [];
for (const target of plan.targets) {
signal?.throwIfAborted();
const result = (await session.send("Page.captureScreenshot", {
format: "png",
fromSurface: true,
@@ -58,6 +62,7 @@ export async function captureDocxMediaWithPlaywrightPage(
png: Buffer.from(result.data, "base64")
});
}
signal?.throwIfAborted();
return { plan, captures };
} finally {
await session.detach();
@@ -69,7 +74,11 @@ export class PlaywrightDocxMediaCaptureAdapter
{
constructor(private readonly page: Page) {}
capture(request: DocxMediaCaptureRequest) {
return captureDocxMediaWithPlaywrightPage(this.page, request);
capture(request: DocxMediaCaptureRequest, signal?: AbortSignal) {
return captureDocxMediaWithPlaywrightPage(
this.page,
request,
signal
);
}
}