PSWriteHTML.psm1

function Add-CustomFormatForDatetimeSorting {
    <#
    .SYNOPSIS
     
    .DESCRIPTION
        This function adds code to make the datatable columns sortable with different datetime formats.
        Formatting:
        Day (of Month)
        D - 1 2 ... 30 31
        Do - 1st 2nd ... 30th 31st
        DD - 01 02 ... 30 31
         
        Month
        M - 1 2 ... 11 12
        Mo - 1st 2nd ... 11th 12th
        MM - 01 02 ... 11 12
        MMM - Jan Feb ... Nov Dec
        MMMM - January February ... November December
 
        Year
        YY - 70 71 ... 29 30
        YYYY - 1970 1971 ... 2029 2030
 
        Hour
        H - 0 1 ... 22 23
        HH - 00 01 ... 22 23
        h - 1 2 ... 11 12
        hh - 01 02 ... 11 12
 
        Minute
        m - 0 1 ... 58 59
        mm - 00 01 ... 58 59
 
        Second
        s - 0 1 ... 58 59
        ss - 00 01 ... 58 59
 
        More formats
        http://momentjs.com/docs/#/displaying/
 
    .PARAMETER CustomDateTimeFormat
        Array with strings of custom datetime format.
        The string is build from two parts. Format and locale. Locale is optional.
        format explanation: http://momentjs.com/docs/#/displaying/
        locale explanation: http://momentjs.com/docs/#/i18n/
 
 
    .LINK
        format explanation: http://momentjs.com/docs/#/displaying/
        locale explanation: http://momentjs.com/docs/#/i18n/
    .Example
        Add-CustomFormatForDatetimeSorting -CustomDateFormat 'dddd, MMMM Do, YYYY','HH:mm MMM D, YY'
    .Example
        Add-CustomFormatForDatetimeSorting -CustomDateFormat 'DD.MM.YYYY HH:mm:ss'
    #>

    [CmdletBinding()]
    param([array]$DateTimeSortingFormat)
    if ($Script:Output) { Remove-Variable Output -Scope Script }
    if ($DateTimeSortingFormat) { [array]$Script:Output = foreach ($format in $DateTimeSortingFormat) { "$.fn.dataTable.moment( '$format' );" } }
    else { $Script:Output = "$.fn.dataTable.moment( 'L' );" }
    return $Script:Output
}
function Add-TableFiltering {
    [CmdletBinding()]
    param([bool] $Filtering,
        [ValidateSet('Top', 'Bottom', 'Both')][string]$FilteringLocation = 'Bottom')
    $Output = @{ }
    if ($Filtering) {
        if ($FilteringLocation -eq 'Bottom') {
            $Output.FilteringTopCode = @"
                // Setup - add a text input to each footer cell
                `$('#$DataTableName tfoot th').each(function () {
                    var title = `$(this).text();
                    `$(this).html('<input type="text" placeholder="' + title + '" />');
                });
"@

            $Output.FilteringBottomCode = @"
                // Apply the search for footer cells
                table.columns().every(function () {
                    var that = this;
 
                    `$('input', this.footer()).on('keyup change', function () {
                        if (that.search() !== this.value) {
                            that.search(this.value).draw();
                        }
                    });
                });
"@

        } elseif ($FilteringLocation -eq 'Both') {
            $Output.FilteringTopCode = @"
                // Setup - add a text input to each header cell
                `$('#$DataTableName thead th').each(function () {
                    var title = `$(this).text();
                    `$(this).html('<input type="text" placeholder="' + title + '" />');
                });
                // Setup - add a text input to each footer cell
                `$('#$DataTableName tfoot th').each(function () {
                    var title = `$(this).text();
                    `$(this).html('<input type="text" placeholder="' + title + '" />');
                });
"@

            $Output.FilteringBottomCode = @"
                // Apply the search for header cells
                table.columns().eq(0).each(function (colIdx) {
                    `$('input', table.column(colIdx).header()).on('keyup change', function () {
                        table
                            .column(colIdx)
                            .search(this.value)
                            .draw();
                    });
 
                    `$('input', table.column(colIdx).header()).on('click', function (e) {
                        e.stopPropagation();
                    });
                });
                // Apply the search for footer cells
                table.columns().every(function () {
                    var that = this;
 
                    `$('input', this.footer()).on('keyup change', function () {
                        if (that.search() !== this.value) {
                            that.search(this.value).draw();
                        }
                    });
                });
"@

        } else {
            $Output.FilteringTopCode = @"
                // Setup - add a text input to each header cell
                `$('#$DataTableName thead th').each(function () {
                    var title = `$(this).text();
                    `$(this).html('<input type="text" placeholder="' + title + '" />');
                });
"@

            $Output.FilteringBottomCode = @"
                // Apply the search for header cells
                table.columns().eq(0).each(function (colIdx) {
                    `$('input', table.column(colIdx).header()).on('keyup change', function () {
                        table
                            .column(colIdx)
                            .search(this.value)
                            .draw();
                    });
 
                    `$('input', table.column(colIdx).header()).on('click', function (e) {
                        e.stopPropagation();
                    });
                });
"@

        }
    } else { $Output.FilteringTopCode = $Output.FilteringBottomCode = '' }
    return $Output
}
function Add-TableState {
    [CmdletBinding()]
    param([bool] $Filtering,
        [bool] $SavedState,
        [string] $DataTableName,
        [ValidateSet('Top', 'Bottom', 'Both')][string]$FilteringLocation = 'Bottom')
    if ($Filtering -and $SavedState) {
        if ($FilteringLocation -eq 'Top') {
            $Output = @"
                // Setup - Looading text input from SavedState
                `$('#$DataTableName').on('stateLoaded.dt', function(e, settings, data) {
                    settings.aoPreSearchCols.forEach(function(col, index) {
                        if (col.sSearch) setTimeout(function() {
                            `$('#$DataTableName thead th:eq('+index+') input').val(col.sSearch)
                        }, 50)
                    })
                });
"@

        } elseif ($FilteringLocation -eq 'Both') {
            $Output = @"
                // Setup - Looading text input from SavedState
                `$('#$DataTableName').on('stateLoaded.dt', function(e, settings, data) {
                    settings.aoPreSearchCols.forEach(function(col, index) {
                        if (col.sSearch) setTimeout(function() {
                            `$('#$DataTableName thead th:eq('+index+') input').val(col.sSearch)
                        }, 50)
                    })
                });
                // Setup - Looading text input from SavedState
                `$('#$DataTableName').on('stateLoaded.dt', function(e, settings, data) {
                    settings.aoPreSearchCols.forEach(function(col, index) {
                        if (col.sSearch) setTimeout(function() {
                            `$('#$DataTableName tfoot th:eq('+index+') input').val(col.sSearch)
                        }, 50)
                    })
                });
"@

        } else {
            $Output = @"
                // Setup - Looading text input from SavedState
                `$('#$DataTableName').on('stateLoaded.dt', function(e, settings, data) {
                    settings.aoPreSearchCols.forEach(function(col, index) {
                        if (col.sSearch) setTimeout(function() {
                            `$('#$DataTableName tfoot th:eq('+index+') input').val(col.sSearch)
                        }, 50)
                    })
                })
"@

        }
    } else { $Output = '' }
    return $Output
}
function Convert-ImagesToBinary {
    [CmdLetBinding()]
    param([string[]] $Content,
        [string] $Search,
        [string] $ReplacePath)
    if ($Content -like "*$Search*") {
        $Replace = "data:image/$FileType;base64," + [Convert]::ToBase64String((Get-Content -LiteralPath $ReplacePath -Encoding Byte))
        $Content = $Content.Replace($Search, $Replace)
    }
    $Content
}
function Convert-StyleContent {
    [CmdLetBinding()]
    param([string[]] $CSS,
        [string] $ImagesPath,
        [string] $SearchPath)
    $ImageFiles = Get-ChildItem -Path (Join-Path $ImagesPath '\*') -Include *.jpg, *.png, *.bmp
    foreach ($Image in $ImageFiles) { $CSS = Convert-ImagesToBinary -Content $CSS -Search "$SearchPath$($Image.Name)" -ReplacePath $Image.FullName }
    return $CSS
}
function Convert-StyleContent1 {
    param([PSCustomObject] $Options)
    if ($null -ne $Options.StyleContent) {
        Write-Verbose "Logos: $($Options.Logos.Keys -join ',')"
        foreach ($Logo in $Options.Logos.Keys) {
            $Search = "../images/$Logo.png", "DataTables-1.10.18/images/$Logo.png"
            $Replace = $Options.Logos[$Logo]
            foreach ($S in $Search) {
                Write-Verbose "Logos - replacing $S with binary representation"
                $Options.StyleContent = ($Options.StyleContent).Replace($S, $Replace)
            }
        }
    }
}
function Get-FeaturesInUse {
    [CmdletBinding()]
    param()
    foreach ($Key in $Script:HTMLSchema.Features.Keys) { if ($Script:HTMLSchema.Features[$Key]) { $Key } }
}
Function Get-HTMLColorSchemes {
    [CmdletBinding()]
    param
    ([Parameter(Mandatory = $false)][String]$SchemePath)
    if ([String]::IsNullOrEmpty($SchemePath)) { $SchemePath = "$PSScriptRoot\Resources\ColorSchemas" }
    $Schemes = @{ }
    Write-Verbose "Retrieving *.rcs from $SchemePath"
    $SchemeFiles = @(Get-ChildItem $SchemePath -Filter '*.rcs' -Recurse)
    foreach ($SchemeFile in $SchemeFiles) {
        $SchemeContent = Import-Csv -Delimiter ';' -Path $SchemeFile.FullName
        $Schemes.Add($SchemeFile.BaseName, $SchemeContent)
    }
    $Schemes.add('Generated1', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated2', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated3', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated4', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated5', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated6', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated7', (Get-RandomColorScheme -NumberOfSchemes 80))
    $Schemes.add('Generated8', (Get-RandomColorScheme -NumberOfSchemes 80))
    Write-Output $Schemes
}
Function Get-HTMLLogos {
    <#
         .SYNOPSIS
            Get Base64 HTML
 
    #>

    [CmdletBinding()]
    param
    ([Parameter(Mandatory = $false)]
        [string]$LeftLogoName = "Sample",
        [string]$RightLogoName = "Alternate",
        [string]$LeftLogoString,
        [string]$RightLogoString)
    $LogoSources = @{ }
    $LogoPath = @()
    if ([String]::IsNullOrEmpty($RightLogoString) -eq $false -or [String]::IsNullOrEmpty($LeftLogoString) -eq $false) {
        if ([String]::IsNullOrEmpty($RightLogoString) -eq $false) { $LogoSources.Add($RightLogoName, $RightLogoString) }
        if ([String]::IsNullOrEmpty($LeftLogoString) -eq $false) { $LogoSources.Add($LeftLogoName, $LeftLogoString) }
    } else { $LogoPath += "$PSScriptRoot\Resources\Images\Other" }
    $LogoPath += "$PSScriptRoot\Resources\Images\DataTables"
    $ImageFiles = Get-ChildItem -Path (Join-Path $LogoPath '\*') -Include *.jpg, *.png, *.bmp -Recurse
    foreach ($ImageFile in $ImageFiles) {
        if ($ImageFile.Extension -eq '.jpg') { $FileType = 'jpeg' } else { $FileType = $ImageFile.Extension.Replace('.', '') }
        Write-Verbose "Converting $($ImageFile.FullName) to base64 ($FileType)"
        $LogoSources.Add($ImageFile.BaseName, "data:image/$FileType;base64," + [Convert]::ToBase64String((Get-Content $ImageFile.FullName -Encoding Byte)))
    }
    Write-Output $LogoSources
}
function Get-HTMLPartContent {
    param([Array] $Content,
        [string] $Start,
        [string] $End,
        [ValidateSet('Before', 'Between', 'After')] $Type = 'Between')
    $NrStart = $Content.IndexOf($Start)
    $NrEnd = $Content.IndexOf($End)
    if ($Type -eq 'Between') {
        if ($NrStart -eq -1) { return }
        $Content[$NrStart..$NrEnd]
    }
    if ($Type -eq 'After') {
        if ($NrStart -eq -1) { return $Content }
        $Content[($NrEnd + 1)..($Content.Count - 1)]
    }
    if ($Type -eq 'Before') {
        if ($NrStart -eq -1) { return }
        $Content[0..$NrStart]
    }
}
Function Get-RandomColor {
    <#
    .SYNOPSIS
        Random colour Function
    #>

    param([int]$RMin = 0,
        [int]$RMax = 255,
        [int]$GMin = 0,
        [int]$GMax = 255,
        [int]$BMin = 0,
        [int]$BMax = 255)
    $R = (Get-Random -Maximum $RMax -Minimum $RMin)
    $G = (Get-Random -Maximum $GMax -Minimum $GMin)
    $B = (Get-Random -Maximum $BMax -Minimum $BMin)
    @($R, $G, $B)
}
Function Get-RandomColorScheme {
    <#
    .SYNOPSIS
    Generate a colour scheme
 
     
    .DESCRIPTION
    Generate a colour scheme
     
    .PARAMETER NumberOfSchemes
    Parameter description
     
    .EXAMPLE
    An example
     
    .NOTES
    General notes
    #>

    param
    ([Parameter(Mandatory = $false)][int]$NumberOfSchemes = 1,
        [int] $ColorSwing = 8,
        [string] $Hover = 0.3,
        [string] $color = 0.6,
        [string] $border = 1,
        [string] $background = 0.7)
    $ColorReference = Get-Random -Minimum 1 -Maximum 3
    $BaseColor = (Get-Random -Maximum (200 - $ColorSwing) -Minimum (50 + $ColorSwing))
    $BCMax = $BaseColor + $ColorSwing
    $BCMin = $BaseColor - $ColorSwing
    $i = 0
    while ($i -ne $NumberOfSchemes) {
        switch ($ColorReference) {
            1 { [int[]] $base = Get-RandomColor -rmin $BCMin -rmax $BCMax }
            2 { [int[]] $base = Get-RandomColor -gmin $BCMin -gmax $BCMax }
            3 { [int[]] $base = Get-RandomColor -bmin $BCMin -bcmax $BCMax }
        }
        [PSCustomObject] @{Background = "rgba($($base + $background -join ','))"
            Border = "rgba($($base + $border -join ','))"
            Colour = "rgba($($base + $color -join ','))"
            Hover = "rgba($($base + $Hover -join ','))"
        }
        $i++
    }
}
function Get-Resources {
    [CmdLetBinding()]
    param([switch] $UseCssLinks,
        [switch] $UseJavaScriptLinks,
        [switch] $NoScript,
        [ValidateSet('Header', 'Footer', 'HeaderAlways', 'FooterAlways')][string] $Location)
    DynamicParam {
        $Names = $Script:Configuration.Features.Keys
        $ParamAttrib = New-Object System.Management.Automation.ParameterAttribute
        $ParamAttrib.Mandatory = $true
        $ParamAttrib.ParameterSetName = '__AllParameterSets'
        $ReportAttrib = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
        $ReportAttrib.Add($ParamAttrib)
        $ReportAttrib.Add((New-Object System.Management.Automation.ValidateSetAttribute($Names)))
        $ReportRuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Features', [string[]], $ReportAttrib)
        $RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
        $RuntimeParamDic.Add('Features', $ReportRuntimeParam)
        return $RuntimeParamDic
    }
    Process {
        [string[]] $Features = $PSBoundParameters.Features
        foreach ($Feature in $Features) {
            Write-Verbose "Get-Resources - Location: $Location - Feature: $Feature UseCssLinks: $UseCssLinks UseJavaScriptLinks: $UseJavaScriptLinks"
            if ($UseCssLinks) { New-HTMLResourceCSS -Link $Script:Configuration.Features.$Feature.$Location.'CssLink' -ResourceComment $Script:Configuration.Features.$Feature.Comment } else {
                $CSSOutput = New-HTMLResourceCSS -FilePath $Script:Configuration.Features.$Feature.$Location.'Css' -ResourceComment $Script:Configuration.Features.$Feature.Comment
                Convert-StyleContent -CSS $CSSOutput -ImagesPath "$PSScriptRoot\Resources\Images\DataTables" -SearchPath "DataTables-1.10.18/images/"
            }
            if ($UseJavaScriptLinks) { New-HTMLResourceJS -Link $Script:Configuration.Features.$Feature.$Location.'JsLink' -ResourceComment $Script:Configuration.Features.$Feature.Comment } else { New-HTMLResourceJS -FilePath $Script:Configuration.Features.$Feature.$Location.'Js' -ResourceComment $Script:Configuration.Features.$Feature.Comment }
            if ($NoScript) {
                [Array] $Output = @(if ($UseCssLinks) { New-HTMLResourceCSS -Link $Script:Configuration.Features.$Feature.$Location.'CssLinkNoScript' -ResourceComment $Script:Configuration.Features.$Feature.Comment } else {
                        $CSSOutput = New-HTMLResourceCSS -FilePath $Script:Configuration.Features.$Feature.$Location.'CssNoScript' -ResourceComment $Script:Configuration.Features.$Feature.Comment
                        Convert-StyleContent -CSS $CSSOutput -ImagesPath "$PSScriptRoot\Resources\Images\DataTables" -SearchPath "DataTables-1.10.18/images/"
                    })
                if (($Output.Count -gt 0) -and ($null -ne $Output[0])) { New-HTMLTag -Tag 'noscript' { $Output } }
            }
        }
    }
}
function New-ApexChart {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [ValidateSet('', 'central')][string] $Positioning)
    $Script:HTMLSchema.Features.ChartsApex = $true
    [string] $ID = "ChartID-" + (Get-RandomStringName -Size 8)
    $Div = New-HTMLTag -Tag 'div' -Attributes @{id = $ID; class = $Positioning }
    $Script = New-HTMLTag -Tag 'script' -Value { $JSON = $Options | ConvertTo-Json -Depth 5 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) }
"var options = $JSON"
""
"var chart = new ApexCharts(document.querySelector('#$ID'),
            options
        );"

"chart.render();" }
$Div
$Script:HTMLSchema.Charts.Add($Script)
}
function New-ChartArea {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [Array] $Data,
        [Array] $DataNames,
        [Array] $DataLegend,
        [ValidateSet('datetime', 'category', 'numeric')][string] $DataCategoriesType = 'category')
    $Options.chart = @{type = 'area' }
    $Options.series = @(New-HTMLChartDataSet -Data $Data -DataNames $DataNames)
    $Options.xaxis = [ordered] @{ }
    if ($DataCategoriesType -ne '') { $Options.xaxis.type = $DataCategoriesType }
    if ($DataCategories.Count -gt 0) { $Options.xaxis.categories = $DataCategories }
}
function New-ChartAxisX {
    param([System.Collections.IDictionary] $Options,
        [string] $Title,
        [int] $MinValue,
        [int] $MaxValue,
        [ValidateSet('datetime', 'category', 'numeric')][string] $DataCategoriesType = 'category',
        $DataCategories)
    if (-not $Options.Contains('xaxis')) { $Options.xaxis = @{ }
    }
    if ($Title -ne '') { $Options.xaxis.title = @{ }
        $Options.xaxis.title.text = $Title
    }
    if ($MinValue -gt 0) { $Options.xaxis.min = $MinValue }
    if ($MinValue -gt 0) { $Options.xaxis.max = $MaxValue }
    if ($DataCategoriesType -ne '') { $Options.xaxis.type = $DataCategoriesType }
    if ($DataCategories.Count -gt 0) { $Options.xaxis.categories = $DataCategories }
}
function New-ChartAxisY {
    param([System.Collections.IDictionary] $Options,
        [string] $Title,
        [int] $MinValue,
        [int] $MaxValue)
    if (-not $Options.Contains('yaxis')) { $Options.yaxis = @{ }
    }
    if ($Title -ne '') { $Options.yaxis.title = @{ }
        $Options.yaxis.title.text = $Title
    }
    if ($MinValue -gt 0) { $Options.yaxis.min = $MinValue }
    if ($MinValue -gt 0) { $Options.yaxis.max = $MaxValue }
}
Function New-ChartBar {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [bool] $Horizontal = $true,
        [bool] $DataLabelsEnabled = $true,
        [int] $DataLabelsOffsetX = -6,
        [string] $DataLabelsFontSize = '12px',
        [RGBColors[]] $DataLabelsColor,
        [string] $Title,
        [ValidateSet('center', 'left', 'right', '')][string] $TitleAlignment = '',
        [string] $Formatter,
        [ValidateSet('bar', 'barStacked', 'barStacked100Percent')] $Type = 'bar',
        [RGBColors[]] $Colors,
        [switch] $PatternedColors,
        [switch] $Distributed,
        [Array] $Data,
        [Array] $DataNames,
        [Array] $DataLegend)
    if ($Type -eq 'bar') { $Options.chart = [ordered] @{type = 'bar' }
    } elseif ($Type -eq 'barStacked') {
        $Options.chart = [ordered] @{type = 'bar'
            stacked = $true
        }
    } else {
        $Options.chart = [ordered] @{type = 'bar'
            stacked = $true
            stackType = '100%'
        }
    }
    if ($Colors.Count -gt 0) {
        $RGBColor = ConvertFrom-Color -Color $Colors
        $Options.colors = @($RGBColor)
    }
    $Options.plotOptions = @{bar = @{horizontal = $Horizontal } }
    if ($Distributed) { $Options.plotOptions.bar.distributed = $Distributed.IsPresent }
    $Options.dataLabels = [ordered] @{enabled = $DataLabelsEnabled
        offsetX = $DataLabelsOffsetX
        style = @{fontSize = $DataLabelsFontSize }
    }
    if ($null -ne $DataLabelsColor) {
        $RGBColorLabel = ConvertFrom-Color -Color $DataLabelsColor
        $Options.dataLabels.style.colors = @($RGBColorLabel)
    }
    $Options.series = @(New-HTMLChartDataSet -Data $Data -DataNames $DataLegend)
    $Options.xaxis = [ordered] @{ }
    if ($DataNames.Count -gt 0) { $Options.xaxis.categories = $DataNames }
    New-ChartTitle -Options $Options -Title $Title -TitleAlignment $TitleAlignment
    if ($PatternedColors) {
        $Options.fill = @{type = 'pattern'
            opacity = 1
            pattern = @{style = @('circles', 'slantedLines', 'verticalLines', 'horizontalLines') }
        }
    }
}
function New-ChartDataLabels {
    param([System.Collections.IDictionary] $Options,
        [bool] $DataLabelsEnabled = $true,
        [int] $DataLabelsOffsetX = -6,
        [string] $DataLabelsFontSize = '12px',
        [RGBColors[]] $DataLabelsColor)
    $Options.dataLabels = [ordered] @{enabled = $DataLabelsEnabled
        offsetX = $DataLabelsOffsetX
        style = @{fontSize = $DataLabelsFontSize }
    }
    if ($DataLabelsColor.Count -gt 0) { $Options.dataLabels.style.colors = @(ConvertFrom-Color -Color $DataLabelsColor) }
}
function New-ChartGridColors {
    param([System.Collections.IDictionary] $Options,
        [RGBColors[]] $GridColors,
        [double] $GridOpacity)
    $Options.grid = @{ }
    $Options.grid.row = @{ }
    if ($GridColors.Count -gt 0) { $Options.grid.row.colors = @(ConvertFrom-Color -Color $GridColors) }
    if ($GridOpacity -ne 0) { $Options.grid.row.opacity = $GridOpacity }
}
function New-ChartLegend {
    param([System.Collections.IDictionary] $Options,
        [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', '')][string] $LegendPosition = '')
    if ($LegendPosition -eq '' -or $LegendPosition -eq 'bottom') { } elseif ($LegendPosition -eq 'right') {
        $Options.legend = [ordered]@{position = 'right'
            offsetY = 100
            height = 230
        }
    } elseif ($LegendPosition -eq 'top') {
        $Options.legend = [ordered]@{position = 'top'
            horizontalAlign = 'left'
            offsetX = 40
        }
    } elseif ($LegendPosition -eq 'topRight') {
        $Options.legend = [ordered]@{position = 'top'
            horizontalAlign = 'right'
            floating = true.exe
            offsetY = -25
            offsetX = -5
        }
    }
}
function New-ChartLine {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [Array] $Data,
        [Array] $DataNames,
        [ValidateSet('datetime', 'category', 'numeric')][string] $DataCategoriesType = 'category')
    $Options.chart = @{type = 'line' }
    $Options.series = @(New-HTMLChartDataSet -Data $Data -DataNames $DataNames)
    $Options.xaxis = [ordered] @{ }
    if ($DataCategoriesType -ne '') { $Options.xaxis.type = $DataCategoriesType }
    if ($DataCategories.Count -gt 0) { $Options.xaxis.categories = $DataCategories }
}
function New-ChartMarker {
    param([System.Collections.IDictionary] $Options,
        [int] $MarkerSize)
    if ($MarkerSize -gt 0) { $Options.markers = @{size = $MarkerSize }
    }
}
function New-ChartRadial {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [Array] $Values,
        [Array] $Names,
        $Type)
    $Options.chart = @{type = 'radialBar' }
    if ($Type -eq '1') { New-ChartRadialType1 -Options $Options } elseif ($Type -eq '2') { New-ChartRadialType2 -Options $Options }
    $Options.series = @($Values)
    $Options.labels = @($Names)
}
function New-ChartRadialCircleType {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [ValidateSet('FullCircleTop', 'FullCircleBottom', 'FullCircleBottomLeft', 'FullCircleLeft', 'Speedometer', 'SemiCircleGauge')] $CircleType)
    if ($CircleType -eq 'SemiCircleGauge') {
        $Options.plotOptions.radialBar = [ordered] @{startAngle = -90
            endAngle = 90
        }
    } elseif ($CircleType -eq 'FullCircleBottom') {
        $Options.plotOptions.radialBar = [ordered] @{startAngle = -180
            endAngle = 180
        }
    } elseif ($CircleType -eq 'FullCircleLeft') {
        $Options.plotOptions.radialBar = [ordered] @{startAngle = -90
            endAngle = 270
        }
    } elseif ($CircleType -eq 'FullCircleBottomLeft') {
        $Options.plotOptions.radialBar = [ordered] @{startAngle = -135
            endAngle = 225
        }
    } elseif ($CircleType -eq 'Speedometer') {
        $Options.plotOptions.radialBar = [ordered] @{startAngle = -135
            endAngle = 135
        }
    } else { }
}
function New-ChartRadialDataLabels {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [string] $LabelAverage = 'Average')
    if ($LabelAverage -ne '') {
        $Options.plotOptions.radialBar.dataLabels = @{showOn = 'always'
            name = @{ }
            value = @{ }
            total = @{show = $true
                label = $LabelAverage
            }
        }
    }
}
function New-ChartRadialType1 {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [Array] $Values,
        [Array] $Names)
    $Options.plotOptions = @{radialBar = [ordered] @{hollow = [ordered] @{margin = 0
                size = '70%'
                background = '#fff'
                image = 'undefined'
                imageOffsetX = 0
                imageOffsetY = 0
                position = 'front'
                dropShadow = @{enabled = $true
                    top = 3
                    left = 0
                    blur = 4
                    opacity = 0.24
                }
            }
            track = [ordered] @{background = '#fff'
                strokeWidth = '70%'
                margin = 0
                dropShadow = [ordered] @{enabled = $true
                    top = -3
                    left = 0
                    blur = 4
                    opacity = 0.35
                }
            }
        }
    }
    $Options.fill = [ordered] @{type = 'gradient'
        gradient = [ordered] @{shade = 'dark'
            type = 'horizontal'
            shadeIntensity = 0.5
            gradientToColors = @('#ABE5A1')
            inverseColors = true.exe
            opacityFrom = 1
            opacityTo = 1
            stops = @(0, 100)
        }
    }
    $Options.stroke = [ordered] @{dashArray = 4 }
}
function New-ChartRadialType2 {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [Array] $Values,
        [Array] $Names)
    $Options.plotOptions = @{radialBar = [ordered] @{hollow = [ordered] @{margin = 0
                size = '70%'
                background = '#fff'
                image = 'undefined'
                imageOffsetX = 0
                imageOffsetY = 0
                position = 'front'
                dropShadow = @{enabled = $true
                    top = 3
                    left = 0
                    blur = 4
                    opacity = 0.24
                }
            }
        }
    }
}
function New-ChartSize {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [nullable[int]] $Height = 350,
        [nullable[int]] $Width)
    if ($null -ne $Height) { $Options.chart.height = $Height }
    if ($null -ne $Width) { $Options.chart.width = $Width }
}
function New-ChartSpark {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [nullable[RGBColors]] $Color,
        [string] $Title,
        [string] $SubTitle,
        [int] $FontSizeTitle = 24,
        [int] $FontSizeSubtitle = 14,
        [Array] $Values)
    if ($Values.Count -eq 0) { Write-Warning 'Get-ChartSpark - Values Empty' }
    if ($null -ne $Color) {
        $ColorRGB = ConvertFrom-Color -Color $Color
        $Options.colors = @($ColorRGB)
    }
    $Options.chart = [ordered] @{type = 'area'
        sparkline = @{enabled = $true }
    }
    $Options.stroke = @{curve = 'straight' }
    $Options.title = [ordered] @{text = $Title
        offsetX = 0
        style = @{fontSize = "$($FontSizeTitle)px"
            cssClass = 'apexcharts-yaxis-title'
        }
    }
    $Options.subtitle = [ordered] @{text = $SubTitle
        offsetX = 0
        style = @{fontSize = "$($FontSizeSubtitle)px"
            cssClass = 'apexcharts-yaxis-title'
        }
    }
    $Options.yaxis = @{min = 0 }
    $Options.fill = @{opacity = 0.3 }
    $Options.series = @(if ($Values[0] -is [Array]) { foreach ($Value in $Values) { @{data = @($Value) } }
        } else { @{data = @($Values) }
        })
}
function New-ChartStrokeDefinition {
    param([System.Collections.IDictionary] $Options,
        [bool] $LineShow = $true,
        [ValidateSet('straight', 'smooth', 'stepline')] $LineCurve = 'straight',
        [int] $LineWidth,
        [RGBColors[]] $LineColor)
    $Options.stroke = [ordered] @{show = $LineShow
        curve = $LineCurve
    }
    if ($LineWidth -ne 0) { $Options.stroke.width = $LineWidth }
    if ($LineColor.Count -gt 0) { $Options.stroke.colors = @(ConvertFrom-Color -Color $LineColor) }
}
function New-ChartTitle {
    param([System.Collections.IDictionary] $Options,
        [string] $Title,
        [ValidateSet('center', 'left', 'right', '')][string] $TitleAlignment = '')
    $Options.title = [ordered] @{ }
    if ($TitleText -ne '') { $Options.title.text = $Title }
    if ($TitleAlignment -ne '') { $Options.title.align = $TitleAlignment }
}
function New-ChartToolbar {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [bool] $Show = $true,
        [bool] $Download = $true,
        [bool] $Selection = $true,
        [bool] $Zoom = $true,
        [bool] $ZoomIn = $true,
        [bool] $ZoomOut = $true,
        [bool] $Pan = $true,
        [bool] $Reset = $true)
    $Options.chart.toolbar = [ordered] @{show = $show
        tools = [ordered] @{download = $Download
            selection = $Selection
            zoom = $Zoom
            zoomin = $ZoomIn
            zoomout = $ZoomOut
            pan = $Pan
            reset = $Reset
        }
        autoSelected = 'zoom'
    }
}
function New-ChartZoom {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $Options,
        [switch] $Enabled)
    if ($Enabled) {
        $Options.chart.zoom = @{type = 'x'
            enabled = $Enabled.IsPresent
        }
    }
}
Function New-HTML {
    [CmdletBinding()]
    param([Parameter(Position = 0)][ValidateNotNull()][ScriptBlock] $HtmlData = $(Throw "Have you put the open curly brace on the next line?"),
        [switch] $UseCssLinks,
        [switch] $UseJavaScriptLinks,
        [String] $TitleText,
        [string] $Author,
        [string] $DateFormat = 'yyyy-MM-dd HH:mm:ss',
        [int] $AutoRefresh,
        [Parameter(Mandatory = $false)][string]$FilePath,
        [Parameter(Mandatory = $false)][switch]$ShowHTML,
        [ValidateSet('Unknown', 'String', 'Unicode', 'Byte', 'BigEndianUnicode', 'UTF8', 'UTF7', 'UTF32', 'Ascii', 'Default', 'Oem', 'BigEndianUTF32')] $Encoding = 'UTF8')
    [string] $CurrentDate = (Get-Date).ToString($DateFormat)
    $Script:HTMLSchema = @{TabsHeaders = [System.Collections.Generic.List[HashTable]]::new()
        Features = @{ }
        Charts = [System.Collections.Generic.List[string]]::new()
    }
    $OutputHTML = Invoke-Command -ScriptBlock $HtmlData
    if ($null -ne $OutputHTML -and $OutputHTML.Count -gt 0) {
        $Logo = Get-HTMLPartContent -Content $OutputHTML -Start '<!-- START LOGO -->' -End '<!-- END LOGO -->' -Type Between
        $OutputHTML = Get-HTMLPartContent -Content $OutputHTML -Start '<!-- START LOGO -->' -End '<!-- END LOGO -->' -Type After
    }
    $Features = Get-FeaturesInUse
    $HTML = @('<!DOCTYPE html>'
        New-HTMLTag -Tag 'html' { '<!-- HEADER -->'
            New-HTMLTag -Tag 'head' { New-HTMLTag -Tag 'meta' -Attributes @{charset = "utf-8" } -SelfClosing
                New-HTMLTag -Tag 'meta' -Attributes @{name = 'viewport'; content = 'width=device-width, initial-scale=1' } -SelfClosing
                New-HTMLTag -Tag 'meta' -Attributes @{name = 'author'; content = $Author } -SelfClosing
                New-HTMLTag -Tag 'meta' -Attributes @{name = 'revised'; content = $CurrentDate } -SelfClosing
                New-HTMLTag -Tag 'title' { $TitleText }
                if ($Autorefresh -gt 0) { New-HTMLTag -Tag 'meta' -Attributes @{'http-equiv' = 'refresh'; content = $Autorefresh } -SelfClosing
                }
                Get-Resources -UseCssLinks:$true -UseJavaScriptLinks:$true -Location 'HeaderAlways' -Features Default, DefaultHeadings, Fonts, FontsAwesome
                Get-Resources -UseCssLinks:$false -UseJavaScriptLinks:$false -Location 'HeaderAlways' -Features Default, DefaultHeadings
                if ($null -ne $Features) {
                    Get-Resources -UseCssLinks:$true -UseJavaScriptLinks:$true -Location 'HeaderAlways' -Features $Features
                    Get-Resources -UseCssLinks:$false -UseJavaScriptLinks:$false -Location 'HeaderAlways' -Features $Features
                    Get-Resources -UseCssLinks:$true -UseJavaScriptLinks:$true -Location 'HeaderAlways' -Features $Features -NoScript
                    Get-Resources -UseCssLinks:$false -UseJavaScriptLinks:$false -Location 'HeaderAlways' -Features $Features -NoScript
                    Get-Resources -UseCssLinks:$UseCssLinks -UseJavaScriptLinks:$UseJavaScriptLinks -Location 'Header' -Features $Features
                } }
            '<!-- END HEADER -->'
            '<!-- BODY -->'
            New-HTMLTag -Tag 'body' { $Logo
                if ($Script:HTMLSchema.TabsHeaders) { New-HTMLTabHead }
                $OutputHTML
                foreach ($Chart in $Script:HTMLSchema.Charts) { $Chart } }
            '<!-- END BODY -->'
            '<!-- FOOTER -->'
            New-HTMLTag -Tag 'footer' { if ($null -ne $Features) {
                    Get-Resources -UseCssLinks:$true -UseJavaScriptLinks:$true -Location 'FooterAlways' -Features $Features
                    Get-Resources -UseCssLinks:$false -UseJavaScriptLinks:$false -Location 'FooterAlways' -Features $Features
                    Get-Resources -UseCssLinks:$UseCssLinks -UseJavaScriptLinks:$UseJavaScriptLinks -Location 'Footer' -Features $Features
                } }
            '<!-- END FOOTER -->' })
    if ($FilePath -ne '') { Save-HTML -HTML $HTML -FilePath $FilePath -ShowHTML:$ShowHTML -Encoding $Encoding } else { $HTML }
}
function New-HTMLAnchor {
    <#
    .SYNOPSIS
    Short description
     
    .DESCRIPTION
    Long description
     
    .PARAMETER Name
    Parameter description
     
    .PARAMETER Id
    Parameter description
     
    .PARAMETER Target
    Parameter description
     
    .PARAMETER Class
    Parameter description
     
    .PARAMETER HrefLink
    Parameter description
     
    .PARAMETER OnClick
    Parameter description
     
    .PARAMETER Style
    Parameter description
     
    .PARAMETER Text
    Parameter description
     
    .EXAMPLE
    New-HTMLAnchor -Target _parent
 
    New-HTMLAnchor -Id "show_$RandomNumber" -Href '#' -OnClick "show('$RandomNumber');" -Style "color: #ffffff; display:none;" -Text 'Show'
 
    Output:
    <a target = "_parent" />
     
    .NOTES
    General notes
    #>

    param([alias('AnchorName')][string] $Name,
        [string] $Id,
        [string] $Target,
        [string] $Class,
        [alias('Url', 'Link', 'UrlLink', 'Href')][string] $HrefLink,
        [string] $OnClick,
        [string] $Style,
        [alias('AnchorText', 'Value')][string] $Text)
    $Attributes = [ordered]@{'id' = $Id
        'name' = $Name
        'class' = $Class
        'target' = $Target
        'href' = $HrefLink
        'onclick' = $OnClick
        'style' = $Style
    }
    New-HTMLTag -Tag 'a' -Attributes $Attributes { $Text }
}
Function New-HTMLAnchorLink {
    <#
    .SYNOPSIS
    Creates Hyperlink for an Anchor
 
    .DESCRIPTION
    Long description
 
    .PARAMETER AnchorName
    The Actual name of the Anchor (Hidden)
 
    .PARAMETER AnchorText
    The HyperLink text. Will default to $AnchorNname if not specified
 
    .EXAMPLE
    Get-HTMLAnchorLink -AnchorName 'test'
 
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    Param
    ([Parameter(Mandatory = $true)][String] $AnchorName,
        [Parameter(Mandatory = $false)][String] $AnchorText)
    if ($AnchorText -eq $null -or $AnchorText -eq '') { $AnchorText = $AnchorName }
    New-HTMLAnchor -Name $AnchorName -HrefLink '#' -Class 'alink' -Text $AnchorText
}
Function New-HTMLAnchorName {
    <#
    .SYNOPSIS
    Creates an anchor
 
    .DESCRIPTION
    Long description
 
    .PARAMETER AnchorName
    Parameter description
 
    .EXAMPLE
    An example
 
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    Param ([Parameter(Mandatory = $true)][String] $AnchorName)
    New-HTMLAnchor -Name $AnchorName
}
function New-HTMLCanvas {
    [CmdletBinding()]
    param([alias('Value')][Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $Content = $(Throw "Open curly brace with Content"),
        [string] $ID,
        [string] $Width,
        [string] $Height,
        [string] $Style)
    $Canvas = [Ordered] @{Tag = 'canvas'
        Attributes = [ordered]@{'id' = $Id
            'width' = $Width
            'height' = $Height
            'style' = $Style
        }
        SelfClosing = $false
        Value = Invoke-Command -ScriptBlock $Content
    }
    $HTML = Set-Tag -HtmlObject $Canvas
    return $HTML
}
function New-HTMLChartArea {
    [CmdletBinding()]
    param([nullable[int]] $Height = 350,
        [nullable[int]] $Width,
        [ValidateSet('', 'central')][string] $Positioning,
        [bool] $DataLabelsEnabled = $true,
        [int] $DataLabelsOffsetX = -6,
        [string] $DataLabelsFontSize = '12px',
        [RGBColors[]] $DataLabelsColor,
        [ValidateSet('datetime', 'category', 'numeric')][string] $DataCategoriesType = 'category',
        [ValidateSet('straight', 'smooth', 'stepline')] $LineCurve = 'straight',
        [int] $LineWidth,
        [RGBColors[]] $LineColor,
        [RGBColors[]] $GridColors,
        [double] $GridOpacity,
        [string] $Title,
        [ValidateSet('center', 'left', 'right', '')][string] $TitleAlignment = '',
        [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', '')][string] $LegendPosition = '',
        [string] $TitleX,
        [string] $TitleY,
        [int] $MarkerSize,
        [Array] $Data,
        [Array] $DataNames,
        [Array] $DataLegend,
        [switch] $Zoom)
    $Options = [ordered] @{ }
    New-ChartArea -Options $Options -Data $Data -DataNames $DataNames
    New-ChartStrokeDefinition -Options $Options -LineShow $true -LineCurve $LineCurve -LineWidth $LineWidth -LineColor $LineColor
    New-ChartDataLabels -Options $Options -DataLabelsEnabled $DataLabelsEnabled -DataLabelsOffsetX $DataLabelsOffsetX -DataLabelsFontSize $DataLabelsFontSize -DataLabelsColor $DataLabelsColor
    New-ChartAxisX -Options $Options -Title $TitleX -DataCategoriesType $DataCategoriesType -DataCategories $DataLegend
    New-ChartAxisY -Options $Options -Title $TitleY
    New-ChartMarker -Options $Options -MarkerSize $MarkerSize
    New-ChartTitle -Options $Options -Title $Title -TitleAlignment $TitleAlignment
    New-ChartGridColors -Options $Options -GridColors $GridColors -GridOpacity $GridOpacity
    New-ChartLegend -Options $Options -LegendPosition $LegendPosition
    New-ChartSize -Options $Options -Height $Height -Width $Width
    New-ChartZoom -Options $Options -Enabled:$Zoom
    New-ChartToolbar -Options $Options
    New-ApexChart -Positioning $Positioning -Options $Options
}
function New-HTMLChartBar {
    [CmdletBinding()]
    param([nullable[int]] $Height = 350,
        [nullable[int]] $Width,
        [ValidateSet('', 'central')][string] $Positioning,
        [ValidateSet('bar', 'barStacked', 'barStacked100Percent')] $Type = 'bar',
        [RGBColors[]] $Colors,
        [switch] $PatternedColors,
        [string] $Title,
        [ValidateSet('center', 'left', 'right', '')][string] $TitleAlignment = '',
        [bool] $Horizontal = $true,
        [bool] $DataLabelsEnabled = $true,
        [int] $DataLabelsOffsetX = -6,
        [string] $DataLabelsFontSize = '12px',
        [nullable[RGBColors]] $DataLabelsColor,
        [switch] $Distributed,
        [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', '')][string] $LegendPosition = '',
        [Array] $Data,
        [Array] $DataNames,
        [Array] $DataLegend)
    $Options = [ordered] @{ }
    New-ChartBar -Options $Options -Horizontal $Horizontal -DataLabelsEnabled $DataLabelsEnabled -DataLabelsOffsetX $DataLabelsOffsetX -DataLabelsFontSize $DataLabelsFontSize -DataLabelsColor $DataLabelsColor -Data $Data -DataNames $DataNames -DataLegend $DataLegend -Title $Title -TitleAlignment $TitleAlignment -Type $Type -Colors $Colors -PatternedColors:$PatternedColors -Distributed:$Distributed
    New-ChartLegend -Options $Options -LegendPosition $LegendPosition
    New-ChartSize -Options $Options -Height $Height -Width $Width
    New-ChartToolbar -Options $Options
    New-ApexChart -Positioning $Positioning -Options $Options
}
function New-HTMLChartDataSet {
    [CmdletBinding()]
    param([Array] $Data,
        [Array] $DataNames)
    if ($null -ne $Data -and $null -ne $DataNames) {
        if ($Data[0] -is [Array]) {
            if ($Data[0].Count -eq $DataNames.Count) {
                for ($a = 0; $a -lt $Data.Count; $a++) {
                    @{name = $DataNames[$a]
                        data = $Data[$a]
                    }
                }
            } elseif ($Data.Count -eq $DataNames.Count) {
                for ($a = 0; $a -lt $Data.Count; $a++) {
                    @{name = $DataNames[$a]
                        data = $Data[$a]
                    }
                }
            } else { New-HTMLChartDataSet -Data $Data }
        } else {
            if ($null -ne $DataNames) {
                @{name = $DataNames
                    data = $Data
                }
            } else { @{data = $Data }
            }
        }
    } elseif ($null -ne $Data) { if ($Data[0] -is [Array]) { foreach ($D in $Data) { @{data = $D } } } else { @{data = $Data }
        }
    } else {
        Write-Warning -Message "New-HTMLChartDataSet - No Data provided. Unabled to create dataset."
        return @{ }
    }
}
function New-HTMLChartLine {
    [CmdletBinding()]
    param([nullable[int]] $Height = 350,
        [nullable[int]] $Width,
        [ValidateSet('', 'central')][string] $Positioning,
        [bool] $DataLabelsEnabled = $true,
        [int] $DataLabelsOffsetX = -6,
        [string] $DataLabelsFontSize = '12px',
        [RGBColors[]] $DataLabelsColor,
        [ValidateSet('datetime', 'category', 'numeric')][string] $DataCategoriesType = 'category',
        [ValidateSet('straight', 'smooth', 'stepline')] $LineCurve = 'straight',
        [int] $LineWidth,
        [RGBColors[]] $LineColor,
        [RGBColors[]] $GridColors,
        [double] $GridOpacity,
        [string] $Title,
        [ValidateSet('center', 'left', 'right', '')][string] $TitleAlignment = '',
        [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', '')][string] $LegendPosition = '',
        [string] $TitleX,
        [string] $TitleY,
        [int] $MarkerSize,
        [Array] $Data,
        [Array] $DataNames,
        [Array] $DataLegend)
    $Options = [ordered] @{ }
    New-ChartLine -Options $Options -Data $Data -DataNames $DataNames
    New-ChartStrokeDefinition -Options $Options -LineShow $true -LineCurve $LineCurve -LineWidth $LineWidth -LineColor $LineColor
    New-ChartDataLabels -Options $Options -DataLabelsEnabled $DataLabelsEnabled -DataLabelsOffsetX $DataLabelsOffsetX -DataLabelsFontSize $DataLabelsFontSize -DataLabelsColor $DataLabelsColor
    New-ChartAxisX -Options $Options -Title $TitleX -DataCategoriesType $DataCategoriesType -DataCategories $DataLegend
    New-ChartAxisY -Options $Options -Title $TitleY
    New-ChartMarker -Options $Options -MarkerSize $MarkerSize
    New-ChartTitle -Options $Options -Title $Title -TitleAlignment $TitleAlignment
    New-ChartGridColors -Options $Options -GridColors $GridColors -GridOpacity $GridOpacity
    New-ChartLegend -Options $Options -LegendPosition $LegendPosition
    New-ChartSize -Options $Options -Height $Height -Width $Width
    New-ChartToolbar -Options $Options
    New-ApexChart -Positioning $Positioning -Options $Options
}
function New-HTMLChartRadial {
    [CmdletBinding()]
    param([nullable[int]] $Height = 350,
        [nullable[int]] $Width,
        [ValidateSet('', 'central')][string] $Positioning,
        [Array] $Names,
        [Array] $Values,
        $Type,
        [ValidateSet('FullCircleTop', 'FullCircleBottom', 'FullCircleBottomLeft', 'FullCircleLeft', 'Speedometer', 'SemiCircleGauge')] $CircleType = 'FullCircleTop',
        [string] $LabelAverage)
    $Options = [ordered] @{ }
    New-ChartRadial -Options $Options -Names $Names -Values $Values -Type $Type
    New-ChartRadialCircleType -Options $Options -CircleType $CircleType
    New-ChartRadialDataLabels -Options $Options -Label $LabelAverage
    New-ChartSize -Options $Options -Height $Height -Width $Width
    New-ChartToolbar -Options $Options
    New-ApexChart -Positioning $Positioning -Options $Options
}
function New-HTMLChartSpark {
    [CmdletBinding()]
    param([nullable[int]] $Height = 350,
        [nullable[int]] $Width,
        [ValidateSet('', 'central')][string] $Positioning,
        [Array] $Data,
        [string] $TitleText,
        [string] $SubTitleText,
        [int] $FontSizeTitle = 24,
        [int] $FontSizeSubtitle = 14,
        [nullable[RGBColors]] $Color)
    $Options = [ordered] @{ }
    New-ChartSpark -Options $Options -Color $Color -Title $TitleText -SubTitle $SubTitleText -FontSizeTitle $FontSizeTitle -FontSizeSubtitle $FontSizeSubtitle -Values $Data
    New-ChartSize -Options $Options -Height $Height -Width $Width
    New-ChartToolbar -Options $Options
    New-ApexChart -Positioning $Positioning -Options $Options
}
Function New-HTMLCodeBlock {
    [CmdletBinding()]
    Param ([Parameter(Mandatory = $true)][String] $Code,
        [Parameter(Mandatory = $false)]
        [ValidateSet('assembly',
            'asm',
            'avrassembly',
            'avrasm',
            'c',
            'cpp',
            'c++',
            'csharp',
            'css',
            'cython',
            'cordpro',
            'diff',
            'docker',
            'dockerfile',
            'generic',
            'standard',
            'groovy',
            'go',
            'golang',
            'html',
            'ini',
            'conf',
            'java',
            'js',
            'javascript',
            'jquery',
            'mootools',
            'ext.js',
            'json',
            'kotlin',
            'less',
            'lua',
            'gfm',
            'md',
            'markdown',
            'octave',
            'matlab',
            'nsis',
            'php',
            'powershell',
            'prolog',
            'py',
            'python',
            'raw',
            'ruby',
            'rust',
            'scss',
            'sass',
            'shell',
            'bash',
            'sql',
            'squirrel',
            'swift',
            'typescript',
            'vhdl',
            'visualbasic',
            'vb',
            'xml',
            'yaml')]
        [String] $Style = 'powershell',
        [Parameter(Mandatory = $false)]
        [ValidateSet('enlighter',
            'standard',
            'classic',
            'bootstrap4',
            'beyond',
            'godzilla',
            'eclipse',
            'mootwo',
            'droide',
            'minimal',
            'atomic',
            'dracula',
            'rowhammer')][String] $Theme,
        [Parameter(Mandatory = $false)][String] $Group,
        [Parameter(Mandatory = $false)][String] $Title,
        [Parameter(Mandatory = $false)][String] $Highlight,
        [Parameter(Mandatory = $false)][nullable[bool]] $ShowLineNumbers,
        [Parameter(Mandatory = $false)][String] $LineOffset)
    $Script:HTMLSchema.Features.CodeBlocks = $true
    $Attributes = [ordered]@{'data-enlighter-language' = "$Style".ToLower()
        'data-enlighter-theme' = "$Theme".ToLower()
        'data-enlighter-group' = "$Group".ToLower()
        'data-enlighter-title' = "$Title"
        'data-enlighter-linenumbers' = "$ShowLineNumbers"
        'data-enlighter-highlight' = "$Highlight"
        'data-enlighter-lineoffset' = "$LineOffset".ToLower()
    }
    New-HTMLTag -Tag 'pre' -Attributes $Attributes { $Code }
}
function New-HTMLContainer {
    param([Parameter(Mandatory = $false, Position = 0)][ScriptBlock] $HTML)
    New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultPanelOther' } { if ($HTML) { Invoke-Command -ScriptBlock $HTML } }
}
Function New-HTMLHeading {
    [CmdletBinding()]
    Param ([validateset('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7')][string]$Heading,
        [string]$HeadingText,
        [validateset('', 'central')][string] $Type,
        [switch] $Underline,
        [nullable[RGBColors]] $Color)
    if ($null -ne $Color) {
        $RGBcolor = ConvertFrom-Color -Color $Color
        $Attributes = @{style = "color: $RGBcolor;" }
    } else { $Attributes = @{ }
    }
    if ($Type -eq 'central') { $Attributes.Class = 'central' }
    if ($Underline) { $Attributes.Class = "$($Attributes.Class) underline" }
    New-HTMLTag -Tag $Heading -Attributes $Attributes { $HeadingText }
}
function New-HTMLHorizontalLine {
    [CmdletBinding()]
    param()
    New-HTMLTag -Tag 'hr' -SelfClosing
}
function New-HTMLImage {
    <#
    .SYNOPSIS
    Short description
     
    .DESCRIPTION
    Long description
     
    .PARAMETER Source
    Parameter description
     
    .PARAMETER UrlLink
    Parameter description
     
    .PARAMETER AlternativeText
    Parameter description
     
    .PARAMETER Class
    Parameter description
     
    .PARAMETER Target
    Parameter description
     
    .PARAMETER Width
    Parameter description
     
    .PARAMETER Height
    Parameter description
     
    .EXAMPLE
    New-HTMLImage -Source 'https://evotec.pl/image.png' -UrlLink 'https://evotc.pl/' -AlternativeText 'My other text' -Class 'otehr' -Width '100%'
     
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    param([string] $Source,
        [Uri] $UrlLink = '',
        [string] $AlternativeText = '',
        [string] $Class = 'Logo',
        [string] $Target = '_blank',
        [string] $Width,
        [string] $Height)
    New-HTMLTag -Tag 'div' -Attributes @{class = $Class.ToLower() } { $AAttributes = [ordered]@{'target' = $Target
            'href' = $UrlLink
        }
        New-HTMLTag -Tag 'a' -Attributes $AAttributes { $ImgAttributes = [ordered]@{'src' = "$Source"
                'alt' = "$AlternativeText"
                'width' = "$Height"
                'height' = "$Width"
            }
            New-HTMLTag -Tag 'img' -Attributes $ImgAttributes } }
}
function New-HTMLList {
    [CmdletBinding()]
    param([ScriptBlock]$ListItems,
        [ValidateSet('Unordered', 'Ordered')] [string] $Type = 'Unordered',
        [RGBColors] $Color,
        [RGBColors] $BackGroundColor,
        [int] $FontSize,
        [ValidateSet('normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900')][string] $FontWeight,
        [ValidateSet('normal', 'italic', 'oblique')][string] $FontStyle,
        [ValidateSet('normal', 'small-caps')][string] $FontVariant,
        [string] $FontFamily,
        [ValidateSet('left', 'center', 'right', 'justify')][string] $Alignment,
        [ValidateSet('none', 'line-through', 'overline', 'underline')][string] $TextDecoration,
        [ValidateSet('uppercase', 'lowercase', 'capitalize')][string] $TextTransform,
        [ValidateSet('rtl')][string] $Direction,
        [switch] $LineBreak)
    $newHTMLSplat = @{ }
    if ($Alignment) { $newHTMLSplat.Alignment = $Alignment }
    if ($FontSize) { $newHTMLSplat.FontSize = $FontSize }
    if ($TextTransform) { $newHTMLSplat.TextTransform = $TextTransform }
    if ($Color) { $newHTMLSplat.Color = $Color }
    if ($FontFamily) { $newHTMLSplat.FontFamily = $FontFamily }
    if ($Direction) { $newHTMLSplat.Direction = $Direction }
    if ($FontStyle) { $newHTMLSplat.FontStyle = $FontStyle }
    if ($TextDecoration) { $newHTMLSplat.TextDecoration = $TextDecoration }
    if ($BackGroundColor) { $newHTMLSplat.BackGroundColor = $BackGroundColor }
    if ($FontVariant) { $newHTMLSplat.FontVariant = $FontVariant }
    if ($FontWeight) { $newHTMLSplat.FontWeight = $FontWeight }
    if ($LineBreak) { $newHTMLSplat.LineBreak = $LineBreak }
    [bool] $SpanRequired = $false
    foreach ($Entry in $newHTMLSplat.GetEnumerator()) {
        if ((Get-ObjectCount -Object $Entry.Value) -gt 0) {
            $SpanRequired = $true
            break
        }
    }
    if ($SpanRequired) { New-HTMLSpanStyle @newHTMLSplat { if ($Type -eq 'Unordered') { New-HTMLTag -Tag 'ul' { Invoke-Command -ScriptBlock $ListItems } } else { New-HTMLTag -Tag 'ol' { Invoke-Command -ScriptBlock $ListItems } } } } else { if ($Type -eq 'Unordered') { New-HTMLTag -Tag 'ul' { Invoke-Command -ScriptBlock $ListItems } } else { New-HTMLTag -Tag 'ol' { Invoke-Command -ScriptBlock $ListItems } } }
}
function New-HTMLListItem {
    [CmdletBinding()]
    param([string[]] $Text,
        [RGBColors[]] $Color = @(),
        [RGBColors[]] $BackGroundColor = @(),
        [int[]] $FontSize = @(),
        [ValidateSet('normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900')][string[]] $FontWeight = @(),
        [ValidateSet('normal', 'italic', 'oblique')][string[]] $FontStyle = @(),
        [ValidateSet('normal', 'small-caps')][string[]] $FontVariant = @(),
        [string[]] $FontFamily = @(),
        [ValidateSet('left', 'center', 'right', 'justify')][string[]] $Alignment = @(),
        [ValidateSet('none', 'line-through', 'overline', 'underline')][string[]] $TextDecoration = @(),
        [ValidateSet('uppercase', 'lowercase', 'capitalize')][string[]] $TextTransform = @(),
        [ValidateSet('rtl')][string[]] $Direction = @(),
        [switch] $LineBreak)
    $newHTMLTextSplat = @{Alignment = $Alignment
        FontSize = $FontSize
        TextTransform = $TextTransform
        Text = $Text
        Color = $Color
        FontFamily = $FontFamily
        Direction = $Direction
        FontStyle = $FontStyle
        TextDecoration = $TextDecoration
        BackGroundColor = $BackGroundColor
        FontVariant = $FontVariant
        FontWeight = $FontWeight
        LineBreak = $LineBreak
    }
    if (($FontSize.Count -eq 0) -or ($FontSize -eq 0)) { $Size = '' } else { $size = "$($FontSize)px" }
    $Style = @{style = @{'color' = ConvertFrom-Color -Color $Color
            'background-color' = ConvertFrom-Color -Color $BackGroundColor
            'font-size' = $Size
            'font-weight' = $FontWeight
            'font-variant' = $FontVariant
            'font-family' = $FontFamily
            'font-style' = $FontStyle
            'text-align' = $Alignment
            'text-decoration' = $TextDecoration
            'text-transform' = $TextTransform
            'direction' = $Direction
        }
    }
    New-HTMLTag -Tag 'li' -Attributes $Style -Value { New-HTMLText @newHTMLTextSplat -SkipParagraph }
}
function New-HTMLLogo {
    param([String] $LogoPath,
        [string] $LeftLogoName = "Sample",
        [string] $RightLogoName = "Alternate",
        [string] $LeftLogoString,
        [string] $RightLogoString,
        [switch] $HideLogos)
    $LogoSources = Get-HTMLLogos -RightLogoName $RightLogoName -LeftLogoName $LeftLogoName -LeftLogoString $LeftLogoString -RightLogoString $RightLogoString
    Convert-StyleContent1 -Options $Options
    $Options = [PSCustomObject] @{Logos = $LogoSources
        ColorSchemes = $ColorSchemes
    }
    if ($HideLogos -eq $false) {
        $Leftlogo = $Options.Logos[$LeftLogoName]
        $Rightlogo = $Options.Logos[$RightLogoName]
        '<!-- START LOGO -->'
        $LogoContent = @"
        <table><tbody>
        <tr>
            <td class="clientlogo"><img src="$Leftlogo" /></td>
            <td class="MainLogo"><img src="$Rightlogo" /></td>
        </tr>
        </tbody></table>
"@

        $LogoContent
        '<!-- END LOGO -->'
    }
}
function New-HTMLMessage {
    param([Parameter(Mandatory = $false, Position = 0)][alias('')][ScriptBlock] $Content,
        $Text)
    $Script:HTMLSchema.Features.Message = $true
    New-HTMLTag -Tag 'div' -Attributes @{class = 'message green' } { New-HTMLTag -Tag 'div' -Attributes @{class = 'message-icon' } { New-HTMLTag -Tag 'i' -Attributes @{class = 'fa fa-bell-o' } }
        New-HTMLTag -Tag 'div' -Attributes @{class = 'message-body' } { New-HTMLTag -Tag 'p' -Attributes @{class = '' } { $Text } } }
}
Function New-HTMLPanel {
    [alias('New-HTMLColumn')]
    [CmdletBinding()]
    param ([Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $Content = $(Throw "Open curly brace with Content"),
        [alias('BackgroundShade')][RGBColors]$BackgroundColor,
        [switch] $Invisible)
    if ($null -ne $BackgroundColor) {
        $BackGroundColorFromRGB = ConvertFrom-Color -Color $BackgroundColor
        $DivColumnStyle = "background-color:$BackGroundColorFromRGB;"
    } else { $DivColumnStyle = "" }
    if ($Invisible) { $DivColumnStyle = "$DivColumnStyle box-shadow: unset !important;" }
    New-HTMLTag -Tag 'div' -Attributes @{class = "defaultPanel defaultCard"; style = $DivColumnStyle } { Invoke-Command -ScriptBlock $Content }
}
function New-HTMLResourceCSS {
    [alias('New-ResourceCSS', 'New-CSS')]
    [CmdletBinding()]
    param([alias('ScriptContent')][Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $Content,
        [string] $Link,
        [string] $ResourceComment,
        [string[]] $FilePath)
    $Output = @("<!-- CSS $ResourceComment START -->"
        foreach ($File in $FilePath) {
            if ($File -ne '') {
                if (Test-Path -LiteralPath $File) { New-HTMLTag -Tag 'style' -Attributes @{type = 'text/css' } { Write-Verbose "New-HTMLResourceCSS - Reading file from $File"
                        Get-Content -LiteralPath $File }
                }
            }
        }
        foreach ($L in $Link) {
            if ($L -ne '') {
                Write-Verbose "New-HTMLResourceCSS - Adding link $L"
                New-HTMLTag -Tag 'link' -Attributes @{rel = "stylesheet"; type = "text/css"; href = $L } -SelfClosing
            }
        }
        "<!-- CSS $ResourceComment END -->")
    if ($Output.Count -gt 2) { $Output }
}
function New-HTMLResourceJS {
    [alias('New-ResourceJS', 'New-JavaScript')]
    [CmdletBinding()]
    param([alias('ScriptContent')][Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $Content,
        [string[]] $Link,
        [string] $ResourceComment,
        [string[]] $FilePath)
    $Output = @("<!-- JS $ResourceComment START -->"
        foreach ($File in $FilePath) { if ($File -ne '') { if (Test-Path -LiteralPath $File) { New-HTMLTag -Tag 'script' -Attributes @{type = 'text/javascript' } { Get-Content -LiteralPath $File } } else { return } }
        }
        foreach ($L in $Link) { if ($L -ne '') { New-HTMLTag -Tag 'script' -Attributes @{type = "text/javascript"; src = $L } } else { return }
        }
        "<!-- JS $ResourceComment END -->")
    if ($Output.Count -gt 2) { $Output }
}
Function New-HTMLSection {
    [alias('New-HTMLContent')]
    [CmdletBinding()]
    Param ([Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $Content = $(Throw "Open curly brace"),
        [Parameter(Mandatory = $false)][string]$HeaderText,
        [RGBColors]$HeaderTextColor = [RGBColors]::White,
        [string][ValidateSet('center', 'left', 'right', 'justify')] $HeaderTextAlignment = 'center',
        [RGBColors]$HeaderBackGroundColor = [RGBColors]::DeepSkyBlue,
        [alias('BackgroundShade')][RGBColors]$BackgroundColor = [RGBColors]::None,
        [Parameter(Mandatory = $false)][switch] $CanCollapse,
        [Parameter(Mandatory = $false)][switch] $IsHidden,
        [switch] $Collapsed,
        [int] $Height,
        [switch] $Invisible)
    $RandomNumber = Get-Random
    $TextHeaderColorFromRGB = ConvertFrom-Color -Color $HeaderTextColor
    if ($CanCollapse) {
        $Script:HTMLSchema.Features.HideSection = $true
        if ($IsHidden) {
            $ShowStyle = "color: $TextHeaderColorFromRGB;"
            $HideStyle = "color: $TextHeaderColorFromRGB; display:none;"
        } else {
            if ($Collapsed) {
                $HideStyle = "color: $TextHeaderColorFromRGB; display:none;"
                $ShowStyle = "color: $TextHeaderColorFromRGB;"
                $HiddenDivStyle = 'display:none;'
            } else {
                $ShowStyle = "color: $TextHeaderColorFromRGB; display:none;"
                $HideStyle = "color: $TextHeaderColorFromRGB;"
            }
        }
    } else {
        if ($IsHidden) {
            $ShowStyle = "color: $TextHeaderColorFromRGB;"
            $HideStyle = "color: $TextHeaderColorFromRGB; display:none;"
        } else {
            $ShowStyle = "color: $TextHeaderColorFromRGB; display:none;"
            $HideStyle = "color: $TextHeaderColorFromRGB; display:none;"
        }
    }
    if ($IsHidden) {
        $DivContentStyle = @{"display" = 'none'
            "height" = if ($Height -ne 0) { "height: $($Height)px" } else { '' }
            "background-color" = ConvertFrom-Color -Color $BackgroundColor
        }
    } else {
        $DivContentStyle = @{"height" = if ($Height -ne 0) { "height: $($Height)px" } else { '' }
            "background-color" = ConvertFrom-Color -Color $BackgroundColor
        }
    }
    $DivHeaderStyle = @{"text-align" = $HeaderTextAlignment
        "background-color" = ConvertFrom-Color -Color $HeaderBackGroundColor
    }
    $HeaderStyle = "color: $TextHeaderColorFromRGB;"
    if ($Invisible) { New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultContainerOther' } -Value { New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultContainerOther defaultPanelOther' } -Value { $Object = Invoke-Command -ScriptBlock $Content
                if ($null -ne $Object) { $Object } } }
    } else { New-HTMLTag -Tag 'div' -Attributes @{'class' = "defaultSection defaultCard"; 'style' = $DivContentStyle } -Value { New-HTMLTag -Tag 'div' -Attributes @{'class' = "defaultHeader"; 'style' = $DivHeaderStyle } -Value { New-HTMLAnchor -Name $HeaderText -Text $HeaderText -Style $HeaderStyle
                New-HTMLAnchor -Id "show_$RandomNumber" -Href 'javascript:void(0)' -OnClick "show('$RandomNumber');" -Style $ShowStyle -Text '(Show)'
                New-HTMLAnchor -Id "hide_$RandomNumber" -Href 'javascript:void(0)' -OnClick "hide('$RandomNumber');" -Style $HideStyle -Text '(Hide)' }
            New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultContainerOther'; id = $RandomNumber; Style = $HiddenDivStyle } -Value { New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultContainer defaultPanelOther collapsable'; id = $RandomNumber } -Value { $Object = Invoke-Command -ScriptBlock $Content
                    if ($null -ne $Object) { $Object } } } }
    }
}
function New-HTMLSection1 {
    param([ScriptBlock] $Content,
        [string] $TextHeader)
    $ID = "AS-$(Get-RandomStringName -Size 8 -LettersOnly)"
    New-HTMLTag -Tag 'div' -Attributes @{id = 'aspect-content' } { New-HTMLTag -Tag 'div' -Attributes @{class = 'aspect-tab' } { New-HTMLTag -Tag 'input' -Attributes @{id = $ID; type = "checkbox"; class = "aspect-input"; name = "aspect" } -SelfClosing
            New-HTMLTag -Tag 'label' -Attributes @{for = $ID; class = "aspect-label" }
            New-HTMLTag -Tag 'div' -Attributes @{class = "aspect-content" } { New-HTMLTag -Tag 'div' -Attributes @{class = "aspect-info" } { New-HTMLTag -Tag 'div' -Attributes @{class = 'aspect-name' } { $TextHeader } }
                New-HTMLTag -Tag 'div' -Attributes @{class = "aspect-stat" } { New-HTMLSectionHeader -Text '14' -Type positive-count
                    New-HTMLSectionHeader -Text '12' -Type neutral-count } }
            New-HTMLTag -Tag 'div' -Attributes @{class = "aspect-tab-content" } { New-HTMLTag -Tag 'div' -Attributes @{class = "sentiment-wrapper" } { if ($null -ne $Content) { & $Content } } } } }
}
function New-HTMLSubSection {
    param([ScriptBlock] $Content,
        [string] $Text,
        [string[]] $TextHeader,
        [ValidateSet('positive', 'negative', 'neutral')][string] $Type = 'positive')
    New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultPanel defaultCar' } { New-HTMLTag -Tag 'div' { New-HTMLTag -Tag 'div' -Attributes @{class = "$Type-count opinion-header" } { New-HTMLText -Text $TextHeader }
            New-HTMLTag -Tag 'div' { if ($null -ne $Content) { & $Content } } } }
}
function New-HTMLSectionHeader {
    param([ValidateSet('all-opinions', 'positive-count', 'neutral-count', 'negative-count')][string] $Type,
        [string] $Text)
    New-HTMLTag -Tag 'span' -Attributes @{class = $Type } { $Text }
}
function New-HTMLSpanStyle {
    [CmdletBinding()]
    param([ScriptBlock] $Content,
        [nullable[RGBColors]] $Color,
        [nullable[RGBColors]] $BackGroundColor,
        [int] $FontSize,
        [ValidateSet('normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900')][string] $FontWeight,
        [ValidateSet('normal', 'italic', 'oblique')][string] $FontStyle,
        [ValidateSet('normal', 'small-caps')][string] $FontVariant,
        [string] $FontFamily,
        [ValidateSet('left', 'center', 'right', 'justify')][string] $Alignment,
        [ValidateSet('none', 'line-through', 'overline', 'underline')][string] $TextDecoration,
        [ValidateSet('uppercase', 'lowercase', 'capitalize')][string] $TextTransform,
        [ValidateSet('rtl')][string] $Direction,
        [switch] $LineBreak)
    Write-Verbose 'New-SpanStyle - BEGIN'
    if ($FontSize -eq 0) { $Size = '' } else { $size = "$($FontSize)px" }
    $Style = @{style = @{'color' = ConvertFrom-Color -Color $Color
            'background-color' = ConvertFrom-Color -Color $BackGroundColor
            'font-size' = $Size
            'font-weight' = $FontWeight
            'font-variant' = $FontVariant
            'font-family' = $FontFamily
            'font-style' = $FontStyle
            'text-align' = $Alignment
            'text-decoration' = $TextDecoration
            'text-transform' = $TextTransform
            'direction' = $Direction
        }
    }
    if ($Alignment) { $StyleDiv = @{ }
        $StyleDiv.Align = $Alignment
        New-HTMLTag -Tag 'div' -Attributes $StyleDiv { New-HTMLTag -Tag 'span' -Attributes $Style { Invoke-Command -ScriptBlock $Content } }
    } else { New-HTMLTag -Tag 'span' -Attributes $Style { Invoke-Command -ScriptBlock $Content } }
}
function New-HTMLStatus {
    param([Parameter(Mandatory = $false, Position = 0)][alias('')][ScriptBlock] $Content)
    $Script:HTMLSchema.Features.StatusButtonical = $true
    New-HTMLTag -Tag 'div' -Attributes @{class = 'buttonicalService' } { Invoke-Command -ScriptBlock $Content }
}
function New-HTMLStatusItem {
    param($ServiceName,
        $ServiceStatus,
        [ValidateSet('Dead', 'Bad', 'Good')]$Icon = 'Good',
        [ValidateSet('0%', '10%', '30%', '70%', '100%')][string] $Percentage = '100%')
    if ($Icon -eq 'Dead') { $IconType = 'performanceDead' } elseif ($Icon -eq 'Bad') { $IconType = 'performanceProblem' } elseif ($Icon -eq 'Good') { }
    if ($Percentage -eq '100%') { $Colors = 'background-color: #0ef49b;' } elseif ($Percentage -eq '70%') { $Colors = 'background-color: #d2dc69;' } elseif ($Percentage -eq '30%') { $Colors = 'background-color: #faa04b;' } elseif ($Percentage -eq '10%') { $Colors = 'background-color: #ff9035;' } elseif ($Percentage -eq '0%') { $Colors = 'background-color: #ff5a64;' }
    New-HTMLTag -Tag 'div' -Attributes @{class = 'buttonical'; style = $Colors } -Value { New-HTMLTag -Tag 'div' -Attributes @{class = 'label' } { New-HTMLTag -Tag 'span' -Attributes @{class = 'performance' } { $ServiceName } }
        New-HTMLTag -Tag 'div' -Attributes @{class = 'middle' }
        New-HTMLTag -Tag 'div' -Attributes @{class = 'status' } { New-HTMLTag -Tag 'input' -Attributes @{name = Get-Random; type = 'radio'; value = 'other-item'; checked = 'true' } -SelfClosing
            New-HTMLTag -Tag 'span' -Attributes @{class = "performance $IconType" } { $ServiceStatus } } }
}
function New-HTMLTab {
    [CmdletBinding()]
    param([Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $HtmlData = $(Throw "No curly brace?)"),
        [Parameter(Mandatory = $false, Position = 1)][String]$TabHeading,
        [string] $TabIcon = 'fas fa-bomb',
        [alias('Name')][string] $TabName)
    $Script:HTMLSchema.Features.Tabs = $true
    $Script:HTMLSchema.Features.JQuery = $true
    foreach ($Tab in $Script:HTMLSchema.TabsHeaders) { $Tab.Current = $false }
    $Tab = @{ }
    $Tab.ID = "Tab-$(Get-RandomStringName -Size 8)"
    $Tab.Name = $TabName
    $Tab.Current = $true
    if ($Script:HTMLSchema.TabsHeaders | Where-Object { $_.Active -eq $true }) { $Tab.Active = $false } else { $Tab.Active = $true }
$Tab.TabIcon = $TabIcon
$Script:HTMLSchema.TabsHeaders.Add($Tab)
if ($Tab.Active) { $Class = 'tabs-content active' } else { $Class = 'tabs-content' }
New-HTMLTag -Tag 'div' -Attributes @{id = $Tab.ID; class = $Class } { if (-not [string]::IsNullOrWhiteSpace($TabHeading)) { New-HTMLTag -Tag 'h7' { $TabHeading } }
    Invoke-Command -ScriptBlock $HtmlData }
}
function New-HTMLTabHead {
    [CmdletBinding()]
    Param ()
    New-HTMLTag -Tag 'div' -Attributes @{class = 'tabsWrapper' } { New-HTMLTag -Tag 'div' -Attributes @{class = 'tabs' } { New-HTMLTag -Tag 'div' -Attributes @{class = 'selector' }
            foreach ($Tab in $Script:HTMLSchema.TabsHeaders) {
                $AttributesA = @{'href' = 'javascript:void(0)'
                    'data-id' = "$($Tab.Id)"
                }
                if ($Tab.Active) { $AttributesA.class = 'active' } else { $AttributesA.class = '' }
                New-HTMLTag -Tag 'a' -Attributes $AttributesA { New-HTMLTag -Tag 'div' -Attributes @{class = $Tab.TabIcon } -Value { $Tab.Name } }
            } } }
}
function New-HTMLTable {
    [CmdletBinding()]
    param([Parameter(Mandatory = $false, Position = 0)][ScriptBlock] $HTML,
        [Parameter(Mandatory = $false, Position = 1)][ScriptBlock] $PreContent,
        [Parameter(Mandatory = $false, Position = 2)][ScriptBlock] $PostContent,
        [alias('ArrayOfObjects', 'Object', 'Table')][Array] $DataTable,
        [string[]][ValidateSet('copyHtml5', 'excelHtml5', 'csvHtml5', 'pdfHtml5')] $Buttons = @('copyHtml5', 'excelHtml5', 'csvHtml5', 'pdfHtml5'),
        [string[]][ValidateSet('numbers', 'simple', 'simple_numbers', 'full', 'full_numbers', 'first_last_numbers')] $PagingStyle = 'full_numbers',
        [int[]]$PagingOptions = @(15, 25, 50, 100),
        [switch]$DisablePaging,
        [switch]$DisableOrdering,
        [switch]$DisableInfo,
        [switch]$HideFooter,
        [switch]$DisableColumnReorder,
        [switch]$DisableProcessing,
        [switch]$DisableResponsiveTable,
        [switch]$DisableSelect,
        [switch]$DisableStateSave,
        [switch]$DisableSearch,
        [switch]$ScrollCollapse,
        [switch]$OrderMulti,
        [switch]$Filtering,
        [ValidateSet('Top', 'Bottom', 'Both')][string]$FilteringLocation = 'Bottom',
        [string[]][ValidateSet('display', 'cell-border', 'compact', 'hover', 'nowrap', 'order-column', 'row-border', 'stripe')] $Style = @('display', 'compact'),
        [switch]$Simplify,
        [string]$TextWhenNoData = 'No data available.',
        [int] $ScreenSizePercent = 0,
        [string[]] $DefaultSortColumn,
        [int[]] $DefaultSortIndex,
        [ValidateSet('Ascending', 'Descending')][string] $DefaultSortOrder = 'Ascending',
        [string[]] $DateTimeSortingFormat,
        [alias('Search')][string]$Find,
        [switch] $InvokeHTMLTags,
        [switch] $DisableNewLine)
    if (-not $Script:HTMLSchema.Features) {
        Write-Warning 'New-HTMLTable - Creation of HTML aborted. Most likely New-HTML is missing.'
        Exit
    }
    [Array] $Output = $HTML.Ast.EndBlock.Statements.Extent
    [Array] $OutputText = foreach ($Line in $Output) { [string] $Line + [System.Environment]::NewLine }
    $ConditionalFormattingText = foreach ($Line in $OutputText) { if ($Line.StartsWith('New-HTMLTableCondition') -or $Line.StartsWith('TableConditionalFormatting')) { $Line } }
    $OtherHTMLText = foreach ($Line in $OutputText) { if ((-not $Line.StartsWith('New-HTMLTableCondition')) -and (-not $Line.StartsWith('TableConditionalFormatting'))) { $Line } }
    if ($ConditionalFormattingText.Count -gt 0) { $ConditionalFormatting = [scriptblock]::Create($ConditionalFormattingText) }
    if ($OtherHTMLText.Count -gt 0) { $OtherHTML = [scriptblock]::Create($OtherHTMLText) }
    [string] $DataTableName = "DT-$(Get-RandomStringName -Size 8 -LettersOnly)"
    if ($null -eq $DataTable -or $DataTable.Count -eq 0) { $DataTable = $TextWhenNoData }
    if ($DataTable[0] -is [System.Collections.IDictionary]) {
        Write-Verbose 'New-HTMLTable - Working with IDictionary'
        [Array ] $Table = $($DataTable).GetEnumerator() | Select-Object Name, Value | ConvertTo-Html -Fragment | Select-Object -SkipLast 1 | Select-Object -Skip 2
} elseif ($DataTable[0] -is [string]) { [Array] $Table = $DataTable | ForEach-Object { [PSCustomObject]@{'Name' = $_ } } | ConvertTo-Html -Fragment | Select-Object -SkipLast 1 | Select-Object -Skip 2
} else {
    Write-Verbose 'New-HTMLTable - Working with Objects'
    [Array] $Table = $DataTable | ConvertTo-Html -Fragment | Select-Object -SkipLast 1 | Select-Object -Skip 2
}
[string] $Header = $Table | Select-Object -First 1
[string[]] $HeaderNames = $Header -replace '</th></tr>' -replace '<tr><th>' -split '</th><th>'
$Table = $Table | Select-Object -Skip 1
$Options = [ordered] @{dom = 'Bfrtip'
    buttons = @($Buttons)
    "colReorder" = -not $DisableColumnReorder.IsPresent
    "paging" = -not $DisablePaging
    "scrollCollapse" = $ScrollCollapse.IsPresent
    "pagingType" = $PagingStyle
    "lengthMenu" = @(@($PagingOptions, -1)
        @($PagingOptions, "All"))
    "ordering" = -not $DisableOrdering.IsPresent
    "order" = @()
    "info" = -not $DisableInfo.IsPresent
    "procesing" = -not $DisableProcessing.IsPresent
    "responsive" = @{details = -not $DisableResponsiveTable.IsPresent }
    "select" = -not $DisableSelect.IsPresent
    "searching" = -not $DisableSearch.IsPresent
    "stateSave" = -not $DisableStateSave.IsPresent
}
if ($OrderMulti) { $Options.orderMulti = $OrderMulti.IsPresent }
if ($Find -ne '') { $Options.search = @{search = $Find }
}
if ($DefaultSortOrder -eq 'Ascending') { $Sort = 'asc' } else { $Sort = 'dsc' }
if ($DefaultSortColumn.Count -gt 0) {
    $ColumnsOrder = foreach ($Column in $DefaultSortColumn) {
        $DefaultSortingNumber = ($HeaderNames).ToLower().IndexOf($Column.ToLower())
        if ($DefaultSortingNumber -ne -1) { , @($DefaultSortingNumber, $Sort) }
    }
}
if ($DefaultSortIndex.Count -gt 0 -and $DefaultSortColumn.Count -eq 0) {
    $ColumnsOrder = foreach ($Column in $DefaultSortIndex) { if ($Column -ne -1) { , @($Column, $Sort) } }
    $Options."order" = @($ColumnsOrder)
    $Options.colReorder = $false
}
if ($ScreenSizePercent -gt 0) { $Options."scrollY" = "$($ScreenSizePercent)vh" }
if ($null -ne $ConditionalFormatting) { $Options.columnDefs = '' }
$Options = $Options | ConvertTo-Json -Depth 6
if ($null -ne $ConditionalFormatting) { $Conditional = Invoke-Command -ScriptBlock $ConditionalFormatting }
$Options = New-TableConditionalFormatting -Options $Options -ConditionalFormatting $Conditional -Header $HeaderNames
[Array] $Tabs = ($Script:HTMLSchema.TabsHeaders | Where-Object { $_.Current -eq $true })
if ($Tabs.Count -eq 0) { $Tab = @{Active = $true }
} else { $Tab = $Tabs[0] }
if (-not $Simplify) {
    $Script:HTMLSchema.Features.DataTables = $true
    $Script:HTMLSchema.Features.DataTablesPDF = $true
    $Script:HTMLSchema.Features.DataTablesExcel = $true
    $TableAttributes = @{id = $DataTableName; class = "$($Style -join ' ')" }
    $SortingFormatDateTime = Add-CustomFormatForDatetimeSorting -DateTimeSortingFormat $DateTimeSortingFormat
    $FilteringOutput = Add-TableFiltering -Filtering $Filtering -FilteringLocation $FilteringLocation
    $FilteringTopCode = $FilteringOutput.FilteringTopCode
    $FilteringBottomCode = $FilteringOutput.FilteringBottomCode
    $LoadSavedState = Add-TableState -DataTableName $DataTableName -Filtering $Filtering -FilteringLocation $FilteringLocation -SavedState (-not $DisableStateSave)
    if ($Tab.Active -eq $true) {
        New-HTMLTag -Tag 'script' { @"
                `$(document).ready(function() {
                    $SortingFormatDateTime
                    $LoadSavedState
                    $FilteringTopCode
                    // Table code
                    var table = `$('#$DataTableName').DataTable(
                        $($Options)
                    );
                    $FilteringBottomCode
                });
"@
 }
    } else {
        [string] $TabName = $Tab.Id
        New-HTMLTag -Tag 'script' { @"
                    `$(document).ready(function() {
                        $SortingFormatDateTime
                        `$('.tabs').on('click', 'a', function (event) {
                            if (`$(event.currentTarget).attr("data-id") == "$TabName" && !$.fn.dataTable.isDataTable("#$DataTableName")) {
                                $LoadSavedState
                                $FilteringTopCode
                                // Table code
                                var table = `$('#$DataTableName').DataTable(
                                    $($Options)
                                );
                                $FilteringBottomCode
                            };
                        });
                    });
"@
 }
    }
} else { $TableAttributes = @{class = 'sortable' }
}
if ($InvokeHTMLTags) { $Table = $Table -replace '&lt;', '<' -replace '&gt;', '>' -replace '&amp;nbsp;', ' ' -replace '&quot;', '"' -replace '&#39;', "'" }
if (-not $DisableNewLine) { $Table = $Table -replace '(?m)\s+$', "<BR>" }
if ($OtherHTML) { $BeforeTableCode = Invoke-Command -ScriptBlock $OtherHTML } else { $BeforeTableCode = '' }
if ($PreContent) { $BeforeTable = Invoke-Command -ScriptBlock $PreContent } else { $BeforeTable = '' }
if ($PostContent) { $AfterTable = Invoke-Command -ScriptBlock $PostContent } else { $AfterTable = '' }
New-HTMLTag -Tag 'div' -Attributes @{class = 'defaultPanelOther' } -Value { $BeforeTableCode
    $BeforeTable
    New-HTMLTag -Tag 'table' -Attributes $TableAttributes { New-HTMLTag -Tag 'thead' { $Header }
        New-HTMLTag -Tag 'tbody' { $Table }
        if (-not $HideFooter) { New-HTMLTag -Tag 'tfoot' { $Header } } }
    $AfterTable }
}
function New-HTMLTableCondition {
    [CmdletBinding()]
    param([alias('ColumnName')][string] $Name,
        [ValidateSet('number', 'string')][string] $Type,
        [ValidateSet('lt', 'le', 'eq', 'ge', 'gt')][string] $Operator,
        [Object] $Value,
        [switch] $Row,
        [nullable[RGBColors]] $Color,
        [nullable[RGBColors]] $BackgroundColor)
    return [PSCustomObject] @{Row = $Row; Type = $Type; Name = $Name; Operator = $Operator; Value = $Value; Color = $Color; BackgroundColor = $BackgroundColor }
}
function New-HTMLTag {
    [CmdletBinding()]
    param([Parameter(Mandatory = $false, Position = 0)][alias('Content')][ScriptBlock] $Value,
        [Parameter(Mandatory = $true, Position = 1)][string] $Tag,
        [System.Collections.IDictionary] $Attributes,
        [switch] $SelfClosing)
    $HTMLTag = [Ordered] @{Tag = $Tag
        Attributes = $Attributes
        Value = if ($null -eq $Value) { '' } else { Invoke-Command -ScriptBlock $Value }
        SelfClosing = $SelfClosing
    }
    $HTML = Set-Tag -HtmlObject $HTMLTag
    return $HTML
}
function New-HTMLText {
    [CmdletBinding()]
    param([string[]] $Text,
        [RGBColors[]] $Color = @(),
        [RGBColors[]] $BackGroundColor = @(),
        [int[]] $FontSize = @(),
        [ValidateSet('normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900')][string[]] $FontWeight = @(),
        [ValidateSet('normal', 'italic', 'oblique')][string[]] $FontStyle = @(),
        [ValidateSet('normal', 'small-caps')][string[]] $FontVariant = @(),
        [string[]] $FontFamily = @(),
        [ValidateSet('left', 'center', 'right', 'justify')][string[]] $Alignment = @(),
        [ValidateSet('none', 'line-through', 'overline', 'underline')][string[]] $TextDecoration = @(),
        [ValidateSet('uppercase', 'lowercase', 'capitalize')][string[]] $TextTransform = @(),
        [ValidateSet('rtl')][string[]] $Direction = @(),
        [switch] $LineBreak,
        [switch] $SkipParagraph)
    $DefaultColor = $Color[0]
    $DefaultFontSize = $FontSize[0]
    $DefaultFontWeight = if ($null -eq $FontWeight[0]) { '' } else { $FontWeight[0] }
    $DefaultBackGroundColor = $BackGroundColor[0]
    $DefaultFontFamily = if ($null -eq $FontFamily[0]) { '' } else { $FontFamily[0] }
    $DefaultFontStyle = if ($null -eq $FontStyle[0]) { '' } else { $FontStyle[0] }
    $DefaultTextDecoration = if ($null -eq $TextDecoration[0]) { '' } else { $TextDecoration[0] }
    $DefaultTextTransform = if ($null -eq $TextTransform[0]) { '' } else { $TextTransform[0] }
    $DefaultFontVariant = if ($null -eq $FontVariant[0]) { '' } else { $FontVariant }
    $DefaultDirection = if ($null -eq $Direction[0]) { '' } else { $Direction[0] }
    $DefaultAlignment = if ($null -eq $Alignment[0]) { '' } else { $Alignment[0] }
    $Output = for ($i = 0; $i -lt $Text.Count; $i++) {
        if ($null -eq $FontWeight[$i]) { $ParamFontWeight = $DefaultFontWeight } else { $ParamFontWeight = $FontWeight[$i] }
        if ($null -eq $FontSize[$i]) { $ParamFontSize = $DefaultFontSize } else { $ParamFontSize = $FontSize[$i] }
        if ($null -eq $Color[$i]) { $ParamColor = $DefaultColor } else { $ParamColor = $Color[$i] }
        if ($null -eq $BackGroundColor[$i]) { $ParamBackGroundColor = $DefaultBackGroundColor } else { $ParamBackGroundColor = $BackGroundColor[$i] }
        if ($null -eq $FontFamily[$i]) { $ParamFontFamily = $DefaultFontFamily } else { $ParamFontFamily = $FontFamily[$i] }
        if ($null -eq $FontStyle[$i]) { $ParamFontStyle = $DefaultFontStyle } else { $ParamFontStyle = $FontStyle[$i] }
        if ($null -eq $TextDecoration[$i]) { $ParamTextDecoration = $DefaultTextDecoration } else { $ParamTextDecoration = $TextDecoration[$i] }
        if ($null -eq $TextTransform[$i]) { $ParamTextTransform = $DefaultTextTransform } else { $ParamTextTransform = $TextTransform[$i] }
        if ($null -eq $FontVariant[$i]) { $ParamFontVariant = $DefaultFontVariant } else { $ParamFontVariant = $FontVariant[$i] }
        if ($null -eq $Direction[$i]) { $ParamDirection = $DefaultDirection } else { $ParamDirection = $Direction[$i] }
        if ($null -eq $Alignment[$i]) { $ParamAlignment = $DefaultAlignment } else { $ParamAlignment = $Alignment[$i] }
        $newSpanTextSplat = @{ }
        $newSpanTextSplat.Color = $ParamColor
        $newSpanTextSplat.BackGroundColor = $ParamBackGroundColor
        $newSpanTextSplat.FontSize = $ParamFontSize
        if ($ParamFontWeight -ne '') { $newSpanTextSplat.FontWeight = $ParamFontWeight }
        $newSpanTextSplat.FontFamily = $ParamFontFamily
        if ($ParamFontStyle -ne '') { $newSpanTextSplat.FontStyle = $ParamFontStyle }
        if ($ParamFontVariant -ne '') { $newSpanTextSplat.FontVariant = $ParamFontVariant }
        if ($ParamTextDecoration -ne '') { $newSpanTextSplat.TextDecoration = $ParamTextDecoration }
        if ($ParamTextTransform -ne '') { $newSpanTextSplat.TextTransform = $ParamTextTransform }
        if ($ParamDirection -ne '') { $newSpanTextSplat.Direction = $ParamDirection }
        if ($ParamAlignment -ne '') { $newSpanTextSplat.Alignment = $ParamAlignment }
        $newSpanTextSplat.LineBreak = $LineBreak
        New-HTMLSpanStyle @newSpanTextSplat { if ($Text[$i] -match "\[([^\[]*)\)") {
                $RegexBrackets1 = [regex] "\[([^\[]*)\]"
                $RegexBrackets2 = [regex] "\(([^\[]*)\)"
                $RegexBrackets3 = [regex] "\[([^\[]*)\)"
                $Text1 = $RegexBrackets1.match($Text[$i]).Groups[1].value
                $Text2 = $RegexBrackets2.match($Text[$i]).Groups[1].value
                $Text3 = $RegexBrackets3.match($Text[$i]).Groups[0].value
                if ($Text1 -ne '' -and $Text2 -ne '') {
                    $Link = New-HTMLAnchor -HrefLink $Text2 -Text $Text1
                    $Text[$i].Replace($Text3, $Link)
                }
            } else { $Text[$i] } }
    }
    if ($SkipParagraph) { $Output -join '' } else { New-HTMLTag -Tag 'div' { $Output } }
    if ($LineBreak) { New-HTMLTag -Tag 'br' -SelfClosing }
}
function New-HTMLTimeline {
    param([Parameter(Mandatory = $false, Position = 0)][alias('TimeLineItems')][ScriptBlock] $Content)
    $Script:HTMLSchema.Features.TimeLine = $true
    New-HTMLTag -Tag 'div' -Attributes @{class = 'timelineSimpleContainer' } { if ($null -eq $Value) { '' } else { Invoke-Command -ScriptBlock $Content } }
}
function New-HTMLTimelineItem {
    [CmdletBinding()]
    param([DateTime] $Date = (Get-Date),
        [string] $HeadingText,
        [string] $Text,
        [nullable[RGBColors]] $Color)
    $Attributes = @{class = 'timelineSimple-item'
        "date-is" = $Date
    }
    if ($null -ne $Color) {
        $RGBcolor = ConvertFrom-Color -Color $Color
        $Style = "color: $RGBcolor;"
    } else { $Style = '' }
    New-HTMLTag -Tag 'div' -Attributes $Attributes -Value { New-HTMLTag -Tag 'h1' -Attributes @{class = 'timelineSimple'; style = $style } { $HeadingText }
        New-HTMLTag -Tag 'p' -Attributes @{class = 'timelineSimple' } { $Text -Replace [Environment]::NewLine, '<br>' -replace '\n', '<br>' } }
}
function New-HTMLToast {
    [CmdletBinding()]
    param([string] $TextHeader,
        [string] $Text,
        [ValidateSet('Green', 'Blue', 'Orange')] $Color = "Green",
        [ValidateSet('Success', 'Information', 'Exclamation')][string] $Icon = 'Success',
        [string] $Type = 'central')
    $Script:HTMLSchema.Features.Toast = $true
    if ($Type -eq 'central') { $DivClass = "toast $($Color.ToLower()) central" } else { $DivClass = "toast $($Color.ToLower())" }
    New-HTMLTag -Tag 'div' -Attributes @{class = $DivClass } { New-HTMLTag -Tag 'div' -Attributes @{class = 'toast__icon' } { if ($Icon -eq 'Success') { New-IconSuccess } elseif ($Icon -eq 'Information') { New-IconInfo } elseif ($Icon -eq 'Exclamation') { New-IconExclamation } }
        New-HTMLTag -Tag 'div' -Attributes @{class = 'toast__content' } { New-HTMLTag -Tag 'p' -Attributes @{class = 'toast__type' } { $TextHeader }
            New-HTMLTag -Tag 'p' -Attributes @{class = 'toast__message' } { $Text } } }
}
function New-IconExclamation {
    <#
    .SYNOPSIS
    This function is used for New-HTMLToast
     
    .DESCRIPTION
    Long description
     
    .EXAMPLE
    An example
     
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    param()
    $SvgAttributes = [ordered] @{version = "1.1"
        class = "toast__svg"
        xmlns = "http://www.w3.org/2000/svg"
        'xmlns:xlink' = "http://www.w3.org/1999/xlink"
        x = "0px"
        y = "0px"
        viewBox = "0 0 301.691 301.691"
        style = "enable-background:new 0 0 301.691 301.691;"
        'xml:space' = "preserve"
    }
    New-HTMLTag -Tag 'svg' -Attributes $SvgAttributes { $Points = @{points = "119.151,0 129.6,218.406 172.06,218.406 182.54,0 " }
        New-HTMLTag -Tag 'polygon' -Attributes $Points
        $React = @{x = "130.563"
            y = "261.168"
            width = "40.525"
            height = "40.523"
        }
        New-HTMLTag -Tag 'react' -Attributes $React }
}
function New-IconInfo {
    <#
    .SYNOPSIS
    This function is used for New-HTMLToast
     
    .DESCRIPTION
    Long description
     
    .EXAMPLE
    An example
     
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    param()
    $SvgAttributes = [ordered] @{version = "1.1"
        class = "toast__svg"
        xmlns = "http://www.w3.org/2000/svg"
        'xmlns:xlink' = "http://www.w3.org/1999/xlink"
        x = "0px"
        y = "0px"
        viewBox = "0 0 32 32"
        style = "enable-background:new 0 0 32 32;"
        'xml:space' = "preserve"
    }
    New-HTMLTag -Tag 'svg' -Attributes $SvgAttributes { $PathAttributes = @{d = "M10,16c1.105,0,2,0.895,2,2v8c0,1.105-0.895,2-2,2H8v4h16v-4h-1.992c-1.102,0-2-0.895-2-2L20,12H8 v4H10z" }
        New-HTMLTag -Tag 'path' -Attributes $PathAttributes
        New-HTMLTag -Tag 'circle' -Attributes @{cx = "16"; cy = "4"; r = "4" } }
}
function New-IconSuccess {
    <#
    .SYNOPSIS
    This function is used for New-HTMLToast
     
    .DESCRIPTION
    Long description
     
    .EXAMPLE
    An example
     
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    param()
    $SvgAttributes = [ordered] @{version = "1.1"
        class = "toast__svg"
        xmlns = "http://www.w3.org/2000/svg"
        'xmlns:xlink' = "http://www.w3.org/1999/xlink"
        x = "0px"
        y = "0px"
        viewBox = "0 0 512 512"
        style = "enable-background:new 0 0 512 512;"
        'xml:space' = "preserve"
    }
    New-HTMLTag -Tag 'svg' -Attributes $SvgAttributes { $PathAttributes = @{d = "M504.502,75.496c-9.997-9.998-26.205-9.998-36.204,0L161.594,382.203L43.702,264.311c-9.997-9.998-26.205-9.997-36.204,0 c-9.998,9.997-9.998,26.205,0,36.203l135.994,135.992c9.994,9.997,26.214,9.99,36.204,0L504.502,111.7 C514.5,101.703,514.499,85.494,504.502,75.496z" }
        New-HTMLTag -Tag 'path' -Attributes $PathAttributes }
}
function New-TableConditionalFormatting {
    [CmdletBinding()]
    param([string] $Options,
        [Array] $ConditionalFormatting,
        [string[]] $Header)
    if ($ConditionalFormatting.Count -gt 0) {
        foreach ($Formatting in $ConditionalFormatting) { if ($Formatting.Operator -eq 'gt') { $Formatting.Operator = '>' } elseif ($Formatting.Operator -eq 'lt') { $Formatting.Operator = '<' } elseif ($Formatting.Operator -eq 'eq') { $Formatting.Operator = '==' } elseif ($Formatting.Operator -eq 'le') { $Formatting.Operator = '<=' } elseif ($Formatting.Operator -eq 'ge') { $Formatting.Operator = '>=' } }
        $Condition1 = '"createdRow": function (row, data, dataIndex, column) {'
        $Condition3 = foreach ($Condition in $ConditionalFormatting) {
            $ConditionHeaderNr = $Header.ToLower().IndexOf($($Condition.Name.ToLower()))
            [string] $ColorJSDefinition = ''
            [string] $ColorBackgroundJSDefinition = ''
            if ($null -ne $Condition.Color) {
                $RGBColor = (ConvertFrom-Color -Color $Condition.Color)
                $C = @{"color" = $RGBColor } | ConvertTo-Json
            $ColorJSDefinition = ".css($C)"
        }
        if ($null -ne $Condition.BackgroundColor) {
            $RGBBackgroundColor = (ConvertFrom-Color -Color $Condition.BackgroundColor)
            $BG = @{"background-color" = $RGBBackgroundColor } | ConvertTo-Json
        $ColorBackgroundJSDefinition = ".css($BG)"
    }
    if ($null -eq $Condition.Type -or $Condition.Type -eq 'number') { "if (data[$ConditionHeaderNr] $($Condition.Operator) $($Condition.Value)) {" } elseif ($Condition.Type -eq 'string') { "if (data[$ConditionHeaderNr] $($Condition.Operator) '$($Condition.Value)') {" } elseif ($Condition.Type -eq 'date') { "if (new Date(data[$ConditionHeaderNr]) $($Condition.Operator) new Date('$($Condition.Value)')) {" }
    if ($null -ne $Condition.Row -and $Condition.Row -eq $true) { "`$(column)$($ColorJSDefinition)$($ColorBackgroundJSDefinition);" } else { "`$(column[$ConditionHeaderNr])$($ColorJSDefinition)$($ColorBackgroundJSDefinition);" }
    "}"
}
$Condition5 = '}'
$Test = $Condition1 + $Condition3 + $Condition5
$Options = $Options -Replace ('"columnDefs": ""', $Test)
}
return $Options
}
function Out-HtmlView {
    <#
    .SYNOPSIS
    Small function that allows to send output to HTML
 
    .DESCRIPTION
    Small function that allows to send output to HTML. When displaying in HTML it allows data to output to EXCEL, CSV and PDF. It allows sorting, searching and so on.
 
    .PARAMETER Table
    Data you want to display
 
    .PARAMETER Title
    Title of HTML Window
 
    .PARAMETER DefaultSortColumn
    Sort by Column Name
 
    .PARAMETER DefaultSortIndex
    Sort by Column Index
 
    .EXAMPLE
    Get-Process | Select-Object -First 5 | Out-HtmlView
 
    .NOTES
    General notes
    #>

    [alias('Out-GridHtml', 'ohv')]
    [CmdletBinding()]
    param([Parameter(ValueFromPipeline = $true, Mandatory = $true)] $Table,
        [string[]] $PriorityProperties,
        [string] $Title = 'Out-HTMLView',
        [string[]] $DefaultSortColumn,
        [int[]] $DefaultSortIndex,
        [string] $FilePath,
        [switch] $DisablePaging,
        [switch] $PassThru,
        [switch]$Filtering,
        [ValidateSet('Top', 'Bottom', 'Both')][string]$FilteringLocation = 'Bottom',
        [alias('Search')][string]$Find,
        [switch] $InvokeHTMLTags,
        [switch] $DisableNewLine)
    Begin {
        $DataTable = [System.Collections.Generic.List[Object]]::new()
        if ($FilePath -eq '') { $FilePath = Get-FileName -Extension 'html' -Temporary }
    }
    Process { foreach ($T in $Table) { $DataTable.Add($T) } }
    End {
        if ($DataTable.Count -gt 0) {
            $Properties = $DataTable[0].PSObject.Properties.Name
            $RemainingProperties = foreach ($Property in $Properties) { if ($PriorityProperties -notcontains $Property) { $Property } }
            $AllProperties = $PriorityProperties + $RemainingProperties
            $DataTable = $DataTable | Select-Object -Property $AllProperties
    }
    New-HTML -FilePath $FilePath -UseCssLinks -UseJavaScriptLinks -TitleText $Title -ShowHTML { New-HTMLTable -DataTable $DataTable -DefaultSortColumn $DefaultSortColumn -DefaultSortIndex $DefaultSortIndex -DisablePaging:$DisablePaging -Filtering:$Filtering -FilteringLocation $FilteringLocation -Find $Find -InvokeHTMLTags:$InvokeHTMLTags -DisableNewLine:$DisableNewLine }
    if ($PassThru) { $DataTable }
}
}
Function Save-HTML {
    <#
    .SYNOPSIS
    Short description
 
    .DESCRIPTION
    Long description
 
    .PARAMETER FilePath
    Parameter description
 
    .PARAMETER HTML
    Parameter description
 
    .PARAMETER ShowReport
    Parameter description
 
    .EXAMPLE
    An example
 
    .NOTES
    General notes
    #>

    [CmdletBinding()]
    Param
    ([Parameter(Mandatory = $false)][string]$FilePath,
        [Parameter(Mandatory = $true)][Array] $HTML,
        [Parameter(Mandatory = $false)][switch]$ShowHTML,
        [ValidateSet('Unknown', 'String', 'Unicode', 'Byte', 'BigEndianUnicode', 'UTF8', 'UTF7', 'UTF32', 'Ascii', 'Default', 'Oem', 'BigEndianUTF32')] $Encoding = 'UTF8',
        [bool] $Supress = $true)
    if ([string]::IsNullOrEmpty($FilePath)) {
        $FilePath = Get-FileName -Temporary -Extension 'html'
        Write-Warning "Save-HTML - FilePath parameter $FilePath is empty, using Temporary $FilePath"
    } else { if (Test-Path -LiteralPath $FilePath) { Write-Warning "Save-HTML - Path $FilePath already exists. Report will be overwritten." } }
    Write-Verbose "Save-HTML - Saving HTML to file $FilePath"
    try {
        $HTML | Set-Content -LiteralPath $FilePath -Force -Encoding $Encoding
    if (-not $Supress) { $FilePath }
} catch {
    $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
    Write-Warning "Save-HTML - Failed with error: $ErrorMessage"
}
if ($ShowHTML) {
    try { Invoke-Item -LiteralPath $FilePath -ErrorAction Stop } catch {
        $ErrorMessage = $_.Exception.Message -replace "`n", " " -replace "`r", " "
        Write-Warning "Save-HTML - couldn't open file $FilePath in a browser. Error: $ErrorMessage"
    }
}
}
$Script:Configuration = [ordered] @{Features = [ordered] @{Default = @{Comment = 'Always Required Default Visual Settings'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\default.css" }
        }
        DefaultHeadings = @{Comment = 'Always Required Default Headings'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\headings.css" }
        }
        Accordion = @{Comment = 'Accordion'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\accordion-1.css" }
        }
        CodeBlocks = @{Comment = 'EnlighterJS CodeBlocks'
            Header = @{CssLink = 'https://evotec.xyz/wp-content/uploads/pswritehtml/enlighterjs.min.css'
                Css = "$PSScriptRoot\Resources\CSS\enlighterjs.min.css"
                JsLink = 'https://evotec.xyz/wp-content/uploads/pswritehtml/enlighterjs.min.js'
                JS = "$PSScriptRoot\Resources\JS\enlighterjs.min.js"
            }
            Footer = @{ }
            HeaderAlways = @{ }
            FooterAlways = @{JS = "$PSScriptRoot\Resources\JS\enlighterjs-footer.js" }
        }
        Charts = @{Comment = 'Charts JS'
            Header = @{JsLink = 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js' }
        }
        ChartsApex = @{Comment = 'Apex Charts'
            Header = @{JsLink = 'https://cdn.jsdelivr.net/npm/apexcharts@latest'
                JS = "$PSScriptRoot\Resources\JS\apexcharts.min.js"
            }
            HeaderAlways = @{ }
        }
        Jquery = @{Comment = 'Jquery'
            Header = @{JsLink = 'http://code.jquery.com/jquery-3.3.1.min.js'
                Js = "$PSScriptRoot\Resources\JS\jquery-3.3.1.min.js"
            }
        }
        DataTables = @{Comment = 'DataTables'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\datatables.css"
                CssNoscript = "$PSScriptRoot\Resources\CSS\datatables.noscript.css"
            }
            Header = @{CssLink = 'https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/af-2.3.2/b-1.5.4/b-colvis-1.5.4/b-html5-1.5.4/b-print-1.5.4/cr-1.5.0/fc-3.2.5/fh-3.1.4/kt-2.5.0/r-2.2.2/rg-1.1.0/rr-1.2.4/sc-1.5.0/sl-1.2.6/datatables.min.css'
                Css = "$PSScriptRoot\Resources\CSS\datatables.min.css"
                JsLink = "https://cdn.datatables.net/v/dt/jq-3.3.1/dt-1.10.18/af-2.3.2/b-1.5.4/b-colvis-1.5.4/b-html5-1.5.4/b-print-1.5.4/cr-1.5.0/fc-3.2.5/fh-3.1.4/kt-2.5.0/r-2.2.2/rg-1.1.0/rr-1.2.4/sc-1.5.0/sl-1.2.6/datatables.min.js", "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js", "https://cdn.datatables.net/plug-ins/1.10.19/sorting/datetime-moment.js"
                JS = "$PSScriptRoot\Resources\JS\datatables.min.js", "$PSScriptRoot\Resources\JS\moment.min.js", "$PSScriptRoot\Resources\JS\datetime-moment.js"
            }
        }
        DataTablesPDF = @{Comment = 'DataTables PDF Features'
            Header = @{JsLink = 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js'
                Js = "$PSScriptRoot\Resources\JS\pdfmake.min.js", "$PSScriptRoot\Resources\JS\vfs_fonts.min.js"
            }
        }
        DataTablesExcel = @{Comment = 'DataTables Excel Features'
            Header = @{JsLink = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/2.5.0/jszip.min.js'
                JS = "$PSScriptRoot\Resources\JS\jszip.min.js"
            }
        }
        Fonts = @{Comment = 'Default fonts'
            HeaderAlways = @{CssLink = 'https://fonts.googleapis.com/css?family=Roboto|Hammersmith+One|Questrial|Oswald' }
        }
        FontsAwesome = @{Comment = 'Default fonts icons'
            HeaderAlways = @{CssLink = 'https://use.fontawesome.com/releases/v5.7.2/css/all.css' }
        }
        HideSection = @{Comment = 'Hide Section Code'
            HeaderAlways = @{JS = "$PSScriptRoot\Resources\JS\HideSection.js" }
        }
        Tabs = @{Comment = 'Elastic Tabs'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\tabs-elastic.css" }
            FooterAlways = @{JS = "$PSScriptRoot\Resources\JS\tabs-elastic.js" }
        }
        TimeLine = @{Comment = 'Timeline Simple'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\timeline-simple.css" }
        }
        StatusButtonical = @{Comment = 'Status Buttonical'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\status.css" }
        }
        Toast = @{Comment = 'Toasts Looking Messages'
            HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\toasts.css" }
        }
        TuiGrid = @{Comment = 'Tui Grid'
            Header = @{Css = "$PSScriptRoot\Resources\CSS\tuigrid.css"
                CssLink = 'https://cdn.jsdelivr.net/npm/tui-grid@3.5.0/dist/tui-grid.css'
            }
        }
    }
}
function Set-Tag {
    [CmdletBinding()]
    param([System.Collections.IDictionary] $HtmlObject)
    $HTML = [System.Text.StringBuilder]::new()
    [void] $HTML.Append("<$($HtmlObject.Tag)")
    foreach ($Property in $HtmlObject.Attributes.Keys) {
        $PropertyValue = $HtmlObject.Attributes[$Property]
        if ($PropertyValue -is [System.Collections.IDictionary]) {
            $OutputSubProperties = foreach ($SubAttributes in $PropertyValue.Keys) {
                $SubPropertyValue = $PropertyValue[$SubAttributes]
                if ($null -ne $SubPropertyValue -and $SubPropertyValue -ne '') { "$($SubAttributes):$($SubPropertyValue)" }
            }
            $MyValue = $OutputSubProperties -join ';'
            if ($MyValue.Trim() -ne '') { [void] $HTML.Append(" $Property=`"$MyValue`"") }
        } else { if ($null -ne $PropertyValue -and $PropertyValue -ne '') { [void] $HTML.Append(" $Property=`"$PropertyValue`"") } }
    }
    if (($null -ne $HtmlObject.Value) -and ($HtmlObject.Value -ne '')) {
        [void] $HTML.Append(">")
        if ($HtmlObject.Value.Count -eq 1) {
            if ($HtmlObject.Value -is [System.Collections.IDictionary]) {
                [string] $NewObject = Set-Tag -HtmlObject ($HtmlObject.Value)
                [void] $HTML.Append($NewObject)
            } else { [void] $HTML.Append([string] $HtmlObject.Value) }
        } else {
            foreach ($Entry in $HtmlObject.Value) {
                if ($Entry -is [System.Collections.IDictionary]) {
                    [string] $NewObject = Set-Tag -HtmlObject ($Entry)
                    [void] $HTML.Append($NewObject)
                } else { [void] $HTML.AppendLine([string] $Entry) }
            }
        }
        [void] $HTML.Append("</$($HtmlObject.Tag)>")
    } else { if ($HtmlObject.SelfClosing) { [void] $HTML.Append("/>") } else { [void] $HTML.Append("></$($HtmlObject.Tag)>") } }
    $HTML.ToString()
}
Export-ModuleMember -Function @('New-HTML', 'New-HTMLAnchor', 'New-HTMLAnchorLink', 'New-HTMLAnchorName', 'New-HTMLChartArea', 'New-HTMLChartBar', 'New-HTMLChartDataSet', 'New-HTMLChartLine', 'New-HTMLChartRadial', 'New-HTMLChartSpark', 'New-HTMLCodeBlock', 'New-HTMLContainer', 'New-HTMLHeading', 'New-HTMLHorizontalLine', 'New-HTMLImage', 'New-HTMLList', 'New-HTMLListItem', 'New-HTMLLogo', 'New-HTMLMessage', 'New-HTMLPanel', 'New-HTMLResourceCSS', 'New-HTMLResourceJS', 'New-HTMLSection', 'New-HTMLSection1', 'New-HTMLSectionHeader', 'New-HTMLSpanStyle', 'New-HTMLStatus', 'New-HTMLStatusItem', 'New-HTMLSubSection', 'New-HTMLTab', 'New-HTMLTabHead', 'New-HTMLTable', 'New-HTMLTableCondition', 'New-HTMLTag', 'New-HTMLText', 'New-HTMLTimeline', 'New-HTMLTimelineItem', 'New-HTMLToast', 'Out-HtmlView', 'Save-HTML') -Alias @('New-CSS', 'New-HTMLColumn', 'New-HTMLContent', 'New-JavaScript', 'New-ResourceCSS', 'New-ResourceJS', 'ohv', 'Out-GridHtml')