Private/Write-EdgesFile.ps1
|
# Copyright (c) 2026 Jeffrey Snover. All rights reserved. # Licensed under the MIT License. See LICENSE file in the project root. function Write-EdgesFile { <# .SYNOPSIS Serialize an edges.json object to disk per the hybrid byte contract. .DESCRIPTION Writes taxonomy/Origin/edges.json in the format defined by docs/edges-json-format.md: top-level structure pretty-printed at 2 spaces, the `edges` array compacted one edge per line at 4-space indent. Output is UTF-8 no-BOM, LF-only, with exactly one trailing newline. This is the single serialization path for edges.json in PowerShell — every cmdlet that writes edges must delegate here so all writers (PS, TypeScript, Python) stay byte-identical and the 14 MB data-repo file does not churn. CRLF trap (already diagnosed in the contract, do not rediscover): `ConvertTo-Json` without `-Compress` emits CRLF on Windows. The pretty-print path below normalizes to LF before re-indenting so no stray `\r` survives. .PARAMETER EdgesData The edges document object (as produced by ConvertFrom-Json). Top-level key order and per-edge key order are preserved exactly as read. .PARAMETER Path Destination path for edges.json. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] $EdgesData, [Parameter(Mandatory = $true)] [string]$Path ) $sb = [System.Text.StringBuilder]::new() [void]$sb.Append("{`n") $props = @($EdgesData.PSObject.Properties) for ($i = 0; $i -lt $props.Count; $i++) { $prop = $props[$i] $keyJson = $prop.Name | ConvertTo-Json -Compress $trailing = if ($i -eq $props.Count - 1) { '' } else { ',' } if ($prop.Name -eq 'edges') { $edges = @($prop.Value) if ($edges.Count -eq 0) { # Rule 4: empty edges array is emitted inline. [void]$sb.Append(' ' + $keyJson + ': []' + $trailing + "`n") } else { [void]$sb.Append(' ' + $keyJson + ": [`n") for ($j = 0; $j -lt $edges.Count; $j++) { $edgeJson = $edges[$j] | ConvertTo-Json -Depth 20 -Compress $edgeComma = if ($j -eq $edges.Count - 1) { '' } else { ',' } [void]$sb.Append(' ' + $edgeJson + $edgeComma + "`n") } [void]$sb.Append(' ]' + $trailing + "`n") } } else { # Every non-edges value: pretty-print at 2 spaces, normalize CRLF->LF, # then re-indent one level (2 more spaces) to sit inside the root object. $pretty = ($prop.Value | ConvertTo-Json -Depth 20) -replace "`r`n", "`n" $lines = $pretty -split "`n" $indented = $lines[0] for ($k = 1; $k -lt $lines.Count; $k++) { $indented += "`n " + $lines[$k] } [void]$sb.Append(' ' + $keyJson + ': ' + $indented + $trailing + "`n") } } [void]$sb.Append('}') # Write-Utf8NoBom normalizes CRLF->LF and guarantees exactly one trailing newline. $sb.ToString() | Write-Utf8NoBom -Path $Path } |