src/ConvertTo-Encoding.psm1
|
using namespace System.Diagnostics.CodeAnalysis using namespace System.IO using namespace System.Text <# .SYNOPSIS The list of binary file extensions. #> $BinaryExtensions = @() <# .SYNOPSIS The list of text file extensions. #> $TextExtensions = @() <# .SYNOPSIS Converts the encoding of input files. .INPUTS A string that contains a path, but not a literal path. .OUTPUTS The log messages. #> function ConvertTo-Encoding { [CmdletBinding(DefaultParameterSetName = "Path")] [OutputType([string])] param ( # The path to the files to convert. [Parameter(Mandatory, ParameterSetName = "Path", Position = 0, ValueFromPipeline)] [SupportsWildcards()] [string[]] $Path, # The literal path to the files to convert. [Parameter(Mandatory, ParameterSetName = "LiteralPath")] [ValidateScript({ Test-Path $_ -IsValid }, ErrorMessage = "The specified literal path is invalid.")] [string[]] $LiteralPath, # The destination encoding. [Parameter(Mandatory)] [ValidateSet("Latin1", "UTF-8")] [string] $Encoding, # The list of folders to exclude from the processing. [ValidateNotNull()] [string[]] $Exclude = @(".git", "node_modules", "vendor"), # A pattern used to filter the list of files to be processed. [Parameter()] [string] $Filter = "", # Value indicating whether to process the input path recursively. [Parameter()] [switch] $Recurse ) begin { if (-not $Script:BinaryExtensions) { $Script:BinaryExtensions = Get-Content "$PSScriptRoot/../res/BinaryExtensions.json" | ConvertFrom-Json } if (-not $Script:TextExtensions) { $Script:TextExtensions = Get-Content "$PSScriptRoot/../res/TextExtensions.json" | ConvertFrom-Json } } process { $sourceEncoding = [Encoding]::GetEncoding($Encoding -eq "Latin1" ? "UTF-8" : "Latin1") $destinationEncoding = [Encoding]::GetEncoding($Encoding) $parameters = @{ File = $true; Recurse = $Recurse } if ($Filter) { $parameters.Filter = $Filter } $files = $PSCmdlet.ParameterSetName -eq "LiteralPath" ? (Get-ChildItem -LiteralPath $LiteralPath @parameters) : (Get-ChildItem $Path @parameters) foreach ($file in $files) { if (Test-IsExcluded $file -Exclude $Exclude) { continue } $extension = Split-Path $file.Name -Extension $isBinary = $extension -and ($extension.Substring(1) -in $Script:BinaryExtensions) if ($isBinary) { continue } $bytes = Get-Content $file.FullName -AsByteStream if (-not $bytes) { continue } $isText = $extension -and ($extension.Substring(1) -in $Script:TextExtensions) if ((-not $isText) -and ([Array]::IndexOf[byte]($bytes, 0, 0, [Math]::Min($bytes.Count, 8000)) -gt 0)) { continue } "Converting: $file" Set-Content $file.FullName ([Encoding]::Convert($sourceEncoding, $destinationEncoding, $bytes)) -AsByteStream } } } <# .SYNOPSIS Checks if the specified file should be excluded from the processing. .OUTPUTS `$true` if the specified file should be excluded from the processing, otherwise `$false`. #> function Test-IsExcluded { [OutputType([bool])] param ( # The file to be checked. [Parameter(Mandatory, Position = 0, ValueFromPipeline)] [FileInfo] $File, # The list of folders to exclude from the processing. [ValidateNotNull()] [string[]] $Exclude = @(".git", "node_modules", "vendor") ) process { $directory = $file.Directory while ($directory) { if ($directory.Name -in $Exclude) { return $true } $directory = $directory.Parent } $false } } |