204 lines
6.8 KiB
PowerShell
204 lines
6.8 KiB
PowerShell
#Requires -Version 5.1
|
|
<#
|
|
.SYNOPSIS
|
|
将 Markdown 转换为 Word 文档 (.docx)
|
|
.DESCRIPTION
|
|
使用 Pandoc 将 Markdown 文件转换为 Word 文档,支持使用参考模板应用公司样式。
|
|
如未指定模板,将自动使用默认模板(若存在)。
|
|
.PARAMETER InputPath
|
|
输入的 Markdown 文件路径(必填)
|
|
.PARAMETER OutputPath
|
|
输出的 Word 文件路径(可选,默认与输入文件同名但扩展名为 .docx)
|
|
.PARAMETER TemplatePath
|
|
参考模板文件路径(可选,用于应用自定义样式;如未指定且存在默认模板则自动使用)
|
|
.PARAMETER ExtractMedia
|
|
图片提取目录(可选,用于提取嵌入的图片)
|
|
.PARAMETER NoDefaultTemplate
|
|
不使用默认模板(即使存在)
|
|
.EXAMPLE
|
|
.\convert-to-docx.ps1 -InputPath "公司概况.md"
|
|
.EXAMPLE
|
|
.\convert-to-docx.ps1 -InputPath "公司概况.md" -TemplatePath "模板.docx"
|
|
.EXAMPLE
|
|
.\convert-to-docx.ps1 -InputPath "公司概况.md" -OutputPath "导出/公司概况.docx"
|
|
#>
|
|
|
|
param(
|
|
[Parameter(Mandatory = $true, HelpMessage = "输入的 Markdown 文件路径")]
|
|
[string]$InputPath,
|
|
|
|
[Parameter(Mandatory = $false, HelpMessage = "输出的 Word 文件路径")]
|
|
[string]$OutputPath,
|
|
|
|
[Parameter(Mandatory = $false, HelpMessage = "参考模板文件路径")]
|
|
[string]$TemplatePath,
|
|
|
|
[Parameter(Mandatory = $false, HelpMessage = "图片提取目录")]
|
|
[string]$ExtractMedia,
|
|
|
|
[Parameter(Mandatory = $false, HelpMessage = "不使用默认模板")]
|
|
[switch]$NoDefaultTemplate
|
|
)
|
|
|
|
# 默认模板路径(相对于脚本位置)
|
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$skillDir = Split-Path -Parent $scriptDir
|
|
$DefaultTemplate = Join-Path $skillDir "template_默认.docx"
|
|
|
|
# 错误时停止
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
# 辅助函数:将路径转换为绝对路径
|
|
function Resolve-AbsolutePath {
|
|
param([string]$Path)
|
|
if ([System.IO.Path]::IsPathRooted($Path)) {
|
|
return $Path
|
|
}
|
|
return Join-Path (Get-Location) $Path
|
|
}
|
|
|
|
# 辅助函数:获取相对于当前目录的路径(用于显示)
|
|
function Get-RelativeDisplayPath {
|
|
param([string]$Path)
|
|
$absPath = Resolve-AbsolutePath $Path
|
|
$currentDir = (Get-Location).Path
|
|
if ($absPath -like "$currentDir*") {
|
|
return $absPath.Substring($currentDir.Length).TrimStart('\', '/')
|
|
}
|
|
return $absPath
|
|
}
|
|
|
|
# ========== 验证 ==========
|
|
|
|
# 检查 Pandoc 是否安装
|
|
try {
|
|
$pandocVersion = pandoc --version | Select-Object -First 1
|
|
Write-Host "✓ 检测到 Pandoc: $pandocVersion" -ForegroundColor Green
|
|
}
|
|
catch {
|
|
Write-Host "✗ 错误:未检测到 Pandoc" -ForegroundColor Red
|
|
Write-Host " 请先安装 Pandoc:" -ForegroundColor Yellow
|
|
Write-Host " winget install --id JohnMacFarlane.Pandoc" -ForegroundColor Cyan
|
|
exit 1
|
|
}
|
|
|
|
# 验证输入文件
|
|
$InputPath = Resolve-AbsolutePath $InputPath
|
|
if (-not (Test-Path $InputPath)) {
|
|
Write-Host "✗ 错误:找不到输入文件: $(Get-RelativeDisplayPath $InputPath)" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
|
|
$inputExtension = [System.IO.Path]::GetExtension($InputPath).ToLower()
|
|
if ($inputExtension -ne ".md" -and $inputExtension -ne ".markdown") {
|
|
Write-Host "⚠ 警告:输入文件扩展名为 $inputExtension,期望 .md 或 .markdown" -ForegroundColor Yellow
|
|
}
|
|
|
|
Write-Host "✓ 输入文件: $(Get-RelativeDisplayPath $InputPath)" -ForegroundColor Green
|
|
|
|
# 确定输出路径
|
|
if (-not $OutputPath) {
|
|
$outputDir = [System.IO.Path]::GetDirectoryName($InputPath)
|
|
$outputName = [System.IO.Path]::GetFileNameWithoutExtension($InputPath) + ".docx"
|
|
$OutputPath = Join-Path $outputDir $outputName
|
|
}
|
|
else {
|
|
$OutputPath = Resolve-AbsolutePath $OutputPath
|
|
# 确保输出目录存在
|
|
$outputDir = [System.IO.Path]::GetDirectoryName($OutputPath)
|
|
if (-not (Test-Path $outputDir)) {
|
|
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
|
|
}
|
|
}
|
|
|
|
Write-Host "→ 输出文件: $(Get-RelativeDisplayPath $OutputPath)" -ForegroundColor Cyan
|
|
|
|
# 处理模板路径
|
|
if ($TemplatePath) {
|
|
# 用户指定了模板,验证它
|
|
$TemplatePath = Resolve-AbsolutePath $TemplatePath
|
|
if (-not (Test-Path $TemplatePath)) {
|
|
Write-Host "✗ 错误:找不到模板文件: $(Get-RelativeDisplayPath $TemplatePath)" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
$templateExtension = [System.IO.Path]::GetExtension($TemplatePath).ToLower()
|
|
if ($templateExtension -ne ".docx") {
|
|
Write-Host "✗ 错误:模板必须是 .docx 文件" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
Write-Host "✓ 使用指定模板: $(Get-RelativeDisplayPath $TemplatePath)" -ForegroundColor Green
|
|
}
|
|
elseif (-not $NoDefaultTemplate -and (Test-Path $DefaultTemplate)) {
|
|
# 使用默认模板
|
|
$TemplatePath = $DefaultTemplate
|
|
Write-Host "✓ 使用默认模板: $(Get-RelativeDisplayPath $TemplatePath)" -ForegroundColor Green
|
|
}
|
|
|
|
# 处理图片提取目录
|
|
if ($ExtractMedia) {
|
|
$ExtractMedia = Resolve-AbsolutePath $ExtractMedia
|
|
if (-not (Test-Path $ExtractMedia)) {
|
|
New-Item -ItemType Directory -Path $ExtractMedia -Force | Out-Null
|
|
Write-Host "✓ 创建图片目录: $(Get-RelativeDisplayPath $ExtractMedia)" -ForegroundColor Green
|
|
}
|
|
}
|
|
|
|
# ========== 执行转换 ==========
|
|
|
|
Write-Host "`n正在转换..." -ForegroundColor Yellow
|
|
|
|
# 构建 Pandoc 参数数组
|
|
$pandocArgs = @()
|
|
|
|
# 输入文件
|
|
$pandocArgs += $InputPath
|
|
|
|
# 输出文件
|
|
$pandocArgs += "-o"
|
|
$pandocArgs += $OutputPath
|
|
|
|
# 模板(如果提供)
|
|
if ($TemplatePath) {
|
|
$pandocArgs += "--reference-doc=$TemplatePath"
|
|
}
|
|
|
|
# 图片提取(如果提供)
|
|
if ($ExtractMedia) {
|
|
$pandocArgs += "--extract-media=$ExtractMedia"
|
|
}
|
|
|
|
# 执行转换
|
|
try {
|
|
$process = Start-Process -FilePath "pandoc" -ArgumentList $pandocArgs -Wait -PassThru -NoNewWindow
|
|
|
|
if ($process.ExitCode -ne 0) {
|
|
throw "Pandoc 返回非零退出码: $($process.ExitCode)"
|
|
}
|
|
|
|
# 验证输出
|
|
if (-not (Test-Path $OutputPath)) {
|
|
throw "转换失败:未生成输出文件"
|
|
}
|
|
|
|
$fileInfo = Get-Item $OutputPath
|
|
$sizeKB = [math]::Round($fileInfo.Length / 1KB, 2)
|
|
|
|
Write-Host "`n✓ 转换成功!" -ForegroundColor Green
|
|
Write-Host " 文件: $(Get-RelativeDisplayPath $OutputPath)" -ForegroundColor White
|
|
Write-Host " 大小: $sizeKB KB" -ForegroundColor White
|
|
|
|
# 显示完成提示
|
|
Write-Host "`n提示:" -ForegroundColor Cyan
|
|
Write-Host " • 输出文档已保存到输入文件所在目录" -ForegroundColor Gray
|
|
if (-not $TemplatePath) {
|
|
Write-Host " • 如需应用公司样式,使用 -TemplatePath 参数指定模板" -ForegroundColor Gray
|
|
}
|
|
if ($ExtractMedia) {
|
|
Write-Host " • 图片已提取到: $(Get-RelativeDisplayPath $ExtractMedia)" -ForegroundColor Gray
|
|
}
|
|
}
|
|
catch {
|
|
Write-Host "`n✗ 转换失败: $($_.Exception.Message)" -ForegroundColor Red
|
|
exit 1
|
|
}
|