Skip to content

v1.0.5#19

Merged
rebelinux merged 18 commits intoAsBuiltReport:devfrom
rebelinux:dev
Apr 2, 2026
Merged

v1.0.5#19
rebelinux merged 18 commits intoAsBuiltReport:devfrom
rebelinux:dev

Conversation

@rebelinux
Copy link
Copy Markdown
Collaborator

[1.0.5] - 2026-03-24

🧰 Added

  • Add Format-HtmlCell cmdlet to the module to format HTML table cells with specified background color, text color, and font size
  • Add Set-ImageOpacity cmdlet to the module to set the opacity of an image file
  • Add new parameters to Add-NodeImage cmdlet to set image opacity for node images
  • Add WaterMark support to SVG output format
    • Use the DiaConvertImageToPDF c# net4.8 package to add watermark support to SVG output format

🔃 Changed

  • Update module version to v1.0.5
  • Update edge length validation range, and help message to reflect the new range of 0 to 50 in Add-NodeEdge function
  • Update Pester workflow to run tests and upload results with code coverage support
  • Optimize aspect ratio calculation in Get-BestImageAspectRatio function

🔧 Fixed

  • Fix pester tests failing in Windows Pwsh 5.1+

rebelinux and others added 16 commits March 19, 2026 12:09
…ration

- Add Add-HtmlTableCell private function that builds Graphviz HTML <TR><TD>
  markup from Hashtable, OrderedDictionary, PSCustomObject, or string array input
- Accept all formatting parameters: FontName, FontSize, FontColor, FontBold,
  FontItalic, FontUnderline, FontStrikeThrough, Align, ColSpan, CellPadding,
  CellBorder, CellBackgroundColor, Port, IconDebug/DraftMode
- Export Add-HtmlTableCell in module manifest (FunctionsToExport)
- Add 26 Pester tests covering all input types, formatting options, and
  composability with Format-HtmlTable
- Add Example18.ps1 demonstrating all four input type variations
- Add .github/copilot-instructions.md for future Copilot sessions
- Mark Todo.md items complete

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Created tests for Add-NodeSpacer, Add-NodeText, Add-RightLShapeLine, Add-RightTShapeLine, Add-TShapeLine, Add-VerticalLine, Export-AbrDiagram, Get-AbrNodeIP, Get-ImagePercent, Get-RandomColorInHex, Get-RandomPastelColorInHex, Remove-SpecialCharacter, Split-ArrayElement, Test-AbrImage, and Test-AbrLogo.
- Each test file includes BeforeAll setup to initialize necessary scripts and variables.
- Tests cover various scenarios including valid inputs, expected outputs, and error handling.
Copilot AI review requested due to automatic review settings April 2, 2026 22:25
Copy link
Copy Markdown

@github-advanced-security github-advanced-security AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PSScriptAnalyzer found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Release prep for v1.0.5 of AsBuiltReport.Diagram, adding new HTML-cell formatting and image/SVG processing capabilities, plus a large expansion of Pester coverage and CI test execution changes.

Changes:

  • Add HTML cell builder (Format-HtmlCell) and extend node image rendering with opacity support.
  • Add/extend .NET cmdlets for image opacity and SVG watermarking (net8.0 + net48).
  • Expand Pester suite and update CI workflow to run tests via a repo script (with optional code coverage output).

Reviewed changes

Copilot reviewed 27 out of 60 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
Todo.md Updates TODO items (now marking some as complete).
CHANGELOG.md Adds v1.0.5 release notes.
AsBuiltReport.Diagram/AsBuiltReport.Diagram.psd1 Bumps module version and updates exported functions list.
AsBuiltReport.Diagram/Src/Private/Format-HtmlCell.ps1 Adds new helper to generate Graphviz HTML <TR><TD> cell markup.
AsBuiltReport.Diagram/Src/Private/Add-NodeImage.ps1 Adds ImageOpacityPercent support when embedding node images.
AsBuiltReport.Diagram/Src/Private/Add-NodeEdge.ps1 Expands EdgeLength validation range (0–50).
AsBuiltReport.Diagram/Src/Private/Get-BestImageAspectRatio.ps1 Refactors aspect-ratio calculation logic.
AsBuiltReport.Diagram/Src/Private/Resize-Image.ps1 Changes smoothing behavior control.
AsBuiltReport.Diagram/Src/Private/ConvertTo-Svg.ps1 Adjusts watermark opacity handling when calling Add-WatermarkToSvg.
AsBuiltReport.Diagram/Src/Private/ConvertTo-Dot.ps1 Forces Export-PSGraph failures to throw (-ErrorAction Stop).
Tests/_InitializeTests.ps1 Updates Graphviz path + assembly paths; adds Test-AbrBase64 helper.
Tests/Invoke-Tests.ps1 New test runner script (optional results XML + code coverage).
Tests/Export-AbrDiagram.Tests.ps1 Relaxes Base64 assertion to validate “is Base64” instead of exact string match.
Tests/Add-NodeImage.Tests.ps1 Adds coverage for new ImageOpacityPercent behavior.
Tests/Format-HtmlCell.Tests.ps1 Adds coverage for new Format-HtmlCell helper.
Tests/Test-AbrLogo.Tests.ps1 Adds Pester coverage for Test-AbrLogo.
Tests/Test-AbrImage.Tests.ps1 Adds Pester coverage for Test-AbrImage.
Tests/Split-ArrayElement.Tests.ps1 Adds Pester coverage for Split-ArrayElement.
Tests/Remove-SpecialCharacter.Tests.ps1 Adds Pester coverage for Remove-SpecialCharacter.
Tests/Get-RandomPastelColorInHex.Tests.ps1 Adds Pester coverage for pastel color helper.
Tests/Get-RandomColorInHex.Tests.ps1 Adds Pester coverage for color helper.
Tests/Get-ImagePercent.Tests.ps1 Adds Pester coverage for image sizing by percent.
Tests/Get-AbrNodeIP.Tests.ps1 Adds Pester coverage for hostname->IP helper.
Tests/Add-NodeEdge.Tests.ps1 Adds/expands edge-generation tests.
Tests/Add-NodeIcon.Tests.ps1 Adds Pester coverage for icon node builder.
Tests/Add-NodeText.Tests.ps1 Adds Pester coverage for text node builder.
Tests/Add-NodeShape.Tests.ps1 Adds Pester coverage for shape node builder.
Tests/Add-NodeSpacer.Tests.ps1 Adds Pester coverage for spacer node builder.
Tests/Add-HtmlLabel.Tests.ps1 Adds Pester coverage for label table builder.
Tests/Add-HtmlTable.Tests.ps1 Adds Pester coverage for HTML table builder.
Tests/Add-HtmlNodeTable.Tests.ps1 Adds Pester coverage for node table builder.
Tests/Add-HtmlSubGraph.Tests.ps1 Adds Pester coverage for subgraph HTML construction.
Tests/Add-HtmlSignatureTable.Tests.ps1 Adds Pester coverage for signature table builder.
Tests/Add-HorizontalLine.Tests.ps1 Adds Pester coverage for horizontal line helper.
Tests/Add-VerticalLine.Tests.ps1 Adds Pester coverage for vertical line helper.
Tests/Add-LShapeLine.Tests.ps1 Adds Pester coverage for L-shape line helper.
Tests/Add-RightLShapeLine.Tests.ps1 Adds Pester coverage for right L-shape line helper.
Tests/Add-LeftLShapeLine.Tests.ps1 Adds Pester coverage for left L-shape line helper.
Tests/Add-TShapeLine.Tests.ps1 Adds Pester coverage for T-shape line helper.
Tests/Add-RightTShapeLine.Tests.ps1 Adds Pester coverage for right T-shape line helper.
Tests/Add-LeftTShapeLine.Tests.ps1 Adds Pester coverage for left T-shape line helper.
Tests/Add-InvertedTShapeLine.Tests.ps1 Adds Pester coverage for inverted T-shape line helper.
Tests/Add-InvertedLShapeLine.Tests.ps1 Adds Pester coverage for inverted L-shape line helper.
Tests/Add-CrossShapeLine.Tests.ps1 Adds Pester coverage for cross-shape line helper.
Tests/Add-AbrWatermarkToImage.Tests.ps1 Adds Pester coverage for watermarking images.
Sources/Diagrammer/ImageProcessor.cs Adds ImageSharp-based SetImageOpacity implementation.
Sources/Diagrammer/PowershellCmdlets/SetImageOpacityPwsh.cs Adds Set-ImageOpacity PowerShell cmdlet (net8.0).
Sources/Diagrammer/AbrDiagrammer.csproj Bumps library version + updates Newtonsoft.Json version.
Sources/DiaConvertImageToPDF/ImageProcessor.cs Adds net48 SVG watermark + opacity processing helpers.
Sources/DiaConvertImageToPDF/PowershellCmdlets/SetImageOpacityPwsh.cs Adds Set-ImageOpacity PowerShell cmdlet (net48).
Sources/DiaConvertImageToPDF/PowershellCmdlets/AddWatermarkToSvgPwsh.cs Adds Add-WatermarkToSvg cmdlet (net48).
Sources/DiaConvertImageToPDF/AbrDiaConvertImageToPDF.csproj Adds explicit framework references for drawing/XML.
Sources/DiaConvertImageToPDF/Todo.md Adds DiaConvertImageToPDF todo notes.
.github/workflows/Pester.yml Switches CI test execution to Tests/Invoke-Tests.ps1 and uploads results XML.
.github/copilot-instructions.md Adds repo-specific Copilot/build/test guidance.
.vscode/tasks.json Updates task labels/paths for renamed csproj files.
.vscode/launch.json Adds launch profiles for debugging PowerShell cmdlets.
.gitignore Stops ignoring launch.json; keeps ignoring .cache.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 124 to +133
$originalWidth = $Image.Width
$originalHeight = $Image.Height
$aspectRatio = $originalWidth / $originalHeight

# Determine new dimensions based on constraints
if ($MaxWidth -and $originalWidth -gt $MaxWidth) {
$newWidth = $MaxWidth
$newHeight = [int]($newWidth / $aspectRatio)
} elseif ($MaxHeight -and $originalHeight -gt $MaxHeight) {
$newHeight = $MaxHeight
$newWidth = [int]($newHeight * $aspectRatio)
} else {
$newWidth = $originalWidth
$newHeight = $originalHeight
}
$ratioX = $MaxWidth / $OriginalWidth
$ratioY = $MaxHeight / $OriginalHeight
$ratio = [Math]::Min($ratioX, $ratioY)

$ImagePrty = @{
'Width' = $newWidth
'Height' = $newHeight
'Width' = [int]($OriginalWidth * $ratio)
'Height' = [int]($OriginalHeight * $ratio)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new aspect-ratio calculation always scales using $MaxWidth/$MaxHeight, but both parameters are optional. When either is omitted/0, the ratio becomes 0 and the function returns Width/Height = 0. It can also upscale images when MaxWidth/MaxHeight are larger than the original. Consider only applying scaling when constraints are provided, and cap the ratio at 1.0 to avoid upscaling.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread AsBuiltReport.Diagram/Src/Private/Add-NodeImage.ps1 Outdated
Comment thread AsBuiltReport.Diagram/AsBuiltReport.Diagram.psd1 Outdated
Comment on lines +24 to 25
default { Join-Path -Path $ProjectRoot -ChildPath 'AsBuiltReport.Diagram\Tools\Graphviz\bin\dot.exe' }
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Windows Graphviz path uses a ChildPath string with doubled backslashes (AsBuiltReport.Diagram\\Tools\\Graphviz...). This works inconsistently depending on how the path is normalized and is harder to read. Prefer building the path via Join-Path segments (or a single-backslash literal) to avoid accidental \\ in the final path.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread Tests/Invoke-Tests.ps1
Comment on lines +1 to +7
<#
.SYNOPSIS
Invoke Pester tests for AsBuiltReport.Microsoft.AD module

.DESCRIPTION
This script runs Pester tests with optional code coverage analysis.
It's designed to work with CI/CD pipelines and local development.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header comment says this runs tests for AsBuiltReport.Microsoft.AD, but this repository/module is AsBuiltReport.Diagram (as used later in the script). Please update the synopsis to avoid confusion for contributors and CI logs.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment on lines +158 to +177
[Parameter(
ParameterSetName = 'Image',
Mandatory = $false,
HelpMessage = 'Applies fixedsize="true" with the given Width and Height to the TD cell.'
)]
[switch] $FixedSize,

[Parameter(
ParameterSetName = 'Image',
Mandatory = $false,
HelpMessage = 'Cell width in pixels. Requires -FixedSize.'
)]
[int] $Width,

[Parameter(
ParameterSetName = 'Image',
Mandatory = $false,
HelpMessage = 'Cell height in pixels. Requires -FixedSize.'
)]
[int] $Height,
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-FixedSize is documented as requiring -Width and -Height, but neither is enforced. If a caller sets -FixedSize without width/height, the function will emit width="0" height="0", producing invalid/unexpected Graphviz HTML. Consider making Width/Height mandatory when -FixedSize is set (or validate > 0 at runtime and throw).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread Todo.md
Comment on lines 5 to +11
- [ ] Add pester to test this funtionality
- [ ] Add documentation for this funtionality
- [ ] Add example for this funtionality
- [ ] Add function to dinamically build Table cells based on input hashtable use Format-HTMLTable as example
- [ ] Add pester to test this funtionality
- [ ] Add documentation for this funtionality
- [ ] Add example for this funtionality
- [x] Add function to dinamically build Table cells based on input use Format-HTMLTable as example
- [x] Add pester to test this funtionality
- [x] Add documentation for this funtionality
- [x] Add example for this funtionality
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: “dinamically” should be “dynamically”, and “funtionality” should be “functionality”. Updating these improves readability of the project todo list.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

rebelinux and others added 2 commits April 2, 2026 18:31
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@rebelinux
Copy link
Copy Markdown
Collaborator Author

@copilot apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 60 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +127 to 134
$ratioX = $MaxWidth / $OriginalWidth
$ratioY = $MaxHeight / $OriginalHeight
$ratio = [Math]::Min($ratioX, $ratioY)

$ImagePrty = @{
'Width' = $newWidth
'Height' = $newHeight
'Width' = [int]($OriginalWidth * $ratio)
'Height' = [int]($OriginalHeight * $ratio)
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated scaling logic will return Width/Height = 0 when either -MaxWidth or -MaxHeight is omitted (they default to 0, so the min ratio becomes 0). It can also upscale images when both max values exceed the original size. Consider treating unspecified constraints as “no limit” and capping the computed ratio at 1.0 so you only downscale (or fall back to original dimensions when both are unset).

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +176
HelpMessage = 'Cell width in pixels. Requires -FixedSize.'
)]
[int] $Width,

[Parameter(
ParameterSetName = 'Image',
Mandatory = $false,
HelpMessage = 'Cell height in pixels. Requires -FixedSize.'
)]
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-FixedSize is documented as requiring -Width and -Height, but there is no enforcement or validation. If callers pass -FixedSize without dimensions (or with 0/negative values), the function will emit width/height attributes with invalid values, which can break Graphviz HTML label rendering. Make Width/Height mandatory when -FixedSize is set (or throw when they are not > 0).

Suggested change
HelpMessage = 'Cell width in pixels. Requires -FixedSize.'
)]
[int] $Width,
[Parameter(
ParameterSetName = 'Image',
Mandatory = $false,
HelpMessage = 'Cell height in pixels. Requires -FixedSize.'
)]
HelpMessage = 'Cell width in pixels. Requires -FixedSize and must be greater than 0.'
)]
[ValidateRange(1, [int]::MaxValue)]
[int] $Width,
[Parameter(
ParameterSetName = 'Image',
Mandatory = $false,
HelpMessage = 'Cell height in pixels. Requires -FixedSize and must be greater than 0.'
)]
[ValidateRange(1, [int]::MaxValue)]

Copilot uses AI. Check for mistakes.
[Parameter(Mandatory = $False, ParameterSetName = 'Absolute')][Int]$Width,
[Parameter(Mandatory = $False, ParameterSetName = 'Percent')][Double]$Percentage,
[Parameter(Mandatory = $False)][System.Drawing.Drawing2D.SmoothingMode]$SmoothingMode = 'HighQuality',
[Parameter(Mandatory = $False)][Switch]$SmoothingMode,
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SmoothingMode parameter was changed from a System.Drawing.Drawing2D.SmoothingMode value (default HighQuality) to a [switch]. This is a breaking change for any callers passing an enum value, and it also contradicts the help text that says the default is HighQuality (now HighQuality is only applied when the switch is present). Consider restoring the enum parameter (with default HighQuality) or updating the parameter name/docs to reflect the new behavior (e.g., -HighQualitySmoothing).

Suggested change
[Parameter(Mandatory = $False)][Switch]$SmoothingMode,
[Parameter(Mandatory = $False)][System.Drawing.Drawing2D.SmoothingMode]$SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality,

Copilot uses AI. Check for mistakes.
Comment on lines +163 to +173
# Apply opacity to a temp file when requested
$IconSrc = $ICON
if ($ImageOpacityPercent -lt 100) {
if (-not $IconPath) {
throw 'IconPath is required when ImageOpacityPercent is less than 100.'
}
$sourcePath = Join-Path -Path $IconPath -ChildPath $ICON
$ext = [System.IO.Path]::GetExtension($ICON)
$tempFileName = [System.IO.Path]::GetRandomFileName()
$IconSrc = [System.IO.Path]::ChangeExtension((Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $tempFileName), $ext)
Set-ImageOpacity -SourceImageFilePath $sourcePath -OutputImageFilePath $IconSrc -Opacity $ImageOpacityPercent | Out-Null
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When ImageOpacityPercent < 100, $IconSrc becomes an absolute temp-file path and is embedded directly into the . This can create two issues: (1) temp files are never cleaned up, and (2) downstream SVG post-processing that regex-replaces image hrefs can break when the matched string contains backslashes/regex metacharacters. Consider writing the opacity-adjusted image into a known module temp folder and returning just the leaf filename (or ensure the later replace step escapes the match string), and add a cleanup strategy.

Suggested change
# Apply opacity to a temp file when requested
$IconSrc = $ICON
if ($ImageOpacityPercent -lt 100) {
if (-not $IconPath) {
throw 'IconPath is required when ImageOpacityPercent is less than 100.'
}
$sourcePath = Join-Path -Path $IconPath -ChildPath $ICON
$ext = [System.IO.Path]::GetExtension($ICON)
$tempFileName = [System.IO.Path]::GetRandomFileName()
$IconSrc = [System.IO.Path]::ChangeExtension((Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $tempFileName), $ext)
Set-ImageOpacity -SourceImageFilePath $sourcePath -OutputImageFilePath $IconSrc -Opacity $ImageOpacityPercent | Out-Null
# Apply opacity to a module-scoped temp file when requested.
# Keep the HTML img src as a leaf filename so later SVG post-processing
# does not have to handle absolute paths with regex metacharacters.
$IconSrc = $ICON
if ($ImageOpacityPercent -lt 100) {
if (-not $IconPath) {
throw 'IconPath is required when ImageOpacityPercent is less than 100.'
}
$sourcePath = Join-Path -Path $IconPath -ChildPath $ICON
$moduleTempPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'AsBuiltReport.Diagram\NodeImageOpacity'
if (-not (Test-Path -Path $moduleTempPath)) {
New-Item -Path $moduleTempPath -ItemType Directory -Force | Out-Null
}
# Opportunistically remove stale generated images to avoid leaking temp files.
Get-ChildItem -Path $moduleTempPath -File -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-1) } |
Remove-Item -Force -ErrorAction SilentlyContinue
$ext = [System.IO.Path]::GetExtension($ICON)
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($ICON)
$generatedFileName = '{0}-{1}{2}' -f $baseName, ([guid]::NewGuid().ToString('N')), $ext
$generatedIconPath = Join-Path -Path $moduleTempPath -ChildPath $generatedFileName
Set-ImageOpacity -SourceImageFilePath $sourcePath -OutputImageFilePath $generatedIconPath -Opacity $ImageOpacityPercent | Out-Null
$IconSrc = [System.IO.Path]::GetFileName($generatedIconPath)

Copilot uses AI. Check for mistakes.
@rebelinux
Copy link
Copy Markdown
Collaborator Author

@copilot apply changes based on the comments in this thread

@rebelinux rebelinux merged commit 9f78763 into AsBuiltReport:dev Apr 2, 2026
9 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants