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-TableHeader { [CmdletBinding()] param([System.Collections.Generic.List[PSCustomObject]] $HeaderRows, [System.Collections.Generic.List[PSCUstomObject]] $HeaderStyle, [System.Collections.Generic.List[PSCUstomObject]] $HeaderTop, [string[]] $HeaderNames) if ($HeaderRows.Count -eq 0 -and $HeaderStyle.Count -eq 0 -and $HeaderTop.Count -eq 0) { return } [Array] $MergeColumns = foreach ($Row in $HeaderRows) { $Index = foreach ($R in $Row.Names) { [array]::indexof($HeaderNames.ToUpper(), $R.ToUpper()) } if ($Index -contains -1) { Write-Warning -Message "Table Header can't be processed properly. Names on the list to merge were not found in Table Header." } else { @{Index = $Index Title = $Row.Title Count = $Index.Count Style = $Row.Style Used = $false } } } $Styles = @{ } foreach ($Row in $HeaderStyle) { foreach ($_ in $Row.Names) { $Index = [array]::indexof($HeaderNames.ToUpper(), $_.ToUpper()) $Styles[$Index] = @{Index = $Index Title = $Row.Title Count = $Index.Count Style = $Row.Style Used = $false } } } if ($HeaderTop.Count -gt 0) { $UsedColumns = 0 $ColumnsTotal = $HeaderNames.Count $TopHeader = New-HTMLTag -Tag 'tr' { foreach ($_ in $HeaderTop) { if ($_.ColumnCount -eq 0) { $UsedColumns = $ColumnsTotal - $UsedColumns New-HTMLTag -Tag 'th' -Attributes @{colspan = $UsedColumns; style = ($_.Style) } -Value { $_.Title } } else { if ($_.ColumnCount -le $ColumnsTotal) { $UsedColumns = $UsedColumns + $_.ColumnCount } else { $UsedColumns = - ($ColumnsTotal - $_.ColumnCount) } New-HTMLTag -Tag 'th' -Attributes @{colspan = $_.ColumnCount; style = ($_.Style) } -Value { $_.Title } } } } } $AddedHeader = @($NewHeader = [System.Collections.Generic.List[string]]::new() $TopHeader New-HTMLTag -Tag 'tr' { for ($i = 0; $i -lt $HeaderNames.Count; $i++) { $Found = $false foreach ($_ in $MergeColumns) { if ($_.Index -contains $i) { if ($_.Used -eq $false) { New-HTMLTag -Tag 'th' -Attributes @{colspan = $_.Count; style = ($_.Style) } -Value { $_.Title } $_.Used = $true $Found = $true } else { $Found = $true } } } if (-not $Found) { if ($MergeColumns.Count -eq 0) { New-HTMLTag -Tag 'th' { $HeaderNames[$i] } -Attributes @{style = $Styles[$i].Style } } else { New-HTMLTag -Tag 'th' { $HeaderNames[$i] } -Attributes @{rowspan = 2; style = $Styles[$i].Style } } } else { $Head = New-HTMLTag -Tag 'th' { $HeaderNames[$i] } -Attributes @{style = $Styles[$i].Style } $NewHeader.Add($Head) } } } if ($NewHeader.Count) { New-HTMLTag -Tag 'tr' { $NewHeader } }) return $AddedHeader } 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 ConvertTo-HTMLStyle { [CmdletBinding()] param([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) if ($FontSize -eq 0) { $Size = '' } else { $size = "$($FontSize)px" } $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 } Remove-EmptyValues -Hashtable $Style return $Style } function Get-FeaturesInUse { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER PriorityFeatures Define priority features - important for ordering when CSS or JS has to be processed in certain order .EXAMPLE Get-FeaturesInUse -PriorityFeatures 'Jquery', 'DataTables', 'Tabs', 'Test' .NOTES General notes #> [CmdletBinding()] param([string[]] $PriorityFeatures) [Array] $Features = foreach ($Key in $Script:HTMLSchema.Features.Keys) { if ($Script:HTMLSchema.Features[$Key]) { $Key } } [Array] $TopFeatures = foreach ($Feature in $PriorityFeatures) { if ($Features -contains $Feature) { $Feature } } [Array] $RemainingFeatures = foreach ($Feature in $Features) { if ($TopFeatures -notcontains $Feature) { $Feature } } [Array] $AllFeatures = $TopFeatures + $RemainingFeatures $AllFeatures } 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-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 -Replace $Script:Configuration.Features.$Feature.CustomActionsReplace 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 -ReplaceData $Script:Configuration.Features.$Feature.CustomActionsReplace } 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 -ReplaceData $Script:Configuration.Features.$Feature.CustomActionsReplace 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('default', 'central')][string] $Positioning = 'default') $Script:HTMLSchema.Features.ChartsApex = $true [string] $ID = "ChartID-" + (Get-RandomStringName -Size 8) if ($Positioning -eq 'default') { $Class = '' } else { $Class = $Positioning } $Div = New-HTMLTag -Tag 'div' -Attributes @{id = $ID; class = $Class } $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-ChartAxisX { [alias('ChartCategory', 'ChartAxisX', 'New-ChartCategory')] [CmdletBinding()] param([alias('Name')][Array] $Names, [alias('Title')][string] $TitleText, [ValidateSet('datetime', 'category', 'numeric')][string] $Type = 'category', [int] $MinValue, [int] $MaxValue) [PSCustomObject] @{ObjectType = 'ChartAxisX' ChartAxisX = @{Names = $Names Type = $Type TitleText = $TitleText Min = $MinValue Max = $MaxValue } } } function New-ChartAxisY { [alias('ChartAxisY')] [CmdletBinding()] param([switch] $Show, [switch] $ShowAlways, [string] $TitleText, [ValidateSet('90', '270')][string] $TitleRotate = '90', [int] $TitleOffsetX = 0, [int] $TitleOffsetY = 0, [RGBColors] $TitleStyleColor = [RGBColors]::None, [int] $TitleStyleFontSize = 12, [string] $TitleStylefontFamily = 'Helvetica, Arial, sans-serif', [int] $MinValue, [int] $MaxValue) [PSCustomObject] @{ObjectType = 'ChartAxisY' ChartAxisY = @{Show = $Show.IsPresent ShowAlways = $ShowAlways.IsPresent TitleText = $TitleText TitleRotate = $TitleRotate TitleOffsetX = $TitleOffsetX TitleOffsetY = $TitleOffsetY TitleStyleColor = $TitleStyleColor TitleStyleFontSize = $TitleStyleFontSize TitleStylefontFamily = $TitleStylefontFamily Min = $MinValue Max = $MaxValue } } } function New-ChartBar { [alias('ChartBar')] [CmdletBinding()] param([string] $Name, [object] $Value) [PSCustomObject] @{ObjectType = 'Bar' Name = $Name Value = $Value } } function New-ChartBarOptions { [alias('ChartBarOptions')] [CmdletBinding()] param([ValidateSet('bar', 'barStacked', 'barStacked100Percent')] $Type = 'bar', [bool] $DataLabelsEnabled = $true, [int] $DataLabelsOffsetX = -6, [string] $DataLabelsFontSize = '12px', [nullable[RGBColors]] $DataLabelsColor, [alias('PatternedColors')][switch] $Patterned, [switch] $Distributed, [switch] $Vertical) [PSCustomObject] @{ObjectType = 'BarOptions' Type = $Type Title = $Title TitleAlignment = $TitleAlignment Horizontal = -not $Vertical.IsPresent DataLabelsEnabled = $DataLabelsEnabled DataLabelsOffsetX = $DataLabelsOffsetX DataLabelsFontSize = $DataLabelsFontSize DataLabelsColor = $DataLabelsColor PatternedColors = $Patterned.IsPresent Distributed = $Distributed.IsPresent } } function New-ChartGrid { [alias('ChartGrid')] [CmdletBinding()] param([switch] $Show, [RGBColors] $BorderColor = [RGBColors]::None, [int] $StrokeDash, [ValidateSet('front', 'back', 'default')][string] $Position = 'default', [switch] $xAxisLinesShow, [switch] $yAxisLinesShow, [RGBColors[]] $RowColors, [double] $RowOpacity = 0.5, [RGBColors[]] $ColumnColors, [double] $ColumnOpacity = 0.5, [int] $PaddingTop, [int] $PaddingRight, [int] $PaddingBottom, [int] $PaddingLeft) [PSCustomObject] @{ObjectType = 'ChartGrid' Grid = @{Show = $Show.IsPresent BorderColor = $BorderColor StrokeDash = $StrokeDash Position = $Position xAxisLinesShow = $xAxisLinesShow.IsPresent yAxisLinesShow = $yAxisLinesShow.IsPresent RowColors = $RowColors RowOpacity = $RowOpacity ColumnColors = $ColumnColors ColumnOpacity = $ColumnOpacity PaddingTop = $PaddingTop PaddingRight = $PaddingRight PaddingBottom = $PaddingBottom PaddingLeft = $PaddingLeft } } } function New-ChartInternalArea { [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-ChartInternalDataSet -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-ChartInternalAxisX { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [string] $TitleText, [int] $Min, [int] $Max, [ValidateSet('datetime', 'category', 'numeric')][string] $Type = 'category', [Array] $Names) if (-not $Options.Contains('xaxis')) { $Options.xaxis = @{ } } if ($TitleText -ne '') { $Options.xaxis.title = @{ } $Options.xaxis.title.text = $TitleText } if ($MinValue -gt 0) { $Options.xaxis.min = $Min } if ($MinValue -gt 0) { $Options.xaxis.max = $Max } if ($Type -ne '') { $Options.xaxis.type = $Type } if ($Names.Count -gt 0) { $Options.xaxis.categories = $Names } } function New-ChartInternalAxisY { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [string] $TitleText, [int] $Min, [int] $Max, [bool] $Show, [bool] $ShowAlways, [ValidateSet('90', '270')][string] $TitleRotate = '90', [int] $TitleOffsetX = 0, [int] $TitleOffsetY = 0, [RGBColors] $TitleStyleColor = [RGBColors]::None, [int] $TitleStyleFontSize = 12, [string] $TitleStylefontFamily = 'Helvetica, Arial, sans-serif') if (-not $Options.Contains('yaxis')) { $Options.yaxis = @{ } } $Options.yaxis.show = $Show $Options.yaxis.showAlways = $ShowAlways if ($TitleText -ne '') { $Options.yaxis.title = [ordered] @{ } $Options.yaxis.title.text = $TitleText $Options.yaxis.title.rotate = [int] $TitleRotate $Options.yaxis.title.offsetX = $TitleOffsetX $Options.yaxis.title.offsetY = $TitleOffsetY $Options.yaxis.title.style = [ordered] @{ } $Color = ConvertFrom-Color -Color $TitleStyleColor if ($null -ne $Color) { $Options.yaxis.title.style.color = $Coor } $Options.yaxis.title.style.fontSize = $TitleStyleFontSize $Options.yaxis.title.style.fontFamily = $TitleStylefontFamily } if ($Min -gt 0) { $Options.yaxis.min = $Min } if ($Min -gt 0) { $Options.yaxis.max = $Max } } Function New-ChartInternalBar { [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', 'default')][string] $TitleAlignment = 'default', [string] $Formatter, [ValidateSet('bar', 'barStacked', 'barStacked100Percent')] $Type = 'bar', [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%' } } $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-ChartInternalDataSet -Data $Data -DataNames $DataLegend) $Options.xaxis = [ordered] @{ } if ($DataNames.Count -gt 0) { $Options.xaxis.categories = $DataNames } New-ChartInternalTitle -Options $Options -Title $Title -TitleAlignment $TitleAlignment if ($PatternedColors) { $Options.fill = @{type = 'pattern' opacity = 1 pattern = @{style = @('circles', 'slantedLines', 'verticalLines', 'horizontalLines') } } } } function New-ChartInternalColors { param([System.Collections.IDictionary] $Options, [RGBColors[]]$Colors) if ($Colors.Count -gt 0) { $RGBColor = ConvertFrom-Color -Color $Colors $Options.colors = @($RGBColor) } } function New-ChartInternalDataLabels { 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-ChartInternalDataSet { [CmdletBinding()] param([Array] $Data, [Array] $DataNames) if ($null -ne $Data -and $null -ne $DataNames) { if ($Data[0] -is [System.Collections.ICollection]) { if ($Data[0].Count -eq $DataNames.Count) { for ($a = 0; $a -lt $Data.Count; $a++) { [ordered] @{name = $DataNames[$a] data = $Data[$a] } } } elseif ($Data.Count -eq $DataNames.Count) { for ($a = 0; $a -lt $Data.Count; $a++) { [ordered] @{name = $DataNames[$a] data = $Data[$a] } } } else { New-ChartInternalDataSet -Data $Data } } else { if ($null -ne $DataNames) { [ordered] @{name = $DataNames data = $Data } } else { [ordered] @{data = $Data } } } } elseif ($null -ne $Data) { if ($Data[0] -is [System.Collections.ICollection]) { foreach ($D in $Data) { [ordered] @{data = $D } } } else { [ordered] @{data = $Data } } } else { Write-Warning -Message "New-ChartInternalDataSet - No Data provided. Unabled to create dataset." return [ordered] @{ } } } function New-ChartInternalGrid { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [bool] $Show, [RGBColors] $BorderColor = [RGBColors]::None, [int] $StrokeDash, [ValidateSet('front', 'back', 'default')][string] $Position = 'default', [nullable[bool]] $xAxisLinesShow = $null, [nullable[bool]] $yAxisLinesShow = $null, [alias('GridColors')][RGBColors[]] $RowColors, [alias('GridOpacity')][double] $RowOpacity = 0.5, [RGBColors[]] $ColumnColors , [double] $ColumnOpacity = 0.5, [int] $PaddingTop, [int] $PaddingRight, [int] $PaddingBottom, [int] $PaddingLeft) $Options.grid = [ordered] @{ } $Options.grid.Show = $Show if ($BorderColor -ne [RGBColors]::None) { $options.grid.borderColor = @(ConvertFrom-Color -Color $BorderColor) } if ($StrokeDash -gt 0) { $Options.grid.strokeDashArray = $StrokeDash } if ($Position -ne 'Default') { $Options.grid.position = $Position } if ($null -ne $xAxisLinesShow) { $Options.grid.xaxis = @{ } $Options.grid.xaxis.lines = @{ } $Options.grid.xaxis.lines.show = $xAxisLinesShow } if ($null -ne $yAxisLinesShow) { $Options.grid.yaxis = @{ } $Options.grid.yaxis.lines = @{ } $Options.grid.yaxis.lines.show = $yAxisLinesShow } if ($RowColors.Count -gt 0 -or $RowOpacity -ne 0) { $Options.grid.row = @{ } if ($RowColors.Count -gt 0) { $Options.grid.row.colors = @(ConvertFrom-Color -Color $RowColors) } if ($RowOpacity -ne 0) { $Options.grid.row.opacity = $RowOpacity } } if ($ColumnColors.Count -gt 0 -or $ColumnOpacity -ne 0) { $Options.grid.column = @{ } if ($ColumnColors.Count -gt 0) { $Options.grid.column.colors = @(ConvertFrom-Color -Color $ColumnColors) } if ($ColumnOpacity -ne 0) { $Options.grid.column.opacity = $ColumnOpacitys } } if ($PaddingTop -gt 0 -or $PaddingRight -gt 0 -or $PaddingBottom -gt 0 -or $PaddingLeft -gt 0) { $Options.grid.padding = @{ } if ($PaddingTop -gt 0) { $Options.grid.padding.PaddingTop = $PaddingTop } if ($PaddingRight -gt 0) { $Options.grid.padding.PaddingRight = $PaddingRight } if ($PaddingBottom -gt 0) { $Options.grid.padding.PaddingBottom = $PaddingBottom } if ($PaddingLeft -gt 0) { $Options.grid.padding.PaddingLeft = $PaddingLeft } } } function New-ChartInternalLegend { param([System.Collections.IDictionary] $Options, [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', 'default')][string] $LegendPosition = 'default') if ($LegendPosition -eq 'default' -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 offsetY = -25 offsetX = -5 } } } function New-ChartInternalLine { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [Array] $Data, [Array] $DataNames, [ValidateSet('datetime', 'category', 'numeric')][string] $DataCategoriesType = 'category') $Options.chart = @{type = 'line' } $Options.series = @(New-ChartInternalDataSet -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-ChartInternalMarker { param([System.Collections.IDictionary] $Options, [int] $MarkerSize) if ($MarkerSize -gt 0) { $Options.markers = @{size = $MarkerSize } } } function New-ChartInternalRadial { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [Array] $Values, [Array] $Names, $Type) $Options.chart = @{type = 'radialBar' } if ($Type -eq '1') { New-ChartInternalRadialType1 -Options $Options } elseif ($Type -eq '2') { New-ChartInternalRadialType2 -Options $Options } $Options.series = @($Values) $Options.labels = @($Names) } function New-ChartInternalRadialCircleType { [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-ChartInternalRadialDataLabels { [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-ChartInternalRadialType1 { [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 opacityFrom = 1 opacityTo = 1 stops = @(0, 100) } } $Options.stroke = [ordered] @{dashArray = 4 } } function New-ChartInternalRadialType2 { [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-ChartInternalSize { [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-ChartInternalSpark { [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-ChartInternalStrokeDefinition { param([System.Collections.IDictionary] $Options, [bool] $LineShow = $true, [ValidateSet('straight', 'smooth', 'stepline')][string[]] $LineCurve, [int[]] $LineWidth, [ValidateSet('butt', 'square', 'round')][string[]] $LineCap, [RGBColors[]] $LineColor, [int[]] $LineDash) $Options.stroke = [ordered] @{show = $LineShow } if ($LineCurve.Count -gt 0) { $Options.stroke.curve = $LineCurve } if ($LineWidth.Count -gt 0) { $Options.stroke.width = $LineWidth } if ($LineColor.Count -gt 0) { $Options.stroke.colors = @(ConvertFrom-Color -Color $LineColor) } if ($LineCap.Count -gt 0) { $Options.stroke.lineCap = $LineCap } if ($LineDash.Count -gt 0) { $Options.stroke.dashArray = $LineDash } } function New-ChartInternalTheme { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [ValidateSet('light', 'dark')][string] $Mode, [ValidateSet('palette1', 'palette2', 'palette3', 'palette4', 'palette5', 'palette6', 'palette7', 'palette8', 'palette9', 'palette10') ][string] $Palette = 'palette1', [switch] $Monochrome, [RGBColors] $Color = [RGBColors]::DodgerBlue, [ValidateSet('light', 'dark')][string] $ShadeTo = 'lightF', [double] $ShadeIntensity = 0.65) $Options.theme = [ordered] @{mode = $Mode palette = $Palette monochrome = [ordered] @{enabled = $Monochrome.IsPresent color = $Color shadeTo = $ShadeTo shadeIntensity = $ShadeIntensity } } } function New-ChartInternalTitle { param([System.Collections.IDictionary] $Options, [string] $Title, [ValidateSet('center', 'left', 'right', 'default')][string] $TitleAlignment = 'default') $Options.title = [ordered] @{ } if ($TitleText -ne '') { $Options.title.text = $Title } if ($TitleAlignment -ne 'default') { $Options.title.align = $TitleAlignment } } function New-ChartInternalToolbar { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [bool] $Show = $false, [bool] $Download = $false, [bool] $Selection = $false, [bool] $Zoom = $false, [bool] $ZoomIn = $false, [bool] $ZoomOut = $false, [bool] $Pan = $false, [bool] $Reset = $false, [ValidateSet('zoom', 'selection', 'pan')][string] $AutoSelected = 'zoom') $Options.chart.toolbar = [ordered] @{show = $show tools = [ordered] @{download = $Download selection = $Selection zoom = $Zoom zoomin = $ZoomIn zoomout = $ZoomOut pan = $Pan reset = $Reset } autoSelected = $AutoSelected } } function New-ChartInternalZoom { [CmdletBinding()] param([System.Collections.IDictionary] $Options, [switch] $Enabled) if ($Enabled) { $Options.chart.zoom = @{type = 'x' enabled = $Enabled.IsPresent } } } function New-ChartLegend { [alias('ChartLegend')] [CmdletBinding()] param([Array] $Names, [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', 'default')][string] $LegendPosition = 'default', [RGBColors[]] $Color) [PSCustomObject] @{ObjectType = 'Legend' Names = $Names LegendPosition = $LegendPosition Color = $Color } } function New-ChartLine { [alias('ChartLine')] [CmdletBinding()] param([string] $Name, [object] $Value, [RGBColors] $Color, [ValidateSet('straight', 'smooth', 'stepline')] $Curve = 'straight', [int] $Width = 6, [ValidateSet('butt', 'square', 'round')][string] $Cap = 'butt', [int] $Dash = 0) [PSCustomObject] @{ObjectType = 'Line' Name = $Name Value = $Value LineColor = $Color LineCurve = $Curve LineWidth = $Width LineCap = $Cap LineDash = $Dash } } function New-ChartTheme { [alias('ChartTheme')] [CmdletBinding()] param([ValidateSet('light', 'dark')][string] $Mode, [ValidateSet('palette1', 'palette2', 'palette3', 'palette4', 'palette5', 'palette6', 'palette7', 'palette8', 'palette9', 'palette10') ][string] $Palette = 'palette1', [switch] $Monochrome, [RGBColors] $Color = [RGBColors]::DodgerBlue, [ValidateSet('light', 'dark')][string] $ShadeTo = 'lightF', [double] $ShadeIntensity = 0.65) [PSCustomObject] @{ObjectType = 'Theme' Mode = $Mode Palette = $Palette Monochrome = $Monochrome.IsPresent Color = $Color ShadeTo = $ShadeTo ShadeIntensity = $ShadeIntensity } } function New-ChartToolbar { [alias('ChartToolbar')] [CmdletBinding()] param([switch] $Download, [switch] $Selection, [switch] $Zoom, [switch] $ZoomIn, [switch] $ZoomOut, [switch] $Pan, [switch] $Reset, [ValidateSet('zoom', 'selection', 'pan')][string] $AutoSelected = 'zoom') [PSCustomObject] @{ObjectType = 'Toolbar' Toolbar = @{download = $Download.IsPresent selection = $Selection.IsPresent zoom = $Zoom.IsPresent zoomin = $ZoomIn.IsPresent zoomout = $ZoomOut.IsPresent pan = $Pan.IsPresent reset = $Reset.IsPresent autoSelected = $AutoSelected } } } 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, [alias('Name')][String] $TitleText, [string] $Author, [string] $DateFormat = 'yyyy-MM-dd HH:mm:ss', [int] $AutoRefresh, [Parameter(Mandatory = $false)][string]$FilePath, [alias('Show', 'Open')][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() TabOptions = @{SlimTabs = $false } } $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 -PriorityFeatures 'JQuery', 'DataTables', 'Tabs' $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 -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-HTMLChart { [alias('Chart')] [CmdletBinding()] param([ScriptBlock] $ChartSettings, [string] $Title, [ValidateSet('center', 'left', 'right', 'default')][string] $TitleAlignment = 'default', [nullable[int]] $Height = 350, [nullable[int]] $Width, [ValidateSet('default', 'central')][string] $Positioning = 'default') $DataSet = [System.Collections.Generic.List[object]]::new() $DataName = [System.Collections.Generic.List[object]]::new() $Colors = @() $LineColors = [System.Collections.Generic.List[RGBColors]]::new() $LineCurves = [System.Collections.Generic.List[string]]::new() $LineWidths = [System.Collections.Generic.List[int]]::new() $LineDashes = [System.Collections.Generic.List[int]]::new() $LineCaps = [System.Collections.Generic.List[string]]::new() [string] $BarType = 'bar' [bool] $BarHorizontal = $true [bool] $BarDataLabelsEnabled = $true [int] $BarDataLabelsOffsetX = -6 [string] $BarDataLabelsFontSize = '12px' [bool] $BarPatternedColors = $false [bool] $BarDistributed = $false [string] $LegendPosition = 'default' [Array] $Settings = & $ChartSettings foreach ($Setting in $Settings) { if ($Setting.ObjectType -eq 'Bar') { $Type = 'Bar' $DataSet.Add($Setting.Value) $DataName.Add($Setting.Name) } elseif ($Setting.ObjectType -eq 'Legend') { $DataLegend = $Setting.Names $LegendPosition = $Setting.LegendPosition if ($null -ne $Setting.Color) { $Colors = $Setting.Color } } elseif ($Setting.ObjectType -eq 'BarOptions') { $BarType = $Setting.Type $BarHorizontal = $Setting.Horizontal $BarDataLabelsEnabled = $Setting.DataLabelsEnabled $BarDataLabelsOffsetX = $Setting.DataLabelsOffsetX $BarDataLabelsFontSize = $Setting.DataLabelsFontSize $BarDataLabelsColor = $Setting.DataLabelsColor $BarPatternedColors = $Setting.PatternedColors $BarDistributed = $Setting.Distributed } elseif ($Setting.ObjectType -eq 'Toolbar') { $Toolbar = $Setting.Toolbar } elseif ($Setting.ObjectType -eq 'Line') { $Type = 'Line' $DataSet.Add($Setting.Value) $DataName.Add($Setting.Name) if ($Setting.LineColor) { $LineColors.Add($Setting.LineColor) } if ($Setting.LineCurve) { $LineCurves.Add($Setting.LineCurve) } if ($Setting.LineWidth) { $LineWidths.Add($Setting.LineWidth) } if ($Setting.LineDash) { $LineDashes.Add($Setting.LineDash) } if ($Setting.LineCap) { $LineCaps.Add($Setting.LineCap) } } elseif ($Setting.ObjectType -eq 'ChartAxisX') { $ChartAxisX = $Setting.ChartAxisX } elseif ($Setting.ObjectType -eq 'ChartGrid') { $GridOptions = $Setting.Grid } elseif ($Setting.ObjectType -eq 'ChartAxisY') { $ChartAxisY = $Setting.ChartAxisY } } if ($Type -eq 'Bar') { if ($DataLegend.Count -lt $DataSet[0].Count) { Write-Warning -Message "Chart Legend count doesn't match values count. Skipping." } $HashTable = [ordered] @{ } $ArrayCount = $DataSet[0].Count if ($ArrayCount -eq 1) { $HashTable.1 = $DataSet } else { for ($i = 0; $i -lt $ArrayCount; $i++) { $HashTable.$i = [System.Collections.Generic.List[object]]::new() } foreach ($Value in $DataSet) { for ($h = 0; $h -lt $Value.Count; $h++) { $HashTable[$h].Add($Value[$h]) } } } New-HTMLChartBar -Data $($HashTable.Values) -DataNames $DataName -DataLegend $DataLegend -LegendPosition $LegendPosition -Type $BarType -Title $Title -TitleAlignment $TitleAlignment -Horizontal:$BarHorizontal -DataLabelsEnabled $BarDataLabelsEnabled -PatternedColors:$BarPatternedColors -DataLabelsOffsetX $BarDataLabelsOffsetX -DataLabelsFontSize $BarDataLabelsFontSize -Distributed:$BarDistributed -DataLabelsColor $BarDataLabelsColor -Height $Height -Width $Width -Colors $Colors -Toolbar $Toolbar -Positioning $Positioning } elseif ($Type -eq 'Line') { if (-not $ChartAxisX) { Write-Warning -Message 'Chart Category (Chart Axis X) is missing.' Exit } New-HTMLChartLine -Data $DataSet -DataNames $DataName -Title $Title -TitleAlignment $TitleAlignment -DataLabelsEnabled $BarDataLabelsEnabled -DataLabelsOffsetX $BarDataLabelsOffsetX -DataLabelsFontSize $BarDataLabelsFontSize -DataLabelsColor $BarDataLabelsColor -Height $Height -Width $Width -Positioning $Positioning -LineColor $LineColors -LineCurve $LineCurves -LineWidth $LineWidths -LineDash $LineDashes -LineCap $LineCaps -GridOptions $GridOptions -ChartAxisX $ChartAxisX -ChartAxisY $ChartAxisY } } function New-HTMLChartArea { [CmdletBinding()] param([nullable[int]] $Height = 350, [nullable[int]] $Width, [ValidateSet('default', 'central')][string] $Positioning = 'default', [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', 'default')][string] $TitleAlignment = 'default', [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', 'default')][string] $LegendPosition = 'default', [string] $TitleX, [string] $TitleY, [int] $MarkerSize, [Array] $Data, [Array] $DataNames, [Array] $DataLegend, [switch] $Zoom) $Options = [ordered] @{ } New-ChartInternalArea -Options $Options -Data $Data -DataNames $DataNames New-ChartInternalStrokeDefinition -Options $Options -LineShow $true -LineCurve $LineCurve -LineWidth $LineWidth -LineColor $LineColor New-ChartInternalDataLabels -Options $Options -DataLabelsEnabled $DataLabelsEnabled -DataLabelsOffsetX $DataLabelsOffsetX -DataLabelsFontSize $DataLabelsFontSize -DataLabelsColor $DataLabelsColor New-ChartInternalAxisX -Options $Options -Title $TitleX -DataCategoriesType $DataCategoriesType -DataCategories $DataLegend New-ChartInternalAxisY -Options $Options -Title $TitleY New-ChartInternalMarker -Options $Options -MarkerSize $MarkerSize New-ChartInternalTitle -Options $Options -Title $Title -TitleAlignment $TitleAlignment New-ChartInternalGrid -Options $Options -GridColors $GridColors -GridOpacity $GridOpacity New-ChartInternalLegend -Options $Options -LegendPosition $LegendPosition New-ChartInternalSize -Options $Options -Height $Height -Width $Width New-ChartInternalZoom -Options $Options -Enabled:$Zoom New-ChartInternalToolbar -Options $Options New-ApexChart -Positioning $Positioning -Options $Options } function New-HTMLChartBar { [CmdletBinding()] param([nullable[int]] $Height = 350, [nullable[int]] $Width, [ValidateSet('default', 'central')][string] $Positioning = 'default', [ValidateSet('bar', 'barStacked', 'barStacked100Percent')] $Type = 'bar', [RGBColors[]] $Colors, [switch] $PatternedColors, [string] $Title, [ValidateSet('center', 'left', 'right', 'default')][string] $TitleAlignment = 'default', [bool] $Horizontal = $true, [bool] $DataLabelsEnabled = $true, [int] $DataLabelsOffsetX = -6, [string] $DataLabelsFontSize = '12px', [nullable[RGBColors]] $DataLabelsColor, [switch] $Distributed, [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', 'default')][string] $LegendPosition = 'default', [Array] $Data, [Array] $DataNames, [Array] $DataLegend, [hashtable] $Toolbar) $Options = [ordered] @{ } New-ChartInternalBar -Options $Options -Horizontal $Horizontal -DataLabelsEnabled $DataLabelsEnabled -DataLabelsOffsetX $DataLabelsOffsetX -DataLabelsFontSize $DataLabelsFontSize -DataLabelsColor $DataLabelsColor -Data $Data -DataNames $DataNames -DataLegend $DataLegend -Title $Title -TitleAlignment $TitleAlignment -Type $Type -PatternedColors:$PatternedColors -Distributed:$Distributed New-ChartInternalColors -Options $Options -Colors $Colors New-ChartInternalLegend -Options $Options -LegendPosition $LegendPosition New-ChartInternalSize -Options $Options -Height $Height -Width $Width if ($Toolbar.Count -eq 0) { $Toolbar = @{Show = $false } } else { $Toolbar.Show = $true } New-ChartInternalToolbar -Options $Options @Toolbar New-ApexChart -Positioning $Positioning -Options $Options } function New-HTMLChartLine { [CmdletBinding()] param([nullable[int]] $Height = 350, [nullable[int]] $Width, [ValidateSet('default', 'central')][string] $Positioning = 'default', [bool] $DataLabelsEnabled = $true, [int] $DataLabelsOffsetX = -6, [string] $DataLabelsFontSize = '12px', [RGBColors[]] $DataLabelsColor, [ValidateSet('straight', 'smooth', 'stepline')][string[]] $LineCurve, [int[]] $LineWidth, [RGBColors[]] $LineColor, [int[]] $LineDash, [ValidateSet('butt', 'square', 'round')][string[]] $LineCap, [string] $Title, [ValidateSet('center', 'left', 'right', 'default')][string] $TitleAlignment = 'default', [ValidateSet('top', 'topRight', 'left', 'right', 'bottom', 'default')][string] $LegendPosition = 'default', [int] $MarkerSize, [Array] $Data, [Array] $DataNames, [System.Collections.IDictionary] $GridOptions, [System.Collections.IDictionary] $ChartAxisX, [System.Collections.IDictionary] $ChartAxisY) $Options = [ordered] @{ } New-ChartInternalLine -Options $Options -Data $Data -DataNames $DataNames if ($LineCurve.Count -eq 0 -or ($LineCurve.Count -ne $DataNames.Count)) { $LineCurve = for ($i = $LineCurve.Count; $i -le $DataNames.Count; $i++) { 'straight' } } if ($LineCap.Count -eq 0 -or ($LineCap.Count -ne $DataNames.Count)) { $LineCap = for ($i = $LineCap.Count; $i -le $DataNames.Count; $i++) { 'butt' } } if ($LineDash.Count -eq 0) { } New-ChartInternalStrokeDefinition -Options $Options -LineShow $true -LineCurve $LineCurve -LineWidth $LineWidth -LineColor $LineColor -LineCap $LineCap -LineDash $LineDash New-ChartInternalColors -Options $Options -Colors $LineColor New-ChartInternalDataLabels -Options $Options -DataLabelsEnabled $DataLabelsEnabled -DataLabelsOffsetX $DataLabelsOffsetX -DataLabelsFontSize $DataLabelsFontSize -DataLabelsColor $DataLabelsColor if ($ChartAxisX) { New-ChartInternalAxisX -Options $Options @ChartAxisX } else { } if ($ChartAxisY) { New-ChartInternalAxisY -Options $Options @ChartAxisY } else { } New-ChartInternalMarker -Options $Options -MarkerSize $MarkerSize New-ChartInternalTitle -Options $Options -Title $Title -TitleAlignment $TitleAlignment if ($GridOptions) { New-ChartInternalGrid -Options $Options @GridOptions } else { New-ChartInternalGrid -Options $Options } New-ChartInternalLegend -Options $Options -LegendPosition $LegendPosition New-ChartInternalSize -Options $Options -Height $Height -Width $Width New-ChartInternalToolbar -Options $Options New-ApexChart -Positioning $Positioning -Options $Options } function New-HTMLChartRadial { [CmdletBinding()] param([nullable[int]] $Height = 350, [nullable[int]] $Width, [ValidateSet('default', 'central')][string] $Positioning = 'default', [Array] $Names, [Array] $Values, $Type, [ValidateSet('FullCircleTop', 'FullCircleBottom', 'FullCircleBottomLeft', 'FullCircleLeft', 'Speedometer', 'SemiCircleGauge')] $CircleType = 'FullCircleTop', [string] $LabelAverage) $Options = [ordered] @{ } New-ChartInternalRadial -Options $Options -Names $Names -Values $Values -Type $Type New-ChartInternalRadialCircleType -Options $Options -CircleType $CircleType New-ChartInternalRadialDataLabels -Options $Options -Label $LabelAverage New-ChartInternalSize -Options $Options -Height $Height -Width $Width New-ChartInternalToolbar -Options $Options New-ApexChart -Positioning $Positioning -Options $Options } function New-HTMLChartSpark { [CmdletBinding()] param([nullable[int]] $Height = 350, [nullable[int]] $Width, [ValidateSet('default', 'central')][string] $Positioning = 'default', [Array] $Data, [string] $TitleText, [string] $SubTitleText, [int] $FontSizeTitle = 24, [int] $FontSizeSubtitle = 14, [nullable[RGBColors]] $Color) $Options = [ordered] @{ } New-ChartInternalSpark -Options $Options -Color $Color -Title $TitleText -SubTitle $SubTitleText -FontSizeTitle $FontSizeTitle -FontSizeSubtitle $FontSizeSubtitle -Values $Data New-ChartInternalSize -Options $Options -Height $Height -Width $Width New-ChartInternalToolbar -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('default', 'central')][string] $Type = 'default', [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://evotec.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 = [RGBColors]::None, [switch] $Invisible) if ($BackgroundColor -ne [RGBColors]::None) { $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, [System.Collections.IDictionary] $ReplaceData) $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" $FileContent = Get-Content -LiteralPath $File if ($null -ne $ReplaceData) { foreach ($_ in $ReplaceData.Keys) { $FileContent = $FileContent -replace $_, $ReplaceData[$_] } } $FileContent } } } } 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, [System.Collections.IDictionary] $ReplaceData) $Output = @("<!-- JS $ResourceComment START -->" foreach ($File in $FilePath) { if ($File -ne '') { if (Test-Path -LiteralPath $File) { New-HTMLTag -Tag 'script' -Attributes @{type = 'text/javascript' } { $FileContent = Get-Content -LiteralPath $File if ($null -ne $ReplaceData) { foreach ($_ in $ReplaceData.Keys) { $FileContent = $FileContent -replace $_, $ReplaceData[$_] } } $FileContent } } 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"), [alias('Name')][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, [alias('Collapsable')][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(DefaultParameterSetName = 'FontAwesomeBrands')] param([parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")] [Parameter(Mandatory = $false, Position = 0)][ValidateNotNull()][ScriptBlock] $HtmlData = $(Throw "No curly brace?)"), [parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")] [alias('TabHeading')][Parameter(Mandatory = $false, Position = 1)][String]$Heading, [parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")] [alias('TabName')][string] $Name = 'Tab', [parameter(ParameterSetName = "FontAwesomeBrands")] [ValidateSet('500px', 'accessible-icon', 'accusoft', 'acquisitions-incorporated', 'adn', 'adobe', 'adversal', 'affiliatetheme', 'airbnb', 'algolia', 'alipay', 'amazon', 'amazon-pay', 'amilia', 'android', 'angellist', 'angrycreative', 'angular', 'app-store', 'app-store-ios', 'apper', 'apple', 'apple-pay', 'artstation', 'asymmetrik', 'atlassian', 'audible', 'autoprefixer', 'avianex', 'aviato', 'aws', 'bandcamp', 'battle-net', 'behance', 'behance-square', 'bimobject', 'bitbucket', 'bitcoin', 'bity', 'black-tie', 'blackberry', 'blogger', 'blogger-b', 'bluetooth', 'bluetooth-b', 'bootstrap', 'btc', 'buffer', 'buromobelexperte', 'buysellads', 'canadian-maple-leaf', 'cc-amazon-pay', 'cc-amex', 'cc-apple-pay', 'cc-diners-club', 'cc-discover', 'cc-jcb', 'cc-mastercard', 'cc-paypal', 'cc-stripe', 'cc-visa', 'centercode', 'centos', 'chrome', 'chromecast', 'cloudscale', 'cloudsmith', 'cloudversify', 'codepen', 'codiepie', 'confluence', 'connectdevelop', 'contao', 'cpanel', 'creative-commons', 'creative-commons-by', 'creative-commons-nc', 'creative-commons-nc-eu', 'creative-commons-nc-jp', 'creative-commons-nd', 'creative-commons-pd', 'creative-commons-pd-alt', 'creative-commons-remix', 'creative-commons-sa', 'creative-commons-sampling', 'creative-commons-sampling-plus', 'creative-commons-share', 'creative-commons-zero', 'critical-role', 'css3', 'css3-alt', 'cuttlefish', 'd-and-d', 'd-and-d-beyond', 'dashcube', 'delicious', 'deploydog', 'deskpro', 'dev', 'deviantart', 'dhl', 'diaspora', 'digg', 'digital-ocean', 'discord', 'discourse', 'dochub', 'docker', 'draft2digital', 'dribbble', 'dribbble-square', 'dropbox', 'drupal', 'dyalog', 'earlybirds', 'ebay', 'edge', 'elementor', 'ello', 'ember', 'empire', 'envira', 'erlang', 'ethereum', 'etsy', 'evernote', 'expeditedssl', 'facebook', 'facebook-f', 'facebook-messenger', 'facebook-square', 'fantasy-flight-games', 'fedex', 'fedora', 'figma', 'firefox', 'first-order', 'first-order-alt', 'firstdraft', 'flickr', 'flipboard', 'fly', 'font-awesome', 'font-awesome-alt', 'font-awesome-flag', 'fonticons', 'fonticons-fi', 'fort-awesome', 'fort-awesome-alt', 'forumbee', 'foursquare', 'free-code-camp', 'freebsd', 'fulcrum', 'galactic-republic', 'galactic-senate', 'get-pocket', 'gg', 'gg-circle', 'git', 'git-alt', 'git-square', 'github', 'github-alt', 'github-square', 'gitkraken', 'gitlab', 'gitter', 'glide', 'glide-g', 'gofore', 'goodreads', 'goodreads-g', 'google', 'google-drive', 'google-play', 'google-plus', 'google-plus-g', 'google-plus-square', 'google-wallet', 'gratipay', 'grav', 'gripfire', 'grunt', 'gulp', 'hacker-news', 'hacker-news-square', 'hackerrank', 'hips', 'hire-a-helper', 'hooli', 'hornbill', 'hotjar', 'houzz', 'html5', 'hubspot', 'imdb', 'instagram', 'intercom', 'internet-explorer', 'invision', 'ioxhost', 'itch-io', 'itunes', 'itunes-note', 'java', 'jedi-order', 'jenkins', 'jira', 'joget', 'joomla', 'js', 'js-square', 'jsfiddle', 'kaggle', 'keybase', 'keycdn', 'kickstarter', 'kickstarter-k', 'korvue', 'laravel', 'lastfm', 'lastfm-square', 'leanpub', 'less', 'line', 'linkedin', 'linkedin-in', 'linode', 'linux', 'lyft', 'magento', 'mailchimp', 'mandalorian', 'markdown', 'mastodon', 'maxcdn', 'medapps', 'medium', 'medium-m', 'medrt', 'meetup', 'megaport', 'mendeley', 'microsoft', 'mix', 'mixcloud', 'mizuni', 'modx', 'monero', 'napster', 'neos', 'nimblr', 'node', 'node-js', 'npm', 'ns8', 'nutritionix', 'odnoklassniki', 'odnoklassniki-square', 'old-republic', 'opencart', 'openid', 'opera', 'optin-monster', 'osi', 'page4', 'pagelines', 'palfed', 'patreon', 'paypal', 'penny-arcade', 'periscope', 'phabricator', 'phoenix-framework', 'phoenix-squadron', 'php', 'pied-piper', 'pied-piper-alt', 'pied-piper-hat', 'pied-piper-pp', 'pinterest', 'pinterest-p', 'pinterest-square', 'playstation', 'product-hunt', 'pushed', 'python', 'qq', 'quinscape', 'quora', 'r-project', 'raspberry-pi', 'ravelry', 'react', 'reacteurope', 'readme', 'rebel', 'red-river', 'reddit', 'reddit-alien', 'reddit-square', 'redhat', 'renren', 'replyd', 'researchgate', 'resolving', 'rev', 'rocketchat', 'rockrms', 'safari', 'salesforce', 'sass', 'schlix', 'scribd', 'searchengin', 'sellcast', 'sellsy', 'servicestack', 'shirtsinbulk', 'shopware', 'simplybuilt', 'sistrix', 'sith', 'sketch', 'skyatlas', 'skype', 'slack', 'slack-hash', 'slideshare', 'snapchat', 'snapchat-ghost', 'snapchat-square', 'soundcloud', 'sourcetree', 'speakap', 'speaker-deck', 'spotify', 'squarespace', 'stack-exchange', 'stack-overflow', 'stackpath', 'staylinked', 'steam', 'steam-square', 'steam-symbol', 'sticker-mule', 'strava', 'stripe', 'stripe-s', 'studiovinari', 'stumbleupon', 'stumbleupon-circle', 'superpowers', 'supple', 'suse', 'symfony', 'teamspeak', 'telegram', 'telegram-plane', 'tencent-weibo', 'the-red-yeti', 'themeco', 'themeisle', 'think-peaks', 'trade-federation', 'trello', 'tripadvisor', 'tumblr', 'tumblr-square', 'twitch', 'twitter', 'twitter-square', 'typo3', 'uber', 'ubuntu', 'uikit', 'uniregistry', 'untappd', 'ups', 'usb', 'usps', 'ussunnah', 'vaadin', 'viacoin', 'viadeo', 'viadeo-square', 'viber', 'vimeo', 'vimeo-square', 'vimeo-v', 'vine', 'vk', 'vnv', 'vuejs', 'waze', 'weebly', 'weibo', 'weixin', 'whatsapp', 'whatsapp-square', 'whmcs', 'wikipedia-w', 'windows', 'wix', 'wizards-of-the-coast', 'wolf-pack-battalion', 'wordpress', 'wordpress-simple', 'wpbeginner', 'wpexplorer', 'wpforms', 'wpressr', 'xbox', 'xing', 'xing-square', 'y-combinator', 'yahoo', 'yammer', 'yandex', 'yandex-international', 'yarn', 'yelp', 'yoast', 'youtube', 'youtube-square', 'zhihu')][string] $IconBrands, [parameter(ParameterSetName = "FontAwesomeRegular")] [ValidateSet('address-book', 'address-card', 'angry', 'arrow-alt-circle-down', 'arrow-alt-circle-left', 'arrow-alt-circle-right', 'arrow-alt-circle-up', 'bell', 'bell-slash', 'bookmark', 'building', 'calendar', 'calendar-alt', 'calendar-check', 'calendar-minus', 'calendar-plus', 'calendar-times', 'caret-square-down', 'caret-square-left', 'caret-square-right', 'caret-square-up', 'chart-bar', 'check-circle', 'check-square', 'circle', 'clipboard', 'clock', 'clone', 'closed-captioning', 'comment', 'comment-alt', 'comment-dots', 'comments', 'compass', 'copy', 'copyright', 'credit-card', 'dizzy', 'dot-circle', 'edit', 'envelope', 'envelope-open', 'eye', 'eye-slash', 'file', 'file-alt', 'file-archive', 'file-audio', 'file-code', 'file-excel', 'file-image', 'file-pdf', 'file-powerpoint', 'file-video', 'file-word', 'flag', 'flushed', 'folder', 'folder-open', 'frown', 'frown-open', 'futbol', 'gem', 'grimace', 'grin', 'grin-alt', 'grin-beam', 'grin-beam-sweat', 'grin-hearts', 'grin-squint', 'grin-squint-tears', 'grin-stars', 'grin-tears', 'grin-tongue', 'grin-tongue-squint', 'grin-tongue-wink', 'grin-wink', 'hand-lizard', 'hand-paper', 'hand-peace', 'hand-point-down', 'hand-point-left', 'hand-point-right', 'hand-point-up', 'hand-pointer', 'hand-rock', 'hand-scissors', 'hand-spock', 'handshake', 'hdd', 'heart', 'hospital', 'hourglass', 'id-badge', 'id-card', 'image', 'images', 'keyboard', 'kiss', 'kiss-beam', 'kiss-wink-heart', 'laugh', 'laugh-beam', 'laugh-squint', 'laugh-wink', 'lemon', 'life-ring', 'lightbulb', 'list-alt', 'map', 'meh', 'meh-blank', 'meh-rolling-eyes', 'minus-square', 'money-bill-alt', 'moon', 'newspaper', 'object-group', 'object-ungroup', 'paper-plane', 'pause-circle', 'play-circle', 'plus-square', 'question-circle', 'registered', 'sad-cry', 'sad-tear', 'save', 'share-square', 'smile', 'smile-beam', 'smile-wink', 'snowflake', 'square', 'star', 'star-half', 'sticky-note', 'stop-circle', 'sun', 'surprise', 'thumbs-down', 'thumbs-up', 'times-circle', 'tired', 'trash-alt', 'user', 'user-circle', 'window-close', 'window-maximize', 'window-minimize', 'window-restore')][string] $IconRegular, [parameter(ParameterSetName = "FontAwesomeSolid")] [ValidateSet('address-card', 'adjust', 'air-freshener', 'align-center', 'align-justify', 'align-left', 'align-right', 'allergies', 'ambulance', 'american-sign-language-interpreting', 'anchor', 'angle-double-down', 'angle-double-left', 'angle-double-right', 'angle-double-up', 'angle-down', 'angle-left', 'angle-right', 'angle-up', 'angry', 'ankh', 'apple-alt', 'archive', 'archway', 'arrow-alt-circle-down', 'arrow-alt-circle-left', 'arrow-alt-circle-right', 'arrow-alt-circle-up', 'arrow-circle-down', 'arrow-circle-left', 'arrow-circle-right', 'arrow-circle-up', 'arrow-down', 'arrow-left', 'arrow-right', 'arrow-up', 'arrows-alt', 'arrows-alt-h', 'arrows-alt-v', 'assistive-listening-systems', 'asterisk', 'at', 'atlas', 'atom', 'audio-description', 'award', 'baby', 'baby-carriage', 'backspace', 'backward', 'bacon', 'balance-scale', 'balance-scale-left', 'balance-scale-right', 'ban', 'band-aid', 'barcode', 'bars', 'baseball-ball', 'basketball-ball', 'bath', 'battery-empty', 'battery-full', 'battery-half', 'battery-quarter', 'battery-three-quarters', 'bed', 'beer', 'bell', 'bell-slash', 'bezier-curve', 'bible', 'bicycle', 'biking', 'binoculars', 'biohazard', 'birthday-cake', 'blender', 'blender-phone', 'blind', 'blog', 'bold', 'bolt', 'bomb', 'bone', 'bong', 'book', 'book-dead', 'book-medical', 'book-open', 'book-reader', 'bookmark', 'border-all', 'border-none', 'border-style', 'bowling-ball', 'box', 'box-open', 'boxes', 'braille', 'brain', 'bread-slice', 'briefcase', 'briefcase-medical', 'broadcast-tower', 'broom', 'brush', 'bug', 'building', 'bullhorn', 'bullseye', 'burn', 'bus', 'bus-alt', 'business-time', 'calculator', 'calendar', 'calendar-alt', 'calendar-check', 'calendar-day', 'calendar-minus', 'calendar-plus', 'calendar-times', 'calendar-week', 'camera', 'camera-retro', 'campground', 'candy-cane', 'cannabis', 'capsules', 'car', 'car-alt', 'car-battery', 'car-crash', 'car-side', 'caret-down', 'caret-left', 'caret-right', 'caret-square-down', 'caret-square-left', 'caret-square-right', 'caret-square-up', 'caret-up', 'carrot', 'cart-arrow-down', 'cart-plus', 'cash-register', 'cat', 'certificate', 'chair', 'chalkboard', 'chalkboard-teacher', 'charging-station', 'chart-area', 'chart-bar', 'chart-line', 'chart-pie', 'check', 'check-circle', 'check-double', 'check-square', 'cheese', 'chess', 'chess-bishop', 'chess-board', 'chess-king', 'chess-knight', 'chess-pawn', 'chess-queen', 'chess-rook', 'chevron-circle-down', 'chevron-circle-left', 'chevron-circle-right', 'chevron-circle-up', 'chevron-down', 'chevron-left', 'chevron-right', 'chevron-up', 'child', 'church', 'circle', 'circle-notch', 'city', 'clinic-medical', 'clipboard', 'clipboard-check', 'clipboard-list', 'clock', 'clone', 'closed-captioning', 'cloud', 'cloud-download-alt', 'cloud-meatball', 'cloud-moon', 'cloud-moon-rain', 'cloud-rain', 'cloud-showers-heavy', 'cloud-sun', 'cloud-sun-rain', 'cloud-upload-alt', 'cocktail', 'code', 'code-branch', 'coffee', 'cog', 'cogs', 'coins', 'columns', 'comment', 'comment-alt', 'comment-dollar', 'comment-dots', 'comment-medical', 'comment-slash', 'comments', 'comments-dollar', 'compact-disc', 'compass', 'compress', 'compress-arrows-alt', 'concierge-bell', 'cookie', 'cookie-bite', 'copy', 'copyright', 'couch', 'credit-card', 'crop', 'crop-alt', 'cross', 'crosshairs', 'crow', 'crown', 'crutch', 'cube', 'cubes', 'cut', 'database', 'deaf', 'democrat', 'desktop', 'dharmachakra', 'diagnoses', 'dice', 'dice-d20', 'dice-d6', 'dice-five', 'dice-four', 'dice-one', 'dice-six', 'dice-three', 'dice-two', 'digital-tachograph', 'directions', 'divide', 'dizzy', 'dna', 'dog', 'dollar-sign', 'dolly', 'dolly-flatbed', 'donate', 'door-closed', 'door-open', 'dot-circle', 'dove', 'download', 'drafting-compass', 'dragon', 'draw-polygon', 'drum', 'drum-steelpan', 'drumstick-bite', 'dumbbell', 'dumpster', 'dumpster-fire', 'dungeon', 'edit', 'egg', 'eject', 'ellipsis-h', 'ellipsis-v', 'envelope', 'envelope-open', 'envelope-open-text', 'envelope-square', 'equals', 'eraser', 'ethernet', 'euro-sign', 'exchange-alt', 'exclamation', 'exclamation-circle', 'exclamation-triangle', 'expand', 'expand-arrows-alt', 'external-link-alt', 'external-link-square-alt', 'eye', 'eye-dropper', 'eye-slash', 'fan', 'fast-backward', 'fast-forward', 'fax', 'feather', 'feather-alt', 'female', 'fighter-jet', 'file', 'file-alt', 'file-archive', 'file-audio', 'file-code', 'file-contract', 'file-csv', 'file-download', 'file-excel', 'file-export', 'file-image', 'file-import', 'file-invoice', 'file-invoice-dollar', 'file-medical', 'file-medical-alt', 'file-pdf', 'file-powerpoint', 'file-prescription', 'file-signature', 'file-upload', 'file-video', 'file-word', 'fill', 'fill-drip', 'film', 'filter', 'fingerprint', 'fire', 'fire-alt', 'fire-extinguisher', 'first-aid', 'fish', 'fist-raised', 'flag', 'flag-checkered', 'flag-usa', 'flask', 'flushed', 'folder', 'folder-minus', 'folder-open', 'folder-plus', 'font', 'football-ball', 'forward', 'frog', 'frown', 'frown-open', 'funnel-dollar', 'futbol', 'gamepad', 'gas-pump', 'gavel', 'gem', 'genderless', 'ghost', 'gift', 'gifts', 'glass-cheers', 'glass-martini', 'glass-martini-alt', 'glass-whiskey', 'glasses', 'globe', 'globe-africa', 'globe-americas', 'globe-asia', 'globe-europe', 'golf-ball', 'gopuram', 'graduation-cap', 'greater-than', 'greater-than-equal', 'grimace', 'grin', 'grin-alt', 'grin-beam', 'grin-beam-sweat', 'grin-hearts', 'grin-squint', 'grin-squint-tears', 'grin-stars', 'grin-tears', 'grin-tongue', 'grin-tongue-squint', 'grin-tongue-wink', 'grin-wink', 'grip-horizontal', 'grip-lines', 'grip-lines-vertical', 'grip-vertical', 'guitar', 'h-square', 'hamburger', 'hammer', 'hamsa', 'hand-holding', 'hand-holding-heart', 'hand-holding-usd', 'hand-lizard', 'hand-middle-finger', 'hand-paper', 'hand-peace', 'hand-point-down', 'hand-point-left', 'hand-point-right', 'hand-point-up', 'hand-pointer', 'hand-rock', 'hand-scissors', 'hand-spock', 'hands', 'hands-helping', 'handshake', 'hanukiah', 'hard-hat', 'hashtag', 'hat-wizard', 'haykal', 'hdd', 'heading', 'headphones', 'headphones-alt', 'headset', 'heart', 'heart-broken', 'heartbeat', 'helicopter', 'highlighter', 'hiking', 'hippo', 'history', 'hockey-puck', 'holly-berry', 'home', 'horse', 'horse-head', 'hospital', 'hospital-alt', 'hospital-symbol', 'hot-tub', 'hotdog', 'hotel', 'hourglass', 'hourglass-end', 'hourglass-half', 'hourglass-start', 'house-damage', 'hryvnia', 'i-cursor', 'ice-cream', 'icicles', 'icons', 'id-badge', 'id-card', 'id-card-alt', 'igloo', 'image', 'images', 'inbox', 'indent', 'industry', 'infinity', 'info', 'info-circle', 'italic', 'jedi', 'joint', 'journal-whills', 'kaaba', 'key', 'keyboard', 'khanda', 'kiss', 'kiss-beam', 'kiss-wink-heart', 'kiwi-bird', 'landmark', 'language', 'laptop', 'laptop-code', 'laptop-medical', 'laugh', 'laugh-beam', 'laugh-squint', 'laugh-wink', 'layer-group', 'leaf', 'lemon', 'less-than', 'less-than-equal', 'level-down-alt', 'level-up-alt', 'life-ring', 'lightbulb', 'link', 'lira-sign', 'list', 'list-alt', 'list-ol', 'list-ul', 'location-arrow', 'lock', 'lock-open', 'long-arrow-alt-down', 'long-arrow-alt-left', 'long-arrow-alt-right', 'long-arrow-alt-up', 'low-vision', 'luggage-cart', 'magic', 'magnet', 'mail-bulk', 'male', 'map', 'map-marked', 'map-marked-alt', 'map-marker', 'map-marker-alt', 'map-pin', 'map-signs', 'marker', 'mars', 'mars-double', 'mars-stroke', 'mars-stroke-h', 'mars-stroke-v', 'mask', 'medal', 'medkit', 'meh', 'meh-blank', 'meh-rolling-eyes', 'memory', 'menorah', 'mercury', 'meteor', 'microchip', 'microphone', 'microphone-alt', 'microphone-alt-slash', 'microphone-slash', 'microscope', 'minus', 'minus-circle', 'minus-square', 'mitten', 'mobile', 'mobile-alt', 'money-bill', 'money-bill-alt', 'money-bill-wave', 'money-bill-wave-alt', 'money-check', 'money-check-alt', 'monument', 'moon', 'mortar-pestle', 'mosque', 'motorcycle', 'mountain', 'mouse-pointer', 'mug-hot', 'music', 'network-wired', 'neuter', 'newspaper', 'not-equal', 'notes-medical', 'object-group', 'object-ungroup', 'oil-can', 'om', 'otter', 'outdent', 'pager', 'paint-brush', 'paint-roller', 'palette', 'pallet', 'paper-plane', 'paperclip', 'parachute-box', 'paragraph', 'parking', 'passport', 'pastafarianism', 'paste', 'pause', 'pause-circle', 'paw', 'peace', 'pen', 'pen-alt', 'pen-fancy', 'pen-nib', 'pen-square', 'pencil-alt', 'pencil-ruler', 'people-carry', 'pepper-hot', 'percent', 'percentage', 'person-booth', 'phone', 'phone-alt', 'phone-slash', 'phone-square', 'phone-square-alt', 'phone-volume', 'photo-video', 'piggy-bank', 'pills', 'pizza-slice', 'place-of-worship', 'plane', 'plane-arrival', 'plane-departure', 'play', 'play-circle', 'plug', 'plus', 'plus-circle', 'plus-square', 'podcast', 'poll', 'poll-h', 'poo', 'poo-storm', 'poop', 'portrait', 'pound-sign', 'power-off', 'pray', 'praying-hands', 'prescription', 'prescription-bottle', 'prescription-bottle-alt', 'print', 'procedures', 'project-diagram', 'puzzle-piece', 'qrcode', 'question', 'question-circle', 'quidditch', 'quote-left', 'quote-right', 'quran', 'radiation', 'radiation-alt', 'rainbow', 'random', 'receipt', 'recycle', 'redo', 'redo-alt', 'registered', 'remove-format', 'reply', 'reply-all', 'republican', 'restroom', 'retweet', 'ribbon', 'ring', 'road', 'robot', 'rocket', 'route', 'rss', 'rss-square', 'ruble-sign', 'ruler', 'ruler-combined', 'ruler-horizontal', 'ruler-vertical', 'running', 'rupee-sign', 'sad-cry', 'sad-tear', 'satellite', 'satellite-dish', 'save', 'school', 'screwdriver', 'scroll', 'sd-card', 'search', 'search-dollar', 'search-location', 'search-minus', 'search-plus', 'seedling', 'server', 'shapes', 'share', 'share-alt', 'share-alt-square', 'share-square', 'shekel-sign', 'shield-alt', 'ship', 'shipping-fast', 'shoe-prints', 'shopping-bag', 'shopping-basket', 'shopping-cart', 'shower', 'shuttle-van', 'sign', 'sign-in-alt', 'sign-language', 'sign-out-alt', 'signal', 'signature', 'sim-card', 'sitemap', 'skating', 'skiing', 'skiing-nordic', 'skull', 'skull-crossbones', 'slash', 'sleigh', 'sliders-h', 'smile', 'smile-beam', 'smile-wink', 'smog', 'smoking', 'smoking-ban', 'sms', 'snowboarding', 'snowflake', 'snowman', 'snowplow', 'socks', 'solar-panel', 'sort', 'sort-alpha-down', 'sort-alpha-down-alt', 'sort-alpha-up', 'sort-alpha-up-alt', 'sort-amount-down', 'sort-amount-down-alt', 'sort-amount-up', 'sort-amount-up-alt', 'sort-down', 'sort-numeric-down', 'sort-numeric-down-alt', 'sort-numeric-up', 'sort-numeric-up-alt', 'sort-up', 'spa', 'space-shuttle', 'spell-check', 'spider', 'spinner', 'splotch', 'spray-can', 'square', 'square-full', 'square-root-alt', 'stamp', 'star', 'star-and-crescent', 'star-half', 'star-half-alt', 'star-of-david', 'star-of-life', 'step-backward', 'step-forward', 'stethoscope', 'sticky-note', 'stop', 'stop-circle', 'stopwatch', 'store', 'store-alt', 'stream', 'street-view', 'strikethrough', 'stroopwafel', 'subscript', 'subway', 'suitcase', 'suitcase-rolling', 'sun', 'superscript', 'surprise', 'swatchbook', 'swimmer', 'swimming-pool', 'synagogue', 'sync', 'sync-alt', 'syringe', 'table', 'table-tennis', 'tablet', 'tablet-alt', 'tablets', 'tachometer-alt', 'tag', 'tags', 'tape', 'tasks', 'taxi', 'teeth', 'teeth-open', 'temperature-high', 'temperature-low', 'tenge', 'terminal', 'text-height', 'text-width', 'th', 'th-large', 'th-list', 'theater-masks', 'thermometer', 'thermometer-empty', 'thermometer-full', 'thermometer-half', 'thermometer-quarter', 'thermometer-three-quarters', 'thumbs-down', 'thumbs-up', 'thumbtack', 'ticket-alt', 'times', 'times-circle', 'tint', 'tint-slash', 'tired', 'toggle-off', 'toggle-on', 'toilet', 'toilet-paper', 'toolbox', 'tools', 'tooth', 'torah', 'torii-gate', 'tractor', 'trademark', 'traffic-light', 'train', 'tram', 'transgender', 'transgender-alt', 'trash', 'trash-alt', 'trash-restore', 'trash-restore-alt', 'tree', 'trophy', 'truck', 'truck-loading', 'truck-monster', 'truck-moving', 'truck-pickup', 'tshirt', 'tty', 'tv', 'umbrella', 'umbrella-beach', 'underline', 'undo', 'undo-alt', 'universal-access', 'university', 'unlink', 'unlock', 'unlock-alt', 'upload', 'user', 'user-alt', 'user-alt-slash', 'user-astronaut', 'user-check', 'user-circle', 'user-clock', 'user-cog', 'user-edit', 'user-friends', 'user-graduate', 'user-injured', 'user-lock', 'user-md', 'user-minus', 'user-ninja', 'user-nurse', 'user-plus', 'user-secret', 'user-shield', 'user-slash', 'user-tag', 'user-tie', 'user-times', 'users', 'users-cog', 'utensil-spoon', 'utensils', 'vector-square', 'venus', 'venus-double', 'venus-mars', 'vial', 'vials', 'video', 'video-slash', 'vihara', 'voicemail', 'volleyball-ball', 'volume-down', 'volume-mute', 'volume-off', 'volume-up', 'vote-yea', 'vr-cardboard', 'walking', 'wallet', 'warehouse', 'water', 'wave-square', 'weight', 'weight-hanging', 'wheelchair', 'wifi', 'wind', 'window-close', 'window-maximize', 'window-minimize', 'window-restore', 'wine-bottle', 'wine-glass', 'wine-glass-alt', 'won-sign', 'wrench', 'x-ray', 'yen-sign', 'yin-yang')][string] $IconSolid, [parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")][int] $TextSize, [parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")][RGBColors] $TextColor = [RGBColors]::None, [parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")][int] $IconSize, [parameter(ParameterSetName = "FontAwesomeBrands")] [parameter(ParameterSetName = "FontAwesomeRegular")] [parameter(ParameterSetName = "FontAwesomeSolid")][RGBColors] $IconColor = [RGBColors]::None) if (-not $Script:HTMLSchema.Features) { Write-Warning 'New-HTMLTab - Creation of HTML aborted. Most likely New-HTML is missing.' Exit } if ($IconBrands) { $Icon = "fab fa-$IconBrands" } elseif ($IconRegular) { $Icon = "far fa-$IconRegular" } elseif ($IconSolid) { $Icon = "fas fa-$IconSolid" } $StyleText = @{ } if ($TextSize -ne 0) { $StyleText.'font-size' = "$($TextSize)px" } if ($TextColor -ne [RGBColors]::None) { $StyleText.'color' = ConvertFrom-Color -Color $TextColor } $StyleIcon = @{ } if ($IconSize -ne 0) { $StyleIcon.'font-size' = "$($IconSize)px" } if ($IconColor -ne [RGBColors]::None) { $StyleIcon.'color' = ConvertFrom-Color -Color $IconColor } $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 = " $Name" $Tab.StyleIcon = $StyleIcon $Tab.StyleText = $StyleText $Tab.Current = $true if ($Script:HTMLSchema.TabsHeaders | Where-Object { $_.Active -eq $true }) { $Tab.Active = $false } else { $Tab.Active = $true } $Tab.Icon = $Icon $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($Heading)) { New-HTMLTag -Tag 'h7' { $Heading } } Invoke-Command -ScriptBlock $HtmlData } } function New-HTMLTabHead { [CmdletBinding()] Param () if ($Script:HTMLSchema.TabOptions.SlimTabs) { $Style = 'display: inline-block;' } else { $Style = '' } New-HTMLTag -Tag 'div' -Attributes @{class = 'tabsWrapper' } { New-HTMLTag -Tag 'div' -Attributes @{class = 'tabs'; style = $Style } { 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.Icon); style = $($Tab.StyleIcon) } New-HTMLTag -Tag 'span' -Attributes @{style = $($Tab.StyleText) } -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', 'pageLength')] $Buttons = @('copyHtml5', 'excelHtml5', 'csvHtml5', 'pdfHtml5', 'pageLength'), [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, [switch] $ScrollX, [switch] $ScrollY, [int] $ScrollSizeY = 500, [int] $FreezeColumnsLeft, [int] $FreezeColumnsRight, [switch] $FixedHeader, [switch] $FixedFooter, [string[]] $ResponsivePriorityOrder, [int[]] $ResponsivePriorityOrderIndex) if (-not $Script:HTMLSchema.Features) { Write-Warning 'New-HTMLTable - Creation of HTML aborted. Most likely New-HTML is missing.' Exit } $ConditionalFormatting = [System.Collections.Generic.List[PSCustomObject]]::new() $CustomButtons = [System.Collections.Generic.List[PSCustomObject]]::new() $HeaderRows = [System.Collections.Generic.List[PSCustomObject]]::new() $HeaderStyle = [System.Collections.Generic.List[PSCustomObject]]::new() $HeaderTop = [System.Collections.Generic.List[PSCustomObject]]::new() if ($HTML) { [Array] $Output = & $HTML if ($Output.Count -gt 0) { foreach ($Parameters in $Output) { if ($Parameters.Type -eq 'TableButtonPDF') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableButtonCSV') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableButtonPageLength') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableButtonExcel') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableButtonPDF') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableButtonPrint') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableButtonCopy') { $CustomButtons.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableCondition') { $ConditionalFormatting.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableHeaderMerge') { $HeaderRows.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableHeaderStyle') { $HeaderStyle.Add($Parameters.Output) } elseif ($Parameters.Type -eq 'TableHeaderFullRow') { $HeaderTop.Add($Parameters.Output) } } } } [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>' $AddedHeader = Add-TableHeader -HeaderRows $HeaderRows -HeaderNames $HeaderNames -HeaderStyle $HeaderStyle -HeaderTop $HeaderTop $Table = $Table | Select-Object -Skip 1 $Options = [ordered] @{dom = 'Bfrtip' buttons = @(if ($CustomButtons) { $CustomButtons } else { foreach ($button in $Buttons) { if ($button -ne 'pdfHtml5') { @{extend = $button } } else { @{extend = 'pdfHtml5' pageSize = 'A3' orientation = 'landscape' } } } }) "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 "select" = -not $DisableSelect.IsPresent "searching" = -not $DisableSearch.IsPresent "stateSave" = -not $DisableStateSave.IsPresent } if ($ScrollX) { $Options.'scrollX' = $true $DisableResponsiveTable = $true } if ($ScrollY) { $Options.'scrollY' = "$($ScrollSizeY)px" } if ($FreezeColumnsLeft -or $FreezeColumnsRight) { $Options.fixedColumns = [ordered] @{ } if ($FreezeColumnsLeft) { $Options.fixedColumns.leftColumns = $FreezeColumnsLeft } if ($FreezeColumnsRight) { $Options.fixedColumns.rightColumns = $FreezeColumnsRight } } if ($FixedHeader -or $FixedFooter) { $Options.fixedHeader = [ordered] @{ } if ($FixedHeader) { $Options.fixedHeader.header = $FixedHeader.IsPresent } if ($FixedFooter) { $Options.fixedHeader.footer = $FixedFooter.IsPresent } } if (-not $DisableResponsiveTable) { $Options."responsive" = @{details = $true } } if ($OrderMulti) { $Options.orderMulti = $OrderMulti.IsPresent } if ($Find -ne '') { $Options.search = @{search = $Find } } if ($DefaultSortOrder -eq 'Ascending') { $Sort = 'asc' } else { $Sort = 'desc' } 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) } } } if ($ColumnsOrder.Count -gt 0) { $Options."order" = @($ColumnsOrder) $Options.colReorder = $false } if ($ScreenSizePercent -gt 0) { $Options."scrollY" = "$($ScreenSizePercent)vh" } if ($null -ne $ConditionalFormatting) { $Options.createdRow = '' } if ($ResponsivePriorityOrderIndex -or $ResponsivePriorityOrder) { $PriorityOrder = 0 [Array] $PriorityOrderBinding = @(foreach ($_ in $ResponsivePriorityOrder) { $Index = [array]::indexof($HeaderNames.ToUpper(), $_.ToUpper()) if ($Index -ne -1) { @{responsivePriority = 0; targets = $Index } } } foreach ($_ in $ResponsivePriorityOrderIndex) { @{responsivePriority = 0; targets = $_ } }) $Options.columnDefs = @(foreach ($_ in $PriorityOrderBinding) { $PriorityOrder++ $_.responsivePriority = $PriorityOrder $_ }) } $Options = $Options | ConvertTo-Json -Depth 6 $Options = New-TableConditionalFormatting -Options $Options -ConditionalFormatting $ConditionalFormatting -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 '<', '<' -replace '>', '>' -replace '&nbsp;', ' ' -replace '"', '"' -replace ''', "'" } 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' { if ($AddedHeader) { $AddedHeader } else { $Header } } New-HTMLTag -Tag 'tbody' { $Table } if (-not $HideFooter) { New-HTMLTag -Tag 'tfoot' { $Header } } } $AfterTable } } function New-HTMLTableButtonCopy { [alias('TableButtonCopy', 'EmailTableButtonCopy')] [CmdletBinding()] param() [PSCustomObject] @{Type = 'TableButtonCopy' Output = @{extend = 'copyHtml5' } } } function New-HTMLTableButtonCSV { [alias('TableButtonCSV', 'EmailTableButtonCSV')] [CmdletBinding()] param() [PSCustomObject] @{Type = 'TableButtonCSV' Output = @{extend = 'csvHtml5' } } } function New-HTMLTableButtonExcel { [alias('TableButtonExcel', 'EmailTableButtonExcel')] [CmdletBinding()] param() [PSCustomObject] @{Type = 'TableButtonExcel' Output = @{extend = 'excelHtml5' } } } function New-HTMLTableButtonPageLength { [alias('TableButtonPageLength', 'EmailTableButtonPageLength')] [CmdletBinding()] param() [PSCustomObject] @{Type = 'TableButtonPageLength' Output = @{extend = 'pageLength' } } } function New-HTMLTableButtonPDF { <# .SYNOPSIS Allows more control when adding buttons to Table .DESCRIPTION Allows more control when adding buttons to Table. Works only within Table or New-HTMLTable scriptblock. .PARAMETER Title Document title (appears above the table in the generated PDF). The special character * is automatically replaced with the value read from the host document's title tag. .PARAMETER DisplayName The button's display text. The text can be configured using this option .PARAMETER MessageBottom Message to be shown at the bottom of the table, or the caption tag if displayed at the bottom of the table. .PARAMETER MessageTop Message to be shown at the top of the table, or the caption tag if displayed at the top of the table. .PARAMETER FileName File name to give the created file (plus the extension defined by the extension option). The special character * is automatically replaced with the value read from the host document's title tag. .PARAMETER Extension The extension to give the created file name. (default .pdf) .PARAMETER PageSize Paper size for the created PDF. This can be A3, A4, A5, LEGAL, LETTER or TABLOID. Other options are available. .PARAMETER Orientation Paper orientation for the created PDF. This can be portrait or landscape .PARAMETER Header Indicate if the table header should be included in the exported data or not. .PARAMETER Footer Indicate if the table footer should be included in the exported data or not. .EXAMPLE Dashboard -Name 'Dashimo Test' -FilePath $PSScriptRoot\DashboardEasy05.html -Show { Section -Name 'Test' -Collapsable { Container { Panel { Table -DataTable $Process { TableButtonPDF TableButtonCopy TableButtonExcel } -Buttons @() -DisableSearch -DisablePaging -HideFooter } Panel { Table -DataTable $Process -Buttons @() -DisableSearch -DisablePaging -HideFooter } Panel { Table -DataTable $Process { TableButtonPDF -PageSize A10 -Orientation landscape TableButtonCopy TableButtonExcel } -Buttons @() -DisableSearch -DisablePaging -HideFooter } } } } .NOTES Options are based on this URL: https://datatables.net/reference/button/pdfHtml5 #> [alias('TableButtonPDF', 'EmailTableButtonPDF')] [CmdletBinding()] param([string] $Title, [string] $DisplayName, [string] $MessageBottom, [string] $MessageTop, [string] $FileName, [string] $Extension, [string][ValidateSet('4A0', '2A0', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'RA0', 'RA1', 'RA2', 'RA3', 'RA4', 'SRA0', 'SRA1', 'SRA2', 'SRA3', 'SRA4', 'EXECUTIVE', 'FOLIO', 'LEGAL', 'LETTER', 'TABLOID')] $PageSize = 'A3', [string][ValidateSet('portrait', 'landscape')] $Orientation = 'landscape', [switch] $Header, [switch] $Footer) $Button = @{ } $Button.extend = 'pdfHtml5' $Button.pageSize = $PageSize $Button.orientation = $Orientation if ($MessageBottom) { $Button.messageBottom = $MessageBottom } if ($MessageTop) { $Button.messageTop = $MessageTop } if ($DisplayName) { $Button.text = $DisplayName } if ($Title) { $Button.title = $Title } if ($FileName) { $Button.filename = $FileName } if ($Extension) { $Button.extension = $Extension } if ($Header) { $Button.header = $Header.IsPresent } if ($Footer) { $Button.footer = $Footer.IsPresent } [PSCustomObject] @{Type = 'TableButtonPDF' Output = $Button } } function New-HTMLTableButtonPrint { [alias('TableButtonPrint', 'EmailTableButtonPrint')] [CmdletBinding()] param() $Button = @{extend = 'print' } [PSCustomObject] @{Type = 'TableButtonPrint' Output = $Button } } function New-HTMLTableCondition { [CmdletBinding()] param([alias('ColumnName')][string] $Name, [alias('Type')][ValidateSet('number', 'string')][string] $ComparisonType, [ValidateSet('lt', 'le', 'eq', 'ge', 'gt')][string] $Operator, [Object] $Value, [switch] $Row, [nullable[RGBColors]] $Color, [nullable[RGBColors]] $BackgroundColor) $TableCondition = [PSCustomObject] @{Row = $Row Type = $ComparisonType Name = $Name Operator = $Operator Value = $Value Color = $Color BackgroundColor = $BackgroundColor } [PSCustomObject] @{Type = 'TableCondition' Output = $TableCondition } } function New-HTMLTableHeader { [alias('TableHeader', 'EmailTableHeader')] [CmdletBinding()] param([string[]] $Names, [string] $Title, [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] $AddRow, [int] $ColumnCount) $Style = @{Color = $Color BackGroundColor = $BackGroundColor FontSize = $FontSize FontWeight = $FontWeight FontStyle = $FontStyle FontVariant = $FontVariant FontFamily = $FontFamily Alignment = $Alignment TextDecoration = $TextDecoration TextTransform = $TextTransform Direction = $Direction } Remove-EmptyValues -Hashtable $Style if (($AddRow -and $Title) -or ($Title -and -not $Names)) { $Type = 'TableHeaderFullRow' } elseif ((-not $AddRow -and $Title) -or ($Title -and $Names)) { $Type = 'TableHeaderMerge' } else { $Type = 'TableHeaderStyle' } [PSCustomObject]@{Type = $Type Output = @{Names = $Names Title = $Title Style = ConvertTo-HTMLStyle @Style ColumnCount = $ColumnCount } } } function New-HTMLTabOptions { [alias('TabOptions')] [CmdletBinding()] param([switch] $SlimTabs, [RGBColors] $SelectorColor = [RGBColors]::None, [RGBColors] $SelectorColorTarget = [RGBColors]::None, [switch] $Transition, [switch] $LinearGradient) if (-not $Script:HTMLSchema) { Write-Warning 'New-HTMLTabOptions - Creation of HTML aborted. Most likely New-HTML is missing.' Exit } $Script:HTMLSchema.TabOptions.SlimTabs = $SlimTabs.IsPresent if ($SelectorColor -ne [RGBColors]::None) { $Script:Configuration.Features.Tabs.CustomActionsReplace.ColorSelector = ConvertFrom-Color -Color $SelectorColor $Script:Configuration.Features.TabsGradient.CustomActionsReplace.ColorSelector = ConvertFrom-Color -Color $SelectorColor } if ($SelectorColorTarget -ne [RGBColors]::None) { $Script:Configuration.Features.Tabs.CustomActionsReplace.ColorTarget = ConvertFrom-Color -Color $SelectorColorTarget $Script:Configuration.Features.TabsGradient.CustomActionsReplace.ColorTarget = ConvertFrom-Color -Color $SelectorColorTarget } $Script:HTMLSchema.Features.TabsGradient = $LinearGradient.IsPresent $Script:HTMLSchema.Features.TabsTransition = $Transition.IsPresent } 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 { [alias('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 if ($PSEdition -eq 'Desktop') { $TextToFind = '"createdRow": ""' } else { $TextToFind = '"createdRow": ""' } $Options = $Options -Replace ($TextToFind, $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, [alias('Show', 'Open')][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 = 'https://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" } } DataTablesExperimental = @{Comment = 'DataTables 1.10.19' Header = @{JsLink = 'https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js' Js = "" Css = "" CssLink = 'https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css' } } DataTablesColReorder = @{Comment = 'DataTables ColReorder' Header = @{JsLink = 'https://cdn.datatables.net/colreorder/1.5.0/js/dataTables.colReorder.min.js' Js = "$PSScriptRoot\Resources\JS\dataTables.colReorder.min.js" Css = "$PSScriptRoot\Resources\CSS\colReorder.dataTables.min.css" CssLink = 'https://cdn.datatables.net/colreorder/1.5.0/css/colReorder.dataTables.min.css' } } 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" } CustomActionsReplace = @{'ColorSelector' = ConvertFrom-Color -Color ([RGBColors]::DodgerBlue) 'ColorTarget' = ConvertFrom-Color -Color ([RGBColors]::MediumSlateBlue) } } TabsGradient = @{Comment = 'Elastic Tabs Gradient' HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\tabs-elastic.gradient.css" } CustomActionsReplace = @{'ColorSelector' = ConvertFrom-Color -Color ([RGBColors]::DodgerBlue) 'ColorTarget' = ConvertFrom-Color -Color ([RGBColors]::MediumSlateBlue) } } TabsTransition = @{Comment = 'Elastic Tabs Transition' HeaderAlways = @{Css = "$PSScriptRoot\Resources\CSS\tabs-elastic.transition.css" } } 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-ChartAxisX', 'New-ChartAxisY', 'New-ChartBar', 'New-ChartBarOptions', 'New-ChartGrid', 'New-ChartLegend', 'New-ChartLine', 'New-ChartTheme', 'New-ChartToolbar', 'New-HTML', 'New-HTMLAnchor', 'New-HTMLAnchorLink', 'New-HTMLAnchorName', 'New-HTMLChart', '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-HTMLTable', 'New-HTMLTableButtonCopy', 'New-HTMLTableButtonCSV', 'New-HTMLTableButtonExcel', 'New-HTMLTableButtonPageLength', 'New-HTMLTableButtonPDF', 'New-HTMLTableButtonPrint', 'New-HTMLTableCondition', 'New-HTMLTableHeader', 'New-HTMLTabOptions', 'New-HTMLTag', 'New-HTMLText', 'New-HTMLTimeline', 'New-HTMLTimelineItem', 'New-HTMLToast', 'Out-HtmlView', 'Save-HTML') -Alias @('Chart', 'ChartAxisX', 'ChartAxisY', 'ChartBar', 'ChartBarOptions', 'ChartCategory', 'ChartGrid', 'ChartLegend', 'ChartLine', 'ChartTheme', 'ChartToolbar', 'EmailTableButtonCopy', 'EmailTableButtonCSV', 'EmailTableButtonExcel', 'EmailTableButtonPageLength', 'EmailTableButtonPDF', 'EmailTableButtonPrint', 'EmailTableHeader', 'HTMLText', 'New-ChartCategory', 'New-CSS', 'New-HTMLColumn', 'New-HTMLContent', 'New-JavaScript', 'New-ResourceCSS', 'New-ResourceJS', 'ohv', 'Out-GridHtml', 'TableButtonCopy', 'TableButtonCSV', 'TableButtonExcel', 'TableButtonPageLength', 'TableButtonPDF', 'TableButtonPrint', 'TableHeader', 'TabOptions') |