feat: 实现 DOCX 主题样式采集
This commit is contained in:
@@ -3,7 +3,12 @@ import type {
|
||||
DocxMediaCaptureAdapter,
|
||||
DocxMediaCaptureRequest
|
||||
} from "@md-to-pdf/application";
|
||||
import type {
|
||||
DocxThemeStyleCaptureAdapter,
|
||||
DocxThemeStyleCaptureRequest
|
||||
} from "@md-to-pdf/docx-theme-engine";
|
||||
import { captureDocxMediaWithElectronWebContents } from "./electron-docx-media-capture.js";
|
||||
import { captureDocxThemeStyleWithElectronWebContents } from "./electron-docx-theme-style.js";
|
||||
import { isAllowedPdfRuntimeUrl } from "./pdf-contract.js";
|
||||
|
||||
export const DESKTOP_DOCX_PARTITION =
|
||||
@@ -14,7 +19,7 @@ export interface ElectronDocxMediaEngineOptions {
|
||||
}
|
||||
|
||||
export class ElectronDocxMediaEngine
|
||||
implements DocxMediaCaptureAdapter
|
||||
implements DocxMediaCaptureAdapter, DocxThemeStyleCaptureAdapter
|
||||
{
|
||||
private readonly renderUrl: string;
|
||||
private windowPromise: Promise<BrowserWindow> | undefined;
|
||||
@@ -42,6 +47,23 @@ export class ElectronDocxMediaEngine
|
||||
return operation;
|
||||
}
|
||||
|
||||
captureThemeStyle(
|
||||
request: DocxThemeStyleCaptureRequest,
|
||||
signal?: AbortSignal
|
||||
) {
|
||||
if (this.closed) {
|
||||
return Promise.reject(new Error("桌面 DOCX 媒体引擎已关闭"));
|
||||
}
|
||||
const operation = this.queue.then(() =>
|
||||
this.captureThemeStyleNow(request, signal)
|
||||
);
|
||||
this.queue = operation.then(
|
||||
() => undefined,
|
||||
() => undefined
|
||||
);
|
||||
return operation;
|
||||
}
|
||||
|
||||
async close() {
|
||||
this.closed = true;
|
||||
await this.queue;
|
||||
@@ -84,6 +106,36 @@ export class ElectronDocxMediaEngine
|
||||
}
|
||||
}
|
||||
|
||||
private async captureThemeStyleNow(
|
||||
request: DocxThemeStyleCaptureRequest,
|
||||
signal?: AbortSignal
|
||||
) {
|
||||
signal?.throwIfAborted();
|
||||
if (
|
||||
new URL(request.baseUrl).origin !==
|
||||
new URL(this.renderUrl).origin
|
||||
) {
|
||||
throw new Error("桌面 DOCX 主题资源地址必须与渲染地址同源");
|
||||
}
|
||||
const window = await this.getWindow();
|
||||
signal?.throwIfAborted();
|
||||
const abort = () => {
|
||||
if (!window.isDestroyed()) {
|
||||
window.destroy();
|
||||
}
|
||||
};
|
||||
signal?.addEventListener("abort", abort, { once: true });
|
||||
try {
|
||||
return await captureDocxThemeStyleWithElectronWebContents(
|
||||
window.webContents,
|
||||
request,
|
||||
signal
|
||||
);
|
||||
} finally {
|
||||
signal?.removeEventListener("abort", abort);
|
||||
}
|
||||
}
|
||||
|
||||
private getWindow() {
|
||||
if (!this.windowPromise) {
|
||||
this.windowPromise = this.createWindow().catch((error) => {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
createDocxThemeStyleCaptureScript,
|
||||
parseDocxThemeStyleRuntimeCapture,
|
||||
type DocxThemeStyleCaptureRequest,
|
||||
type DocxThemeStyleSnapshot
|
||||
} from "@md-to-pdf/docx-theme-engine";
|
||||
import type { WebContents } from "electron";
|
||||
|
||||
export async function captureDocxThemeStyleWithElectronWebContents(
|
||||
webContents: WebContents,
|
||||
request: DocxThemeStyleCaptureRequest,
|
||||
signal?: AbortSignal
|
||||
): Promise<DocxThemeStyleSnapshot> {
|
||||
signal?.throwIfAborted();
|
||||
const ownsDebugger = !webContents.debugger.isAttached();
|
||||
if (ownsDebugger) {
|
||||
webContents.debugger.attach("1.3");
|
||||
}
|
||||
try {
|
||||
await webContents.debugger.sendCommand(
|
||||
"Emulation.setEmulatedMedia",
|
||||
{ media: "print" }
|
||||
);
|
||||
const capture = await webContents.executeJavaScript(
|
||||
createDocxThemeStyleCaptureScript(request),
|
||||
true
|
||||
);
|
||||
signal?.throwIfAborted();
|
||||
return parseDocxThemeStyleRuntimeCapture(request, capture);
|
||||
} finally {
|
||||
if (
|
||||
!webContents.isDestroyed() &&
|
||||
webContents.debugger.isAttached()
|
||||
) {
|
||||
await webContents.debugger
|
||||
.sendCommand("Emulation.setEmulatedMedia", {
|
||||
media: "screen"
|
||||
})
|
||||
.catch(() => undefined);
|
||||
if (ownsDebugger && webContents.debugger.isAttached()) {
|
||||
webContents.debugger.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user