Skip to content

Commit

Permalink
Advance Show-BuildGraph.ps1
Browse files Browse the repository at this point in the history
- use node ids and escape labels
- use node and edge tooltips
  • Loading branch information
nightroman committed Mar 1, 2024
1 parent eee20d2 commit 072ca3e
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 58 deletions.
8 changes: 6 additions & 2 deletions Release-Notes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Invoke-Build Release Notes

- `Show-BuildGraph.ps1` uses `Viz.js` by default and `dot` if `-Dot`
- `Show-BuildMermaid.ps1` uses `Mermaid` 10.8.0
`Show-BuildGraph.ps1`
- uses `Viz.js` by default and `dot` with `-Dot`
- shows node and edge tooltips (synopses, names)

`Show-BuildMermaid.ps1`
- uses `Mermaid` 10.8.0

## v5.10.5

Expand Down
36 changes: 20 additions & 16 deletions Show-BuildDgml.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,40 @@

param(
[Parameter(Position=0)]
[string]$File,
[string]$File
,
[Parameter(Position=1)]
[string]$Output,
[hashtable]$Parameters,
[switch]$NoShow,
[string]$Output
,
[hashtable]$Parameters
,
[switch]$NoShow
,
[switch]$Number
)

trap {$PSCmdlet.ThrowTerminatingError($_)}
$ErrorActionPreference = 'Stop'
$ErrorActionPreference = 1

# output
### resolve output
if ($Output) {
$Output = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Output)
}
else {
$path = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($(if ($File) {$File} else {''}))
$name = [System.IO.Path]::GetFileNameWithoutExtension($path)
$hash = [IO.Path]::GetFileName([IO.Path]::GetDirectoryName($path))
$Output = "$env:TEMP\$name-$hash.dgml"
$hash = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName($path))
$Output = [System.IO.Path]::GetTempPath() + "$name-$hash.dgml"
}

# get tasks
### get tasks
if (!$Parameters) {$Parameters = @{}}
$all = Invoke-Build ?? $File @Parameters

# synopses
### for synopses
$docs = @{}
. Invoke-Build

# make DGML
### make DGML
$xml = [xml]'<?xml version="1.0" encoding="utf-8"?><DirectedGraph/>'
$doc = $xml.DocumentElement
$nodes = $doc.AppendChild($xml.CreateElement('Nodes'))
Expand Down Expand Up @@ -127,10 +130,11 @@ foreach($it in $all.get_Values()) {
}
}

# save DGML
### save DGML
$doc.SetAttribute('xmlns', 'http://schemas.microsoft.com/vs/2009/dgml')
$xml.Save($Output)

# show
if ($NoShow) {return}
Invoke-Item $Output
### show file
if (!$NoShow) {
Invoke-Item -LiteralPath $Output
}
94 changes: 60 additions & 34 deletions Show-BuildGraph.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# Make and show HTML using viz-standalone.js (local or online)
Show-BuildGraph
# Make and show PDF using dot
# Make and show SVG using dot
Show-BuildGraph -Dot
# Make Build.png with job numbers and top to bottom edges
Expand All @@ -33,18 +33,18 @@
.Parameter Output
The custom output file path. The default is in the temp directory.
When -Dot, the format is inferred from extension, PDF by default.
Otherwise the file extension should be .html.
When -Dot, the format is inferred from extension, SVG by default,
otherwise the file extension should be htm or html.
.Parameter Code
Custom DOT code added to the graph definition, see Graphviz manuals.
The default 'graph [rankdir=LR]' tells edges to go from left to right.
The default 'graph [rankdir=LR]' tells to make left to right edges.
.Parameter Parameters
Build script parameters needed in special cases when they alter tasks.
.Parameter Dot
Tells to use Graphviz dot. By default it creates a PDF file.
Tells to use Graphviz dot. By default it creates a SVG file.
For different formats use Output with the format extension.
.Parameter NoShow
Expand Down Expand Up @@ -92,7 +92,7 @@ else {
$jsUrl = 'file:///' + $app.Source.Replace('\', '/')
}
else {
$jsUrl = "https://github.com/mdaines/viz-js/releases/download/release-viz-3.2.4/viz-standalone.js"
$jsUrl = 'https://github.com/mdaines/viz-js/releases/download/release-viz-3.2.4/viz-standalone.js'
}
}

Expand All @@ -109,11 +109,11 @@ else {
$name = [System.IO.Path]::GetFileNameWithoutExtension($path)
$hash = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName($path))
if ($Dot) {
$Output = "$([System.IO.Path]::GetTempPath())/$name-$hash.pdf"
$type = 'pdf'
$Output = [System.IO.Path]::GetTempPath() + "$name-$hash.svg"
$type = 'svg'
}
else {
$Output = "$([System.IO.Path]::GetTempPath())/$name-$hash.html"
$Output = [System.IO.Path]::GetTempPath() + "$name-$hash.html"
$type = 'html'
}
}
Expand All @@ -122,45 +122,72 @@ else {
if (!$Parameters) {$Parameters = @{}}
$all = Invoke-Build ?? $File @Parameters

### for synopses
$docs = @{}
. Invoke-Build

### make dot-code

function escape_text($text) {
$text.Replace('\', '\\').Replace('"', '\"')
}

$text = @(
'digraph Tasks {'
### begin
'digraph {'
$Code

### nodes
$id = 0
$map = @{}
foreach($it in $all.get_Values()) {
++$id
$name = $it.Name
'"{0}"' -f $name
$map[$name] = $id
$attr = 'label="{0}"' -f (escape_text $name)

if ($synopsis = Get-BuildSynopsis $it $docs) {
$attr += ' tooltip="{0}"' -f (escape_text $synopsis)
}

$hasScript = foreach($job in $it.Jobs) {if ($job -is [scriptblock]) {$true}}
if ($hasScript) {
if ((-9).Equals($it.If)) {
$attr += ' shape=box'
}
else {
$attr += ' shape=diamond'
}
}

'{0} [{1}]' -f $id, $attr
}

### edges
$id = 0
foreach($it in $all.get_Values()) {
++$id
$jobNumber = 0
$hasScript = $false
foreach($job in $it.Jobs) {
++$jobNumber
if ($job -is [string]) {
$job, $safe = if ($job[0] -eq '?') {$job.Substring(1), 1} else {$job}
$job = $all[$job].Name
$edge = ' '
$id2 = $map[$job]
$tooltip = escape_text "$($it.Name) -> $job"
$attr = 'edgetooltip="{0}"' -f $tooltip
if ($Number) {
$edge += "label=$jobNumber "
$attr += ' label="{0}" labeltooltip="{1}"' -f $jobNumber, $tooltip
}
if ($safe) {
$edge += "style=dotted "
$attr += ' style=dotted'
}
'"{0}" -> "{1}" [{2}]' -f $name, $job, $edge
}
else {
$hasScript = $true
'{0} -> {1} [{2}]' -f $id, $id2, $attr
}
}

if ($hasScript) {
if ((-9).Equals($it.If)) {
$node = 'shape=box'
}
else {
$node = 'shape=diamond'
}
'"{0}" [ {1} ]' -f $name, $node
}
}

### end
'}'
)

Expand All @@ -175,7 +202,7 @@ if ($Dot) {
}
}
else {
$text = $text | .{process{$_.Replace('"', '\"') + '\'}} | Out-String -Width 9999
$text = $text | .{process{$_.Replace('\', '\\').Replace('"', '\"') + '\'}} | Out-String -Width 9999
@"
<!DOCTYPE html>
<html>
Expand All @@ -186,15 +213,14 @@ else {
<body>
<script src="$jsUrl"></script>
<script>
Viz.instance().then(function(viz) {document.body.appendChild(viz.renderSVGElement("$text"));});
Viz.instance().then(function(viz) {document.body.appendChild(viz.renderSVGElement("$text"))})
</script>
</body>
</html>
"@ | Set-Content -LiteralPath $Output -Encoding UTF8
}

### show file
if ($NoShow) {
return
if (!$NoShow) {
Invoke-Item -LiteralPath $Output
}
Invoke-Item $Output
11 changes: 5 additions & 6 deletions Show-BuildMermaid.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ else {
$path = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($(if ($File) {$File} else {''}))
$name = [System.IO.Path]::GetFileNameWithoutExtension($path)
$hash = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName($path))
$Output = "$([System.IO.Path]::GetTempPath())\$name-$hash.html"
$Output = [System.IO.Path]::GetTempPath() + "$name-$hash.html"
}

### get tasks
if (!$Parameters) {$Parameters = @{}}
$all = Invoke-Build ?? $File @Parameters

### synopses
### for synopses
$docs = @{}
. Invoke-Build

Expand Down Expand Up @@ -161,8 +161,7 @@ $text = @(
'@
) | Set-Content -LiteralPath $Output -Encoding UTF8

### show HTML
if ($NoShow) {
return
### show file
if (!$NoShow) {
Invoke-Item -LiteralPath $Output
}
Invoke-Item $Output

0 comments on commit 072ca3e

Please sign in to comment.