Skip to content
This repository was archived by the owner on Apr 8, 2021. It is now read-only.

Commit eac5115

Browse files
Pawel Cejrowskipcejrowski
authored andcommitted
Added dependencyBrowseTreeHTML and dependencyBrowseTree tasks
1 parent 5ef1db0 commit eac5115

File tree

5 files changed

+123
-8
lines changed

5 files changed

+123
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ the notes of version [0.8.2](https://github.com/jrudolph/sbt-dependency-graph/tr
2121

2222
## Main Tasks
2323

24+
* `dependencyBrowseTree`: Opens a browser window with a visualization of the dependency tree (courtesy of jstree).
2425
* `dependencyTree`: Shows an ASCII tree representation of the project's dependencies
2526
* `dependencyBrowseGraph`: Opens a browser window with a visualization of the dependency graph (courtesy of graphlib-dot + dagre-d3).
2627
* `dependencyList`: Shows a flat list of all transitive dependencies on the sbt console (sorted by organization and name)

src/main/resources/tree.html

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>dependencyBrowseTree</title>
6+
7+
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
8+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
9+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
10+
<script src="tree.data.js"></script>
11+
12+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"/>
13+
14+
<style>
15+
#input-field {
16+
display: inline;
17+
}
18+
#tree_div {
19+
font-family: monospace
20+
}
21+
</style>
22+
</head>
23+
<body>
24+
<h1>Dependencies</h1>
25+
Search: <input type="search" id="input-field" value="">
26+
<div id="tree_div" class="jstree-no-icons"></div>
27+
28+
<script>
29+
$(function() {
30+
$('#tree_div').jstree({
31+
"plugins": ["search", "sort"],
32+
"core": {
33+
"data": tree_data
34+
}
35+
});
36+
var to = false;
37+
$('#input-field').keyup(function() {
38+
if (to) {
39+
clearTimeout(to);
40+
}
41+
to = setTimeout(function() {
42+
var v = $('#input-field').val();
43+
$('#tree_div').jstree(true).search(v);
44+
}, 250);
45+
});
46+
});
47+
</script>
48+
</body>
49+
</html>

src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphKeys.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ trait DependencyGraphKeys {
4949
val dependencyBrowseGraph = TaskKey[URI](
5050
"dependency-browse-graph",
5151
"Opens an HTML page that can be used to view the graph.")
52+
val dependencyBrowseTreeTarget = SettingKey[File](
53+
"dependency-browse-tree-target",
54+
"The location dependency browse tree files should be put.")
55+
val dependencyBrowseTreeHTML = TaskKey[URI](
56+
"dependency-browse-tree-html",
57+
"Creates an HTML page that can be used to view the dependency tree")
58+
val dependencyBrowseTree = TaskKey[URI](
59+
"dependency-browse-tree",
60+
"Opens an HTML page that can be used to view the dependency tree")
5261
val moduleGraph = TaskKey[ModuleGraph](
5362
"module-graph",
5463
"The dependency graph for a project")
@@ -97,4 +106,4 @@ trait DependencyGraphKeys {
97106
private[graph] val crossProjectId = SettingKey[ModuleID]("dependency-graph-cross-project-id")
98107
}
99108

100-
object DependencyGraphKeys extends DependencyGraphKeys
109+
object DependencyGraphKeys extends DependencyGraphKeys

src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import sbt._
2222
import Keys._
2323
import sbt.complete.Parser
2424
import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport }
25-
import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML }
25+
import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML, TreeView }
2626
import net.virtualvoid.sbt.graph.util.IOUtil
2727
import internal.librarymanagement._
2828
import librarymanagement._
@@ -74,12 +74,10 @@ object DependencyGraphSettings {
7474
dependencyDot := writeToFile(dependencyDotString, dependencyDotFile).value,
7575
dependencyBrowseGraphTarget := { target.value / "browse-dependency-graph" },
7676
dependencyBrowseGraphHTML := browseGraphHTMLTask.value,
77-
dependencyBrowseGraph := {
78-
val uri = dependencyBrowseGraphHTML.value
79-
streams.value.log.info("Opening in browser...")
80-
java.awt.Desktop.getDesktop.browse(uri)
81-
uri
82-
},
77+
dependencyBrowseGraph := openBrowser(dependencyBrowseGraphHTML).value,
78+
dependencyBrowseTreeTarget := { target.value / "browse-dependency-tree" },
79+
dependencyBrowseTreeHTML := browseTreeHTMLTask.value,
80+
dependencyBrowseTree := openBrowser(dependencyBrowseTreeHTML).value,
8381
dependencyList := printFromGraph(rendering.FlatList.render(_, _.id.idString)).value,
8482
dependencyStats := printFromGraph(rendering.Statistics.renderModuleStatsList).value,
8583
dependencyDotHeader :=
@@ -139,6 +137,14 @@ object DependencyGraphSettings {
139137
link
140138
}
141139

140+
def browseTreeHTMLTask =
141+
Def.task {
142+
val renderedTree = TreeView.createJson(moduleGraph.value)
143+
val link = TreeView.createLink(renderedTree, target.value)
144+
streams.value.log.info(s"HTML tree written to $link")
145+
link
146+
}
147+
142148
def writeToFile(dataTask: TaskKey[String], fileTask: SettingKey[File]) =
143149
Def.task {
144150
val outFile = fileTask.value
@@ -156,6 +162,14 @@ object DependencyGraphSettings {
156162
def printFromGraph(f: ModuleGraph String) =
157163
Def.task { streams.value.log.info(f(moduleGraph.value)) }
158164

165+
def openBrowser(uriKey: TaskKey[URI]) =
166+
Def.task {
167+
val uri = uriKey.value
168+
streams.value.log.info("Opening in browser...")
169+
java.awt.Desktop.getDesktop.browse(uri)
170+
uri
171+
}
172+
159173
def showLicenseInfo(graph: ModuleGraph, streams: TaskStreams): Unit = {
160174
val output =
161175
graph.nodes.filter(_.isUsed).groupBy(_.license).toSeq.sortBy(_._1).map {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package net.virtualvoid.sbt.graph.rendering
2+
3+
import java.io.File
4+
import java.net.URI
5+
6+
import net.virtualvoid.sbt.graph.util.IOUtil
7+
import net.virtualvoid.sbt.graph.{ Module, ModuleGraph }
8+
9+
import scala.util.parsing.json.{ JSONArray, JSONObject }
10+
11+
object TreeView {
12+
def createJson(graph: ModuleGraph): String = {
13+
val trees = graph.roots
14+
.map(module processSubtree(graph, module))
15+
.toList
16+
JSONArray(trees).toString
17+
}
18+
19+
def createLink(graphJson: String, targetDirectory: File): URI = {
20+
targetDirectory.mkdirs()
21+
val graphHTML = new File(targetDirectory, "tree.html")
22+
IOUtil.saveResource("tree.html", graphHTML)
23+
IOUtil.writeToFile(graphJson, new File(targetDirectory, "tree.json"))
24+
IOUtil.writeToFile(s"tree_data = $graphJson;", new File(targetDirectory, "tree.data.js"))
25+
new URI(graphHTML.toURI.toString)
26+
}
27+
28+
private def processSubtree(graph: ModuleGraph, module: Module): JSONObject = {
29+
val children = graph.dependencyMap
30+
.getOrElse(module.id, List())
31+
.map(module processSubtree(graph, module))
32+
.toList
33+
moduleAsJson(module, children)
34+
}
35+
36+
private def moduleAsJson(module: Module, children: List[JSONObject]): JSONObject = {
37+
val eviction = module.evictedByVersion.map(version s" (evicted by $version)").getOrElse("")
38+
val error = module.error.map(err s" (errors: $err)").getOrElse("")
39+
val text = module.id.idString + eviction + error
40+
JSONObject(Map("text" -> text, "children" -> JSONArray(children)))
41+
}
42+
}

0 commit comments

Comments
 (0)