2026-10-21 15:41:51 -07:00
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
2026-10-23 09:08:21 -07:00
|
|
|
|
#if os(macOS)
|
2026-10-21 15:41:51 -07:00
|
|
|
|
@MainActor
|
2026-10-23 08:12:23 -07:00
|
|
|
|
func renderDiagram(html: Bool) -> Int32 {
|
2026-10-21 15:41:51 -07:00
|
|
|
|
FontSize.stored = false
|
|
|
|
|
|
let source = String(decoding: FileHandle.standardInput.readDataToEndOfFile(), as: UTF8.self)
|
2026-10-23 09:57:58 -07:00
|
|
|
|
let diagram: DiagramLayout
|
2026-10-21 15:41:51 -07:00
|
|
|
|
switch cachedBoxLayout(source) {
|
2026-10-23 09:57:58 -07:00
|
|
|
|
case .success(let d):
|
|
|
|
|
|
diagram = d
|
2026-10-21 15:41:51 -07:00
|
|
|
|
case .failure(let error):
|
|
|
|
|
|
FileHandle.standardError.write(Data(error.reason.utf8))
|
|
|
|
|
|
return 1
|
|
|
|
|
|
}
|
2026-10-23 08:12:23 -07:00
|
|
|
|
if html {
|
2026-10-23 09:57:58 -07:00
|
|
|
|
FileHandle.standardOutput.write(Data(diagramHTML(diagram).utf8))
|
2026-10-23 08:12:23 -07:00
|
|
|
|
return 0
|
|
|
|
|
|
}
|
2026-10-23 09:57:58 -07:00
|
|
|
|
let content = VStack(alignment: .leading, spacing: 24) {
|
|
|
|
|
|
ForEach(diagram.order, id: \.self) { level in
|
|
|
|
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
|
|
|
|
if diagram.order.count > 1 {
|
|
|
|
|
|
Text(diagram.trail(level).map(diagram.title).joined(separator: " › "))
|
|
|
|
|
|
.font(Font(titleFont))
|
|
|
|
|
|
.foregroundStyle(Palette.text)
|
|
|
|
|
|
}
|
|
|
|
|
|
let layout = diagram.levels[level]!
|
|
|
|
|
|
BoxCanvas(layout: layout)
|
|
|
|
|
|
.frame(width: layout.size.width, height: layout.size.height)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
guard let png = diagramCGImage(content).flatMap({ NSBitmapImageRep(cgImage: $0).representation(using: .png, properties: [:]) }) else {
|
2026-10-23 09:08:21 -07:00
|
|
|
|
FileHandle.standardError.write(Data("diagram didn't render".utf8))
|
|
|
|
|
|
return 1
|
|
|
|
|
|
}
|
|
|
|
|
|
FileHandle.standardOutput.write(png)
|
|
|
|
|
|
return 0
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
@MainActor
|
|
|
|
|
|
func diagramCGImage(_ layout: BoxLayout) -> CGImage? {
|
2026-10-23 09:57:58 -07:00
|
|
|
|
diagramCGImage(BoxCanvas(layout: layout).frame(width: layout.size.width, height: layout.size.height))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@MainActor
|
|
|
|
|
|
func diagramCGImage(_ view: some View) -> CGImage? {
|
|
|
|
|
|
let content = view
|
2026-10-21 15:41:51 -07:00
|
|
|
|
.padding(16)
|
|
|
|
|
|
.background(Palette.bg)
|
|
|
|
|
|
.environment(\.colorScheme, .light)
|
|
|
|
|
|
let renderer = ImageRenderer(content: content)
|
|
|
|
|
|
renderer.scale = 2
|
2026-10-23 09:08:21 -07:00
|
|
|
|
var image: CGImage?
|
|
|
|
|
|
#if os(macOS)
|
2026-10-21 15:41:51 -07:00
|
|
|
|
NSAppearance(named: .aqua)!.performAsCurrentDrawingAppearance {
|
2026-10-23 09:08:21 -07:00
|
|
|
|
image = renderer.cgImage
|
2026-10-21 15:41:51 -07:00
|
|
|
|
}
|
2026-10-23 09:08:21 -07:00
|
|
|
|
#else
|
|
|
|
|
|
UITraitCollection(userInterfaceStyle: .light).performAsCurrent {
|
|
|
|
|
|
image = renderer.cgImage
|
2026-10-21 15:41:51 -07:00
|
|
|
|
}
|
2026-10-23 09:08:21 -07:00
|
|
|
|
#endif
|
|
|
|
|
|
return image
|
2026-10-21 15:41:51 -07:00
|
|
|
|
}
|