param( [string]$OutputFile = "code_export.txt" ) $ErrorActionPreference = "Stop" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path if ([System.IO.Path]::IsPathRooted($OutputFile)) { $OutputPath = $OutputFile } else { $OutputPath = Join-Path $ScriptDir $OutputFile } $ExcludedDirectories = @("node_modules", "vendor", "dist", "build", "images") $ExcludedFilePatterns = @( "code_export*.txt", "gitea-token*.txt", "gitea-token*.txt.sig" ) $ExcludedExtensions = @( ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".svg", ".ico", ".webp", ".mp4", ".mov", ".avi", ".mkv", ".webm", ".mp3", ".wav", ".ogg", ".flac", ".pdf", ".zip", ".tar", ".gz", ".bz2", ".rar", ".7z", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".eot", ".ttf", ".woff", ".woff2" ) function Get-RelativePath { param( [string]$BasePath, [string]$FullPath ) $baseUri = [System.Uri](([System.IO.Path]::GetFullPath($BasePath)).TrimEnd("\") + "\") $fullUri = [System.Uri]([System.IO.Path]::GetFullPath($FullPath)) $relativeUri = $baseUri.MakeRelativeUri($fullUri) return [System.Uri]::UnescapeDataString($relativeUri.ToString()).Replace("/", "\") } function Test-IsProbablyBinary { param( [string]$Path ) try { $stream = [System.IO.File]::OpenRead($Path) try { $buffer = New-Object byte[] 4096 $bytesRead = $stream.Read($buffer, 0, $buffer.Length) } finally { $stream.Dispose() } } catch { return $true } if ($bytesRead -ge 2) { if ( ($buffer[0] -eq 0xFF -and $buffer[1] -eq 0xFE) -or ($buffer[0] -eq 0xFE -and $buffer[1] -eq 0xFF) ) { return $false } } if ($bytesRead -ge 3) { if ($buffer[0] -eq 0xEF -and $buffer[1] -eq 0xBB -and $buffer[2] -eq 0xBF) { return $false } } if ($bytesRead -ge 4) { if ( ($buffer[0] -eq 0xFF -and $buffer[1] -eq 0xFE -and $buffer[2] -eq 0x00 -and $buffer[3] -eq 0x00) -or ($buffer[0] -eq 0x00 -and $buffer[1] -eq 0x00 -and $buffer[2] -eq 0xFE -and $buffer[3] -eq 0xFF) ) { return $false } } for ($index = 0; $index -lt $bytesRead; $index++) { if ($buffer[$index] -eq 0) { return $true } } return $false } function Test-ShouldSkipFile { param( [System.IO.FileInfo]$File ) $fullPath = [System.IO.Path]::GetFullPath($File.FullName) if ($fullPath -eq [System.IO.Path]::GetFullPath($OutputPath)) { return $true } $relativePath = Get-RelativePath -BasePath $ScriptDir -FullPath $File.FullName if ($relativePath -eq "export_code.sh" -or $relativePath -eq "export_code.ps1") { return $true } foreach ($pattern in $ExcludedFilePatterns) { if ($File.Name -like $pattern) { return $true } } $segments = $relativePath -split "[\\/]+" foreach ($segment in $segments) { if ($segment.StartsWith(".")) { return $true } if ($ExcludedDirectories -contains $segment) { return $true } } if ($ExcludedExtensions -contains $File.Extension) { return $true } return $false } if (Test-Path -LiteralPath $OutputPath) { Remove-Item -LiteralPath $OutputPath -Force } $builder = New-Object System.Text.StringBuilder $files = Get-ChildItem -LiteralPath $ScriptDir -File -Recurse | Sort-Object { (Get-RelativePath -BasePath $ScriptDir -FullPath $_.FullName).Replace("\", "/") } foreach ($file in $files) { if (Test-ShouldSkipFile -File $file) { continue } if (Test-IsProbablyBinary -Path $file.FullName) { continue } try { $content = Get-Content -LiteralPath $file.FullName -Raw -ErrorAction Stop } catch { continue } $relativePath = (Get-RelativePath -BasePath $ScriptDir -FullPath $file.FullName).Replace("\", "/") [void]$builder.AppendLine(("`"./{0}`" : " -f $relativePath)) [void]$builder.AppendLine('"""') [void]$builder.Append($content) if (-not $content.EndsWith("`n")) { [void]$builder.AppendLine() } [void]$builder.AppendLine('"""') [void]$builder.AppendLine() [void]$builder.AppendLine() } $utf8NoBom = New-Object System.Text.UTF8Encoding $false [System.IO.File]::WriteAllText($OutputPath, $builder.ToString(), $utf8NoBom) Write-Host ("Code export finished. Output saved to {0}" -f $OutputPath)