├── .gitignore ├── LICENSE ├── README-CN.md ├── README.md ├── gmchart └── main.go ├── go.mod ├── go.sum ├── godist └── static.go ├── gosrc ├── graphutil.go ├── graphutil_test.go ├── treeutil.go ├── treeutil_test.go ├── util.go └── util_test.go ├── package-lock.json ├── package.json ├── plugin └── pack-all-in-go-plugin.js ├── show.gif ├── src ├── css │ └── styles.css ├── index.js ├── js │ ├── graph.js │ └── tree.js ├── static │ ├── an-tree.json │ ├── graph.json │ └── tree.json └── temp-index.html └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.o 7 | *.dylib 8 | 9 | # Test binary, built with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | .idea/ 15 | 16 | # Dependency directories (remove the comment below to include it) 17 | vendor/ 18 | node_modules/ 19 | 20 | dist/* 21 | gmchart/* 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 PaulXu-cn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | [English](./README.md) | 中文 2 | 3 | [![go-recipes](https://raw.githubusercontent.com/nikolaydubina/go-recipes/main/badge.svg?raw=true)](https://github.com/nikolaydubina/go-recipes) 4 | 5 | # go-mod-graph-chart 6 | 一个能将 `go mod graph` 输出内容可视化的无依赖小工具 7 | 8 | ## 安装 9 | 10 | ```shell 11 | $ go get -u github.com/PaulXu-cn/go-mod-graph-chart/gmchart 12 | ``` 13 | 14 | Go v1.16 或者更高版本使用如下命令安装 15 | 16 | ```shell 17 | $ go install github.com/PaulXu-cn/go-mod-graph-chart/gmchart@latest 18 | ``` 19 | 20 | ## 使用 21 | 22 | ```shell 23 | $ cd goProject 24 | $ go mod graph | gmchart 25 | ``` 26 | 27 | 执行 `go mod graph` 命令,输出的文本作为该程序的输入,该程序会起一个http服务,并打开 `url` 展示图表 28 | 29 | ![show](./show.gif) 30 | ## 改动重建 31 | 32 | 如果你改动了 `JS` 代码,记得重新构建前端项目,然后重新构建 `go` 项目 33 | ```shell 34 | $ npm run build 35 | $ go install ./gmchart 36 | ``` 37 | 38 | ## 开源协议 39 | 40 | MIT 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | English | [中文](./README-CN.md) 2 | 3 | [![go-recipes](https://raw.githubusercontent.com/nikolaydubina/go-recipes/main/badge.svg?raw=true)](https://github.com/nikolaydubina/go-recipes) 4 | 5 | # go-mod-graph-chart 6 | A tool build chart by `go mod graph` output with zero dependencies 7 | 8 | ## Install 9 | 10 | ```shell 11 | $ go get -u github.com/PaulXu-cn/go-mod-graph-chart/gmchart 12 | ``` 13 | 14 | Go v1.16 or higher 15 | 16 | ```shell 17 | $ go install github.com/PaulXu-cn/go-mod-graph-chart/gmchart@latest 18 | ``` 19 | 20 | ## Usage 21 | 22 | ```shell 23 | $ cd goProject 24 | $ go mod graph | gmchart 25 | ``` 26 | 27 | The program will start a http server and open the url in default browser. 28 | 29 | ![show](./show.gif) 30 | 31 | ## Change & Rebuild 32 | 33 | If you has changed js code, the front-end project needs to be rebuilt,and then `go install` 34 | ```shell 35 | $ npm run build 36 | $ go install ./gmchart 37 | ``` 38 | 39 | ## License 40 | 41 | MIT 42 | -------------------------------------------------------------------------------- /gmchart/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "net" 8 | "net/http" 9 | "os" 10 | "strconv" 11 | "strings" 12 | "time" 13 | 14 | dist "github.com/PaulXu-cn/go-mod-graph-chart/godist" 15 | src "github.com/PaulXu-cn/go-mod-graph-chart/gosrc" 16 | ) 17 | 18 | var ( 19 | debug int = 0 20 | keep int = 0 21 | port int = 0 22 | mode string = "tree" 23 | ) 24 | 25 | func init() { 26 | flag.IntVar(&debug, "debug", 0, "whether debug model") 27 | flag.IntVar(&keep, "keep", 0, "set no zero http server never exit") 28 | flag.IntVar(&port, "port", 0, "set http server port or random port number") 29 | flag.StringVar(&mode, "mode", "tree", "work mode, [tree/graph]") 30 | } 31 | 32 | func IndexHandler(w http.ResponseWriter, r *http.Request) { 33 | var header = w.Header() 34 | header.Add("Content-type", "text/html; charset=utf-8") 35 | var indexStr = dist.GetFile("index.html") 36 | w.Write([]byte(indexStr)) 37 | w.WriteHeader(http.StatusOK) 38 | } 39 | 40 | func MainJsHandler(w http.ResponseWriter, r *http.Request) { 41 | var header = w.Header() 42 | header.Add("Content-type", "text/javascript; charset=utf-8") 43 | var indexStr = dist.GetFile("main.js") 44 | w.Write([]byte(indexStr)) 45 | w.WriteHeader(http.StatusOK) 46 | } 47 | 48 | func PingHandler(w http.ResponseWriter, r *http.Request) { 49 | var header = w.Header() 50 | header.Add("content-type", "text/json; charset=utf-8") 51 | var jsonStr = "{\"message\": \"pong\"}" 52 | w.Write([]byte(jsonStr)) 53 | w.WriteHeader(http.StatusOK) 54 | } 55 | 56 | type GraphData struct { 57 | Nodes []src.Node `json:"nodes"` 58 | Links []src.Link `json:"links"` 59 | Num uint32 `json:"num"` 60 | } 61 | 62 | type GraphJson struct { 63 | Message string `json:"message"` 64 | Data GraphData `json:"data"` 65 | } 66 | 67 | type TreeData struct { 68 | Tree src.Tree `json:"tree"` 69 | Depth uint32 `json:"depth"` 70 | Width uint32 `json:"width"` 71 | } 72 | 73 | type TreeJson struct { 74 | Message string `json:"message"` 75 | Data TreeData `json:"data"` 76 | } 77 | 78 | type AnTreeData struct { 79 | Tree map[string]*src.Tree `json:"tree"` 80 | } 81 | 82 | type AnTreeJson struct { 83 | Message string `json:"message"` 84 | Data AnTreeData `json:"data"` 85 | } 86 | 87 | func main() { 88 | flag.Parse() 89 | fmt.Println("go mod graph version v0.5.3") 90 | var goModGraph string = src.GetGoModGraph() 91 | 92 | // nodes and links 93 | nodes, links := src.GraphToNodeLinks(goModGraph) 94 | nodeArr := map[uint32]src.Node{} 95 | for _, item := range nodes { 96 | nodeArr[item.Id] = item 97 | } 98 | nodeSortArr := []src.Node{} 99 | for key := 0; key < len(nodes); key++ { 100 | nodeSortArr = append(nodeSortArr, nodeArr[uint32(key)]) 101 | } 102 | 103 | // tree 104 | tree, depth, width, anotherTree := src.BuildTree(goModGraph) 105 | 106 | if 0 < debug { 107 | // 如果是 debug 模式 108 | re, _ := json.Marshal(&nodeSortArr) 109 | fmt.Printf("nodes : %s\n\n", string(re)) 110 | re, _ = json.Marshal(&links) 111 | fmt.Printf("links : %s\n\n", string(re)) 112 | re, _ = json.Marshal(&tree) 113 | fmt.Printf("tree : %s\n", string(re)) 114 | return 115 | } 116 | 117 | mux := http.NewServeMux() 118 | mux.HandleFunc("/", IndexHandler) 119 | mux.HandleFunc("/main.js", MainJsHandler) 120 | mux.HandleFunc("/ping", PingHandler) 121 | 122 | mux.HandleFunc("/graph.json", func(w http.ResponseWriter, r *http.Request) { 123 | var header = w.Header() 124 | header.Add("Content-type", "text/javascript; charset=utf-8") 125 | w.WriteHeader(http.StatusOK) 126 | var graph = GraphJson{ 127 | Message: "success", 128 | Data: GraphData{ 129 | Nodes: nodeSortArr, 130 | Links: links, 131 | Num: uint32(len(nodeSortArr)), 132 | }, 133 | } 134 | var graphStr, _ = json.Marshal(graph) 135 | w.Write(graphStr) 136 | }) 137 | 138 | mux.HandleFunc("/tree.json", func(w http.ResponseWriter, r *http.Request) { 139 | var header = w.Header() 140 | header.Add("Content-type", "text/javascript; charset=utf-8") 141 | w.WriteHeader(http.StatusOK) 142 | var tree = TreeJson{ 143 | Message: "success", 144 | Data: TreeData{ 145 | Tree: *tree, 146 | Depth: depth, 147 | Width: width, 148 | }, 149 | } 150 | var treeStr, _ = json.Marshal(tree) 151 | w.Write(treeStr) 152 | }) 153 | 154 | var host = "0.0.0.0" 155 | // 监听并在 0.0.0.0:xx 上启动服务 156 | li, err := net.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(port))) 157 | if nil != err { 158 | fmt.Printf("gmchart server listen err(%v)\n", err) 159 | } 160 | 161 | mux.HandleFunc("/an-tree.json", func (w http.ResponseWriter, r *http.Request) { 162 | var header = w.Header() 163 | header.Add("Content-type", "text/javascript; charset=utf-8") 164 | w.WriteHeader(http.StatusOK) 165 | var tree = AnTreeJson{ 166 | Message: "success", 167 | Data: AnTreeData{ 168 | Tree: anotherTree, 169 | }, 170 | } 171 | var treeStr, _ = json.Marshal(tree) 172 | w.Write(treeStr) 173 | }) 174 | 175 | server := &http.Server{ 176 | Handler: mux, 177 | } 178 | addr := li.Addr().String() 179 | var addrs = strings.Split(addr, ":") 180 | var printAddr = "http://127.0.0.1:" + addrs[len(addrs)-1] // 这里127.0.0.1 写死,兼容win 181 | if strings.ToLower(mode) == "graph" { 182 | printAddr += "/#graph" 183 | } 184 | 185 | go func() error { 186 | // open it by default browser 187 | return src.OpenBrowser(printAddr) 188 | }() 189 | 190 | if 1 > keep { 191 | go func() error { 192 | fmt.Printf("the go mod graph will top in 60s\nvisit it by %s\n", printAddr) 193 | time.Sleep(60 * time.Second) 194 | os.Exit(0) 195 | return nil 196 | }() 197 | } 198 | 199 | err = server.Serve(li) 200 | if err != nil { 201 | fmt.Printf("gmchart server start err(%v)\n", err) 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PaulXu-cn/go-mod-graph-chart 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulXu-cn/go-mod-graph-chart/21b9575a3e4d19534f72faaf9b611c6a66b03b1f/go.sum -------------------------------------------------------------------------------- /gosrc/graphutil.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | type Node struct { 13 | Id uint32 `json:"id"` 14 | Name string `json:"name"` 15 | Value uint32 `json:"value"` 16 | } 17 | 18 | type Link struct { 19 | Source uint32 `json:"source"` 20 | Target uint32 `json:"target"` 21 | Weight uint32 `json:"weight"` 22 | Width uint32 `json:"width"` 23 | } 24 | 25 | func GraphToNodeLinks(graph string) (nodes map[string]Node, links []Link) { 26 | nodes = map[string]Node{} 27 | links = []Link{} 28 | var key uint32 = 0 29 | for _, line := range strings.Split(graph, "\n") { 30 | if 1 > len(line) { 31 | continue 32 | } 33 | splitStr := strings.Split(line, " ") 34 | if 2 > len(splitStr) { 35 | panic(fmt.Sprintf("go mod graph output format error——%s", line)) 36 | } 37 | var nKey uint32 = 0 38 | var nKey1 uint32 = 0 39 | node, ok := nodes[splitStr[0]] 40 | if ok { 41 | // 权重自增 42 | node.Value++ 43 | nodes[splitStr[0]] = node 44 | nKey = node.Id 45 | } else { 46 | // 新增node 47 | var newNode = Node{ 48 | Id: key, 49 | Name: splitStr[0], 50 | Value: 1, 51 | } 52 | nodes[splitStr[0]] = newNode 53 | nKey = key 54 | key++ 55 | } 56 | 57 | node1, ok1 := nodes[splitStr[1]] 58 | if ok1 { 59 | node1.Value++ 60 | nodes[splitStr[0]] = node 61 | nKey1 = node1.Id 62 | } else { 63 | // 新增node 64 | var newNode = Node{ 65 | Id: key, 66 | Name: splitStr[1], 67 | Value: 1, 68 | } 69 | nodes[splitStr[1]] = newNode 70 | nKey1 = key 71 | key++ 72 | } 73 | 74 | newLink := Link{ 75 | Source: nKey, 76 | Target: nKey1, 77 | Weight: 1, 78 | Width: 1, 79 | } 80 | links = append(links, newLink) 81 | } 82 | return 83 | } 84 | 85 | func GetGoModGraph() string { 86 | var goModGraph string = "" 87 | 88 | go func() { 89 | var scanner = bufio.NewScanner(os.Stdin) 90 | for scanner.Scan() { 91 | goModGraph += scanner.Text() + "\n" 92 | } 93 | }() 94 | 95 | time.Sleep(2000 * time.Millisecond) 96 | if 1 > len(goModGraph) { 97 | fmt.Printf("no output pass in by pipe!\n") 98 | cmd := exec.Command("go mod graph") 99 | if out, err := cmd.CombinedOutput(); nil != err { 100 | panic(fmt.Sprintf("go mod graph cmd run failed: %+v", err)) 101 | } else { 102 | return string(out) 103 | } 104 | } 105 | return goModGraph 106 | } 107 | -------------------------------------------------------------------------------- /gosrc/graphutil_test.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | import "testing" 4 | 5 | func TestGraphToNodeLinks(t *testing.T) { 6 | var urlTests = []struct { 7 | expected bool // expected result 8 | in string // input 9 | }{ 10 | {true, `go-mod-graph-charting github.com/gin-gonic/gin@v1.6.3 11 | go-mod-graph-charting github.com/go-playground/validator/v10@v10.4.1 12 | go-mod-graph-charting github.com/golang/protobuf@v1.4.3 13 | go-mod-graph-charting github.com/json-iterator/go@v1.1.10 14 | go-mod-graph-charting github.com/leodido/go-urn@v1.2.1 15 | go-mod-graph-charting github.com/modern-go/concurrent@v0.0.0-20180306012644-bacd9c7ef1dd 16 | go-mod-graph-charting github.com/modern-go/reflect2@v1.0.1 17 | go-mod-graph-charting github.com/ugorji/go@v1.2.2 18 | go-mod-graph-charting golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad 19 | go-mod-graph-charting golang.org/x/sys@v0.0.0-20201223074533-0d417f636930 20 | go-mod-graph-charting google.golang.org/protobuf@v1.25.0 21 | go-mod-graph-charting gopkg.in/yaml.v2@v2.4.0 22 | github.com/leodido/go-urn@v1.2.1 github.com/stretchr/testify@v1.6.1 23 | github.com/gin-gonic/gin@v1.6.3 github.com/gin-contrib/sse@v0.1.0 24 | github.com/gin-gonic/gin@v1.6.3 github.com/go-playground/validator/v10@v10.2.0 25 | github.com/gin-gonic/gin@v1.6.3 github.com/golang/protobuf@v1.3.3 26 | github.com/gin-gonic/gin@v1.6.3 github.com/json-iterator/go@v1.1.9 27 | github.com/gin-gonic/gin@v1.6.3 github.com/mattn/go-isatty@v0.0.12 28 | github.com/gin-gonic/gin@v1.6.3 github.com/stretchr/testify@v1.4.0 29 | github.com/gin-gonic/gin@v1.6.3 github.com/ugorji/go/codec@v1.1.7 30 | github.com/gin-gonic/gin@v1.6.3 gopkg.in/yaml.v2@v2.2.8 31 | github.com/stretchr/testify@v1.4.0 github.com/davecgh/go-spew@v1.1.0 32 | github.com/stretchr/testify@v1.4.0 github.com/pmezard/go-difflib@v1.0.0 33 | github.com/stretchr/testify@v1.4.0 github.com/stretchr/objx@v0.1.0 34 | github.com/stretchr/testify@v1.4.0 gopkg.in/yaml.v2@v2.2.2 35 | github.com/ugorji/go/codec@v1.1.7 github.com/ugorji/go@v1.1.7 36 | github.com/stretchr/testify@v1.6.1 github.com/davecgh/go-spew@v1.1.0 37 | github.com/stretchr/testify@v1.6.1 github.com/pmezard/go-difflib@v1.0.0 38 | github.com/stretchr/testify@v1.6.1 github.com/stretchr/objx@v0.1.0 39 | github.com/stretchr/testify@v1.6.1 gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c 40 | golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 41 | golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037 42 | golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221 43 | google.golang.org/protobuf@v1.25.0 github.com/golang/protobuf@v1.4.1 44 | google.golang.org/protobuf@v1.25.0 github.com/google/go-cmp@v0.5.0 45 | google.golang.org/protobuf@v1.25.0 google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 46 | github.com/golang/protobuf@v1.4.1 github.com/google/go-cmp@v0.4.0 47 | github.com/golang/protobuf@v1.4.1 google.golang.org/protobuf@v1.22.0 48 | github.com/ugorji/go@v1.2.2 github.com/ugorji/go/codec@v1.2.2 49 | gopkg.in/yaml.v2@v2.2.8 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 50 | github.com/gin-contrib/sse@v0.1.0 github.com/stretchr/testify@v1.3.0 51 | github.com/json-iterator/go@v1.1.10 github.com/davecgh/go-spew@v1.1.1 52 | github.com/json-iterator/go@v1.1.10 github.com/google/gofuzz@v1.0.0 53 | github.com/json-iterator/go@v1.1.10 github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421 54 | github.com/json-iterator/go@v1.1.10 github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742 55 | github.com/json-iterator/go@v1.1.10 github.com/stretchr/testify@v1.3.0 56 | github.com/golang/protobuf@v1.4.3 github.com/google/go-cmp@v0.4.0 57 | github.com/golang/protobuf@v1.4.3 google.golang.org/protobuf@v1.23.0 58 | golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 59 | golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/text@v0.3.0 60 | gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 61 | github.com/json-iterator/go@v1.1.9 github.com/davecgh/go-spew@v1.1.1 62 | github.com/json-iterator/go@v1.1.9 github.com/google/gofuzz@v1.0.0 63 | github.com/json-iterator/go@v1.1.9 github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421 64 | github.com/json-iterator/go@v1.1.9 github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742 65 | github.com/json-iterator/go@v1.1.9 github.com/stretchr/testify@v1.3.0 66 | github.com/stretchr/testify@v1.3.0 github.com/davecgh/go-spew@v1.1.0 67 | github.com/stretchr/testify@v1.3.0 github.com/pmezard/go-difflib@v1.0.0 68 | github.com/stretchr/testify@v1.3.0 github.com/stretchr/objx@v0.1.0 69 | github.com/google/go-cmp@v0.5.0 golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 70 | github.com/google/go-cmp@v0.4.0 golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 71 | github.com/ugorji/go@v1.1.7 github.com/ugorji/go/codec@v1.1.7 72 | gopkg.in/yaml.v2@v2.4.0 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 73 | github.com/mattn/go-isatty@v0.0.12 golang.org/x/sys@v0.0.0-20200116001909-b77594299b42 74 | github.com/go-playground/validator/v10@v10.4.1 github.com/go-playground/assert/v2@v2.0.1 75 | github.com/go-playground/validator/v10@v10.4.1 github.com/go-playground/locales@v0.13.0 76 | github.com/go-playground/validator/v10@v10.4.1 github.com/go-playground/universal-translator@v0.17.0 77 | github.com/go-playground/validator/v10@v10.4.1 github.com/leodido/go-urn@v1.2.0 78 | github.com/go-playground/validator/v10@v10.4.1 golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 79 | github.com/leodido/go-urn@v1.2.0 github.com/stretchr/testify@v1.4.0 80 | golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 81 | golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 golang.org/x/sys@v0.0.0-20190412213103-97732733099d 82 | github.com/go-playground/validator/v10@v10.2.0 github.com/go-playground/assert/v2@v2.0.1 83 | github.com/go-playground/validator/v10@v10.2.0 github.com/go-playground/locales@v0.13.0 84 | github.com/go-playground/validator/v10@v10.2.0 github.com/go-playground/universal-translator@v0.17.0 85 | github.com/go-playground/validator/v10@v10.2.0 github.com/leodido/go-urn@v1.2.0 86 | github.com/go-playground/universal-translator@v0.17.0 github.com/go-playground/locales@v0.13.0 87 | google.golang.org/protobuf@v1.23.0 github.com/golang/protobuf@v1.4.0 88 | google.golang.org/protobuf@v1.23.0 github.com/google/go-cmp@v0.4.0 89 | github.com/ugorji/go/codec@v1.2.2 github.com/ugorji/go@v1.2.2 90 | github.com/golang/protobuf@v1.4.0 github.com/google/go-cmp@v0.4.0 91 | github.com/golang/protobuf@v1.4.0 google.golang.org/protobuf@v1.21.0 92 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 github.com/golang/protobuf@v1.4.1 93 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3 94 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 95 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 google.golang.org/grpc@v1.27.0 96 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc 97 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc 98 | google.golang.org/protobuf@v1.21.0 github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0 99 | google.golang.org/protobuf@v1.21.0 github.com/google/go-cmp@v0.4.0 100 | golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3 golang.org/x/tools@v0.0.0-20190311212946-11955173bddd 101 | golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221 golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037 102 | github.com/go-playground/locales@v0.13.0 golang.org/x/text@v0.3.2 103 | golang.org/x/text@v0.3.2 golang.org/x/tools@v0.0.0-20180917221912-90fa682c2a6e 104 | golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a 105 | github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0 github.com/google/go-cmp@v0.4.0 106 | github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0 google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967 107 | golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 golang.org/x/net@v0.0.0-20190311183353-d8887717615a 108 | golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 golang.org/x/sync@v0.0.0-20190423024810-112230192c58 109 | golang.org/x/tools@v0.0.0-20190311212946-11955173bddd golang.org/x/net@v0.0.0-20190311183353-d8887717615a 110 | google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc github.com/golang/protobuf@v1.4.0 111 | google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc github.com/google/go-cmp@v0.4.0 112 | gopkg.in/yaml.v2@v2.2.2 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 113 | google.golang.org/grpc@v1.27.0 github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 114 | google.golang.org/grpc@v1.27.0 github.com/envoyproxy/protoc-gen-validate@v0.1.0 115 | google.golang.org/grpc@v1.27.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b 116 | google.golang.org/grpc@v1.27.0 github.com/golang/mock@v1.1.1 117 | google.golang.org/grpc@v1.27.0 github.com/golang/protobuf@v1.3.2 118 | google.golang.org/grpc@v1.27.0 github.com/google/go-cmp@v0.2.0 119 | google.golang.org/grpc@v1.27.0 golang.org/x/net@v0.0.0-20190311183353-d8887717615a 120 | google.golang.org/grpc@v1.27.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be 121 | google.golang.org/grpc@v1.27.0 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a 122 | google.golang.org/grpc@v1.27.0 google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 123 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 github.com/golang/protobuf@v1.3.2 124 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 golang.org/x/exp@v0.0.0-20190121172915-509febef88a4 125 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961 126 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 golang.org/x/tools@v0.0.0-20190226205152-f727befe758c 127 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 google.golang.org/grpc@v1.19.0 128 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099 129 | google.golang.org/grpc@v1.19.0 cloud.google.com/go@v0.26.0 130 | google.golang.org/grpc@v1.19.0 github.com/BurntSushi/toml@v0.3.1 131 | google.golang.org/grpc@v1.19.0 github.com/client9/misspell@v0.3.4 132 | google.golang.org/grpc@v1.19.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b 133 | google.golang.org/grpc@v1.19.0 github.com/golang/mock@v1.1.1 134 | google.golang.org/grpc@v1.19.0 github.com/golang/protobuf@v1.2.0 135 | google.golang.org/grpc@v1.19.0 golang.org/x/lint@v0.0.0-20181026193005-c67002cb31c3 136 | google.golang.org/grpc@v1.19.0 golang.org/x/net@v0.0.0-20180826012351-8a410e7b638d 137 | google.golang.org/grpc@v1.19.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be 138 | google.golang.org/grpc@v1.19.0 golang.org/x/sync@v0.0.0-20180314180146-1d60e4601c6f 139 | google.golang.org/grpc@v1.19.0 golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522 140 | google.golang.org/grpc@v1.19.0 golang.org/x/text@v0.3.0 141 | google.golang.org/grpc@v1.19.0 golang.org/x/tools@v0.0.0-20190114222345-bf090417da8b 142 | google.golang.org/grpc@v1.19.0 google.golang.org/appengine@v1.1.0 143 | google.golang.org/grpc@v1.19.0 google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8 144 | google.golang.org/grpc@v1.19.0 honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099 145 | golang.org/x/net@v0.0.0-20190311183353-d8887717615a golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 146 | golang.org/x/net@v0.0.0-20190311183353-d8887717615a golang.org/x/text@v0.3.0 147 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/census-instrumentation/opencensus-proto@v0.2.1 148 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/envoyproxy/protoc-gen-validate@v0.1.0 149 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/golang/protobuf@v1.3.2 150 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4 151 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 152 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 google.golang.org/grpc@v1.23.0 153 | golang.org/x/tools@v0.0.0-20190226205152-f727befe758c golang.org/x/net@v0.0.0-20190213061140-3a22650c66bd 154 | golang.org/x/tools@v0.0.0-20190226205152-f727befe758c golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f 155 | golang.org/x/tools@v0.0.0-20190226205152-f727befe758c google.golang.org/appengine@v1.4.0 156 | google.golang.org/appengine@v1.4.0 github.com/golang/protobuf@v1.2.0 157 | google.golang.org/appengine@v1.4.0 golang.org/x/net@v0.0.0-20180724234803-3673e40ba225 158 | google.golang.org/appengine@v1.4.0 golang.org/x/text@v0.3.0 159 | google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967 github.com/golang/protobuf@v1.4.0-rc.2 160 | google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967 github.com/google/go-cmp@v0.4.0 161 | google.golang.org/protobuf@v1.22.0 github.com/golang/protobuf@v1.4.0 162 | google.golang.org/protobuf@v1.22.0 github.com/google/go-cmp@v0.4.0 163 | github.com/golang/protobuf@v1.4.0-rc.2 github.com/google/go-cmp@v0.4.0 164 | github.com/golang/protobuf@v1.4.0-rc.2 google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60 165 | google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60 github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208 166 | google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60 github.com/google/go-cmp@v0.4.0 167 | github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4 github.com/golang/protobuf@v1.2.0 168 | github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4 golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f 169 | golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961 golang.org/x/tools@v0.0.0-20190226205152-f727befe758c 170 | github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208 github.com/google/go-cmp@v0.4.0 171 | github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208 google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64 172 | google.golang.org/grpc@v1.23.0 cloud.google.com/go@v0.26.0 173 | google.golang.org/grpc@v1.23.0 github.com/BurntSushi/toml@v0.3.1 174 | google.golang.org/grpc@v1.23.0 github.com/client9/misspell@v0.3.4 175 | google.golang.org/grpc@v1.23.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b 176 | google.golang.org/grpc@v1.23.0 github.com/golang/mock@v1.1.1 177 | google.golang.org/grpc@v1.23.0 github.com/golang/protobuf@v1.2.0 178 | google.golang.org/grpc@v1.23.0 github.com/google/go-cmp@v0.2.0 179 | google.golang.org/grpc@v1.23.0 golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3 180 | google.golang.org/grpc@v1.23.0 golang.org/x/net@v0.0.0-20190311183353-d8887717615a 181 | google.golang.org/grpc@v1.23.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be 182 | google.golang.org/grpc@v1.23.0 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a 183 | google.golang.org/grpc@v1.23.0 golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 184 | google.golang.org/grpc@v1.23.0 google.golang.org/appengine@v1.1.0 185 | google.golang.org/grpc@v1.23.0 google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8 186 | google.golang.org/grpc@v1.23.0 honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc 187 | google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64 github.com/golang/protobuf@v1.4.0-rc.1 188 | google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64 github.com/google/go-cmp@v0.3.1 189 | github.com/golang/protobuf@v1.4.0-rc.1 github.com/google/go-cmp@v0.3.1 190 | github.com/golang/protobuf@v1.4.0-rc.1 google.golang.org/protobuf@v0.0.0-20200109180630-ec00e32a8dfd 191 | google.golang.org/protobuf@v0.0.0-20200109180630-ec00e32a8dfd github.com/google/go-cmp@v0.3.0`}, 192 | } 193 | 194 | for _, tt := range urlTests { 195 | actual1, actual2 := GraphToNodeLinks(tt.in) 196 | if (nil != actual1 && nil != actual2) != tt.expected { 197 | t.Errorf("GraphToNodeLinks(%s) = %v, %v; expected %t", tt.in, actual1, actual2, tt.expected) 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /gosrc/treeutil.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type RouteNode struct { 9 | Id uint32 `json:"id"` 10 | Name string `json:"name"` 11 | Value uint32 `json:"value"` 12 | Route []uint32 `json:"-"` 13 | } 14 | 15 | type Tree struct { 16 | Id uint32 `json:"-"` 17 | Name string `json:"name"` 18 | Value uint32 `json:"value"` 19 | Children []*Tree `json:"children"` 20 | } 21 | 22 | var routeNodes = map[string]RouteNode{} 23 | 24 | func BuildTree(graph string) (root *Tree, depth uint32, width uint32, repeatDependNodes map[string]*Tree) { 25 | root = new(Tree) 26 | repeatDependNodes = make(map[string]*Tree, 0) 27 | var roots = make(map[string]*Tree, 0) 28 | var key uint32 = 0 29 | for _, line := range strings.Split(graph, "\n") { 30 | if 1 > len(line) { 31 | continue 32 | } 33 | splitStr := strings.Split(line, " ") 34 | if 2 > len(splitStr) { 35 | panic(fmt.Sprintf("go mod graph output format error——%s", line)) 36 | } 37 | 38 | var tree = new(Tree) 39 | var theRouteNode1 = GetRouteNode(splitStr[0]) 40 | if nil == theRouteNode1 { 41 | // 寻找父节点 42 | tree.Name = splitStr[0] 43 | tree.Id = key 44 | tree.Value = 1 45 | 46 | if newRoot, ok := roots[splitStr[0]]; ok { 47 | newRoot.Value++ 48 | } else { 49 | newRoot = &Tree{ 50 | Id: key, 51 | Name: splitStr[0], 52 | Value: 1, 53 | } 54 | roots[splitStr[0]] = newRoot 55 | InsertTreeRoute(newRoot, []uint32{}) 56 | } 57 | if 1 > len(root.Name) { 58 | // 如果 root 为空 59 | root.Id = tree.Id 60 | root.Name = tree.Name 61 | root.Value = tree.Value 62 | InsertTreeRoute(tree, []uint32{}) 63 | key ++ 64 | } 65 | theRouteNode1val := routeNodes[tree.Name] 66 | theRouteNode1 = &theRouteNode1val 67 | } else { 68 | // 重复正常 69 | //fmt.Println("重复的依赖节点") 70 | } 71 | 72 | var tree2 = new(Tree) 73 | tree2.Name = splitStr[1] 74 | tree2.Id = key 75 | tree2.Value = 1 76 | 77 | // 依赖节点 78 | var theRouteNode2 = GetRouteNode(splitStr[1]) 79 | if nil == theRouteNode2 { 80 | // 新节点 81 | AppendTreeAfter(root, splitStr[0], tree2) 82 | key ++ 83 | } else { 84 | // 这是规则外的 85 | //fmt.Println("重复的依赖节点", splitStr[1]) 86 | tree2.Id = theRouteNode2.Id // 重复了就要用原来的 87 | var theRouteKeys = append([]uint32{0}, theRouteNode2.Route...) 88 | var theParentNode = &Tree{} 89 | if getNode := GetNodeByKeys([]*Tree{root}, theRouteKeys); nil != getNode { 90 | theParentNode = getNode 91 | } 92 | var newRepeatDependNode = Tree{} 93 | if value, ok := repeatDependNodes[theRouteNode2.Name]; !ok { 94 | newRepeatDependNode = Tree{ 95 | Name: tree2.Name, 96 | Value: tree2.Value, 97 | Id: tree2.Id, 98 | Children: []*Tree{ 99 | { // 之前的那个节点也带上啊a 100 | Name: theParentNode.Name, 101 | Value: theParentNode.Value, 102 | Id: theParentNode.Id, 103 | }, 104 | { 105 | Name: theRouteNode1.Name, 106 | Value: theRouteNode1.Value, 107 | Id: theRouteNode1.Id, 108 | }, 109 | }, 110 | } 111 | repeatDependNodes[tree2.Name] = &newRepeatDependNode 112 | } else { 113 | value.Children = append(value.Children, &Tree{ 114 | Name: theRouteNode1.Name, 115 | Value: theRouteNode1.Value, 116 | Id: theRouteNode1.Id, 117 | }) 118 | repeatDependNodes[tree2.Name] = value 119 | } 120 | } 121 | } 122 | depth, width = CalculateDepthHeight(root) 123 | return 124 | } 125 | 126 | func AppendTreeAfter(parentTreeNode *Tree, parent string, new *Tree) { 127 | routeKey := FindTreeRoute(parent) 128 | resultKeys := insertTree(parentTreeNode, routeKey, new) 129 | InsertTreeRoute(new, resultKeys) 130 | } 131 | 132 | func insertTree(parentTree *Tree, keys []uint32, new *Tree) (route []uint32) { 133 | if 1 > len(keys) { 134 | // 如果没有,直接挂根节点下 135 | if nil == parentTree.Children { 136 | parentTree.Children = make([]*Tree, 0) 137 | } 138 | parentTree.Children = append(parentTree.Children, new) 139 | parentTree.Value++ 140 | return []uint32{uint32(len(parentTree.Children)-1)} 141 | } 142 | theKey := keys[0] 143 | if nil != parentTree.Children && 0 < len(parentTree.Children) { 144 | if int(theKey) > len(parentTree.Children) { 145 | fmt.Println("out range of arr length") 146 | } 147 | var theChild = parentTree.Children[theKey] 148 | if 1 == len(keys) { 149 | if nil == theChild.Children { 150 | theChild.Children = make([]*Tree, 0) 151 | } 152 | theChild.Children = append(theChild.Children, new) 153 | parentTree.Value++ 154 | return []uint32{theKey, uint32(len(theChild.Children)-1)} 155 | } else { 156 | // 进入下级 157 | lastKeys := insertTree(theChild, keys[1:], new) 158 | return append([]uint32{theKey}, lastKeys...) 159 | } 160 | } else { 161 | 162 | } 163 | return 164 | } 165 | 166 | func GetRouteNode(key string) (*RouteNode) { 167 | if routeNode, ok := routeNodes[key]; ok { 168 | return &routeNode 169 | } else { 170 | // 没找到 171 | return nil 172 | } 173 | if "" == key { 174 | return nil 175 | } else { 176 | return nil 177 | } 178 | } 179 | 180 | func FindTreeRoute(key string) (route []uint32) { 181 | if routeNode, ok := routeNodes[key]; ok { 182 | return routeNode.Route 183 | } 184 | if "" == key { 185 | return []uint32{} 186 | } else { 187 | panic("有问题") 188 | } 189 | } 190 | 191 | func InsertTreeRoute(newTree *Tree, keys []uint32) { 192 | if the, ok := routeNodes[newTree.Name]; ok { 193 | the.Route = keys 194 | } else { 195 | routeNodes[newTree.Name] = RouteNode { 196 | Id: newTree.Id, 197 | Name: newTree.Name, 198 | Route: keys, 199 | Value: newTree.Value, 200 | } 201 | } 202 | return 203 | } 204 | 205 | func CalculateDepthHeight(root *Tree) (depth uint32, width uint32) { 206 | depth = calcDepth(root.Children) 207 | var treeWidths = &[]uint32{1} 208 | calcWidth(root.Children, treeWidths, 1) 209 | width = (*treeWidths)[0] 210 | for _, item := range *treeWidths { 211 | if width < item { 212 | width = item 213 | } 214 | } 215 | return 216 | } 217 | 218 | func calcDepth(node []*Tree) (depth uint32) { 219 | if nil != node && 0 < len(node) { 220 | // 有 221 | var maxDepth uint32 = 0 222 | var theDepth uint32 = 0 223 | for _, item := range node { 224 | theDepth = calcDepth(item.Children) 225 | if theDepth > maxDepth { 226 | // 如果更深 227 | maxDepth = theDepth 228 | } 229 | } 230 | return maxDepth + 1 231 | } 232 | // 没有 233 | return 1 234 | } 235 | 236 | func calcWidth(node []*Tree, treeWidths *[]uint32, level int) { 237 | if nil != node && 0 < len(node) { 238 | // 有 239 | var theWidth uint32 = uint32(len(node)) 240 | if level < len(*treeWidths) { 241 | var originWidth = (*treeWidths)[level] 242 | (*treeWidths)[level] = originWidth + theWidth 243 | } else { 244 | *treeWidths = append(*treeWidths, theWidth) 245 | } 246 | for _, item := range node { 247 | calcWidth(item.Children, treeWidths, level + 1) 248 | } 249 | } 250 | } 251 | 252 | func GetNodeByKeys(tree []*Tree, keys []uint32) (re *Tree) { 253 | if 1 > len(keys) { 254 | return nil 255 | } 256 | if int(keys[0]) >= len(tree) { 257 | return nil 258 | } 259 | node := tree[keys[0]] 260 | if 1 < len(keys) { 261 | return GetNodeByKeys(node.Children, keys[1:]) 262 | } else if 1 == len(keys) { 263 | return node 264 | } else { 265 | return nil 266 | } 267 | } -------------------------------------------------------------------------------- /gosrc/treeutil_test.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | ) 7 | 8 | func TestBuildTree(t *testing.T) { 9 | var urlTests = []struct { 10 | expected bool // expected result 11 | in string // input 12 | }{ 13 | {true, `go-mod-graph-charting github.com/gin-gonic/gin@v1.6.3 14 | go-mod-graph-charting github.com/go-playground/validator/v10@v10.4.1 15 | go-mod-graph-charting github.com/golang/protobuf@v1.4.3 16 | go-mod-graph-charting github.com/json-iterator/go@v1.1.10 17 | go-mod-graph-charting github.com/leodido/go-urn@v1.2.1 18 | go-mod-graph-charting github.com/modern-go/concurrent@v0.0.0-20180306012644-bacd9c7ef1dd 19 | go-mod-graph-charting github.com/modern-go/reflect2@v1.0.1 20 | go-mod-graph-charting github.com/ugorji/go@v1.2.2 21 | go-mod-graph-charting golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad 22 | go-mod-graph-charting golang.org/x/sys@v0.0.0-20201223074533-0d417f636930 23 | go-mod-graph-charting google.golang.org/protobuf@v1.25.0 24 | go-mod-graph-charting gopkg.in/yaml.v2@v2.4.0 25 | github.com/leodido/go-urn@v1.2.1 github.com/stretchr/testify@v1.6.1 26 | github.com/gin-gonic/gin@v1.6.3 github.com/gin-contrib/sse@v0.1.0 27 | github.com/gin-gonic/gin@v1.6.3 github.com/go-playground/validator/v10@v10.2.0 28 | github.com/gin-gonic/gin@v1.6.3 github.com/golang/protobuf@v1.3.3 29 | github.com/gin-gonic/gin@v1.6.3 github.com/json-iterator/go@v1.1.9 30 | github.com/gin-gonic/gin@v1.6.3 github.com/mattn/go-isatty@v0.0.12 31 | github.com/gin-gonic/gin@v1.6.3 github.com/stretchr/testify@v1.4.0 32 | github.com/gin-gonic/gin@v1.6.3 github.com/ugorji/go/codec@v1.1.7 33 | github.com/gin-gonic/gin@v1.6.3 gopkg.in/yaml.v2@v2.2.8 34 | github.com/stretchr/testify@v1.4.0 github.com/davecgh/go-spew@v1.1.0 35 | github.com/stretchr/testify@v1.4.0 github.com/pmezard/go-difflib@v1.0.0 36 | github.com/stretchr/testify@v1.4.0 github.com/stretchr/objx@v0.1.0 37 | github.com/stretchr/testify@v1.4.0 gopkg.in/yaml.v2@v2.2.2 38 | github.com/ugorji/go/codec@v1.1.7 github.com/ugorji/go@v1.1.7 39 | github.com/stretchr/testify@v1.6.1 github.com/davecgh/go-spew@v1.1.0 40 | github.com/stretchr/testify@v1.6.1 github.com/pmezard/go-difflib@v1.0.0 41 | github.com/stretchr/testify@v1.6.1 github.com/stretchr/objx@v0.1.0 42 | github.com/stretchr/testify@v1.6.1 gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c 43 | golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 44 | golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037 45 | golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221 46 | google.golang.org/protobuf@v1.25.0 github.com/golang/protobuf@v1.4.1 47 | google.golang.org/protobuf@v1.25.0 github.com/google/go-cmp@v0.5.0 48 | google.golang.org/protobuf@v1.25.0 google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 49 | github.com/golang/protobuf@v1.4.1 github.com/google/go-cmp@v0.4.0 50 | github.com/golang/protobuf@v1.4.1 google.golang.org/protobuf@v1.22.0 51 | github.com/ugorji/go@v1.2.2 github.com/ugorji/go/codec@v1.2.2 52 | gopkg.in/yaml.v2@v2.2.8 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 53 | github.com/gin-contrib/sse@v0.1.0 github.com/stretchr/testify@v1.3.0 54 | github.com/json-iterator/go@v1.1.10 github.com/davecgh/go-spew@v1.1.1 55 | github.com/json-iterator/go@v1.1.10 github.com/google/gofuzz@v1.0.0 56 | github.com/json-iterator/go@v1.1.10 github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421 57 | github.com/json-iterator/go@v1.1.10 github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742 58 | github.com/json-iterator/go@v1.1.10 github.com/stretchr/testify@v1.3.0 59 | github.com/golang/protobuf@v1.4.3 github.com/google/go-cmp@v0.4.0 60 | github.com/golang/protobuf@v1.4.3 google.golang.org/protobuf@v1.23.0 61 | golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 62 | golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/text@v0.3.0 63 | gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 64 | github.com/json-iterator/go@v1.1.9 github.com/davecgh/go-spew@v1.1.1 65 | github.com/json-iterator/go@v1.1.9 github.com/google/gofuzz@v1.0.0 66 | github.com/json-iterator/go@v1.1.9 github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421 67 | github.com/json-iterator/go@v1.1.9 github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742 68 | github.com/json-iterator/go@v1.1.9 github.com/stretchr/testify@v1.3.0 69 | github.com/stretchr/testify@v1.3.0 github.com/davecgh/go-spew@v1.1.0 70 | github.com/stretchr/testify@v1.3.0 github.com/pmezard/go-difflib@v1.0.0 71 | github.com/stretchr/testify@v1.3.0 github.com/stretchr/objx@v0.1.0 72 | github.com/google/go-cmp@v0.5.0 golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 73 | github.com/google/go-cmp@v0.4.0 golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 74 | github.com/ugorji/go@v1.1.7 github.com/ugorji/go/codec@v1.1.7 75 | gopkg.in/yaml.v2@v2.4.0 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 76 | github.com/mattn/go-isatty@v0.0.12 golang.org/x/sys@v0.0.0-20200116001909-b77594299b42 77 | github.com/go-playground/validator/v10@v10.4.1 github.com/go-playground/assert/v2@v2.0.1 78 | github.com/go-playground/validator/v10@v10.4.1 github.com/go-playground/locales@v0.13.0 79 | github.com/go-playground/validator/v10@v10.4.1 github.com/go-playground/universal-translator@v0.17.0 80 | github.com/go-playground/validator/v10@v10.4.1 github.com/leodido/go-urn@v1.2.0 81 | github.com/go-playground/validator/v10@v10.4.1 golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 82 | github.com/leodido/go-urn@v1.2.0 github.com/stretchr/testify@v1.4.0 83 | golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 84 | golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 golang.org/x/sys@v0.0.0-20190412213103-97732733099d 85 | github.com/go-playground/validator/v10@v10.2.0 github.com/go-playground/assert/v2@v2.0.1 86 | github.com/go-playground/validator/v10@v10.2.0 github.com/go-playground/locales@v0.13.0 87 | github.com/go-playground/validator/v10@v10.2.0 github.com/go-playground/universal-translator@v0.17.0 88 | github.com/go-playground/validator/v10@v10.2.0 github.com/leodido/go-urn@v1.2.0 89 | github.com/go-playground/universal-translator@v0.17.0 github.com/go-playground/locales@v0.13.0 90 | google.golang.org/protobuf@v1.23.0 github.com/golang/protobuf@v1.4.0 91 | google.golang.org/protobuf@v1.23.0 github.com/google/go-cmp@v0.4.0 92 | github.com/ugorji/go/codec@v1.2.2 github.com/ugorji/go@v1.2.2 93 | github.com/golang/protobuf@v1.4.0 github.com/google/go-cmp@v0.4.0 94 | github.com/golang/protobuf@v1.4.0 google.golang.org/protobuf@v1.21.0 95 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 github.com/golang/protobuf@v1.4.1 96 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3 97 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 98 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 google.golang.org/grpc@v1.27.0 99 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc 100 | google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013 honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc 101 | google.golang.org/protobuf@v1.21.0 github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0 102 | google.golang.org/protobuf@v1.21.0 github.com/google/go-cmp@v0.4.0 103 | golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3 golang.org/x/tools@v0.0.0-20190311212946-11955173bddd 104 | golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221 golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037 105 | github.com/go-playground/locales@v0.13.0 golang.org/x/text@v0.3.2 106 | golang.org/x/text@v0.3.2 golang.org/x/tools@v0.0.0-20180917221912-90fa682c2a6e 107 | golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a 108 | github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0 github.com/google/go-cmp@v0.4.0 109 | github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0 google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967 110 | golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 golang.org/x/net@v0.0.0-20190311183353-d8887717615a 111 | golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 golang.org/x/sync@v0.0.0-20190423024810-112230192c58 112 | golang.org/x/tools@v0.0.0-20190311212946-11955173bddd golang.org/x/net@v0.0.0-20190311183353-d8887717615a 113 | google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc github.com/golang/protobuf@v1.4.0 114 | google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc github.com/google/go-cmp@v0.4.0 115 | gopkg.in/yaml.v2@v2.2.2 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 116 | google.golang.org/grpc@v1.27.0 github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 117 | google.golang.org/grpc@v1.27.0 github.com/envoyproxy/protoc-gen-validate@v0.1.0 118 | google.golang.org/grpc@v1.27.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b 119 | google.golang.org/grpc@v1.27.0 github.com/golang/mock@v1.1.1 120 | google.golang.org/grpc@v1.27.0 github.com/golang/protobuf@v1.3.2 121 | google.golang.org/grpc@v1.27.0 github.com/google/go-cmp@v0.2.0 122 | google.golang.org/grpc@v1.27.0 golang.org/x/net@v0.0.0-20190311183353-d8887717615a 123 | google.golang.org/grpc@v1.27.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be 124 | google.golang.org/grpc@v1.27.0 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a 125 | google.golang.org/grpc@v1.27.0 google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 126 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 github.com/golang/protobuf@v1.3.2 127 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 golang.org/x/exp@v0.0.0-20190121172915-509febef88a4 128 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961 129 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 golang.org/x/tools@v0.0.0-20190226205152-f727befe758c 130 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 google.golang.org/grpc@v1.19.0 131 | google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099 132 | google.golang.org/grpc@v1.19.0 cloud.google.com/go@v0.26.0 133 | google.golang.org/grpc@v1.19.0 github.com/BurntSushi/toml@v0.3.1 134 | google.golang.org/grpc@v1.19.0 github.com/client9/misspell@v0.3.4 135 | google.golang.org/grpc@v1.19.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b 136 | google.golang.org/grpc@v1.19.0 github.com/golang/mock@v1.1.1 137 | google.golang.org/grpc@v1.19.0 github.com/golang/protobuf@v1.2.0 138 | google.golang.org/grpc@v1.19.0 golang.org/x/lint@v0.0.0-20181026193005-c67002cb31c3 139 | google.golang.org/grpc@v1.19.0 golang.org/x/net@v0.0.0-20180826012351-8a410e7b638d 140 | google.golang.org/grpc@v1.19.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be 141 | google.golang.org/grpc@v1.19.0 golang.org/x/sync@v0.0.0-20180314180146-1d60e4601c6f 142 | google.golang.org/grpc@v1.19.0 golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522 143 | google.golang.org/grpc@v1.19.0 golang.org/x/text@v0.3.0 144 | google.golang.org/grpc@v1.19.0 golang.org/x/tools@v0.0.0-20190114222345-bf090417da8b 145 | google.golang.org/grpc@v1.19.0 google.golang.org/appengine@v1.1.0 146 | google.golang.org/grpc@v1.19.0 google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8 147 | google.golang.org/grpc@v1.19.0 honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099 148 | golang.org/x/net@v0.0.0-20190311183353-d8887717615a golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 149 | golang.org/x/net@v0.0.0-20190311183353-d8887717615a golang.org/x/text@v0.3.0 150 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/census-instrumentation/opencensus-proto@v0.2.1 151 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/envoyproxy/protoc-gen-validate@v0.1.0 152 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/golang/protobuf@v1.3.2 153 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4 154 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55 155 | github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473 google.golang.org/grpc@v1.23.0 156 | golang.org/x/tools@v0.0.0-20190226205152-f727befe758c golang.org/x/net@v0.0.0-20190213061140-3a22650c66bd 157 | golang.org/x/tools@v0.0.0-20190226205152-f727befe758c golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f 158 | golang.org/x/tools@v0.0.0-20190226205152-f727befe758c google.golang.org/appengine@v1.4.0 159 | google.golang.org/appengine@v1.4.0 github.com/golang/protobuf@v1.2.0 160 | google.golang.org/appengine@v1.4.0 golang.org/x/net@v0.0.0-20180724234803-3673e40ba225 161 | google.golang.org/appengine@v1.4.0 golang.org/x/text@v0.3.0 162 | google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967 github.com/golang/protobuf@v1.4.0-rc.2 163 | google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967 github.com/google/go-cmp@v0.4.0 164 | google.golang.org/protobuf@v1.22.0 github.com/golang/protobuf@v1.4.0 165 | google.golang.org/protobuf@v1.22.0 github.com/google/go-cmp@v0.4.0 166 | github.com/golang/protobuf@v1.4.0-rc.2 github.com/google/go-cmp@v0.4.0 167 | github.com/golang/protobuf@v1.4.0-rc.2 google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60 168 | google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60 github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208 169 | google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60 github.com/google/go-cmp@v0.4.0 170 | github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4 github.com/golang/protobuf@v1.2.0 171 | github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4 golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f 172 | golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961 golang.org/x/tools@v0.0.0-20190226205152-f727befe758c 173 | github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208 github.com/google/go-cmp@v0.4.0 174 | github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208 google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64 175 | google.golang.org/grpc@v1.23.0 cloud.google.com/go@v0.26.0 176 | google.golang.org/grpc@v1.23.0 github.com/BurntSushi/toml@v0.3.1 177 | google.golang.org/grpc@v1.23.0 github.com/client9/misspell@v0.3.4 178 | google.golang.org/grpc@v1.23.0 github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b 179 | google.golang.org/grpc@v1.23.0 github.com/golang/mock@v1.1.1 180 | google.golang.org/grpc@v1.23.0 github.com/golang/protobuf@v1.2.0 181 | google.golang.org/grpc@v1.23.0 github.com/google/go-cmp@v0.2.0 182 | google.golang.org/grpc@v1.23.0 golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3 183 | google.golang.org/grpc@v1.23.0 golang.org/x/net@v0.0.0-20190311183353-d8887717615a 184 | google.golang.org/grpc@v1.23.0 golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be 185 | google.golang.org/grpc@v1.23.0 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a 186 | google.golang.org/grpc@v1.23.0 golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135 187 | google.golang.org/grpc@v1.23.0 google.golang.org/appengine@v1.1.0 188 | google.golang.org/grpc@v1.23.0 google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8 189 | google.golang.org/grpc@v1.23.0 honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc 190 | google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64 github.com/golang/protobuf@v1.4.0-rc.1 191 | google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64 github.com/google/go-cmp@v0.3.1 192 | github.com/golang/protobuf@v1.4.0-rc.1 github.com/google/go-cmp@v0.3.1 193 | github.com/golang/protobuf@v1.4.0-rc.1 google.golang.org/protobuf@v0.0.0-20200109180630-ec00e32a8dfd 194 | google.golang.org/protobuf@v0.0.0-20200109180630-ec00e32a8dfd github.com/google/go-cmp@v0.3.0`}, 195 | } 196 | 197 | for _, tt := range urlTests { 198 | actual, _, _, actual2 := BuildTree(tt.in) 199 | if (nil != actual) != tt.expected { 200 | t.Errorf("BuildTree(%s) = %v, %v, expected %t", tt.in, actual, actual2, tt.expected) 201 | } else { 202 | v1, _ :=json.Marshal(actual) 203 | v2, _ :=json.Marshal(actual2) 204 | t.Logf("tree: %s\n an-tree: %s\n", v1, v2) 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /gosrc/util.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "net" 7 | "net/url" 8 | "os" 9 | "os/exec" 10 | "runtime" 11 | "strconv" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | func CheckTcpConnect(host string, port string) (err error) { 17 | timeout := time.Second 18 | conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), timeout) 19 | if err != nil { 20 | return 21 | } 22 | if conn != nil { 23 | defer conn.Close() 24 | return 25 | } 26 | return 27 | } 28 | 29 | func GetUnUsePort() uint32 { 30 | for i := 0; i < 10; i++ { 31 | if i < 1024 { 32 | continue 33 | } 34 | var newPort = rand.Intn(65535) 35 | if err := CheckTcpConnect("127.0.0.1", strconv.Itoa(newPort)); nil != err { 36 | return uint32(newPort) 37 | } 38 | } 39 | return 0 40 | } 41 | 42 | // browsers returns a list of commands to attempt for web visualization. 43 | func browsers() []string { 44 | var cmds []string 45 | if userBrowser := os.Getenv("BROWSER"); userBrowser != "" { 46 | cmds = append(cmds, userBrowser) 47 | } 48 | switch runtime.GOOS { 49 | case "darwin": 50 | cmds = append(cmds, "/usr/bin/open") 51 | case "windows": 52 | cmds = append(cmds, "cmd /c start") 53 | default: 54 | // Commands opening browsers are prioritized over xdg-open, so browser() 55 | // command can be used on linux to open the .svg file generated by the -web 56 | // command (the .svg file includes embedded javascript so is best viewed in 57 | // a browser). 58 | cmds = append(cmds, []string{"chrome", "google-chrome", "chromium", "firefox", "sensible-browser"}...) 59 | if os.Getenv("DISPLAY") != "" { 60 | // xdg-open is only for use in a desktop environment. 61 | cmds = append(cmds, "xdg-open") 62 | } 63 | } 64 | return cmds 65 | } 66 | 67 | // open browser with url 68 | func OpenBrowser(targetUrl string) (err error) { 69 | // Construct URL. 70 | u, _ := url.Parse(targetUrl) 71 | 72 | for _, b := range browsers() { 73 | args := strings.Split(b, " ") 74 | if len(args) == 0 { 75 | continue 76 | } 77 | viewer := exec.Command(args[0], append(args[1:], u.String())...) 78 | viewer.Stderr = os.Stderr 79 | if err = viewer.Start(); err == nil { 80 | return 81 | } 82 | } 83 | // No visualizer succeeded, so just print URL. 84 | fmt.Println(u.String()) 85 | return 86 | } 87 | -------------------------------------------------------------------------------- /gosrc/util_test.go: -------------------------------------------------------------------------------- 1 | package gosrc 2 | 3 | import "testing" 4 | 5 | func TestCheckTcpConnect(t *testing.T) { 6 | var urlTests = []struct { 7 | expected bool // expected result 8 | in string // input 9 | }{ 10 | {true, "1024"}, 11 | {true, "2048"}, 12 | {false, "80"}, 13 | {false, "8080"}, 14 | } 15 | 16 | for _, tt := range urlTests { 17 | actual := CheckTcpConnect("0.0.0.0", tt.in) 18 | if (nil == actual) != tt.expected { 19 | t.Errorf("CheckTcpConnect(%s) = %t; expected %t", tt.in, actual, tt.expected) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-webpack-project", 3 | "version": "1.0.0", 4 | "description": "My webpack project", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "cross-env NODE_ENV=production webpack", 9 | "dev": "cross-env NODE_ENV=development webpack serve --mode development" 10 | }, 11 | "keywords": [ 12 | "go", 13 | "mod", 14 | "graph", 15 | "d3" 16 | ], 17 | "author": "Paul Xu", 18 | "license": "MIT", 19 | "dependencies": { 20 | "d3": "^5.16.0", 21 | "npm": "^8.6.0" 22 | }, 23 | "devDependencies": { 24 | "@webpack-cli/init": "^1.0.3", 25 | "@webpack-cli/serve": "^1.2.0", 26 | "babel-plugin-syntax-dynamic-import": "^6.18.0", 27 | "cross-env": "^7.0.3", 28 | "css-loader": "^5.0.1", 29 | "html-loader": "^1.3.2", 30 | "html-webpack-plugin": "^4.5.0", 31 | "mini-css-extract-plugin": "^1.3.3", 32 | "style-loader": "^2.0.0", 33 | "terser-webpack-plugin": "^5.0.3", 34 | "uglify-js": "^3.12.2", 35 | "webpack": "^5.11.1", 36 | "webpack-cli": "^4.2.0", 37 | "webpack-dev-server": "^3.11.0", 38 | "webpack-parallel-uglify-plugin": "^2.0.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /plugin/pack-all-in-go-plugin.js: -------------------------------------------------------------------------------- 1 | class PackAllInGoPlugin { 2 | apply(compiler) { 3 | // emit is asynchronous hook, tapping into it using tapAsync, you can use tapPromise/tap(synchronous) as well 4 | compiler.hooks.emit.tapAsync('PackAllInGoPlugin', (compilation, callback) => { 5 | // Create a header string for the generated file: 6 | var filelist = ''; 7 | var indexHtml, mainJs; 8 | var goCode = `package godist 9 | 10 | func GetFile(file string) string { 11 | switch { 12 | case \`index.html\` == file: 13 | return IndexHtml 14 | case \`main.js\` == file: 15 | return MainJson 16 | case \`favicon.ico\` == file: 17 | return Favicon 18 | default: 19 | return "" 20 | } 21 | } 22 | 23 | var IndexHtml = \`--index.html--\` 24 | 25 | var MainJson = \`--main.js--\` 26 | 27 | var Favicon = \`favicon.ico\`` 28 | 29 | // Loop through all compiled assets, 30 | // adding a new line item for each filename. 31 | for (var filename in compilation.assets) { 32 | if ("main.js" == filename) { 33 | let jsCode = compilation.assets[filename].source() 34 | let jsCodeString = jsCode.slice(); 35 | jsCodeString = jsCodeString.replace(/\`/g, "\` + \"\`\" + \`") 36 | goCode = goCode.replace('--main.js--', jsCodeString) 37 | } else if ("index.html") { 38 | let htmlCode = compilation.assets[filename].source() 39 | goCode = goCode.replace('--index.html--', htmlCode) 40 | } 41 | } 42 | 43 | // 将这个列表作为一个新的文件资源,插入到 webpack 构建中: 44 | compilation.assets['../godist/static.go'] = { 45 | source: function() { 46 | return goCode; 47 | }, 48 | size: function() { 49 | return goCode.length; 50 | } 51 | }; 52 | 53 | callback(); 54 | }); 55 | } 56 | } 57 | 58 | module.exports = PackAllInGoPlugin; 59 | -------------------------------------------------------------------------------- /show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulXu-cn/go-mod-graph-chart/21b9575a3e4d19534f72faaf9b611c6a66b03b1f/show.gif -------------------------------------------------------------------------------- /src/css/styles.css: -------------------------------------------------------------------------------- 1 | 2 | .tree-path { 3 | fill: none; 4 | stroke: black; 5 | stroke-width: 1.5px; 6 | opacity: 0.6; 7 | } 8 | 9 | .tree-circle { 10 | stroke-width: 1; 11 | } 12 | 13 | .tree-circle.on { 14 | stroke-width: 3; 15 | stroke: black; 16 | } 17 | 18 | .tree-text { 19 | opacity: 0.7; 20 | stroke-width: 0.2px; 21 | stroke: white; 22 | } 23 | 24 | .tree-text.on { 25 | opacity: 1; 26 | stroke-width: 0.8px; 27 | stroke: black; 28 | } 29 | 30 | .mask { 31 | background-color: rgba(100, 100, 100, 0.6); 32 | /* opacity:0.6; */ 33 | position: fixed; 34 | top: 0; 35 | left: 0; 36 | right: 0; 37 | bottom: 0; 38 | z-index: 1000; 39 | transition: all 0.3s ease-in-out; 40 | visibility: visible; 41 | } 42 | 43 | .sub-board { 44 | background-color: white; 45 | position: fixed; 46 | opacity: 1; 47 | top: 0px; 48 | bottom: 0px; 49 | left: 0px; 50 | right: 0px; 51 | width: 640px; 52 | height: 480px; 53 | margin-left:auto; 54 | margin-right:auto; 55 | margin-top: auto; 56 | margin-bottom: auto; 57 | z-index: 1001; 58 | visibility: visible; 59 | overflow-y: auto; 60 | overflow-x: hidden; 61 | } 62 | 63 | div.hide { 64 | display: none; 65 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import graph from './js/graph.js'; 2 | import tree from './js/tree.js'; 3 | 4 | var hostPath = window.location.href; 5 | var paths = hostPath.split("#"); 6 | // 这判断下,什么模式 7 | if (0 < paths.length && "graph" == (paths[paths.length - 1]).toLowerCase()) { 8 | graph(); 9 | } else { 10 | tree(); 11 | } 12 | -------------------------------------------------------------------------------- /src/js/graph.js: -------------------------------------------------------------------------------- 1 | import * as d3 from 'd3'; 2 | import CSS from '../css/styles.css'; 3 | 4 | var width = 1000, height = 1000; 5 | var num = 1; 6 | 7 | export default function graph() { 8 | width = num * 30; 9 | height = num * 30; 10 | 11 | let colorScale, color, circles, lines, texts, arrowMarker, tickCount, simulation; 12 | let svg = d3.select('#app').append('svg').attr('width', width).attr('height', height); 13 | 14 | let nodes = [{ name: 'haha', value: 12 }, { name: '323', value: 32 }, { name: '我们', value: 24 }, { name: 'yes~', value: 43 }, { name: 'sukabulei', value: 18 }], 15 | links = [ 16 | { 'source': 0, 'target': 3, weight: 1 }, 17 | { 'source': 3, 'target': 4, weight: 1 }, 18 | { 'source': 1, 'target': 2, weight: 0.5 }, 19 | ]; 20 | 21 | function dragstarted(d) { 22 | d3.select(this).raise().attr("stroke", "black"); 23 | simulation.stop(); 24 | } 25 | function dragged(d) { 26 | d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y); 27 | ticked(); 28 | } 29 | function dragended(d) { 30 | d3.select(this).attr("stroke", null); 31 | simulation.restart(); 32 | } 33 | const drag = d3.drag() 34 | .on("start", dragstarted) 35 | .on("drag", dragged) 36 | .on("end", dragended); 37 | 38 | const render_init = function () { 39 | var defs = svg.append("defs"); 40 | 41 | arrowMarker = defs.append("marker") 42 | .attr("id", "arrow") 43 | .attr("markerUnits", "strokeWidth") 44 | .attr("markerWidth", "12") 45 | .attr("markerHeight", "12") 46 | .attr("viewBox", "0 0 12 12") 47 | .attr("refX", "6") 48 | .attr("refY", "6") 49 | .attr("orient", "auto"); 50 | 51 | var arrow_path = "M2,2 L10,6 L2,10 L6,6 L2,2"; 52 | 53 | arrowMarker.append("path") 54 | .attr("d", arrow_path) 55 | .attr("fill", "black"); 56 | 57 | lines = svg.selectAll('line').data(links) 58 | .enter().append('line') 59 | .attr('stroke', 'black') 60 | .attr('opacity', 0.8) 61 | // .attr('stroke-width', d => d.width * 5) 62 | .attr('stroke-width', 1) 63 | .attr("marker-end", "url(#arrow)"); 64 | 65 | circles = svg.selectAll('circle').data(nodes) 66 | .enter().append('circle') 67 | .attr('r', 8) 68 | .attr('fill', function (d, i) { return color(i); }) 69 | .call(drag); 70 | 71 | texts = d3.select('svg').selectAll('.circle-text').data(nodes) 72 | .enter().append('text').classed('circle-text', true).text(d => d.name) 73 | .attr('fill', 'gray') 74 | .attr('transform', `translate(10, 5)`); 75 | } 76 | 77 | tickCount = 1; 78 | 79 | function ticked() { 80 | lines.attr('x1', function (d) { return d.source.x; }). 81 | attr('y1', function (d) { return d.source.y; }). 82 | attr('x2', function (d) { if (0 < d.source.x - d.target.x) { return d.target.x + 8; } else { return d.target.x - 8; } }). 83 | attr('y2', function (d) { if (0 < d.source.y - d.target.y) { return d.target.y + 8; } else { return d.target.y - 8; } }). 84 | attr("marker-end", "url(#arrow)"). 85 | attr('d', function (d) { return 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y }). 86 | classed('edgeline', true); 87 | 88 | circles.attr('cx', function (d) { return d.x; }) 89 | .attr('cy', function (d) { return d.y; }) 90 | 91 | texts.attr('x', function (d) { return d.x; }).attr('y', d => d.y); 92 | 93 | // if (tickCount++ > 1000) { 94 | // return false; 95 | // } 96 | } 97 | 98 | function strengthFunc(link) { 99 | return link.weight * 0.01; 100 | } 101 | 102 | function distanceFunc(link) { 103 | return 200 * (1 / link.weight); 104 | } 105 | 106 | d3.json('/graph.json').then(data => { 107 | links = data.data.links; 108 | nodes = data.data.nodes; 109 | num = data.data.num; 110 | 111 | width = num * 30; 112 | height = num * 30; 113 | d3.select('#app').select('svg').attr('width', width).attr('height', height); 114 | 115 | colorScale = d3.scaleDiverging(d3.interpolatePuOr).domain([0, (nodes.length - 1)]); 116 | color = d3.scaleDiverging(d3.interpolateRainbow).domain([0, nodes.length - 1]) 117 | tickCount = 1; 118 | 119 | render_init(); 120 | 121 | simulation = d3.forceSimulation(nodes) 122 | .force('charge', d3.forceManyBody) 123 | .force('center', d3.forceCenter(width / 2, height / 2)) 124 | .force('link', d3.forceLink(links).strength(strengthFunc).distance(distanceFunc)) 125 | .alphaTarget(0.3) 126 | .on('tick', ticked); 127 | 128 | setTimeout(function () { 129 | window.scrollTo(width / 2, height / 2) 130 | }, 1000); 131 | }) 132 | } -------------------------------------------------------------------------------- /src/js/tree.js: -------------------------------------------------------------------------------- 1 | import * as d3 from 'd3'; 2 | import CSS from '../css/styles.css'; 3 | 4 | var treeWidth = 1; 5 | var treeDepth = 1; 6 | 7 | var width = 4000; 8 | var height = 2500; 9 | 10 | var innerWidth = 0 11 | var innerHeight = 0; 12 | 13 | var subWidth = 640; 14 | var subHeight = 480; 15 | 16 | var root; 17 | var color; 18 | var anTree; 19 | 20 | const margin = { top: 5, right: 200, bottom: 5, left: 200 }; 21 | 22 | export default function tree() { 23 | const svg = d3.select('#app').append('svg').attr('id', 'svg') 24 | .attr('width', width).attr('height', height); 25 | const subSvg = d3.select('#sub-board').append('svg').attr('id', 'sub-svg') 26 | .attr('width', subWidth).attr('height', subHeight); 27 | 28 | let markerBoxWidth = 10; 29 | let markerBoxHeight = 10; 30 | let refX = 10; 31 | let refY = 4; 32 | svg.append('defs') 33 | .append('marker') 34 | .attr('id', 'arrow') 35 | .attr('viewBox', [0, 0, markerBoxWidth, markerBoxHeight]) 36 | .attr('refX', refX) 37 | .attr('refY', refY) 38 | .attr('markerWidth', markerBoxWidth) 39 | .attr('markerHeight', markerBoxHeight) 40 | .attr('orient', 'auto-start-reverse') 41 | .append('path') 42 | .attr('d', d3.line()([[0, 0], [8, 4], [0, 8], [0, 7], [9, 4], [0, 1], [0, 0]])) 43 | .attr('stroke', 'black'); 44 | 45 | 46 | const g = svg.append('g') 47 | .attr('transform', `translate(${margin.left}, ${margin.top})`); 48 | 49 | const fill = d => { 50 | if (d.depth === 0) 51 | return color(d.data.name) 52 | else 53 | return color(d.parent.data.name) 54 | } 55 | 56 | document.getElementById('mask').addEventListener('click', function (ev) { 57 | if ('mask' == ev.target.getAttribute('id')) { 58 | // ev.target.setAttribute("class", "mask hide"); 59 | document.getElementById('mask').setAttribute("class", "mask hide"); 60 | } 61 | }); 62 | 63 | const subRender = function (data) { 64 | let anotation = 500; 65 | color = d3.scaleOrdinal() 66 | .domain(data.descendants().filter(d => d.depth <= 1).map(d => d.data.name)) 67 | .range(d3.schemeCategory10); 68 | 69 | subSvg.selectAll("path") 70 | .data(data.links()) 71 | .join("path") 72 | .classed('tree-path', true) 73 | .attr("d", d3.linkHorizontal().x(d => anotation - d.y).y(d => d.x)); 74 | 75 | subSvg.selectAll('circle').data(data.descendants()).join('circle') 76 | // optionally, we can use stroke-linejoin to beautify the path connection; 77 | //.attr("stroke-linejoin", "round") 78 | .classed('tree-circle', true) 79 | .attr("fill", fill) 80 | .attr('id', (d, i) => `circle-${i}`) 81 | .attr('cx', d => anotation - d.y) 82 | .attr('cy', d => d.x) 83 | .attr("r", function (d) { 84 | if (d.children) { 85 | return 6 + Math.sqrt(d.children.length) * 3; 86 | } else { 87 | return 7; 88 | } 89 | }); 90 | 91 | subSvg.selectAll('text').data(data.descendants()).join('text') 92 | .classed('tree-text', true) 93 | .attr("text-anchor", d => d.children ? "end" : "start") 94 | .attr('id', (d, i) => `text-${i}`) 95 | // note that if d is a child, d.children is undefined which is actually false! 96 | .attr('x', d => (d.children ? -6 : 6) + (anotation - d.y)) 97 | .attr('y', function (d) { return d.depth % 2 ? d.x - 3 : d.x + 14 }) 98 | .text(function (d) { 99 | // 默认最多只展示版本号,不展示hash 100 | return d.data.name.replace(/(@[\w\.]*?)(-)(.*$)/, "$1") 101 | }); 102 | } 103 | 104 | const renderSubTree = function (d, i) { 105 | let theName = d.data.name; 106 | let subTree = undefined; 107 | if (anTree[theName] !== undefined) { 108 | subTree = anTree[theName] 109 | } else { 110 | return 111 | } 112 | 113 | document.getElementById('mask').setAttribute("class", "mask"); 114 | 115 | let theSubHeight = subTree.children.length * 150; 116 | d3.select('#sub-board').select('#sub-svg').attr('width', subWidth).attr('height', theSubHeight); 117 | 118 | let subRoot = d3.hierarchy(subTree); 119 | subRoot = d3.tree().size([theSubHeight, subWidth - 200])(subRoot); 120 | subRender(subRoot); 121 | } 122 | 123 | const render = function (data, anData) { 124 | color = d3.scaleOrdinal() 125 | .domain(data.descendants().filter(d => d.depth <= 1).map(d => d.data.name)) 126 | .range(d3.schemeCategory10); 127 | 128 | g.selectAll("path") 129 | .data(data.links()) 130 | .join("path") 131 | .classed('tree-path', true) 132 | .attr("d", d3.linkHorizontal().x(d => d.y).y(d => d.x)) 133 | .attr("marker-end", function (d, i) { 134 | let check = anData[d.target.data.name]; 135 | if (undefined != check) { 136 | return "url(#arrow)" 137 | } 138 | }); 139 | 140 | g.selectAll('circle').data(data.descendants()).join('circle') 141 | // optionally, we can use stroke-linejoin to beautify the path connection; 142 | //.attr("stroke-linejoin", "round") 143 | .classed('tree-circle', true) 144 | .attr("fill", fill) 145 | .attr('id', (d, i) => `circle-${i}`) 146 | .attr('cx', d => d.y) 147 | .attr('cy', d => d.x) 148 | .attr("r", function (d) { 149 | if (d.children) { 150 | return 6 + Math.sqrt(d.children.length) * 3; 151 | } else { 152 | return 7; 153 | } 154 | }).on('mouseover', function (d, i) { 155 | d3.select(this).classed('on', true); 156 | d3.select("#text-" + i).classed('on', true); 157 | }).on('mouseout', function (d, i) { 158 | d3.select(this).classed('on', false).attr('stroke', fill(d)); 159 | d3.select("#text-" + i).classed('on', false); 160 | }).on('click', renderSubTree); 161 | 162 | g.selectAll('text').data(data.descendants()).join('text') 163 | .classed('tree-text', true) 164 | .attr("text-anchor", d => d.children ? "end" : "start") 165 | .attr('id', (d, i) => `text-${i}`) 166 | // note that if d is a child, d.children is undefined which is actually false! 167 | .attr('x', d => (d.children ? -6 : 6) + d.y) 168 | .attr('y', function (d) { return d.depth % 2 ? d.x - 3 : d.x + 14 }) 169 | .text(function (d) { 170 | // 默认最多只展示版本号,不展示hash 171 | return d.data.name.replace(/(@[\w\.]*?)(-)(.*$)/, "$1") 172 | }) 173 | .on('mouseover', function (d, i) { 174 | // 鼠标放上去时,才展示后面的hash值 175 | d3.select(this).classed('on', true).text(d => d.data.name); 176 | d3.select("#circle-" + i).classed('on', true); 177 | }).on('mouseout', function (d, i) { 178 | d3.select(this).classed('on', false).text(function (d) { 179 | return d.data.name.replace(/(@[\w\.]*?)(-)(.*$)/, "$1") 180 | }); 181 | d3.select("#circle-" + i).classed('on', false).attr('stroke', fill(d)); 182 | }).on('click', renderSubTree); 183 | } 184 | 185 | d3.json('/an-tree.json').then(data => { 186 | anTree = data.data.tree; 187 | 188 | d3.json('/tree.json').then(data => { 189 | let treeData = data.data.tree; 190 | treeWidth = data.data.width; 191 | treeDepth = data.data.depth; 192 | 193 | innerWidth = treeDepth * 450; 194 | innerHeight = treeWidth * 70; 195 | 196 | width = innerWidth + margin.left + margin.right; 197 | height = innerHeight + margin.top + margin.bottom; 198 | 199 | d3.select('#app').select('svg').attr('width', width).attr('height', height); 200 | 201 | root = d3.hierarchy(treeData); 202 | // alternatively, we can set size of each node; 203 | // root = d3.tree().nodeSize([30, width / (root.height + 1)])(root); 204 | root = d3.tree().size([innerHeight, innerWidth])(root); 205 | render(root, anTree); 206 | 207 | setTimeout(function () { 208 | window.scrollTo(0, height / 2) 209 | }, 1000); 210 | }); 211 | }); 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/static/an-tree.json: -------------------------------------------------------------------------------- 1 | {"message":"success","data":{"tree":{"cloud.google.com/go@v0.26.0":{"name":"cloud.google.com/go@v0.26.0","value":1,"children":[{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/BurntSushi/toml@v0.3.1":{"name":"github.com/BurntSushi/toml@v0.3.1","value":1,"children":[{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/client9/misspell@v0.3.4":{"name":"github.com/client9/misspell@v0.3.4","value":1,"children":[{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/davecgh/go-spew@v1.1.0":{"name":"github.com/davecgh/go-spew@v1.1.0","value":1,"children":[{"name":"github.com/stretchr/testify@v1.4.0","value":1,"children":null},{"name":"github.com/stretchr/testify@v1.6.1","value":1,"children":null},{"name":"github.com/stretchr/testify@v1.3.0","value":1,"children":null}]},"github.com/davecgh/go-spew@v1.1.1":{"name":"github.com/davecgh/go-spew@v1.1.1","value":1,"children":[{"name":"github.com/json-iterator/go@v1.1.10","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.9","value":1,"children":null}]},"github.com/envoyproxy/protoc-gen-validate@v0.1.0":{"name":"github.com/envoyproxy/protoc-gen-validate@v0.1.0","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":7,"children":null},{"name":"github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473","value":1,"children":null}]},"github.com/go-playground/assert/v2@v2.0.1":{"name":"github.com/go-playground/assert/v2@v2.0.1","value":1,"children":[{"name":"github.com/go-playground/validator/v10@v10.4.1","value":2,"children":null},{"name":"github.com/go-playground/validator/v10@v10.2.0","value":1,"children":null}]},"github.com/go-playground/locales@v0.13.0":{"name":"github.com/go-playground/locales@v0.13.0","value":1,"children":[{"name":"github.com/go-playground/validator/v10@v10.4.1","value":2,"children":null},{"name":"github.com/go-playground/validator/v10@v10.2.0","value":1,"children":null},{"name":"github.com/go-playground/universal-translator@v0.17.0","value":1,"children":null}]},"github.com/go-playground/universal-translator@v0.17.0":{"name":"github.com/go-playground/universal-translator@v0.17.0","value":1,"children":[{"name":"github.com/go-playground/validator/v10@v10.4.1","value":2,"children":null},{"name":"github.com/go-playground/validator/v10@v10.2.0","value":1,"children":null}]},"github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b":{"name":"github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":6,"children":null},{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/golang/mock@v1.1.1":{"name":"github.com/golang/mock@v1.1.1","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":6,"children":null},{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/golang/protobuf@v1.2.0":{"name":"github.com/golang/protobuf@v1.2.0","value":1,"children":[{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/appengine@v1.4.0","value":1,"children":null},{"name":"github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/golang/protobuf@v1.3.2":{"name":"github.com/golang/protobuf@v1.3.2","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":1,"children":null},{"name":"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55","value":1,"children":null},{"name":"github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473","value":1,"children":null}]},"github.com/golang/protobuf@v1.4.0":{"name":"github.com/golang/protobuf@v1.4.0","value":1,"children":[{"name":"google.golang.org/protobuf@v1.23.0","value":2,"children":null},{"name":"google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.22.0","value":1,"children":null}]},"github.com/golang/protobuf@v1.4.1":{"name":"github.com/golang/protobuf@v1.4.1","value":1,"children":[{"name":"google.golang.org/protobuf@v1.25.0","value":4,"children":null},{"name":"google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013","value":1,"children":null}]},"github.com/google/go-cmp@v0.2.0":{"name":"github.com/google/go-cmp@v0.2.0","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":9,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"github.com/google/go-cmp@v0.3.1":{"name":"github.com/google/go-cmp@v0.3.1","value":1,"children":[{"name":"google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.4.0-rc.1","value":1,"children":null}]},"github.com/google/go-cmp@v0.4.0":{"name":"github.com/google/go-cmp@v0.4.0","value":1,"children":[{"name":"github.com/golang/protobuf@v1.4.1","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.4.3","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.23.0","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.4.0","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.21.0","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.22.0","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.4.0-rc.2","value":1,"children":null},{"name":"google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208","value":1,"children":null}]},"github.com/google/gofuzz@v1.0.0":{"name":"github.com/google/gofuzz@v1.0.0","value":1,"children":[{"name":"github.com/json-iterator/go@v1.1.10","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.9","value":1,"children":null}]},"github.com/leodido/go-urn@v1.2.0":{"name":"github.com/leodido/go-urn@v1.2.0","value":1,"children":[{"name":"github.com/go-playground/validator/v10@v10.4.1","value":2,"children":null},{"name":"github.com/go-playground/validator/v10@v10.2.0","value":1,"children":null}]},"github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421":{"name":"github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421","value":1,"children":[{"name":"github.com/json-iterator/go@v1.1.10","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.9","value":1,"children":null}]},"github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742":{"name":"github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742","value":1,"children":[{"name":"github.com/json-iterator/go@v1.1.10","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.9","value":1,"children":null}]},"github.com/pmezard/go-difflib@v1.0.0":{"name":"github.com/pmezard/go-difflib@v1.0.0","value":1,"children":[{"name":"github.com/stretchr/testify@v1.4.0","value":1,"children":null},{"name":"github.com/stretchr/testify@v1.6.1","value":1,"children":null},{"name":"github.com/stretchr/testify@v1.3.0","value":1,"children":null}]},"github.com/stretchr/objx@v0.1.0":{"name":"github.com/stretchr/objx@v0.1.0","value":1,"children":[{"name":"github.com/stretchr/testify@v1.4.0","value":1,"children":null},{"name":"github.com/stretchr/testify@v1.6.1","value":1,"children":null},{"name":"github.com/stretchr/testify@v1.3.0","value":1,"children":null}]},"github.com/stretchr/testify@v1.3.0":{"name":"github.com/stretchr/testify@v1.3.0","value":1,"children":[{"name":"github.com/gin-contrib/sse@v0.1.0","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.10","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.9","value":1,"children":null}]},"github.com/stretchr/testify@v1.4.0":{"name":"github.com/stretchr/testify@v1.4.0","value":1,"children":[{"name":"github.com/gin-gonic/gin@v1.6.3","value":9,"children":null},{"name":"github.com/leodido/go-urn@v1.2.0","value":1,"children":null}]},"github.com/ugorji/go/codec@v1.1.7":{"name":"github.com/ugorji/go/codec@v1.1.7","value":1,"children":[{"name":"github.com/gin-gonic/gin@v1.6.3","value":8,"children":null},{"name":"github.com/ugorji/go@v1.1.7","value":1,"children":null}]},"github.com/ugorji/go@v1.2.2":{"name":"github.com/ugorji/go@v1.2.2","value":1,"children":[{"name":"go-mod-graph-charting","value":39,"children":null},{"name":"github.com/ugorji/go/codec@v1.2.2","value":1,"children":null}]},"golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2":{"name":"golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2","value":1,"children":[{"name":"golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3","value":2,"children":null},{"name":"golang.org/x/net@v0.0.0-20190311183353-d8887717615a","value":1,"children":null}]},"golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3":{"name":"golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3","value":1,"children":[{"name":"google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013","value":12,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"golang.org/x/net@v0.0.0-20190311183353-d8887717615a":{"name":"golang.org/x/net@v0.0.0-20190311183353-d8887717615a","value":1,"children":[{"name":"golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135","value":1,"children":null},{"name":"golang.org/x/tools@v0.0.0-20190311212946-11955173bddd","value":1,"children":null},{"name":"google.golang.org/grpc@v1.27.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3":{"name":"golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3","value":1,"children":[{"name":"golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad","value":3,"children":null},{"name":"golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9","value":1,"children":null}]},"golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be":{"name":"golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":6,"children":null},{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f":{"name":"golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f","value":1,"children":[{"name":"golang.org/x/tools@v0.0.0-20190226205152-f727befe758c","value":2,"children":null},{"name":"github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4","value":1,"children":null}]},"golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a":{"name":"golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a","value":1,"children":[{"name":"golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2","value":1,"children":null},{"name":"google.golang.org/grpc@v1.27.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037":{"name":"golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037","value":1,"children":[{"name":"golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad","value":3,"children":null},{"name":"golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221","value":1,"children":null}]},"golang.org/x/text@v0.3.0":{"name":"golang.org/x/text@v0.3.0","value":1,"children":[{"name":"golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3","value":2,"children":null},{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"golang.org/x/net@v0.0.0-20190311183353-d8887717615a","value":1,"children":null},{"name":"google.golang.org/appengine@v1.4.0","value":1,"children":null}]},"golang.org/x/tools@v0.0.0-20190226205152-f727befe758c":{"name":"golang.org/x/tools@v0.0.0-20190226205152-f727befe758c","value":1,"children":[{"name":"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55","value":15,"children":null},{"name":"golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961","value":1,"children":null}]},"golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135":{"name":"golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135","value":1,"children":[{"name":"google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013","value":12,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543":{"name":"golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543","value":1,"children":[{"name":"github.com/google/go-cmp@v0.5.0","value":1,"children":null},{"name":"github.com/google/go-cmp@v0.4.0","value":1,"children":null}]},"google.golang.org/appengine@v1.1.0":{"name":"google.golang.org/appengine@v1.1.0","value":1,"children":[{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8":{"name":"google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8","value":1,"children":[{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55":{"name":"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55","value":1,"children":[{"name":"google.golang.org/grpc@v1.27.0","value":8,"children":null},{"name":"github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473","value":1,"children":null}]},"gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405":{"name":"gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405","value":1,"children":[{"name":"gopkg.in/yaml.v2@v2.2.8","value":1,"children":null},{"name":"gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c","value":1,"children":null},{"name":"gopkg.in/yaml.v2@v2.4.0","value":1,"children":null},{"name":"gopkg.in/yaml.v2@v2.2.2","value":1,"children":null}]},"honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099":{"name":"honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099","value":1,"children":[{"name":"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55","value":12,"children":null},{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":null}]},"honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc":{"name":"honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc","value":1,"children":[{"name":"google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013","value":12,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]}}}} -------------------------------------------------------------------------------- /src/static/graph.json: -------------------------------------------------------------------------------- 1 | {"message":"success","data":{"nodes":[{"id":0,"name":"go-mod-graph-charting","value":12},{"id":1,"name":"github.com/gin-gonic/gin@v1.6.3","value":9},{"id":2,"name":"github.com/go-playground/validator/v10@v10.4.1","value":6},{"id":3,"name":"github.com/golang/protobuf@v1.4.3","value":3},{"id":4,"name":"github.com/json-iterator/go@v1.1.10","value":6},{"id":5,"name":"github.com/leodido/go-urn@v1.2.1","value":2},{"id":6,"name":"github.com/modern-go/concurrent@v0.0.0-20180306012644-bacd9c7ef1dd","value":1},{"id":7,"name":"github.com/modern-go/reflect2@v1.0.1","value":1},{"id":8,"name":"github.com/ugorji/go@v1.2.2","value":2},{"id":9,"name":"golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad","value":4},{"id":10,"name":"golang.org/x/sys@v0.0.0-20201223074533-0d417f636930","value":1},{"id":11,"name":"google.golang.org/protobuf@v1.25.0","value":4},{"id":12,"name":"gopkg.in/yaml.v2@v2.4.0","value":2},{"id":13,"name":"github.com/stretchr/testify@v1.6.1","value":5},{"id":14,"name":"github.com/gin-contrib/sse@v0.1.0","value":2},{"id":15,"name":"github.com/go-playground/validator/v10@v10.2.0","value":5},{"id":16,"name":"github.com/golang/protobuf@v1.3.3","value":1},{"id":17,"name":"github.com/json-iterator/go@v1.1.9","value":6},{"id":18,"name":"github.com/mattn/go-isatty@v0.0.12","value":2},{"id":19,"name":"github.com/stretchr/testify@v1.4.0","value":5},{"id":20,"name":"github.com/ugorji/go/codec@v1.1.7","value":2},{"id":21,"name":"gopkg.in/yaml.v2@v2.2.8","value":2},{"id":22,"name":"github.com/davecgh/go-spew@v1.1.0","value":1},{"id":23,"name":"github.com/pmezard/go-difflib@v1.0.0","value":1},{"id":24,"name":"github.com/stretchr/objx@v0.1.0","value":1},{"id":25,"name":"gopkg.in/yaml.v2@v2.2.2","value":2},{"id":26,"name":"github.com/ugorji/go@v1.1.7","value":2},{"id":27,"name":"gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c","value":2},{"id":28,"name":"golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3","value":3},{"id":29,"name":"golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037","value":1},{"id":30,"name":"golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221","value":2},{"id":31,"name":"github.com/golang/protobuf@v1.4.1","value":3},{"id":32,"name":"github.com/google/go-cmp@v0.5.0","value":2},{"id":33,"name":"google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013","value":7},{"id":34,"name":"github.com/google/go-cmp@v0.4.0","value":2},{"id":35,"name":"google.golang.org/protobuf@v1.22.0","value":3},{"id":36,"name":"github.com/ugorji/go/codec@v1.2.2","value":2},{"id":37,"name":"gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405","value":1},{"id":38,"name":"github.com/stretchr/testify@v1.3.0","value":4},{"id":39,"name":"github.com/davecgh/go-spew@v1.1.1","value":1},{"id":40,"name":"github.com/google/gofuzz@v1.0.0","value":1},{"id":41,"name":"github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421","value":1},{"id":42,"name":"github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742","value":1},{"id":43,"name":"google.golang.org/protobuf@v1.23.0","value":3},{"id":44,"name":"golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2","value":2},{"id":45,"name":"golang.org/x/text@v0.3.0","value":1},{"id":46,"name":"golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543","value":1},{"id":47,"name":"golang.org/x/sys@v0.0.0-20200116001909-b77594299b42","value":1},{"id":48,"name":"github.com/go-playground/assert/v2@v2.0.1","value":1},{"id":49,"name":"github.com/go-playground/locales@v0.13.0","value":2},{"id":50,"name":"github.com/go-playground/universal-translator@v0.17.0","value":2},{"id":51,"name":"github.com/leodido/go-urn@v1.2.0","value":2},{"id":52,"name":"golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9","value":3},{"id":53,"name":"golang.org/x/sys@v0.0.0-20190412213103-97732733099d","value":1},{"id":54,"name":"github.com/golang/protobuf@v1.4.0","value":3},{"id":55,"name":"google.golang.org/protobuf@v1.21.0","value":3},{"id":56,"name":"golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3","value":2},{"id":57,"name":"golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135","value":3},{"id":58,"name":"google.golang.org/grpc@v1.27.0","value":11},{"id":59,"name":"google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc","value":3},{"id":60,"name":"honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc","value":1},{"id":61,"name":"github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0","value":3},{"id":62,"name":"golang.org/x/tools@v0.0.0-20190311212946-11955173bddd","value":2},{"id":63,"name":"golang.org/x/text@v0.3.2","value":2},{"id":64,"name":"golang.org/x/tools@v0.0.0-20180917221912-90fa682c2a6e","value":1},{"id":65,"name":"golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a","value":1},{"id":66,"name":"google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967","value":3},{"id":67,"name":"golang.org/x/net@v0.0.0-20190311183353-d8887717615a","value":3},{"id":68,"name":"golang.org/x/sync@v0.0.0-20190423024810-112230192c58","value":1},{"id":69,"name":"github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473","value":7},{"id":70,"name":"github.com/envoyproxy/protoc-gen-validate@v0.1.0","value":1},{"id":71,"name":"github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b","value":1},{"id":72,"name":"github.com/golang/mock@v1.1.1","value":1},{"id":73,"name":"github.com/golang/protobuf@v1.3.2","value":1},{"id":74,"name":"github.com/google/go-cmp@v0.2.0","value":1},{"id":75,"name":"golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be","value":1},{"id":76,"name":"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55","value":7},{"id":77,"name":"golang.org/x/exp@v0.0.0-20190121172915-509febef88a4","value":1},{"id":78,"name":"golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961","value":2},{"id":79,"name":"golang.org/x/tools@v0.0.0-20190226205152-f727befe758c","value":4},{"id":80,"name":"google.golang.org/grpc@v1.19.0","value":17},{"id":81,"name":"honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099","value":1},{"id":82,"name":"cloud.google.com/go@v0.26.0","value":1},{"id":83,"name":"github.com/BurntSushi/toml@v0.3.1","value":1},{"id":84,"name":"github.com/client9/misspell@v0.3.4","value":1},{"id":85,"name":"github.com/golang/protobuf@v1.2.0","value":1},{"id":86,"name":"golang.org/x/lint@v0.0.0-20181026193005-c67002cb31c3","value":1},{"id":87,"name":"golang.org/x/net@v0.0.0-20180826012351-8a410e7b638d","value":1},{"id":88,"name":"golang.org/x/sync@v0.0.0-20180314180146-1d60e4601c6f","value":1},{"id":89,"name":"golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522","value":1},{"id":90,"name":"golang.org/x/tools@v0.0.0-20190114222345-bf090417da8b","value":1},{"id":91,"name":"google.golang.org/appengine@v1.1.0","value":1},{"id":92,"name":"google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8","value":1},{"id":93,"name":"github.com/census-instrumentation/opencensus-proto@v0.2.1","value":1},{"id":94,"name":"github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4","value":3},{"id":95,"name":"google.golang.org/grpc@v1.23.0","value":16},{"id":96,"name":"golang.org/x/net@v0.0.0-20190213061140-3a22650c66bd","value":1},{"id":97,"name":"golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f","value":1},{"id":98,"name":"google.golang.org/appengine@v1.4.0","value":4},{"id":99,"name":"golang.org/x/net@v0.0.0-20180724234803-3673e40ba225","value":1},{"id":100,"name":"github.com/golang/protobuf@v1.4.0-rc.2","value":3},{"id":101,"name":"google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60","value":3},{"id":102,"name":"github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208","value":3},{"id":103,"name":"google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64","value":3},{"id":104,"name":"github.com/golang/protobuf@v1.4.0-rc.1","value":3},{"id":105,"name":"github.com/google/go-cmp@v0.3.1","value":1},{"id":106,"name":"google.golang.org/protobuf@v0.0.0-20200109180630-ec00e32a8dfd","value":2},{"id":107,"name":"github.com/google/go-cmp@v0.3.0","value":1}],"links":[{"source":0,"target":1,"weight":1,"width":1},{"source":0,"target":2,"weight":1,"width":1},{"source":0,"target":3,"weight":1,"width":1},{"source":0,"target":4,"weight":1,"width":1},{"source":0,"target":5,"weight":1,"width":1},{"source":0,"target":6,"weight":1,"width":1},{"source":0,"target":7,"weight":1,"width":1},{"source":0,"target":8,"weight":1,"width":1},{"source":0,"target":9,"weight":1,"width":1},{"source":0,"target":10,"weight":1,"width":1},{"source":0,"target":11,"weight":1,"width":1},{"source":0,"target":12,"weight":1,"width":1},{"source":5,"target":13,"weight":1,"width":1},{"source":1,"target":14,"weight":1,"width":1},{"source":1,"target":15,"weight":1,"width":1},{"source":1,"target":16,"weight":1,"width":1},{"source":1,"target":17,"weight":1,"width":1},{"source":1,"target":18,"weight":1,"width":1},{"source":1,"target":19,"weight":1,"width":1},{"source":1,"target":20,"weight":1,"width":1},{"source":1,"target":21,"weight":1,"width":1},{"source":19,"target":22,"weight":1,"width":1},{"source":19,"target":23,"weight":1,"width":1},{"source":19,"target":24,"weight":1,"width":1},{"source":19,"target":25,"weight":1,"width":1},{"source":20,"target":26,"weight":1,"width":1},{"source":13,"target":22,"weight":1,"width":1},{"source":13,"target":23,"weight":1,"width":1},{"source":13,"target":24,"weight":1,"width":1},{"source":13,"target":27,"weight":1,"width":1},{"source":9,"target":28,"weight":1,"width":1},{"source":9,"target":29,"weight":1,"width":1},{"source":9,"target":30,"weight":1,"width":1},{"source":11,"target":31,"weight":1,"width":1},{"source":11,"target":32,"weight":1,"width":1},{"source":11,"target":33,"weight":1,"width":1},{"source":31,"target":34,"weight":1,"width":1},{"source":31,"target":35,"weight":1,"width":1},{"source":8,"target":36,"weight":1,"width":1},{"source":21,"target":37,"weight":1,"width":1},{"source":14,"target":38,"weight":1,"width":1},{"source":4,"target":39,"weight":1,"width":1},{"source":4,"target":40,"weight":1,"width":1},{"source":4,"target":41,"weight":1,"width":1},{"source":4,"target":42,"weight":1,"width":1},{"source":4,"target":38,"weight":1,"width":1},{"source":3,"target":34,"weight":1,"width":1},{"source":3,"target":43,"weight":1,"width":1},{"source":28,"target":44,"weight":1,"width":1},{"source":28,"target":45,"weight":1,"width":1},{"source":27,"target":37,"weight":1,"width":1},{"source":17,"target":39,"weight":1,"width":1},{"source":17,"target":40,"weight":1,"width":1},{"source":17,"target":41,"weight":1,"width":1},{"source":17,"target":42,"weight":1,"width":1},{"source":17,"target":38,"weight":1,"width":1},{"source":38,"target":22,"weight":1,"width":1},{"source":38,"target":23,"weight":1,"width":1},{"source":38,"target":24,"weight":1,"width":1},{"source":32,"target":46,"weight":1,"width":1},{"source":34,"target":46,"weight":1,"width":1},{"source":26,"target":20,"weight":1,"width":1},{"source":12,"target":37,"weight":1,"width":1},{"source":18,"target":47,"weight":1,"width":1},{"source":2,"target":48,"weight":1,"width":1},{"source":2,"target":49,"weight":1,"width":1},{"source":2,"target":50,"weight":1,"width":1},{"source":2,"target":51,"weight":1,"width":1},{"source":2,"target":52,"weight":1,"width":1},{"source":51,"target":19,"weight":1,"width":1},{"source":52,"target":28,"weight":1,"width":1},{"source":52,"target":53,"weight":1,"width":1},{"source":15,"target":48,"weight":1,"width":1},{"source":15,"target":49,"weight":1,"width":1},{"source":15,"target":50,"weight":1,"width":1},{"source":15,"target":51,"weight":1,"width":1},{"source":50,"target":49,"weight":1,"width":1},{"source":43,"target":54,"weight":1,"width":1},{"source":43,"target":34,"weight":1,"width":1},{"source":36,"target":8,"weight":1,"width":1},{"source":54,"target":34,"weight":1,"width":1},{"source":54,"target":55,"weight":1,"width":1},{"source":33,"target":31,"weight":1,"width":1},{"source":33,"target":56,"weight":1,"width":1},{"source":33,"target":57,"weight":1,"width":1},{"source":33,"target":58,"weight":1,"width":1},{"source":33,"target":59,"weight":1,"width":1},{"source":33,"target":60,"weight":1,"width":1},{"source":55,"target":61,"weight":1,"width":1},{"source":55,"target":34,"weight":1,"width":1},{"source":56,"target":62,"weight":1,"width":1},{"source":30,"target":29,"weight":1,"width":1},{"source":49,"target":63,"weight":1,"width":1},{"source":63,"target":64,"weight":1,"width":1},{"source":44,"target":65,"weight":1,"width":1},{"source":61,"target":34,"weight":1,"width":1},{"source":61,"target":66,"weight":1,"width":1},{"source":57,"target":67,"weight":1,"width":1},{"source":57,"target":68,"weight":1,"width":1},{"source":62,"target":67,"weight":1,"width":1},{"source":59,"target":54,"weight":1,"width":1},{"source":59,"target":34,"weight":1,"width":1},{"source":25,"target":37,"weight":1,"width":1},{"source":58,"target":69,"weight":1,"width":1},{"source":58,"target":70,"weight":1,"width":1},{"source":58,"target":71,"weight":1,"width":1},{"source":58,"target":72,"weight":1,"width":1},{"source":58,"target":73,"weight":1,"width":1},{"source":58,"target":74,"weight":1,"width":1},{"source":58,"target":67,"weight":1,"width":1},{"source":58,"target":75,"weight":1,"width":1},{"source":58,"target":65,"weight":1,"width":1},{"source":58,"target":76,"weight":1,"width":1},{"source":76,"target":73,"weight":1,"width":1},{"source":76,"target":77,"weight":1,"width":1},{"source":76,"target":78,"weight":1,"width":1},{"source":76,"target":79,"weight":1,"width":1},{"source":76,"target":80,"weight":1,"width":1},{"source":76,"target":81,"weight":1,"width":1},{"source":80,"target":82,"weight":1,"width":1},{"source":80,"target":83,"weight":1,"width":1},{"source":80,"target":84,"weight":1,"width":1},{"source":80,"target":71,"weight":1,"width":1},{"source":80,"target":72,"weight":1,"width":1},{"source":80,"target":85,"weight":1,"width":1},{"source":80,"target":86,"weight":1,"width":1},{"source":80,"target":87,"weight":1,"width":1},{"source":80,"target":75,"weight":1,"width":1},{"source":80,"target":88,"weight":1,"width":1},{"source":80,"target":89,"weight":1,"width":1},{"source":80,"target":45,"weight":1,"width":1},{"source":80,"target":90,"weight":1,"width":1},{"source":80,"target":91,"weight":1,"width":1},{"source":80,"target":92,"weight":1,"width":1},{"source":80,"target":81,"weight":1,"width":1},{"source":67,"target":44,"weight":1,"width":1},{"source":67,"target":45,"weight":1,"width":1},{"source":69,"target":93,"weight":1,"width":1},{"source":69,"target":70,"weight":1,"width":1},{"source":69,"target":73,"weight":1,"width":1},{"source":69,"target":94,"weight":1,"width":1},{"source":69,"target":76,"weight":1,"width":1},{"source":69,"target":95,"weight":1,"width":1},{"source":79,"target":96,"weight":1,"width":1},{"source":79,"target":97,"weight":1,"width":1},{"source":79,"target":98,"weight":1,"width":1},{"source":98,"target":85,"weight":1,"width":1},{"source":98,"target":99,"weight":1,"width":1},{"source":98,"target":45,"weight":1,"width":1},{"source":66,"target":100,"weight":1,"width":1},{"source":66,"target":34,"weight":1,"width":1},{"source":35,"target":54,"weight":1,"width":1},{"source":35,"target":34,"weight":1,"width":1},{"source":100,"target":34,"weight":1,"width":1},{"source":100,"target":101,"weight":1,"width":1},{"source":101,"target":102,"weight":1,"width":1},{"source":101,"target":34,"weight":1,"width":1},{"source":94,"target":85,"weight":1,"width":1},{"source":94,"target":97,"weight":1,"width":1},{"source":78,"target":79,"weight":1,"width":1},{"source":102,"target":34,"weight":1,"width":1},{"source":102,"target":103,"weight":1,"width":1},{"source":95,"target":82,"weight":1,"width":1},{"source":95,"target":83,"weight":1,"width":1},{"source":95,"target":84,"weight":1,"width":1},{"source":95,"target":71,"weight":1,"width":1},{"source":95,"target":72,"weight":1,"width":1},{"source":95,"target":85,"weight":1,"width":1},{"source":95,"target":74,"weight":1,"width":1},{"source":95,"target":56,"weight":1,"width":1},{"source":95,"target":67,"weight":1,"width":1},{"source":95,"target":75,"weight":1,"width":1},{"source":95,"target":65,"weight":1,"width":1},{"source":95,"target":57,"weight":1,"width":1},{"source":95,"target":91,"weight":1,"width":1},{"source":95,"target":92,"weight":1,"width":1},{"source":95,"target":60,"weight":1,"width":1},{"source":103,"target":104,"weight":1,"width":1},{"source":103,"target":105,"weight":1,"width":1},{"source":104,"target":105,"weight":1,"width":1},{"source":104,"target":106,"weight":1,"width":1},{"source":106,"target":107,"weight":1,"width":1}],"num":108}} -------------------------------------------------------------------------------- /src/static/tree.json: -------------------------------------------------------------------------------- 1 | {"message":"success","data":{"tree":{"name":"go-mod-graph-charting","value":39,"children":[{"name":"github.com/gin-gonic/gin@v1.6.3","value":9,"children":[{"name":"github.com/gin-contrib/sse@v0.1.0","value":1,"children":[{"name":"github.com/stretchr/testify@v1.3.0","value":1,"children":null}]},{"name":"github.com/go-playground/validator/v10@v10.2.0","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.3.3","value":1,"children":null},{"name":"github.com/json-iterator/go@v1.1.9","value":1,"children":null},{"name":"github.com/mattn/go-isatty@v0.0.12","value":1,"children":[{"name":"golang.org/x/sys@v0.0.0-20200116001909-b77594299b42","value":1,"children":null}]},{"name":"github.com/stretchr/testify@v1.4.0","value":1,"children":[{"name":"github.com/davecgh/go-spew@v1.1.0","value":1,"children":null},{"name":"github.com/pmezard/go-difflib@v1.0.0","value":1,"children":null},{"name":"github.com/stretchr/objx@v0.1.0","value":1,"children":null},{"name":"gopkg.in/yaml.v2@v2.2.2","value":1,"children":null}]},{"name":"github.com/ugorji/go/codec@v1.1.7","value":1,"children":[{"name":"github.com/ugorji/go@v1.1.7","value":1,"children":null}]},{"name":"gopkg.in/yaml.v2@v2.2.8","value":1,"children":[{"name":"gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405","value":1,"children":null}]}]},{"name":"github.com/go-playground/validator/v10@v10.4.1","value":3,"children":[{"name":"github.com/go-playground/assert/v2@v2.0.1","value":1,"children":null},{"name":"github.com/go-playground/locales@v0.13.0","value":2,"children":[{"name":"golang.org/x/text@v0.3.2","value":1,"children":[{"name":"golang.org/x/tools@v0.0.0-20180917221912-90fa682c2a6e","value":1,"children":null}]}]},{"name":"github.com/go-playground/universal-translator@v0.17.0","value":1,"children":null},{"name":"github.com/leodido/go-urn@v1.2.0","value":1,"children":null},{"name":"golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9","value":1,"children":[{"name":"golang.org/x/sys@v0.0.0-20190412213103-97732733099d","value":1,"children":null}]}]},{"name":"github.com/golang/protobuf@v1.4.3","value":2,"children":[{"name":"google.golang.org/protobuf@v1.23.0","value":2,"children":[{"name":"github.com/golang/protobuf@v1.4.0","value":2,"children":[{"name":"google.golang.org/protobuf@v1.21.0","value":2,"children":[{"name":"github.com/golang/protobuf@v1.4.0-rc.4.0.20200313231945-b860323f09d0","value":2,"children":[{"name":"google.golang.org/protobuf@v1.20.1-0.20200309200217-e05f789c0967","value":2,"children":[{"name":"github.com/golang/protobuf@v1.4.0-rc.2","value":2,"children":[{"name":"google.golang.org/protobuf@v0.0.0-20200228230310-ab0ca4ff8a60","value":2,"children":[{"name":"github.com/golang/protobuf@v1.4.0-rc.1.0.20200221234624-67d41d38c208","value":3,"children":[{"name":"google.golang.org/protobuf@v0.0.0-20200221191635-4d8936d0db64","value":2,"children":[{"name":"github.com/golang/protobuf@v1.4.0-rc.1","value":2,"children":[{"name":"google.golang.org/protobuf@v0.0.0-20200109180630-ec00e32a8dfd","value":1,"children":[{"name":"github.com/google/go-cmp@v0.3.0","value":1,"children":null}]}]},{"name":"github.com/google/go-cmp@v0.3.1","value":1,"children":null}]}]}]}]}]}]}]}]}]}]},{"name":"github.com/json-iterator/go@v1.1.10","value":1,"children":[{"name":"github.com/davecgh/go-spew@v1.1.1","value":1,"children":null},{"name":"github.com/google/gofuzz@v1.0.0","value":1,"children":null},{"name":"github.com/modern-go/concurrent@v0.0.0-20180228061459-e0a39a4cb421","value":1,"children":null},{"name":"github.com/modern-go/reflect2@v0.0.0-20180701023420-4b7aa43c6742","value":1,"children":null}]},{"name":"github.com/leodido/go-urn@v1.2.1","value":2,"children":[{"name":"github.com/stretchr/testify@v1.6.1","value":1,"children":[{"name":"gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c","value":1,"children":null}]}]},{"name":"github.com/modern-go/concurrent@v0.0.0-20180306012644-bacd9c7ef1dd","value":1,"children":null},{"name":"github.com/modern-go/reflect2@v1.0.1","value":1,"children":null},{"name":"github.com/ugorji/go@v1.2.2","value":1,"children":[{"name":"github.com/ugorji/go/codec@v1.2.2","value":1,"children":null}]},{"name":"golang.org/x/crypto@v0.0.0-20201221181555-eec23a3978ad","value":3,"children":[{"name":"golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3","value":2,"children":[{"name":"golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2","value":1,"children":[{"name":"golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a","value":1,"children":null}]},{"name":"golang.org/x/text@v0.3.0","value":1,"children":null}]},{"name":"golang.org/x/sys@v0.0.0-20191026070338-33540a1f6037","value":1,"children":null},{"name":"golang.org/x/term@v0.0.0-20201117132131-f5c789dd3221","value":1,"children":null}]},{"name":"golang.org/x/sys@v0.0.0-20201223074533-0d417f636930","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.25.0","value":9,"children":[{"name":"github.com/golang/protobuf@v1.4.1","value":1,"children":[{"name":"github.com/google/go-cmp@v0.4.0","value":1,"children":null},{"name":"google.golang.org/protobuf@v1.22.0","value":1,"children":null}]},{"name":"github.com/google/go-cmp@v0.5.0","value":1,"children":[{"name":"golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543","value":1,"children":null}]},{"name":"google.golang.org/genproto@v0.0.0-20200526211855-cb27e3aa2013","value":12,"children":[{"name":"golang.org/x/lint@v0.0.0-20190313153728-d0100b6bd8b3","value":1,"children":[{"name":"golang.org/x/tools@v0.0.0-20190311212946-11955173bddd","value":1,"children":null}]},{"name":"golang.org/x/tools@v0.0.0-20190524140312-2c0ae7006135","value":1,"children":[{"name":"golang.org/x/net@v0.0.0-20190311183353-d8887717615a","value":1,"children":null},{"name":"golang.org/x/sync@v0.0.0-20190423024810-112230192c58","value":1,"children":null}]},{"name":"google.golang.org/grpc@v1.27.0","value":9,"children":[{"name":"github.com/envoyproxy/go-control-plane@v0.9.1-0.20191026205805-5f8ba28d4473","value":1,"children":[{"name":"github.com/census-instrumentation/opencensus-proto@v0.2.1","value":1,"children":null},{"name":"github.com/prometheus/client_model@v0.0.0-20190812154241-14fe0d1b01d4","value":1,"children":null},{"name":"google.golang.org/grpc@v1.23.0","value":1,"children":null}]},{"name":"github.com/envoyproxy/protoc-gen-validate@v0.1.0","value":1,"children":null},{"name":"github.com/golang/glog@v0.0.0-20160126235308-23def4e6c14b","value":1,"children":null},{"name":"github.com/golang/mock@v1.1.1","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.3.2","value":1,"children":null},{"name":"github.com/google/go-cmp@v0.2.0","value":1,"children":null},{"name":"golang.org/x/oauth2@v0.0.0-20180821212333-d2e6202438be","value":1,"children":null},{"name":"google.golang.org/genproto@v0.0.0-20190819201941-24fa4b261c55","value":15,"children":[{"name":"golang.org/x/exp@v0.0.0-20190121172915-509febef88a4","value":1,"children":null},{"name":"golang.org/x/lint@v0.0.0-20190227174305-5b3e6a55c961","value":1,"children":null},{"name":"golang.org/x/tools@v0.0.0-20190226205152-f727befe758c","value":2,"children":[{"name":"golang.org/x/net@v0.0.0-20190213061140-3a22650c66bd","value":1,"children":null},{"name":"golang.org/x/sync@v0.0.0-20181108010431-42b317875d0f","value":1,"children":null},{"name":"google.golang.org/appengine@v1.4.0","value":1,"children":[{"name":"golang.org/x/net@v0.0.0-20180724234803-3673e40ba225","value":1,"children":null}]}]},{"name":"google.golang.org/grpc@v1.19.0","value":1,"children":[{"name":"cloud.google.com/go@v0.26.0","value":1,"children":null},{"name":"github.com/BurntSushi/toml@v0.3.1","value":1,"children":null},{"name":"github.com/client9/misspell@v0.3.4","value":1,"children":null},{"name":"github.com/golang/protobuf@v1.2.0","value":1,"children":null},{"name":"golang.org/x/lint@v0.0.0-20181026193005-c67002cb31c3","value":1,"children":null},{"name":"golang.org/x/net@v0.0.0-20180826012351-8a410e7b638d","value":1,"children":null},{"name":"golang.org/x/sync@v0.0.0-20180314180146-1d60e4601c6f","value":1,"children":null},{"name":"golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522","value":1,"children":null},{"name":"golang.org/x/tools@v0.0.0-20190114222345-bf090417da8b","value":1,"children":null},{"name":"google.golang.org/appengine@v1.1.0","value":1,"children":null},{"name":"google.golang.org/genproto@v0.0.0-20180817151627-c66870c02cf8","value":1,"children":null}]},{"name":"honnef.co/go/tools@v0.0.0-20190102054323-c2f93a96b099","value":1,"children":null}]}]},{"name":"google.golang.org/protobuf@v1.23.1-0.20200526195155-81db48ad09cc","value":1,"children":null},{"name":"honnef.co/go/tools@v0.0.0-20190523083050-ea95bdfd59fc","value":1,"children":null}]}]},{"name":"gopkg.in/yaml.v2@v2.4.0","value":1,"children":null}]},"depth":14,"width":26}} -------------------------------------------------------------------------------- /src/temp-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | 5 | 6 | 7 | /* 8 | * SplitChunksPlugin is enabled by default and replaced 9 | * deprecated CommonsChunkPlugin. It automatically identifies modules which 10 | * should be splitted of chunk by heuristics using module duplication count and 11 | * module category (i. e. node_modules). And splits the chunks… 12 | * 13 | * It is safe to remove "splitChunks" from the generated configuration 14 | * and was added as an educational example. 15 | * 16 | * https://webpack.js.org/plugins/split-chunks-plugin/ 17 | * 18 | */ 19 | 20 | /* 21 | * We've enabled TerserPlugin for you! This minifies your app 22 | * in order to load faster and run less javascript. 23 | * 24 | * https://github.com/webpack-contrib/terser-webpack-plugin 25 | * 26 | */ 27 | 28 | const TerserPlugin = require('terser-webpack-plugin'); 29 | 30 | 31 | /* 32 | * webpack Html Plugin 33 | */ 34 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 35 | 36 | 37 | /* 38 | * 引入 ParallelUglifyPlugin 插件 39 | */ 40 | const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin'); 41 | 42 | 43 | /* 44 | * 引入自定义插件 45 | */ 46 | const PackAllInGoPlugin = require('./plugin/pack-all-in-go-plugin'); 47 | 48 | 49 | const isDev = process.env.NODE_ENV === 'development' 50 | 51 | 52 | config = { 53 | mode: 'development', 54 | devtool: false, // 编译成果 保留换行 55 | plugins: [ 56 | new HtmlWebpackPlugin({ 57 | title: 'go mod graph charting', 58 | filename: 'index.html', 59 | template: './src/temp-index.html' 60 | }), 61 | new ParallelUglifyPlugin({ 62 | // 传递给 UglifyJS的参数如下: 63 | uglifyJS: { 64 | output: { 65 | /* 66 | 是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果, 67 | 可以设置为false 68 | */ 69 | beautify: true, 70 | /* 71 | 是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false 72 | */ 73 | comments: false 74 | }, 75 | compress: { 76 | /* 77 | 是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,可以设置为false关闭这些作用 78 | 不大的警告 79 | */ 80 | warnings: false, 81 | 82 | /* 83 | 是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句 84 | */ 85 | drop_console: true, 86 | 87 | /* 88 | 是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不 89 | 转换,为了达到更好的压缩效果,可以设置为false 90 | */ 91 | collapse_vars: true, 92 | 93 | /* 94 | 是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx' 转换成 95 | var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false 96 | */ 97 | reduce_vars: true 98 | }, 99 | beautify: { 100 | semicolons: false 101 | } 102 | }, 103 | test: /.js$/g, 104 | include: [], 105 | exclude: [], 106 | cacheDir: '', 107 | workerCount: '', 108 | sourceMap: false 109 | }), 110 | new webpack.ProgressPlugin(), 111 | new PackAllInGoPlugin({options: true}) 112 | ], 113 | 114 | module: { 115 | rules: [{ 116 | test: /.css$/, 117 | 118 | use: [{ 119 | loader: "style-loader" 120 | }, { 121 | loader: "css-loader", 122 | 123 | options: { 124 | sourceMap: true 125 | } 126 | }] 127 | }] 128 | }, 129 | 130 | optimization: { 131 | minimizer: [new TerserPlugin({ 132 | terserOptions: { 133 | comments: false 134 | }, 135 | extractComments: false 136 | })], 137 | 138 | splitChunks: { 139 | cacheGroups: { 140 | vendors: { 141 | priority: -10, 142 | test: /[\\/]node_modules[\\/]/ 143 | } 144 | }, 145 | 146 | chunks: 'async', 147 | minChunks: 1, 148 | minSize: 30000, 149 | name: false 150 | } 151 | } 152 | } 153 | 154 | 155 | if (isDev) { 156 | config.devServer = { 157 | host: '0.0.0.0', 158 | contentBase: path.join(__dirname, 'src', 'static'), 159 | open: true, 160 | port: 8080, 161 | overlay: { 162 | errors: true 163 | } 164 | } 165 | } else { 166 | } 167 | 168 | 169 | module.exports = config 170 | --------------------------------------------------------------------------------