<# .SYNOPSIS 把受管文本文件规范成仓库约定的编码:UTF-8 with BOM、LF 行尾。 .DESCRIPTION 为什么需要一个可重放的脚本,而不是"改一次就完了": * Windows PowerShell 5.1 在没有 BOM 时会按 ANSI 代码页解码源码文件, 中文变乱码,而全角问号之类的字节序列会吃掉字符串引号、整块语法失效。 * 但很多编辑器与工具在保存时会**悄悄去掉 BOM**。实测本仓库用的编辑工具就会 (改过一次 test.ps1 之后它只在 5.1 上解析失败,在 7 上完全正常,极其隐蔽)。 * 所以"加过 BOM"必须是一次能在任何改动之后重放的规范化操作。 受管范围与 .editorconfig 一致: * *.ps1 / *.psm1 / *.psd1 —— PowerShell 引擎直接读取,必须有 BOM * BackupList.txt —— 被 Get-Content 读取,必须有 BOM 只做两件事:补 BOM、把 CRLF 归一成 LF。不动缩进、不动内容、不换编码以外的东西。 文件按 UTF-8 解码:本仓库的所有文本文件都是 UTF-8(见 .editorconfig)。 .PARAMETER WhatIf 只报告将要改动什么,不写任何文件。 .EXAMPLE .\tools\Set-SourceEncoding.ps1 -WhatIf .EXAMPLE .\tools\Set-SourceEncoding.ps1 #> [CmdletBinding(SupportsShouldProcess = $true)] param() $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $excluded = '\\(\.git|\.tools|Backups|logs|dist|snapshots)\\' $targets = @(Get-ChildItem -LiteralPath $projectRoot -Recurse -File | Where-Object { $_.Extension -in '.ps1', '.psm1', '.psd1' -or $_.Name -eq 'BackupList.txt' } | Where-Object { $_.FullName -notmatch $excluded }) $utf8Bom = New-Object System.Text.UTF8Encoding($true) $utf8NoBom = New-Object System.Text.UTF8Encoding($false) $addedBom = @() $normalizedLf = @() foreach ($file in $targets) { $bytes = [System.IO.File]::ReadAllBytes($file.FullName) $hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF $text = if ($hasBom) { $utf8NoBom.GetString($bytes, 3, $bytes.Length - 3) } else { $utf8NoBom.GetString($bytes) } $normalized = ($text -split "`r?`n") -join "`n" $needsWrite = (-not $hasBom) -or ($normalized -ne $text) if (-not $hasBom) { $addedBom += $file.FullName.Substring($projectRoot.Length).TrimStart('\') } if ($normalized -ne $text) { $normalizedLf += $file.FullName.Substring($projectRoot.Length).TrimStart('\') } if ($needsWrite -and $PSCmdlet.ShouldProcess($file.FullName, '规范成 UTF-8 with BOM 与 LF')) { [System.IO.File]::WriteAllText($file.FullName, $normalized, $utf8Bom) } } Write-Host '' Write-Host ("受管文件 {0} 个" -f $targets.Count) if ($addedBom.Count -gt 0) { Write-Host ("补上 BOM {0} 个:" -f $addedBom.Count) -ForegroundColor Yellow $addedBom | ForEach-Object { Write-Host " $_" } } else { Write-Host '所有文件都已经带 BOM。' -ForegroundColor Green } if ($normalizedLf.Count -gt 0) { Write-Host ("行尾归一成 LF {0} 个:" -f $normalizedLf.Count) -ForegroundColor Yellow $normalizedLf | ForEach-Object { Write-Host " $_" } } if (-not $WhatIfPreference) { Write-Host '' Write-Host '下一步:.\test.ps1 -Suite Parse 确认两个版本都能解析。' -ForegroundColor Cyan }