Src/Plugins/Private/OutText.Internal.ps1
#region OutText Private Functions function New-PScriboTextOption { <# .SYNOPSIS Sets the text plugin specific formatting/output options. .NOTES All plugin options should be prefixed with the plugin name. #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')] [OutputType([System.Collections.Hashtable])] param ( ## Text/output width. 0 = none/no wrap. [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()] [System.Int32] $TextWidth = 120, ## Document header separator character. [Parameter(ValueFromPipelineByPropertyName)] [ValidateLength(1,1)] [System.String] $HeaderSeparator = '=', ## Document section separator character. [Parameter(ValueFromPipelineByPropertyName)] [ValidateLength(1,1)] [System.String] $SectionSeparator = '-', ## Document section separator character. [Parameter(ValueFromPipelineByPropertyName)] [ValidateLength(1,1)] [System.String] $LineBreakSeparator = '_', ## Default header/section separator width. [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()] [System.Int32] $SeparatorWidth = $TextWidth, ## Text encoding [Parameter(ValueFromPipelineByPropertyName)] [ValidateSet('ASCII','Unicode','UTF7','UTF8')] [System.String] $Encoding = 'ASCII' ) process { return @{ TextWidth = $TextWidth; HeaderSeparator = $HeaderSeparator; SectionSeparator = $SectionSeparator; LineBreakSeparator = $LineBreakSeparator; SeparatorWidth = $SeparatorWidth; Encoding = $Encoding; } } #end process } #end function New-PScriboTextOption function OutTextTOC { <# .SYNOPSIS Output formatted Table of Contents #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $TOC ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboTextOption; } } process { $tocBuilder = New-Object -TypeName System.Text.StringBuilder; [ref] $null = $tocBuilder.AppendLine($TOC.Name); [ref] $null = $tocBuilder.AppendLine(''.PadRight($options.SeparatorWidth, $options.SectionSeparator)); if ($Options.ContainsKey('EnableSectionNumbering')) { $maxSectionNumberLength = $Document.TOC.Number | ForEach-Object { $_.Length } | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum; foreach ($tocEntry in $Document.TOC) { $sectionNumberPaddingLength = $maxSectionNumberLength - $tocEntry.Number.Length; $sectionNumberIndent = ''.PadRight($tocEntry.Level, ' '); $sectionPadding = ''.PadRight($sectionNumberPaddingLength, ' '); [ref] $null = $tocBuilder.AppendFormat('{0}{1} {2}{3}', $tocEntry.Number, $sectionPadding, $sectionNumberIndent, $tocEntry.Name).AppendLine(); } #end foreach TOC entry } else { $maxSectionNumberLength = $Document.TOC.Level | Sort-Object | Select-Object -Last 1; foreach ($tocEntry in $Document.TOC) { $sectionNumberIndent = ''.PadRight($tocEntry.Level, ' '); [ref] $null = $tocBuilder.AppendFormat('{0}{1}', $sectionNumberIndent, $tocEntry.Name).AppendLine(); } #end foreach TOC entry } return $tocBuilder.ToString(); } #end process } #end function OutTextTOC function OutTextBlankLine { <# .SYNOPSIS Output formatted text blankline. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $BlankLine ) process { $blankLineBuilder = New-Object -TypeName System.Text.StringBuilder; for ($i = 0; $i -lt $BlankLine.LineCount; $i++) { [ref] $null = $blankLineBuilder.AppendLine(); } return $blankLineBuilder.ToString(); } #end process } #end function OutHtmlBlankLine function OutTextSection { <# .SYNOPSIS Output formatted text section. #> [CmdletBinding()] param ( ## Section to output [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Section ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboTextOption; } } process { $padding = ''.PadRight(($Section.Tabs * 4), ' '); $sectionBuilder = New-Object -TypeName System.Text.StringBuilder; if ($Document.Options['EnableSectionNumbering']) { [string] $sectionName = '{0} {1}' -f $Section.Number, $Section.Name; } else { [string] $sectionName = '{0}' -f $Section.Name; } [ref] $null = $sectionBuilder.AppendLine(); [ref] $null = $sectionBuilder.Append($padding); [ref] $null = $sectionBuilder.AppendLine($sectionName.TrimStart()); [ref] $null = $sectionBuilder.Append($padding); [ref] $null = $sectionBuilder.AppendLine(''.PadRight(($options.SeparatorWidth - $padding.Length), $options.SectionSeparator)); foreach ($s in $Section.Sections.GetEnumerator()) { if ($s.Id.Length -gt 40) { $sectionId = '{0}..' -f $s.Id.Substring(0,38); } else { $sectionId = $s.Id; } $currentIndentationLevel = 1; if ($null -ne $s.PSObject.Properties['Level']) { $currentIndentationLevel = $s.Level +1; } WriteLog -Message ($localized.PluginProcessingSection -f $s.Type, $sectionId) -Indent $currentIndentationLevel; switch ($s.Type) { 'PScribo.Section' { [ref] $null = $sectionBuilder.Append((OutTextSection -Section $s)); } 'PScribo.Paragraph' { [ref] $null = $sectionBuilder.Append(($s | OutTextParagraph)); } 'PScribo.PageBreak' { [ref] $null = $sectionBuilder.AppendLine((OutTextPageBreak)); } ## Page breaks implemented as line break with extra padding 'PScribo.LineBreak' { [ref] $null = $sectionBuilder.AppendLine((OutTextLineBreak)); } 'PScribo.Table' { [ref] $null = $sectionBuilder.AppendLine(($s | OutTextTable)); } 'PScribo.BlankLine' { [ref] $null = $sectionBuilder.AppendLine(($s | OutTextBlankLine)); } 'PScribo.Image' { [ref] $null = $sectionBuilder.AppendLine(($s | OutTextImage)); } Default { WriteLog -Message ($localized.PluginUnsupportedSection -f $s.Type) -IsWarning; } } #end switch } #end foreach return $sectionBuilder.ToString(); } #end process } #end function outtextsection function OutTextParagraph { <# .SYNOPSIS Output formatted paragraph text. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Object] $Paragraph ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboTextOption; } } process { $padding = ''.PadRight(($Paragraph.Tabs * 4), ' '); if ([string]::IsNullOrEmpty($Paragraph.Text)) { $text = "$padding$($Paragraph.Id)"; } else { $text = "$padding$($Paragraph.Text)"; } $formattedText = OutStringWrap -InputObject $text -Width $Options.TextWidth; if ($Paragraph.NewLine) { return "$formattedText`r`n"; } else { return $formattedText; } } #end process } #end outtextparagraph function OutTextLineBreak { <# .SYNOPSIS Output formatted line break text. #> [CmdletBinding()] [OutputType([System.String])] param ( ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboTextOption; } } process { ## Use the specified output width if ($options.TextWidth -eq 0) { $options.TextWidth = $Host.UI.RawUI.BufferSize.Width -1; } $lb = ''.PadRight($options.SeparatorWidth, $options.LineBreakSeparator); return "$(OutStringWrap -InputObject $lb -Width $options.TextWidth)`r`n"; } #end process } #end function OutTextLineBreak function OutTextPageBreak { <# .SYNOPSIS Output formatted line break text. #> [CmdletBinding()] [OutputType([System.String])] param ( ) process { return "$(OutTextLineBreak)`r`n"; } #end process } #end function OutTextLineBreak function OutTextTable { <# .SYNOPSIS Output formatted text table. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.Object] $Table ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboTextOption; } } process { ## Use the current output buffer width if ($options.TextWidth -eq 0) { $options.TextWidth = $Host.UI.RawUI.BufferSize.Width -1; } $tableWidth = $options.TextWidth - ($Table.Tabs * 4); if ($Table.List) { $tableText = ($Table.Rows | Select-Object -Property * -ExcludeProperty '*__Style' | Format-List | Out-String -Width $tableWidth).Trim(); } else { ## Don't trim tabs for table headers ## Tables set to AutoSize as otherwise rendering is different between PoSh v4 and v5 $tableText = ($Table.Rows | Select-Object -Property * -ExcludeProperty '*__Style' | Format-Table -Wrap -AutoSize | Out-String -Width $tableWidth).Trim("`r`n"); } $tableText = IndentString -InputObject $tableText -Tabs $Table.Tabs; return ('{0}{1}' -f [System.Environment]::NewLine, $tableText); } #end process } #end function outtexttable function OutStringWrap { <# .SYNOPSIS Outputs objects to strings, wrapping as required. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [Object[]] $InputObject, [Parameter()] [ValidateNotNull()] [System.Int32] $Width = $Host.UI.RawUI.BufferSize.Width ) begin { ## 2 is the minimum, therefore default to wiiiiiiiiiide! if ($Width -lt 2) { $Width = 4096; } WriteLog -Message ('Wrapping text at "{0}" characters.' -f $Width) -IsDebug; } process { foreach ($object in $InputObject) { $textBuilder = New-Object -TypeName System.Text.StringBuilder; $text = (Out-String -InputObject $object).TrimEnd("`r`n"); for ($i = 0; $i -le $text.Length; $i += $Width) { if (($i + $Width) -ge ($text.Length -1)) { [ref] $null = $textBuilder.Append($text.Substring($i)); } else { [ref] $null = $textBuilder.AppendLine($text.Substring($i, $Width)); } } #end for return $textBuilder.ToString(); $textBuilder = $null; } #end foreach } #end process } #end function OutStringWrap function IndentString { <# .SYNOPSIS Indents a block of text using the number of tab stops. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [Object[]] $InputObject, ## Tab indent [Parameter()] [ValidateRange(0,10)] [System.Int32] $Tabs = 0 ) process { $padding = ''.PadRight(($Tabs * 4), ' '); ## Use a StringBuilder to write the table line by line (to indent it) [System.Text.StringBuilder] $builder = New-Object System.Text.StringBuilder; foreach ($line in ($InputObject -split '\r\n?|\n')) { [ref] $null = $builder.Append($padding); [ref] $null = $builder.AppendLine($line.TrimEnd()); ## Trim trailing space (#67) } return $builder.ToString(); } #endprocess } #end function IndentString function OutTextimage { <# .SYNOPSIS Output formatted image text. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [System.Object] $Image ) begin { ## Fix Set-StrictMode if (-not (Test-Path -Path Variable:\Options)) { $options = New-PScriboTextOption; } } process { $imageText = '[Image Text="{0}"]' -f $Image.Text return OutStringWrap -InputObject $imageText -Width $Options.TextWidth } #end process } #end function outtextimage #endregion OutText Private Functions # SIG # Begin signature block # MIIcawYJKoZIhvcNAQcCoIIcXDCCHFgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUNidZGHcBVW+SG4AnhU2NiPJ/ # MKKggheaMIIFIzCCBAugAwIBAgIQAsbTxa4q6RSRmx0hkVyicTANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE5MDcwMzAwMDAwMFoXDTIxMTEw # MzEyMDAwMFowYDELMAkGA1UEBhMCR0IxDzANBgNVBAcTBkxvbmRvbjEfMB0GA1UE # ChMWVmlydHVhbCBFbmdpbmUgTGltaXRlZDEfMB0GA1UEAxMWVmlydHVhbCBFbmdp # bmUgTGltaXRlZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ/s4NME # JLA1Aji4EHJ85uwyEEAepndYn1X8pRnGkOlTzVHITAeH7BQnehjbNwCj7MHUPTSM # zSucXhyfaMZthCNYtugyZ2uU4uVjB1f3xdmXXFX+aukMYgCk1ZQFbQMBqbzRY4Cl # DwlLNGVEjDJeLBUL6ciIETqDc27YLg772WLpuvIXne13EYXN422Y83XRqEMf4v9S # 398S8MRk5qdasRtxYZY6GciZZQnAL/XObpXDM3tDFgcQuyGcZttRuXVZXEj+mlY8 # gUIzkSJ0aJn1pVVTsa+tCvAZuJMJwdPhyM7NUa7Ysm7n9qdF7BvcrWBmaYRfDyya # lLwRoOcI2HVodX8CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nED # wGD5LfZldQ5YMB0GA1UdDgQWBBSDFWXl70FjVfl8IBwATpE46qvGeDAOBgNVHQ8B # Af8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYv # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmww # NaAzoDGGL2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3Mt # ZzEuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGEBggrBgEFBQcB # AQR4MHYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggr # BgEFBQcwAoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hB # MkFzc3VyZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI # hvcNAQELBQADggEBAJ1VZZNMAy8KyQLBqwRWAWDqcOxjVly6FTIeqO2/ul9rEYm8 # B9mNx60/AL+TbTbUwBzia2pwBuIin70eClZHFstvQcASBbB0k14R/rs+jestfFRm # rsEz272POc6vsKce3TOlqBc2rtvVyuUPRvI2yQm1WYTpOgQnnp3ix2LBd+fgRANs # P9yurvnGdEFFzToFDXFVkFHBQ9Pr5tAb4i7ZkSFC52BtB7NVuoiH83lx07SyjIxU # 11ELEDZBpO3HiTsTzbhPAEw4CP++ONK8fieWZevDK9DFEiNIC0gWL/DH1+c7eihO # oJdJqRAT9wkAMIjcskZ5LObGvMst/hqwBewpLzYwggUwMIIEGKADAgECAhAECRgb # X9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYD # VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAi # BgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAw # MDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp # Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERp # Z2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE # 9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvsp # J8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWu # HEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel0 # 5iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4P # waLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHN # MIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUE # DDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0f # BHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNz # dXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29t # L0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG # /WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ # UzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYD # VR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEB # AD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh # 9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6R # Ffu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEM # j7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutm # Q9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUu # kpHqaGxEMrJmoecYpJpkUe8wggZqMIIFUqADAgECAhADAZoCOv9YsWvW1ermF/Bm # MA0GCSqGSIb3DQEBBQUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IEFzc3VyZWQgSUQgQ0EtMTAeFw0xNDEwMjIwMDAwMDBaFw0yNDEwMjIwMDAw # MDBaMEcxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDElMCMGA1UEAxMc # RGlnaUNlcnQgVGltZXN0YW1wIFJlc3BvbmRlcjCCASIwDQYJKoZIhvcNAQEBBQAD # ggEPADCCAQoCggEBAKNkXfx8s+CCNeDg9sYq5kl1O8xu4FOpnx9kWeZ8a39rjJ1V # +JLjntVaY1sCSVDZg85vZu7dy4XpX6X51Id0iEQ7Gcnl9ZGfxhQ5rCTqqEsskYnM # Xij0ZLZQt/USs3OWCmejvmGfrvP9Enh1DqZbFP1FI46GRFV9GIYFjFWHeUhG98oO # jafeTl/iqLYtWQJhiGFyGGi5uHzu5uc0LzF3gTAfuzYBje8n4/ea8EwxZI3j6/oZ # h6h+z+yMDDZbesF6uHjHyQYuRhDIjegEYNu8c3T6Ttj+qkDxss5wRoPp2kChWTrZ # FQlXmVYwk/PJYczQCMxr7GJCkawCwO+k8IkRj3cCAwEAAaOCAzUwggMxMA4GA1Ud # DwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI # MIIBvwYDVR0gBIIBtjCCAbIwggGhBglghkgBhv1sBwEwggGSMCgGCCsGAQUFBwIB # FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIIBZAYIKwYBBQUHAgIwggFW # HoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBm # AGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0 # AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAv # AEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0 # AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAg # AGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBw # AG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBu # AGMAZQAuMAsGCWCGSAGG/WwDFTAfBgNVHSMEGDAWgBQVABIrE5iymQftHt+ivlcN # K2cCzTAdBgNVHQ4EFgQUYVpNJLZJMp1KKnkag0v0HonByn0wfQYDVR0fBHYwdDA4 # oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE # Q0EtMS5jcmwwOKA2oDSGMmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dEFzc3VyZWRJRENBLTEuY3JsMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNydDANBgkq # hkiG9w0BAQUFAAOCAQEAnSV+GzNNsiaBXJuGziMgD4CH5Yj//7HUaiwx7ToXGXEX # zakbvFoWOQCd42yE5FpA+94GAYw3+puxnSR+/iCkV61bt5qwYCbqaVchXTQvH3Gw # g5QZBWs1kBCge5fH9j/n4hFBpr1i2fAnPTgdKG86Ugnw7HBi02JLsOBzppLA044x # 2C/jbRcTBu7kA7YUq/OPQ6dxnSHdFMoVXZJB2vkPgdGZdA0mxA5/G7X1oPHGdwYo # FenYk+VVFvC7Cqsc21xIJ2bIo4sKHOWV2q7ELlmgYd3a822iYemKC23sEhi991VU # QAOSK2vCUcIKSK+w1G7g9BQKOhvjjz3Kr2qNe9zYRDCCBs0wggW1oAMCAQICEAb9 # +QOWA63qAArrPye7uhswDQYJKoZIhvcNAQEFBQAwZTELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEk # MCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTA2MTExMDAw # MDAwMFoXDTIxMTExMDAwMDAwMFowYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMY # RGlnaUNlcnQgQXNzdXJlZCBJRCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A # MIIBCgKCAQEA6IItmfnKwkKVpYBzQHDSnlZUXKnE0kEGj8kz/E1FkVyBn+0snPgW # Wd+etSQVwpi5tHdJ3InECtqvy15r7a2wcTHrzzpADEZNk+yLejYIA6sMNP4YSYL+ # x8cxSIB8HqIPkg5QycaH6zY/2DDD/6b3+6LNb3Mj/qxWBZDwMiEWicZwiPkFl32j # x0PdAug7Pe2xQaPtP77blUjE7h6z8rwMK5nQxl0SQoHhg26Ccz8mSxSQrllmCsSN # vtLOBq6thG9IhJtPQLnxTPKvmPv2zkBdXPao8S+v7Iki8msYZbHBc63X8djPHgp0 # XEK4aH631XcKJ1Z8D2KkPzIUYJX9BwSiCQIDAQABo4IDejCCA3YwDgYDVR0PAQH/ # BAQDAgGGMDsGA1UdJQQ0MDIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG # CCsGAQUFBwMEBggrBgEFBQcDCDCCAdIGA1UdIASCAckwggHFMIIBtAYKYIZIAYb9 # bAABBDCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNlcnQuY29tL3Nz # bC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5 # ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABl # ACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAg # AG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABh # AG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwBy # AGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBp # AGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABl # AGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJ # YIZIAYb9bAMVMBIGA1UdEwEB/wQIMAYBAf8CAQAweQYIKwYBBQUHAQEEbTBrMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKG # N2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv # b3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9j # cmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwHQYD # VR0OBBYEFBUAEisTmLKZB+0e36K+Vw0rZwLNMB8GA1UdIwQYMBaAFEXroq/0ksuC # MS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBBQUAA4IBAQBGUD7Jtygkpzgdtlspr1LP # UukxR6tWXHvVDQtBs+/sdR90OPKyXGGinJXDUOSCuSPRujqGcq04eKx1XRcXNHJH # hZRW0eu7NoR3zCSl8wQZVann4+erYs37iy2QwsDStZS9Xk+xBdIOPRqpFFumhjFi # qKgz5Js5p8T1zh14dpQlc+Qqq8+cdkvtX8JLFuRLcEwAiR78xXm8TBJX/l/hHrwC # Xaj++wc4Tw3GXZG5D2dFzdaD7eeSDY2xaYxP+1ngIw/Sqq4AfO6cQg7Pkdcntxbu # D8O9fAqg7iwIVYUiuOsYGk38KiGtSTGDR5V3cdyxG0tLHBCcdxTBnU8vWpUIKRAm # MYIEOzCCBDcCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 # IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNl # cnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQAsbTxa4q6RSRmx0h # kVyicTAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC # NwIBFTAjBgkqhkiG9w0BCQQxFgQUep4s/fDnz5j9IjgdrYIONV6B3towDQYJKoZI # hvcNAQEBBQAEggEAi8FYJJqHgHaep1W7WtYPy7Gro687MChCPk9nAii8n0l+d0HD # kVT3Ou8Y2fOZT/iHti8/o1TYR5EeYeahh1bs0X8XrnZwSc5+jspA/IFyQMwGlITU # 9dYT2F3BscLvcq6v9N0FddrKNjU5WRcbtcfJitCXkCJuSqEUnjcEpVmcgtzGpX3e # vIvw3+BRshB2qC83SVTEbZBVbUaglOW0Z/kXD2eJ5jTGCfoHXeIYDilT/04BJD4C # MobCOBz7jUXyNEE1E0vI7pPH1mRlGuHe0YGcLLHodDq1FgNW5h21mdh3Bs9s8P3F # Pkst3+K5Xt55gTV3Kxgr9O5ByWOaleuWopGHbaGCAg8wggILBgkqhkiG9w0BCQYx # ggH8MIIB+AIBATB2MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IEFzc3VyZWQgSUQgQ0EtMQIQAwGaAjr/WLFr1tXq5hfwZjAJBgUrDgMCGgUAoF0w # GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwMjI0 # MDk0MzIyWjAjBgkqhkiG9w0BCQQxFgQU33yHUxVNL1VVyi/PWvvupDk5aIQwDQYJ # KoZIhvcNAQEBBQAEggEAOT14uKRvF+90swNcLKAdWjpLLK9beKTjIL65aW5yWi1i # SR916SfHQ5fVqPc+g7JLn6/YkP8W8CwetP3wt5qfKb9jPCKxfsbb5a9uvSQI6YL1 # 7mL24IpSSPZBm5keOB7It/uAZp0ZbLtSazQdWuhM/wPy9OXAF7FbdCZSzHOSFtdf # 7n6WP5LdFUjsF8YTdxDzeeAvJ6OHkE2CUwQFoqSvKZwWtibeLpxmUeKy1yFA+jNs # Na0blXNzeum9rp0cqzHZS697+4zMTX9Twb/uy+qKi5MHKH0ShFlgy4enxeca9l6Q # 3Xhm3tRfjk0F+m/kCRpHRVlVa9c8ODY3s69QxEBu/g== # SIG # End signature block |