Private/Reporting.Html.ps1
|
function Complete-M365SnapshotHtmlReport { param( [Parameter(Mandatory=$true)] [string]$HtmlContent, [Parameter(Mandatory=$true)] [string]$ReportPath ) $HtmlContent = $HtmlContent -replace '<br>', '<br>' $HtmlContent = [regex]::Replace( $HtmlContent, '__APP_PORTAL_LINK__(?<id>[0-9a-fA-F\-]{36})\|(?<url>https?://[^<\s_]+(?:_[^<\s]+)?)?(?:__END_APP_PORTAL_LINK__)?', { param($match) $appId = $match.Groups['id'].Value $url = $match.Groups['url'].Value if ([string]::IsNullOrWhiteSpace($url)) { $url = "https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Overview/appId/$appId" } $safeHref = [System.Net.WebUtility]::HtmlEncode($url) $safeText = [System.Net.WebUtility]::HtmlEncode($appId) return ('<a href="{0}" target="_blank" rel="noopener noreferrer">{1}</a>' -f $safeHref, $safeText) }, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase ) $HtmlContent = [regex]::Replace( $HtmlContent, '(?<=<td>|<br>)([A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,})(?=</td>|<br>)', { param($match) $email = $match.Groups[1].Value $safeEmail = [System.Net.WebUtility]::HtmlEncode($email) return ('<a href="mailto:{0}">{1}</a>' -f $safeEmail, $safeEmail) }, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase ) $HtmlContent = [regex]::Replace( $HtmlContent, '(?<=<td>)([^<]+?)\s*\((https?://[^<]+)\)(?=</td>)', { param($match) $title = $match.Groups[1].Value.Trim() $url = $match.Groups[2].Value $safeHref = [System.Net.WebUtility]::HtmlEncode($url) $safeText = [System.Net.WebUtility]::HtmlEncode($title) return ('<a href="{0}" target="_blank" rel="noopener noreferrer">{1}</a>' -f $safeHref, $safeText) } ) $HtmlContent = [regex]::Replace( $HtmlContent, '(?<=<td>)(https?://[^<]+)(?=</td>)', { param($match) $url = $match.Groups[1].Value $displayText = $url try { $uri = [Uri]$url $displayText = if ([string]::IsNullOrWhiteSpace($uri.PathAndQuery)) { "/" } else { $uri.PathAndQuery } if (-not [string]::IsNullOrWhiteSpace($uri.Fragment)) { $displayText += $uri.Fragment } } catch { $displayText = $url } $safeHref = [System.Net.WebUtility]::HtmlEncode($url) $safeText = [System.Net.WebUtility]::HtmlEncode($displayText) return ('<a href="{0}" target="_blank" rel="noopener noreferrer">{1}</a>' -f $safeHref, $safeText) } ) $HtmlContent = [regex]::Replace( $HtmlContent, '<td(?<attrs>[^>]*)>(?<value>[^<]*)</td>', { param($match) $attrs = [string]$match.Groups['attrs'].Value $value = [string]$match.Groups['value'].Value $trimmedValue = $value.Trim() if ([string]::IsNullOrWhiteSpace($trimmedValue)) { return $match.Value } $isNumericLike = $trimmedValue -match '^[\(\[]?\s*[+-]?\d[\d,]*(?:\.\d+)?(?:\s?(?:%|GB|MB|TB|KB|B|days?|hrs?|hours?|mins?|minutes?|secs?|seconds?))?(?:\s*\([^)]+\))?[\)\]]?$' if (-not $isNumericLike) { return $match.Value } if ($attrs -match 'class\s*=\s*"(?<classes>[^"]*)"') { $existingClasses = [string]$Matches['classes'] if ($existingClasses -notmatch '(^|\s)num(\s|$)') { $newClasses = ($existingClasses + ' num').Trim() $attrs = [regex]::Replace($attrs, 'class\s*=\s*"[^"]*"', ('class="{0}"' -f $newClasses), 1) } return ('<td{0}>{1}</td>' -f $attrs, $value) } return ('<td class="num"{0}>{1}</td>' -f $attrs, $value) }, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase ) $HtmlContent | Out-File -FilePath $ReportPath -Encoding UTF8 -Force return $HtmlContent } |