release: 发布字体直接内置版 v0.6.1

新增能力:14 套主题按纵横方向与五组页边距组成的 140 场景视觉矩阵全部通过,封面执行整页严格门禁,正文执行分页无关的语义块门禁。

问题修复:统一 CSS 到 WordprocessingML 的通用翻译,修复字体嵌入、中文标点字距、精确行距、打印媒体与行内代码连续性,不包含按主题 ID 的特调。

发行变化:Desktop 安装器与免安装 ZIP 直接内置 Serif、Sans、Mono 三套字体包;NSIS 移除字体选择和伴随安装逻辑,不再发布独立字体安装器或字体 ZIP。正式附件收敛为 Desktop 安装器、Desktop ZIP、Docker 离线镜像、Web 部署包和发行说明。

部署兼容:Docker 镜像 md-to-pdf:v0.6.1 使用完整无缓存路径构建,固定 Chromium、Pandoc 3.9.0.2 和三套内置字体包;支持覆盖安装 v0.6.0,Windows 安装器保持未签名的内部发布状态。

验证结果:116 个测试文件、616 项测试、全项目类型检查、生产构建和 git diff --check 全部通过;140/140 视觉矩阵阻断失败和诊断失败均为 0;源码服务、Docker Web API 与实际安装 Desktop 的 DOCX 字体嵌入链路均通过。
This commit is contained in:
SkyJourney
2026-08-04 12:25:02 +08:00
parent f93abf064f
commit 01b06abc2c
11 changed files with 47 additions and 140 deletions
+4
View File
@@ -62,6 +62,10 @@ npm run verify:pandoc-runtime -w @md-to-pdf/desktop
辅助包;当前未配置代码签名,Windows 首次运行可能显示“未知发布者”
提示。
Serif、Sans、Mono 三套正式字体随 NSIS 安装包和便携 ZIP 直接进入
`resources/font-packs`,由应用私有加载,不写入 Windows 系统字体目录。
安装向导不再提供字体选择页,正式发行也不附带独立字体安装器或字体 ZIP。
NSIS 使用标准辅助安装模式,支持选择当前用户/所有用户安装和自定义安装
目录,并创建桌面及开始菜单快捷方式。正式安装包作为 Gitea Release 附件
发布,不提交进 Git 历史。
-82
View File
@@ -9,70 +9,6 @@
; 独立键可让 v0.6.0 默认进入 MorphDoc 目录,同时仍由相同卸载身份识别旧版。
!define INSTALL_REGISTRY_KEY "Software\${APP_GUID}.MorphDoc"
!ifdef FONT_PACK_COMPANION_FILE
!ifndef BUILD_UNINSTALLER
!include "FileFunc.nsh"
!include "nsDialogs.nsh"
Var fontPackCompanionAvailable
Var fontPackCompanionCheckbox
Var fontPackCompanionExitCode
Var fontPackCompanionHash
Var fontPackCompanionPath
Var fontPackCompanionSelected
!macro customInit
StrCpy $fontPackCompanionAvailable "0"
StrCpy $fontPackCompanionSelected "0"
StrCpy $fontPackCompanionPath "$EXEDIR\${FONT_PACK_COMPANION_FILE}"
IfFileExists "$fontPackCompanionPath" 0 font_pack_init_done
${StdUtils.HashFile} $fontPackCompanionHash "SHA2-256" "$fontPackCompanionPath"
StrCmp $fontPackCompanionHash "${FONT_PACK_COMPANION_SHA256}" 0 font_pack_init_done
StrCpy $fontPackCompanionAvailable "1"
IfSilent font_pack_silent font_pack_interactive
font_pack_interactive:
StrCpy $fontPackCompanionSelected "1"
Goto font_pack_init_done
font_pack_silent:
${GetParameters} $R0
${GetOptions} $R0 "/WITHFONTPACK=" $R1
StrCmp $R1 "1" 0 font_pack_init_done
StrCpy $fontPackCompanionSelected "1"
font_pack_init_done:
!macroend
Function FontPackCompanionPage
StrCmp $fontPackCompanionAvailable "1" 0 font_pack_page_skip
nsDialogs::Create 1018
Pop $R0
StrCmp $R0 "error" 0 +2
Abort
${NSD_CreateLabel} 0 0 100% 28u "检测到经过完整性校验的墨呈可选字体包。安装后,政企公文主题可使用与 PDF 相同的原生中文字体资产。"
Pop $R0
${NSD_CreateCheckbox} 0 38u 100% 14u "安装 ${FONT_PACK_COMPANION_NAME}"
Pop $fontPackCompanionCheckbox
${NSD_Check} $fontPackCompanionCheckbox
nsDialogs::Show
Return
font_pack_page_skip:
Abort
FunctionEnd
Function FontPackCompanionPageLeave
${NSD_GetState} $fontPackCompanionCheckbox $R0
StrCmp $R0 ${BST_CHECKED} 0 font_pack_page_unchecked
StrCpy $fontPackCompanionSelected "1"
Return
font_pack_page_unchecked:
StrCpy $fontPackCompanionSelected "0"
FunctionEnd
!macro customPageAfterChangeDir
Page custom FontPackCompanionPage FontPackCompanionPageLeave
!macroend
!endif
!endif
!macro customInstall
DeleteRegKey SHCTX "${MORPHDOC_LEGACY_INSTALL_REGISTRY_KEY}"
WriteRegStr SHCTX \
@@ -124,24 +60,6 @@
"" \
"$INSTDIR\${MORPHDOC_EXECUTABLE}"
StrCpy $launchLink "$INSTDIR\${MORPHDOC_EXECUTABLE}"
!ifdef FONT_PACK_COMPANION_FILE
StrCmp $fontPackCompanionAvailable "1" 0 font_pack_install_done
StrCmp $fontPackCompanionSelected "1" 0 font_pack_install_done
${StdUtils.HashFile} $fontPackCompanionHash "SHA2-256" "$fontPackCompanionPath"
StrCmp $fontPackCompanionHash "${FONT_PACK_COMPANION_SHA256}" 0 font_pack_integrity_failed
DetailPrint "正在安装可选字体包:${FONT_PACK_COMPANION_NAME}"
ExecWait '"$fontPackCompanionPath" /S' $fontPackCompanionExitCode
StrCmp $fontPackCompanionExitCode "0" font_pack_install_done
DetailPrint "可选字体包安装失败,退出码:$fontPackCompanionExitCode"
IfSilent font_pack_install_done 0
MessageBox MB_ICONEXCLAMATION|MB_OK "主程序已安装,但可选字体包安装失败(退出码 $fontPackCompanionExitCode)。您可以稍后单独运行字体包安装器。"
Goto font_pack_install_done
font_pack_integrity_failed:
DetailPrint "可选字体包完整性复核失败,已跳过安装。"
IfSilent font_pack_install_done 0
MessageBox MB_ICONEXCLAMATION|MB_OK "可选字体包完整性复核失败,主程序已安装,但字体包已跳过。"
font_pack_install_done:
!endif
System::Call 'shell32::SHChangeNotify(i 0x08000000, i 0, i 0, i 0)'
!macroend
+13 -2
View File
@@ -74,6 +74,10 @@ describe("桌面发行构建链", () => {
expect(rootManifest.scripts?.["desktop:package"]).toBe(
"npm run build:font-pack && npm run package -w @md-to-pdf/desktop"
);
expect(rootManifest.scripts?.["desktop:make"]).toBe(
"npm run build:font-pack && node scripts/build-desktop-release.mjs"
);
expect(rootManifest.scripts?.["desktop:make:with-font-pack"]).toBeUndefined();
});
it("将固定 Pandoc 最小运行时作为 Desktop 独立资源打包", () => {
@@ -190,7 +194,11 @@ describe("桌面发行构建链", () => {
"utf8"
);
const bundledBuild = readFileSync(
`${projectRoot}/scripts/build-desktop-with-font-pack.mjs`,
`${projectRoot}/scripts/build-desktop-release.mjs`,
"utf8"
);
const installerInclude = readFileSync(
`${desktopRoot}/build/installer.nsh`,
"utf8"
);
@@ -201,7 +209,10 @@ describe("桌面发行构建链", () => {
);
expect(desktopMain).toContain("getDesktopUserFontPackDirectory()");
expect(bundledBuild).not.toContain("createDesktopCompanionInclude");
expect(bundledBuild).toContain("已生成内置字体包");
expect(bundledBuild).toContain("已生成字体直接内置");
expect(installerInclude).not.toContain("FONT_PACK_COMPANION");
expect(installerInclude).not.toContain("FontPackCompanionPage");
expect(installerInclude).not.toContain("/WITHFONTPACK=");
});
it("将 DOCX Lua Filter 复制到桌面主进程资源目录", () => {
+11 -7
View File
@@ -1522,13 +1522,17 @@ ECharts 第二阶段浏览器与 PDF 验证结果:
使用同一 `red-briefing` 复验,三份 DOCX 均约 24.17 MB、包含 5 个字体
部件和 40,731,432 字节嵌入字体;安装版产物经 Word/WPS 渲染均为 2 页
A4,逐页视觉通过;
- 阶段 F:已完成。发布提交为 `2c5c1bd`annotated tag 为 `v0.6.1`
`release/v0.6.1` 已归集 Desktop 安装器与 ZIP、字体安装器与 ZIP、
Docker 离线镜像、Web 部署包、发行说明、机器清单和 SHA-256 校验文件。
8 项校验和全部通过;799,432,994 字节的离线镜像归档经 `docker load`
重新导入后内容 ID 保持
`sha256:1f901fd481ca078d62d22f975691373a160c716e3bfed05721d0704ae5098696`
临时容器首页、健康接口、14 主题及 Pandoc 3.9.0.2 capability 均通过
- 阶段 F:已完成最终发行重构。Desktop 的 Serif、Sans、Mono 三套字体包
直接内置于安装器和免安装 ZIP,NSIS 不再显示字体选择页,正式发行不再
拆分字体安装器或字体 ZIP。正式安装包为 185,578,422 字节,免安装 ZIP
为 242,513,118 字节;安装版默认媒体示例真实导出 10,931,974 字节的
DOCX,包含 7 个字体部件和 12 个媒体部件。Docker 使用 `--pull`
`--no-cache` 且禁用运行层复用的完整路径正式构建,镜像内容 ID 为
`sha256:f81dbce5857a0a5496851e149936d1fd7da52b76c035187be1079fa1fd5a4717`
`release/v0.6.1` 只归集 Desktop 安装器与 ZIP、Docker 离线镜像、Web
部署包和发行说明五个主附件,并生成机器清单与包含六项的 SHA-256 校验
文件;发布引用由本轮 `release:` 提交和重新创建的 annotated `v0.6.1`
标签统一指向最终发行状态。
每个阶段验收通过后创建一个独立提交,再进入下一阶段。当前阶段不得混入
后续阶段的功能实现。
+3 -4
View File
@@ -24,8 +24,6 @@ release/v<semver>/
release/v<version>/
├── MorphDoc-<version>-x86_64-Setup.exe
├── MorphDoc-<version>-x86_64.zip
├── MorphDoc-FontPack-<id>-<font-version>-x86_64-Setup.exe
├── MorphDoc-FontPack-<id>-<font-version>.zip
├── MorphDoc-Web-<version>-image.tar.gz
├── MorphDoc-Web-<version>-deploy.zip
├── manifest.json
@@ -54,7 +52,7 @@ TTF、OTF、WOFF 和 WOFF2 必须由 Git LFS 跟踪。新增或升级字体前
## 发版步骤
1. 完成全量测试、类型检查、生产构建和视觉门禁。
2. 构建 Desktop 安装包便携 ZIP 和字体附件
2. 构建字体直接内置的 Desktop 安装包便携 ZIP。
3. 构建并验证版本化 Docker 镜像。
4. 准备 `docs/releases/v<version>.md`
5. 执行:
@@ -65,7 +63,8 @@ TTF、OTF、WOFF 和 WOFF2 必须由 Git LFS 跟踪。新增或升级字体前
6. 逐项核验 `SHA256SUMS.txt`,并从离线归档重新加载 Docker 镜像。
7. 创建内容完整的 `release:` 提交。
8. 创建 annotated `v<version>` 标签,标签说明与发布提交正文一致
8. 重新生成 release 清单,确保 `gitCommit` 指向该发布提交
9. 创建 annotated `v<version>` 标签,标签说明与发布提交正文一致。
安装器公开分发前应完成 Authenticode 签名;未签名产物只能按内部发布风险
规则分发。
+8 -2
View File
@@ -34,16 +34,22 @@
部件,嵌入字体字节数为 40,731,432。
- 已安装 Desktop 产物经真实 Word 和 WPS 渲染均为 2 页 A4,独立封面及
正文逐页复核通过。
- 正式安装包覆盖安装后,默认 10 页媒体示例从实际 Desktop 窗口导出
10,931,974 字节的 DOCX,包含 7 个字体部件和 12 个媒体部件;字体部件
解压后共 11,190,728 字节,确认安装版直接使用随程序内置的字体资源。
- Docker 镜像内置三套字体包与 Pandoc 3.9.0.2;修复复用运行层时 Pandoc
软链接已存在导致构建失败的问题,并通过根级 `.dockerignore` 固定精简
构建上下文。
构建上下文。正式镜像已使用 `--pull --no-cache` 和禁用运行层复用的完整
路径重新构建并通过生产门禁。
- 全项目测试、类型检查、生产构建及 `git diff --check` 通过。
## 发行与兼容性
- Desktop 安装器和免安装 ZIP 版本均为 0.6.1;支持覆盖 v0.6.0 安装。
- Serif、Sans、Mono 三套字体直接内置于 Desktop 安装器和免安装 ZIP
不写入系统字体目录;安装过程不再显示字体选择,也不再发布独立字体附件。
- Docker 发布镜像为 `md-to-pdf:v0.6.1`,内容 ID 为
`sha256:1f901fd481ca078d62d22f975691373a160c716e3bfed05721d0704ae5098696`
`sha256:f81dbce5857a0a5496851e149936d1fd7da52b76c035187be1079fa1fd5a4717`
- DOCX 保持原生可编辑段落、Run、列表和表格结构,没有以整页图片替代正文。
- 当前 Windows 安装器未进行 Authenticode 签名,适用于公司内部发布;
公开网络分发前建议增加代码签名。
+3 -2
View File
@@ -78,13 +78,14 @@ Cascadia、Consolas、SFMono、Menlo、Monaco 与 Courier 等候选名称。
组合构建命令为:
```powershell
npm run desktop:make:with-font-pack
npm run desktop:make
```
该命令先重建完整字体包集合,再构建主安装器和便携 ZIP。electron-builder
`output/font-packs/root` 复制到 `resources/font-packs`Desktop 生产
运行时优先读取该只读内置根目录,再读取用户目录中的额外字体包。内置包
因此不会被缺失、旧版或同 ID 用户包替换。
因此不会被缺失、旧版或同 ID 用户包替换。NSIS 不安装系统字体、不显示
字体选择页,正式发行也不再拆分独立字体安装器或字体 ZIP。
## Docker 内置发行
+1 -1
View File
@@ -29,7 +29,7 @@
"build:font-pack": "npm run build -w @md-to-pdf/core && npm run build -w @md-to-pdf/docx-theme-engine && npm run build -w @md-to-pdf/font-pack-registry && npm run build -w @md-to-pdf/docx-engine && npm run build -w @md-to-pdf/font-pack-builder && node scripts/build-font-packs.mjs",
"verify:font-pack": "npm run build:font-pack",
"verify:docker-font-pack": "npm run verify:font-pack && npm run build:web-runtime && npm run build -w @md-to-pdf/server && node deploy/verify-font-pack-compose.mjs",
"desktop:make:with-font-pack": "npm run build:font-pack && node scripts/build-desktop-with-font-pack.mjs",
"desktop:make": "npm run build:font-pack && node scripts/build-desktop-release.mjs",
"release:stage": "node scripts/stage-release.mjs",
"test:release-stage": "node --test scripts/stage-release.test.mjs",
"test:docx-layout-visual-matrix-cases": "node --test scripts/docx-layout-visual-matrix-cases.test.mjs",
@@ -37,5 +37,5 @@ await new Promise((resolvePromise, reject) => {
});
process.stdout.write(
`已生成内置字体包的主安装器与便携 ZIP${join(desktopRoot, "out", `v${desktopManifest.version}`)}\n`
`已生成字体直接内置的主安装器与便携 ZIP${join(desktopRoot, "out", `v${desktopManifest.version}`)}\n`
);
-29
View File
@@ -186,28 +186,6 @@ export async function stageRelease(options = {}) {
`MorphDoc-${version}-x86_64-Setup.exe`,
`MorphDoc-${version}-x86_64.zip`
];
const fontPackArtifacts = [
{
name: "MorphDoc-FontPack-mdtp-serif-sc-1.0.0-x86_64-Setup.exe",
source: join(
repositoryRoot,
"output",
"font-packs",
"windows",
"MorphDoc-FontPack-mdtp-serif-sc-1.0.0-x86_64-Setup.exe"
)
},
{
name: "MorphDoc-FontPack-mdtp-serif-sc-1.0.0.zip",
source: join(
repositoryRoot,
"output",
"font-packs",
"release",
"MorphDoc-FontPack-mdtp-serif-sc-1.0.0.zip"
)
}
];
const releaseNotesSource = join(
repositoryRoot,
"docs",
@@ -217,9 +195,6 @@ export async function stageRelease(options = {}) {
for (const name of desktopNames) {
await assertReadableFile(join(desktopDirectory, name));
}
for (const artifact of fontPackArtifacts) {
await assertReadableFile(artifact.source);
}
await assertReadableFile(releaseNotesSource);
await mkdir(stageDirectory, { recursive: true });
@@ -227,9 +202,6 @@ export async function stageRelease(options = {}) {
for (const name of desktopNames) {
await copyFile(join(desktopDirectory, name), join(stageDirectory, name));
}
for (const artifact of fontPackArtifacts) {
await copyFile(artifact.source, join(stageDirectory, artifact.name));
}
await copyFile(releaseNotesSource, join(stageDirectory, "RELEASE-NOTES.md"));
const deployName = `MorphDoc-Web-${version}-deploy.zip`;
@@ -249,7 +221,6 @@ export async function stageRelease(options = {}) {
const primaryNames = [
...desktopNames,
...fontPackArtifacts.map((artifact) => artifact.name),
imageName,
deployName,
"RELEASE-NOTES.md"
+3 -10
View File
@@ -61,14 +61,7 @@ test("Web 离线部署 ZIP 包含 Compose 和导入说明", async () => {
}
});
test("正式发布强制归集独立字体安装器和 ZIP", () => {
assert.match(
stageReleaseSource,
/MorphDoc-FontPack-mdtp-serif-sc-1\.0\.0-x86_64-Setup\.exe/u
);
assert.match(
stageReleaseSource,
/MorphDoc-FontPack-mdtp-serif-sc-1\.0\.0\.zip/u
);
assert.match(stageReleaseSource, /fontPackArtifacts\.map/u);
test("正式发布不再拆分独立字体安装器和 ZIP", () => {
assert.doesNotMatch(stageReleaseSource, /MorphDoc-FontPack-/u);
assert.doesNotMatch(stageReleaseSource, /fontPackArtifacts/u);
});