TheDashboard.psm1

function Format-StringToSentence { 
    <#
    .SYNOPSIS
    Formats a given string by adding spaces before uppercase letters, digits, and non-word characters.
 
    .DESCRIPTION
    The Format-AddSpaceToSentence function takes a string or an array of strings
    and adds a space before each uppercase letter, digit, and non-word character (excluding dots, spaces, and underscores).
    It also provides options to convert the string to lowercase, remove certain characters before or after the formatting, and remove double spaces.
 
    .PARAMETER Text
    The string or array of strings to be formatted.
 
    .PARAMETER RemoveCharsBefore
    An array of characters to be removed from the string before the formatting is applied.
 
    .PARAMETER RemoveCharsAfter
    An array of characters to be removed from the string after the formatting is applied.
 
    .PARAMETER ToLowerCase
    If this switch is present, the function will convert the string to lowercase.
 
    .PARAMETER RemoveDoubleSpaces
    If this switch is present, the function will remove any double spaces from the string.
 
    .PARAMETER MakeWordsUpperCase
    An array of words that should be converted to uppercase after the formatting is applied.
 
    .PARAMETER DisableAddingSpace
    If this switch is present, the function will not add spaces before uppercase letters, digits, and non-word characters.
 
    .EXAMPLE
    $test = @(
        'OnceUponATime',
        'OnceUponATime1',
        'Money@Risk',
        'OnceUponATime123',
        'AHappyMan2014'
        'OnceUponATime_123'
        'Domain test.com'
    )
 
    Format-StringToSentence -Text $Test -RemoveCharsAfter '_' -RemoveDoubleSpaces
 
    This example formats each string in the $test array, removes any underscores after the formatting, and removes any double spaces.
 
    .EXAMPLE
    $test = @(
        'OnceUponATime',
        'OnceUponATime1',
        'Money@Risk',
        'OnceUponATime123',
        'AHappyMan2014'
        'OnceUponATime_123'
        'Domain test.com'
    )
 
    $Test | Format-StringToSentence -ToLowerCase -RemoveCharsAfter '_' -RemoveDoubleSpaces
 
    This example does the same as the previous one, but also converts each string to lowercase.
 
    .EXAMPLE
    $test = @(
        'OnceUponATime',
        'OnceUponATime1',
        'Money@Risk',
        'OnceUponATime123',
        'AHappyMan2014'
        'OnceUponATime_123'
        'Domain test.com'
    )
 
    Format-StringToSentence -Text $Test -RemoveCharsAfter '_' -RemoveDoubleSpaces -MakeWordsUpperCase 'test.com', 'money'
 
    .NOTES
    The function uses the -creplace operator to add spaces, which is case-insensitive. Therefore, it will add spaces before both uppercase and lowercase letters if they are specified in the RemoveCharsBefore or RemoveCharsAfter parameters.
    #>

    [alias('Format-AddSpaceToSentence')]
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false, ValueFromPipeline = $true, Position = 0)][string[]] $Text,
        [string[]] $RemoveCharsBefore,
        [string[]] $RemoveCharsAfter,
        [switch] $ToLowerCase,
        [switch] $RemoveDoubleSpaces,
        [string[]] $MakeWordsUpperCase,
        [switch] $DisableAddingSpace
    )
    Process {
        foreach ($T in $Text) {
            if ($RemoveCharsBefore) {
                foreach ($R in $RemoveCharsBefore) {
                    $T = $T -ireplace [regex]::Escape($R), ""
                }
            }
            if (-not $DisableAddingSpace) {
                $T = $T -creplace '([A-Z]|[^a-zA-Z0-9_.\s]|_|\d+)(?<![a-z])', ' $&'
            }
            if ($ToLowerCase) {
                $T = $T.ToLower()
            }
            if ($RemoveCharsAfter) {
                foreach ($R in $RemoveCharsAfter) {
                    $T = $T -ireplace [regex]::Escape($R), ""
                }
            }
            if ($RemoveDoubleSpaces) {
                $T = $T -creplace '\s+', ' '
            }
            if ($MakeWordsUpperCase) {
                foreach ($W in $MakeWordsUpperCase) {
                    $T = $T -ireplace [regex]::Escape($W), $W.ToUpper()
                }
            }
            $T.Trim()
        }
    }
}
function Get-FileEncoding { 
    <#
    .SYNOPSIS
    Get the encoding of a file (ASCII, UTF8, UTF8BOM, Unicode, BigEndianUnicode, UTF7)
 
    .DESCRIPTION
    Get the encoding of a file (ASCII, UTF8, UTF8BOM, Unicode, BigEndianUnicode, UTF7).
    Encoding is determined by the first few bytes of the file or by the presence of non-ASCII characters.
 
    .PARAMETER Path
    Path to the file to check
 
    .EXAMPLE
    Get-FileEncoding -Path 'C:\Users\pklys\Desktop\test.txt'
 
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string] $Path
    )
    if (-not (Test-Path -Path $Path)) {
        if ($ErrorActionPreference -eq 'Stop') {
            throw "Get-FileEncoding - File not found: $Path"
        }
        Write-Warning -Message "Get-FileEncoding - File not found: $Path"
        return
    }
    $fileStream = [System.IO.FileStream]::new($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
    $byte = [byte[]]::new(4)
    $null = $fileStream.Read($byte, 0, 4)
    $fileStream.Close()

    if ($byte[0] -eq 0xef -and $byte[1] -eq 0xbb -and $byte[2] -eq 0xbf) {
        return 'UTF8BOM'
    } elseif ($byte[0] -eq 0xff -and $byte[1] -eq 0xfe) {
        return 'Unicode'
    } elseif ($byte[0] -eq 0xfe -and $byte[1] -eq 0xff) {
        return 'BigEndianUnicode'
    } elseif ($byte[0] -eq 0x2b -and $byte[1] -eq 0x2f -and $byte[2] -eq 0x76) {
        return 'UTF7'
    } else {

        $fileStream = [System.IO.FileStream]::new($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
        $byte = [byte[]]::new(1)
        while ($fileStream.Read($byte, 0, 1) -gt 0) {
            if ($byte[0] -gt 0x7F) {
                $fileStream.Close()
                return 'UTF8'
            }
        }
        $fileStream.Close()
        return 'ASCII'
    }
}
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.com/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 { 
    <#
    .SYNOPSIS
    Removes empty values from a hashtable recursively.
 
    .DESCRIPTION
    This function removes empty values from a given hashtable. It can be used to clean up a hashtable by removing keys with null, empty string, empty array, or empty dictionary values. The function supports recursive removal of empty values.
 
    .PARAMETER Hashtable
    The hashtable from which empty values will be removed.
 
    .PARAMETER ExcludeParameter
    An array of keys to exclude from the removal process.
 
    .PARAMETER Recursive
    Indicates whether to recursively remove empty values from nested hashtables.
 
    .PARAMETER Rerun
    Specifies the number of times to rerun the removal process recursively.
 
    .PARAMETER DoNotRemoveNull
    If specified, null values will not be removed.
 
    .PARAMETER DoNotRemoveEmpty
    If specified, empty string values will not be removed.
 
    .PARAMETER DoNotRemoveEmptyArray
    If specified, empty array values will not be removed.
 
    .PARAMETER DoNotRemoveEmptyDictionary
    If specified, empty dictionary values will not be removed.
 
    .EXAMPLE
    $hashtable = @{
        'Key1' = '';
        'Key2' = $null;
        'Key3' = @();
        'Key4' = @{}
    }
    Remove-EmptyValue -Hashtable $hashtable -Recursive
 
    Description
    -----------
    This example removes empty values from the $hashtable recursively.
 
    #>

    [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 Remove-FileItem { 
    <#
    .SYNOPSIS
    Removes one or more files and/or folders using one of three methods:
    Remove-Item, .NET Delete(), or move to Recycle Bin.
 
    .DESCRIPTION
    - If the path is a file, removes it in one shot.
    - If the path is a folder and -SkipFolder is NOT used, removes that folder
      in one shot (recursively if -Recursive is specified).
    - If -SkipFolder is used (and the path is a folder), calls Remove-ChildItems
      to remove only the folder's contents, leaving the folder itself.
 
    Supports:
     - RemoveItem, DotNetDelete, RecycleBin
     - Retries
     - WhatIf/Confirm
     - Passthru (detailed objects)
     - SimpleReturn (boolean overall result)
 
    .PARAMETER Paths
    One or more paths to files/folders.
 
    .PARAMETER DeleteMethod
    "RemoveItem", "DotNetDelete", or "RecycleBin". Defaults to "RemoveItem".
 
    .PARAMETER Recursive
    If set, allows recursive removal for folder contents.
 
    .PARAMETER SkipTopFolder
    If set for a folder, removes the contents only, not the folder itself.
 
    .PARAMETER Retries
    Specifies how many times to attempt removal before giving up. Defaults to 1.
 
    .PARAMETER Include
    Patterns (e.g., *.log) to include if removing child items individually.
    Will work only if SkipTopFolder is used.
 
    .PARAMETER Exclude
    Patterns (e.g., *.log) to exclude if removing child items individually.
    Will work only if SkipTopFolder is used.
 
    .PARAMETER Filter
    Filter for Get-ChildItem when removing child items individually.
    Will work only if SkipTopFolder is used.
 
    .PARAMETER Passthru
    Outputs an object for each path with details on success or failure.
 
    .PARAMETER SimpleReturn
    Outputs a single boolean indicating overall success or failure.
 
    .EXAMPLE
    Remove-FileItem -Paths "C:\SomeFolder" -DeleteMethod RemoveItem -Recursive -WhatIf
 
    Shows which items would be removed, but doesn't actually remove them,
    because -WhatIf is in effect.
 
    .EXAMPLE
    Remove-FileItem -Paths "C:\SomeFolder", "C:\SomeFile.txt" -Passthru -DeleteMethod DotNetDelete
 
    Removes both the folder (and everything in it) and the file, then returns details on each removal attempt.
 
    #>

    [Alias('Remove-ItemAlternative')]
    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Include')]
    param(
        [Parameter(Mandatory, ValueFromPipeline, Position = 0)][Alias('LiteralPath', 'Path')][string[]] $Paths,

        [ValidateSet("RemoveItem", "DotNetDelete", "RecycleBin")]
        [string] $DeleteMethod = "RecycleBin",

        [switch] $Recursive,

        [alias('SkipFolder')][switch] $SkipTopFolder,

        [int] $Retries = 1,

        [Parameter(ParameterSetName = 'Include')][string[]] $Include,

        [Parameter(ParameterSetName = 'Exclude')][string[]] $Exclude,

        [string] $Filter,

        [switch] $Passthru,

        [switch] $SimpleReturn
    )

    begin {
        $Results = [System.Collections.Generic.List[PSObject]]::new()
        $AllSucceeded = $true
    }

    process {
        foreach ($Path in $Paths) {

            $UnresolvedFullPath = $null
            try {
                $UnresolvedFullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
            } catch {
                $UnresolvedFullPath = $null
            }

            if (-not $UnresolvedFullPath) {
                $Message = "Remove-FileItem - Unable to resolve path '$Path'."
                if ($PSCmdlet.ErrorAction -eq 'Stop') {
                    throw $Message
                } else {
                    Write-Warning -Message $Message
                }
                $AllSucceeded = $false

                if ($Passthru) {
                    $Results.Add(
                        [PSCustomObject]@{
                            Path         = $Path
                            Status       = $false
                            Reason       = "Path could not be resolved."
                            AttemptCount = 0
                            WhatIf       = $WhatIfPreference
                        }
                    )
                }
                continue
            }

            if (-not (Test-Path -LiteralPath $UnresolvedFullPath)) {
                $Message = "Remove-FileItem - Path '$UnresolvedFullPath' does not exist."
                if ($PSCmdlet.ErrorAction -eq 'Stop') {
                    throw $Message
                } else {
                    Write-Warning -Message $Message
                }
                $AllSucceeded = $false
                if ($Passthru) {
                    $Results.Add(
                        [PSCustomObject]@{
                            Path         = $UnresolvedFullPath
                            Status       = $false
                            Reason       = "Path does not exist."
                            AttemptCount = 0
                            WhatIf       = $WhatIfPreference
                        }
                    )
                }
                continue
            }

            $ItemInfo = Get-Item -LiteralPath $UnresolvedFullPath -Force
            $IsDirectory = $ItemInfo.PSIsContainer

            if ($IsDirectory -and $SkipTopFolder) {

                $removeChildItemsSplat = @{
                    TopLevelPath    = $UnresolvedFullPath
                    DeleteMethod    = $DeleteMethod
                    Recursive       = $Recursive
                    Retries         = $Retries
                    Include         = $Include
                    Exclude         = $Exclude
                    Filter          = $Filter
                    Passthru        = $Passthru
                    Results         = $Results
                    AllSucceededRef = ([ref]$AllSucceeded)
                }
                Remove-ChildItems @removeChildItemsSplat
            } else {

                $Attempt = 0
                $Deleted = $false
                $LastError = $null
                $WhatIfUsed = $WhatIfPreference

                while ($Attempt -lt $Retries -and -not $Deleted) {
                    $Attempt++
                    Write-Verbose -Message "Remove-FileItem - Attempting to remove '$UnresolvedFullPath' (Attempt $Attempt of $Retries)."

                    if ($WhatIfUsed) {
                        $LastError = "Skipped because -WhatIf was used."
                    }
                    if ($PSCmdlet.ShouldProcess($UnresolvedFullPath, "Remove top-level")) {

                        try {
                            switch ($DeleteMethod) {
                                'RemoveItem' {
                                    if ($IsDirectory -and $Recursive) {
                                        Remove-Item -LiteralPath $UnresolvedFullPath -Recurse -Force -ErrorAction Stop
                                    } else {
                                        Remove-Item -LiteralPath $UnresolvedFullPath -Force -ErrorAction Stop
                                    }
                                }
                                'DotNetDelete' {
                                    if ($IsDirectory) {
                                        $DirInfo = [System.IO.DirectoryInfo] $UnresolvedFullPath
                                        if ($Recursive) {
                                            $DirInfo.Delete($true)
                                        } else {
                                            $DirInfo.Delete()
                                        }
                                    } else {
                                        $FileInfo = [System.IO.FileInfo] $UnresolvedFullPath
                                        $FileInfo.Delete()
                                    }
                                }
                                'RecycleBin' {
                                    $Shell = [Activator]::CreateInstance([Type]::GetTypeFromProgID("Shell.Application"))
                                    $FolderPath = Split-Path $UnresolvedFullPath
                                    $Leaf = Split-Path $UnresolvedFullPath -Leaf
                                    $Folder = $Shell.NameSpace($FolderPath)
                                    if (-not $Folder) {
                                        throw "Could not open folder: $FolderPath"
                                    }
                                    $ShellItem = $Folder.ParseName($Leaf)
                                    if (-not $ShellItem) {
                                        throw "Item '$Leaf' not found in folder: $FolderPath"
                                    }
                                    $ShellItem.InvokeVerb("delete")
                                }
                            }
                            $Deleted = $true
                        } catch {
                            $LastError = $_.Exception.Message
                            Write-Verbose -Message "Remove-FileItem - Error deleting '$UnresolvedFullPath': $LastError"

                            if ($PSCmdlet.ErrorAction -eq 'Stop') {
                                if ($Attempt -ge $Retries) {
                                    throw "Remove-FileItem - Couldn't delete '$UnresolvedFullPath' after $Retries attempts. Error: $LastError"
                                }
                            } else {
                                if ($Attempt -ge $Retries) {
                                    Write-Warning -Message "Remove-FileItem - Couldn't delete '$UnresolvedFullPath' after $Retries attempts. Error: $LastError"
                                }
                            }
                        }
                    }
                }

                if (-not $Deleted -and -not $WhatIfUsed) {
                    $AllSucceeded = $false
                }

                if ($WhatIfUsed) {
                    $AllSucceeded = $false
                }

                if ($Passthru) {
                    $Results.Add(
                        [PSCustomObject]@{
                            Path         = $UnresolvedFullPath
                            Status       = $Deleted
                            Reason       = if ($Deleted) {
                                $null 
                            } else {
                                $LastError 
                            }
                            AttemptCount = $Attempt
                            WhatIf       = $WhatIfUsed
                        }
                    )
                }
            }
        }
    }
    end {
        if ($Passthru) {
            $Results
        } elseif ($SimpleReturn) {
            $AllSucceeded
        }
    }
}
function Set-LoggingCapabilities { 
    <#
    .SYNOPSIS
    Sets up logging capabilities by managing log files.
 
    .DESCRIPTION
    This function sets up logging capabilities by creating the necessary directories and managing the number of log files based on the specified maximum.
 
    .PARAMETER LogPath
    The path where the log files will be stored.
 
    .PARAMETER ScriptPath
    The path of the script that generates the logs.
 
    .PARAMETER LogMaximum
    The maximum number of log files to keep. Older files will be deleted if this limit is exceeded.
 
    .PARAMETER ShowTime
    Switch to include timestamps in the log entries.
 
    .PARAMETER TimeFormat
    The format of the timestamps in the log entries.
 
    .PARAMETER ParameterPSDefaultParameterValues
    The hashtable of default parameter values for the Write-Color function.
    If this parameter is not provided, the function will create a new hashtable.
    This will only work properly if the function is nested as private function in another module.
    It's advised to provide the hashtable from the parent function for this to work always.
 
    .EXAMPLE
    Set-LoggingCapabilities -LogPath "C:\Logs\log.log" -ScriptPath "C:\Scripts\script.ps1" -LogMaximum 10 -ShowTime -TimeFormat "yyyy-MM-dd HH:mm:ss" -ParameterPSDefaultParameterValues $Script:PSDefaultParameterValues
 
    .EXAMPLE
    Set-LoggingCapabilities -LogPath "C:\Logs\log.log" -ScriptPath "C:\Scripts\script.ps1" -LogMaximum 10 -ShowTime -TimeFormat "yyyy-MM-dd HH:mm:ss"
 
    .NOTES
    This function is used in:
    - CleanupMonster
    - PasswordSolution
    - SharePointEssentials
 
    And many other scripts.
    #>

    [CmdletBinding()]
    param(
        [Alias('Path', 'Log', 'Folder', 'LiteralPath', 'FilePath')][string] $LogPath,
        [string] $ScriptPath,
        [Alias('Maximum')][int] $LogMaximum,
        [switch] $ShowTime,
        [string] $TimeFormat,
        [System.Collections.IDictionary] $ParameterPSDefaultParameterValues
    )
    if (-not $ParameterPSDefaultParameterValues) {
        $Script:PSDefaultParameterValues = @{
            "Write-Color:LogFile"    = $LogPath
            "Write-Color:ShowTime"   = if ($PSBoundParameters.ContainsKey('ShowTime')) {
                $ShowTime.IsPresent 
            } else {
                $null 
            }
            "Write-Color:TimeFormat" = $TimeFormat
        }
    } else {
        $ParameterPSDefaultParameterValues["Write-Color:LogFile"] = $LogPath
        $ParameterPSDefaultParameterValues["Write-Color:ShowTime"] = if ($PSBoundParameters.ContainsKey('ShowTime')) {
            $ShowTime.IsPresent 
        } else {
            $null 
        }
        $ParameterPSDefaultParameterValues["Write-Color:TimeFormat"] = $TimeFormat
    }
    if ($LogPath) {
        try {
            $FolderPath = [io.path]::GetDirectoryName($LogPath)
            if (-not (Test-Path -LiteralPath $FolderPath)) {
                $null = New-Item -Path $FolderPath -ItemType Directory -Force -WhatIf:$false
            }
            if ($LogMaximum -gt 0) {
                if ($ScriptPath) {
                    $ScriptPathFolder = [io.path]::GetDirectoryName($ScriptPath)
                    if ($ScriptPathFolder -eq $FolderPath) {
                        Write-Color -Text '[i] ', "LogMaximum is set to ", $LogMaximum, " but log files are in the same folder as the script. Cleanup disabled." -Color Yellow, White, DarkCyan, White
                        return
                    }

                    $LogPathExtension = [io.path]::GetExtension($LogPath)

                    if ($LogPathExtension) {

                        $CurrentLogs = Get-ChildItem -LiteralPath $FolderPath -Filter "*$LogPathExtension" -ErrorAction Stop | Sort-Object -Property CreationTime -Descending | Select-Object -Skip $LogMaximum
                    } else {
                        $CurrentLogs = $null
                        Write-Color -Text '[i] ', "Log file has no extension (?!). Cleanup disabled." -Color Yellow, White, DarkCyan, White
                    }
                    if ($CurrentLogs) {
                        Write-Color -Text '[i] ', "Logs directory has more than ", $LogMaximum, " log files. Cleanup required..." -Color Yellow, DarkCyan, Red, DarkCyan
                        foreach ($Log in $CurrentLogs) {
                            try {
                                Remove-Item -LiteralPath $Log.FullName -Confirm:$false -WhatIf:$false
                                Write-Color -Text '[+] ', "Deleted ", "$($Log.FullName)" -Color Yellow, White, Green
                            } catch {
                                Write-Color -Text '[-] ', "Couldn't delete log file $($Log.FullName). Error: ', "$($_.Exception.Message) -Color Yellow, White, Red
                            }
                        }
                    }
                } else {
                    Write-Color -Text '[i] ', "LogMaximum is set to ", $LogMaximum, " but no script path detected. Most likely running interactively. Cleanup disabled." -Color Yellow, White, DarkCyan, White
                }
            } else {
                Write-Color -Text '[i] ', "LogMaximum is set to 0 (Unlimited). No log files will be deleted." -Color Yellow, DarkCyan
            }
        } catch {
            Write-Color -Text "[e] ", "Couldn't create the log directory. Error: $($_.Exception.Message)" -Color Yellow, Red
            $Script:PSDefaultParameterValues["Write-Color:LogFile"] = $null
        }
    } else {
        $Script:PSDefaultParameterValues["Write-Color:LogFile"] = $null
    }
    Remove-EmptyValue -Hashtable $Script:PSDefaultParameterValues
}
function Start-TimeLog { 
    <#
    .SYNOPSIS
    Starts a new stopwatch for logging time.
 
    .DESCRIPTION
    This function starts a new stopwatch that can be used for logging time durations.
 
    .EXAMPLE
    Start-TimeLog
    Starts a new stopwatch for logging time.
 
    #>

    [CmdletBinding()]
    param()
    [System.Diagnostics.Stopwatch]::StartNew()
}
function Stop-TimeLog { 
    <#
    .SYNOPSIS
    Stops the stopwatch and returns the elapsed time in a specified format.
 
    .DESCRIPTION
    The Stop-TimeLog function stops the provided stopwatch and returns the elapsed time in a specified format. The function can output the elapsed time as a single string or an array of days, hours, minutes, seconds, and milliseconds.
 
    .PARAMETER Time
    Specifies the stopwatch object to stop and retrieve the elapsed time from.
 
    .PARAMETER Option
    Specifies the format in which the elapsed time should be returned. Valid values are 'OneLiner' (default) or 'Array'.
 
    .PARAMETER Continue
    Indicates whether the stopwatch should continue running after retrieving the elapsed time.
 
    .EXAMPLE
    $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
    # Perform some operations
    Stop-TimeLog -Time $stopwatch
    # Output: "0 days, 0 hours, 0 minutes, 5 seconds, 123 milliseconds"
 
    .EXAMPLE
    $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
    # Perform some operations
    Stop-TimeLog -Time $stopwatch -Option Array
    # Output: ["0 days", "0 hours", "0 minutes", "5 seconds", "123 milliseconds"]
    #>

    [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 delivering a lot of additional features for easier color options.
 
    .DESCRIPTION
    Write-Color is a wrapper around Write-Host delivering a lot of additional features for easier color options.
 
    It provides:
    - Easy manipulation of colors,
    - Logging output to file (log)
    - Nice formatting options out of the box.
    - Ability to use aliases for parameters
 
    .PARAMETER Text
    Text to display on screen and write to log file if specified.
    Accepts an array of strings.
 
    .PARAMETER Color
    Color of the text. Accepts an array of colors. If more than one color is specified it will loop through colors for each string.
    If there are more strings than colors it will start from the beginning.
    Available colors are: Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White
 
    .PARAMETER BackGroundColor
    Color of the background. Accepts an array of colors. If more than one color is specified it will loop through colors for each string.
    If there are more strings than colors it will start from the beginning.
    Available colors are: Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White
 
    .PARAMETER StartTab
    Number of tabs to add before text. Default is 0.
 
    .PARAMETER LinesBefore
    Number of empty lines before text. Default is 0.
 
    .PARAMETER LinesAfter
    Number of empty lines after text. Default is 0.
 
    .PARAMETER StartSpaces
    Number of spaces to add before text. Default is 0.
 
    .PARAMETER LogFile
    Path to log file. If not specified no log file will be created.
 
    .PARAMETER DateTimeFormat
    Custom date and time format string. Default is yyyy-MM-dd HH:mm:ss
 
    .PARAMETER LogTime
    If set to $true it will add time to log file. Default is $true.
 
    .PARAMETER LogRetry
    Number of retries to write to log file, in case it can't write to it for some reason, before skipping. Default is 2.
 
    .PARAMETER Encoding
    Encoding of the log file. Default is Unicode.
 
    .PARAMETER ShowTime
    Switch to add time to console output. Default is not set.
 
    .PARAMETER NoNewLine
    Switch to not add new line at the end of the output. Default is not set.
 
    .PARAMETER NoConsoleOutput
    Switch to not output to console. Default all output goes to console.
 
    .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
    Write-Color -T "My text", " is ", "all colorful" -C Yellow, Red, Green -B Green, Green, Yellow
    Write-Color -t "my text" -c yellow -b green
    Write-Color -text "my text" -c red
 
    .EXAMPLE
    Write-Color -Text "Testuję czy się ładnie zapisze, czy będą problemy" -Encoding unicode -LogFile 'C:\temp\testinggg.txt' -Color Red -NoConsoleOutput
 
    .NOTES
    Understanding Custom date and time format strings: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
    Project support: https://github.com/EvotecIT/PSWriteColor
    Original idea: Josh (https://stackoverflow.com/users/81769/josh)
 
    #>

    [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,
        [alias('HideConsole')][switch] $NoConsoleOutput
    )
    if (-not $NoConsoleOutput) {
        $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) {
                    Write-Warning "Write-Color - Couldn't write to log file $($_.Exception.Message). Tried ($Retry/$LogRetry))"
                } 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 Remove-ChildItems { 
    <#
    .SYNOPSIS
    Helper function that removes the child items of a given folder.
 
    .DESCRIPTION
    - Enumerates the folder's contents (recursively if requested).
    - Removes each child item individually, respecting the chosen DeleteMethod.
    - Respects -WhatIf and -Confirm (because of CmdletBinding with SupportsShouldProcess).
    - Records attempts in Passthru objects if desired.
 
    .PARAMETER TopLevelPath
    Specifies the path to the folder whose contents are to be removed.
 
    .PARAMETER DeleteMethod
    Specifies the removal method: RemoveItem, DotNetDelete, or RecycleBin.
 
    .PARAMETER Recursive
    Specifies whether to enumerate child items recursively.
 
    .PARAMETER Retries
    Number of retry attempts for each item.
 
    .PARAMETER Include
    Include patterns for Get-ChildItem.
 
    .PARAMETER Exclude
    Exclude patterns for Get-ChildItem.
 
    .PARAMETER Filter
    Filter for Get-ChildItem.
 
    .PARAMETER Passthru
    If true, records results in $Results.
 
    .PARAMETER Results
    [System.Collections.Generic.List[PSObject]] passed in from the parent function.
 
    .PARAMETER AllSucceededRef
    [ref] reference to a boolean tracking overall success/failure.
 
    .EXAMPLE
    Remove-ChildItems -TopLevelPath "C:\Folder" -DeleteMethod RemoveItem -Recursive -WhatIf
 
    Shows (via WhatIf) which items would be removed inside "C:\Folder".
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)][string] $TopLevelPath,

        [Parameter(Mandatory)][ValidateSet("RemoveItem", "DotNetDelete", "RecycleBin")]
        [string] $DeleteMethod,

        [switch] $Recursive,

        [int] $Retries,

        [string[]] $Include,

        [string[]] $Exclude,

        [string] $Filter,

        [switch] $Passthru,

        [System.Collections.Generic.List[PSObject]] $Results,

        [ref] $AllSucceededRef
    )
    begin {
        Write-Verbose -Message "Remove-ItemAlternative - Removing contents of '$TopLevelPath' (SkipFolder)."
        $getChildItemSplat = @{
            LiteralPath = $TopLevelPath
            Force       = $true
            Include     = $Include
            Exclude     = $Exclude
            Filter      = $Filter
            ErrorAction = 'SilentlyContinue'
        }
        Remove-EmptyValue -Hashtable $getChildItemSplat

        $Items = Get-ChildItem @getChildItemSplat
        if ($Recursive) {
            $Items = $Items | Sort-Object -Property FullName -Descending
        }

        $WhatIfUsed = $WhatIfPreference
    }
    process {
        foreach ($Item in $Items) {
            $Attempt = 0
            $Deleted = $false
            $LastError = $null

            while ($Attempt -lt $Retries -and -not $Deleted) {
                $Attempt++
                Write-Verbose -Message "Remove-ItemAlternative - Attempting to remove '$($Item.FullName)' (Attempt $Attempt of $Retries)."

                if ($WhatIfUsed) {

                    $LastError = "Skipped because -WhatIf was used."
                }
                if ($PSCmdlet.ShouldProcess($Item.FullName, "Remove child item")) {
                    try {
                        switch ($DeleteMethod) {
                            'RemoveItem' {
                                if ($Recursive -and $Item.PSIsContainer) {
                                    Remove-Item -LiteralPath $Item.FullName -Recurse -Force -ErrorAction Stop
                                } else {
                                    Remove-Item -LiteralPath $Item.FullName -Force -ErrorAction Stop
                                }
                            }
                            'DotNetDelete' {
                                if ($Item.PSIsContainer) {
                                    $Dir = [System.IO.DirectoryInfo] $Item.FullName
                                    if ($Recursive) {
                                        $Dir.Delete($true)
                                    } else {
                                        $Dir.Delete()
                                    }
                                } else {
                                    $File = [System.IO.FileInfo] $Item.FullName
                                    $File.Delete()
                                }
                            }
                            'RecycleBin' {
                                $Shell = [Activator]::CreateInstance([Type]::GetTypeFromProgID("Shell.Application"))
                                $FolderPath = Split-Path $Item.FullName
                                $Leaf = Split-Path $Item.FullName -Leaf
                                $Folder = $Shell.NameSpace($FolderPath)
                                if (-not $Folder) {
                                    throw "Could not open folder: $FolderPath"
                                }
                                $ShellItem = $Folder.ParseName($Leaf)
                                if (-not $ShellItem) {
                                    throw "Item '$Leaf' not found in folder: $FolderPath"
                                }
                                $ShellItem.InvokeVerb("delete")
                            }
                        }
                        $Deleted = $true
                    } catch {
                        $LastError = $_.Exception.Message
                        Write-Verbose -Message "Remove-ItemAlternative - Error deleting '$($Item.FullName)': $LastError"

                        if ($PSCmdlet.ErrorAction -eq 'Stop') {
                            if ($Attempt -ge $Retries) {
                                throw "Remove-ItemAlternative - Couldn't delete '$($Item.FullName)' after $Retries attempts. Error: $LastError"
                            }
                        } else {
                            if ($Attempt -ge $Retries) {
                                Write-Warning -Message "Remove-ItemAlternative - Couldn't delete '$($Item.FullName)' after $Retries attempts. Error: $LastError"
                            }
                        }
                    }
                }
            }

            if (-not $Deleted -and -not $WhatIfUsed) {
                $AllSucceededRef.Value = $false
            }

            if ($Passthru) {
                $Results.Add(
                    [PSCustomObject]@{
                        Path         = $Item.FullName
                        Status       = $Deleted
                        Reason       = if ($Deleted) {
                            $null 
                        } else {
                            $LastError 
                        }
                        AttemptCount = $Attempt
                        WhatIf       = $WhatIfUsed
                    }
                )
            }
        }
    }
}
function Convert-FilesToKeepOrRemove {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Array] $FilePathsGenerated,
        [Array] $Files,
        [switch] $RemoveNotIncluded,
        [ValidateSet("RemoveItem", "DotNetDelete", "RecycleBin")]
        [string] $DeleteMethod = "RecycleBin"
    )
    [Array] $FullSummary = @(
        foreach ($File in $FilePathsGenerated) {
            try {
                $FileInfo = Get-Item -LiteralPath $File -ErrorAction Stop
                $Output = [PSCustomObject] @{
                    Type    = 'Dashboard'
                    Path    = $File
                    Include = $true
                    Date    = ($FileInfo).LastWriteTime
                    Status  = 'Included'
                }
            } catch {
                $Output = [PSCustomObject] @{
                    Type    = 'Dashboard'
                    Path    = $File
                    Include = $false
                    Date    = $null
                    Status  = 'Included (WhatIf)'
                }
            }
            if ($WhatIfPreference) {
                $Output.Status = 'Included (WhatIf)'
            }
            $Output
        }
        foreach ($File in $Files) {
            [PSCustomObject] @{
                Type    = 'Report'
                Path    = $File.FullPath
                Include = $File.Include
                Date    = $File.Date
                Status  = if ($File.Include) {
                    'Included' } else {
                    'Excluded' }
            }
        }
    )
    if ($RemoveNotIncluded) {
        foreach ($File in $FullSummary) {
            if (-not $File.Include) {
                Remove-FileItem -Paths $File.Path -DeleteMethod $DeleteMethod -WhatIf:$WhatIfPreference
                if ($WhatIfPreference) {
                    $File.Status = 'Removed (WhatIf)'
                } else {
                    $File.Status = 'Removed'
                }
            }
        }
    }
    $FullSummary
}
function Convert-FilesToMenu {
    <#
    .SYNOPSIS
    Generates a structured menu from a collection of files and folders.
 
    .DESCRIPTION
    Builds ordered folders and file entries, applies filtering and history logic.
 
    .PARAMETER Folders
    Dictionary defining folder metadata and optional limits configuration.
 
    .PARAMETER Files
    Array of file data, each containing attributes such as Date, Menu, and Name.
 
    .EXAMPLE
    Convert-FilesToMenu -Folders $Folders -Files $FileList
 
    .NOTES
    Part of TheDashboard module, creates the navigation menu from report files.
    #>

    [CmdletBinding()]
    param(
        [System.Collections.IDictionary] $Folders,
        [Array] $Files,
        [System.Collections.IDictionary] $ExportData
    )
    $CurrentDate = Get-Date

    $MenuBuilder = [ordered] @{}

    foreach ($Folder in $Folders.Keys) {
        if (-not $MenuBuilder[$Folder]) {
            $MenuBuilder[$Folder] = [ordered] @{}
        }
    }

    foreach ($Entry in $Files | Sort-Object { $_.Date } -Descending) {
        $LimitsConfiguration = $Folders[$Entry.Menu].LimitsConfiguration
        if ($LimitsConfiguration) {
            $Limits = $LimitsConfiguration[$Entry.Name]
            if (-not $Limits) {
                if ($LimitsConfiguration['*']) {
                    $Limits = $LimitsConfiguration['*']
                } else {
                    $Limits = $null
                }
            }
        } else {
            $Limits = $null
        }

        if (-not $MenuBuilder[$Entry.Menu][$Entry.Name]) {
            $Entry.Include = $true
            $MenuBuilder[$Entry.Menu][$Entry.Name] = @{
                Current = $Entry
                Full    = [System.Collections.Generic.List[Object]]::new()
                History = [System.Collections.Generic.List[Object]]::new()
            }
        }
        if ($Entry.Include -ne $true) {
            if ($Limits.LimitItem) {
                if ($MenuBuilder[$Entry.Menu][$Entry.Name]['Full'].Count -ge $Limits.LimitItem) {
                    $Entry.Include = $true

                    Limit-FilesHistory -MenuBuilder $MenuBuilder -Entry $Entry -Limits $Limits -CurrentDate $CurrentDate
                    continue
                }
            } elseif ($Limits.LimitDate) {
                if ($Entry.Date -lt $Limits.LimitDate) {
                    $Entry.Include = $true

                    Limit-FilesHistory -MenuBuilder $MenuBuilder -Entry $Entry -Limits $Limits -CurrentDate $CurrentDate
                    continue
                }
            } elseif ($Limits.LimitDays) {
                if ($Entry.Date -lt ($CurrentDate).AddDays(-$Limits.LimitDays)) {
                    $Entry.Include = $true

                    Limit-FilesHistory -MenuBuilder $MenuBuilder -Entry $Entry -Limits $Limits -CurrentDate $CurrentDate
                    continue
                }
            }
        }
        $Entry.Include = $true
        $MenuBuilder[$Entry.Menu][$Entry.Name]['Full'].Add($Entry)
    }

    if ($ExportData.MenuBuilder.Keys.Count -eq 0) {

        return $MenuBuilder
    }
    if ($MenuBuilder.Keys -and $ExportData.MenuBuilder.Keys -and $MenuBuilder.Keys.Count -ne $ExportData.MenuBuilder.Keys.Count) {

        return $MenuBuilder
    }
    $Comparison = Compare-Object -ReferenceObject $MenuBuilder.Keys -DifferenceObject $ExportData.MenuBuilder.Keys
    if ($Comparison) {

        return $MenuBuilder
    }

    foreach ($Section in $MenuBuilder.Keys) {
        if ($ExportData.MenuBuilder[$Section].Count -ne $MenuBuilder[$Section].Count) {

            return $MenuBuilder
        }
        $Comparison = Compare-Object -ReferenceObject $MenuBuilder[$Section].Keys -DifferenceObject $ExportData.MenuBuilder[$Section].Keys
        if ($Comparison) {

            return $MenuBuilder
        }
    }

    foreach ($Section in $MenuBuilder.Keys) {
        foreach ($Name in $MenuBuilder[$Section].Keys) {
            $MenuData = $MenuBuilder[$Section][$Name]
            $MenuDataFromImport = $ExportData.MenuBuilder[$Section][$Name]

            $RegenerateNotRequired = $true
            $Comparison = Compare-Object -ReferenceObject $MenuData.Current -DifferenceObject $MenuDataFromImport.Current -Property Date, Name, Href
            if ($Comparison) {
                $RegenerateNotRequired = $false
            }
            $Comparison = Compare-Object -ReferenceObject $MenuData.Full -DifferenceObject $MenuDataFromImport.Full -Property Date, Name, Href
            if ($Comparison) {
                $RegenerateNotRequired = $false
            }
            $Comparison = Compare-Object -ReferenceObject $MenuData.History -DifferenceObject $MenuDataFromImport.History -Property Date, Name, Href
            if ($Comparison) {
                $RegenerateNotRequired = $false
            }
            if ($RegenerateNotRequired -eq $true) {
                $MenuData.Current.SkipGeneration = $true
                foreach ($Entry in $MenuData.Full) {
                    $Entry.SkipGeneration = $true
                }
                foreach ($Entry in $MenuData.History) {
                    $Entry.SkipGeneration = $true
                }
            }
        }
    }
    $MenuBuilder
}
function Convert-FilesToMenuData {
    [CmdletBinding()]
    param(
        [System.Collections.IDictionary] $Folders,
        [System.Collections.IDictionary] $Replacements,
        [string] $Extension
    )
    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 "*$Extension" | 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) {
            $RelativeFolder = Split-Path -Path $Folders[$FolderName].Path -Leaf
            $Href = "$($RelativeFolder)/$($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
                    if ($null -ne $Replacements.AfterSplitPositionName) {
                        $PositionPlace = @(0)
                        $Name = ''
                        if ($Replacements.AfterSplitPositionName -is [System.Collections.IDictionary]) {
                            foreach ($FileNameToFind in $Replacements.AfterSplitPositionName.Keys) {
                                [Array] $PositionPlace = $Replacements.AfterSplitPositionName[$FileNameToFind]
                                if ($MenuName -like $FileNameToFind) {
                                    break
                                }
                            }
                        } else {
                            [Array] $PositionPlace = $Replacements.AfterSplitPositionName
                        }
                        $NameParts = foreach ($Position in $PositionPlace) {
                            $Splitted[$Position]
                        }
                        $Name = $NameParts -join ' '
                    } else {
                        $Name = $Splitted[0]
                    }
                } else {
                    $Name = $MenuName
                }

                $formatStringToSentenceSplat = @{
                    Text               = $Name
                    RemoveCharsBefore  = $Replacements.BeforeRemoveChars
                    RemoveCharsAfter   = $Replacements.AfterRemoveChars
                    RemoveDoubleSpaces = $Replacements.AfterRemoveDoubleSpaces
                    MakeWordsUpperCase = $Replacements.AfterUpperChars
                    DisableAddingSpace = -not $Replacements.AddSpaceToName
                }
                $Name = Format-StringToSentence @formatStringToSentenceSplat

                foreach ($Replace in $Replacements.AfterSplit.Keys) {
                    $Name = $Name.Replace($Replace, $Replacements.AfterSplit[$Replace])
                }
                $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
                    if ($null -ne $Folder.Replacements.AfterSplitPositionName) {
                        $PositionPlace = @(0)
                        $Name = ''
                        if ($Folder.Replacements.AfterSplitPositionName -is [System.Collections.IDictionary]) {
                            foreach ($FileNameToFind in $Folder.Replacements.AfterSplitPositionName.Keys) {
                                [Array] $PositionPlace = $Folder.Replacements.AfterSplitPositionName[$FileNameToFind]
                                if ($MenuName -like $FileNameToFind) {
                                    break
                                }
                            }
                        } else {
                            [Array] $PositionPlace = $Folder.Replacements.AfterSplitPositionName
                        }
                        $NameParts = foreach ($Position in $PositionPlace) {
                            $Splitted[$Position]
                        }
                        $Name = $NameParts -join ' '
                    } else {
                        $Name = $Splitted[0]
                    }
                } else {
                    $Name = $MenuName
                }

                $formatStringToSentenceSplat = @{
                    Text               = $Name
                    RemoveCharsBefore  = $Folder.Replacements.BeforeRemoveChars
                    RemoveCharsAfter   = $Folder.Replacements.AfterRemoveChars
                    RemoveDoubleSpaces = $Folder.Replacements.AfterRemoveDoubleSpaces
                    MakeWordsUpperCase = $Folder.Replacements.AfterUpperChars
                    DisableAddingSpace = -not $Folder.Replacements.AddSpaceToName
                }

                $Name = Format-StringToSentence @formatStringToSentenceSplat

                foreach ($Replace in $Folder.Replacements.AfterSplit.Keys) {
                    $Name = $Name.Replace($Replace, $Folder.Replacements.AfterSplit[$Replace])
                }
                $Type = 'folder replacements'
            } else {
                $Name = $MenuName
                $Type = 'no replacements applied'
            }
            if ($Name) {
                [PSCustomObject] @{
                    Name           = $Name
                    Href           = $Href
                    FileName       = "$($Folder.Url)_$($File.Name)"
                    Menu           = $FolderName
                    MenuLink       = $Folder.Url
                    Date           = $File.LastWriteTime

                    FullPath       = $File.FullName

                    Include        = $false

                    SkipGeneration = $false
                }
            } 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
    )

    if (-not $Replacements) {
        $ReplacementSetting = [ordered] @{
            SplitOn                 = $null
            BeforeSplit             = [ordered] @{}
            AfterSplit              = [ordered] @{}
            AddSpaceToName          = $null
            AfterSplitPositionName  = $null
            AfterRemoveChars        = $null
            AfterUpperChars         = $null
            AfterRemoveDoubleSpaces = $null
            BeforeRemoveChars       = $null
        }
    } else {
        $ReplacementSetting = $Replacements
    }

    foreach ($Replacement in $ReplacementConfiguration) {
        Remove-EmptyValue -Hashtable $Replacement
        foreach ($R in $Replacement.Keys) {
            if ($R -eq 'SplitOn') {
                if ($null -ne $Replacement[$R]) {
                    $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') {
                if ($null -ne $Replacement[$R]) {
                    $ReplacementSetting['AddSpaceToName'] = $Replacement[$R]
                }
            } elseif ($R -eq 'AfterSplitPositionName') {
                if ($null -ne $Replacement[$R]) {
                    $ReplacementSetting['AfterSplitPositionName'] = $Replacement[$R]
                }
            } else {
                if ($null -ne $Replacement[$R]) {
                    if ($Replacement[$R].GetType().Name -eq 'SwitchParameter') {
                        $ReplacementSetting[$R] = $Replacement[$R].IsPresent
                    } else {
                        $ReplacementSetting[$R] = $Replacement[$R]
                    }
                }
            }
        }
    }
    $ReplacementSetting
}
function Convert-NestedElements {
    [CmdletBinding()]
    param(
        [ScriptBlock] $Elements,
        [System.Collections.Generic.List[System.Collections.IDictionary]] $GageConfiguration,
        [System.Collections.Generic.List[System.Collections.IDictionary]] $FoldersConfiguration,
        [System.Collections.Generic.List[System.Collections.IDictionary]] $ReplacementConfiguration,
        [System.Collections.IDictionary] $FolderLimit
    )

    if ($Elements) {
        $TimeLogElements = Start-TimeLog
        Write-Color -Text '[i]', "[TheDashboard] ", 'Executing nested elements (data gathering/conversions)', ' [Informative] ' -Color Yellow, DarkGray, Yellow, DarkGray, Magenta

        try {
            $OutputElements = & $Elements
        } catch {
            Write-Color -Text '[e]', "[TheDashboard] ", 'Failed to execute nested elements', ' [Error] ', $_.Exception.Message -Color Yellow, DarkGray, Yellow, DarkGray, Red
            return
        }
        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)
            } elseif ($E.Type -eq 'FolderLimit') {
                foreach ($Setting in $E.Settings.Keys) {
                    $FolderLimit[$Setting] = $E.Settings[$Setting]
                }
            }
        }

        $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
    }
}
function Copy-HTMLFiles {
    [cmdletbinding()]
    param(
        [System.Collections.IDictionary] $Folders,
        [string] $Extension
    )

    Write-Color -Text '[i]', "[TheDashboard] ", 'Copying or HTML files', ' [Informative] ' -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 "*$Extension" -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 "*$Extension" -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 Import-DashboardStatistics {
    [CmdletBinding()]
    param(
        [string] $StatisticsPath
    )
    $ExportData = [ordered] @{
        MenuBuilder = [ordered] @{}
        Statistics  = [ordered] @{}
    }
    if ($StatisticsPath -and (Test-Path -LiteralPath $StatisticsPath)) {
        Write-Color -Text '[i]', "[TheDashboard] ", 'Importing Statistics', ' [Informative] ', $StatisticsPath -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
        $ImportedData = Import-Clixml -LiteralPath $StatisticsPath
        if (-not $ImportedData.Statistics) {
            $ExportData.Statistics = $ImportedData
        } else {
            $ExportData = $ImportedData
        }
    }
    foreach ($E in $GageConfiguration) {
        $ExportData['Statistics'][$E.Date] = [ordered] @{}
        $ExportData['Statistics'][$E.Date].Date = $E.Date
    }
    $ExportData
}
function Limit-FilesHistory {
    <#
    .SYNOPSIS
    Controls how files are moved into history based on specified limits.
 
    .DESCRIPTION
    Checks and applies IncludeHistory settings, filtering by date or count.
 
    .PARAMETER MenuBuilder
    Contains the menu structure to which entries will be added.
 
    .PARAMETER Entry
    Represents the current file entry under evaluation.
 
    .PARAMETER Limits
    Holds data about various limits for item, days, and date filtering.
 
    .PARAMETER CurrentDate
    Specifies the current date for time-based comparisons.
 
    .EXAMPLE
    Limit-FilesHistory -MenuBuilder $Builder -Entry $File -Limits $Limits -CurrentDate (Get-Date)
 
    .NOTES
    Part of TheDashboard module, handles history-limit logic for file entries.
    #>

    [CmdletBinding()]
    param(
        [System.Collections.IDictionary] $MenuBuilder,
        [PSCustomObject] $Entry,
        [System.Collections.IDictionary] $Limits,
        [DateTime] $CurrentDate
    )
    if ($Limits.IncludeHistory) {
        if ($null -ne $Limits.IncludeHistoryLimit) {
            if ($MenuBuilder[$Entry.Menu][$Entry.Name]['History'].Count -ge $Limits.IncludeHistoryLimit) {
                $Entry.Include = $false
                return
            }
        }
        if ($null -ne $Limits.IncludeHistoryLimitDate) {
            if ($Entry.Date -lt $Limits.IncludeHistoryLimitDate) {
                $Entry.Include = $false
                return
            }
        }
        if ($null -ne $Limits.IncludeHistoryLimitDays) {
            if ($Entry.Date -lt ($CurrentDate).AddDays(-$Limits.IncludeHistoryLimitDays)) {
                $Entry.Include = $false
                return
            }
        }
        $Entry.Include = $true
        $MenuBuilder[$Entry.Menu][$Entry.Name]['History'].Add($Entry)
    }
}
function New-HTMLReport {
    [cmdletBinding()]
    param(
        [Array] $OutputElements,
        [string] $Logo,
        [string] $Extension,
        [System.Collections.IDictionary] $MenuBuilder,
        [System.Collections.IDictionary] $Configuration,
        [System.Collections.IDictionary] $ExportData,
        [Array] $Files,
        [string] $HTMLPath,
        [switch] $ShowHTML,
        [switch] $Online,
        [Uri] $UrlPath,
        [switch] $Force,
        [switch] $Pretend
    )
    $TimeLogHTML = Start-TimeLog
    Write-Color -Text '[i]', '[HTML ] ', "Generating HTML report ($HTMLPath)" -Color Yellow, DarkGray, Yellow

    $FilePathsGenerated = [System.Collections.Generic.List[string]]::new()
    $FilePathsGenerated.Add($HTMLPath) 

    if ($Pretend) {
        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 | Sort-Object) {
                $MenuLink = $MenuBuilder[$Menu][$MenuReport]['Current'].MenuLink
                $PathToSubReports = [io.path]::GetDirectoryName($HTMLPath)
                $PageName = ($MenuBuilder[$Menu][$MenuReport]['Current'].Name).Replace(":", "_").Replace(" ", "_")
                $FullPath = [io.path]::Combine($PathToSubReports, "$($MenuLink)_$PageName$($Extension)")

                $CurrentReport = $MenuBuilder[$Menu][$MenuReport]['Current']
                [Array] $FullReports = $MenuBuilder[$Menu][$MenuReport]['Full']
                [Array] $HistoryReports = $MenuBuilder[$Menu][$MenuReport]['History']

                $Name = $CurrentReport.Name
                $FilePathsGenerated.Add($FullPath)  

                foreach ($Report in $FullReports) {
                    $FullPathOther = [io.path]::Combine($PathToSubReports, $Report.FileName)
                    $Name = $Report.Name + ' - ' + $Report.Date
                    $FilePathsGenerated.Add($FullPathOther) 
                }
            }
            Write-Color -Text '[i]', '[HTML ] ', "Ending Menu for ", $Menu -Color Yellow, DarkGray, Yellow, DarkCyan
        }
    } else {

        New-HTML {
            $newHTMLNavTopSplat = @{
                Logo            = $Logo
                MenuItemsWidth  = '250px'
                NavigationLinks = {
                    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 | Sort-Object) {
                                $MenuLink = $MenuBuilder[$Menu][$MenuReport]['Current'].MenuLink
                                $PageName = (( -join ($MenuBuilder[$Menu][$MenuReport]['Current'].Name)).Replace(":", "_").Replace(" ", "_"))
                                if ($UrlPath) {
                                    New-NavLink -IconRegular calendar-check -Name $MenuBuilder[$Menu][$MenuReport]['Current'].Name -Href "$UrlPath/$($MenuLink)_$($PageName)$($Extension)"
                                } else {
                                    New-NavLink -IconRegular calendar-check -Name $MenuBuilder[$Menu][$MenuReport]['Current'].Name -Href "$($MenuLink)_$($PageName)$($Extension)"
                                }
                            }
                        }
                    }
                }
            }
            if ($UrlPath) {
                $FileNameHome = [System.IO.Path]::GetFileName($HTMLPath)
                $newHTMLNavTopSplat['HomeLink'] = "$UrlPath/$FileNameHome"
            } else {
                $newHTMLNavTopSplat['HomeLinkHome'] = $true
            }
            New-HTMLNavTop @newHTMLNavTopSplat

            New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
            New-HTMLPanelStyle -BorderRadius 0px

            New-HTMLSection -Invisible {
                foreach ($E in $OutputElements) {
                    New-HTMLPanel {
                        New-HTMLGage -Label $E.Label -MinValue $E.MinValue -MaxValue $E.MaxValue -Value $E.Value -Counter
                        $ExportData['Statistics'][$E.Date][$($E.Label)] = $E.Value

                    }
                }
            }
            New-HTMLSection -Invisible {
                New-HTMLPanel {
                    $StatisticsKeys = $ExportData['Statistics'].Keys | Sort-Object | Select-Object -Last 50
                    [Array] $Dates = foreach ($Day in $StatisticsKeys) {
                        $ExportData['Statistics'][$Day].Date
                    }

                    foreach ($UserInput in $Dates) {
                        $ExportData['Statistics'][$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) {
                                $ExportData['Statistics'][$Day].$($UserInput.Label)
                            }
                            New-ChartLine -Name $UserInput.Label -Value $Values
                        }
                    }
                }
                New-HTMLPanel {
                    New-HTMLCalendar {
                        foreach ($Menu in $MenuBuilder.Keys) {
                            foreach ($MenuReport in $MenuBuilder[$Menu].Keys) {
                                [Array] $FullReports = $MenuBuilder[$Menu][$MenuReport]['Full']
                                foreach ($CalendarEntry in $FullReports) {

                                    if ($CalendarEntry.Include) {
                                        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 | Sort-Object) {
                    $MenuLink = $MenuBuilder[$Menu][$MenuReport]['Current'].MenuLink
                    $PathToSubReports = [io.path]::GetDirectoryName($HTMLPath)
                    $PageName = ($MenuBuilder[$Menu][$MenuReport]['Current'].Name).Replace(":", "_").Replace(" ", "_")
                    $FullPath = [io.path]::Combine($PathToSubReports, "$($MenuLink)_$PageName$($Extension)")

                    $CurrentReport = $MenuBuilder[$Menu][$MenuReport]['Current']
                    [Array] $FullReports = $MenuBuilder[$Menu][$MenuReport]['Full']
                    [Array] $HistoryReports = $MenuBuilder[$Menu][$MenuReport]['History']

                    $Name = $CurrentReport.Name
                    if (-not $CurrentReport.SkipGeneration) {
                        New-HTMLReportPage -Report $CurrentReport -FullReports $FullReports -HistoryReports $HistoryReports -FilePath $FullPath -PathToSubReports $PathToSubReports -Name $Name
                    } else {
                        Write-Color -Text '[i]', '[HTML ] ', "Skipping generation of ", $FullPath, ". generation not required..." -Color Yellow, DarkGray, Yellow
                    }
                    $FilePathsGenerated.Add($FullPath)  

                    foreach ($Report in $FullReports) {
                        if ($Report.Include) {
                            $FullPathOther = [io.path]::Combine($PathToSubReports, $Report.FileName)
                            $Name = $Report.Name + ' - ' + $Report.Date
                            $FilePathsGenerated.Add($FullPathOther) 
                            if (-not $Report.SkipGeneration) {
                                New-HTMLReportPage -SubReport -Report $Report -FullReports $FullReports -FilePath $FullPathOther -PathToSubReports $PathToSubReports -Name $Name -HistoryReports $HistoryReports
                            } else {
                                Write-Color -Text '[i]', '[HTML ] ', "Skipping generation of ", $FullPathOther, ". generation not required..." -Color Yellow, DarkGray, Yellow
                            }
                        }
                    }
                }
                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 -Author "Przemyslaw Klys @ Evotec"
    }
    $TimeLogEndHTML = Stop-TimeLog -Time $TimeLogHTML -Option OneLiner
    Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report', " [Time to execute: $TimeLogEndHTML]" -Color Yellow, DarkGray, Yellow, DarkGray

    $FilePathsGenerated
}
function New-HTMLReportPage {
    [cmdletBinding()]
    param(
        [PSCustomObject] $Report,
        [Array] $FullReports,
        [Array] $HistoryReports,
        [string] $FilePath,
        [string] $PathToSubReports,
        [string] $Name,
        [switch] $SubReport
    )
    if ($SubReport) {
        Write-Color -Text '[i]', '[HTML ] ', "Generating HTML page ($MenuReport) sub report ($FilePath)" -Color Yellow, DarkGray, Yellow
    } else {
        Write-Color -Text '[i]', '[HTML ] ', "Generating HTML page ($MenuReport) report ($FilePath)" -Color Yellow, DarkGray, Yellow
    }
    New-HTMLPage -Name $Name -Title "The Dashboard - $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: ", $FullReports.Count -FontSize 12px
                    New-HTMLList {
                        if ($FullReports.Count -eq 1) {
                            New-HTMLListItem -Text "Date in report: ", $FullReports[0].Date -FontSize 12px -FontWeight normal, bold -TextDecoration none, underline
                        } else {
                            New-HTMLListItem -Text "Date ranges from: ", $FullReports[$FullReports.Count - 1].Date, " to ", $FullReports[0].Date -FontSize 12px -FontWeight normal, bold, normal, bold -TextDecoration none, underline, none, underline
                        }
                    }
                    if ($HistoryReports.Count) {
                        New-HTMLText -Text "History reports in this catagory: ", $HistoryReports.Count -FontSize 12px
                        New-HTMLList {
                            if ($HistoryReports.Count -gt 1) {
                                New-HTMLListItem -Text "Date ranges from: ", $HistoryReports[$FullReports.Count - 1].Date, " to ", $HistoryReports[0].Date -FontSize 12px -FontWeight normal, bold, normal, bold -TextDecoration none, underline, none, underline
                            } else {
                                New-HTMLListItem -Text "Date in report: ", $HistoryReports[0].Date -FontSize 12px -FontWeight normal, bold -TextDecoration none, underline
                            }
                        }
                    }
                } -Invisible
            }
            New-HTMLSection -Invisible {
                New-HTMLCalendar {
                    foreach ($CalendarEntry in $FullReports) {

                        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
                        }
                    }

                    foreach ($CalendarEntry in $HistoryReports) {

                        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.Href -TargetName 'iFrameWithContent'
                        } else {
                            New-CalendarEvent -Title $CalendarEntry.Name -StartDate $CalendarEntry.Date.AddMinutes(-30) -EndDate $($CalendarEntry.Date) -Url $CalendarEntry.Href -TargetName 'iFrameWithContent'
                        }
                    }
                } -HeaderRight @('dayGridMonth', 'timeGridWeek', 'timeGridDay', 'listMonth', 'listYear')
            }
        } -Height 300px
        New-HTMLSection -Invisible {

        } -Height 15px
        New-HTMLFrame -SourcePath $Report.Href -Scrolling Auto -Height 2000px -Name 'iFrameWithContent'
    } -FilePath $FilePath
}

$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 Remove-DiscardedReports {
    [CmdletBinding()]
    param(
        [Array] $FilePathsGenerated,
        [string] $FolderPath,
        [string] $Extension
    )
    $FilePathsCurrent = Get-ChildItem -LiteralPath $FolderPath -File -Filter "*$($Extension)" | Select-Object -ExpandProperty FullName
    foreach ($File in $FilePathsCurrent) {
        if ($File -notin $FilePathsGenerated) {
            Write-Color -Text '[i]', '[FILE ] ', "Removing discarded report: $File" -Color Yellow, DarkGray, Yellow
            Remove-Item -LiteralPath $File -Force
        }
    }
}
function Set-FolderConfiguration {
    [CmdletBinding()]
    param(
        [System.Collections.IDictionary]$Folders,
        [Array] $FoldersConfiguration,
        [System.Collections.IDictionary]$FolderLimit
    )
    foreach ($Folder in $FoldersConfiguration) {
        if (-not $Folder.Name -and $Folder.Url) {
            $Folder.Name = $Folder.Url
        } elseif (-not $Folder.Url -and $Folder.Name) {
            $Folder.Url = $Folder.Name
        }

        if ($FolderLimit -and $FolderLimit.Name -and -not $Folder.DisableGlobalLimits) {
            $Folder.LimitsConfiguration[$FolderLimit.Name] = $FolderLimit
        }
        $Folders[$Folder.Name] = $Folder
    }
}
function New-DashboardEmailParameter {
    [cmdletBinding(DefaultParameterSetName = 'Compatibility', SupportsShouldProcess)]
    param(
        [Parameter(ParameterSetName = 'SecureString')]

        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [alias('SmtpServer')][string] $Server,

        [Parameter(ParameterSetName = 'SecureString')]

        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [int] $Port,

        [Parameter(Mandatory, ParameterSetName = 'SecureString')]
        [Parameter(Mandatory, ParameterSetName = 'oAuth')]
        [Parameter(Mandatory, ParameterSetName = 'Graph')]
        [Parameter(Mandatory, ParameterSetName = 'MgGraphRequest')]
        [Parameter(Mandatory, ParameterSetName = 'Compatibility')]
        [Parameter(Mandatory, ParameterSetName = 'SendGrid')]
        [object] $From,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [Parameter(ParameterSetName = 'SendGrid')]
        [string] $ReplyTo,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [Parameter(ParameterSetName = 'SendGrid')]
        [alias('Importance')][ValidateSet('Low', 'Normal', 'High')][string] $Priority,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [ValidateSet('None', 'OnSuccess', 'OnFailure', 'Delay', 'Never')][string[]] $DeliveryNotificationOption,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [MailKit.Net.Smtp.DeliveryStatusNotificationType] $DeliveryStatusNotificationType,

        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(Mandatory, ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [Parameter(Mandatory, ParameterSetName = 'SendGrid')]
        [pscredential] $Credential,

        [Parameter(ParameterSetName = 'SecureString')]
        [string] $Username,

        [Parameter(ParameterSetName = 'SecureString')]
        [string] $Password,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [MailKit.Security.SecureSocketOptions] $SecureSocketOptions,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [switch] $UseSsl,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [switch] $SkipCertificateRevocation,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [alias('SkipCertificateValidatation')][switch] $SkipCertificateValidation,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [int] $Timeout,

        [Parameter(ParameterSetName = 'oAuth')]
        [alias('oAuth')][switch] $oAuth2,

        [Parameter(ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [switch] $RequestReadReceipt,

        [Parameter(ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [switch] $RequestDeliveryReceipt,

        [Parameter(ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [switch] $Graph,

        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [switch] $MgGraphRequest,

        [Parameter(ParameterSetName = 'SecureString')]
        [switch] $AsSecureString,

        [Parameter(ParameterSetName = 'SendGrid')]
        [switch] $SendGrid,

        [Parameter(ParameterSetName = 'SendGrid')]
        [switch] $SeparateTo,

        [Parameter(ParameterSetName = 'Graph')]
        [Parameter(ParameterSetName = 'MgGraphRequest')]
        [switch] $DoNotSaveToSentItems,

        [Parameter(ParameterSetName = 'SecureString')]
        [Parameter(ParameterSetName = 'oAuth')]
        [Parameter(ParameterSetName = 'Compatibility')]
        [string] $LocalDomain
    )

    $Output = [ordered] @{
        Type     = 'DashboardConfigurationEmail'
        Settings = [ordered] @{
            Server                         = if ($PSBoundParameters.ContainsKey('Server')) {
                $Server } else {
                $null }
            Port                           = if ($PSBoundParameters.ContainsKey('Port')) {
                $Port } else {
                $null }
            From                           = if ($PSBoundParameters.ContainsKey('From')) {
                $From } else {
                $null }
            ReplyTo                        = if ($PSBoundParameters.ContainsKey('ReplyTo')) {
                $ReplyTo } else {
                $null }
            Priority                       = if ($PSBoundParameters.ContainsKey('Priority')) {
                $Priority } else {
                $null }
            DeliveryNotificationOption     = if ($PSBoundParameters.ContainsKey('DeliveryNotificationOption')) {
                $DeliveryNotificationOption } else {
                $null }
            DeliveryStatusNotificationType = if ($PSBoundParameters.ContainsKey('DeliveryStatusNotificationType')) {
                $DeliveryStatusNotificationType } else {
                $null }
            Credential                     = if ($PSBoundParameters.ContainsKey('Credential')) {
                $Credential } else {
                $null }
            Username                       = if ($PSBoundParameters.ContainsKey('Username')) {
                $Username } else {
                $null }
            Password                       = if ($PSBoundParameters.ContainsKey('Password')) {
                $Password } else {
                $null }
            SecureSocketOptions            = if ($PSBoundParameters.ContainsKey('SecureSocketOptions')) {
                $SecureSocketOptions } else {
                $null }
            UseSsl                         = if ($PSBoundParameters.ContainsKey('UseSsl')) {
                $UseSsl } else {
                $null }
            SkipCertificateRevocation      = if ($PSBoundParameters.ContainsKey('SkipCertificateRevocation')) {
                $SkipCertificateRevocation } else {
                $null }
            SkipCertificateValidation      = if ($PSBoundParameters.ContainsKey('SkipCertificateValidatation')) {
                $SkipCertificateValidation } else {
                $null }
            Timeout                        = if ($PSBoundParameters.ContainsKey('Timeout')) {
                $Timeout } else {
                $null }
            oAuth2                         = if ($PSBoundParameters.ContainsKey('oAuth2')) {
                $oAuth2 } else {
                $null }
            RequestReadReceipt             = if ($PSBoundParameters.ContainsKey('RequestReadReceipt')) {
                $RequestReadReceipt } else {
                $null }
            RequestDeliveryReceipt         = if ($PSBoundParameters.ContainsKey('RequestDeliveryReceipt')) {
                $RequestDeliveryReceipt } else {
                $null }
            Graph                          = if ($PSBoundParameters.ContainsKey('Graph')) {
                $Graph } else {
                $null }
            MgGraphRequest                 = if ($PSBoundParameters.ContainsKey('MgGraphRequest')) {
                $MgGraphRequest } else {
                $null }
            AsSecureString                 = if ($PSBoundParameters.ContainsKey('AsSecureString')) {
                $AsSecureString } else {
                $null }
            SendGrid                       = if ($PSBoundParameters.ContainsKey('SendGrid')) {
                $SendGrid } else {
                $null }
            SeparateTo                     = if ($PSBoundParameters.ContainsKey('SeparateTo')) {
                $SeparateTo } else {
                $null }
            DoNotSaveToSentItems           = if ($PSBoundParameters.ContainsKey('DoNotSaveToSentItems')) {
                $DoNotSaveToSentItems } else {
                $null }
            WhatIf                         = $WhatIfPreference
        }
    }
    Remove-EmptyValue -Hashtable $Output.Settings
    $Output
}
function New-DashboardFolder {
    [alias('New-TheDashboardFolder')]
    [CmdletBinding()]
    param(
        [Parameter(Position = 0)][scriptblock] $Entries,
        [Parameter(Mandatory)][string] $Name,
        [Parameter(Mandatory)][string] $Path,
        [Parameter(Mandatory)][string] $UrlName,
        [string] $CopyFrom,
        [string] $MoveFrom,
        [switch] $DisableGlobalReplacement,
        [switch] $DisableGlobalLimits,
        # 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 ($Entries) {
        $ReplacementConfiguration = [System.Collections.Generic.List[System.Collections.IDictionary]]::new()
        $LimitsConfiguration = [ordered] @{}
        $OutputElements = & $Entries
        foreach ($E in $OutputElements) {
            if ($E.Type -eq 'Replacement') {
                $ReplacementConfiguration.Add($E.Settings)
            } elseif ($E.Type -eq 'FolderLimit') {
                $LimitsConfiguration[$E.Settings.Name] = $E.Settings
            }
        }
        $ReplacementsConfiguration = Convert-MultipleReplacements -ReplacementConfiguration $ReplacementConfiguration
    } else {
        $LimitsConfiguration = [ordered] @{}
        $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
            LimitsConfiguration = $LimitsConfiguration
            DisableGlobalLimits = $DisableGlobalLimits.IsPresent
        }
    }
    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-DashboardLimit {
    <#
    .SYNOPSIS
    Sets limit rules (date, days, item count) for dashboard reports.
 
    .DESCRIPTION
    Creates a structured object defining limits for how many reports to keep,
    how many to store in history, and date-based handling when displaying files.
 
    .PARAMETER Name
    Specifies which reports the limit applies to.
 
    .PARAMETER LimitItem
    Limits how many newest files are kept before moving to history.
 
    .PARAMETER LimitDate
    Specifies date threshold for including files in the menu.
 
    .PARAMETER LimitDays
    Specifies how many days back reports are displayed.
 
    .PARAMETER IncludeHistory
    Indicates whether older files are added to a history list instead of excluded.
 
    .PARAMETER IncludeHistoryLimitDate
    Date threshold after which history entries should not be included.
 
    .PARAMETER IncludeHistoryLimitDays
    Number of days to preserve history entries.
 
    .PARAMETER IncludeHistoryLimit
    Limits how many history entries are kept.
 
    .EXAMPLE
    New-DashboardLimit -LimitItem 3 -LimitDays 10
 
    .NOTES
    Part of TheDashboard module, used to configure file retention rules.
    #>

    [CmdletBinding()]
    param(
        [string] $Name = '*',
        [nullable[int]] $LimitItem,
        [nullable[DateTime]] $LimitDate,
        [nullable[int]] $LimitDays,
        [switch] $IncludeHistory,
        [nullable[DateTime]] $IncludeHistoryLimitDate,
        [nullable[int]] $IncludeHistoryLimitDays,
        [nullable[int]] $IncludeHistoryLimit
    )
    if ($IncludeHistoryLimitDate -or $IncludeHistoryLimitDays -or $IncludeHistoryLimit) {
        $IncludeHistory = $true
    }

    $Limit = [ordered] @{
        Type     = 'FolderLimit'
        Settings = [ordered] @{
            Name                    = $Name
            LimitItem               = $LimitItem
            LimitDate               = $LimitDate
            LimitDays               = $LimitDays
            IncludeHistory          = $IncludeHistory
            IncludeHistoryLimit     = $IncludeHistoryLimit
            IncludeHistoryLimitDate = $IncludeHistoryLimitDate
            IncludeHistoryLimitDays = $IncludeHistoryLimitDays
        }
    }

    Remove-EmptyValue -Hashtable $Limit.Settings
    $Limit
}
function New-DashboardNotification {
    [CmdletBinding(DefaultParameterSetName = 'Report')]
    param(
        [Parameter(ParameterSetName = 'Report')][string] $Name,
        [Parameter(ParameterSetName = 'Report')][string] $Category,
        [string] $Type,
        [string] $Filter,
        [Parameter(Mandatory)][string] $EmailTo,
        [Parameter()][string] $EmailCC,
        [Parameter(Mandatory)][string] $EmailSubject
    )

    $Notification = [ordered] @{
        Type     = 'Notification'
        Settings = [ordered] @{
            Id           = [Guid]::NewGuid().ToString()
            Name         = $Name
            Category     = $Category
            Type         = $Type
            Filter       = $Filter
            EmailTo      = $EmailTo
            EmailCC      = $EmailCC
            EmailSubject = $EmailSubject
        }
    }
    Remove-EmptyValue -Hashtable $Notification
    $Notification
}
function New-DashboardReplacement {
    [alias('New-TheDashboardReplacement')]
    [CmdletBinding()]
    param(
        [string] $SplitOn,
        [Array] $BeforeSplit,
        [alias('RemoveCharsBefore')][string[]] $BeforeRemoveChars,
        [Array] $AfterSplit,
        [alias('AfterAddSpaceToName')][switch] $AddSpaceToName,
        [object] $AfterSplitPositionName,
        [alias('RemoveCharsAfter')][string[]] $AfterRemoveChars,
        [alias('ConvertToUpperChars')][string[]] $AfterUpperChars,
        [alias('RemoveDoubleSpaces')][switch] $AfterRemoveDoubleSpaces
    )

    $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 }
            AfterSplitPositionName  = if ($PSBoundParameters.ContainsKey('AfterSplitPositionName')) {
                $AfterSplitPositionName } else {
                $null }
            AfterRemoveChars        = if ($PSBoundParameters.ContainsKey('AfterRemoveChars')) {
                $AfterRemoveChars } else {
                $null }
            AfterUpperChars         = if ($PSBoundParameters.ContainsKey('AfterUpperChars')) {
                $AfterUpperChars } else {
                $null }
            AfterRemoveDoubleSpaces = if ($PSBoundParameters.ContainsKey('AfterRemoveDoubleSpaces')) {
                $AfterRemoveDoubleSpaces } else {
                $null }
            BeforeRemoveChars       = if ($PSBoundParameters.ContainsKey('BeforeRemoveChars')) {
                $BeforeRemoveChars } else {
                $null }
        }
    }
    $Replacements
}
function Repair-DashboardContent {
    <#
    .SYNOPSIS
    This function helps to replace content in files with a specific extension in a specific directory with a new content.
 
    .DESCRIPTION
    This function helps to replace content in files with a specific extension in a specific directory with a new content.
 
    .PARAMETER Directory
    Directory where files are located
 
    .PARAMETER ExtensionFrom
    File extension to look for. Default is .aspx
 
    .EXAMPLE
    $SearchString = "_|:|@|#|<-|←|<:|<%|=|=>|⇒|>:"
    $ReplaceString = "_|:|@|#|<-|←|<:|<-%|=|=>|⇒|>:"
    $Directory = "C:\Users\przemyslaw.klys\Downloads"
 
    Repair-ReportContent -Directory $Directory -Search $SearchString -Replace $ReplaceString -EscapeRegex
 
    .EXAMPLE
    $SearchString = '<meta http-equiv="Content-Security-Policy".*?/>'
    $ReplaceString = ''
    $Directory = "C:\Support\GitHub\TheDashboard\Examples\Reports\Security"
 
    Repair-ReportContent -Directory $Directory -Search $SearchString -Replace $ReplaceString
 
    .NOTES
    This is a fix for a SharePoint error that occurs when a string contains "<%"
    - Sorry, something went wrong. An error occurred during the processing of /sites/TheDashboard/Shared Documents/Gpozaurr_GPOBrokenPartially_2024-03-27_025637.aspx. The server block is not well formed.
    The reports created by several scripts contain "<%" in the string, which is not allowed in SharePoint. This is used by the Enlighter.JS library and shows up when not using -Online switch.
    Since the enlighter.js library is put inside HTML directly it causes issues with SharePoint.
    The script will replace "<%" with "<-%" in all files with the .aspx extension in the Reports folder.
 
    This is also a fix for PingCastle reports that contain characters that block it from hosting on Sharepoint or IIS (<meta http-equiv="Content-Security-Policy".*?/>)
 
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [parameter(Mandatory)][string] $Directory,
        [string] $ExtensionFrom = '.aspx',
        [string] $Search,
        [string] $Replace,
        [switch] $EscapeRegex,
        [int] $OnlyNewerThan,
        [switch] $AddOneMinute
    )

    if ($EscapeRegex) {
        $SearchString = [regex]::Escape($Search)
        $ReplaceString = [regex]::Escape($Replace)
    } else {
        $SearchString = $Search
        $ReplaceString = $Replace
    }

    if (-not (Test-Path -Path $Directory)) {
        Write-Color -Text '[i]', "[TheDashboard] ", "Directory $Directory does not exist" -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
        return
    }
    $Files = Get-ChildItem -Path $Directory -File -Recurse -Include "*$ExtensionFrom"
    foreach ($File in $Files) {
        if ($File.Extension -eq $ExtensionFrom) {
            if ($OnlyNewerThan -and $File.LastWriteTime -lt (Get-Date).AddDays(-$OnlyNewerThan)) {

                continue
            }
            Write-Color -Text '[i]', "[TheDashboard] ", "Processing fixes $($File.FullName) / $($File.LastWriteTime)" -Color Yellow, DarkGray, Yellow, DarkGray, Magenta

            $originalCreationTime = $File.CreationTime
            $originalLastWriteTime = $File.LastWriteTime

            $Encoding = Get-FileEncoding -Path $File.FullName
            if ($PSVersionTable.PSVersion.Major -ge 7) {
                $FileContent = Get-Content -Raw -Path $File.FullName -Encoding $Encoding
            } else {

                if ($Encoding -eq 'UTF8BOM') {
                    $Encoding = 'UTF8'
                }
                $FileContent = Get-Content -Raw -Path $File.FullName -Encoding $Encoding
            }
            if ($FileContent -match $SearchString) {
                Write-Color -Text '[i]', "[TheDashboard] ", "Processing fixes $($File.FullName) for ($SearchString)" -Color Green
                $NewContent = $FileContent -replace $SearchString, $ReplaceString
                $NewContent | Set-Content -Path $File.FullName -Encoding $Encoding

                $item = Get-Item $File.FullName
                $item.CreationTime = $originalCreationTime
                if ($AddOneMinute) {
                    $item.LastWriteTime = $originalLastWriteTime.AddMinutes(1)
                } else {
                    $item.LastWriteTime = $originalLastWriteTime
                }
            }
        }
    }
}
function Repair-DashboardExtension {
    <#
    .SYNOPSIS
    This function renames the extension of files in a given directory.
 
    .DESCRIPTION
    The Repair-DashboardExtension function is used to rename the extension of files in a specified directory from one extension to another.
    It's a part of the process of converting the reports to a SharePoint compatible format.
 
    .PARAMETER Path
    The path to the directory containing the files whose extensions are to be renamed.
 
    .PARAMETER ExtensionFrom
    The current extension of the files to be renamed.
 
    .PARAMETER ExtensionTo
    The new extension to be given to the files.
 
    .EXAMPLE
    Repair-DashboardExtension -Path "C:\Reports" -ExtensionFrom ".html" -ExtensionTo ".aspx"
    This command renames the extension of all .html files in the C:\Reports directory to .aspx.
 
    .NOTES
    If a file with the new name already exists in the directory, the function will skip renaming that file.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)][string] $Path,
        [Parameter(Mandatory)][string] $ExtensionFrom,
        [Parameter(Mandatory)][string] $ExtensionTo
    )

    if (-not (Test-Path -Path $Path)) {
        Write-Color -Text '[i]', "[TheDashboard] ", "Directory $Path does not exist" -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
        return
    }
    $Files = Get-ChildItem -Path $Path -File -Recurse -Include "*$ExtensionFrom"
    foreach ($File in $Files) {
        if ($File.Extension -eq $ExtensionFrom) {
            Write-Color -Text '[i]', "[TheDashboard] ", "Processing rename $($File.FullName) / $($File.LastWriteTime)" -Color Yellow, DarkGray, Yellow, DarkGray, Magenta

            $NewName = $File.FullName -replace "$($ExtensionFrom)$", $ExtensionTo

            $ExpectedName = [io.path]::Combine($File.DirectoryName, $NewName)
            if (Test-Path -LiteralPath $ExpectedName) {
                Write-Color -Text "[i]", "[TheDashboard] ", "File already exists: $($ExpectedName). Skipping" -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
                continue
            } else {
                if ($PSCmdlet.ShouldProcess($File.FullName, "Rename to $NewName")) {
                    Rename-Item -Path $File.FullName -NewName $NewName -Force
                }
            }
        }
    }
}
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 UrlPath
    URL that will be used as a starting point for TheDashboard, and used by all the links.
    By default the URL uses relative path, but it can be changed to absolute path.
    This is useful for example when you want to use TheDashboard on a SharePoint site, where the files are stored in a different place.
 
    .PARAMETER Replacements
    Replacements that will be used to replace names within TheDashboard.
 
    .PARAMETER RemoveNotIncluded
    Removes files that are not included in the menu.
    This is useful to clean up files that are not displayed, but be careful during testing.
 
    .PARAMETER DeleteMethod
    Specifies how files are removed when they are not included in the menu.
    By default, files are moved to the Recycle Bin.
    All options are: RemoveItem, DotNetDelete, RecycleBin.
 
    .PARAMETER TestMode
    Pretends to generate TheDashboard, but does not actually generate it.
    Other processes are executed, but no HTML files are created.
    This is useful for testing along with PassThru parameter, which will return all the data that would be used to generate 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 PassThru
    Returns the object that was generated by the script.
 
    .PARAMETER LogPath
    Path to log file where all actions will be logged
 
    .PARAMETER LogMaximum
    Maximum number of log files to keep. If 0 then unlimited. Default unlimited.
    Please keep in mind that this will only work if the logs are in the dedicated folder.
    If you use the same folder as the script, then logging deletion will be disabled.
 
    .PARAMETER LogShowTime
    Show time in console output. Default $false. Logs will always have time.
 
    .PARAMETER LogTimeFormat
    Time format to use in log file. Default "yyyy-MM-dd HH:mm:ss"
 
    .EXAMPLE
    An example
 
    .NOTES
    General notes
    #>

    [cmdletBinding(SupportsShouldProcess)]
    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] $RemoveNotIncluded,
        [ValidateSet("RemoveItem", "DotNetDelete", "RecycleBin")]
        [string] $DeleteMethod = "RecycleBin",
        [Uri] $UrlPath,
        [switch] $ShowHTML,
        [switch] $Online,
        [switch] $PassThru,
        [switch] $TestMode,
        [string] $LogPath,
        [int] $LogMaximum,
        [switch] $LogShowTime,
        [string] $LogTimeFormat
    )
    $Script:Reporting = [ordered] @{}
    $Script:Reporting['Version'] = Get-GitHubVersion -Cmdlet 'Start-TheDashboard' -RepositoryOwner 'evotecit' -RepositoryName 'TheDashboard'

    Set-LoggingCapabilities -LogPath $LogPath -LogMaximum $LogMaximum -ShowTime:$LogShowTime -TimeFormat $LogTimeFormat -ScriptPath $MyInvocation.ScriptName -ParameterPSDefaultParameterValues $Script:PSDefaultParameterValues

    Write-Color '[i]', "[TheDashboard] ", 'Version', ' [Informative] ', $Script:Reporting['Version'] -Color Yellow, DarkGray, Yellow, DarkGray, Magenta

    if ($TestMode) {
        Write-Color -Text '[i]', "[TheDashboard] ", 'TestMode enabled', ' [Informative] ' -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
        $WhatIfPreference = $true
    }
    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()
    $FolderLimit = [ordered] @{}

    $convertNestedElementsSplat = @{
        Elements                 = $Elements
        GageConfiguration        = $GageConfiguration
        FoldersConfiguration     = $FoldersConfiguration
        ReplacementConfiguration = $ReplacementConfiguration
        FolderLimit              = $FolderLimit
    }

    Convert-NestedElements @convertNestedElementsSplat

    $Extension = [io.path]::GetExtension($HTMLPath)
    $FolderPath = [io.path]::GetDirectoryName($HTMLPath)

    $ExportData = Import-DashboardStatistics -StatisticsPath $StatisticsPath

    $Replacements = Convert-MultipleReplacements -Replacements $Replacements -ReplacementConfiguration $ReplacementConfiguration

    Set-FolderConfiguration -Folders $Folders -FoldersConfiguration $FoldersConfiguration -FolderLimit $FolderLimit

    Copy-HTMLFiles -Folders $Folders -Extension $Extension

    $Files = Convert-FilesToMenuData -Folders $Folders -Replacements $Replacements -Extension $Extension

    $MenuBuilder = Convert-FilesToMenu -Files $Files -Folders $Folders -ExportData $ExportData

    $FilePathsGenerated = New-HTMLReport -OutputElements $GageConfiguration -Logo $Logo -MenuBuilder $MenuBuilder -Configuration $Configuration -ExportData $ExportData -Files $Files -ShowHTML:$ShowHTML.IsPresent -HTMLPath $HTMLPath -Online:$Online.IsPresent -Force:$Force.IsPresent -Extension $Extension -UrlPath $UrlPath -Pretend:$TestMode.IsPresent
    Remove-DiscardedReports -FilePathsGenerated $FilePathsGenerated -FolderPath $FolderPath -Extension $Extension

    $FilesToKeepOrRemove = Convert-FilesToKeepOrRemove -FilePathsGenerated $FilePathsGenerated -Files $Files -DeleteMethod $DeleteMethod -RemoveNotIncluded:$RemoveNotIncluded.IsPresent -WhatIf:$WhatIfPreference

    if ($PassThru) {
        [ordered] @{
            FilesToKeepOrRemove = $FilesToKeepOrRemove
            Folders             = $Folders
            Extension           = $Extension
            Files               = $Files
            MenuBuilder         = $MenuBuilder
            Statistics          = $ExportData.Statistics
            StatisticsPath      = $StatisticsPath
            Replacements        = $Replacements
            FilePathsGenerated  = $FilePathsGenerated
        }
    }

    $ExportData['MenuBuilder'] = $MenuBuilder

    if ($StatisticsPath) {
        try {
            $ExportData | Export-Clixml -Depth 5 -LiteralPath $StatisticsPath -ErrorAction Stop -WhatIf:$false
        } catch {
            Write-Color -Text '[e]', "[TheDashboard] ", 'Failed to export statistics', ' [Error] ', $_.Exception.Message -Color Yellow, DarkGray, Yellow, DarkGray, Red
        }
    }
    Write-Color -Text '[i]', "[TheDashboard] ", 'Done', ' [Informative] ' -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
}

Export-ModuleMember -Function @('New-DashboardEmailParameter', 'New-DashboardFolder', 'New-DashboardGage', 'New-DashboardLimit', 'New-DashboardNotification', 'New-DashboardReplacement', 'Repair-DashboardContent', 'Repair-DashboardExtension', 'Start-TheDashboard') -Alias @('New-TheDashboardFolder', 'New-TheDashboardGage', 'New-TheDashboardReplacement')
# SIG # Begin signature block
# MIItqwYJKoZIhvcNAQcCoIItnDCCLZgCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB7SszmL4YHYhGx
# VA8Or1CnfSMnOowqkxhZP4tZYWur46CCJq4wggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggWQMIIDeKADAgECAhAFmxtXno4hMuI5B72nd3VcMA0GCSqG
# SIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH
# NDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIw
# aTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLK
# EdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4Tm
# dDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembu
# d8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnD
# eMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1
# XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVld
# QnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTS
# YW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSm
# M9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzT
# QRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6Kx
# fgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
# VR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzANBgkq
# hkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNkaA9Wz3eucPn9mkqZucl4
# XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjSPMFDQK4dUPVS/JA7u5iZ
# aWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK7VB6fWIhCoDIc2bRoAVg
# X+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eBcg3AFDLvMFkuruBx8lbk
# apdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp5aPNoiBB19GcZNnqJqGL
# FNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msgdDDS4Dk0EIUhFQEI6FUy
# 3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vriRbgjU2wGb2dVf0a1TD9u
# KFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ79ARj6e/CVABRoIoqyc54
# zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5nLGbsQAe79APT0JsyQq8
# 7kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3i0objwG2J5VT6LaJbVu8
# aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0HEEcRrYc9B9F1vM/zZn4w
# ggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH
# NDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVT
# MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1
# c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqG
# SIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbS
# g9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9
# /UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXn
# HwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0
# VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4f
# sbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40Nj
# gHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0
# QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvv
# mz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T
# /jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk
# 42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5r
# mQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E
# FgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5n
# P+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcG
# CCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu
# Y29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln
# aUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8v
# Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNV
# HSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIB
# AH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxp
# wc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIl
# zpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQ
# cAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfe
# Kuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+j
# Sbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJsh
# IUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6
# OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDw
# N7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR
# 81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2
# VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIGsDCCBJigAwIBAgIQ
# CK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQGEwJVUzEV
# MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t
# MSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjEwNDI5MDAw
# MDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln
# aUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBT
# aWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjANBgkqhkiG9w0BAQEF
# AAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zrPYGXcMW7xIUmMJ+k
# jmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHMgQM+TXAkZLON4gh9
# NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8IrgnQnAZaf6mIBJNYc9
# URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyCEUhSaN4QvRRXXegY
# E2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0p6MDDnSlrzm2q2AS
# 4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQakhCBj7A7CdfHmzJa
# wv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0XLyTRSiDNipmKF+w
# c86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960IHnWmZcy740hQ83eR
# Gv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2FKZbS110YU0/EpF2
# 3r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBHX8mBUHOFECMhWWCK
# ZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q27IwyCQLMbDwMVhEC
# AwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGg34Ou2
# O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P
# MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB3BggrBgEFBQcB
# AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr
# BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1
# c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwHAYDVR0gBBUwEzAH
# BgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIBADojRD2NCHbuj7w6
# mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6jfCbVN7w6XUhtldU/
# SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmImoqKwba9oUgYftzY
# gBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtfJqGVWEjVGv7XJz/9
# kNF2ht0csGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrxoj7bQ7gzyE84FJKZ
# 9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3LIU/Gs4m6Ri+kAew
# Q3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx4b6cpwoG1iZnt5Lm
# Tl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9Oj9FpsToFpFSi0HA
# SIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+ICw2/O/TOHnuO77Xr
# y7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug0wcCampAMEhLNKhR
# ILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5Vzu0nAPthkX0tGFu
# v2jiJmCG6sivqf6UHedjGzqGVnhOMIIGvDCCBKSgAwIBAgIQC65mvFq6f5WHxvnp
# BOMzBDANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln
# aUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5
# NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTI0MDkyNjAwMDAwMFoXDTM1MTEy
# NTIzNTk1OVowQjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSAwHgYD
# VQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQAD
# ggIPADCCAgoCggIBAL5qc5/2lSGrljC6W23mWaO16P2RHxjEiDtqmeOlwf0KMCBD
# Er4IxHRGd7+L660x5XltSVhhK64zi9CeC9B6lUdXM0s71EOcRe8+CEJp+3R2O8oo
# 76EO7o5tLuslxdr9Qq82aKcpA9O//X6QE+AcaU/byaCagLD/GLoUb35SfWHh43rO
# H3bpLEx7pZ7avVnpUVmPvkxT8c2a2yC0WMp8hMu60tZR0ChaV76Nhnj37DEYTX9R
# eNZ8hIOYe4jl7/r419CvEYVIrH6sN00yx49boUuumF9i2T8UuKGn9966fR5X6kgX
# j3o5WHhHVO+NBikDO0mlUh902wS/Eeh8F/UFaRp1z5SnROHwSJ+QQRZ1fisD8UTV
# DSupWJNstVkiqLq+ISTdEjJKGjVfIcsgA4l9cbk8Smlzddh4EfvFrpVNnes4c16J
# idj5XiPVdsn5n10jxmGpxoMc6iPkoaDhi6JjHd5ibfdp5uzIXp4P0wXkgNs+CO/C
# acBqU0R4k+8h6gYldp4FCMgrXdKWfM4N0u25OEAuEa3JyidxW48jwBqIJqImd93N
# Rxvd1aepSeNeREXAu2xUDEW8aqzFQDYmr9ZONuc2MhTMizchNULpUEoA6Vva7b1X
# CB+1rxvbKmLqfY/M/SdV6mwWTyeVy5Z/JkvMFpnQy5wR14GJcv6dQ4aEKOX5AgMB
# AAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUB
# Af8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1s
# BwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFJ9X
# LAN3DigVkGalY17uT5IfdqBbMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwz
# LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1l
# U3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhho
# dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNl
# cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZU
# aW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAD2tHh92mVvjOIQS
# R9lDkfYR25tOCB3RKE/P09x7gUsmXqt40ouRl3lj+8QioVYq3igpwrPvBmZdrlWB
# b0HvqT00nFSXgmUrDKNSQqGTdpjHsPy+LaalTW0qVjvUBhcHzBMutB6HzeledbDC
# zFzUy34VarPnvIWrqVogK0qM8gJhh/+qDEAIdO/KkYesLyTVOoJ4eTq7gj9UFAL1
# UruJKlTnCVaM2UeUUW/8z3fvjxhN6hdT98Vr2FYlCS7Mbb4Hv5swO+aAXxWUm3Wp
# ByXtgVQxiBlTVYzqfLDbe9PpBKDBfk+rabTFDZXoUke7zPgtd7/fvWTlCs30VAGE
# sshJmLbJ6ZbQ/xll/HjO9JbNVekBv2Tgem+mLptR7yIrpaidRJXrI+UzB6vAlk/8
# a1u7cIqV0yef4uaZFORNekUgQHTqddmsPCEIYQP7xGxZBIhdmm4bhYsVA6G2WgNF
# YagLDBzpmk9104WQzYuVNsxyoVLObhx3RugaEGru+SojW4dHPoWrUhftNpFC5H7Q
# EY7MhKRyrBe7ucykW7eaCuWBsBb4HOKRFVDcrZgdwaSIqMDiCLg4D+TPVgKx2EgE
# deoHNHT9l3ZDBD+XgbF+23/zBjeCtxz+dL/9NWR6P2eZRi7zcEO1xwcdcqJsyz/J
# ceENc2Sg8h3KeFUCS7tpFk7CrDqkMIIHXzCCBUegAwIBAgIQB8JSdCgUotar/iTq
# F+XdLjANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln
# aUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBT
# aWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMB4XDTIzMDQxNjAwMDAwMFoX
# DTI2MDcwNjIzNTk1OVowZzELMAkGA1UEBhMCUEwxEjAQBgNVBAcMCU1pa2/FgsOz
# dzEhMB8GA1UECgwYUHJ6ZW15c8WCYXcgS8WCeXMgRVZPVEVDMSEwHwYDVQQDDBhQ
# cnplbXlzxYJhdyBLxYJ5cyBFVk9URUMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
# ggIKAoICAQCUmgeXMQtIaKaSkKvbAt8GFZJ1ywOH8SwxlTus4McyrWmVOrRBVRQA
# 8ApF9FaeobwmkZxvkxQTFLHKm+8knwomEUslca8CqSOI0YwELv5EwTVEh0C/Daeh
# vxo6tkmNPF9/SP1KC3c0l1vO+M7vdNVGKQIQrhxq7EG0iezBZOAiukNdGVXRYOLn
# 47V3qL5PwG/ou2alJ/vifIDad81qFb+QkUh02Jo24SMjWdKDytdrMXi0235CN4Rr
# W+8gjfRJ+fKKjgMImbuceCsi9Iv1a66bUc9anAemObT4mF5U/yQBgAuAo3+jVB8w
# iUd87kUQO0zJCF8vq2YrVOz8OJmMX8ggIsEEUZ3CZKD0hVc3dm7cWSAw8/FNzGNP
# lAaIxzXX9qeD0EgaCLRkItA3t3eQW+IAXyS/9ZnnpFUoDvQGbK+Q4/bP0ib98XLf
# QpxVGRu0cCV0Ng77DIkRF+IyR1PcwVAq+OzVU3vKeo25v/rntiXCmCxiW4oHYO28
# eSQ/eIAcnii+3uKDNZrI15P7VxDrkUIc6FtiSvOhwc3AzY+vEfivUkFKRqwvSSr4
# fCrrkk7z2Qe72Zwlw2EDRVHyy0fUVGO9QMuh6E3RwnJL96ip0alcmhKABGoIqSW0
# 5nXdCUbkXmhPCTT5naQDuZ1UkAXbZPShKjbPwzdXP2b8I9nQ89VSgQIDAQABo4IC
# AzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYE
# FHrxaiVZuDJxxEk15bLoMuFI5233MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK
# BggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEz
# ODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0Rp
# Z2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5j
# cmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3
# dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcw
# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8v
# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu
# Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEB
# CwUAA4ICAQC3EeHXUPhpe31K2DL43Hfh6qkvBHyR1RlD9lVIklcRCR50ZHzoWs6E
# BlTFyohvkpclVCuRdQW33tS6vtKPOucpDDv4wsA+6zkJYI8fHouW6Tqa1W47YSrc
# 5AOShIcJ9+NpNbKNGih3doSlcio2mUKCX5I/ZrzJBkQpJ0kYha/pUST2CbE3JroJ
# f2vQWGUiI+J3LdiPNHmhO1l+zaQkSxv0cVDETMfQGZKKRVESZ6Fg61b0djvQSx51
# 0MdbxtKMjvS3ZtAytqnQHk1ipP+Rg+M5lFHrSkUlnpGa+f3nuQhxDb7N9E8hUVev
# xALTrFifg8zhslVRH5/Df/CxlMKXC7op30/AyQsOQxHW1uNx3tG1DMgizpwBasrx
# h6wa7iaA+Lp07q1I92eLhrYbtw3xC2vNIGdMdN7nd76yMIjdYnAn7r38wwtaJ3KY
# D0QTl77EB8u/5cCs3ShZdDdyg4K7NoJl8iEHrbqtooAHOMLiJpiL2i9Yn8kQMB6/
# Q6RMO3IUPLuycB9o6DNiwQHf6Jt5oW7P09k5NxxBEmksxwNbmZvNQ65Zn3exUAKq
# G+x31Egz5IZ4U/jPzRalElEIpS0rgrVg8R8pEOhd95mEzp5WERKFyXhe6nB6bSYH
# v8clLAV0iMku308rpfjMiQkqS3LLzfUJ5OHqtKKQNMLxz9z185UCszGCBlMwggZP
# AgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEw
# PwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2
# IFNIQTM4NCAyMDIxIENBMQIQB8JSdCgUotar/iTqF+XdLjANBglghkgBZQMEAgEF
# AKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgor
# BgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3
# DQEJBDEiBCD+dD9/fPUdbR7HBJrjKSessY7AGS0o5gmca34S0RyjjDANBgkqhkiG
# 9w0BAQEFAASCAgBTdrS9qrPZYxEbm+AB9SbZdQWKjDs9q6RAcXTAyyuQw6as+tVT
# fr6vFM64+P8aQn0w82Vn9ZjlGbZs4s+xBLQNTDSReUcz+DY9PkArs/NDUNidJW3l
# LoPeoCJAU37rRYVuFVrExgeHxMz2KRea0nD22oTLNQV25PtrR3Avct1jAb+aC0v4
# D1GNJ6KE+d2ozUrSe7v07MUD4uhmxmRuZhW9ErPLcM5BwrNuY7Ul6h0v+2JVCMa+
# lxjSs82UysntkO3w9Bm09bTsuDynnTgEDe9U9S0vTF+59D1ICOxksJPxsEH8lqMh
# 8XxQq1ce2xNXnhbGbrWuwVeNgCTZj0AgTi0F59xiZs9XiFdqZcR3hl7xXH1zVkGP
# zYUFdb5fiGkbPwEKDx9tyROVCH5xDqiVJY4j4uyiNPw1+q4Df3vBPqTPiTrlv0OK
# XXrzhSXjxnds5Nwv9ERZGcLqTPDuGFkwLIj4sEg8zkLGmMEHPxXXE3P99rtAS/Mm
# U285keUJ/Sa25XGmbrKz4AMNOBZ3pBFwH+eaMg/i89itmHE/Mur25rIsRqL3EI23
# vR/5kJ33gUkeIdAnQe9EpNxUJzFcZ5sIvE8rlqPUnI7EC6zt7lu9GYTHYXURpg81
# vCY7miLDCq8Bin9b2fGSZ6XLT07f3PGl6lbtCNGGJhQIDOX5cx0ixcN17aGCAyAw
# ggMcBgkqhkiG9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYD
# VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH
# NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAuuZrxaun+Vh8b56QTj
# MwQwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG
# CSqGSIb3DQEJBTEPFw0yNTAxMjQxNTQ5MzBaMC8GCSqGSIb3DQEJBDEiBCCwfGi/
# Jt9qMNUW03OaZUDGSuyYERQneIx3sh/aOEujGzANBgkqhkiG9w0BAQEFAASCAgCK
# z4F+pEQ/JJsp9gAmzC8x61QwejwYW720RzFRbiJIpOEP0TyHeSk827khE5MucKkw
# K6+ArVE2AlAANjQBV3el0yukWKQoCbRexvdm0EII1LR0Y7g+1L8IoRZdFY+ns46X
# CK8SBigImZ8b2rEHvmia2tOp4+xvNCspoE7syiVestX1PT3aLtQ9Jh3Vo0rGrdiO
# NS2un8Bbv2eXBrk5c43Cd1LQEPs/Po99V7uWyKO20RiInrxc/TZ4ZEK+YXlPuZSO
# LLAXiJuy8s90vXWMuhYVyLXwHrjxVdRVr2mHR0wCb24VplgqrKRU5iqJm2KZ3+lG
# rYkw5JODF7XU0WPGw0754qMK5R+OVsKDxDcYnYklhj4i0UyBB3qKrhMf7EAwk5cN
# YWVyRLmmt0TFhId8QZygbv+c1kkrURmEIUmkoEqq2jtUokrARNtcDSuQOLRY1vB1
# BkdT8pf/lJsi09V1duPd7Z1+wQX4oI6ADleytRgMrdayfr8dX/F5yPDROsSAPWEU
# HQ/px4P1QkJNjU/a/0Bf0Vf30rj3OihDpmVXZq+calJDCAykPF4HpGEmnji4WS3b
# c7UjOOFU8JTFZ9Ordjmwy0uu6GbAwFEEGNpji8P9aHCOfqugbvuitLpjnTr3mByV
# N0vqeU8lIi/yiktWsNUqRic9xcPSEum30VASg08kHQ==
# SIG # End signature block