新增通用 CSS 到 OOXML 翻译修复,统一字体、字距、精确行距、段落、列表、表格、引用、代码块与行内代码连续性,不引入按主题 ID 分支。 新增 MdTP Mono 并统一 Serif、Sans、Mono 三字体包的 Chromium 与 DOCX 使用链;字体声明、嵌入部件和 Word/WPS 实际采用均进入硬门禁。 重建封面整页及正文语义块视觉差分,14 套主题、纵横两个方向、五组页边距共 140 个真实场景全部通过,阻断失败和诊断失败均为零。 源码服务、Docker Web API 与实际安装 Desktop 的 red-briefing 导出均包含 5 个字体部件;Word/WPS 原生渲染和逐页复核通过。修复 Docker 构建上下文与运行层复用软链接,并完善 v0.6.1 版本、发行说明和发布归集。 验证:npm test(116 个文件、616 项测试)、npm run typecheck、npm run build、git diff --check 全部通过。Desktop 安装器与 ZIP、Docker v0.6.1 镜像已生成;Windows 产物仍为未签名内部发行。
107 lines
2.6 KiB
TypeScript
107 lines
2.6 KiB
TypeScript
import type {
|
|
DocxThemeTokenSet,
|
|
DocxThemeStyleCaptureAdapter
|
|
} from "@md-to-pdf/docx-theme-engine";
|
|
import {
|
|
DOCX_STYLE_SLOTS,
|
|
DocxThemeStyleSnapshotCache,
|
|
createDocxThemeStyleFingerprint,
|
|
normalizeDocxThemeMappingConfig,
|
|
resolveDocxThemeTokens,
|
|
type DocxThemeStyleSnapshot
|
|
} from "@md-to-pdf/docx-theme-engine";
|
|
import type { PreparedDocxExport } from "./application-service.js";
|
|
import { SHARED_HIGHLIGHT_CSS } from "@md-to-pdf/preview-engine";
|
|
|
|
export interface PreparedDocxThemeTokens {
|
|
tokens: DocxThemeTokenSet;
|
|
warnings: string[];
|
|
}
|
|
|
|
export interface DocxThemeTokenProvider {
|
|
prepare(
|
|
prepared: PreparedDocxExport,
|
|
signal?: AbortSignal
|
|
): Promise<PreparedDocxThemeTokens>;
|
|
}
|
|
|
|
function createExplicitSnapshot(
|
|
themeId: string,
|
|
themeFingerprint: string
|
|
): DocxThemeStyleSnapshot {
|
|
return {
|
|
schemaVersion: 1,
|
|
themeId,
|
|
themeFingerprint,
|
|
viewport: {
|
|
widthPx: 794,
|
|
heightPx: 1123,
|
|
deviceScaleFactor: 1
|
|
},
|
|
rootFontSizePx: 16,
|
|
slots: DOCX_STYLE_SLOTS.map(({ name }) => ({
|
|
slot: name,
|
|
matched: false
|
|
}))
|
|
};
|
|
}
|
|
|
|
export class DocxThemeTokenService
|
|
implements DocxThemeTokenProvider
|
|
{
|
|
private readonly snapshots: DocxThemeStyleSnapshotCache;
|
|
|
|
constructor(
|
|
private readonly adapter: DocxThemeStyleCaptureAdapter
|
|
) {
|
|
this.snapshots = new DocxThemeStyleSnapshotCache(adapter);
|
|
}
|
|
|
|
async prepare(
|
|
prepared: PreparedDocxExport,
|
|
signal?: AbortSignal
|
|
): Promise<PreparedDocxThemeTokens> {
|
|
signal?.throwIfAborted();
|
|
const config = normalizeDocxThemeMappingConfig(
|
|
prepared.theme.manifest
|
|
);
|
|
const themeFingerprint =
|
|
await createDocxThemeStyleFingerprint(
|
|
prepared.theme.manifest.id,
|
|
`${SHARED_HIGHLIGHT_CSS}\n${prepared.theme.css}`
|
|
);
|
|
signal?.throwIfAborted();
|
|
const snapshot =
|
|
config.mode === "explicit"
|
|
? createExplicitSnapshot(
|
|
prepared.theme.manifest.id,
|
|
themeFingerprint
|
|
)
|
|
: await this.snapshots.capture(
|
|
{
|
|
themeId: prepared.theme.manifest.id,
|
|
themeFingerprint,
|
|
themeCss: `${SHARED_HIGHLIGHT_CSS}\n${prepared.theme.css}`,
|
|
baseUrl: this.adapter.themeStyleBaseUrl
|
|
},
|
|
signal
|
|
);
|
|
const tokens = resolveDocxThemeTokens({
|
|
snapshot,
|
|
config
|
|
});
|
|
return {
|
|
tokens,
|
|
warnings: tokens.diagnostics
|
|
.filter(
|
|
(diagnostic) => diagnostic.severity !== "info"
|
|
)
|
|
.map((diagnostic) => diagnostic.message)
|
|
};
|
|
}
|
|
|
|
invalidate(themeId?: string) {
|
|
this.snapshots.invalidate(themeId);
|
|
}
|
|
}
|