elk-go

August 10, 2026 ยท View on GitHub

elk-go is a native Go port of the Eclipse Layout Kernel behavior used by D2. Its compatibility target is D2's ELK integration running against the exact official ELK.js 0.12.0 release; it is not a general drop-in replacement for every ELK option combination.

The port is based on:

ELK.js compiles ELK's Java algorithms to JavaScript with GWT. This repository translates the provider registry used by D2 to Go while preserving the ordering, option-default, and floating-point behavior observable on that path. It registers D2's 11 selectable 0.12 algorithms: Fixed, Box, Random, Layered, Stress, MR Tree, Radial, Force, SPOrE Overlap, SPOrE Compaction, and Rectangle Packing. ELK.js removed DisCo from its bundled algorithm surface after 0.8.2, so it is not registered by this version.

D2's default and documented engine is Layered. Its complete D2 option profile, including compounds, ports, self loops, labels, model order, and orthogonal routing, is the primary end-to-end compatibility contract. Exact, deterministic oracle fixtures cover all eleven registered providers. D2 also smoke-tests its literal provider defaults; unseeded Random and the two SPOrE providers use finite-output checks because those default calls are nondeterministic.

The contract tests vary algorithm selection, all four directions, nodeNodeBetweenLayers, padding, edgeNodeBetweenLayers, and nodeSelfLoop, and include compound graphs, ports, inline edge labels, and self loops. Each scalar option pair is also required to change official-oracle geometry, which guards against a silently ignored option.

The option metadata exposed by the Go registry matches the official 0.12 bundle so D2 can resolve its option IDs consistently. Metadata presence is not an execution guarantee for expert ELK configurations outside D2's profile. Known out-of-scope Layered values include SCC_CONNECTIVITY and BFS_NODE_ORDER cycle breaking; LONGEST_PATH_SOURCE, BF_MODEL_ORDER, and DF_MODEL_ORDER layering; and MEDIAN_LAYER_SWEEP crossing minimization.

API

The public graph types mirror ELK JSON. Layout can be requested either with a typed graph or with JSON:

graph := &elk.Graph{
    ID: elk.StringID("root"),
    LayoutOptions: elk.LayoutOptions{
        "elk.algorithm": "layered",
        "elk.direction": "DOWN",
    },
    Children: []*elk.Node{
        {ID: elk.StringID("a"), Width: elk.Float64(80), Height: elk.Float64(40)},
        {ID: elk.StringID("b"), Width: elk.Float64(80), Height: elk.Float64(40)},
    },
    Edges: []*elk.Edge{
        {ID: elk.StringID("e"), Sources: []elk.ID{elk.StringID("a")}, Targets: []elk.ID{elk.StringID("b")}},
    },
}

if err := elk.Layout(graph); err != nil {
    // handle the layout error
}

Compatibility testing

Normal tests are pure Go:

go test ./...
go test -race ./...
go vet ./...

Development differentials compare ordered ELK JSON output with the official ELK.js 0.12.0 oracle. IDs, element order, topology, edge-section structure, field presence, and coordinates are exact for the provider matrix, curated D2 fixtures, D2-profile random cases, codec behavior used by D2, and the complete captured D2 corpus. Broader provider and expert-option probes are development diagnostics, not part of the supported D2 contract. See internal/oracle for the opt-in oracle setup.

License

This program is available under the Eclipse Public License 2.0. Two attributed GWT runtime adaptations retain the Apache License 2.0; the V8/fdlibm math adaptation retains its BSD-3-Clause and SunPro terms. See LICENSE, LICENSE.apache-2.0, LICENSE.v8-bsd, NOTICE.md, the preserved NOTICE.eclipse-elk.md, and PROVENANCE.md.