Compress-ScriptBlock.min.ps1

function Compress-ScriptBlock{[OutputType([string])]param([Parameter(Mandatory=$true,ValueFromPipelineByPropertyName)][ScriptBlock]$ScriptBlock,[Parameter(ValueFromPipelineByPropertyName)][string]$Name,[Parameter(ValueFromPipelineByPropertyName)][switch]$Anonymous,[Parameter(ValueFromPipelineByPropertyName)][Alias('Zip', 'Compress')][switch]$GZip,[Parameter(ValueFromPipelineByPropertyName)][Alias('Dot', '.')][switch]$DotSource,[Parameter(ValueFromPipelineByPropertyName)][Alias('NoBlocks')][switch]$NoBlock,[Parameter(ValueFromPipelineByPropertyName)][string]$OutputPath,[Parameter(ValueFromPipelineByPropertyName)][switch]$PassThru)begin{foreach($_ in 'BinaryExpression','Expression','ScriptBlockExpression','ParenExpression','ArrayExpression','SubExpression','Command','CommandExpression','IfStatement','LoopStatement','Hashtable','ConvertExpression','FunctionDefinition','AssignmentStatement','Pipeline','Statement','TryStatement','CommandExpression'){$ExecutionContext.SessionState.PSVariable.Set($_, "Management.Automation.Language.${_}Ast" -as [Type])};$CompressScriptBlockAst={param($ast)if($ast.Body){$ast=$ast.Body};$dps=$ast.DynamicParamBlock.Statements;$bs=$ast.BeginBlock.Statements;$ps=$ast.ProcessBlock.Statements;$es=$ast.EndBlock.Statements;@(if($ast.UsingStatements){(@(foreach($using in $ast.UsingStatements){"$using"})-join';')+';'};if($ast.ParamBlock){$pb=$ast.ParamBlock;foreach($a in $pb.Attributes){$a};'param(';@(foreach($p in $pb.Parameters){@(foreach($a in $p.Attributes){$a};$p.Name)-join''})-join',';')'};if($dps){'dynamicParam{';@($dps|& $CompressStatement)-join';';'}'};if($bs){'begin{';@($bs|& $CompressStatement)-join';';'}'};if($ps){'process{';@($ps|& $CompressStatement)-join';';'}'};if($es){if($bs-or$ps){'end{'};@($es|& $CompressStatement)-join';';if($bs-or$ps){'}'}})-join''};$CompressStatement={param([Parameter(ValueFromPipeline=$true)][Management.Automation.Language.StatementAst]$s)process{if($s-is$IfStatement){$nc=0;@(foreach($c in $s.Clauses){if(-not $nc){'if'}else{'elseif'};'(';@($c.Item1.PipelineElements|& $CompressPipeline)-join'|';')';'{';@($c.Item2.Statements|& $CompressStatement)-join';';$nc++;'}'};if($s.ElseClause){'else{';@($s.ElseClause.Statements|& $CompressStatement)-join';';'}'})-join''}elseif($s-is$LoopStatement){$loopType=$s.GetType().Name.Replace('StatementAst','');@(if($s.Label){":$($s.Label) "};if($loopType-eq'foreach'){'foreach(';$s.Variable;' in ';& $compressPart $s.Condition;')'}elseif($loopType-eq'for'){'for(';$s.Initializer;';';$s.Condition;';';$s.Iterator;')'}elseif($loopType-eq'while'){'while(';$s.Condition;')'}elseif($loopType-eq'dowhile'){'do'};'{';@($s.Body.Statements|& $CompressStatement)-join';';'}';if($loopType-eq'dowhile'){'while(';$s.Condition;')'})-join''}elseif($s-is$AssignmentStatement){$as=$s;@($as.Left.ToString().Trim();$as.ErrorPosition.Text;if($as.Right-is[Management.Automation.Language.StatementAst]){@($as.right|& $CompressStatement)-join';'})-join''}elseif($s-is$Pipeline){@($s.PipelineElements|& $CompressPipeline)-join'|'}elseif($s-is$TryStatement){@('try{';@($s.Body.statements|& $CompressStatement)-join';';'}';foreach($cc in $s.CatchClauses){'catch';if($cc.CatchTypes){foreach($ct in $cc.CatchTypes){' [';$ct.TypeName.FullName;']'}};'{';@($cc.Body.statements|& $CompressStatement)-join';';'}'};if($s.Finally){'finally{';$($s.Finally.statements|& $CompressStatement)-join';';'}'})-join''}elseif($s-is$CommandExpression){if($s.Expression){$s.Expression|& $CompressExpression}else{$s.ToString()}}elseif($s-is$FunctionDefinition){$(if($s.IsWorklow){"workflow "}elseif($s.IsFilter){"filter "}else{"function "})+$s.Name+"{$(& $CompressScriptBlockAst $s.Body)}"}else{$s.ToString()}}};$CompressPipeline={param([Parameter(ValueFromPipeline=$true)][Management.Automation.Language.CommandBaseAst]$p)process{if($p-is$CommandExpression){& $CompressExpression $p.Expression}elseif($p-is$Command){@(if($p.InvocationOperator-eq'Ampersand'){'&'}elseif($p.InvocationOperator-eq'Dot'){'.'};foreach($e in $p.CommandElements){if($e.ScriptBlock){"{$(& $CompressScriptBlockAst $e.ScriptBlock)}"}else{$e}})-join' '}elseif($p){$p.ToString()}else{$null=$null}}};$CompressExpression={param([Parameter(ValueFromPipeline=$true,Position=0)][Management.Automation.Language.ExpressionAst]$e)process{@(if($e-is$BinaryExpression){if($e.Left-is$Expression){& $CompressExpression $e.Left}else{$e.Left};$e.ErrorPosition;if($e.Right-is$Expression){& $CompressExpression $e.Right}else{$e.Right}}elseif($e-is$ScriptBlockExpression){'{';& $CompressScriptBlockAst $e.ScriptBlock;'}'}elseif($e-is$ParenExpression){'(';. $compressPart $e;')'}elseif($e-is$ArrayExpression){'@(';. $compressPart $e;')'}elseif($e-is$SubExpression){'$(';. $compressPart $e;')'}elseif($e-is$convertExpression){"[$($e.Type.TypeName -replace '\s')]";. $CompressExpression $e.Child}elseif($e-is$hashtable){'@{'+(@(foreach($kvp in $e.KeyValuePairs){@(. $compressPart $kvp.Item1;'=';. $compressPart $kvp.Item2)-join''})-join';')+'}'}elseif($e.Elements){@(foreach($_ in $e.Elements){. $CompressPart $_})-join','}else{$e.ToString()})-join''}};$CompressPart={param([Parameter(ValueFromPipeline=$true,Position=0)]$p)process{if($p.SubExpression){@($p.Subexpression.Statements|& $CompressStatement)-join';'}elseif($p.Pipeline){@($p.Pipeline.PipelineElements|& $CompressPipeline)-join'|'}elseif($p-is$FunctionDefinition){$(if($p.IsWorklow){"workflow "}elseif($p.IsFilter){"filter "}else{"function "})+$p.Name+"{$(& $CompressScriptBlockAst $p.Body)}"}elseif($p.ScriptBlock){"{$(& $CompressScriptBlockAst $p.ScriptBlock)}"}elseif($p-is$Pipeline){@($p.PipelineElements|& $CompressPipeline)-join'|'}else{$p}}}}process{if($_-is[Management.Automation.CommandInfo]){$name=''};$compressedScriptBlock=& $CompressScriptBlockAst $ScriptBlock.Ast;$compressedScriptBlock=if(-not $GZip){$compressedScriptBlock}else{$data=[Text.Encoding]::Unicode.GetBytes($compressedScriptBlock);$ms=[IO.MemoryStream]::new();$cs=[IO.Compression.GZipStream]::new($ms, [Io.Compression.CompressionMode]"Compress");$cs.Write($Data, 0, $Data.Length);$cs.Close();$cs.Dispose();if($NoBlock){"`$([ScriptBlock]::Create(([IO.StreamReader]::new(([IO.Compression.GZipStream]::new([IO.MemoryStream]::new([Convert]::FromBase64String('$([Convert]::ToBase64String($ms.ToArray()))')),[IO.Compression.CompressionMode]'Decompress')),[Text.Encoding]::unicode)).ReadToEnd()))"}else{"`$([ScriptBlock]::Create(([IO.StreamReader]::new((
    [IO.Compression.GZipStream]::new([IO.MemoryStream]::new(
        [Convert]::FromBase64String('
$([Convert]::ToBase64String($ms.ToArray(), 'InsertLineBreaks'))
        ')),
        [IO.Compression.CompressionMode]'Decompress')),
    [Text.Encoding]::unicode)).ReadToEnd()
))"
};$ms.Close();$ms.Dispose()};if($DotSource){$compressedScriptBlock=if($GZip){". $compressedScriptBlock"}else{". {$compressedScriptBlock}"}};$minified=if($Name-and-not $Anonymous){if(-not $GZip-and-not $DotSource){$compressedScriptBlock="{$compressedScriptBlock}"};if($Name-match'\W'){"`${$name} = $compressedScriptBlock"}else{"`$$name = $compressedScriptBlock"}}else{$compressedScriptBlock};if($OutputPath){$unresolvedOutputPath=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputPath);[IO.File]::WriteAllText("$unresolvedOutputPath", $minified);if($PassThru-and[IO.File]::Exists("$unresolvedOutputPath")){[IO.FileInfo]"$unresolvedOutputPath"}}else{$minified}}}