Skip to content

Commit 994943f

Browse files
committed
chore: automate README screenshot capture
1 parent 5ace0fa commit 994943f

3 files changed

Lines changed: 139 additions & 0 deletions

File tree

docs/readme/screenshot.png

6.47 KB
Loading

docs/tools.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,16 @@ dotnet run --project tools/Clever.TokenMap.VisualHarness -- compare --left .arti
2727
```
2828

2929
- Capture artifacts land under `.artifacts/visual-harness/`, compare artifacts under `.artifacts/visual-compare/`.
30+
31+
## README Screenshot
32+
33+
- Location: `scripts/capture-readme-screenshot.ps1`
34+
- Purpose: capture the current main window through `Visual Harness` directly at the `README` screenshot resolution so the docs asset can be refreshed without manual image editing.
35+
- Use it when you need to refresh `docs/readme/screenshot.png` for releases, documentation updates, or visual checks against the repo's current state.
36+
37+
```powershell
38+
powershell -File scripts/capture-readme-screenshot.ps1
39+
```
40+
41+
- By default the script captures the current repo root, writes raw harness artifacts to `.artifacts/visual-harness/readme/`, and updates `docs/readme/screenshot.png`.
42+
- If `docs/readme/screenshot.png` already exists, its current pixel size is reused automatically as the harness window size so the capture stays in the same native resolution.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
param(
2+
[string]$ProjectRoot = "",
3+
[string]$OutputPath = "",
4+
[string]$ArtifactDirectory = "",
5+
[int]$WindowWidth = 0,
6+
[int]$WindowHeight = 0
7+
)
8+
9+
$ErrorActionPreference = "Stop"
10+
Set-StrictMode -Version Latest
11+
12+
function Invoke-ExternalCommand {
13+
param(
14+
[Parameter(Mandatory = $true)]
15+
[string]$FilePath,
16+
[string[]]$ArgumentList = @()
17+
)
18+
19+
$display = if ($ArgumentList.Count -gt 0) { "$FilePath $($ArgumentList -join ' ')" } else { $FilePath }
20+
Write-Host ">> $display"
21+
22+
& $FilePath @ArgumentList
23+
if ($LASTEXITCODE -ne 0) {
24+
throw "Command failed: $display"
25+
}
26+
}
27+
28+
function Resolve-AbsolutePath {
29+
param(
30+
[Parameter(Mandatory = $true)]
31+
[string]$BasePath,
32+
[Parameter(Mandatory = $true)]
33+
[string]$PathValue
34+
)
35+
36+
if ([System.IO.Path]::IsPathRooted($PathValue)) {
37+
return [System.IO.Path]::GetFullPath($PathValue)
38+
}
39+
40+
return [System.IO.Path]::GetFullPath((Join-Path $BasePath $PathValue))
41+
}
42+
43+
function Get-ImageSize {
44+
param(
45+
[Parameter(Mandatory = $true)]
46+
[string]$Path
47+
)
48+
49+
Add-Type -AssemblyName System.Drawing
50+
51+
$image = [System.Drawing.Image]::FromFile($Path)
52+
try {
53+
return [pscustomobject]@{
54+
Width = $image.Width
55+
Height = $image.Height
56+
}
57+
}
58+
finally {
59+
$image.Dispose()
60+
}
61+
}
62+
63+
$repoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot ".."))
64+
$projectRootValue = if ([string]::IsNullOrWhiteSpace($ProjectRoot)) { $repoRoot } else { Resolve-AbsolutePath -BasePath $repoRoot -PathValue $ProjectRoot }
65+
$outputPathValue = if ([string]::IsNullOrWhiteSpace($OutputPath)) { Join-Path $repoRoot "docs\\readme\\screenshot.png" } else { Resolve-AbsolutePath -BasePath $repoRoot -PathValue $OutputPath }
66+
$artifactDirectoryValue = if ([string]::IsNullOrWhiteSpace($ArtifactDirectory)) { Join-Path $repoRoot ".artifacts\\visual-harness\\readme" } else { Resolve-AbsolutePath -BasePath $repoRoot -PathValue $ArtifactDirectory }
67+
68+
if (-not (Test-Path $projectRootValue -PathType Container)) {
69+
throw "Project root was not found at '$projectRootValue'."
70+
}
71+
72+
if (($WindowWidth -le 0 -or $WindowHeight -le 0) -and (Test-Path $outputPathValue -PathType Leaf)) {
73+
$existingImageSize = Get-ImageSize -Path $outputPathValue
74+
if ($WindowWidth -le 0) {
75+
$WindowWidth = $existingImageSize.Width
76+
}
77+
78+
if ($WindowHeight -le 0) {
79+
$WindowHeight = $existingImageSize.Height
80+
}
81+
}
82+
83+
if ($WindowWidth -le 0) {
84+
$WindowWidth = 1257
85+
}
86+
87+
if ($WindowHeight -le 0) {
88+
$WindowHeight = 786
89+
}
90+
91+
if (Test-Path $artifactDirectoryValue) {
92+
Remove-Item -LiteralPath $artifactDirectoryValue -Recurse -Force
93+
}
94+
95+
New-Item -ItemType Directory -Force -Path $artifactDirectoryValue | Out-Null
96+
97+
Invoke-ExternalCommand -FilePath "dotnet" -ArgumentList @(
98+
"run",
99+
"--project", (Join-Path $repoRoot "tools\\Clever.TokenMap.VisualHarness"),
100+
"--",
101+
"capture",
102+
"--source", "repo",
103+
"--project-root", $projectRootValue,
104+
"--theme", "dark",
105+
"--surface", "main",
106+
"--palette", "weighted",
107+
"--metric", "tokens",
108+
"--window-width", $WindowWidth.ToString([System.Globalization.CultureInfo]::InvariantCulture),
109+
"--window-height", $WindowHeight.ToString([System.Globalization.CultureInfo]::InvariantCulture),
110+
"--output-dir", $artifactDirectoryValue
111+
)
112+
113+
$capturedImagePath = Join-Path $artifactDirectoryValue "main.weighted.png"
114+
if (-not (Test-Path $capturedImagePath -PathType Leaf)) {
115+
throw "Expected capture artifact was not produced: '$capturedImagePath'."
116+
}
117+
118+
$parentDirectory = Split-Path -Parent $outputPathValue
119+
if (-not [string]::IsNullOrWhiteSpace($parentDirectory)) {
120+
New-Item -ItemType Directory -Force -Path $parentDirectory | Out-Null
121+
}
122+
123+
Copy-Item -LiteralPath $capturedImagePath -Destination $outputPathValue -Force
124+
125+
Write-Host "Saved README screenshot: $outputPathValue ($WindowWidth x $WindowHeight)"
126+
Write-Host "Capture artifact directory: $artifactDirectoryValue"

0 commit comments

Comments
 (0)