Skip to content

Commit 04217e2

Browse files
committed
feat(render): add JSON output format for tower layout
- Add JSON tags to Layout and Block structs - Add RenderJSON sink alongside RenderSVG - Add --format flag to render command (svg default, json)
1 parent 5580558 commit 04217e2

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

internal/cli/render.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type renderOpts struct {
4141
nebraska bool
4242
popups bool
4343
topDown bool
44+
format string
4445
}
4546

4647
func newRenderCmd() *cobra.Command {
@@ -83,6 +84,7 @@ func newRenderCmd() *cobra.Command {
8384
cmd.Flags().BoolVar(&opts.nebraska, "nebraska", false, "show Nebraska guy maintainer ranking")
8485
cmd.Flags().BoolVar(&opts.popups, "popups", opts.popups, "show hover popups with metadata")
8586
cmd.Flags().BoolVar(&opts.topDown, "top-down", false, "use top-down width flow (roots get equal width)")
87+
cmd.Flags().StringVar(&opts.format, "format", "svg", "output format: svg (default), json")
8688

8789
return cmd
8890
}
@@ -228,8 +230,16 @@ func renderTower(ctx context.Context, g *dag.DAG, opts *renderOpts) ([]byte, err
228230
layout = layouttransform.Randomize(layout, g, defaultSeed, nil)
229231
}
230232

231-
logger.Infof("Rendering tower SVG (%s style)", opts.style)
232-
return tower.RenderSVG(layout, buildRenderOpts(g, opts)...), nil
233+
switch opts.format {
234+
case "json":
235+
logger.Info("Rendering tower layout as JSON")
236+
return tower.RenderJSON(layout)
237+
case "svg", "":
238+
logger.Infof("Rendering tower SVG (%s style)", opts.style)
239+
return tower.RenderSVG(layout, buildRenderOpts(g, opts)...), nil
240+
default:
241+
return nil, fmt.Errorf("unknown format: %s (must be 'svg' or 'json')", opts.format)
242+
}
233243
}
234244

235245
func buildLayoutOpts(ctx context.Context, opts *renderOpts) ([]tower.Option, error) {

pkg/render/tower/block.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
package tower
22

33
type Block struct {
4-
NodeID string
5-
Left, Right float64
6-
Bottom, Top float64
4+
NodeID string `json:"id"`
5+
Left float64 `json:"x"`
6+
Right float64 `json:"-"`
7+
Bottom float64 `json:"y"`
8+
Top float64 `json:"-"`
79
}
810

9-
func (b Block) Width() float64 { return b.Right - b.Left }
10-
func (b Block) Height() float64 { return b.Top - b.Bottom }
11-
11+
func (b Block) Width() float64 { return b.Right - b.Left }
12+
func (b Block) Height() float64 { return b.Top - b.Bottom }
1213
func (b Block) CenterX() float64 { return (b.Left + b.Right) / 2 }
1314
func (b Block) CenterY() float64 { return (b.Bottom + b.Top) / 2 }
15+
16+
type jsonBlock struct {
17+
ID string `json:"id"`
18+
X float64 `json:"x"`
19+
Y float64 `json:"y"`
20+
Width float64 `json:"width"`
21+
Height float64 `json:"height"`
22+
}
23+
24+
func (b Block) MarshalJSON() ([]byte, error) {
25+
return jsonMarshal(jsonBlock{
26+
ID: b.NodeID,
27+
X: b.Left,
28+
Y: b.Bottom,
29+
Width: b.Width(),
30+
Height: b.Height(),
31+
})
32+
}

pkg/render/tower/json.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package tower
2+
3+
import "encoding/json"
4+
5+
func RenderJSON(layout Layout) ([]byte, error) {
6+
return json.MarshalIndent(layout, "", " ")
7+
}
8+
9+
func jsonMarshal(v any) ([]byte, error) {
10+
return json.Marshal(v)
11+
}

pkg/render/tower/layout.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ const (
1313
)
1414

1515
type Layout struct {
16-
FrameWidth, FrameHeight float64
17-
Blocks map[string]Block
18-
RowOrders map[int][]string
19-
MarginX, MarginY float64
16+
FrameWidth float64 `json:"width"`
17+
FrameHeight float64 `json:"height"`
18+
Blocks map[string]Block `json:"blocks"`
19+
RowOrders map[int][]string `json:"rows,omitempty"`
20+
MarginX float64 `json:"margin_x"`
21+
MarginY float64 `json:"margin_y"`
2022
}
2123

2224
type Option func(*config)

0 commit comments

Comments
 (0)