feat: 实现 Windows 可选字体包安装链

This commit is contained in:
SkyJourney
2026-07-31 22:29:23 +08:00
parent ae9fde3ac6
commit 6f62cfebd6
14 changed files with 725 additions and 5 deletions
+49
View File
@@ -45,3 +45,52 @@ root/<pack-id>/<semver>/font-pack.json
当前 `mdtp-serif-sc@1.0.0` 只替换 `FandolSong`
`Mdpdf Fandol Song` 的 400/700 字重,不匹配 `SimSun` 等通用别名,避免
错误替换仿宋、黑体、楷体或普通外部主题字体。
## Windows 独立安装器
发布人员可以使用 electron-builder 锁定并校验的 NSIS 工具链构建独立
字体包安装器,不需要额外安装系统 NSIS:
```powershell
npm run build:font-pack:windows
```
默认产物为:
```text
output/font-packs/windows/
└── md-to-pdf-font-pack-mdtp-serif-sc-1.0.0-x86_64-Setup.exe
```
安装器使用当前用户权限,将整个 `mdtp-serif-sc` ID 安装到:
```text
%LOCALAPPDATA%/md-to-pdf/font-packs/mdtp-serif-sc/1.0.0/
```
它不向 Windows 系统字体目录注册字体。同一版本重装保持幂等,升级时先把
该 ID 的现有目录移入备份,再原子提升新版本;失败会回滚。独立卸载项只
删除安装器拥有的 `mdtp-serif-sc` ID,不影响其他字体包 ID。安装器支持
`/S` 静默安装和卸载。
## Desktop 伴随发行
组合构建命令为:
```powershell
npm run desktop:make:with-font-pack
```
该命令把主安装器和字体包安装器作为两个同目录文件发行。主安装器只编译
字体包文件名与 SHA-256,不嵌入字体二进制;仅当同目录文件存在且哈希完全
一致时,交互安装向导才显示默认勾选的字体包选项。字体包失败不回滚已安装
的主程序。
主安装器静默运行时默认不安装伴随字体包;只有显式传入以下参数才会安装:
```powershell
md-to-pdf-<version>-x86_64-Setup.exe /S /WITHFONTPACK=1
```
普通 `npm run make -w @md-to-pdf/desktop` 不启用伴随逻辑,避免本地残留的
生成文件影响常规桌面构建。
+132
View File
@@ -0,0 +1,132 @@
Unicode true
RequestExecutionLevel user
SetCompressor /SOLID lzma
SetCompressorDictSize 64
!include "MUI2.nsh"
!include "LogicLib.nsh"
!ifndef PACK_DIRECTORY
!error "PACK_DIRECTORY is required"
!endif
!ifndef PACK_ID
!error "PACK_ID is required"
!endif
!ifndef PACK_VERSION
!error "PACK_VERSION is required"
!endif
!ifndef PACK_NAME
!error "PACK_NAME is required"
!endif
!ifndef PACK_LICENSE_FILE
!error "PACK_LICENSE_FILE is required"
!endif
!ifndef OUTPUT_FILE
!error "OUTPUT_FILE is required"
!endif
!ifndef FONT_PACK_ROOT
!define FONT_PACK_ROOT "$LOCALAPPDATA\md-to-pdf\font-packs"
!endif
!ifndef MANAGER_ROOT
!define MANAGER_ROOT "$LOCALAPPDATA\md-to-pdf\font-pack-installers"
!endif
Name "Markdown PDF 导出器字体包 - ${PACK_NAME}"
OutFile "${OUTPUT_FILE}"
InstallDir "${MANAGER_ROOT}\${PACK_ID}"
ShowInstDetails show
ShowUninstDetails show
BrandingText "Markdown PDF 导出器"
!ifdef ICON_FILE
Icon "${ICON_FILE}"
UninstallIcon "${ICON_FILE}"
!define MUI_ICON "${ICON_FILE}"
!define MUI_UNICON "${ICON_FILE}"
!endif
!define MUI_ABORTWARNING
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${PACK_LICENSE_FILE}"
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "SimpChinese"
VIProductVersion "1.0.0.0"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "ProductName" "Markdown PDF 导出器字体包"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileDescription" "${PACK_NAME}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileVersion" "${PACK_VERSION}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "LegalCopyright" "Copyright © YIXIONG Tech.ltd"
Section "安装字体包" SEC_FONT_PACK
SetShellVarContext current
StrCpy $R0 "${FONT_PACK_ROOT}\.installing-${PACK_ID}"
StrCpy $R1 "${FONT_PACK_ROOT}\${PACK_ID}"
StrCpy $R2 "${FONT_PACK_ROOT}\.backup-${PACK_ID}"
CreateDirectory "${FONT_PACK_ROOT}"
RMDir /r "$R0"
RMDir /r "$R2"
CreateDirectory "$R0\${PACK_ID}\${PACK_VERSION}"
SetOutPath "$R0\${PACK_ID}\${PACK_VERSION}"
File /r "${PACK_DIRECTORY}\*.*"
SetOutPath "$TEMP"
IfFileExists "$R0\${PACK_ID}\${PACK_VERSION}\font-pack.json" +3 0
RMDir /r "$R0"
Abort "字体包暂存校验失败:缺少 font-pack.json"
ClearErrors
IfFileExists "$R1\*.*" 0 promote_pack
Rename "$R1" "$R2"
IfErrors install_failed
promote_pack:
ClearErrors
Rename "$R0\${PACK_ID}" "$R1"
IfErrors rollback_pack
RMDir /r "$R0"
RMDir /r "$R2"
SetOutPath "$INSTDIR"
WriteUninstaller "$INSTDIR\Uninstall.exe"
FileOpen $R3 "$INSTDIR\installed-version.txt" w
FileWrite $R3 "${PACK_VERSION}$\r$\n"
FileClose $R3
!ifdef REGISTER_UNINSTALL
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "DisplayName" "Markdown PDF 导出器字体包 - ${PACK_NAME}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "DisplayVersion" "${PACK_VERSION}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "Publisher" "YIXIONG Tech.ltd"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "InstallLocation" "$INSTDIR"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "UninstallString" '"$INSTDIR\Uninstall.exe"'
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "NoModify" 1
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}" "NoRepair" 1
!endif
Goto install_done
rollback_pack:
RMDir /r "$R1"
IfFileExists "$R2\*.*" 0 install_failed
Rename "$R2" "$R1"
install_failed:
RMDir /r "$R0"
Abort "字体包安装失败,原版本已保留。"
install_done:
SectionEnd
Section "Uninstall"
SetShellVarContext current
RMDir /r "${FONT_PACK_ROOT}\${PACK_ID}"
RMDir /r "${FONT_PACK_ROOT}\.installing-${PACK_ID}"
RMDir /r "${FONT_PACK_ROOT}\.backup-${PACK_ID}"
!ifdef REGISTER_UNINSTALL
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\md-to-pdf-font-pack-${PACK_ID}"
!endif
Delete "$INSTDIR\installed-version.txt"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR"
SectionEnd