PSParseHTML.psm1
function Convert-InternalHTMLToText { [CmdletBinding()] param( [string] $Content ) $Output = [NUglify.Uglify]::HtmlToText($Content) if ($Output.HasErrors) { Write-Warning "Convert-HTMLToText -Errors: $($Output.Errors)" } $Output.Code } function ConvertFrom-HTMLTableAgilityPack { [cmdletbinding()] param( [Uri] $Url, [string] $Content, [System.Collections.IDictionary] $ReplaceContent, [System.Collections.IDictionary] $ReplaceHeaders, [switch] $ReverseTable ) Begin { } Process { if ($Content) { [HtmlAgilityPack.HtmlDocument] $HtmlDocument = [HtmlAgilityPack.HtmlDocument]::new() $HtmlDocument.LoadHtml($Content) } else { [HtmlAgilityPack.HtmlWeb] $HtmlWeb = [HtmlAgilityPack.HtmlWeb]::new() [HtmlAgilityPack.HtmlDocument] $HtmlDocument = $HtmlWeb.Load($url) } [Array] $Tables = $HtmlDocument.DocumentNode.SelectNodes("//table") [Array] $OutputTables = :table foreach ($table in $Tables) { $Rows = $table.SelectNodes('.//tr') if ($ReverseTable) { $Count = 0 [Array] $TableContent = @( $obj = [ordered] @{ } $TableContent = foreach ($Row in $Rows) { $Count++ #for ($x = 0; $x -lt $headers.count; $x++) { # if ($($headers[$x])) { # $obj["$($headers[$x])"] = $row.SelectNodes("th|td")[$x].InnerText.Trim() [string] $CellHeader = $row.SelectNodes("th").InnerText [string] $CellContent = $row.SelectNodes("td").InnerText $CellContent = $CellContent.Trim() if ($ReplaceContent) { foreach ($Key in $ReplaceContent.Keys) { $CellContent = $CellContent -replace $Key, $ReplaceContent.$Key } } if ($CellHeader) { $obj["$($CellHeader)"] = $CellContent } else { $obj["$Count"] = $CellContent } # } else { # $obj["$x"] = $row.SelectNodes("th|td")[$x].InnerText.Trim() # } #} } #[PSCustomObject] $obj $obj ) } else { $Headers = foreach ($Row in $Rows[0]) { foreach ($Cell in $row.SelectNodes("th|td")) { $CellContent = $Cell.InnerText.Trim() if ($ReplaceHeaders) { foreach ($Key in $ReplaceHeaders.Keys) { $CellContent = $CellContent -replace $Key, $ReplaceHeaders.$Key } } $CellContent } } $TableContent = foreach ($Row in $Rows | Select-Object -Skip 1) { $obj = [ordered] @{ } for ($x = 0; $x -lt $headers.count; $x++) { if ($($headers[$x])) { # $obj["$($headers[$x])"] = $row.SelectNodes("th|td")[$x].InnerText.Trim() [string] $CellContent = $row.SelectNodes("th|td")[$x].InnerText $CellContent = $CellContent.Trim() if ($ReplaceContent) { foreach ($Key in $ReplaceContent.Keys) { $CellContent = $CellContent -replace $Key, $ReplaceContent.$Key } } $obj["$($headers[$x])"] = $CellContent } else { $obj["$x"] = $row.SelectNodes("th|td")[$x].InnerText.Trim() } } [PSCustomObject] $obj } } @(, $TableContent) } $OutputTables } End { } } function ConvertFrom-HTMLTableAngle { [cmdletbinding()] param( [Uri] $Url, [string] $Content, [System.Collections.IDictionary] $ReplaceContent, [System.Collections.IDictionary] $ReplaceHeaders ) Begin { } Process { if ($Url) { $Content = (Invoke-WebRequest -Uri $Url).Content } if (-not $Content) { return } # Initialize the parser $HTMLParser = [AngleSharp.Html.Parser.HtmlParser]::new() # Load the html $ParsedDocument = $HTMLParser.ParseDocument($Content) # Get all the tables [Array] $Tables = $ParsedDocument.GetElementsByTagName('table') # For each table :table foreach ($table in $tables) { [Array] $headers = foreach ($_ in $Table.Rows[0].Cells) { $CellContent = $_.TextContent.Trim() if ($ReplaceHeaders) { foreach ($Key in $ReplaceHeaders.Keys) { $CellContent = $CellContent -replace $Key, $ReplaceHeaders.$Key } } $CellContent } # if headers have value if ($Headers.Count -ge 1) { [Array] $output = foreach ($row in $table.Rows | Select-Object -Skip 1) { $obj = [ordered]@{ } # add all the properties, one per row for ($x = 0; $x -lt $headers.count; $x++) { if ($($headers[$x])) { if ($row.Cells[$x].TextContent) { $CellContent = $row.Cells[$x].TextContent.Trim() if ($ReplaceContent) { foreach ($Key in $ReplaceContent.Keys) { $CellContent = $CellContent -replace $Key, $ReplaceContent.$Key } } $obj["$($headers[$x])"] = $CellContent } else { $obj["$($headers[$x])"] = $row.Cells[$x].TextContent } } else { $obj["$x"] = $row.Cells[$x].TextContent #.Trim() } } [PSCustomObject] $obj } # if there are any rows, output if ($output.count -ge 1) { @(, $output) } else { Write-Verbose 'ConvertFrom-HtmlTable - Table has no rows. Skipping' } } } } End { } } function Format-InternalCSS { [CmdletBinding()] param( [string] $Content ) $CssParser = [AngleSharp.Css.Parser.CssParser]::new() $ParsedDocument = $CssParser.ParseStyleSheet($Content) $StringWriter = [System.IO.StringWriter]::new() $PrettyMarkupFormatter = [AngleSharp.Css.CssStyleFormatter]::new() $ParsedDocument.ToCss($StringWriter, $PrettyMarkupFormatter) $StringWriter.ToString() } function Format-InternalFormatWithUglify { [CmdletBinding()] param( [string] $Content, [string] $Indent = ' ', [NUglify.BlockStart] $BlockStartLine = [NUglify.BlockStart]::SameLine, [switch] $RemoveOptionalTags, [switch] $OutputTextNodesOnNewLine, [switch] $RemoveEmptyAttributes, [switch] $AlphabeticallyOrderAttributes, [switch] $RemoveEmptyBlocks, [switch] $RemoveComments, [switch] $IsFragment ) $Settings = [NUglify.Html.HtmlSettings]::new() # HTML Settings if ($IsFragment) { $Settings.IsFragmentOnly = $true } # Keep first comment # $Pattern = "<!-- saved from url=\(0014\)about:internet -->" # $MOTW = [System.Text.RegularExpressions.Regex]::new($Pattern) #, [System.Text.RegularExpressions.RegexOptions]::MultiLine) # $Settings.KeepCommentsRegex.Add($MOTW) $Settings.RemoveOptionalTags = $RemoveOptionalTags.IsPresent $Settings.PrettyPrint = $true $Settings.Indent = $Indent $Settings.OutputTextNodesOnNewLine = $OutputTextNodesOnNewLine.IsPresent # option to not indent textnodes when theyre the only child $Settings.RemoveEmptyAttributes = $RemoveEmptyAttributes.IsPresent $Settings.AlphabeticallyOrderAttributes = $AlphabeticallyOrderAttributes.IsPresent $Settings.RemoveComments = $RemoveComments $Settings.RemoveQuotedAttributes = $false #$Settings.LineTerminator = [System.Environment]::NewLine # JS Settings $Settings.JsSettings.MinifyCode = $true $Settings.JsSettings.OutputMode = [NUglify.OutputMode]::MultipleLines $Settings.JsSettings.Indent = $Indent $Settings.JsSettings.BlocksStartOnSameLine = $BlockStartLine $Settings.JsSettings.PreserveFunctionNames = $true $Settings.JsSettings.LocalRenaming = [NUglify.JavaScript.LocalRenaming]::KeepAll #$Settings.JsSettings.EvalTreatment = [NUglify.JavaScript.EvalTreatment]::Ignore #$Settings.JsSettings.Format = [NUglify.JavaScript.JavaScriptFormat]::Normal $Settings.JsSettings.NoAutoRenameList = $true $Settings.JsSettings.PreserveFunctionNames = $true #$Settings.JsSettings.CollapseToLiteral = $true #$Settings.JsSettings.ConstStatementsMozilla = $true #$Settings.JsSettings.LineBreakThreshold = 50 $Settings.JsSettings.ReorderScopeDeclarations = $false #$Settings.JsSettings.RenamePairs = $false #$Settings.JsSettings.QuoteObjectLiteralProperties = $true $Settings.JsSettings.TermSemicolons = $true #$Settings.JsSettings.Format = [NUglify.JavaScript.JavaScriptFormat]::Normal $Settings.JsSettings.RemoveUnneededCode = $false; $Settings.JsSettings.RemoveFunctionExpressionNames = $false; # $Settings.NoAutoRenameCollection # ReadOnly #$Settings.JsSettings.LineTerminator = "`r`n" # CSS Settings $Settings.CssSettings.OutputMode = [NUglify.OutputMode]::MultipleLines $Settings.CssSettings.Indent = $Indent $Settings.CssSettings.BlocksStartOnSameLine = $BlockStartLine $Settings.CssSettings.RemoveEmptyBlocks = $RemoveEmptyBlocks $Settings.CssSettings.DecodeEscapes = $false #$Settings.CssSettings.LineTerminator = "`r`n" [NUglify.Uglify]::Html($Content, $Settings).Code } function Format-InternalHTML { [CmdletBinding()] param( [string] $Content ) $HTMLParser = [AngleSharp.Html.Parser.HtmlParser]::new() $ParsedDocument = $HTMLParser.ParseDocument($Content) $StringWriter = [System.IO.StringWriter]::new() $PrettyMarkupFormatter = [AngleSharp.Html.PrettyMarkupFormatter]::new() $ParsedDocument.ToHtml($StringWriter, $PrettyMarkupFormatter) $StringWriter.ToString() } function Format-InternalJS { [CmdletBinding()] param( [string] $Content, [int] $IndentSize = 4, [string] $IndentChar = ' ', [bool] $IndentWithTabs = $false, [bool] $PreserveNewlines = $true, [double] $MaxPreserveNewlines = 10.0, [bool] $JslintHappy = $false, [Jsbeautifier.BraceStyle] $BraceStyle = [Jsbeautifier.BraceStyle]::Collapse, [bool] $KeepArrayIndentation = $false, [bool] $KeepFunctionIndentation = $false, [bool] $EvalCode = $false, #[int] $WrapLineLength = 0, [bool] $BreakChainedMethods = $false ) $Jsbeautifier = [Jsbeautifier.Beautifier]::new() $Jsbeautifier.Opts.IndentSize = $IndentSize $Jsbeautifier.Opts.IndentChar = $IndentChar $Jsbeautifier.Opts.IndentWithTabs = $IndentWithTabs $Jsbeautifier.Opts.PreserveNewlines = $PreserveNewlines $Jsbeautifier.Opts.MaxPreserveNewlines = $MaxPreserveNewlines $Jsbeautifier.Opts.JslintHappy = $JslintHappy $Jsbeautifier.Opts.BraceStyle = $BraceStyle $Jsbeautifier.Opts.KeepArrayIndentation = $KeepArrayIndentation $Jsbeautifier.Opts.KeepFunctionIndentation = $KeepFunctionIndentation $Jsbeautifier.Opts.EvalCode = $EvalCode #$Jsbeautifier.Opts.WrapLineLength = $WrapLineLength $Jsbeautifier.Opts.BreakChainedMethods = $BreakChainedMethods #$Jsbeautifier.Flags <# public BeautifierFlags(string mode) { PreviousMode = "BLOCK"; Mode = mode; VarLine = false; VarLineTainted = false; VarLineReindented = false; InHtmlComment = false; IfLine = false; ChainExtraIndentation = 0; InCase = false; InCaseStatement = false; CaseBody = false; IndentationLevel = 0; TernaryDepth = 0; } #> $FormattedJS = $Jsbeautifier.Beautify($Content) $FormattedJS } function Format-InternalUglifyJS { [CmdletBinding()] param( [string] $Content ) $Settings = [NUglify.JavaScript.CodeSettings]::new() $Settings.MinifyCode = $true $Settings.OutputMode = [NUglify.OutputMode]::MultipleLines $Settings.Indent = $Indent $Settings.LocalRenaming = [NUglify.JavaScript.LocalRenaming]::KeepAll #$Settings.EvalTreatment = [NUglify.JavaScript.EvalTreatment]::Ignore #$Settings.Format = [NUglify.JavaScript.JavaScriptFormat]::Normal $Settings.Indent = ' ' $Settings.NoAutoRenameList = $true $Settings.PreserveFunctionNames = $true # $Settings.NoAutoRenameCollection # ReadOnly [NUglify.Uglify]::Js($Content, $Code).Code } function Optimize-InternalCSS { [CmdletBinding()] param( [string] $Content ) $CSSParser = [AngleSharp.Css.Parser.CssParser]::new() $ParsedDocument = $CSSParser.ParseStyleSheet($Content) $StringWriter = [System.IO.StringWriter]::new() $PrettyMarkupFormatter = [AngleSharp.Css.MinifyStyleFormatter]::new() $ParsedDocument.ToCss($StringWriter, $PrettyMarkupFormatter) $StringWriter.ToString() } function Optimize-InternalUglifyCSS { [CmdletBinding()] param( [string] $Content ) $Settings = [NUglify.Css.CssSettings]::new() $Settings.DecodeEscapes = $false [NUglify.Uglify]::Css($Content, $Settings).Code } function Optimize-InternalUglifyHTML { [CmdletBinding()] param( [string] $Content, [switch] $CSSDecodeEscapes ) $Settings = [NUglify.Html.HtmlSettings]::new() $Settings.RemoveOptionalTags = $false $Settings.CssSettings.DecodeEscapes = $CSSDecodeEscapes.IsPresent # Keep first comment #$Pattern = "<!-- saved from url=\(0014\)about:internet -->" #$Pattern = "^\ssaved\sfrom\url=" #$MOTW = [System.Text.RegularExpressions.Regex]::new($Pattern, [System.Text.RegularExpressions.RegexOptions]::MultiLine) #$Settings.KeepCommentsRegex.Add($MOTW) if ($Content -like "*<!-- saved from url=(0014)about:internet -->*") { $MOTW = "<!-- saved from url=(0014)about:internet -->" } else { $MOTW = '' } $Settings.RemoveComments = $true $Output = [NUglify.Uglify]::Html($Content, $Settings).Code if ($MOTW) { $MOTW + [System.Environment]::NewLine + $Output } else { $Output } } <# $Settings AttributesCaseSensitive : False CollapseWhitespaces : True RemoveComments : True RemoveOptionalTags : False RemoveInvalidClosingTags : True RemoveEmptyAttributes : True RemoveQuotedAttributes : True DecodeEntityCharacters : True AttributeQuoteChar : RemoveScriptStyleTypeAttribute : True ShortBooleanAttribute : True IsFragmentOnly : False MinifyJs : True JsSettings : NUglify.JavaScript.CodeSettings MinifyCss : True MinifyCssAttributes : True CssSettings : NUglify.Css.CssSettings PrettyPrint : False RemoveJavaScript : False InlineTagsPreservingSpacesAround : {[a, True], [abbr, True], [acronym, True], [b, True]...} KeepOneSpaceWhenCollapsing : False TagsWithNonCollapsableWhitespaces : {[pre, True], [textarea, True]} KeepCommentsRegex : {^!, ^/?ko(?:[\s\-]|$)} KeepTags : {} RemoveAttributes : {} AlphabeticallyOrderAttributes : False #> <# $Settings.JsSettings HasRenamePairs : False RenamePairs : NoAutoRenameCollection : {$super} NoAutoRenameList : $super KnownGlobalCollection : {} KnownGlobalNamesList : DebugLookupCollection : {} DebugLookupList : AlwaysEscapeNonAscii : False AmdSupport : False CollapseToLiteral : True ConstStatementsMozilla : False ErrorIfNotInlineSafe : False EvalLiteralExpressions : True EvalTreatment : Ignore Format : Normal IgnoreConditionalCompilation : False IgnorePreprocessorDefines : False InlineSafeStrings : True LocalRenaming : CrunchAll MacSafariQuirks : True MinifyCode : True ManualRenamesProperties : True PreprocessOnly : False PreserveFunctionNames : False PreserveImportantComments : True QuoteObjectLiteralProperties : False ReorderScopeDeclarations : True RemoveFunctionExpressionNames : True RemoveUnneededCode : True ScriptVersion : None SourceMode : Program StrictMode : False StripDebugStatements : True SymbolsMap : WarningLevel : 0 AllowEmbeddedAspNetBlocks : False BlocksStartOnSameLine : NewLine IgnoreAllErrors : False IndentSize : 4 LineBreakThreshold : 2147482647 OutputMode : SingleLine TermSemicolons : False KillSwitch : 0 LineTerminator : IgnoreErrorCollection : {} IgnoreErrorList : PreprocessorValues : {} PreprocessorDefineList : ResourceStrings : {} ReplacementTokens : {} ReplacementFallbacks : {} #> <# $Settings.CssSettings ColorNames : Hex CommentMode : Important MinifyExpressions : True CssType : FullStyleSheet RemoveEmptyBlocks : True FixIE8Fonts : True ExcludeVendorPrefixes : {} IgnoreRazorEscapeSequence : False DecodeEscapes : True WarningLevel : 0 AllowEmbeddedAspNetBlocks : False BlocksStartOnSameLine : NewLine IgnoreAllErrors : False IndentSize : 4 LineBreakThreshold : 2147482647 OutputMode : SingleLine TermSemicolons : False KillSwitch : 0 LineTerminator : IgnoreErrorCollection : {} IgnoreErrorList : PreprocessorValues : {} PreprocessorDefineList : ResourceStrings : {} ReplacementTokens : {} ReplacementFallbacks : {} #> function Optimize-InternalUglifyJS { [CmdletBinding()] param( [string] $Content, [string] $Indent = ' ' ) #$Settings = [NUglify.JavaScript.CodeSettings]::new() #$Settings.MinifyCode = $true #$Settings.OutputMode = [NUglify.OutputMode]::MultipleLines #$Settings.Indent = $Indent #$Settings.JsSettings.MinifyCode = $true #$Settings.JsSettings.OutputMode = [NUglify.OutputMode]::MultipleLines #$Settings.JsSettings.Indent = $Indent #$Settings.JsSettings.BlocksStartOnSameLine = $BlockStartLine [NUglify.Uglify]::Js($Content).Code } function Convert-HTMLToText { [CmdletBinding()] param( [string] $File, [string] $OutputFile, [string] $Content ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Convert-HTMLToText - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Convert-HTMLToText - No choice file or Content. Termninated.' return } $Output = Convert-InternalHTMLToText -Content $Content # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } } function ConvertFrom-HTMLAttributes { [alias('ConvertFrom-HTMLTag', 'ConvertFrom-HTMLClass')] [cmdletbinding()] param ( [Parameter(Mandatory = $true)][Array] $Content, [string] $Tag, [string] $Class, [string] $Id, [string] $Name, [switch] $ReturnObject ) Begin { # Initialize the parser $HTMLParser = [AngleSharp.Html.Parser.HtmlParser]::new() } Process { # Load the html $ParsedDocument = $HTMLParser.ParseDocument($content) # Get all the tables if ($Tag) { [Array] $OutputContent = $ParsedDocument.GetElementsByTagName($Tag) } elseif ($Class) { [Array] $OutputContent = $ParsedDocument.GetElementsByClassName($Class) } elseif ($Id) { [Array] $OutputContent = $ParsedDocument.GetElementById($Id) } elseif ($Name) { [Array] $OutputContent = $ParsedDocument.GetElementsByName($Name) } if ($OutputContent) { if ($ReturnObject) { $OutputContent } else { $OutputContent.TextContent } } } End { } } Function ConvertFrom-HtmlTable { [cmdletbinding()] param ( [Parameter(Mandatory, ParameterSetName = 'Content', ValueFromPipeline, ValueFromPipelineByPropertyName)][string]$Content, [alias('Uri')][Parameter(Mandatory, ParameterSetName = 'Uri')][Uri] $Url, [System.Collections.IDictionary] $ReplaceContent, [System.Collections.IDictionary] $ReplaceHeaders, [ValidateSet('AngleSharp', 'AgilityPack')] $Engine, [switch] $ReverseTable ) Begin { # This fixes an issue https://github.com/PowerShell/PowerShell/issues/11287 for ConvertTo-HTML $HeadersReplacement = [ordered] @{ '\*' = ''; } if (-not $ReplaceHeaders) { $ReplaceHeaders = [ordered] @{ } } foreach ($Key in $HeadersReplacement.Keys) { $ReplaceHeaders["$Key"] = $HeadersReplacement.$Key } } Process { if ($Engine -eq 'AngleSharp' -and -not $ReverseTable) { ConvertFrom-HTMLTableAngle -Url $Url -Content $Content -ReplaceHeaders $ReplaceHeaders -ReplaceContent $ReplaceContent } else { ConvertFrom-HTMLTableAgilityPack -Url $url -Content $Content -ReplaceHeaders $ReplaceHeaders -ReplaceContent $ReplaceContent -ReverseTable:$ReverseTable } } End { } } function Format-CSS { [CmdletBinding()] param( [string] $File, [string] $OutputFile, [string] $Content ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Format-CSS - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Format-CSS - No choice file or Content. Termninated.' return } $Output = Format-InternalCSS -Content $Content #$Content = "<style>$Content</style>" #$Output = Format-InternalFormatWithUglify -Content $Content -IsFragment # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } } function Format-HTML { [CmdletBinding()] param( [string] $File, [string] $OutputFile, [string] $Content, [string] $Indent = ' ', [NUglify.BlockStart] $BlockStartLine = [NUglify.BlockStart]::SameLine, [switch] $RemoveHTMLComments, [switch] $RemoveOptionalTags, [switch] $OutputTextNodesOnNewLine, [switch] $RemoveEmptyAttributes, [switch] $AlphabeticallyOrderAttributes, [switch] $RemoveEmptyBlocks ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Format-HTML - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Format-HTML - No choice file or Content. Termninated.' return } # Do the magic $formatInternalFormatWithUglifySplat = @{ Content = $Content Indent = $Indent BlockStartLine = $BlockStartLine OutputTextNodesOnNewLine = $OutputTextNodesOnNewLine RemoveOptionalTags = $RemoveOptionalTags RemoveEmptyAttributes = $RemoveEmptyAttributes AlphabeticallyOrderAttributes = $AlphabeticallyOrderAttributes RemoveEmptyBlocks = $RemoveEmptyBlocks RemoveComments = $RemoveHTMLComments #IsFragment = $true } $Output = Format-InternalFormatWithUglify @formatInternalFormatWithUglifySplat # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } } function Format-JavaScript { [alias('Format-JS')] [CmdletBinding()] param( [string] $File, [string] $OutputFile, [alias('FileContent')][string] $Content ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Format-JavaScript - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Format-JavaScript - No choice file or Content. Termninated.' return } # For now don't want to give this as an option [int] $IndentSize = 4 [string] $IndentChar = ' ' [bool] $IndentWithTabs = $false [bool] $PreserveNewlines = $true [double] $MaxPreserveNewlines = 10.0 [bool] $JslintHappy = $false [Jsbeautifier.BraceStyle] $BraceStyle = [Jsbeautifier.BraceStyle]::Collapse [bool] $KeepArrayIndentation = $false [bool] $KeepFunctionIndentation = $false [bool] $EvalCode = $false #[int] $WrapLineLength = 0 [bool] $BreakChainedMethods = $false # do the magic $SplatJS = @{ IndentSize = $IndentSize IndentChar = $IndentChar IndentWithTabs = $IndentWithTabs PreserveNewlines = $PreserveNewlines MaxPreserveNewlines = $MaxPreserveNewlines JslintHappy = $JslintHappy BraceStyle = $BraceStyle KeepArrayIndentation = $KeepArrayIndentation KeepFunctionIndentation = $KeepFunctionIndentation EvalCode = $EvalCode #WrapLineLength = $WrapLineLength BreakChainedMethods = $BreakChainedMethods } #$Output = Format-InternalJS -Content $Content @SplatJS $Output = Format-InternalUglifyJS -Content $Content if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } <# $IndentLenght = $Indent.Length $Content = "<script>$Content</script>" $Output = Format-InternalFormatWithUglify -Content $Content -IsFragment $SplitOutput = ($Output.Split("`n")) $NewOutput = for ($i = 1; $i -lt $SplitOutput.Count - 1; $i++) { $SplitOutput[$i].SubString($IndentLenght) } $FinalOutput = $NewOutput -join "`n" # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $FinalOutput) } else { $FinalOutput } #> } function Optimize-CSS { [CmdletBinding()] param( [string] $File, [string] $OutputFile, [string] $Content ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Optimize-CSS - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Optimize-CSS - No choice file or Content. Termninated.' return } # Do magic #$Output = Optimize-InternalCSS -Content $Content $Output = Optimize-InternalUglifyCSS -Content $Content # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } } function Optimize-HTML { [CmdletBinding()] param( [string] $File, [string] $OutputFile, [string] $Content, [switch] $CSSDecodeEscapes ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Optimize-HTML - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Optimize-HTML - No choice file or Content. Termninated.' return } # Do magic $Output = Optimize-InternalUglifyHTML -Content $Content -CSSDecodeEscapes:$CSSDecodeEscapes # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } } function Optimize-JavaScript { [CmdletBinding()] param( [string] $File, [string] $OutputFile, [string] $Content ) # Load from file or text if ($File) { if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else { Write-Warning "Optimize-JavaScript - File doesn't exists" return } } elseif ($Content) { } else { Write-Warning 'Optimize-JavaScript - No choice file or Content. Termninated.' return } $Output = Optimize-InternalUglifyJS -Content $Content # Output to file or to text if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output } } if ($PSEdition -eq 'Core') { Add-Type -Path $PSScriptRoot\Lib\Standard\AngleSharp.Css.dll Add-Type -Path $PSScriptRoot\Lib\Standard\AngleSharp.dll Add-Type -Path $PSScriptRoot\Lib\Standard\HtmlAgilityPack.dll Add-Type -Path $PSScriptRoot\Lib\Standard\Jsbeautifier.dll Add-Type -Path $PSScriptRoot\Lib\Standard\NUglify.dll Add-Type -Path $PSScriptRoot\Lib\Standard\System.Text.Encoding.CodePages.dll } else { Add-Type -Path $PSScriptRoot\Lib\Standard\AngleSharp.Css.dll Add-Type -Path $PSScriptRoot\Lib\Standard\AngleSharp.dll Add-Type -Path $PSScriptRoot\Lib\Standard\HtmlAgilityPack.dll Add-Type -Path $PSScriptRoot\Lib\Standard\Jsbeautifier.dll Add-Type -Path $PSScriptRoot\Lib\Standard\NUglify.dll Add-Type -Path $PSScriptRoot\Lib\Standard\System.Text.Encoding.CodePages.dll } Export-ModuleMember -Function @('ConvertFrom-HTMLAttributes', 'ConvertFrom-HtmlTable', 'Convert-HTMLToText', 'Format-CSS', 'Format-HTML', 'Format-JavaScript', 'Optimize-CSS', 'Optimize-HTML', 'Optimize-JavaScript') -Alias @('ConvertFrom-HTMLClass', 'ConvertFrom-HTMLTag', 'Format-JS') # SIG # Begin signature block # MIIdSQYJKoZIhvcNAQcCoIIdOjCCHTYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUokawoxxRrMqA84arHTe9CU2C # gsigghhnMIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0B # AQUFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg # Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg # +XESpa7cJpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lT # XDGEKvYPmDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5 # a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g # 0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1 # roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf # GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G # A1UdDgQWBBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLL # gjEtUYunpyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3 # cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmr # EthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+ # fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5Q # Z7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu # 838fYxAe+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw # 8jCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZIhvcNAQELBQAw # cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk # IElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAxMDYwMDAw # MDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4G # A1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqGSIb3DQEBAQUA # A4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVNlLQMULUmEP4d # yG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXeAhjzeG28ffnH # bQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPsTm0zinxdRS1L # sVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMDgzEpSlwMMYpK # jIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8H6GHq756Wwog # L0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4MIIBtDAOBgNV # HQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD # CDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIBFhtodHRwOi8v # d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+Ka7S5GGlsqIl # ssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEGA1UdHwRqMGgw # MqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMu # Y3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVk # LXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz # cC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNlcnRzLmRpZ2lj # ZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBpbmdDQS5jcnQw # DQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJRdAojR6OrktIl # xHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo9VFKeHk2eie3 # 8+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPtkMyNoRdzDfTz # ZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ2CKadRVC9S0y # OIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdKDXF+l7f0P4Tr # weOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUwMIIEGKADAgEC # AhAECRgbX9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEw # MjIxMjAwMDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEi # MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7 # RZmxOttE9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p # 0WfTxvspJ8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj # 6YgsIJWuHEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grk # V7tKtel05iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHy # DxL0xY4PwaLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMB # AAGjggHNMIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAT # BgNVHSUEDDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGG # GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2Nh # Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCB # gQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lD # ZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNl # cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgG # CmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu # Y29tL0NQUzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1 # DlgwHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQEL # BQADggEBAD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q # 3yBVN7Dh9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/ # kLEbBw6RFfu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dc # IFzZcbEMj7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6 # dGRrsutmQ9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT # +hKUGIUukpHqaGxEMrJmoecYpJpkUe8wggUxMIIEGaADAgECAhAKoSXW1jIbfkHk # Bdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE # aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMT # G0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xNjAxMDcxMjAwMDBaFw0z # MTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0 # IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0EwggEiMA0GCSqGSIb3DQEB # AQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92puoKZxTlUKFe2I0rEDgdFM1EQfdD5 # fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I1moUADj3Lh477sym9jJZ/l9lP+Cb # 6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6Ij4YrBHk8JkDbTuFfAnT7l3ImgtU # 46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkUxk0kIzBdvOw8YGqsLwfM/fDqR9mI # UF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqYD4R/nzEU1q3V8mTLex4F0IQZchfx # FwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXdrKzpVv+TAgMBAAGjggHOMIIByjAd # BgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgXNW4wHwYDVR0jBBgwFoAUReuir/SS # y4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMC # AYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6 # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5j # cnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwUAYDVR0gBEkw # RzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2lj # ZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4IBAQBxlRLp # UYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC/cWnww4gQiyvd/MrHwwhWiq3BTQd # aq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6CJR7Euhx7LCHi1lssFDVDBGiy23UC # 4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyvKYnleB/WCxSlgNcSR3CzddWThZN+ # tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOFIoxhynmUfln8jA/jb7UBJrZspe6H # USHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bhfEJCKMYYVs9BNLZmXbZ0e/VWMyIv # IjayS6JKldj1po5SMIIFPTCCBCWgAwIBAgIQBNXcH0jqydhSALrNmpsqpzANBgkq # hkiG9w0BAQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT # SEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMDYyNjAwMDAwMFoX # DTIzMDcwNzEyMDAwMFowejELMAkGA1UEBhMCUEwxEjAQBgNVBAgMCcWabMSFc2tp # ZTERMA8GA1UEBxMIS2F0b3dpY2UxITAfBgNVBAoMGFByemVteXPFgmF3IEvFgnlz # IEVWT1RFQzEhMB8GA1UEAwwYUHJ6ZW15c8WCYXcgS8WCeXMgRVZPVEVDMIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7KB3iyBrhkLUbbFe9qxhKKPBYqD # Bqlnr3AtpZplkiVjpi9dMZCchSeT5ODsShPuZCIxJp5I86uf8ibo3vi2S9F9AlfF # jVye3dTz/9TmCuGH8JQt13ozf9niHecwKrstDVhVprgxi5v0XxY51c7zgMA2g1Ub # +3tii0vi/OpmKXdL2keNqJ2neQ5cYly/GsI8CREUEq9SZijbdA8VrRF3SoDdsWGf # 3tZZzO6nWn3TLYKQ5/bw5U445u/V80QSoykszHRivTj+H4s8ABiforhi0i76beA6 # Ea41zcH4zJuAp48B4UhjgRDNuq8IzLWK4dlvqrqCBHKqsnrF6BmBrv+BXQIDAQAB # o4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0O # BBYEFBixNSfoHFAgJk4JkDQLFLRNlJRmMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUE # DDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOgMYYvaHR0cDovL2Ny # bDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwTAYDVR0gBEUw # QzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNl # cnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgwdjAkBggrBgEFBQcw # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUFBzAChkJodHRwOi8v # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNzdXJlZElEQ29kZVNp # Z25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAmr1s # z4lsLARi4wG1eg0B8fVJFowtect7SnJUrp6XRnUG0/GI1wXiLIeow1UPiI6uDMsR # XPHUF/+xjJw8SfIbwava2eXu7UoZKNh6dfgshcJmo0QNAJ5PIyy02/3fXjbUREHI # NrTCvPVbPmV6kx4Kpd7KJrCo7ED18H/XTqWJHXa8va3MYLrbJetXpaEPpb6zk+l8 # Rj9yG4jBVRhenUBUUj3CLaWDSBpOA/+sx8/XB9W9opYfYGb+1TmbCkhUg7TB3gD6 # o6ESJre+fcnZnPVAPESmstwsT17caZ0bn7zETKlNHbc1q+Em9kyBjaQRcEQoQQNp # ezQug9ufqExx6lHYDjGCBEwwggRIAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYD # VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAv # BgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EC # EATV3B9I6snYUgC6zZqbKqcwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAI # oAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIB # CzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFCVP6I65QeKk1TI4orhy # fV1MuvGXMA0GCSqGSIb3DQEBAQUABIIBAFAuLiA52ciuyvlsQ6JR5JI27IhEdEz+ # 4GbQJyoOBRuCkMW+Xg4czw8nu5QHwcJizag6w1RNikOUqxn8TINGEZ1SqDEj+BGP # qkC+vS4K7XnGrtN+xEhpChEjDqZe6G8jassq5f46BvljpWCkzX0+XKqukCKf/aXy # RIvZsyCF+Xspqtqqje+RU+2W+nb2R6NkEymqxSSwROuU+kmDKTycktvGFNCYg2kT # mlRS25tK4+Xffok3uZVby7Luz8OVgCzU+CSIHMgA11zwxULwrw4xSEG01V9HbzVm # gVG1gIBtE4Jqn0NLdaUjTMSNN6R6a6uUV1en0CuNq/tfSYgWcQdjlu6hggIgMIIC # HAYJKoZIhvcNAQkGMYICDTCCAgkCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G # A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQQIQ # DUJK4L46iP9gQCHOFADw3TAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqG # SIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjEwMjAyMTkxMzMwWjAjBgkqhkiG9w0B # CQQxFgQUh9jVsnaCccwziI6BV8r4zYJGV6owDQYJKoZIhvcNAQEBBQAEggEAMTGk # WTwAbLjRGQuzGNC5sARIe9CuogYXbmPGHSkviRSlVPT0QLIa/2ylHEP8jJbj7C2t # lIfKfEJ8vS7o4+FpzX6w54s1i+KjTw8ojikRjcT+lLWxuC3NivFyI9KKdQaT1LAX # ZPiZoey2DqThOrhnNXOepIQLP/0U3tvUEOT+bu9F2nOeezX9s7vjajqusIedIdGY # MR0VsnktzDAXJeOeUnBkUqOcMzdx/u1lEVQHuDQIKCM8IAN1tGffF4LAetGlZxkN # vFadhyVtv1CUFNBi5NEu5amBnw+f1Gax2AwXnm9oKDeqFKsJHJ7E5Cxv7hKe1xNt # O32zwtiwQ0I2t3yHNg== # SIG # End signature block |