Private/Write-AACResourceMapHtml.ps1
|
function Write-AACResourceMapHtml { <# .SYNOPSIS Writes the resource map as one self-contained HTML page: the map (ConvertTo-AACResourceMap), the Azure icons it uses and the ELK layout library, all inline - it opens without a network connection. .DESCRIPTION The page lays the map out in the browser with ELK's layered layout (left to right or top to bottom), draws it as SVG with the Azure icons, and lets you pan, zoom, search, highlight a resource's connections, switch the theme and direction, and save the map as a PNG, JPEG or SVG image. See Private\ResourceMap.html. #> [CmdletBinding()] param( [Parameter(Mandatory)] [hashtable] $Map, [Parameter(Mandatory)] [string] $Path, [Parameter(Mandatory)] [string] $Title, [string[]] $Fact = @(), [ValidateSet('RIGHT', 'DOWN')] [string] $Direction = 'RIGHT', [ValidateSet('dark', 'light', 'blueprint')] [string] $Theme = 'dark', # NSGs and route tables as chips on what they're applied to, or as cards. [ValidateSet('chips', 'cards')] [string] $NsgView = 'chips' ) $asset = Get-AACResourceMapAsset # Only the icons the map uses, plus the boxes' and the fallback. $used = [System.Collections.Generic.HashSet[string]]::new([string[]]@('resource', 'subscription', 'resourcegroup', 'vnet', 'subnet', 'nsg', 'routetable')) foreach ($node in $Map.Nodes) { [void]$used.Add([string]$node.icon) } foreach ($cluster in $Map.Clusters) { [void]$used.Add([string]$cluster.icon) } $icons = [ordered]@{} foreach ($key in $used) { if ($asset.Icons.icons.Contains($key)) { $icons[$key] = $asset.Icons.icons[$key] } } $model = [ordered]@{ title = $Title facts = @($Fact) options = @{ direction = $Direction; theme = $Theme; nsgView = $NsgView } clusters = @($Map.Clusters) nodes = @($Map.Nodes) edges = @($Map.Edges) icons = $icons } # '</' can't appear inside a <script> element; '<\/' is the same JSON. $json = (ConvertTo-Json -InputObject $model -Depth 12 -Compress).Replace('</', '<\/') $titleHtml = [System.Net.WebUtility]::HtmlEncode($Title) $html = $asset.Template.Replace('/*AAC:TITLE*/', $titleHtml).Replace('/*AAC:DATA*/', $json).Replace('/*AAC:ELK*/', $asset.Elk.Replace('</script', '<\/script')) $folder = Split-Path -Path $Path -Parent if ($folder -and -not (Test-Path -LiteralPath $folder)) { $null = New-Item -ItemType Directory -Path $folder -Force } [System.IO.File]::WriteAllText($Path, $html, [System.Text.UTF8Encoding]::new($false)) } |