TheDashboard.psm1
function Format-AddSpaceToSentence { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Text Parameter description .EXAMPLE $test = @( 'OnceUponATime', 'OnceUponATime1', 'Money@Risk', 'OnceUponATime123', 'AHappyMan2014' 'OnceUponATime_123' ) Format-AddSpaceToSentence -Text $Test $Test | Format-AddSpaceToSentence -ToLowerCase .NOTES General notes #> [CmdletBinding()] param([Parameter(Mandatory = $false, ValueFromPipeline = $true, Position = 0)][string[]] $Text, [switch] $ToLowerCase) Begin {} Process { $Value = foreach ($T in $Text) { ($T -creplace '([A-Z\W_]|\d+)(?<![a-z])', ' $&').trim() } if ($ToLowerCase) { $Value.ToLower() } else { $Value } } End {} } function Get-GitHubLatestRelease { <# .SYNOPSIS Gets one or more releases from GitHub repository .DESCRIPTION Gets one or more releases from GitHub repository .PARAMETER Url Url to github repository .EXAMPLE Get-GitHubLatestRelease -Url "https://api.github.com1/repos/evotecit/Testimo/releases" | Format-Table .NOTES General notes #> [CmdLetBinding()] param([parameter(Mandatory)][alias('ReleasesUrl')][uri] $Url) $ProgressPreference = 'SilentlyContinue' $Responds = Test-Connection -ComputerName $URl.Host -Quiet -Count 1 if ($Responds) { Try { [Array] $JsonOutput = (Invoke-WebRequest -Uri $Url -ErrorAction Stop | ConvertFrom-Json) foreach ($JsonContent in $JsonOutput) { [PSCustomObject] @{PublishDate = [DateTime] $JsonContent.published_at CreatedDate = [DateTime] $JsonContent.created_at PreRelease = [bool] $JsonContent.prerelease Version = [version] ($JsonContent.name -replace 'v', '') Tag = $JsonContent.tag_name Branch = $JsonContent.target_commitish Errors = '' } } } catch { [PSCustomObject] @{PublishDate = $null CreatedDate = $null PreRelease = $null Version = $null Tag = $null Branch = $null Errors = $_.Exception.Message } } } else { [PSCustomObject] @{PublishDate = $null CreatedDate = $null PreRelease = $null Version = $null Tag = $null Branch = $null Errors = "No connection (ping) to $($Url.Host)" } } $ProgressPreference = 'Continue' } function Remove-EmptyValue { [alias('Remove-EmptyValues')] [CmdletBinding()] param([alias('Splat', 'IDictionary')][Parameter(Mandatory)][System.Collections.IDictionary] $Hashtable, [string[]] $ExcludeParameter, [switch] $Recursive, [int] $Rerun, [switch] $DoNotRemoveNull, [switch] $DoNotRemoveEmpty, [switch] $DoNotRemoveEmptyArray, [switch] $DoNotRemoveEmptyDictionary) foreach ($Key in [string[]] $Hashtable.Keys) { if ($Key -notin $ExcludeParameter) { if ($Recursive) { if ($Hashtable[$Key] -is [System.Collections.IDictionary]) { if ($Hashtable[$Key].Count -eq 0) { if (-not $DoNotRemoveEmptyDictionary) { $Hashtable.Remove($Key) } } else { Remove-EmptyValue -Hashtable $Hashtable[$Key] -Recursive:$Recursive } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } } if ($Rerun) { for ($i = 0; $i -lt $Rerun; $i++) { Remove-EmptyValue -Hashtable $Hashtable -Recursive:$Recursive } } } function Start-TimeLog { [CmdletBinding()] param() [System.Diagnostics.Stopwatch]::StartNew() } function Stop-TimeLog { [CmdletBinding()] param ([Parameter(ValueFromPipeline = $true)][System.Diagnostics.Stopwatch] $Time, [ValidateSet('OneLiner', 'Array')][string] $Option = 'OneLiner', [switch] $Continue) Begin {} Process { if ($Option -eq 'Array') { $TimeToExecute = "$($Time.Elapsed.Days) days", "$($Time.Elapsed.Hours) hours", "$($Time.Elapsed.Minutes) minutes", "$($Time.Elapsed.Seconds) seconds", "$($Time.Elapsed.Milliseconds) milliseconds" } else { $TimeToExecute = "$($Time.Elapsed.Days) days, $($Time.Elapsed.Hours) hours, $($Time.Elapsed.Minutes) minutes, $($Time.Elapsed.Seconds) seconds, $($Time.Elapsed.Milliseconds) milliseconds" } } End { if (-not $Continue) { $Time.Stop() } return $TimeToExecute } } function Write-Color { <# .SYNOPSIS Write-Color is a wrapper around Write-Host. It provides: - Easy manipulation of colors, - Logging output to file (log) - Nice formatting options out of the box. .DESCRIPTION Author: przemyslaw.klys at evotec.pl Project website: https://evotec.xyz/hub/scripts/write-color-ps1/ Project support: https://github.com/EvotecIT/PSWriteColor Original idea: Josh (https://stackoverflow.com/users/81769/josh) .EXAMPLE Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow .EXAMPLE Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan .EXAMPLE Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan -StartTab 3 -LinesBefore 1 -LinesAfter 1 .EXAMPLE Write-Color "1. ", "Option 1" -Color Yellow, Green Write-Color "2. ", "Option 2" -Color Yellow, Green Write-Color "3. ", "Option 3" -Color Yellow, Green Write-Color "4. ", "Option 4" -Color Yellow, Green Write-Color "9. ", "Press 9 to exit" -Color Yellow, Gray -LinesBefore 1 .EXAMPLE Write-Color -LinesBefore 2 -Text "This little ","message is ", "written to log ", "file as well." ` -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" -TimeFormat "yyyy-MM-dd HH:mm:ss" Write-Color -Text "This can get ","handy if ", "want to display things, and log actions to file ", "at the same time." ` -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" .EXAMPLE # Added in 0.5 Write-Color -T "My text", " is ", "all colorful" -C Yellow, Red, Green -B Green, Green, Yellow wc -t "my text" -c yellow -b green wc -text "my text" -c red .NOTES Additional Notes: - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx #> [alias('Write-Colour')] [CmdletBinding()] param ([alias ('T')] [String[]]$Text, [alias ('C', 'ForegroundColor', 'FGC')] [ConsoleColor[]]$Color = [ConsoleColor]::White, [alias ('B', 'BGC')] [ConsoleColor[]]$BackGroundColor = $null, [alias ('Indent')][int] $StartTab = 0, [int] $LinesBefore = 0, [int] $LinesAfter = 0, [int] $StartSpaces = 0, [alias ('L')] [string] $LogFile = '', [Alias('DateFormat', 'TimeFormat')][string] $DateTimeFormat = 'yyyy-MM-dd HH:mm:ss', [alias ('LogTimeStamp')][bool] $LogTime = $true, [int] $LogRetry = 2, [ValidateSet('unknown', 'string', 'unicode', 'bigendianunicode', 'utf8', 'utf7', 'utf32', 'ascii', 'default', 'oem')][string]$Encoding = 'Unicode', [switch] $ShowTime, [switch] $NoNewLine) $DefaultColor = $Color[0] if ($null -ne $BackGroundColor -and $BackGroundColor.Count -ne $Color.Count) { Write-Error "Colors, BackGroundColors parameters count doesn't match. Terminated." return } if ($LinesBefore -ne 0) { for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host -Object "`n" -NoNewline } } if ($StartTab -ne 0) { for ($i = 0; $i -lt $StartTab; $i++) { Write-Host -Object "`t" -NoNewline } } if ($StartSpaces -ne 0) { for ($i = 0; $i -lt $StartSpaces; $i++) { Write-Host -Object ' ' -NoNewline } } if ($ShowTime) { Write-Host -Object "[$([datetime]::Now.ToString($DateTimeFormat))] " -NoNewline } if ($Text.Count -ne 0) { if ($Color.Count -ge $Text.Count) { if ($null -eq $BackGroundColor) { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewline } } else { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewline } } } else { if ($null -eq $BackGroundColor) { for ($i = 0; $i -lt $Color.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewline } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -NoNewline } } else { for ($i = 0; $i -lt $Color.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewline } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -BackgroundColor $BackGroundColor[0] -NoNewline } } } } if ($NoNewLine -eq $true) { Write-Host -NoNewline } else { Write-Host } if ($LinesAfter -ne 0) { for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host -Object "`n" -NoNewline } } if ($Text.Count -and $LogFile) { $TextToFile = "" for ($i = 0; $i -lt $Text.Length; $i++) { $TextToFile += $Text[$i] } $Saved = $false $Retry = 0 Do { $Retry++ try { if ($LogTime) { "[$([datetime]::Now.ToString($DateTimeFormat))] $TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append -ErrorAction Stop -WhatIf:$false } else { "$TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append -ErrorAction Stop -WhatIf:$false } $Saved = $true } catch { if ($Saved -eq $false -and $Retry -eq $LogRetry) { $PSCmdlet.WriteError($_) } else { Write-Warning "Write-Color - Couldn't write to log file $($_.Exception.Message). Retrying... ($Retry/$LogRetry)" } } } Until ($Saved -eq $true -or $Retry -ge $LogRetry) } } function Convert-FilesToMenu { [CmdletBinding()] param( [System.Collections.IDictionary] $Folders, [Array] $Files ) # Prepare menu based on files $MenuBuilder = [ordered] @{} # lets build top level based on folders to keep the order of menus foreach ($Folder in $Folders.Keys) { if (-not $MenuBuilder[$Folder]) { $MenuBuilder[$Folder] = [ordered] @{} } } # We now build menu from files foreach ($Entry in $Files) { if (-not $MenuBuilder[$Entry.Menu][$Entry.Name]) { $MenuBuilder[$Entry.Menu][$Entry.Name] = @{ Current = $Entry All = [System.Collections.Generic.List[Object]]::new() } } else { if ($MenuBuilder[$Entry.Menu][$Entry.Name]['Current'].Date -lt $Entry.Date) { $MenuBuilder[$Entry.Menu][$Entry.Name]['Current'] = $Entry } } $MenuBuilder[$Entry.Menu][$Entry.Name]['All'].Add($Entry) } $MenuBuilder } function Convert-FilesToMenuData { [CmdletBinding()] param( [System.Collections.IDictionary] $Folders, [System.Collections.IDictionary] $Replacements ) Write-Color -Text '[i]', "[TheDashboard] ", 'Creating Menu from files', ' [Informative] ' -Color Yellow, DarkGray, Yellow, DarkGray, Magenta foreach ($FolderName in $Folders.Keys) { $Folder = $Folders[$FolderName] $FilesInFolder = Get-ChildItem -LiteralPath $Folders[$FolderName].Path -ErrorAction SilentlyContinue -Filter *.html | Sort-Object -Property Name Write-Color -Text '[i]', "[TheDashboard] ", "Creating Menu from files in folder ", "'$FolderName'", " files in folder ", $($FilesInFolder.Count), ' [Informative] ' -Color Yellow, DarkGray, Yellow, Magenta, Yellow, Magenta, DarkGray foreach ($File in $FilesInFolder) { $Href = "$($Folders[$FolderName].Url)/$($File.Name)" $MenuName = $File.BaseName if ($Folder.ReplacementsGlobal -eq $true) { foreach ($Replace in $Replacements.BeforeSplit.Keys) { $MenuName = $MenuName.Replace($Replace, $Replacements.BeforeSplit[$Replace]) } if ($Replacements.SplitOn) { $Splitted = $MenuName -split $Replacements.SplitOn $Name = $Splitted[0] $NameDate = $Splitted[1] } else { $Name = $MenuName $NameDate = $MenuName } if ($Replacements.AddSpaceToName) { $Name = Format-AddSpaceToSentence -Text $Name } foreach ($Replace in $Replacements.AfterSplit.Keys) { $Name = $Name.Replace($Replace, $Replacements.AfterSplit[$Replace]) } # $NameDate = $Splitted[1] $Type = 'global replacements' } elseif ($Folder.Replacements) { foreach ($Replace in $Folder.Replacements.BeforeSplit.Keys) { $MenuName = $MenuName.Replace($Replace, $Folder.Replacements.BeforeSplit[$Replace]) } if ($Folder.Replacements.SplitOn) { $Splitted = $MenuName -split $Folder.Replacements.SplitOn $Name = $Splitted[0] $NameDate = $Splitted[1] } else { $Name = $MenuName $NameDate = $MenuName } if ($Folder.Replacements.AddSpaceToName) { $Name = Format-AddSpaceToSentence -Text $Name } foreach ($Replace in $Folder.Replacements.AfterSplit.Keys) { $Name = $Name.Replace($Replace, $Folder.Replacements.AfterSplit[$Replace]) } # $NameDate = $Splitted[1] $Type = 'folder replacements' } else { $Name = $MenuName $NameDate = $MenuName $Type = 'no replacements applied' } if ($Name -and $NameDate) { [ordered] @{ Name = $Name NameDate = $NameDate Href = $Href FileName = "$($Folder.Url)_$($File.Name)" Menu = $FolderName Date = $File.LastWriteTime } } else { Write-Color -Text "[e]", "[TheDashboard] ", "Creating Menu ", "[error] ", "Couldn't create menu item for $($File.FullName). Problem with $Type" -Color Red, DarkGray, Red, DarkGray, Red } } } } function Convert-MultipleReplacements { [CmdletBinding()] param( [System.Collections.IDictionary] $Replacements, [Array] $ReplacementConfiguration ) # otherwise try to build the replacement configuration if (-not $Replacements) { $ReplacementSetting = [ordered] @{ SplitOn = $null BeforeSplit = [ordered] @{} AfterSplit = [ordered] @{} AddSpaceToName = $null } } else { $ReplacementSetting = $Replacements } foreach ($Replacement in $ReplacementConfiguration) { Remove-EmptyValue -Hashtable $Replacement foreach ($R in $Replacement.Keys) { if ($R -eq 'SplitOn') { $ReplacementSetting['SplitOn'] = $Replacement[$R] } elseif ($R -eq 'beforeSplit') { foreach ($Before in $Replacement[$R]) { foreach ($Key in $Before.Keys) { $ReplacementSetting['BeforeSplit'][$Key] = $Before[$Key] } } } elseif ($R -eq 'afterSplit') { foreach ($After in $Replacement[$R]) { foreach ($Key in $After.Keys) { $ReplacementSetting['AfterSplit'][$Key] = $After[$Key] } } } elseif ($R -eq 'addSpaceToName') { $ReplacementSetting['AddSpaceToName'] = $Replacement[$R] } } } $ReplacementSetting } function Copy-HTMLFiles { [cmdletbinding()] param( [System.Collections.IDictionary] $Folders, [string] $HTMLPath ) Write-Color -Text '[i]', "[TheDashboard] ", 'Copying or HTML files', ' [Informative] ', $HTMLPath -Color Yellow, DarkGray, Yellow, DarkGray, Magenta foreach ($FolderName in $Folders.Keys) { if ($Folders[$FolderName].CopyFrom) { foreach ($Path in $Folders[$FolderName].CopyFrom) { foreach ($File in Get-ChildItem -LiteralPath $Path -Filter "*.html" -Recurse) { $Destination = $File.FullName.Replace($Path, $Folders[$FolderName].Path) $DIrectoryName = [io.path]::GetDirectoryName($Destination) $null = New-Item -Path $DIrectoryName -ItemType Directory -Force Copy-Item -LiteralPath $File.FullName -Destination $Destination -Force -ErrorAction Stop } } } elseif ($Folders[$FolderName].MoveFrom) { foreach ($Path in $Folders[$FolderName].MoveFrom) { foreach ($File in Get-ChildItem -LiteralPath $Path -Filter "*.html" -Recurse) { $Destination = $File.FullName.Replace($Path, $Folders[$FolderName].Path) $DIrectoryName = [io.path]::GetDirectoryName($Destination) $null = New-Item -Path $DIrectoryName -ItemType Directory -Force Move-Item -LiteralPath $File.FullName -Destination $Destination -Force -ErrorAction Stop } } } } } function Get-GitHubVersion { [cmdletBinding()] param( [Parameter(Mandatory)][string] $Cmdlet, [Parameter(Mandatory)][string] $RepositoryOwner, [Parameter(Mandatory)][string] $RepositoryName ) $App = Get-Command -Name $Cmdlet -ErrorAction SilentlyContinue if ($App) { [Array] $GitHubReleases = (Get-GitHubLatestRelease -Url "https://api.github.com/repos/$RepositoryOwner/$RepositoryName/releases" -Verbose:$false) $LatestVersion = $GitHubReleases[0] if (-not $LatestVersion.Errors) { if ($App.Version -eq $LatestVersion.Version) { "Current/Latest: $($LatestVersion.Version) at $($LatestVersion.PublishDate)" } elseif ($App.Version -lt $LatestVersion.Version) { "Current: $($App.Version), Published: $($LatestVersion.Version) at $($LatestVersion.PublishDate). Update?" } elseif ($App.Version -gt $LatestVersion.Version) { "Current: $($App.Version), Published: $($LatestVersion.Version) at $($LatestVersion.PublishDate). Lucky you!" } } else { "Current: $($App.Version)" } } } function New-DashboardMenu { [CmdletBinding()] param( ) } function New-DashboardMenuFiles { [CmdletBinding()] param( ) } function New-HTMLReport { [cmdletBinding()] param( [Array] $OutputElements, [string] $Logo, [System.Collections.IDictionary] $MenuBuilder, [System.Collections.IDictionary] $Configuration, [System.Collections.IDictionary] $TopStats, [Array] $Files, [string] $HTMLPath, [switch] $ShowHTML, [switch] $Online, [switch] $Force ) $TimeLogHTML = Start-TimeLog Write-Color -Text '[i]', '[HTML ] ', "Generating HTML report ($HTMLPath)" -Color Yellow, DarkGray, Yellow # Build report New-HTML { New-HTMLNavTop -HomeLinkHome -Logo $Logo { foreach ($Menu in $MenuBuilder.Keys) { $TopMenuSplat = @{ Name = $Menu } if ($Configuration.Folders.$Menu.IconType) { $TopMenuSplat[$Configuration.Folders.$Menu.IconType] = $Configuration.Folders.$Menu.Icon } New-NavTopMenu @TopMenuSplat { foreach ($MenuReport in $MenuBuilder[$Menu].Keys) { #$PageName = (( -join ($MenuBuilder[$Menu][$MenuReport].Name, " ", $MenuBuilder[$Menu][$MenuReport].Date)).Replace(":", "_").Replace(" ", "_")) $PageName = (( -join ($MenuBuilder[$Menu][$MenuReport]['Current'].Name)).Replace(":", "_").Replace(" ", "_")) New-NavLink -IconRegular calendar-check -Name $MenuBuilder[$Menu][$MenuReport]['Current'].Name -Href "$($Menu)_$($PageName).html" } } } } -MenuItemsWidth 250px # primary page data New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow New-HTMLPanelStyle -BorderRadius 0px New-HTMLSection -Invisible { foreach ($E in $OutputElements) { New-HTMLPanel { #New-HTMLText -Text 'Users' -Color Red -Alignment center -FontSize 20px New-HTMLGage -Label $E.Label -MinValue $E.MinValue -MaxValue $E.MaxValue -Value $E.Value -Counter $TopStats[$E.Date][$($E.Label)] = $E.Value # New-HTMLText -Text 'Change since last + ', $DifferenceUsers -Color Red -Alignment right -FontSize 20px -SkipParagraph } } } New-HTMLSection -Invisible { New-HTMLPanel { $StatisticsKeys = $TopStats.Keys | Sort-Object | Select-Object -Last 50 [Array] $Dates = foreach ($Day in $StatisticsKeys) { $TopStats[$Day].Date } foreach ($UserInput in $Dates) { $TopStats[$Day].$($UserInput.Label) = $UserInput.Value } New-HTMLChart -Title 'Domain Summary' -TitleAlignment center { New-ChartAxisX -Type datetime -Names $Dates New-ChartAxisY -TitleText 'Numbers' -Show foreach ($UserInput in $OutputElements) { $Values = foreach ($Day in $StatisticsKeys) { $TopStats[$Day].$($UserInput.Label) } New-ChartLine -Name $UserInput.Label -Value $Values } } } New-HTMLPanel { New-HTMLCalendar { foreach ($CalendarEntry in $Files) { # The check make sure that report doesn't run over midnight when using +30 minutes. If it runs over midnight it looks bad as it spans over 2 days # we then remove 30 minutes instead to prevent this if ($($CalendarEntry.Date).Day -eq $($($CalendarEntry.Date).AddMinutes(30)).Day) { New-CalendarEvent -Title $CalendarEntry.Name -StartDate $CalendarEntry.Date -EndDate $($CalendarEntry.Date).AddMinutes(30) -Url $CalendarEntry.FileName } else { New-CalendarEvent -Title $CalendarEntry.Name -StartDate $CalendarEntry.Date.AddMinutes(-30) -EndDate $($CalendarEntry.Date) -Url $CalendarEntry.FileName } } } -HeaderRight @('dayGridMonth', 'timeGridWeek', 'timeGridDay', 'listMonth', 'listYear') } } foreach ($Menu in $MenuBuilder.Keys) { Write-Color -Text '[i]', '[HTML ] ', "Building Menu for ", $Menu -Color Yellow, DarkGray, Yellow, DarkCyan $TopMenuSplat = @{ Name = $Menu } if ($Configuration.Folders.$Menu.IconType) { $TopMenuSplat[$Configuration.Folders.$Menu.IconType] = $Configuration.Folders.$Menu.Icon } foreach ($MenuReport in $MenuBuilder[$Menu].Keys) { $PathToSubReports = [io.path]::GetDirectoryName($HTMLPath) #$PageName = ( -join ($MenuBuilder[$Menu][$MenuReport].Name, " ", $MenuBuilder[$Menu][$MenuReport].Date)).Replace(":", "_").Replace(" ", "_") $PageName = ($MenuBuilder[$Menu][$MenuReport]['Current'].Name).Replace(":", "_").Replace(" ", "_") $FullPath = [io.path]::Combine($PathToSubReports, "$($Menu)_$PageName.html") $CurrentReport = $MenuBuilder[$Menu][$MenuReport]['Current'] $AllReports = $MenuBuilder[$Menu][$MenuReport]['All'] $Name = $CurrentReport.Name New-HTMLReportPage -Report $CurrentReport -AllReports $AllReports -FilePath $FullPath -PathToSubReports $PathToSubReports -Name $Name foreach ($Report in $AllReports) { if ($Report.Name -eq $CurrentReport.Name -and $Report.Date -eq $CurrentReport.Date) { #continue } $FullPathOther = [io.path]::Combine($PathToSubReports, $Report.FileName) $Name = $Report.Name + ' - ' + $Report.Date # we only generate the report if it doesn't exist or if the force parameter is used if ((Test-Path -LiteralPath $FullPathOther) -and -not $Force.IsPresent) { Write-Color -Text '[i]', '[HTML ] ', "Generating HTML page ($MenuReport) report ", "($FullPathOther)", " skipped. Already exists." -Color Yellow, DarkGray, Yellow, Red, Yellow, Yellow } else { New-HTMLReportPage -Report $Report -AllReports $AllReports -FilePath $FullPathOther -PathToSubReports $PathToSubReports -Name $Name } } } Write-Color -Text '[i]', '[HTML ] ', "Ending Menu for ", $Menu -Color Yellow, DarkGray, Yellow, DarkCyan } Write-Color -Text '[i]', '[HTML ] ', "Saving HTML reports (this may take a while...)" -Color Yellow, DarkGray, Yellow } -FilePath $HTMLPath -ShowHTML:$ShowHTML.IsPresent -TitleText 'The Dashboard' -Online:$Online.IsPresent $TimeLogEndHTML = Stop-TimeLog -Time $TimeLogHTML -Option OneLiner Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report', " [Time to execute: $TimeLogEndHTML]" -Color Yellow, DarkGray, Yellow, DarkGray } function New-HTMLReportPage { [cmdletBinding()] param( [System.Collections.IDictionary] $Report, [Array] $AllReports, [string] $FilePath, [string] $PathToSubReports, [string] $Name ) #$TimeLogPageHTML = Start-TimeLog Write-Color -Text '[i]', '[HTML ] ', "Generating HTML page ($MenuReport) report ($FilePath)" -Color Yellow, DarkGray, Yellow New-HTMLPage -Name $Name { New-HTMLSection -HeaderText "Summary for $($Report.Name)" -HeaderBackGroundColor Black { New-HTMLSection -Invisible { New-HTMLPanel { New-HTMLText -Text "Report name: ", $CurrentReport.Name -FontSize 12px New-HTMLText -Text "Report date: ", $CurrentReport.Date -FontSize 12px New-HTMLText -Text "All reports in this catagory: ", $AllReports.Count -FontSize 12px New-HTMLList { New-HTMLListItem -Text "Date ranges from: ", $AllReports[0].Date, " to ", $AllReports[$AllReports.Count - 1].Date -FontSize 12px -FontWeight normal, bold, normal, bold -TextDecoration none, underline, none, underline } } -Invisible } New-HTMLSection -Invisible { New-HTMLCalendar { foreach ($CalendarEntry in $AllReports) { # The check make sure that report doesn't run over midnight when using +30 minutes. If it runs over midnight it looks bad as it spans over 2 days # we then remove 30 minutes instead to prevent this $FullPathOther = [io.path]::Combine($PathToSubReports, $CalendarEntry.FileName) if ($($CalendarEntry.Date).Day -eq $($($CalendarEntry.Date).AddMinutes(30)).Day) { New-CalendarEvent -Title $CalendarEntry.Name -StartDate $CalendarEntry.Date -EndDate $($CalendarEntry.Date).AddMinutes(30) -Url $CalendarEntry.FileName } else { New-CalendarEvent -Title $CalendarEntry.Name -StartDate $CalendarEntry.Date.AddMinutes(-30) -EndDate $($CalendarEntry.Date) -Url $CalendarEntry.FileName } } } -HeaderRight @('dayGridMonth', 'timeGridWeek', 'timeGridDay', 'listMonth', 'listYear') } } -Height 300px New-HTMLSection -Invisible { } -Height 15px New-HTMLFrame -SourcePath $Report.Href -Scrolling Auto -Height 2000px } -FilePath $FilePath #$TimeLogPageEndHTML = Stop-TimeLog -Time $TimeLogPageHTML -Option OneLiner #Write-Color -Text '[i]', '[HTML ] ', "Generating HTML page ($MenuReport) report", " [Time to execute: $TimeLogPageEndHTML]" -Color Yellow, DarkGray, Yellow, DarkGray } # Another way to access # https://use.fontawesome.com/releases/v5.11.2/svgs/brands/accessible-icon.svg # https://github.com/FortAwesome/Font-Awesome/blob/master/UPGRADING.md # https://fontawesome.com/cheatsheet/ $Global:HTMLIcons = [ordered] @{ FontAwesomeBrands = [ordered] @{ '500px' = 'f26e' 'accessible-icon' = 'f368' 'accusoft' = 'f369' 'acquisitions-incorporated' = 'f6af' 'adn' = 'f170' 'adversal' = 'f36a' 'affiliatetheme' = 'f36b' 'airbnb' = 'f834' 'algolia' = 'f36c' 'alipay' = 'f642' 'amazon' = 'f270' 'amazon-pay' = 'f42c' 'amilia' = 'f36d' 'android' = 'f17b' 'angellist' = 'f209' 'angrycreative' = 'f36e' 'angular' = 'f420' 'app-store' = 'f36f' 'app-store-ios' = 'f370' 'apper' = 'f371' 'apple' = 'f179' 'apple-pay' = 'f415' 'artstation' = 'f77a' 'asymmetrik' = 'f372' 'atlassian' = 'f77b' 'audible' = 'f373' 'autoprefixer' = 'f41c' 'avianex' = 'f374' 'aviato' = 'f421' 'aws' = 'f375' 'bandcamp' = 'f2d5' 'battle-net' = 'f835' 'behance' = 'f1b4' 'behance-square' = 'f1b5' 'bimobject' = 'f378' 'bitbucket' = 'f171' 'bitcoin' = 'f379' 'bity' = 'f37a' 'black-tie' = 'f27e' 'blackberry' = 'f37b' 'blogger' = 'f37c' 'blogger-b' = 'f37d' 'bluetooth' = 'f293' 'bluetooth-b' = 'f294' 'bootstrap' = 'f836' 'btc' = 'f15a' 'buffer' = 'f837' 'buromobelexperte' = 'f37f' 'buy-n-large' = 'f8a6' 'canadian-maple-leaf' = 'f785' 'cc-amazon-pay' = 'f42d' 'cc-amex' = 'f1f3' 'cc-apple-pay' = 'f416' 'cc-diners-club' = 'f24c' 'cc-discover' = 'f1f2' 'cc-jcb' = 'f24b' 'cc-mastercard' = 'f1f1' 'cc-paypal' = 'f1f4' 'cc-stripe' = 'f1f5' 'cc-visa' = 'f1f0' 'centercode' = 'f380' 'centos' = 'f789' 'chrome' = 'f268' 'chromecast' = 'f838' 'cloudflare' = 'e07d' 'cloudscale' = 'f383' 'cloudsmith' = 'f384' 'cloudversify' = 'f385' 'codepen' = 'f1cb' 'codiepie' = 'f284' 'confluence' = 'f78d' 'connectdevelop' = 'f20e' 'contao' = 'f26d' 'cotton-bureau' = 'f89e' 'cpanel' = 'f388' 'creative-commons' = 'f25e' 'creative-commons-by' = 'f4e7' 'creative-commons-nc' = 'f4e8' 'creative-commons-nc-eu' = 'f4e9' 'creative-commons-nc-jp' = 'f4ea' 'creative-commons-nd' = 'f4eb' 'creative-commons-pd' = 'f4ec' 'creative-commons-pd-alt' = 'f4ed' 'creative-commons-remix' = 'f4ee' 'creative-commons-sa' = 'f4ef' 'creative-commons-sampling' = 'f4f0' 'creative-commons-sampling-plus' = 'f4f1' 'creative-commons-share' = 'f4f2' 'creative-commons-zero' = 'f4f3' 'critical-role' = 'f6c9' 'css3' = 'f13c' 'css3-alt' = 'f38b' 'cuttlefish' = 'f38c' 'd-and-d' = 'f38d' 'd-and-d-beyond' = 'f6ca' 'dailymotion' = 'e052' 'dashcube' = 'f210' 'deezer' = 'e077' 'delicious' = 'f1a5' 'deploydog' = 'f38e' 'deskpro' = 'f38f' 'dev' = 'f6cc' 'deviantart' = 'f1bd' 'dhl' = 'f790' 'diaspora' = 'f791' 'digg' = 'f1a6' 'digital-ocean' = 'f391' 'discord' = 'f392' 'discourse' = 'f393' 'dochub' = 'f394' 'docker' = 'f395' 'draft2digital' = 'f396' 'dribbble' = 'f17d' 'dribbble-square' = 'f397' 'dropbox' = 'f16b' 'drupal' = 'f1a9' 'dyalog' = 'f399' 'earlybirds' = 'f39a' 'ebay' = 'f4f4' 'edge' = 'f282' 'edge-legacy' = 'e078' 'elementor' = 'f430' 'ello' = 'f5f1' 'ember' = 'f423' 'empire' = 'f1d1' 'envira' = 'f299' 'erlang' = 'f39d' 'ethereum' = 'f42e' 'etsy' = 'f2d7' 'evernote' = 'f839' 'expeditedssl' = 'f23e' 'facebook' = 'f09a' 'facebook-f' = 'f39e' 'facebook-messenger' = 'f39f' 'facebook-square' = 'f082' 'fantasy-flight-games' = 'f6dc' 'fedex' = 'f797' 'fedora' = 'f798' 'figma' = 'f799' 'firefox' = 'f269' 'firefox-browser' = 'e007' 'first-order' = 'f2b0' 'first-order-alt' = 'f50a' 'firstdraft' = 'f3a1' 'flickr' = 'f16e' 'flipboard' = 'f44d' 'fly' = 'f417' 'font-awesome' = 'f2b4' 'font-awesome-alt' = 'f35c' 'font-awesome-flag' = 'f425' 'fonticons' = 'f280' 'fonticons-fi' = 'f3a2' 'fort-awesome' = 'f286' 'fort-awesome-alt' = 'f3a3' 'forumbee' = 'f211' 'foursquare' = 'f180' 'free-code-camp' = 'f2c5' 'freebsd' = 'f3a4' 'fulcrum' = 'f50b' 'galactic-republic' = 'f50c' 'galactic-senate' = 'f50d' 'get-pocket' = 'f265' 'gg' = 'f260' 'gg-circle' = 'f261' 'git' = 'f1d3' 'git-alt' = 'f841' 'git-square' = 'f1d2' 'github' = 'f09b' 'github-alt' = 'f113' 'github-square' = 'f092' 'gitkraken' = 'f3a6' 'gitlab' = 'f296' 'gitter' = 'f426' 'glide' = 'f2a5' 'glide-g' = 'f2a6' 'gofore' = 'f3a7' 'goodreads' = 'f3a8' 'goodreads-g' = 'f3a9' 'google' = 'f1a0' 'google-drive' = 'f3aa' 'google-pay' = 'e079' 'google-play' = 'f3ab' 'google-plus' = 'f2b3' 'google-plus-g' = 'f0d5' 'google-plus-square' = 'f0d4' 'google-wallet' = 'f1ee' 'gratipay' = 'f184' 'grav' = 'f2d6' 'gripfire' = 'f3ac' 'grunt' = 'f3ad' 'guilded' = 'e07e' 'gulp' = 'f3ae' 'hacker-news' = 'f1d4' 'hacker-news-square' = 'f3af' 'hackerrank' = 'f5f7' 'hips' = 'f452' 'hire-a-helper' = 'f3b0' 'hive' = 'e07f' 'hooli' = 'f427' 'hornbill' = 'f592' 'hotjar' = 'f3b1' 'houzz' = 'f27c' 'html5' = 'f13b' 'hubspot' = 'f3b2' 'ideal' = 'e013' 'imdb' = 'f2d8' 'innosoft' = 'e080' 'instagram' = 'f16d' 'instagram-square' = 'e055' 'instalod' = 'e081' 'intercom' = 'f7af' 'internet-explorer' = 'f26b' 'invision' = 'f7b0' 'ioxhost' = 'f208' 'itch-io' = 'f83a' 'itunes' = 'f3b4' 'itunes-note' = 'f3b5' 'java' = 'f4e4' 'jedi-order' = 'f50e' 'jenkins' = 'f3b6' 'jira' = 'f7b1' 'joget' = 'f3b7' 'joomla' = 'f1aa' 'js' = 'f3b8' 'js-square' = 'f3b9' 'jsfiddle' = 'f1cc' 'kaggle' = 'f5fa' 'keybase' = 'f4f5' 'keycdn' = 'f3ba' 'kickstarter' = 'f3bb' 'kickstarter-k' = 'f3bc' 'korvue' = 'f42f' 'laravel' = 'f3bd' 'lastfm' = 'f202' 'lastfm-square' = 'f203' 'leanpub' = 'f212' 'less' = 'f41d' 'line' = 'f3c0' 'linkedin' = 'f08c' 'linkedin-in' = 'f0e1' 'linode' = 'f2b8' 'linux' = 'f17c' 'lyft' = 'f3c3' 'magento' = 'f3c4' 'mailchimp' = 'f59e' 'mandalorian' = 'f50f' 'markdown' = 'f60f' 'mastodon' = 'f4f6' 'maxcdn' = 'f136' 'mdb' = 'f8ca' 'medapps' = 'f3c6' 'medium' = 'f23a' 'medium-m' = 'f3c7' 'medrt' = 'f3c8' 'meetup' = 'f2e0' 'megaport' = 'f5a3' 'mendeley' = 'f7b3' 'microblog' = 'e01a' 'microsoft' = 'f3ca' 'mix' = 'f3cb' 'mixcloud' = 'f289' 'mixer' = 'e056' 'mizuni' = 'f3cc' 'modx' = 'f285' 'monero' = 'f3d0' 'napster' = 'f3d2' 'neos' = 'f612' 'nimblr' = 'f5a8' 'node' = 'f419' 'node-js' = 'f3d3' 'npm' = 'f3d4' 'ns8' = 'f3d5' 'nutritionix' = 'f3d6' 'octopus-deploy' = 'e082' 'odnoklassniki' = 'f263' 'odnoklassniki-square' = 'f264' 'old-republic' = 'f510' 'opencart' = 'f23d' 'openid' = 'f19b' 'opera' = 'f26a' 'optin-monster' = 'f23c' 'orcid' = 'f8d2' 'osi' = 'f41a' 'page4' = 'f3d7' 'pagelines' = 'f18c' 'palfed' = 'f3d8' 'patreon' = 'f3d9' 'paypal' = 'f1ed' 'penny-arcade' = 'f704' 'perbyte' = 'e083' 'periscope' = 'f3da' 'phabricator' = 'f3db' 'phoenix-framework' = 'f3dc' 'phoenix-squadron' = 'f511' 'php' = 'f457' 'pied-piper' = 'f2ae' 'pied-piper-alt' = 'f1a8' 'pied-piper-hat' = 'f4e5' 'pied-piper-pp' = 'f1a7' 'pied-piper-square' = 'e01e' 'pinterest' = 'f0d2' 'pinterest-p' = 'f231' 'pinterest-square' = 'f0d3' 'playstation' = 'f3df' 'product-hunt' = 'f288' 'pushed' = 'f3e1' 'python' = 'f3e2' 'qq' = 'f1d6' 'quinscape' = 'f459' 'quora' = 'f2c4' 'r-project' = 'f4f7' 'raspberry-pi' = 'f7bb' 'ravelry' = 'f2d9' 'react' = 'f41b' 'reacteurope' = 'f75d' 'readme' = 'f4d5' 'rebel' = 'f1d0' 'red-river' = 'f3e3' 'reddit' = 'f1a1' 'reddit-alien' = 'f281' 'reddit-square' = 'f1a2' 'redhat' = 'f7bc' 'renren' = 'f18b' 'replyd' = 'f3e6' 'researchgate' = 'f4f8' 'resolving' = 'f3e7' 'rev' = 'f5b2' 'rocketchat' = 'f3e8' 'rockrms' = 'f3e9' 'rust' = 'e07a' 'safari' = 'f267' 'salesforce' = 'f83b' 'sass' = 'f41e' 'schlix' = 'f3ea' 'scribd' = 'f28a' 'searchengin' = 'f3eb' 'sellcast' = 'f2da' 'sellsy' = 'f213' 'servicestack' = 'f3ec' 'shirtsinbulk' = 'f214' 'shopify' = 'e057' 'shopware' = 'f5b5' 'simplybuilt' = 'f215' 'sistrix' = 'f3ee' 'sith' = 'f512' 'sketch' = 'f7c6' 'skyatlas' = 'f216' 'skype' = 'f17e' 'slack' = 'f198' 'slack-hash' = 'f3ef' 'slideshare' = 'f1e7' 'snapchat' = 'f2ab' 'snapchat-ghost' = 'f2ac' 'snapchat-square' = 'f2ad' 'soundcloud' = 'f1be' 'sourcetree' = 'f7d3' 'speakap' = 'f3f3' 'speaker-deck' = 'f83c' 'spotify' = 'f1bc' 'squarespace' = 'f5be' 'stack-exchange' = 'f18d' 'stack-overflow' = 'f16c' 'stackpath' = 'f842' 'staylinked' = 'f3f5' 'steam' = 'f1b6' 'steam-square' = 'f1b7' 'steam-symbol' = 'f3f6' 'sticker-mule' = 'f3f7' 'strava' = 'f428' 'stripe' = 'f429' 'stripe-s' = 'f42a' 'studiovinari' = 'f3f8' 'stumbleupon' = 'f1a4' 'stumbleupon-circle' = 'f1a3' 'superpowers' = 'f2dd' 'supple' = 'f3f9' 'suse' = 'f7d6' 'swift' = 'f8e1' 'symfony' = 'f83d' 'teamspeak' = 'f4f9' 'telegram' = 'f2c6' 'telegram-plane' = 'f3fe' 'tencent-weibo' = 'f1d5' 'the-red-yeti' = 'f69d' 'themeco' = 'f5c6' 'themeisle' = 'f2b2' 'think-peaks' = 'f731' 'tiktok' = 'e07b' 'trade-federation' = 'f513' 'trello' = 'f181' 'tripadvisor' = 'f262' 'tumblr' = 'f173' 'tumblr-square' = 'f174' 'twitch' = 'f1e8' 'twitter' = 'f099' 'twitter-square' = 'f081' 'typo3' = 'f42b' 'uber' = 'f402' 'ubuntu' = 'f7df' 'uikit' = 'f403' 'umbraco' = 'f8e8' 'uncharted' = 'e084' 'uniregistry' = 'f404' 'unity' = 'e049' 'unsplash' = 'e07c' 'untappd' = 'f405' 'ups' = 'f7e0' 'usb' = 'f287' 'usps' = 'f7e1' 'ussunnah' = 'f407' 'vaadin' = 'f408' 'viacoin' = 'f237' 'viadeo' = 'f2a9' 'viadeo-square' = 'f2aa' 'viber' = 'f409' 'vimeo' = 'f40a' 'vimeo-square' = 'f194' 'vimeo-v' = 'f27d' 'vine' = 'f1ca' 'vk' = 'f189' 'vnv' = 'f40b' 'vuejs' = 'f41f' 'watchman-monitoring' = 'e087' 'waze' = 'f83f' 'weebly' = 'f5cc' 'weibo' = 'f18a' 'weixin' = 'f1d7' 'whatsapp' = 'f232' 'whatsapp-square' = 'f40c' 'whmcs' = 'f40d' 'wikipedia-w' = 'f266' 'windows' = 'f17a' 'wix' = 'f5cf' 'wizards-of-the-coast' = 'f730' 'wodu' = 'e088' 'wolf-pack-battalion' = 'f514' 'wordpress' = 'f19a' 'wordpress-simple' = 'f411' 'wpbeginner' = 'f297' 'wpexplorer' = 'f2de' 'wpforms' = 'f298' 'wpressr' = 'f3e4' 'xbox' = 'f412' 'xing' = 'f168' 'xing-square' = 'f169' 'y-combinator' = 'f23b' 'yahoo' = 'f19e' 'yammer' = 'f840' 'yandex' = 'f413' 'yandex-international' = 'f414' 'yarn' = 'f7e3' 'yelp' = 'f1e9' 'yoast' = 'f2b1' 'youtube' = 'f167' 'youtube-square' = 'f431' 'zhihu' = 'f63f' } FontAwesomeRegular = [ordered] @{ 'address-book' = 'f2b9' 'address-card' = 'f2bb' 'angry' = 'f556' 'arrow-alt-circle-down' = 'f358' 'arrow-alt-circle-left' = 'f359' 'arrow-alt-circle-right' = 'f35a' 'arrow-alt-circle-up' = 'f35b' 'bell' = 'f0f3' 'bell-slash' = 'f1f6' 'bookmark' = 'f02e' 'building' = 'f1ad' 'calendar' = 'f133' 'calendar-alt' = 'f073' 'calendar-check' = 'f274' 'calendar-minus' = 'f272' 'calendar-plus' = 'f271' 'calendar-times' = 'f273' 'caret-square-down' = 'f150' 'caret-square-left' = 'f191' 'caret-square-right' = 'f152' 'caret-square-up' = 'f151' 'chart-bar' = 'f080' 'check-circle' = 'f058' 'check-square' = 'f14a' 'circle' = 'f111' 'clipboard' = 'f328' 'clock' = 'f017' 'clone' = 'f24d' 'closed-captioning' = 'f20a' 'comment' = 'f075' 'comment-alt' = 'f27a' 'comment-dots' = 'f4ad' 'comments' = 'f086' 'compass' = 'f14e' 'copy' = 'f0c5' 'copyright' = 'f1f9' 'credit-card' = 'f09d' 'dizzy' = 'f567' 'dot-circle' = 'f192' 'edit' = 'f044' 'envelope' = 'f0e0' 'envelope-open' = 'f2b6' 'eye' = 'f06e' 'eye-slash' = 'f070' 'file' = 'f15b' 'file-alt' = 'f15c' 'file-archive' = 'f1c6' 'file-audio' = 'f1c7' 'file-code' = 'f1c9' 'file-excel' = 'f1c3' 'file-image' = 'f1c5' 'file-pdf' = 'f1c1' 'file-powerpoint' = 'f1c4' 'file-video' = 'f1c8' 'file-word' = 'f1c2' 'flag' = 'f024' 'flushed' = 'f579' 'folder' = 'f07b' 'folder-open' = 'f07c' 'frown' = 'f119' 'frown-open' = 'f57a' 'futbol' = 'f1e3' 'gem' = 'f3a5' 'grimace' = 'f57f' 'grin' = 'f580' 'grin-alt' = 'f581' 'grin-beam' = 'f582' 'grin-beam-sweat' = 'f583' 'grin-hearts' = 'f584' 'grin-squint' = 'f585' 'grin-squint-tears' = 'f586' 'grin-stars' = 'f587' 'grin-tears' = 'f588' 'grin-tongue' = 'f589' 'grin-tongue-squint' = 'f58a' 'grin-tongue-wink' = 'f58b' 'grin-wink' = 'f58c' 'hand-lizard' = 'f258' 'hand-paper' = 'f256' 'hand-peace' = 'f25b' 'hand-point-down' = 'f0a7' 'hand-point-left' = 'f0a5' 'hand-point-right' = 'f0a4' 'hand-point-up' = 'f0a6' 'hand-pointer' = 'f25a' 'hand-rock' = 'f255' 'hand-scissors' = 'f257' 'hand-spock' = 'f259' 'handshake' = 'f2b5' 'hdd' = 'f0a0' 'heart' = 'f004' 'hospital' = 'f0f8' 'hourglass' = 'f254' 'id-badge' = 'f2c1' 'id-card' = 'f2c2' 'image' = 'f03e' 'images' = 'f302' 'keyboard' = 'f11c' 'kiss' = 'f596' 'kiss-beam' = 'f597' 'kiss-wink-heart' = 'f598' 'laugh' = 'f599' 'laugh-beam' = 'f59a' 'laugh-squint' = 'f59b' 'laugh-wink' = 'f59c' 'lemon' = 'f094' 'life-ring' = 'f1cd' 'lightbulb' = 'f0eb' 'list-alt' = 'f022' 'map' = 'f279' 'meh' = 'f11a' 'meh-blank' = 'f5a4' 'meh-rolling-eyes' = 'f5a5' 'minus-square' = 'f146' 'money-bill-alt' = 'f3d1' 'moon' = 'f186' 'newspaper' = 'f1ea' 'object-group' = 'f247' 'object-ungroup' = 'f248' 'paper-plane' = 'f1d8' 'pause-circle' = 'f28b' 'play-circle' = 'f144' 'plus-square' = 'f0fe' 'question-circle' = 'f059' 'registered' = 'f25d' 'sad-cry' = 'f5b3' 'sad-tear' = 'f5b4' 'save' = 'f0c7' 'share-square' = 'f14d' 'smile' = 'f118' 'smile-beam' = 'f5b8' 'smile-wink' = 'f4da' 'snowflake' = 'f2dc' 'square' = 'f0c8' 'star' = 'f005' 'star-half' = 'f089' 'sticky-note' = 'f249' 'stop-circle' = 'f28d' 'sun' = 'f185' 'surprise' = 'f5c2' 'thumbs-down' = 'f165' 'thumbs-up' = 'f164' 'times-circle' = 'f057' 'tired' = 'f5c8' 'trash-alt' = 'f2ed' 'user' = 'f007' 'user-circle' = 'f2bd' 'window-close' = 'f410' 'window-maximize' = 'f2d0' 'window-minimize' = 'f2d1' 'window-restore' = 'f2d2' } FontAwesomeSolid = [ordered] @{ 'ad' = 'f641' 'address-book' = 'f2b9' 'address-card' = 'f2bb' 'adjust' = 'f042' 'air-freshener' = 'f5d0' 'align-center' = 'f037' 'align-justify' = 'f039' 'align-left' = 'f036' 'align-right' = 'f038' 'allergies' = 'f461' 'ambulance' = 'f0f9' 'american-sign-language-interpreting' = 'f2a3' 'anchor' = 'f13d' 'angle-double-down' = 'f103' 'angle-double-left' = 'f100' 'angle-double-right' = 'f101' 'angle-double-up' = 'f102' 'angle-down' = 'f107' 'angle-left' = 'f104' 'angle-right' = 'f105' 'angle-up' = 'f106' 'angry' = 'f556' 'ankh' = 'f644' 'apple-alt' = 'f5d1' 'archive' = 'f187' 'archway' = 'f557' 'arrow-alt-circle-down' = 'f358' 'arrow-alt-circle-left' = 'f359' 'arrow-alt-circle-right' = 'f35a' 'arrow-alt-circle-up' = 'f35b' 'arrow-circle-down' = 'f0ab' 'arrow-circle-left' = 'f0a8' 'arrow-circle-right' = 'f0a9' 'arrow-circle-up' = 'f0aa' 'arrow-down' = 'f063' 'arrow-left' = 'f060' 'arrow-right' = 'f061' 'arrow-up' = 'f062' 'arrows-alt' = 'f0b2' 'arrows-alt-h' = 'f337' 'arrows-alt-v' = 'f338' 'assistive-listening-systems' = 'f2a2' 'asterisk' = 'f069' 'at' = 'f1fa' 'atlas' = 'f558' 'atom' = 'f5d2' 'audio-description' = 'f29e' 'award' = 'f559' 'baby' = 'f77c' 'baby-carriage' = 'f77d' 'backspace' = 'f55a' 'backward' = 'f04a' 'bacon' = 'f7e5' 'bacteria' = 'e059' 'bacterium' = 'e05a' 'bahai' = 'f666' 'balance-scale' = 'f24e' 'balance-scale-left' = 'f515' 'balance-scale-right' = 'f516' 'ban' = 'f05e' 'band-aid' = 'f462' 'barcode' = 'f02a' 'bars' = 'f0c9' 'baseball-ball' = 'f433' 'basketball-ball' = 'f434' 'bath' = 'f2cd' 'battery-empty' = 'f244' 'battery-full' = 'f240' 'battery-half' = 'f242' 'battery-quarter' = 'f243' 'battery-three-quarters' = 'f241' 'bed' = 'f236' 'beer' = 'f0fc' 'bell' = 'f0f3' 'bell-slash' = 'f1f6' 'bezier-curve' = 'f55b' 'bible' = 'f647' 'bicycle' = 'f206' 'biking' = 'f84a' 'binoculars' = 'f1e5' 'biohazard' = 'f780' 'birthday-cake' = 'f1fd' 'blender' = 'f517' 'blender-phone' = 'f6b6' 'blind' = 'f29d' 'blog' = 'f781' 'bold' = 'f032' 'bolt' = 'f0e7' 'bomb' = 'f1e2' 'bone' = 'f5d7' 'bong' = 'f55c' 'book' = 'f02d' 'book-dead' = 'f6b7' 'book-medical' = 'f7e6' 'book-open' = 'f518' 'book-reader' = 'f5da' 'bookmark' = 'f02e' 'border-all' = 'f84c' 'border-none' = 'f850' 'border-style' = 'f853' 'bowling-ball' = 'f436' 'box' = 'f466' 'box-open' = 'f49e' 'box-tissue' = 'e05b' 'boxes' = 'f468' 'braille' = 'f2a1' 'brain' = 'f5dc' 'bread-slice' = 'f7ec' 'briefcase' = 'f0b1' 'briefcase-medical' = 'f469' 'broadcast-tower' = 'f519' 'broom' = 'f51a' 'brush' = 'f55d' 'bug' = 'f188' 'building' = 'f1ad' 'bullhorn' = 'f0a1' 'bullseye' = 'f140' 'burn' = 'f46a' 'bus' = 'f207' 'bus-alt' = 'f55e' 'business-time' = 'f64a' 'calculator' = 'f1ec' 'calendar' = 'f133' 'calendar-alt' = 'f073' 'calendar-check' = 'f274' 'calendar-day' = 'f783' 'calendar-minus' = 'f272' 'calendar-plus' = 'f271' 'calendar-times' = 'f273' 'calendar-week' = 'f784' 'camera' = 'f030' 'camera-retro' = 'f083' 'campground' = 'f6bb' 'candy-cane' = 'f786' 'cannabis' = 'f55f' 'capsules' = 'f46b' 'car' = 'f1b9' 'car-alt' = 'f5de' 'car-battery' = 'f5df' 'car-crash' = 'f5e1' 'car-side' = 'f5e4' 'caravan' = 'f8ff' 'caret-down' = 'f0d7' 'caret-left' = 'f0d9' 'caret-right' = 'f0da' 'caret-square-down' = 'f150' 'caret-square-left' = 'f191' 'caret-square-right' = 'f152' 'caret-square-up' = 'f151' 'caret-up' = 'f0d8' 'carrot' = 'f787' 'cart-arrow-down' = 'f218' 'cart-plus' = 'f217' 'cash-register' = 'f788' 'cat' = 'f6be' 'certificate' = 'f0a3' 'chair' = 'f6c0' 'chalkboard' = 'f51b' 'chalkboard-teacher' = 'f51c' 'charging-station' = 'f5e7' 'chart-area' = 'f1fe' 'chart-bar' = 'f080' 'chart-line' = 'f201' 'chart-pie' = 'f200' 'check' = 'f00c' 'check-circle' = 'f058' 'check-double' = 'f560' 'check-square' = 'f14a' 'cheese' = 'f7ef' 'chess' = 'f439' 'chess-bishop' = 'f43a' 'chess-board' = 'f43c' 'chess-king' = 'f43f' 'chess-knight' = 'f441' 'chess-pawn' = 'f443' 'chess-queen' = 'f445' 'chess-rook' = 'f447' 'chevron-circle-down' = 'f13a' 'chevron-circle-left' = 'f137' 'chevron-circle-right' = 'f138' 'chevron-circle-up' = 'f139' 'chevron-down' = 'f078' 'chevron-left' = 'f053' 'chevron-right' = 'f054' 'chevron-up' = 'f077' 'child' = 'f1ae' 'church' = 'f51d' 'circle' = 'f111' 'circle-notch' = 'f1ce' 'city' = 'f64f' 'clinic-medical' = 'f7f2' 'clipboard' = 'f328' 'clipboard-check' = 'f46c' 'clipboard-list' = 'f46d' 'clock' = 'f017' 'clone' = 'f24d' 'closed-captioning' = 'f20a' 'cloud' = 'f0c2' 'cloud-download-alt' = 'f381' 'cloud-meatball' = 'f73b' 'cloud-moon' = 'f6c3' 'cloud-moon-rain' = 'f73c' 'cloud-rain' = 'f73d' 'cloud-showers-heavy' = 'f740' 'cloud-sun' = 'f6c4' 'cloud-sun-rain' = 'f743' 'cloud-upload-alt' = 'f382' 'cocktail' = 'f561' 'code' = 'f121' 'code-branch' = 'f126' 'coffee' = 'f0f4' 'cog' = 'f013' 'cogs' = 'f085' 'coins' = 'f51e' 'columns' = 'f0db' 'comment' = 'f075' 'comment-alt' = 'f27a' 'comment-dollar' = 'f651' 'comment-dots' = 'f4ad' 'comment-medical' = 'f7f5' 'comment-slash' = 'f4b3' 'comments' = 'f086' 'comments-dollar' = 'f653' 'compact-disc' = 'f51f' 'compass' = 'f14e' 'compress' = 'f066' 'compress-alt' = 'f422' 'compress-arrows-alt' = 'f78c' 'concierge-bell' = 'f562' 'cookie' = 'f563' 'cookie-bite' = 'f564' 'copy' = 'f0c5' 'copyright' = 'f1f9' 'couch' = 'f4b8' 'credit-card' = 'f09d' 'crop' = 'f125' 'crop-alt' = 'f565' 'cross' = 'f654' 'crosshairs' = 'f05b' 'crow' = 'f520' 'crown' = 'f521' 'crutch' = 'f7f7' 'cube' = 'f1b2' 'cubes' = 'f1b3' 'cut' = 'f0c4' 'database' = 'f1c0' 'deaf' = 'f2a4' 'democrat' = 'f747' 'desktop' = 'f108' 'dharmachakra' = 'f655' 'diagnoses' = 'f470' 'dice' = 'f522' 'dice-d20' = 'f6cf' 'dice-d6' = 'f6d1' 'dice-five' = 'f523' 'dice-four' = 'f524' 'dice-one' = 'f525' 'dice-six' = 'f526' 'dice-three' = 'f527' 'dice-two' = 'f528' 'digital-tachograph' = 'f566' 'directions' = 'f5eb' 'disease' = 'f7fa' 'divide' = 'f529' 'dizzy' = 'f567' 'dna' = 'f471' 'dog' = 'f6d3' 'dollar-sign' = 'f155' 'dolly' = 'f472' 'dolly-flatbed' = 'f474' 'donate' = 'f4b9' 'door-closed' = 'f52a' 'door-open' = 'f52b' 'dot-circle' = 'f192' 'dove' = 'f4ba' 'download' = 'f019' 'drafting-compass' = 'f568' 'dragon' = 'f6d5' 'draw-polygon' = 'f5ee' 'drum' = 'f569' 'drum-steelpan' = 'f56a' 'drumstick-bite' = 'f6d7' 'dumbbell' = 'f44b' 'dumpster' = 'f793' 'dumpster-fire' = 'f794' 'dungeon' = 'f6d9' 'edit' = 'f044' 'egg' = 'f7fb' 'eject' = 'f052' 'ellipsis-h' = 'f141' 'ellipsis-v' = 'f142' 'envelope' = 'f0e0' 'envelope-open' = 'f2b6' 'envelope-open-text' = 'f658' 'envelope-square' = 'f199' 'equals' = 'f52c' 'eraser' = 'f12d' 'ethernet' = 'f796' 'euro-sign' = 'f153' 'exchange-alt' = 'f362' 'exclamation' = 'f12a' 'exclamation-circle' = 'f06a' 'exclamation-triangle' = 'f071' 'expand' = 'f065' 'expand-alt' = 'f424' 'expand-arrows-alt' = 'f31e' 'external-link-alt' = 'f35d' 'external-link-square-alt' = 'f360' 'eye' = 'f06e' 'eye-dropper' = 'f1fb' 'eye-slash' = 'f070' 'fan' = 'f863' 'fast-backward' = 'f049' 'fast-forward' = 'f050' 'faucet' = 'e005' 'fax' = 'f1ac' 'feather' = 'f52d' 'feather-alt' = 'f56b' 'female' = 'f182' 'fighter-jet' = 'f0fb' 'file' = 'f15b' 'file-alt' = 'f15c' 'file-archive' = 'f1c6' 'file-audio' = 'f1c7' 'file-code' = 'f1c9' 'file-contract' = 'f56c' 'file-csv' = 'f6dd' 'file-download' = 'f56d' 'file-excel' = 'f1c3' 'file-export' = 'f56e' 'file-image' = 'f1c5' 'file-import' = 'f56f' 'file-invoice' = 'f570' 'file-invoice-dollar' = 'f571' 'file-medical' = 'f477' 'file-medical-alt' = 'f478' 'file-pdf' = 'f1c1' 'file-powerpoint' = 'f1c4' 'file-prescription' = 'f572' 'file-signature' = 'f573' 'file-upload' = 'f574' 'file-video' = 'f1c8' 'file-word' = 'f1c2' 'fill' = 'f575' 'fill-drip' = 'f576' 'film' = 'f008' 'filter' = 'f0b0' 'fingerprint' = 'f577' 'fire' = 'f06d' 'fire-alt' = 'f7e4' 'fire-extinguisher' = 'f134' 'first-aid' = 'f479' 'fish' = 'f578' 'fist-raised' = 'f6de' 'flag' = 'f024' 'flag-checkered' = 'f11e' 'flag-usa' = 'f74d' 'flask' = 'f0c3' 'flushed' = 'f579' 'folder' = 'f07b' 'folder-minus' = 'f65d' 'folder-open' = 'f07c' 'folder-plus' = 'f65e' 'font' = 'f031' 'football-ball' = 'f44e' 'forward' = 'f04e' 'frog' = 'f52e' 'frown' = 'f119' 'frown-open' = 'f57a' 'funnel-dollar' = 'f662' 'futbol' = 'f1e3' 'gamepad' = 'f11b' 'gas-pump' = 'f52f' 'gavel' = 'f0e3' 'gem' = 'f3a5' 'genderless' = 'f22d' 'ghost' = 'f6e2' 'gift' = 'f06b' 'gifts' = 'f79c' 'glass-cheers' = 'f79f' 'glass-martini' = 'f000' 'glass-martini-alt' = 'f57b' 'glass-whiskey' = 'f7a0' 'glasses' = 'f530' 'globe' = 'f0ac' 'globe-africa' = 'f57c' 'globe-americas' = 'f57d' 'globe-asia' = 'f57e' 'globe-europe' = 'f7a2' 'golf-ball' = 'f450' 'gopuram' = 'f664' 'graduation-cap' = 'f19d' 'greater-than' = 'f531' 'greater-than-equal' = 'f532' 'grimace' = 'f57f' 'grin' = 'f580' 'grin-alt' = 'f581' 'grin-beam' = 'f582' 'grin-beam-sweat' = 'f583' 'grin-hearts' = 'f584' 'grin-squint' = 'f585' 'grin-squint-tears' = 'f586' 'grin-stars' = 'f587' 'grin-tears' = 'f588' 'grin-tongue' = 'f589' 'grin-tongue-squint' = 'f58a' 'grin-tongue-wink' = 'f58b' 'grin-wink' = 'f58c' 'grip-horizontal' = 'f58d' 'grip-lines' = 'f7a4' 'grip-lines-vertical' = 'f7a5' 'grip-vertical' = 'f58e' 'guitar' = 'f7a6' 'h-square' = 'f0fd' 'hamburger' = 'f805' 'hammer' = 'f6e3' 'hamsa' = 'f665' 'hand-holding' = 'f4bd' 'hand-holding-heart' = 'f4be' 'hand-holding-medical' = 'e05c' 'hand-holding-usd' = 'f4c0' 'hand-holding-water' = 'f4c1' 'hand-lizard' = 'f258' 'hand-middle-finger' = 'f806' 'hand-paper' = 'f256' 'hand-peace' = 'f25b' 'hand-point-down' = 'f0a7' 'hand-point-left' = 'f0a5' 'hand-point-right' = 'f0a4' 'hand-point-up' = 'f0a6' 'hand-pointer' = 'f25a' 'hand-rock' = 'f255' 'hand-scissors' = 'f257' 'hand-sparkles' = 'e05d' 'hand-spock' = 'f259' 'hands' = 'f4c2' 'hands-helping' = 'f4c4' 'hands-wash' = 'e05e' 'handshake' = 'f2b5' 'handshake-alt-slash' = 'e05f' 'handshake-slash' = 'e060' 'hanukiah' = 'f6e6' 'hard-hat' = 'f807' 'hashtag' = 'f292' 'hat-cowboy' = 'f8c0' 'hat-cowboy-side' = 'f8c1' 'hat-wizard' = 'f6e8' 'hdd' = 'f0a0' 'head-side-cough' = 'e061' 'head-side-cough-slash' = 'e062' 'head-side-mask' = 'e063' 'head-side-virus' = 'e064' 'heading' = 'f1dc' 'headphones' = 'f025' 'headphones-alt' = 'f58f' 'headset' = 'f590' 'heart' = 'f004' 'heart-broken' = 'f7a9' 'heartbeat' = 'f21e' 'helicopter' = 'f533' 'highlighter' = 'f591' 'hiking' = 'f6ec' 'hippo' = 'f6ed' 'history' = 'f1da' 'hockey-puck' = 'f453' 'holly-berry' = 'f7aa' 'home' = 'f015' 'horse' = 'f6f0' 'horse-head' = 'f7ab' 'hospital' = 'f0f8' 'hospital-alt' = 'f47d' 'hospital-symbol' = 'f47e' 'hospital-user' = 'f80d' 'hot-tub' = 'f593' 'hotdog' = 'f80f' 'hotel' = 'f594' 'hourglass' = 'f254' 'hourglass-end' = 'f253' 'hourglass-half' = 'f252' 'hourglass-start' = 'f251' 'house-damage' = 'f6f1' 'house-user' = 'e065' 'hryvnia' = 'f6f2' 'i-cursor' = 'f246' 'ice-cream' = 'f810' 'icicles' = 'f7ad' 'icons' = 'f86d' 'id-badge' = 'f2c1' 'id-card' = 'f2c2' 'id-card-alt' = 'f47f' 'igloo' = 'f7ae' 'image' = 'f03e' 'images' = 'f302' 'inbox' = 'f01c' 'indent' = 'f03c' 'industry' = 'f275' 'infinity' = 'f534' 'info' = 'f129' 'info-circle' = 'f05a' 'italic' = 'f033' 'jedi' = 'f669' 'joint' = 'f595' 'journal-whills' = 'f66a' 'kaaba' = 'f66b' 'key' = 'f084' 'keyboard' = 'f11c' 'khanda' = 'f66d' 'kiss' = 'f596' 'kiss-beam' = 'f597' 'kiss-wink-heart' = 'f598' 'kiwi-bird' = 'f535' 'landmark' = 'f66f' 'language' = 'f1ab' 'laptop' = 'f109' 'laptop-code' = 'f5fc' 'laptop-house' = 'e066' 'laptop-medical' = 'f812' 'laugh' = 'f599' 'laugh-beam' = 'f59a' 'laugh-squint' = 'f59b' 'laugh-wink' = 'f59c' 'layer-group' = 'f5fd' 'leaf' = 'f06c' 'lemon' = 'f094' 'less-than' = 'f536' 'less-than-equal' = 'f537' 'level-down-alt' = 'f3be' 'level-up-alt' = 'f3bf' 'life-ring' = 'f1cd' 'lightbulb' = 'f0eb' 'link' = 'f0c1' 'lira-sign' = 'f195' 'list' = 'f03a' 'list-alt' = 'f022' 'list-ol' = 'f0cb' 'list-ul' = 'f0ca' 'location-arrow' = 'f124' 'lock' = 'f023' 'lock-open' = 'f3c1' 'long-arrow-alt-down' = 'f309' 'long-arrow-alt-left' = 'f30a' 'long-arrow-alt-right' = 'f30b' 'long-arrow-alt-up' = 'f30c' 'low-vision' = 'f2a8' 'luggage-cart' = 'f59d' 'lungs' = 'f604' 'lungs-virus' = 'e067' 'magic' = 'f0d0' 'magnet' = 'f076' 'mail-bulk' = 'f674' 'male' = 'f183' 'map' = 'f279' 'map-marked' = 'f59f' 'map-marked-alt' = 'f5a0' 'map-marker' = 'f041' 'map-marker-alt' = 'f3c5' 'map-pin' = 'f276' 'map-signs' = 'f277' 'marker' = 'f5a1' 'mars' = 'f222' 'mars-double' = 'f227' 'mars-stroke' = 'f229' 'mars-stroke-h' = 'f22b' 'mars-stroke-v' = 'f22a' 'mask' = 'f6fa' 'medal' = 'f5a2' 'medkit' = 'f0fa' 'meh' = 'f11a' 'meh-blank' = 'f5a4' 'meh-rolling-eyes' = 'f5a5' 'memory' = 'f538' 'menorah' = 'f676' 'mercury' = 'f223' 'meteor' = 'f753' 'microchip' = 'f2db' 'microphone' = 'f130' 'microphone-alt' = 'f3c9' 'microphone-alt-slash' = 'f539' 'microphone-slash' = 'f131' 'microscope' = 'f610' 'minus' = 'f068' 'minus-circle' = 'f056' 'minus-square' = 'f146' 'mitten' = 'f7b5' 'mobile' = 'f10b' 'mobile-alt' = 'f3cd' 'money-bill' = 'f0d6' 'money-bill-alt' = 'f3d1' 'money-bill-wave' = 'f53a' 'money-bill-wave-alt' = 'f53b' 'money-check' = 'f53c' 'money-check-alt' = 'f53d' 'monument' = 'f5a6' 'moon' = 'f186' 'mortar-pestle' = 'f5a7' 'mosque' = 'f678' 'motorcycle' = 'f21c' 'mountain' = 'f6fc' 'mouse' = 'f8cc' 'mouse-pointer' = 'f245' 'mug-hot' = 'f7b6' 'music' = 'f001' 'network-wired' = 'f6ff' 'neuter' = 'f22c' 'newspaper' = 'f1ea' 'not-equal' = 'f53e' 'notes-medical' = 'f481' 'object-group' = 'f247' 'object-ungroup' = 'f248' 'oil-can' = 'f613' 'om' = 'f679' 'otter' = 'f700' 'outdent' = 'f03b' 'pager' = 'f815' 'paint-brush' = 'f1fc' 'paint-roller' = 'f5aa' 'palette' = 'f53f' 'pallet' = 'f482' 'paper-plane' = 'f1d8' 'paperclip' = 'f0c6' 'parachute-box' = 'f4cd' 'paragraph' = 'f1dd' 'parking' = 'f540' 'passport' = 'f5ab' 'pastafarianism' = 'f67b' 'paste' = 'f0ea' 'pause' = 'f04c' 'pause-circle' = 'f28b' 'paw' = 'f1b0' 'peace' = 'f67c' 'pen' = 'f304' 'pen-alt' = 'f305' 'pen-fancy' = 'f5ac' 'pen-nib' = 'f5ad' 'pen-square' = 'f14b' 'pencil-alt' = 'f303' 'pencil-ruler' = 'f5ae' 'people-arrows' = 'e068' 'people-carry' = 'f4ce' 'pepper-hot' = 'f816' 'percent' = 'f295' 'percentage' = 'f541' 'person-booth' = 'f756' 'phone' = 'f095' 'phone-alt' = 'f879' 'phone-slash' = 'f3dd' 'phone-square' = 'f098' 'phone-square-alt' = 'f87b' 'phone-volume' = 'f2a0' 'photo-video' = 'f87c' 'piggy-bank' = 'f4d3' 'pills' = 'f484' 'pizza-slice' = 'f818' 'place-of-worship' = 'f67f' 'plane' = 'f072' 'plane-arrival' = 'f5af' 'plane-departure' = 'f5b0' 'plane-slash' = 'e069' 'play' = 'f04b' 'play-circle' = 'f144' 'plug' = 'f1e6' 'plus' = 'f067' 'plus-circle' = 'f055' 'plus-square' = 'f0fe' 'podcast' = 'f2ce' 'poll' = 'f681' 'poll-h' = 'f682' 'poo' = 'f2fe' 'poo-storm' = 'f75a' 'poop' = 'f619' 'portrait' = 'f3e0' 'pound-sign' = 'f154' 'power-off' = 'f011' 'pray' = 'f683' 'praying-hands' = 'f684' 'prescription' = 'f5b1' 'prescription-bottle' = 'f485' 'prescription-bottle-alt' = 'f486' 'print' = 'f02f' 'procedures' = 'f487' 'project-diagram' = 'f542' 'pump-medical' = 'e06a' 'pump-soap' = 'e06b' 'puzzle-piece' = 'f12e' 'qrcode' = 'f029' 'question' = 'f128' 'question-circle' = 'f059' 'quidditch' = 'f458' 'quote-left' = 'f10d' 'quote-right' = 'f10e' 'quran' = 'f687' 'radiation' = 'f7b9' 'radiation-alt' = 'f7ba' 'rainbow' = 'f75b' 'random' = 'f074' 'receipt' = 'f543' 'record-vinyl' = 'f8d9' 'recycle' = 'f1b8' 'redo' = 'f01e' 'redo-alt' = 'f2f9' 'registered' = 'f25d' 'remove-format' = 'f87d' 'reply' = 'f3e5' 'reply-all' = 'f122' 'republican' = 'f75e' 'restroom' = 'f7bd' 'retweet' = 'f079' 'ribbon' = 'f4d6' 'ring' = 'f70b' 'road' = 'f018' 'robot' = 'f544' 'rocket' = 'f135' 'route' = 'f4d7' 'rss' = 'f09e' 'rss-square' = 'f143' 'ruble-sign' = 'f158' 'ruler' = 'f545' 'ruler-combined' = 'f546' 'ruler-horizontal' = 'f547' 'ruler-vertical' = 'f548' 'running' = 'f70c' 'rupee-sign' = 'f156' 'sad-cry' = 'f5b3' 'sad-tear' = 'f5b4' 'satellite' = 'f7bf' 'satellite-dish' = 'f7c0' 'save' = 'f0c7' 'school' = 'f549' 'screwdriver' = 'f54a' 'scroll' = 'f70e' 'sd-card' = 'f7c2' 'search' = 'f002' 'search-dollar' = 'f688' 'search-location' = 'f689' 'search-minus' = 'f010' 'search-plus' = 'f00e' 'seedling' = 'f4d8' 'server' = 'f233' 'shapes' = 'f61f' 'share' = 'f064' 'share-alt' = 'f1e0' 'share-alt-square' = 'f1e1' 'share-square' = 'f14d' 'shekel-sign' = 'f20b' 'shield-alt' = 'f3ed' 'shield-virus' = 'e06c' 'ship' = 'f21a' 'shipping-fast' = 'f48b' 'shoe-prints' = 'f54b' 'shopping-bag' = 'f290' 'shopping-basket' = 'f291' 'shopping-cart' = 'f07a' 'shower' = 'f2cc' 'shuttle-van' = 'f5b6' 'sign' = 'f4d9' 'sign-in-alt' = 'f2f6' 'sign-language' = 'f2a7' 'sign-out-alt' = 'f2f5' 'signal' = 'f012' 'signature' = 'f5b7' 'sim-card' = 'f7c4' 'sink' = 'e06d' 'sitemap' = 'f0e8' 'skating' = 'f7c5' 'skiing' = 'f7c9' 'skiing-nordic' = 'f7ca' 'skull' = 'f54c' 'skull-crossbones' = 'f714' 'slash' = 'f715' 'sleigh' = 'f7cc' 'sliders-h' = 'f1de' 'smile' = 'f118' 'smile-beam' = 'f5b8' 'smile-wink' = 'f4da' 'smog' = 'f75f' 'smoking' = 'f48d' 'smoking-ban' = 'f54d' 'sms' = 'f7cd' 'snowboarding' = 'f7ce' 'snowflake' = 'f2dc' 'snowman' = 'f7d0' 'snowplow' = 'f7d2' 'soap' = 'e06e' 'socks' = 'f696' 'solar-panel' = 'f5ba' 'sort' = 'f0dc' 'sort-alpha-down' = 'f15d' 'sort-alpha-down-alt' = 'f881' 'sort-alpha-up' = 'f15e' 'sort-alpha-up-alt' = 'f882' 'sort-amount-down' = 'f160' 'sort-amount-down-alt' = 'f884' 'sort-amount-up' = 'f161' 'sort-amount-up-alt' = 'f885' 'sort-down' = 'f0dd' 'sort-numeric-down' = 'f162' 'sort-numeric-down-alt' = 'f886' 'sort-numeric-up' = 'f163' 'sort-numeric-up-alt' = 'f887' 'sort-up' = 'f0de' 'spa' = 'f5bb' 'space-shuttle' = 'f197' 'spell-check' = 'f891' 'spider' = 'f717' 'spinner' = 'f110' 'splotch' = 'f5bc' 'spray-can' = 'f5bd' 'square' = 'f0c8' 'square-full' = 'f45c' 'square-root-alt' = 'f698' 'stamp' = 'f5bf' 'star' = 'f005' 'star-and-crescent' = 'f699' 'star-half' = 'f089' 'star-half-alt' = 'f5c0' 'star-of-david' = 'f69a' 'star-of-life' = 'f621' 'step-backward' = 'f048' 'step-forward' = 'f051' 'stethoscope' = 'f0f1' 'sticky-note' = 'f249' 'stop' = 'f04d' 'stop-circle' = 'f28d' 'stopwatch' = 'f2f2' 'stopwatch-20' = 'e06f' 'store' = 'f54e' 'store-alt' = 'f54f' 'store-alt-slash' = 'e070' 'store-slash' = 'e071' 'stream' = 'f550' 'street-view' = 'f21d' 'strikethrough' = 'f0cc' 'stroopwafel' = 'f551' 'subscript' = 'f12c' 'subway' = 'f239' 'suitcase' = 'f0f2' 'suitcase-rolling' = 'f5c1' 'sun' = 'f185' 'superscript' = 'f12b' 'surprise' = 'f5c2' 'swatchbook' = 'f5c3' 'swimmer' = 'f5c4' 'swimming-pool' = 'f5c5' 'synagogue' = 'f69b' 'sync' = 'f021' 'sync-alt' = 'f2f1' 'syringe' = 'f48e' 'table' = 'f0ce' 'table-tennis' = 'f45d' 'tablet' = 'f10a' 'tablet-alt' = 'f3fa' 'tablets' = 'f490' 'tachometer-alt' = 'f3fd' 'tag' = 'f02b' 'tags' = 'f02c' 'tape' = 'f4db' 'tasks' = 'f0ae' 'taxi' = 'f1ba' 'teeth' = 'f62e' 'teeth-open' = 'f62f' 'temperature-high' = 'f769' 'temperature-low' = 'f76b' 'tenge' = 'f7d7' 'terminal' = 'f120' 'text-height' = 'f034' 'text-width' = 'f035' 'th' = 'f00a' 'th-large' = 'f009' 'th-list' = 'f00b' 'theater-masks' = 'f630' 'thermometer' = 'f491' 'thermometer-empty' = 'f2cb' 'thermometer-full' = 'f2c7' 'thermometer-half' = 'f2c9' 'thermometer-quarter' = 'f2ca' 'thermometer-three-quarters' = 'f2c8' 'thumbs-down' = 'f165' 'thumbs-up' = 'f164' 'thumbtack' = 'f08d' 'ticket-alt' = 'f3ff' 'times' = 'f00d' 'times-circle' = 'f057' 'tint' = 'f043' 'tint-slash' = 'f5c7' 'tired' = 'f5c8' 'toggle-off' = 'f204' 'toggle-on' = 'f205' 'toilet' = 'f7d8' 'toilet-paper' = 'f71e' 'toilet-paper-slash' = 'e072' 'toolbox' = 'f552' 'tools' = 'f7d9' 'tooth' = 'f5c9' 'torah' = 'f6a0' 'torii-gate' = 'f6a1' 'tractor' = 'f722' 'trademark' = 'f25c' 'traffic-light' = 'f637' 'trailer' = 'e041' 'train' = 'f238' 'tram' = 'f7da' 'transgender' = 'f224' 'transgender-alt' = 'f225' 'trash' = 'f1f8' 'trash-alt' = 'f2ed' 'trash-restore' = 'f829' 'trash-restore-alt' = 'f82a' 'tree' = 'f1bb' 'trophy' = 'f091' 'truck' = 'f0d1' 'truck-loading' = 'f4de' 'truck-monster' = 'f63b' 'truck-moving' = 'f4df' 'truck-pickup' = 'f63c' 'tshirt' = 'f553' 'tty' = 'f1e4' 'tv' = 'f26c' 'umbrella' = 'f0e9' 'umbrella-beach' = 'f5ca' 'underline' = 'f0cd' 'undo' = 'f0e2' 'undo-alt' = 'f2ea' 'universal-access' = 'f29a' 'university' = 'f19c' 'unlink' = 'f127' 'unlock' = 'f09c' 'unlock-alt' = 'f13e' 'upload' = 'f093' 'user' = 'f007' 'user-alt' = 'f406' 'user-alt-slash' = 'f4fa' 'user-astronaut' = 'f4fb' 'user-check' = 'f4fc' 'user-circle' = 'f2bd' 'user-clock' = 'f4fd' 'user-cog' = 'f4fe' 'user-edit' = 'f4ff' 'user-friends' = 'f500' 'user-graduate' = 'f501' 'user-injured' = 'f728' 'user-lock' = 'f502' 'user-md' = 'f0f0' 'user-minus' = 'f503' 'user-ninja' = 'f504' 'user-nurse' = 'f82f' 'user-plus' = 'f234' 'user-secret' = 'f21b' 'user-shield' = 'f505' 'user-slash' = 'f506' 'user-tag' = 'f507' 'user-tie' = 'f508' 'user-times' = 'f235' 'users' = 'f0c0' 'users-cog' = 'f509' 'users-slash' = 'e073' 'utensil-spoon' = 'f2e5' 'utensils' = 'f2e7' 'vector-square' = 'f5cb' 'venus' = 'f221' 'venus-double' = 'f226' 'venus-mars' = 'f228' 'vest' = 'e085' 'vest-patches' = 'e086' 'vial' = 'f492' 'vials' = 'f493' 'video' = 'f03d' 'video-slash' = 'f4e2' 'vihara' = 'f6a7' 'virus' = 'e074' 'virus-slash' = 'e075' 'viruses' = 'e076' 'voicemail' = 'f897' 'volleyball-ball' = 'f45f' 'volume-down' = 'f027' 'volume-mute' = 'f6a9' 'volume-off' = 'f026' 'volume-up' = 'f028' 'vote-yea' = 'f772' 'vr-cardboard' = 'f729' 'walking' = 'f554' 'wallet' = 'f555' 'warehouse' = 'f494' 'water' = 'f773' 'wave-square' = 'f83e' 'weight' = 'f496' 'weight-hanging' = 'f5cd' 'wheelchair' = 'f193' 'wifi' = 'f1eb' 'wind' = 'f72e' 'window-close' = 'f410' 'window-maximize' = 'f2d0' 'window-minimize' = 'f2d1' 'window-restore' = 'f2d2' 'wine-bottle' = 'f72f' 'wine-glass' = 'f4e3' 'wine-glass-alt' = 'f5ce' 'won-sign' = 'f159' 'wrench' = 'f0ad' 'x-ray' = 'f497' 'yen-sign' = 'f157' 'yin-yang' = 'f6ad' } FontsMaterialIcon = @( '3d-rotation' '500px' '8tracks' 'account' 'account-add' 'account-box' 'account-box-mail' 'account-box-o' 'account-box-phone' 'account-calendar' 'account-circle' 'account-o' 'accounts' 'accounts-add' 'accounts-alt' 'accounts-list' 'accounts-list-alt' 'accounts-outline' 'airline-seat-flat' 'airline-seat-flat-angled' 'airline-seat-individual-suite' 'airline-seat-legroom-extra' 'airline-seat-legroom-normal' 'airline-seat-legroom-reduced' 'airline-seat-recline-extra' 'airline-seat-recline-normal' 'airplane' 'airplane-off' 'airplay' 'alarm' 'alarm-check' 'alarm-off' 'alarm-plus' 'alarm-snooze' 'album' 'alert-circle' 'alert-circle-o' 'alert-octagon' 'alert-polygon' 'alert-triangle' 'amazon' 'android' 'android-alt' 'apple' 'apps' 'archive' 'arrow-left' 'arrow-left-bottom' 'arrow-merge' 'arrow-missed' 'arrow-right' 'arrow-right-top' 'arrows' 'arrow-split' 'aspect-ratio' 'aspect-ratio-alt' 'assignment' 'assignment-account' 'assignment-alert' 'assignment-check' 'assignment-o' 'assignment-return' 'assignment-returned' 'attachment' 'attachment-alt' 'audio' 'badge-check' 'balance' 'balance-wallet' 'battery' 'battery-alert' 'battery-flash' 'battery-unknown' 'behance' 'bike' 'block' 'block-alt' 'blogger' 'bluetooth' 'bluetooth-connected' 'bluetooth-off' 'bluetooth-search' 'bluetooth-setting' 'blur' 'blur-circular' 'blur-linear' 'blur-off' 'boat' 'book' 'book-image' 'bookmark' 'bookmark-outline' 'border-all' 'border-bottom' 'border-clear' 'border-color' 'border-horizontal' 'border-inner' 'border-left' 'border-outer' 'border-right' 'border-style' 'border-top' 'border-vertical' 'brightness-2' 'brightness-3' 'brightness-4' 'brightness-5' 'brightness-6' 'brightness-7' 'brightness-auto' 'brightness-setting' 'broken-image' 'brush' 'bug' 'bus' 'cake' 'calendar' 'calendar-alt' 'calendar-check' 'calendar-close' 'calendar-note' 'camera' 'camera-add' 'camera-alt' 'camera-bw' 'camera-front' 'camera-mic' 'camera-party-mode' 'camera-rear' 'camera-roll' 'camera-switch' 'car' 'card' 'card-alert' 'card-giftcard' 'card-membership' 'card-off' 'card-sd' 'card-sim' 'card-travel' 'caret-down' 'caret-down-circle' 'caret-left' 'caret-left-circle' 'caret-right' 'caret-right-circle' 'caret-up' 'caret-up-circle' 'car-taxi' 'car-wash' 'case' 'case-check' 'case-download' 'case-play' 'cast' 'cast-connected' 'center-focus-strong' 'center-focus-weak' 'chart' 'chart-donut' 'check' 'check-all' 'check-circle' 'check-circle-u' 'check-square' 'chevron-down' 'chevron-left' 'chevron-right' 'chevron-up' 'circle' 'circle-o' 'city' 'city-alt' 'close' 'close-circle' 'close-circle-o' 'closed-caption' 'cloud' 'cloud-box' 'cloud-circle' 'cloud-done' 'cloud-download' 'cloud-off' 'cloud-outline' 'cloud-outline-alt' 'cloud-upload' 'cocktail' 'code' 'codepen' 'code-setting' 'code-smartphone' 'coffee' 'collection-bookmark' 'collection-case-play' 'collection-folder-image' 'collection-image' 'collection-image-o' 'collection-item' 'collection-item-1' 'collection-item-2' 'collection-item-3' 'collection-item-4' 'collection-item-5' 'collection-item-6' 'collection-item-7' 'collection-item-8' 'collection-item-9' 'collection-item-9-plus' 'collection-music' 'collection-pdf' 'collection-plus' 'collection-speaker' 'collection-text' 'collection-video' 'comment' 'comment-alert' 'comment-alt' 'comment-alt-text' 'comment-edit' 'comment-image' 'comment-list' 'comment-more' 'comment-outline' 'comments' 'comment-text' 'comment-text-alt' 'comment-video' 'compare' 'compass' 'confirmation-number' 'copy' 'crop' 'crop-16-9' 'crop-3-2' 'crop-5-4' 'crop-7-5' 'crop-din' 'crop-free' 'crop-landscape' 'crop-portrait' 'crop-square' 'cutlery' 'delete' 'delicious' 'desktop-mac' 'desktop-windows' 'developer-board' 'device-hub' 'devices' 'devices-off' 'dialpad' 'disc-full' 'disqus' 'dns' 'dock' 'dot-circle' 'dot-circle-alt' 'download' 'dribbble' 'drink' 'dropbox' 'edit' 'eject' 'eject-alt' 'email' 'email-open' 'equalizer' 'evernote' 'explicit' 'exposure' 'exposure-alt' 'eye' 'eyedropper' 'eye-off' 'face' 'facebook' 'facebook-box' 'fast-forward' 'fast-rewind' 'favorite' 'favorite-outline' 'female' 'file' 'file-plus' 'file-text' 'filter-b-and-w' 'filter-center-focus' 'filter-frames' 'filter-list' 'filter-tilt-shift' 'fire' 'flag' 'flare' 'flash' 'flash-auto' 'flash-off' 'flattr' 'flickr' 'flight-land' 'flight-takeoff' 'flip' 'flip-to-back' 'flip-to-front' 'floppy' 'flower' 'flower-alt' 'folder' 'folder-outline' 'folder-person' 'folder-star' 'folder-star-alt' 'font' 'format-align-center' 'format-align-justify' 'format-align-left' 'format-align-right' 'format-bold' 'format-clear' 'format-clear-all' 'format-color-fill' 'format-color-reset' 'format-color-text' 'format-indent-decrease' 'format-indent-increase' 'format-italic' 'format-line-spacing' 'format-list-bulleted' 'format-list-numbered' 'format-ltr' 'format-rtl' 'format-size' 'format-strikethrough' 'format-strikethrough-s' 'format-subject' 'format-underlined' 'format-valign-bottom' 'format-valign-center' 'format-valign-top' 'forward' 'forward-10' 'forward-30' 'forward-5' 'fullscreen' 'fullscreen-alt' 'fullscreen-exit' 'functions' 'gamepad' 'gas-station' 'gesture' 'gif' 'github' 'github-alt' 'github-box' 'globe' 'globe-alt' 'globe-lock' 'google' 'google-drive' 'google-earth' 'google-glass' 'google-maps' 'google-old' 'google-pages' 'google-play' 'google-plus' 'google-plus-box' 'gps' 'gps-dot' 'gps-off' 'gradient' 'graduation-cap' 'grain' 'graphic-eq' 'grid' 'grid-off' 'group' 'group-work' 'hd' 'hdr' 'hdr-off' 'hdr-strong' 'hdr-weak' 'headset' 'headset-mic' 'hearing' 'help' 'help-outline' 'home' 'hospital' 'hospital-alt' 'hotel' 'hourglass' 'hourglass-alt' 'hourglass-outline' 'hq' 'http' 'image' 'image-alt' 'image-o' 'inbox' 'info' 'info-outline' 'input-antenna' 'input-composite' 'input-hdmi' 'input-power' 'input-svideo' 'instagram' 'invert-colors' 'invert-colors-off' 'iridescent' 'key' 'keyboard' 'keyboard-hide' 'label' 'label-alt' 'label-alt-outline' 'label-heart' 'labels' 'lamp' 'landscape' 'language-css3' 'language-html5' 'language-javascript' 'language-python' 'language-python-alt' 'laptop' 'laptop-chromebook' 'laptop-mac' 'lastfm' 'layers' 'layers-off' 'leak' 'leak-off' 'library' 'link' 'linkedin' 'linkedin-box' 'lock' 'lock-open' 'lock-outline' 'long-arrow-down' 'long-arrow-left' 'long-arrow-return' 'long-arrow-right' 'long-arrow-tab' 'long-arrow-up' 'looks' 'loupe' 'mail-reply' 'mail-reply-all' 'mail-send' 'male' 'male-alt' 'male-female' 'mall' 'map' 'markunread-mailbox' 'memory' 'menu' 'mic' 'mic-off' 'mic-outline' 'mic-setting' 'minus' 'minus-circle' 'minus-circle-outline' 'minus-square' 'money' 'money-box' 'money-off' 'mood' 'mood-bad' 'more' 'more-vert' 'mouse' 'movie' 'movie-alt' 'n-1-square' 'n-2-square' 'n-3-square' 'n-4-square' 'n-5-square' 'n-6-square' 'nature' 'nature-people' 'navigation' 'neg-1' 'neg-2' 'network' 'network-alert' 'network-locked' 'network-off' 'network-outline' 'network-setting' 'nfc' 'notifications' 'notifications-active' 'notifications-add' 'notifications-none' 'notifications-off' 'notifications-paused' 'odnoklassniki' 'open-in-browser' 'open-in-new' 'outlook' 'palette' 'panorama-horizontal' 'panorama-vertical' 'panorama-wide-angle' 'parking' 'pause' 'pause-circle' 'pause-circle-outline' 'paypal' 'paypal-alt' 'phone' 'phone-bluetooth' 'phone-end' 'phone-forwarded' 'phone-in-talk' 'phone-locked' 'phone-missed' 'phone-msg' 'phone-paused' 'phone-ring' 'phone-setting' 'phone-sip' 'photo-size-select-large' 'photo-size-select-small' 'picture-in-picture' 'pin' 'pin-account' 'pin-assistant' 'pin-drop' 'pin-help' 'pin-off' 'pinterest' 'pinterest-box' 'pizza' 'plaster' 'play' 'play-circle' 'play-circle-outline' 'play-for-work' 'playlist-audio' 'playlist-plus' 'playstation' 'plus' 'plus-1' 'plus-2' 'plus-circle' 'plus-circle-o' 'plus-circle-o-duplicate' 'plus-square' 'pocket' 'polymer' 'portable-wifi' 'portable-wifi-changes' 'portable-wifi-off' 'power' 'power-input' 'power-setting' 'present-to-all' 'print' 'puzzle-piece' 'quote' 'radio' 'railway' 'reader' 'receipt' 'reddit' 'redo' 'refresh' 'refresh-alt' 'refresh-sync' 'refresh-sync-alert' 'refresh-sync-off' 'remote-control' 'remote-control-alt' 'repeat' 'repeat-one' 'replay' 'replay-10' 'replay-30' 'replay-5' 'roller' 'rotate-ccw' 'rotate-cw' 'rotate-left' 'rotate-right' 'router' 'rss' 'ruler' 'run' 'satellite' 'scanner' 'scissors' 'screen-rotation' 'screen-rotation-lock' 'search' 'search-for' 'search-in-file' 'search-in-page' 'search-replace' 'seat' 'sec-10' 'sec-3' 'select-all' 'settings' 'settings-square' 'shape' 'share' 'shield-check' 'shield-security' 'shopping-basket' 'shopping-cart' 'shopping-cart-plus' 'shuffle' 'sign-in' 'skip-next' 'skip-previous' 'skype' 'slideshare' 'slideshow' 'smartphone' 'smartphone-android' 'smartphone-download' 'smartphone-erase' 'smartphone-info' 'smartphone-iphone' 'smartphone-landscape' 'smartphone-landscape-lock' 'smartphone-lock' 'smartphone-portrait-lock' 'smartphone-ring' 'smartphone-setting' 'smartphone-setup' 'sort-amount-asc' 'sort-amount-desc' 'sort-asc' 'sort-desc' 'soundcloud' 'space-bar' 'speaker' 'spellcheck' 'spinner' 'square-down' 'square-o' 'square-right' 'stackoverflow' 'star' 'star-circle' 'star-half' 'star-outline' 'steam' 'steam-square' 'stop' 'storage' 'store' 'store-24' 'subway' 'sun' 'surround-sound' 'swap' 'swap-alt' 'swap-vertical' 'swap-vertical-circle' 'tab' 'tablet' 'tablet-android' 'tablet-mac' 'tab-unselected' 'tag' 'tag-close' 'tag-more' 'tap-and-play' 'text-format' 'texture' 'thumb-down' 'thumb-up' 'thumb-up-down' 'ticket-star' 'time' 'time-countdown' 'time-interval' 'timer' 'time-restore' 'time-restore-setting' 'timer-off' 'toll' 'tonality' 'toys' 'traffic' 'transform' 'translate' 'trending-down' 'trending-flat' 'trending-up' 'triangle-down' 'triangle-up' 'truck' 'tumblr' 'tune' 'turning-sign' 'tv' 'tv-alt-play' 'tv-list' 'tv-play' 'twitch' 'twitter' 'twitter-box' 'undo' 'unfold-less' 'unfold-more' 'ungroup' 'upload' 'usb' 'vibration' 'videocam' 'videocam-off' 'videocam-switch' 'view-agenda' 'view-array' 'view-carousel' 'view-column' 'view-comfy' 'view-compact' 'view-dashboard' 'view-day' 'view-headline' 'view-list' 'view-list-alt' 'view-module' 'view-quilt' 'view-stream' 'view-subtitles' 'view-toc' 'view-web' 'view-week' 'vignette' 'vimeo' 'vk' 'voicemail' 'volume-down' 'volume-mute' 'volume-off' 'volume-up' 'walk' 'wallpaper' 'washing-machine' 'watch' 'wb-auto' 'whatsapp' 'widgets' 'wifi' 'wifi-alt' 'wifi-alt-2' 'wifi-info' 'wifi-lock' 'wifi-off' 'wifi-outline' 'wikipedia' 'window-maximize' 'window-minimize' 'window-restore' 'windows' 'wrap-text' 'wrench' 'xbox' 'yahoo' 'youtube' 'youtube-play' 'zero' 'zoom-in' 'zoom-out' ) FontsSimple = @( '1001tracklists' '1password' '3m' '42' '4d' '500px' 'a-frame' 'abbrobotstudio' 'abbvie' 'abletonlive' 'about-dot-me' 'abstract' 'academia' 'accenture' 'acclaim' 'accusoft' 'acer' 'acm' 'actigraph' 'activision' 'adafruit' 'adblock' 'adblockplus' 'addthis' 'adguard' 'adobe' 'adobeacrobatreader' 'adobeaftereffects' 'adobeaudition' 'adobecreativecloud' 'adobedreamweaver' 'adobefonts' 'adobeillustrator' 'adobeindesign' 'adobelightroom' 'adobelightroomclassic' 'adobephonegap' 'adobephotoshop' 'adobepremierepro' 'adobexd' 'adonisjs' 'aerlingus' 'aeroflot' 'aeromexico' 'aerospike' 'affinity' 'affinitydesigner' 'affinityphoto' 'affinitypublisher' 'aidungeon' 'aiohttp' 'aiqfome' 'airasia' 'airbnb' 'airbus' 'aircall' 'aircanada' 'airchina' 'airfrance' 'airplayaudio' 'airplayvideo' 'airtable' 'alacritty' 'alfaromeo' 'algolia' 'alibaba-dot-com' 'alibabacloud' 'aliexpress' 'alipay' 'alitalia' 'alliedmodders' 'allocine' 'alltrails' 'alpinedotjs' 'alpinelinux' 'altiumdesigner' 'amazon' 'amazonalexa' 'amazonaws' 'amazondynamodb' 'amazonfiretv' 'amazonlumberyard' 'amazonpay' 'amazonprime' 'amazons3' 'amd' 'americanairlines' 'americanexpress' 'amp' 'amul' 'ana' 'anaconda' 'analogue' 'anchor' 'andela' 'android' 'androidauto' 'androidstudio' 'angellist' 'angular' 'angularjs' 'angularuniversal' 'anilist' 'ansible' 'ansys' 'antdesign' 'antena3' 'anydesk' 'aol' 'apache' 'apacheairflow' 'apacheant' 'apachecassandra' 'apachecloudstack' 'apachecordova' 'apachedruid' 'apacheecharts' 'apacheflink' 'apachegroovy' 'apachehive' 'apachejmeter' 'apachekafka' 'apachekylin' 'apachemaven' 'apachenetbeanside' 'apacheopenoffice' 'apachepulsar' 'apacherocketmq' 'apachesolr' 'apachespark' 'apachetomcat' 'aparat' 'apollographql' 'apostrophe' 'apple' 'applearcade' 'applemusic' 'applepay' 'applepodcasts' 'appletv' 'appsignal' 'appstore' 'appveyor' 'aral' 'arangodb' 'archicad' 'archiveofourown' 'archlinux' 'ardour' 'arduino' 'arkecosystem' 'arlo' 'artixlinux' 'artstation' 'arxiv' 'asana' 'asciidoctor' 'asciinema' 'aseprite' 'askfm' 'askubuntu' 'assemblyscript' 'asus' 'at-and-t' 'atari' 'atlassian' 'atom' 'audacity' 'audi' 'audible' 'audio-technica' 'audioboom' 'audiomack' 'aurelia' 'auth0' 'authy' 'autodesk' 'autohotkey' 'automatic' 'automattic' 'autotask' 'aventrix' 'awesomelists' 'awesomewm' 'awsamplify' 'azureartifacts' 'azuredataexplorer' 'azuredevops' 'azurefunctions' 'azurepipelines' 'b-and-rautomation' 'babel' 'badgr' 'badoo' 'baidu' 'bamboo' 'bancontact' 'bandcamp' 'bandlab' 'bandsintown' 'bankofamerica' 'barclays' 'baremetrics' 'basecamp' 'bata' 'bathasu' 'battle-dot-net' 'bbc' 'bbciplayer' 'beatport' 'beats' 'beatsbydre' 'behance' 'beijingsubway' 'bentley' 'betfair' 'bigbasket' 'bigcartel' 'bigcommerce' 'bilibili' 'bing' 'bit' 'bitbucket' 'bitcoin' 'bitcoincash' 'bitcoinsv' 'bitdefender' 'bitly' 'bitrise' 'bitwarden' 'bitwig' 'blackberry' 'blazemeter' 'blazor' 'blender' 'blockchain-dot-com' 'blogger' 'bloglovin' 'blueprint' 'bluetooth' 'bmcsoftware' 'bmw' 'boeing' 'bookbub' 'bookmeter' 'bookstack' 'boost' 'bootstrap' 'bosch' 'bose' 'bower' 'box' 'brand-dot-ai' 'brandfolder' 'brave' 'breaker' 'britishairways' 'broadcom' 'bt' 'buddy' 'buefy' 'buffer' 'bugatti' 'bugcrowd' 'bugsnag' 'buildkite' 'bulma' 'bunq' 'buymeacoffee' 'buzzfeed' 'byte' 'c' 'cachet' 'cairometro' 'cakephp' 'campaignmonitor' 'canonical' 'canva' 'capacitor' 'carthrottle' 'carto' 'cashapp' 'castbox' 'castorama' 'castro' 'caterpillar' 'cbs' 'cdprojekt' 'celery' 'centos' 'ceph' 'cesium' 'cevo' 'chai' 'chainlink' 'chakraui' 'chart-dot-js' 'chartmogul' 'chase' 'chatbot' 'checkio' 'checkmarx' 'chef' 'chevrolet' 'chinaeasternairlines' 'chinasouthernairlines' 'chocolatey' 'chrysler' 'chupachups' 'cinema4d' 'circle' 'circleci' 'cirrusci' 'cisco' 'citrix' 'citroen' 'civicrm' 'ckeditor4' 'claris' 'clickup' 'clion' 'cliqz' 'clockify' 'clojure' 'cloud66' 'cloudbees' 'cloudcannon' 'cloudera' 'cloudflare' 'cloudsmith' 'cloudways' 'clubhouse' 'clyp' 'cmake' 'cnn' 'co-op' 'cockroachlabs' 'cocoapods' 'cocos' 'coda' 'codacy' 'codeberg' 'codecademy' 'codeceptjs' 'codechef' 'codeclimate' 'codecov' 'codefactor' 'codeforces' 'codeigniter' 'codemagic' 'codemirror' 'codenewbie' 'codepen' 'codeproject' 'codersrank' 'coderwall' 'codesandbox' 'codeship' 'codewars' 'codingame' 'codingninjas' 'codio' 'coffeescript' 'cognizant' 'coinbase' 'commerzbank' 'commonworkflowlanguage' 'composer' 'compropago' 'concourse' 'conda-forge' 'conekta' 'confluence' 'consul' 'contactlesspayment' 'contentful' 'convertio' 'cookiecutter' 'coronaengine' 'coronarenderer' 'corsair' 'couchbase' 'counter-strike' 'countingworkspro' 'coursera' 'coveralls' 'cpanel' 'cplusplus' 'craftcms' 'creativecommons' 'crehana' 'crowdin' 'crowdsource' 'crunchbase' 'crunchyroll' 'cryengine' 'crystal' 'csharp' 'css3' 'csswizardry' 'cucumber' 'curl' 'curseforge' 'cycling74' 'cypress' 'd-wavesystems' 'd3-dot-js' 'dacia' 'daf' 'dailymotion' 'daimler' 'darkreader' 'dart' 'daserste' 'dash' 'dashlane' 'dassaultsystemes' 'databricks' 'datacamp' 'datadog' 'datastax' 'dataversioncontrol' 'datocms' 'datto' 'dazn' 'dblp' 'dcentertainment' 'debian' 'deepin' 'deepnote' 'deezer' 'delicious' 'deliveroo' 'dell' 'delonghi' 'delphi' 'delta' 'deno' 'dependabot' 'derspiegel' 'designernews' 'deutschebahn' 'deutschebank' 'dev-dot-to' 'deviantart' 'devpost' 'devrant' 'dgraph' 'dhl' 'diagrams-dot-net' 'dialogflow' 'diaspora' 'digg' 'digi-keyelectronics' 'digitalocean' 'dior' 'directus' 'discogs' 'discord' 'discourse' 'discover' 'disqus' 'disroot' 'django' 'dlna' 'docker' 'docusign' 'dogecoin' 'dolby' 'doordash' 'dot-net' 'douban' 'draugiem-dot-lv' 'dribbble' 'drone' 'drooble' 'dropbox' 'drupal' 'dsautomobiles' 'dtube' 'duckduckgo' 'dunked' 'duolingo' 'dwm' 'dynamics365' 'dynatrace' 'ea' 'eagle' 'easyjet' 'ebay' 'eclipseche' 'eclipseide' 'eclipsejetty' 'eclipsemosquitto' 'eclipsevert-dot-x' 'editorconfig' 'edx' 'egghead' 'egnyte' 'eightsleep' 'elastic' 'elasticcloud' 'elasticsearch' 'elasticstack' 'electron' 'element' 'elementary' 'eleventy' 'elixir' 'eljueves' 'ello' 'elm' 'elsevier' 'embarcadero' 'ember-dot-js' 'emby' 'emirates' 'emlakjet' 'empirekred' 'enpass' 'envato' 'epel' 'epicgames' 'epson' 'erlang' 'esea' 'eslgaming' 'eslint' 'esphome' 'espressif' 'ethereum' 'ethiopianairlines' 'etihadairways' 'etsy' 'eventbrite' 'eventstore' 'evernote' 'everplaces' 'evry' 'exercism' 'expensify' 'expertsexchange' 'expo' 'express' 'eyeem' 'f-droid' 'f-secure' 'facebook' 'facebookgaming' 'facebooklive' 'faceit' 'facepunch' 'falcon' 'fampay' 'fandango' 'fandom' 'farfetch' 'fastapi' 'fastify' 'fastlane' 'fastly' 'fathom' 'favro' 'feathub' 'fedex' 'fedora' 'fedramp' 'feedly' 'ferrari' 'ferrarin-dot-v-dot' 'ffmpeg' 'fiat' 'fidoalliance' 'fifa' 'figma' 'figshare' 'fila' 'files' 'filezilla' 'fing' 'firebase' 'firefox' 'firefoxbrowser' 'first' 'fitbit' 'fite' 'fiverr' 'flask' 'flathub' 'flattr' 'flickr' 'flipboard' 'flipkart' 'floatplane' 'flood' 'fluentd' 'flutter' 'fmod' 'fnac' 'folium' 'fontawesome' 'fontbase' 'foodpanda' 'ford' 'forestry' 'formstack' 'fortinet' 'fortran' 'fossa' 'fossilscm' 'foursquare' 'foxtel' 'fozzy' 'framer' 'fraunhofer-gesellschaft' 'freebsd' 'freecodecamp' 'freedesktop-dot-org' 'freelancer' 'freenas' 'fujifilm' 'fujitsu' 'furaffinity' 'furrynetwork' 'futurelearn' 'g2a' 'gamejolt' 'garmin' 'gatling' 'gatsby' 'gauges' 'geeksforgeeks' 'generalelectric' 'generalmotors' 'genius' 'gentoo' 'geocaching' 'gerrit' 'ghost' 'ghostery' 'gimp' 'giphy' 'git' 'gitbook' 'gitea' 'gitee' 'gitextensions' 'github' 'githubactions' 'githubsponsors' 'gitkraken' 'gitlab' 'gitlfs' 'gitpod' 'gitter' 'glassdoor' 'glitch' 'gmail' 'gnome' 'gnu' 'gnubash' 'gnuemacs' 'gnuicecat' 'gnuprivacyguard' 'gnusocial' 'go' 'godotengine' 'gofundme' 'gog-dot-com' 'goldenline' 'goodreads' 'google' 'googleads' 'googleadsense' 'googleanalytics' 'googleassistant' 'googlecalendar' 'googlecardboard' 'googlecast' 'googlechat' 'googlechrome' 'googleclassroom' 'googlecloud' 'googlecolab' 'googledomains' 'googledrive' 'googleearth' 'googlefit' 'googlefonts' 'googlehangouts' 'googlekeep' 'googlelens' 'googlemaps' 'googlemeet' 'googlemessages' 'googlemybusiness' 'googlenearby' 'googlenews' 'googleoptimize' 'googlepay' 'googlephotos' 'googleplay' 'googlepodcasts' 'googlescholar' 'googlesearchconsole' 'googlesheets' 'googlestreetview' 'googletagmanager' 'googletranslate' 'gotomeeting' 'gov-dot-uk' 'gradle' 'grafana' 'grammarly' 'graphcool' 'graphql' 'grav' 'gravatar' 'graylog' 'greensock' 'griddotai' 'gridsome' 'groupon' 'grubhub' 'grunt' 'guangzhoumetro' 'gulp' 'gumroad' 'gumtree' 'gutenberg' 'habr' 'hackaday' 'hackclub' 'hackerearth' 'hackerone' 'hackerrank' 'hackhands' 'hackster' 'hackthebox' 'handshake' 'handshake_protocol' 'happycow' 'harbor' 'hashnode' 'haskell' 'hasura' 'hatenabookmark' 'haveibeenpwned' 'haxe' 'hbo' 'hcl' 'headspace' 'hellofresh' 'hellyhansen' 'helm' 'helpdesk' 'here' 'heroku' 'hexo' 'hey' 'hibernate' 'highly' 'hilton' 'hipchat' 'hitachi' 'hive' 'hive_blockchain' 'hockeyapp' 'homeadvisor' 'homeassistant' 'homeassistantcommunitystore' 'homebrew' 'homebridge' 'homify' 'honda' 'hootsuite' 'hoppscotch' 'hotels-dot-com' 'hotjar' 'houdini' 'houzz' 'hp' 'html5' 'htmlacademy' 'huawei' 'hubspot' 'hugo' 'hulu' 'humblebundle' 'hungryjacks' 'hurriyetemlak' 'husqvarna' 'hyper' 'hyperledger' 'hypothesis' 'hyundai' 'iata' 'ibeacon' 'ibm' 'ibmwatson' 'icinga' 'icloud' 'icomoon' 'icon' 'iconfinder' 'iconify' 'iconjar' 'icq' 'ideal' 'ieee' 'ifixit' 'ifood' 'ifttt' 'iheartradio' 'ikea' 'imagej' 'imdb' 'imgur' 'immer' 'imou' 'indeed' 'infiniti' 'influxdb' 'informatica' 'infosys' 'ingress' 'inkscape' 'insomnia' 'instacart' 'instagram' 'instapaper' 'instructables' 'integromat' 'intel' 'intellijidea' 'intercom' 'internetarchive' 'internetexplorer' 'intigriti' 'invision' 'invoiceninja' 'iobroker' 'ionic' 'ios' 'iota' 'ipfs' 'issuu' 'itch-dot-io' 'itunes' 'iveco' 'jabber' 'jaguar' 'jamboard' 'jameson' 'jamstack' 'jasmine' 'java' 'javascript' 'jbl' 'jcb' 'jeep' 'jekyll' 'jellyfin' 'jenkins' 'jenkinsx' 'jest' 'jet' 'jetbrains' 'jfrog' 'jfrogbintray' 'jinja' 'jira' 'jirasoftware' 'jitsi' 'johndeere' 'joomla' 'jpeg' 'jquery' 'jrgroup' 'jsdelivr' 'jsfiddle' 'json' 'jsonwebtokens' 'jss' 'julia' 'junipernetworks' 'junit5' 'jupyter' 'justeat' 'justgiving' 'kaggle' 'kahoot' 'kaios' 'kakao' 'kakaotalk' 'kalilinux' 'karlsruherverkehrsverbund' 'kasasmart' 'kashflow' 'kaspersky' 'katacoda' 'katana' 'kde' 'kdenlive' 'keepassxc' 'kentico' 'keras' 'keybase' 'keycdn' 'khanacademy' 'khronosgroup' 'kia' 'kibana' 'kickstarter' 'kik' 'kirby' 'kitsu' 'klarna' 'klm' 'klook' 'klout' 'knowledgebase' 'known' 'ko-fi' 'kodi' 'koding' 'kofax' 'komoot' 'kongregate' 'kotlin' 'krita' 'ktm' 'kubernetes' 'kubuntu' 'kyocera' 'labview' 'lada' 'lamborghini' 'landrover' 'laragon' 'laravel' 'laravelhorizon' 'laravelnova' 'last-dot-fm' 'lastpass' 'latex' 'launchpad' 'lbry' 'leaflet' 'leanpub' 'leetcode' 'lenovo' 'less' 'letsencrypt' 'letterboxd' 'lg' 'lgtm' 'liberapay' 'libraries-dot-io' 'librarything' 'libreoffice' 'libuv' 'lichess' 'lifx' 'lighthouse' 'line' 'lineageos' 'linewebtoon' 'linkedin' 'linktree' 'linode' 'linux' 'linuxcontainers' 'linuxfoundation' 'linuxmint' 'lionair' 'lit' 'litecoin' 'livechat' 'livejournal' 'livestream' 'llvm' 'lmms' 'logitech' 'logmein' 'logstash' 'looker' 'loom' 'loop' 'lospec' 'lotpolishairlines' 'lua' 'lubuntu' 'lufthansa' 'lumen' 'lydia' 'lyft' 'maas' 'macos' 'macys' 'magento' 'magisk' 'mail-dot-ru' 'mailchimp' 'majorleaguehacking' 'makerbot' 'man' 'manageiq' 'manjaro' 'mapbox' 'mariadb' 'mariadbfoundation' 'markdown' 'marketo' 'marriott' 'maserati' 'mastercard' 'mastercomfig' 'mastodon' 'material-ui' 'materialdesign' 'materialdesignicons' 'mathworks' 'matomo' 'matrix' 'mattermost' 'matternet' 'max-planck-gesellschaft' 'max' 'maytag' 'mazda' 'mcafee' 'mcdonalds' 'mclaren' 'mdnwebdocs' 'mediafire' 'mediatek' 'mediatemple' 'medium' 'meetup' 'mega' 'mendeley' 'mercedes' 'mercurial' 'messenger' 'metabase' 'metafilter' 'meteor' 'metro' 'metrodelaciudaddemexico' 'metrodemadrid' 'metrodeparis' 'mewe' 'micro-dot-blog' 'microbit' 'microgenetics' 'micropython' 'microsoft' 'microsoftacademic' 'microsoftaccess' 'microsoftazure' 'microsoftedge' 'microsoftexcel' 'microsoftexchange' 'microsoftoffice' 'microsoftonedrive' 'microsoftonenote' 'microsoftoutlook' 'microsoftpowerpoint' 'microsoftsharepoint' 'microsoftsqlserver' 'microsoftteams' 'microsoftvisio' 'microsoftword' 'microstrategy' 'midi' 'minds' 'minecraft' 'minetest' 'mini' 'minutemailer' 'miro' 'mitsubishi' 'mix' 'mixcloud' 'mobx-state-tree' 'mobx' 'mocha' 'modx' 'mojangstudios' 'moleculer' 'momenteo' 'monero' 'mongodb' 'monkeytie' 'monogram' 'monster' 'monzo' 'moo' 'moscowmetro' 'motorola' 'mozilla' 'mta' 'mtr' 'mumble' 'musescore' 'musicbrainz' 'mxlinux' 'myanimelist' 'myob' 'myspace' 'mysql' 'n26' 'namebase' 'namecheap' 'nano' 'nasa' 'nationalgrid' 'nativescript' 'naver' 'nba' 'nbb' 'ndr' 'nec' 'neo4j' 'neovim' 'nestjs' 'netapp' 'netflix' 'netlify' 'newjapanpro-wrestling' 'newrelic' 'newyorktimes' 'next-dot-js' 'nextcloud' 'nextdoor' 'nfc' 'nginx' 'ngrok' 'niconico' 'nim' 'nintendo' 'nintendo3ds' 'nintendogamecube' 'nintendonetwork' 'nintendoswitch' 'nissan' 'nixos' 'node-dot-js' 'node-red' 'nodemon' 'nokia' 'norwegian' 'notepadplusplus' 'notion' 'notist' 'nounproject' 'npm' 'nrwl' 'nubank' 'nucleo' 'nuget' 'nuke' 'numba' 'numpy' 'nutanix' 'nuxt-dot-js' 'nvidia' 'nx' 'observable' 'obsstudio' 'ocaml' 'octave' 'octopusdeploy' 'oculus' 'odnoklassniki' 'odysee' 'okcupid' 'okta' 'oneplus' 'onlyfans' 'onnx' 'onstar' 'opel' 'openaccess' 'openai' 'openaigym' 'openapiinitiative' 'openbadges' 'openbsd' 'openbugbounty' 'opencollective' 'opencontainersinitiative' 'opencv' 'openfaas' 'opengl' 'openid' 'openlayers' 'opennebula' 'opensourceinitiative' 'openssl' 'openstack' 'openstreetmap' 'opensuse' 'openvpn' 'openwrt' 'opera' 'opnsense' 'opsgenie' 'opslevel' 'oracle' 'orcid' 'org' 'origin' 'osano' 'oshkosh' 'osmc' 'osu' 'overcast' 'overleaf' 'ovh' 'owasp' 'oxygen' 'oyo' 'p5-dot-js' 'packagist' 'pagekit' 'pagerduty' 'pagespeedinsights' 'pagseguro' 'palantir' 'paloaltosoftware' 'pandas' 'pandora' 'pantheon' 'paritysubstrate' 'parse-dot-ly' 'passport' 'pastebin' 'patreon' 'payoneer' 'paypal' 'paytm' 'pcgamingwiki' 'peertube' 'pegasusairlines' 'pelican' 'peloton' 'pepsi' 'perforce' 'periscope' 'perl' 'peugeot' 'pexels' 'pfsense' 'phabricator' 'philipshue' 'phonepe' 'photobucket' 'photocrowd' 'photopea' 'php' 'phpstorm' 'pi-hole' 'picarto-dot-tv' 'picnic' 'picpay' 'pimcore' 'pinboard' 'pingdom' 'pingup' 'pinterest' 'pioneerdj' 'pivotaltracker' 'piwigo' 'pixabay' 'pixiv' 'pjsip' 'planet' 'plangrid' 'platzi' 'playcanvas' 'player-dot-me' 'playerfm' 'playstation' 'playstation2' 'playstation3' 'playstation4' 'playstation5' 'playstationvita' 'pleroma' 'plesk' 'plex' 'plotly' 'pluralsight' 'plurk' 'pluscodes' 'pm2' 'pnpm' 'pocket' 'pocketcasts' 'podcastaddict' 'podman' 'pointy' 'pokemon' 'poly' 'polymerproject' 'pop_os' 'porsche' 'postcss' 'postgresql' 'postman' 'postmates' 'powerbi' 'powers' 'powershell' 'pr-dot-co' 'pre-commit' 'premierleague' 'prestashop' 'presto' 'prettier' 'prezi' 'prime' 'primevideo' 'prisma' 'prismic' 'privateinternetaccess' 'probot' 'processingfoundation' 'processwire' 'producthunt' 'progate' 'progress' 'prometheus' 'prosieben' 'proto-dot-io' 'protocols-dot-io' 'protondb' 'protonmail' 'protonvpn' 'protools' 'proxmox' 'publons' 'pubmed' 'pug' 'puppet' 'puppeteer' 'purescript' 'purgecss' 'purism' 'pusher' 'pycharm' 'pypi' 'pypy' 'python' 'pytorch' 'pytorchlightning' 'pyup' 'qantas' 'qatarairways' 'qemu' 'qgis' 'qi' 'qiita' 'qiskit' 'qiwi' 'qt' 'qualcomm' 'qualtrics' 'quantcast' 'quantconnect' 'quantopian' 'quarkus' 'quasar' 'qubesos' 'quest' 'quickbooks' 'quicktime' 'quip' 'quora' 'qwiklabs' 'qzone' 'r' 'r3' 'rabbitmq' 'racket' 'radar' 'radiopublic' 'rainmeter' 'rakuten' 'ram' 'rancher' 'raspberrypi' 'razer' 'react' 'reactivex' 'reactos' 'reactrouter' 'readthedocs' 'realm' 'reason' 'reasonstudios' 'redbubble' 'reddit' 'redhat' 'redhatopenshift' 'redis' 'redux-saga' 'redux' 'redwoodjs' 'relianceindustrieslimited' 'renault' 'renovatebot' 'renpy' 'renren' 'repl-dot-it' 'researchgate' 'resurrectionremixos' 'retroarch' 'retropie' 'reveal-dot-js' 'reverbnation' 'revolut' 'revue' 'rewe' 'rezgo' 'rhinoceros' 'rider' 'ring' 'riotgames' 'ripple' 'riseup' 'roamresearch' 'roblox' 'robotframework' 'rocket-dot-chat' 'roku' 'rolls-royce' 'rollup-dot-js' 'roots' 'rootsbedrock' 'rootssage' 'ros' 'rottentomatoes' 'roundcube' 'rss' 'rstudio' 'rte' 'rtl' 'rtlzwei' 'ruby' 'rubygems' 'rubyonrails' 'runkeeper' 'runkit' 'rust' 'rxdb' 'ryanair' 's7airlines' 'safari' 'sahibinden' 'salesforce' 'saltstack' 'samsung' 'samsungpay' 'sanfranciscomunicipalrailway' 'saopaulometro' 'sap' 'sass' 'sat-dot-1' 'saucelabs' 'scala' 'scaleway' 'scania' 'scikit-learn' 'scipy' 'scopus' 'scratch' 'screencastify' 'scribd' 'scrimba' 'scrollreveal' 'scrumalliance' 'scrutinizerci' 'seagate' 'seat' 'sefaria' 'sega' 'selenium' 'sellfy' 'semantic-release' 'semanticuireact' 'semanticweb' 'semaphoreci' 'semver' 'sencha' 'sennheiser' 'sensu' 'sentry' 'sepa' 'serverfault' 'serverless' 'sfml' 'shanghaimetro' 'sharp' 'shazam' 'shell' 'shelly' 'shenzhenmetro' 'shields-dot-io' 'shikimori' 'shopify' 'shopware' 'shotcut' 'showpad' 'showtime' 'shutterstock' 'siemens' 'signal' 'simkl' 'simpleanalytics' 'simpleicons' 'sinaweibo' 'singlestore' 'sitepoint' 'sketch' 'sketchfab' 'sketchup' 'skillshare' 'skoda' 'sky' 'skyliner' 'skype' 'skypeforbusiness' 'slack' 'slackware' 'slashdot' 'slickpic' 'slides' 'slideshare' 'smart' 'smartthings' 'smashingmagazine' 'smrt' 'smugmug' 'snapchat' 'snapcraft' 'snowflake' 'snyk' 'society6' 'socket-dot-io' 'sogou' 'solidity' 'sololearn' 'solus' 'sonarcloud' 'sonarlint' 'sonarqube' 'sonarsource' 'songkick' 'songoda' 'sonicwall' 'sonos' 'soundcloud' 'sourceengine' 'sourceforge' 'sourcegraph' 'southwestairlines' 'spacemacs' 'spacex' 'sparkar' 'sparkasse' 'sparkfun' 'sparkpost' 'spdx' 'speakerdeck' 'spectrum' 'speedtest' 'spinnaker' 'spinrilla' 'splunk' 'spotify' 'spotlight' 'spreaker' 'spring' 'springboot' 'sprint' 'spyderide' 'sqlite' 'square' 'squareenix' 'squarespace' 'ssrn' 'stackbit' 'stackexchange' 'stackoverflow' 'stackpath' 'stackshare' 'stadia' 'staffbase' 'starlingbank' 'starship' 'startrek' 'starz' 'statamic' 'staticman' 'statuspage' 'statuspal' 'steam' 'steamdb' 'steamworks' 'steem' 'steemit' 'steinberg' 'stellar' 'stencyl' 'stimulus' 'stitcher' 'stmicroelectronics' 'storify' 'storyblok' 'storybook' 'strapi' 'strava' 'streamlit' 'stripe' 'strongswan' 'stubhub' 'styled-components' 'stylelint' 'styleshare' 'stylus' 'subaru' 'sublimetext' 'substack' 'subversion' 'suckless' 'sumologic' 'supabase' 'superuser' 'surveymonkey' 'suse' 'suzuki' 'svelte' 'svg' 'svgo' 'swagger' 'swarm' 'swift' 'swiggy' 'swiper' 'symantec' 'symfony' 'symphony' 'sympy' 'synology' 't-mobile' 'tableau' 'tado' 'tails' 'tailwindcss' 'talend' 'tampermonkey' 'taobao' 'tapas' 'tasmota' 'tata' 'taxbuzz' 'teamcity' 'teamspeak' 'teamviewer' 'ted' 'teespring' 'tekton' 'tele5' 'telegram' 'telegraph' 'tencentqq' 'tencentweibo' 'tensorflow' 'teradata' 'teratail' 'terraform' 'tesla' 'testin' 'testinglibrary' 'textpattern' 'theconversation' 'theirishtimes' 'themighty' 'themodelsresource' 'themoviedatabase' 'theregister' 'thesoundsresource' 'thespritersresource' 'thewashingtonpost' 'thingiverse' 'thinkpad' 'three-dot-js' 'threema' 'thumbtack' 'thunderbird' 'thymeleaf' 'ticketmaster' 'tidal' 'tide' 'tiktok' 'tile' 'timescale' 'tinder' 'tinyletter' 'tmux' 'todoist' 'toggl' 'tokyometro' 'tomorrowland' 'topcoder' 'toptal' 'torbrowser' 'torproject' 'toshiba' 'toyota' 'tp-link' 'tqdm' 'trainerroad' 'trakt' 'transferwise' 'transportforireland' 'transportforlondon' 'travisci' 'treehouse' 'trello' 'trendmicro' 'treyarch' 'triller' 'trino' 'trip-dot-com' 'tripadvisor' 'trove' 'truenas' 'trulia' 'trustedshops' 'trustpilot' 'tryhackme' 'tryitonline' 'ts-node' 'tui' 'tumblr' 'tunein' 'turbosquid' 'turkishairlines' 'tutanota' 'tvtime' 'twilio' 'twitch' 'twitter' 'twoo' 'typescript' 'typo3' 'uber' 'ubereats' 'ubiquiti' 'ubisoft' 'ublockorigin' 'ubuntu' 'udacity' 'udemy' 'ufc' 'uikit' 'ulule' 'umbraco' 'unacademy' 'undertale' 'unicode' 'unilever' 'unitedairlines' 'unity' 'unraid' 'unrealengine' 'unsplash' 'untangle' 'untappd' 'upcloud' 'uplabs' 'uploaded' 'ups' 'upwork' 'usps' 'v' 'v8' 'vaadin' 'vagrant' 'valve' 'vapor' 'vault' 'vauxhall' 'vbulletin' 'vectorlogozone' 'vectorworks' 'veeam' 'veepee' 'venmo' 'vercel' 'verdaccio' 'veritas' 'verizon' 'vfairs' 'viadeo' 'viber' 'vim' 'vimeo' 'vimeolivestream' 'vine' 'virb' 'virtualbox' 'virustotal' 'visa' 'visualstudio' 'visualstudiocode' 'vite' 'vivaldi' 'vivino' 'vk' 'vlcmediaplayer' 'vmware' 'vodafone' 'volkswagen' 'volvo' 'vonage' 'vox' 'vsco' 'vue-dot-js' 'vuetify' 'vulkan' 'vultr' 'w3c' 'wagtail' 'wakatime' 'walkman' 'wappalyzer' 'warnerbros-dot' 'wattpad' 'waze' 'wearos' 'weasyl' 'webassembly' 'webauthn' 'webcomponents-dot-org' 'webdriverio' 'webflow' 'webgl' 'webhint' 'weblate' 'webmin' 'webmoney' 'webpack' 'webrtc' 'webstorm' 'wechat' 'weights-and-biases' 'wemo' 'wetransfer' 'whatsapp' 'wheniwork' 'whitesource' 'wii' 'wiiu' 'wikidata' 'wikimediacommons' 'wikipedia' 'wikiquote' 'wikivoyage' 'windows' 'windows95' 'windowsterminal' 'windowsxp' 'winmate' 'wipro' 'wire' 'wireguard' 'wireshark' 'wish' 'wistia' 'wix' 'wizzair' 'wolfram' 'wolframlanguage' 'wolframmathematica' 'woo' 'woocommerce' 'wordpress' 'workplace' 'worldhealthorganization' 'wpengine' 'wprocket' 'write-dot-as' 'wwe' 'wwise' 'x-dot-org' 'x-pack' 'xamarin' 'xaml' 'xampp' 'xbox' 'xcode' 'xdadevelopers' 'xero' 'xfce' 'xiaomi' 'xilinx' 'xing' 'xmpp' 'xrp' 'xsplit' 'xstate' 'yahoo' 'yale' 'yamahacorporation' 'yamahamotorcorporation' 'yammer' 'yandex' 'yarn' 'ycombinator' 'yelp' 'yoast' 'yourtravel-dot-tv' 'youtube' 'youtubegaming' 'youtubemusic' 'youtubestudio' 'youtubetv' 'z-wave' 'zalando' 'zapier' 'zdf' 'zelle' 'zend' 'zendesk' 'zendframework' 'zenn' 'zerodha' 'zeromq' 'zerply' 'zhihu' 'zigbee' 'zillow' 'zingat' 'zoho' 'zoiper' 'zomato' 'zoom' 'zorin' 'zotero' 'zulip' ) } function Set-FolderConfiguration { [CmdletBinding()] param( [System.Collections.IDictionary]$Folders, [Array] $FoldersConfiguration ) foreach ($Folder in $FoldersConfiguration) { if (-not $Folder.Name -and $Folder.UrlName) { $Folder.Name = $Folder.UrlName } elseif (-not $Folder.UrlName -and $Folder.Name) { $Folder.Url = $Folder.Name } $Folders[$Folder.Name] = $Folder } } function New-DashboardFolder { [alias('New-TheDashboardFolder')] [CmdletBinding()] param( [Parameter(Position = 0)][scriptblock] $Replacements, [Parameter(Mandatory)][string] $Name, [Parameter(Mandatory)][string] $Path, [Parameter(Mandatory)][string] $UrlName, [string] $CopyFrom, [string] $MoveFrom, [switch] $DisableGlobalReplacement, # ICON BRANDS [ArgumentCompleter( { param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) ($Global:HTMLIcons.FontAwesomeBrands.Keys) } )] [ValidateScript( { $_ -in (($Global:HTMLIcons.FontAwesomeBrands.Keys)) } )] [parameter(ParameterSetName = "FontAwesomeBrands")][string] $IconBrands, # ICON REGULAR [ArgumentCompleter( { param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) ($Global:HTMLIcons.FontAwesomeRegular.Keys) } )] [ValidateScript( { $_ -in (($Global:HTMLIcons.FontAwesomeRegular.Keys)) } )] [parameter(ParameterSetName = "FontAwesomeRegular")][string] $IconRegular, # ICON SOLID [ArgumentCompleter( { param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) ($Global:HTMLIcons.FontAwesomeSolid.Keys) } )] [ValidateScript( { $_ -in (($Global:HTMLIcons.FontAwesomeSolid.Keys)) } )] [parameter(ParameterSetName = "FontAwesomeSolid")][string] $IconSolid ) if ($IconBrands) { $IconType = 'IconBrands' $Icon = $IconBrands } elseif ($IconRegular) { $IconType = 'IconRegular' $Icon = $IconRegular } elseif ($IconSolid) { $IconType = 'IconSolid' $Icon = $IconSolid } else { $IconType = 'IconSolid' $Icon = 'folder' } if ($Replacements) { $ReplacementConfiguration = [System.Collections.Generic.List[System.Collections.IDictionary]]::new() $OutputElements = & $Replacements foreach ($E in $OutputElements) { # if ($E.Type -eq 'Gage') { # $GageConfiguration.Add($E.Settings) # } elseif ($E.Type -eq 'Folder') { # $FoldersConfiguration.Add($E.Settings) if ($E.Type -eq 'Replacement') { $ReplacementConfiguration.Add($E.Settings) } } $ReplacementsConfiguration = Convert-MultipleReplacements -ReplacementConfiguration $ReplacementConfiguration } else { $ReplacementsConfiguration = $null } $Folder = [ordered] @{ Type = 'Folder' Settings = [ordered] @{ Name = $Name IconType = $IconType Icon = $Icon Path = $Path Url = $UrlName CopyFrom = $CopyFrom MoveFrom = $MoveFrom ReplacementsGlobal = -not $DisableGlobalReplacement.IsPresent Replacements = $ReplacementsConfiguration } } Remove-EmptyValue -Hashtable $Folder $Folder } function New-DashboardGage { [alias('New-TheDashboardGage')] [cmdletBinding()] param( [Parameter(Mandatory)][string] $Label, [Parameter()][int] $MinValue, [Parameter(Mandatory)][int] $MaxValue, [Parameter(Mandatory)][int] $Value, [Parameter(Mandatory)][DateTime] $Date ) [ordered] @{ Type = 'Gage' Settings = [ordered] @{ Label = $Label Value = $Value Date = $Date MinValue = $MinValue MaxValue = $MaxValue } } } function New-DashboardReplacement { [alias('New-TheDashboardReplacement')] [CmdletBinding()] param( [string] $SplitOn, [Array] $BeforeSplit, [Array] $AfterSplit, [switch] $AddSpaceToName ) $BeforeEntry = [ordered] @{} foreach ($Before in $BeforeSplit) { foreach ($Key in $Before.Keys) { $BeforeEntry[$Key] = $Before[$Key] } } $AfterEntry = [ordered] @{} foreach ($After in $AfterSplit) { foreach ($Key in $After.Keys) { $AfterEntry[$Key] = $After[$Key] } } $Replacements = [ordered] @{ Type = 'Replacement' Settings = @{ SplitOn = if ($PSBoundParameters.ContainsKey('SplitOn')) { $SplitOn } else { $null } BeforeSplit = if ($PSBoundParameters.ContainsKey('BeforeSplit')) { $BeforeEntry } else { $null } AfterSplit = if ($PSBoundParameters.ContainsKey('AfterSplit')) { $AfterEntry } else { $null } AddSpaceToName = if ($PSBoundParameters.ContainsKey('AddSpaceToName')) { $AddSpaceToName } else { $null } } } $Replacements } function Start-TheDashboard { <# .SYNOPSIS Generates TheDashboard from multiple provided reports in form of HTML files. .DESCRIPTION Generates TheDashboard from multiple provided reports in form of HTML files. It also generates statistics and charts based on the data provided by additional data. .PARAMETER Elements ScriptBlock that accepts New-Dashboard* functions, allowing for configuration of TheDashboard. .PARAMETER HTMLPath Path to HTML files that will be generated. .PARAMETER StatisticsPath Path to XML file that will save some of the data that is used to generate charts .PARAMETER Logo Path to logo that will be used in the header. .PARAMETER Folders Folders that will be used to generate TheDashboard. Can co-exist with Elements parameter, and configuration using both will be merged. .PARAMETER Replacements Replacements that will be used to replace names within TheDashboard. .PARAMETER ShowHTML Show TheDashboard in browser after generating it. .PARAMETER Online Tells Dashboard to use CSS/JS from CDN instead of local files. .PARAMETER Force By default dashboard generates HTML files once, and then refreshes only main file from each category leaving the rest as is if it exists. This saves a lot of time when generating historical reports. If you want to force regeneration of all files, use this parameter. .EXAMPLE An example .NOTES General notes #> [cmdletBinding()] param( [Parameter(Position = 0)][ScriptBlock] $Elements, [Parameter(Position = 1, Mandatory)][alias('FilePath')][string] $HTMLPath, [string] $StatisticsPath, [string] $Logo, [System.Collections.IDictionary] $Folders, [System.Collections.IDictionary] $Replacements, [switch] $ShowHTML, [switch] $Online, [switch] $Force ) $Script:Reporting = [ordered] @{} $Script:Reporting['Version'] = Get-GitHubVersion -Cmdlet 'Start-TheDashboard' -RepositoryOwner 'evotecit' -RepositoryName 'TheDashboard' Write-Color '[i]', "[TheDashboard] ", 'Version', ' [Informative] ', $Script:Reporting['Version'] -Color Yellow, DarkGray, Yellow, DarkGray, Magenta $TopStats = [ordered] @{} if (-not $Folders) { $Folders = [ordered] @{} } $GageConfiguration = [System.Collections.Generic.List[System.Collections.IDictionary]]::new() $FoldersConfiguration = [System.Collections.Generic.List[System.Collections.IDictionary]]::new() $ReplacementConfiguration = [System.Collections.Generic.List[System.Collections.IDictionary]]::new() if ($Elements) { $TimeLogElements = Start-TimeLog Write-Color -Text '[i]', "[TheDashboard] ", 'Executing nested elements (data gathering/conversions)', ' [Informative] ' -Color Yellow, DarkGray, Yellow, DarkGray, Magenta $OutputElements = & $Elements foreach ($E in $OutputElements) { if ($E.Type -eq 'Gage') { $GageConfiguration.Add($E.Settings) } elseif ($E.Type -eq 'Folder') { $FoldersConfiguration.Add($E.Settings) } elseif ($E.Type -eq 'Replacement') { $ReplacementConfiguration.Add($E.Settings) } } $TimeLogElements = Stop-TimeLog -Time $TimeLogElements -Option OneLiner Write-Color -Text '[i]', "[TheDashboard] ", 'Executing nested elements (data gathering/conversions)', ' [Time to execute: ', $TimeLogElements, ']' -Color Yellow, DarkGray, Yellow, DarkGray, Magenta } if ($StatisticsPath -and (Test-Path -LiteralPath $StatisticsPath)) { Write-Color -Text '[i]', "[TheDashboard] ", 'Importing Statistics', ' [Informative] ', $StatisticsPath -Color Yellow, DarkGray, Yellow, DarkGray, Magenta $TopStats = Import-Clixml -LiteralPath $StatisticsPath } foreach ($E in $GageConfiguration) { $TopStats[$E.Date] = [ordered] @{} $TopStats[$E.Date].Date = $E.Date } # convert replacements into a single entry # this is to make sure user can use different ways of replacing things $Replacements = Convert-MultipleReplacements -Replacements $Replacements -ReplacementConfiguration $ReplacementConfiguration # build folders configuration Set-FolderConfiguration -Folders $Folders -FoldersConfiguration $FoldersConfiguration # copy or move HTML files to the right place, as user requested Copy-HTMLFiles -HTMLPath $HTMLPath -Folders $Folders # create menu data information based on files $Files = Convert-FilesToMenuData -Folders $Folders -Replacements $Replacements # Prepare menu based on files $MenuBuilder = Convert-FilesToMenu -Files $Files -Folders $Folders New-HTMLReport -OutputElements $GageConfiguration -Logo $Logo -MenuBuilder $MenuBuilder -Configuration $Configuration -TopStats $TopStats -Files $Files -ShowHTML:$ShowHTML.IsPresent -HTMLPath $HTMLPath -Online:$Online.IsPresent -Force:$Force.IsPresent # Export statistics to file to create charts later on if ($StatisticsPath) { try { $TopStats | Export-Clixml -Depth 3 -LiteralPath $StatisticsPath -ErrorAction Stop } catch { Write-Color -Text '[e]', "[TheDashboard] ", 'Failed to export statistics', ' [Error] ', $_.Exception.Message -Color Yellow, DarkGray, Yellow, DarkGray, Red } } } # Export functions and aliases as required Export-ModuleMember -Function @('New-DashboardFolder', 'New-DashboardGage', 'New-DashboardReplacement', 'Start-TheDashboard') -Alias @('New-TheDashboardFolder', 'New-TheDashboardGage', 'New-TheDashboardReplacement') # SIG # Begin signature block # MIInPgYJKoZIhvcNAQcCoIInLzCCJysCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCHroQo8Dhn5RAU # 9LphteTAiRAyg7GOgNTqDNI6RDzOSKCCITcwggO3MIICn6ADAgECAhAM5+DlF9hG # /o/lYPwb8DA5MA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBa # Fw0zMTExMTAwMDAwMDBaMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lD # ZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC # AQoCggEBAK0OFc7kQ4BcsYfzt2D5cRKlrtwmlIiq9M71IDkoWGAM+IDaqRWVMmE8 # tbEohIqK3J8KDIMXeo+QrIrneVNcMYQq9g+YMjZ2zN7dPKii72r7IfJSYd+fINcf # 4rHZ/hhk0hJbX/lYGDW8R82hNvlrf9SwOD7BG8OMM9nYLxj+KA+zp4PWw25EwGE1 # lhb+WZyLdm3X8aJLDSv/C3LanmDQjpA1xnhVhyChz+VtCshJfDGYM2wi6YfQMlqi # uhOCEe05F52ZOnKh5vqk2dUXMXWuhX0irj8BRob2KHnIsdrkVxfEfhwOsLSSplaz # vbKX7aqn8LfFqD+VFtD/oZbrCF8Yd08CAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGG # MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEXroq/0ksuCMS1Ri6enIZ3zbcgP # MB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBBQUA # A4IBAQCiDrzf4u3w43JzemSUv/dyZtgy5EJ1Yq6H6/LV2d5Ws5/MzhQouQ2XYFwS # TFjk0z2DSUVYlzVpGqhH6lbGeasS2GeBhN9/CTyU5rgmLCC9PbMoifdf/yLil4Qf # 6WXvh+DfwWdJs13rsgkq6ybteL59PyvztyY1bV+JAbZJW58BBZurPSXBzLZ/wvFv # hsb6ZGjrgS2U60K3+owe3WLxvlBnt2y98/Efaww2BxZ/N3ypW2168RJGYIPXJwS+ # S86XvsNnKmgR34DnDDNmvxMNFG7zfx9jEB76jRslbWyPpbdhAbHSoyahEHGdreLD # +cOZUbcrBwjOLuZQsqf6CkUvovDyMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1 # b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtE # aWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgx # MDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT # SEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEF # AAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLX # cep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSR # I5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXi # TWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5 # Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8 # vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYD # VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYB # BQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k # aWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4 # oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJv # b3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCow # KAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZI # AYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaA # FEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPz # ItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRu # pY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKN # JK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmif # z0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN # 3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKy # ZqHnGKSaZFHvMIIFPTCCBCWgAwIBAgIQBNXcH0jqydhSALrNmpsqpzANBgkqhkiG # 9w0BAQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw # FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEy # IEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMDYyNjAwMDAwMFoXDTIz # MDcwNzEyMDAwMFowejELMAkGA1UEBhMCUEwxEjAQBgNVBAgMCcWabMSFc2tpZTER # MA8GA1UEBxMIS2F0b3dpY2UxITAfBgNVBAoMGFByemVteXPFgmF3IEvFgnlzIEVW # T1RFQzEhMB8GA1UEAwwYUHJ6ZW15c8WCYXcgS8WCeXMgRVZPVEVDMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7KB3iyBrhkLUbbFe9qxhKKPBYqDBqln # r3AtpZplkiVjpi9dMZCchSeT5ODsShPuZCIxJp5I86uf8ibo3vi2S9F9AlfFjVye # 3dTz/9TmCuGH8JQt13ozf9niHecwKrstDVhVprgxi5v0XxY51c7zgMA2g1Ub+3ti # i0vi/OpmKXdL2keNqJ2neQ5cYly/GsI8CREUEq9SZijbdA8VrRF3SoDdsWGf3tZZ # zO6nWn3TLYKQ5/bw5U445u/V80QSoykszHRivTj+H4s8ABiforhi0i76beA6Ea41 # zcH4zJuAp48B4UhjgRDNuq8IzLWK4dlvqrqCBHKqsnrF6BmBrv+BXQIDAQABo4IB # xTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYE # FBixNSfoHFAgJk4JkDQLFLRNlJRmMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRwOi8vY3JsMy5kaWdpY2Vy # dC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOgMYYvaHR0cDovL2NybDQu # ZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3 # BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu # Y29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgwdjAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUFBzAChkJodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNzdXJlZElEQ29kZVNpZ25p # bmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAmr1sz4ls # LARi4wG1eg0B8fVJFowtect7SnJUrp6XRnUG0/GI1wXiLIeow1UPiI6uDMsRXPHU # F/+xjJw8SfIbwava2eXu7UoZKNh6dfgshcJmo0QNAJ5PIyy02/3fXjbUREHINrTC # vPVbPmV6kx4Kpd7KJrCo7ED18H/XTqWJHXa8va3MYLrbJetXpaEPpb6zk+l8Rj9y # G4jBVRhenUBUUj3CLaWDSBpOA/+sx8/XB9W9opYfYGb+1TmbCkhUg7TB3gD6o6ES # Jre+fcnZnPVAPESmstwsT17caZ0bn7zETKlNHbc1q+Em9kyBjaQRcEQoQQNpezQu # g9ufqExx6lHYDjCCBY0wggR1oAMCAQICEA6bGI750C3n79tQ4ghAGFowDQYJKoZI # hvcNAQEMBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNz # dXJlZCBJRCBSb290IENBMB4XDTIyMDgwMTAwMDAwMFoXDTMxMTEwOTIzNTk1OVow # YjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290 # IEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv+aQc2jeu+RdSjww # IjBpM+zCpyUuySE98orYWcLhKac9WKt2ms2uexuEDcQwH/MbpDgW61bGl20dq7J5 # 8soR0uRf1gU8Ug9SH8aeFaV+vp+pVxZZVXKvaJNwwrK6dZlqczKU0RBEEC7fgvMH # hOZ0O21x4i0MG+4g1ckgHWMpLc7sXk7Ik/ghYZs06wXGXuxbGrzryc/NrDRAX7F6 # Zu53yEioZldXn1RYjgwrt0+nMNlW7sp7XeOtyU9e5TXnMcvak17cjo+A2raRmECQ # ecN4x7axxLVqGDgDEI3Y1DekLgV9iPWCPhCRcKtVgkEy19sEcypukQF8IUzUvK4b # A3VdeGbZOjFEmjNAvwjXWkmkwuapoGfdpCe8oU85tRFYF/ckXEaPZPfBaYh2mHY9 # WV1CdoeJl2l6SPDgohIbZpp0yt5LHucOY67m1O+SkjqePdwA5EUlibaaRBkrfsCU # tNJhbesz2cXfSwQAzH0clcOP9yGyshG3u3/y1YxwLEFgqrFjGESVGnZifvaAsPvo # ZKYz0YkH4b235kOkGLimdwHhD5QMIR2yVCkliWzlDlJRR3S+Jqy2QXXeeqxfjT/J # vNNBERJb5RBQ6zHFynIWIgnffEx1P2PsIV/EIFFrb7GrhotPwtZFX50g/KEexcCP # orF+CiaZ9eRpL5gdLfXZqbId5RsCAwEAAaOCATowggE2MA8GA1UdEwEB/wQFMAMB # Af8wHQYDVR0OBBYEFOzX44LScV1kTN8uZz/nupiuHA9PMB8GA1UdIwQYMBaAFEXr # oq/0ksuCMS1Ri6enIZ3zbcgPMA4GA1UdDwEB/wQEAwIBhjB5BggrBgEFBQcBAQRt # MGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEF # BQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl # ZElEUm9vdENBLmNydDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMBEGA1UdIAQKMAgw # BgYEVR0gADANBgkqhkiG9w0BAQwFAAOCAQEAcKC/Q1xV5zhfoKN0Gz22Ftf3v1cH # vZqsoYcs7IVeqRq7IviHGmlUIu2kiHdtvRoU9BNKei8ttzjv9P+Aufih9/Jy3iS8 # UgPITtAq3votVs/59PesMHqai7Je1M/RQ0SbQyHrlnKhSLSZy51PpwYDE3cnRNTn # f+hZqPC/Lwum6fI0POz3A8eHqNJMQBk1RmppVLC4oVaO7KTVPeix3P0c2PR3WlxU # jG/voVA9/HYJaISfb8rbII01YBwCA8sgsKxYoA5AY8WYIsGyWfVVa88nq2x2zm8j # LfR+cWojayL/ErhULSd+2DrZ8LaHlv1b0VysGMNNn3O3AamfV6peKOK5lDCCBq4w # ggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkG # A1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRp # Z2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4X # DTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAV # BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVk # IEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5M # om2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE # 2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWN # lCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFo # bjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhN # ef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3Vu # JyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtz # Q87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4O # uGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5 # sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm # 4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIz # tM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6 # FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qY # rhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYB # BQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20w # QQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy # dFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZ # MBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmO # wJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H # 6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/ # R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzv # qLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/ae # sXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdm # kfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3 # EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh # 3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA # 3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8 # BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsf # gPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwggbAMIIEqKADAgECAhAMTWly # S5T6PCpKPSkHgD1aMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjIwOTIxMDAwMDAw # WhcNMzMxMTIxMjM1OTU5WjBGMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNl # cnQxJDAiBgNVBAMTG0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIyIC0gMjCCAiIwDQYJ # KoZIhvcNAQEBBQADggIPADCCAgoCggIBAM/spSY6xqnya7uNwQ2a26HoFIV0Mxom # rNAcVR4eNm28klUMYfSdCXc9FZYIL2tkpP0GgxbXkZI4HDEClvtysZc6Va8z7GGK # 6aYo25BjXL2JU+A6LYyHQq4mpOS7eHi5ehbhVsbAumRTuyoW51BIu4hpDIjG8b7g # L307scpTjUCDHufLckkoHkyAHoVW54Xt8mG8qjoHffarbuVm3eJc9S/tjdRNlYRo # 44DLannR0hCRRinrPibytIzNTLlmyLuqUDgN5YyUXRlav/V7QG5vFqianJVHhoV5 # PgxeZowaCiS+nKrSnLb3T254xCg/oxwPUAY3ugjZNaa1Htp4WB056PhMkRCWfk3h # 3cKtpX74LRsf7CtGGKMZ9jn39cFPcS6JAxGiS7uYv/pP5Hs27wZE5FX/NurlfDHn # 88JSxOYWe1p+pSVz28BqmSEtY+VZ9U0vkB8nt9KrFOU4ZodRCGv7U0M50GT6Vs/g # 9ArmFG1keLuY/ZTDcyHzL8IuINeBrNPxB9ThvdldS24xlCmL5kGkZZTAWOXlLimQ # prdhZPrZIGwYUWC6poEPCSVT8b876asHDmoHOWIZydaFfxPZjXnPYsXs4Xu5zGcT # B5rBeO3GiMiwbjJ5xwtZg43G7vUsfHuOy2SJ8bHEuOdTXl9V0n0ZKVkDTvpd6kVz # HIR+187i1Dp3AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/ # BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEE # AjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8w # HQYDVR0OBBYEFGKK3tBh/I8xFO2XC809KpQU31KcMFoGA1UdHwRTMFEwT6BNoEuG # SWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQw # OTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKG # TGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJT # QTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIB # AFWqKhrzRvN4Vzcw/HXjT9aFI/H8+ZU5myXm93KKmMN31GT8Ffs2wklRLHiIY1UJ # RjkA/GnUypsp+6M/wMkAmxMdsJiJ3HjyzXyFzVOdr2LiYWajFCpFh0qYQitQ/Bu1 # nggwCfrkLdcJiXn5CeaIzn0buGqim8FTYAnoo7id160fHLjsmEHw9g6A++T/350Q # p+sAul9Kjxo6UrTqvwlJFTU2WZoPVNKyG39+XgmtdlSKdG3K0gVnK3br/5iyJpU4 # GYhEFOUKWaJr5yI+RCHSPxzAm+18SLLYkgyRTzxmlK9dAlPrnuKe5NMfhgFknADC # 6Vp0dQ094XmIvxwBl8kZI4DXNlpflhaxYwzGRkA7zl011Fk+Q5oYrsPJy8P7mxNf # arXH4PMFw1nfJ2Ir3kHJU7n/NBBn9iYymHv+XEKUgZSCnawKi8ZLFUrTmJBFYDOA # 4CPe+AOk9kVH5c64A0JH6EE2cXet/aLol3ROLtoeHYxayB6a1cLwxiKoT5u92Bya # UcQvmvZfpyeXupYuhVfAYOd4Vn9q78KVmksRAsiCnMkaBXy6cbVOepls9Oie1FqY # yJ+/jbsYXEP10Cro4mLueATbvdH7WwqocH7wl4R44wgDXUcsY6glOJcB0j862uXl # 9uab3H4szP8XTE0AotjWAQ64i+7m4HJViSwnGWH2dwGMMYIFXTCCBVkCAQEwgYYw # cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk # IElEIENvZGUgU2lnbmluZyBDQQIQBNXcH0jqydhSALrNmpsqpzANBglghkgBZQME # AgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEM # BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqG # SIb3DQEJBDEiBCAW3URt6lo3y1UHQfIth3fQY2tQcvpnCMfojHvvRm15WjANBgkq # hkiG9w0BAQEFAASCAQBbozaggoKUrhA+iJgFCUTLwJIcc2FOwb7uFoCgYm3VrOP9 # MvRFUDUNi7cs6A8jtL2lBWcz+fFrwAHd7bPlD+Y/3/XVQh7TX9YI9uv4BiO6kc+z # 5KbRMAKAMpkp2ZwSH+jDhWCCt9zVP3002KjcyHGjYzoSYon6yuXrAxd1qrPMcF5P # 87wXYdIsMHcPbFeGjrvs8uCWNlLoZMVTsthLBuMR24Wrj/s3GvKgxdoaeY1Xi36y # QdrhVEwUOwp7Sp54RDCVh2wv5K85TefyKgoYwtmLwaLneFq/bvCGDK25P3VxeGAS # HL/A8sLs3s/pYYEua7bRxnFg3VoaoEHOIiLmco18oYIDIDCCAxwGCSqGSIb3DQEJ # BjGCAw0wggMJAgEBMHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0 # LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hB # MjU2IFRpbWVTdGFtcGluZyBDQQIQDE1pckuU+jwqSj0pB4A9WjANBglghkgBZQME # AgEFAKBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X # DTIzMDMyNzA5MDYwOVowLwYJKoZIhvcNAQkEMSIEILJn0lVNs1jbpADshzocp6pf # rgEK9T4clJP3iGir86EtMA0GCSqGSIb3DQEBAQUABIICACmM3sf9oTrOEws6GuFY # pwZr7E3bMem/Do3aOPQ6SZ98hY/nSzuhXvXxpEBJYPy3o2PiTdsyiREWg4Pj+XAG # P/w1t9FK/Jc+OpfpW4Yc/W/ETRSOk2UV4+ButSZdDiZwdq3KktJJKuijbZt3oIU1 # NAv76iNsxYTbPebCs7O9py2f6ZibmJRsyXgjb7qPtIgM5D+9amten8sGdnf8lu60 # DqdQj7sNP7uqxgW5Ml9/FJjiKLUrN0xbnqUdPYYtNZkPt4bTFfUUUQ5XbGCobJ1k # 3Ww/Imf1KIA3ic5UE07pKEhyH60svMKF0ApuFY7aDUIqv4LFMdzynZG2cysI9TcE # z9QwF2S1OxVdYTVynDJsf7jo4Vn2N6duAuWFRaoxqT+WFSnpQeX2PwgK/dmHhi2X # Rm2yyR6Rl3j1g28waZsi6vFsdCbxWVkMFRBYezKv9GXECk6DnmdZA0CW71DQ3Jli # wgz9J0YQpXWduc/m/+afIeCnKcqs7yCU8vFv5/lPY3L0AP0InMKw6ede3rcGLFhN # N7SD4vUEswiNDP12wb0lBVbaKdvJVzEm597aEtEBlUGZqwUm5cwuHI+mUKiqW5ue # /bpy9mWdRDi5rXDJY3iEaW/FMgMRDq4jhbPnmaJS5PEizCEkxhNcM/K88ujqk88a # otSWFSUZvv1ugBB8Dj8PKmlU # SIG # End signature block |