1
2
3 package d2plugin
4
5 import (
6 "context"
7 "encoding/json"
8 "fmt"
9
10 "oss.terrastruct.com/d2/d2graph"
11 "oss.terrastruct.com/d2/d2layouts/d2elklayout"
12 "oss.terrastruct.com/util-go/xmain"
13 )
14
15 var ELKPlugin = elkPlugin{}
16
17 func init() {
18 plugins = append(plugins, &ELKPlugin)
19 }
20
21 type elkPlugin struct {
22 opts *d2elklayout.ConfigurableOpts
23 }
24
25 func (p elkPlugin) Flags(context.Context) ([]PluginSpecificFlag, error) {
26 return []PluginSpecificFlag{
27 {
28 Name: "elk-algorithm",
29 Type: "string",
30 Default: d2elklayout.DefaultOpts.Algorithm,
31 Usage: "layout algorithm",
32 Tag: "elk.algorithm",
33 },
34 {
35 Name: "elk-nodeNodeBetweenLayers",
36 Type: "int64",
37 Default: int64(d2elklayout.DefaultOpts.NodeSpacing),
38 Usage: "the spacing to be preserved between any pair of nodes of two adjacent layers",
39 Tag: "spacing.nodeNodeBetweenLayers",
40 },
41 {
42 Name: "elk-padding",
43 Type: "string",
44 Default: d2elklayout.DefaultOpts.Padding,
45 Usage: "the padding to be left to a parent element’s border when placing child elements",
46 Tag: "elk.padding",
47 },
48 {
49 Name: "elk-edgeNodeBetweenLayers",
50 Type: "int64",
51 Default: int64(d2elklayout.DefaultOpts.EdgeNodeSpacing),
52 Usage: "the spacing to be preserved between nodes and edges that are routed next to the node’s layer",
53 Tag: "spacing.edgeNodeBetweenLayers",
54 },
55 {
56 Name: "elk-nodeSelfLoop",
57 Type: "int64",
58 Default: int64(d2elklayout.DefaultOpts.SelfLoopSpacing),
59 Usage: "spacing to be preserved between a node and its self loops",
60 Tag: "elk.spacing.nodeSelfLoop",
61 },
62 }, nil
63 }
64
65 func (p *elkPlugin) HydrateOpts(opts []byte) error {
66 if opts != nil {
67 var elkOpts d2elklayout.ConfigurableOpts
68 err := json.Unmarshal(opts, &elkOpts)
69 if err != nil {
70 return xmain.UsageErrorf("non-ELK layout options given for ELK")
71 }
72
73 p.opts = &elkOpts
74 }
75 return nil
76 }
77
78 func (p elkPlugin) Info(ctx context.Context) (*PluginInfo, error) {
79 opts := xmain.NewOpts(nil, nil)
80 flags, err := p.Flags(ctx)
81 if err != nil {
82 return nil, err
83 }
84 for _, f := range flags {
85 f.AddToOpts(opts)
86 }
87 return &PluginInfo{
88 Name: "elk",
89 Type: "bundled",
90 Features: []PluginFeature{
91 CONTAINER_DIMENSIONS,
92 DESCENDANT_EDGES,
93 },
94 ShortHelp: "Eclipse Layout Kernel (ELK) with the Layered algorithm.",
95 LongHelp: fmt.Sprintf(`ELK is a layout engine offered by Eclipse.
96 Originally written in Java, it has been ported to Javascript and cross-compiled into D2.
97 See https://d2lang.com/tour/elk for more.
98
99 Flags correspond to ones found at https://www.eclipse.org/elk/reference.html.
100
101 Flags:
102 %s
103 `, opts.Defaults()),
104 }, nil
105 }
106
107 func (p elkPlugin) Layout(ctx context.Context, g *d2graph.Graph) error {
108 return d2elklayout.Layout(ctx, g, p.opts)
109 }
110
111 func (p elkPlugin) PostProcess(ctx context.Context, in []byte) ([]byte, error) {
112 return in, nil
113 }
114
View as plain text