Parses the Graphviz DOT language in golang

Overview

Parses the Graphviz DOT language and creates an interface, in golang, with which to easily create new and manipulate existing graphs which can be written back to the DOT format.

This parser has been created using gocc.

Example (Parse and Edit)

graphAst, _ := gographviz.ParseString(`digraph G {}`)
graph := gographviz.NewGraph()
if err := gographviz.Analyse(graphAst, graph); err != nil {
    panic(err)
}
graph.AddNode("G", "a", nil)
graph.AddNode("G", "b", nil)
graph.AddEdge("a", "b", true, nil)
output := graph.String()

Documentation

Installation

go get github.com/awalterschulze/gographviz

Build and Tests

Build Status

Users

  • aptly - Debian repository management tool
  • gorgonia - A Library that helps facilitate machine learning in Go
  • imagemonkey - Let's create our own image dataset
  • depviz - GitHub dependency visualizer (auto-roadmap)
  • kustomize-graph - A tool to visualize Kustomize dependencies
  • inframap - Read your tfstate or HCL to generate a graph specific for each Terraform provider
  • Antrea Traceflow supports using Traceflow for network diagnosis for Antrea, a Kubernetes networking solution intended to be Kubernetes native

Mentions

Using Golang and GraphViz to Visualize Complex Grails Applications

Comments
  • Typesafe (kinda) Attributes now available

    Typesafe (kinda) Attributes now available

    So, the attributes is now a static set (found in common/attributes.go). The API still takes a map[string]string but all public methods (AddNode, AddAttr etc) will call FromStringMap(), which will create a Attrs from the string map, and then pass them into private methods (addNode, addAttr, etc)

    This way, the API stays the same, per #4 .

    Caveat: I have also silenced the panic(err) in almost all of them because the test cases themselves are wrong/have wrong attributes. I'll probably leave that to someone else to fix. (grep for the below:)

    if err != nil {
        // panic(err)  // TODO: Fix...
    }```
    
    opened by chewxy 19
  • Fix Go module name

    Fix Go module name

    From https://blog.golang.org/using-go-modules:

    Each different major version (v1, v2, and so on) of a Go module uses a different module path: starting at v2, the path must end in the major version. In the example, v3 of rsc.io/quote is no longer rsc.io/quote: instead, it is identified by the module path rsc.io/quote/v3. This convention is called semantic import versioning

    Currently running go mod download in a module using github.com/awalterschulze/gographviz in version v2.0.2 results in the following error:

    github.com/awalterschulze/[email protected]+incompatible: invalid version: +incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required

    opened by piepmatz 16
  • Attributes and Errors

    Attributes and Errors

    This pull request contains backwards incompatible changes:

    1. Some methods now return errors, instead of panicing.
    2. Attributes are checked to be valid attributes.
    opened by awalterschulze 10
  • [Question] Is there any way to get the Node in a Graph?

    [Question] Is there any way to get the Node in a Graph?

    I want to edit a node attributes inside a graph. Is there any way to get the node by name of node and edit it? Like in nodejs package JNXnetwork we can do that by

    G.node.get(0).foo = 'bar';
    

    Is there anyway in this package to do that?

    Thanks

    opened by knrt10 9
  • Default attributes are not inherited by nodes or edges in subgraphs

    Default attributes are not inherited by nodes or edges in subgraphs

    Given an input graph with default node/edge attributes and a subgraph, like this one:

    digraph g {
        node [shape=record];
        edge [style=dashed];
        subgraph cluster_key {
            graph [label=KEY];
            key_user [fontcolor=red];
            key_dep  [fontcolor=blue];
            key_user -> key_dep;
        }
        A [fontcolor=red];
        B [fontcolor=blue];
        A -> B;
    }
    

    In the rendering from dot, the default attributes are inherited by the objects in the subgraph:

    image

    but gographviz only applies the attributes to the top-level objects, not the ones in the subgraph:

    image

    opened by nkitchen 9
  • how to set `node[shape=box style=rounded labelloc=b]` global attribute?

    how to set `node[shape=box style=rounded labelloc=b]` global attribute?

    image

    it's not allowed use like this:

    graph.AddAttr(workflowName, "node", "shape=rect style=rounded, labelloc=b")
    

    but if set attribute one by one, it will not take affect.

    graph.AddAttr(workflowName, "shape", "rect")
    graph.AddAttr(workflowName, "style", "rounded")
    graph.AddAttr(workflowName, "labelloc", "b")
    

    image

    opened by tsjsdbd 8
  • Nesting cluster subgraphs doesn't work

    Nesting cluster subgraphs doesn't work

    What I am trying to achive:

    pic

    Code I used:

    g := gographviz.NewGraph()
    g.SetName("G")
    g.SetDir(true)
    
    g.AddNode("G", "Ga", nil)
    g.AddNode("G", "Gb", nil)
    g.AddEdge("Ga", "Gb", true, nil)
    
    g.AddSubGraph("G", "clusterone", map[string]string{
        "style": "filled", 
        "fillcolor": "red",
    })
    g.AddNode("clusterone", "sA", nil)
    g.AddNode("clusterone", "sB", nil)
    g.AddEdge("sA", "sB", true, nil)
    
    g.AddSubGraph("clusterone", "clustertwo", map[string]string{
        "style": "filled", 
        "fillcolor": "blue",
    })
    g.AddNode("clustertwo", "ssA", nil)
    g.AddNode("clustertwo", "ssB", nil)
    g.AddEdge("ssA", "ssB", true, nil)
    
    fmt.Println(g.String())
    

    However this is what the result looked like:

    pic2

    Am I doing something wrong?

    opened by ofabry 8
  • Quote node IDs and attributes

    Quote node IDs and attributes

    Hi there, thanks for this package.

    My node IDs and attribute values disagree strongly with the DOT schema, and I've found that I have to quote them in order for tools like Gephi to parse them as they all are of type "ID".

    Could gographviz detect the need to quote/escape anything that it needs to write out as type ID and do so automatically so I don't have to add the quotes myself? Here's an example that produces an unreadable file:

    graph := gographviz.NewGraph()
    graph.SetName("G")
    graph.AddNode("G", "331fb1985e8884cfaaae65be7f8cfe5b", gographviz.Attrs{"label": "1:6:1w/w/PYqH7d1+6Fg"})
    graph.AddEdge("331fb1985e8884cfaaae65be7f8cfe5b", "ec2f3d34a4f4c4f82dd1d0b2f1a581e", gographviz.Attrs{"label": "FOO_BAR"})
    os.Stdout.Write(gographviz.WriteAst().String())
    

    Thanks!

    opened by joshk0 8
  • How to get subtree based on parent node?

    How to get subtree based on parent node?

    Hi,

    first of all, many thanks for the great library - it's really a pleasure to use!

    I am currently evaluating gographviz for another project (https://github.com/bbernhard/imagemonkey-core) and would be glad if I could use it there.

    One thing I am currently struggling with is, the possibility to extract a subtree based on a given label. If I understood the documentation correctly, then that's what SortedChildren is meant to be for. However, for some obscure reason it doesn't seem to work - it looks like I have messed something up here.

    Here is a small code snippet which illustrates my problem. truck, bike, motorbike and car are all children of vehicle. When asking gographviz for the label vehicle I would like to get a list of all its children. I tried to accomplish that with graph.Relations.SortedChildren("vehicle") but that returns an empty list.

    I am pretty sure that I have missed something here and would be glad, if you could point me in the right direction.

    Thanks a lot, Bernhard

    package main
    
    import (
    	"bytes"
    	"os"
    	"fmt"
    	"github.com/awalterschulze/gographviz"
    )
    
    func main() {
    	graphAst, _ := gographviz.ParseString(`
    		digraph G { 
    			{ 
    				car [label="car" id="94bbd2ff-8a8e-4d1c-9ac5-f9506aa20e43"] 
    				vehicle [color=green style=filled label="vehicle"] 
    				truck [label="truck"] 
    			} 
    			
    		   vehicle -> truck
    		    vehicle -> car
    		    vehicle -> motorbike
    		    vehicle -> bike
    		}
    	`)
    	graph := gographviz.NewGraph()
    	graph.SetDir(true)
    	if err := gographviz.Analyse(graphAst, graph); err != nil {
        	panic(err)
    	}
    
    	childrens := graph.Relations.SortedChildren("vehicle")
    	for _, child := range childrens {
    		fmt.Printf("%s\n", child)
    	}
    }
    
    opened by bbernhard 7
  • Make cluster subgraphs as nodes for edges

    Make cluster subgraphs as nodes for edges

    There's an issue where making edges between cluster subgraphs (which are useful with fdp) would double subgraphs in output string.

    Consider this code:

    g := gographviz.NewEscape()
    g.SetName("G")
    g.SetDir(false)
    g.AddSubGraph("G", "cluster0", map[string]string{"label": "root"})
    g.AddSubGraph("cluster0", "cluster_1", map[string]string{"label": "child 1"})
    g.AddSubGraph("cluster0", "cluster_2", map[string]string{"label": "child 2"})
    nodeStyle := map[string]string{"style": "rounded"}
    g.AddNode("cluster_1", "1", nodeStyle)
    g.AddNode("cluster_1", "2", nodeStyle)
    g.AddNode("cluster_2", "3", nodeStyle)
    g.AddNode("cluster_2", "4", nodeStyle)
    g.AddNode("G", "Code deployment", map[string]string{"style": "dotted"})
    g.AddPortEdge("cluster_2", "", "cluster_1", "", false, nil)
    s := g.String()
    fmt.Println(s)
    

    It currently renders such code, which is incorrect and would not render:

    graph G { subgraph cluster_2 { label="child 2"; 3 [ style=rounded ]; 4 [ style=rounded ];

    } --subgraph cluster_1 { label="child 1"; 1 [ style=rounded ]; 2 [ style=rounded ];

    }; subgraph cluster0 { label=root; subgraph cluster_1 { label="child 1"; 1 [ style=rounded ]; 2 [ style=rounded ];

    } ; subgraph cluster_2 { label="child 2"; 3 [ style=rounded ]; 4 [ style=rounded ];

    } ;

    } ; "Code deployment" [ style=dotted ];

    }

    After the patch applied it would make such code (subgraphs starting with cluster would be rendered as nodes for edges): graph G { cluster_2--cluster_1; subgraph cluster0 { label=root; subgraph cluster_1 { label="child 1"; 1 [ style=rounded ]; 2 [ style=rounded ];

    } ; subgraph cluster_2 { label="child 2"; 3 [ style=rounded ]; 4 [ style=rounded ];

    } ;

    } ; "Code deployment" [ style=dotted ];

    }

    opened by Didainius 7
  • Replace travis job with github action.

    Replace travis job with github action.

    Created github action that performs the same tasks as travis job.

    Note that the badge in Readme.md is already pointing to https://github.com/awalterschulze/gographviz to work correctly when merged.

    opened by jmrtt 6
  • Extend does not escape attributes

    Extend does not escape attributes

    I am using the following to update node labels in an Escape

    graph.Nodes.Lookup[id].Attrs.Extend(attrs)
    

    but the new label is not automatically escaped. Maybe there is a better way to update node attributes that I'm missing.

    On the other hand, if this is a bug, I'd happy to try to fix it. At a first glance at the implementation, it does not look like the escaping logic is executed for any Attrs method.

    Thanks!

    opened by rupanshusoi 3
  • How to define default attributes for node, edge, or graph

    How to define default attributes for node, edge, or graph

    Hi, all.

    I am trying to use the node, edge, and graph statement from the Lexical and Semantic Notes. However, since this library always sorts and prints nodes, the order is changed. How can I always define it first?

    Output:

    digraph G {
    	rank=LR;
    	Hello->World[ headlabel="head", taillabel="tail" ];
    	Hello->World:f0;
    	Hello->World:f1;
    	Hello->World:f2;
    	Hello [ label="Hi\nStart", shape=Mrecord ];
    	World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
    	node [ shape=Mrecord ];
    }
    

    You can see that the node line is defined last.

    Expected:

    digraph G {
    	node [ shape=Mrecord ];  <-------------- This line
    	rank=LR;
    	Hello->World[ headlabel="head", taillabel="tail" ];
    	Hello->World:f0;
    	Hello->World:f1;
    	Hello->World:f2;
    	Hello [ label="Hi\nStart", shape=Mrecord ];
    	World [ label="<f0>one|<f1>two|<f2>three", shape=Mrecord ];
    }
    

    Only when defined like this, the output I want is completed.

    Looking at the source code, there seem to be no solutions. For now, is the only way to add properties to each node?

    ...
    go 1.14
    
    require github.com/awalterschulze/gographviz v2.0.1+incompatible
    ...
    
    opened by DreamerKMP 3
  • quoted string and its quirks

    quoted string and its quirks

    From the spec http://www.graphviz.org/content/dot-language

    As another aid for readability, dot allows double-quoted strings to span
    multiple physical lines using the standard C convention of a backslash
    immediately preceding a newline character.
    
    In addition, double-quoted strings can be concatenated using a '+' operator.
    
    opened by awalterschulze 3
  • isNumber accepts non-numbers

    isNumber accepts non-numbers

    isNumber in escape.go is supposed to return true if it is passed a string that represents a number. However, it accepts "127.0.0.1" as a number but dot does not accept that. More generally it allows an arbitrary number of "."s in a number. This causes strings to not be escaped when they should be.

    opened by drt24 2
Releases(v2.0.3)
  • v2.0.3(Nov 3, 2020)

  • v2.0.2(Oct 20, 2020)

  • v2.0.1(Apr 5, 2020)

  • v2.0(Apr 10, 2017)

    version 2.0 includes some backwards incompatible changes:

    • panics have been removed and replaced with the returning of errors.
    • attribute name validation has been added as has been requested multiple times.
    • golint and errcheck are now applied to the build.

    These backwards incompatible changes were not made lightly and only because it increases the maturity of the package.

    Source code(tar.gz)
    Source code(zip)
  • v1.1(Mar 23, 2017)

  • v1.0(Oct 1, 2016)

    Generated using gocc 1.0 Hand written scanner Open Issues:

    • https://github.com/awalterschulze/gographviz/issues/13
    • https://github.com/awalterschulze/gographviz/issues/12
    • https://github.com/awalterschulze/gographviz/issues/11
    • https://github.com/awalterschulze/gographviz/issues/10
    • https://github.com/awalterschulze/gographviz/issues/9
    • https://github.com/awalterschulze/gographviz/issues/4
    Source code(tar.gz)
    Source code(zip)
Owner
Walter Schulze
Pair programmer with an interest in language design.
Walter Schulze
Decode / encode XML to/from map[string]interface{} (or JSON); extract values with dot-notation paths and wildcards. Replaces x2j and j2x packages.

mxj - to/from maps, XML and JSON Decode/encode XML to/from map[string]interface{} (or JSON) values, and extract/modify values from maps by key or key-

Charles Banning 537 Dec 29, 2022
An anthology of a variety of tools for the Persian language in Golang

Persian tools An anthology of a variety of tools for the Persian language in Golang Todos Bill calculator Digits Validate Bank card number. Find Bank'

Persian Tools 29 Nov 22, 2022
Frongo is a Golang package to create HTML/CSS components using only the Go language.

Frongo Frongo is a Go tool to make HTML/CSS document out of Golang code. It was designed with readability and usability in mind, so HTML objects are c

Rewan_ 21 Jul 29, 2021
Go library for the TOML language

go-toml Go library for the TOML format. This library supports TOML version v1.0.0-rc.3 Features Go-toml provides the following features for using data

Thomas Pelletier 1.4k Dec 27, 2022
Guess the natural language of a text in Go

guesslanguage This is a Go version of python guess-language. guesslanguage provides a simple way to detect the natural language of unicode string and

Nikita Vershinin 56 Dec 26, 2022
String i18n utilities for the Go Programming Language

About polyglot polyglot is a String translation package and tool for Go. Setup Make sure you have a working Go installation. See Getting Started Now r

Alexander Neumann 40 Dec 22, 2022
Unified text diffing in Go (copy of the internal diffing packages the officlal Go language server uses)

gotextdiff - unified text diffing in Go This is a copy of the Go text diffing packages that the official Go language server gopls uses internally to g

Hexops 96 Dec 26, 2022
Simple HCL (HashiCorp Configuration Language) parser for your vars.

HCL to Markdown About To write a good documentation for terraform module, quite often we just need to print all our input variables as a fancy table.

Dmytro Shamenko 15 Dec 14, 2021
The Freetype font rasterizer in the Go programming language.

The Freetype font rasterizer in the Go programming language. To download and install from source: $ go get github.com/golang/freetype It is an incom

Go 699 Dec 25, 2022
👄 The most accurate natural language detection library in the Go ecosystem, suitable for long and short text alike

?? The most accurate natural language detection library in the Go ecosystem, suitable for long and short text alike

Peter M. Stahl 822 Dec 25, 2022
A simple programming language with emojis only

MOGEE mogee (pronounced ēˈmōjē) is an extremely simple interpreted programming language that consists solely of emojis. Similar to Brainfuck, mogee is

Barış İnandıoğlu 1 Nov 15, 2021
Toy scripting language with a syntax similar to Rust.

Dust - toy scripting language Toy scripting language with a syntax similar to Rust. ?? Syntax similar to Rust ?? Loose JSON parsing ?? Calling host fu

shellyln 2 Sep 28, 2022
Build "Dictionary of the Old Norwegian Language" into easier-to-use data formats

Old Norwegian Dictionary Builder Build "Dictionary of the Old Norwegian Language" into easier-to-use data formats. Available formats: JSON DSL XML Usa

Sampo Silvennoinen 0 Oct 11, 2022
Interpreted Programming Language built in Go. Lexer, Parser, AST, VM.

Gago | Programming Language Built in Go if you are looking for the docs, go here Gago is a interpreted programming language. It is fully written in Go

Glaukio 4 May 6, 2022
[Crawler/Scraper for Golang]🕷A lightweight distributed friendly Golang crawler framework.一个轻量的分布式友好的 Golang 爬虫框架。

Goribot 一个分布式友好的轻量的 Golang 爬虫框架。 完整文档 | Document !! Warning !! Goribot 已经被迁移到 Gospider|github.com/zhshch2002/gospider。修复了一些调度问题并分离了网络请求部分到另一个仓库。此仓库会继续

null 210 Oct 29, 2022
golang 在线预览word,excel,pdf,MarkDown(Online Preview Word,Excel,PPT,PDF,Image by Golang)

Go View File 在线体验地址 http://39.97.98.75:8082/view/upload (不会经常更新,保留最基本的预览功能。服务器配置较低,如果出现链接超时请等待几秒刷新重试,或者换Chrome) 目前已经完成 docker部署 (不用为运行环境烦恼) Wor

CZC 78 Dec 26, 2022
bluemonday: a fast golang HTML sanitizer (inspired by the OWASP Java HTML Sanitizer) to scrub user generated content of XSS

bluemonday bluemonday is a HTML sanitizer implemented in Go. It is fast and highly configurable. bluemonday takes untrusted user generated content as

Microcosm 2.6k Jan 4, 2023
Elegant Scraper and Crawler Framework for Golang

Colly Lightning Fast and Elegant Scraping Framework for Gophers Colly provides a clean interface to write any kind of crawler/scraper/spider. With Col

Colly 18.5k Dec 30, 2022
A golang package to work with Decentralized Identifiers (DIDs)

did did is a Go package that provides tools to work with Decentralized Identifiers (DIDs). Install go get github.com/ockam-network/did Example packag

Ockam 69 Nov 25, 2022