Skip to content

Commit

Permalink
feat(mermaid): add a new output format
Browse files Browse the repository at this point in the history
  • Loading branch information
phiz71 committed Apr 14, 2022
1 parent 5671441 commit 8436913
Show file tree
Hide file tree
Showing 26 changed files with 957 additions and 1 deletion.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This Maven plugin generates dependency graphs on single modules or in an aggrega
DOT files can be visualized with [Graphviz](http://www.graphviz.org/). When [Graphviz](http://www.graphviz.org/) is installed, the generated `.dot` files can be directly rendered into all supported image formats.
- `.gml` (Graph Markup Language)<br/>
GML files can be visualized with the [yEd Graph Editor](https://www.yworks.com/products/yed) which allows further processing and layouting of the dependency graph.
- `.mmd` (Mermaid)<br/>
Mermaid graphes can be easily embedded in application and in markdown files. See [here](https://mermaid-js.github.io/mermaid/#/).
- `.puml` (PlantUML)<br/>
PlantUML files can be visualized by various tools like [planttext.com](https://www.planttext.com/) or in IntelliJ with the [PlantUML Plugin](https://plugins.jetbrains.com/plugin/7017-plantuml-integration).
- `.json`<br/>
Expand Down Expand Up @@ -154,6 +156,47 @@ Since the generated dependency graph does not store any layout information, you
- Choose *Tools -> Fit Node To Label* and press *OK* in the upcoming dialog
- Choose your layout algorithm in the *Layout* menu to layout the graph


#### Mermaid

Mermaid graphes can be easily embedded in application and in markdown files. See [here](https://mermaid-js.github.io/mermaid/#/).

```mermaid
flowchart TD
%% Node Definitions:
com.github.ferstl:module-1:jar["module-1<br/>1.0.0-SNAPSHOT"]
commons-codec:commons-codec:jar["commons-codec<br/>1.10"]
org.apache.commons:commons-lang3:jar["commons-lang3<br/>3.1"]
com.github.ferstl:module-3:jar["module-3<br/>1.0.0-SNAPSHOT"]
com.github.ferstl:module-2:jar["module-2<br/>1.0.0-SNAPSHOT"]
com.google.guava:guava:jar["guava<br/>30.1.1-jre"]
com.mysema.querydsl:querydsl-core:jar["querydsl-core<br/>3.7.4"]
com.google.code.findbugs:jsr305:jar["jsr305<br/>1.3.9"]
com.mysema.commons:mysema-commons-lang:jar["mysema-commons-lang<br/>0.2.4"]
com.infradna.tool:bridge-method-annotation:jar["bridge-method-annotation<br/>1.13"]
%% Edge Definitions:
com.github.ferstl:module-1:jar --> commons-codec:commons-codec:jar
com.github.ferstl:module-1:jar --> org.apache.commons:commons-lang3:jar
com.github.ferstl:module-3:jar --> com.github.ferstl:module-1:jar
com.github.ferstl:module-2:jar --> com.github.ferstl:module-1:jar
com.github.ferstl:module-2:jar --> com.google.guava:guava:jar
com.github.ferstl:module-2:jar --> commons-codec:commons-codec:jar
com.github.ferstl:module-2:jar --3.0--> org.apache.commons:commons-lang3:jar
com.github.ferstl:module-3:jar --> com.github.ferstl:module-2:jar
com.mysema.querydsl:querydsl-core:jar --> com.google.guava:guava:jar
com.mysema.querydsl:querydsl-core:jar --> com.google.code.findbugs:jsr305:jar
com.mysema.querydsl:querydsl-core:jar --> com.mysema.commons:mysema-commons-lang:jar
com.mysema.querydsl:querydsl-core:jar --> com.infradna.tool:bridge-method-annotation:jar
com.github.ferstl:module-3:jar --> com.mysema.querydsl:querydsl-core:jar
%% Edge Styles:
linkStyle 3 color:#000000, stroke:#000000, stroke-dasharray:3px
linkStyle 5 color:#000000, stroke:#000000, stroke-dasharray:3px
linkStyle 6 color:#FF0000, stroke:#FF0000, stroke-dasharray:10px
linkStyle 8 color:#000000, stroke:#000000, stroke-dasharray:3px
```

#### PlantUML

PlantUML graphs can be visualized with various tools, e.g. [planttext.com](https://www.planttext.com/) or the [PlantUML Integration](https://plugins.jetbrains.com/plugin/7017-plantuml-integration) for IntelliJ (requires [Graphviz](http://www.graphviz.org/) for rendering).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Pattern;

import com.github.ferstl.depgraph.dependency.mermaid.MermaidGraphStyleConfigurer;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
Expand Down Expand Up @@ -69,7 +71,7 @@ abstract class AbstractGraphMojo extends AbstractMojo {
private static final String OUTPUT_FILE_NAME = "dependency-graph";

/**
* Format of the graph, either &quot;dot&quot; (default), &quot;gml&quot;, &quot;puml&quot;, &quot;json&quot; or &quot;text&quot;.
* Format of the graph, either &quot;dot&quot; (default), &quot;gml&quot;, &quot;puml&quot;, &quot;mermaid&quot;, &quot;json&quot; or &quot;text&quot;.
*
* @since 2.1.0
*/
Expand Down Expand Up @@ -260,6 +262,8 @@ private GraphStyleConfigurer createGraphStyleConfigurer(GraphFormat graphFormat)
return new PumlGraphStyleConfigurer();
case JSON:
return new JsonGraphStyleConfigurer();
case MERMAID:
return new MermaidGraphStyleConfigurer();
case TEXT:
return new TextGraphStyleConfigurer();
default:
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/github/ferstl/depgraph/GraphFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ public enum GraphFormat {
GML,
PUML,
JSON,
MERMAID {
@Override
public String getFileExtension() {
return ".mmd";
}
},
TEXT {
@Override
public String getFileExtension() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2014 - 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.ferstl.depgraph.dependency.mermaid;

import com.github.ferstl.depgraph.dependency.DependencyNode;
import com.github.ferstl.depgraph.dependency.NodeResolution;
import com.github.ferstl.depgraph.graph.EdgeRenderer;

import static com.github.ferstl.depgraph.dependency.VersionAbbreviator.abbreviateVersion;


public class MermaidDependencyEdgeRenderer implements EdgeRenderer<DependencyNode> {

public static final String DUPLICATE_PREFIX = "+";
public static final String CONFLICT_PREFIX = "*";
private final boolean renderVersions;

public MermaidDependencyEdgeRenderer(boolean renderVersions) {
this.renderVersions = renderVersions;
}

@Override
public String render(DependencyNode from, DependencyNode to) {
NodeResolution toResolution = to.getResolution();
switch (toResolution) {
case OMITTED_FOR_CONFLICT:
return CONFLICT_PREFIX + (this.renderVersions ? abbreviateVersion(to.getArtifact().getVersion()) : "");
case OMITTED_FOR_DUPLICATE:
return DUPLICATE_PREFIX;
}
return "";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2014 - 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.ferstl.depgraph.dependency.mermaid;

import com.github.ferstl.depgraph.dependency.DependencyNode;
import com.github.ferstl.depgraph.dependency.dot.style.StyleConfiguration;
import com.github.ferstl.depgraph.dependency.dot.style.StyleKey;
import com.github.ferstl.depgraph.graph.NodeRenderer;
import com.google.common.base.Joiner;
import org.apache.maven.artifact.Artifact;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

import static org.apache.maven.artifact.Artifact.SCOPE_COMPILE;


public class MermaidDependencyNodeNameRenderer implements NodeRenderer<DependencyNode> {

private static final Joiner SLASH_JOINER = Joiner.on("/").skipNulls();
private static final Joiner NEWLINE_JOINER = Joiner.on("<br/>").skipNulls();

private final boolean showGroupId;
private final boolean showArtifactId;
private final boolean showTypes;
private final boolean showClassifiers;
private final boolean showVersion;
private final boolean showOptional;
private final boolean showScope;

public MermaidDependencyNodeNameRenderer(boolean showGroupId, boolean showArtifactId, boolean showTypes, boolean showClassifiers, boolean showVersion, boolean showOptional, boolean showScope) {
this.showGroupId = showGroupId;
this.showArtifactId = showArtifactId;
this.showTypes = showTypes;
this.showClassifiers = showClassifiers;
this.showVersion = showVersion;
this.showOptional = showOptional;
this.showScope = showScope;
}

@Override
public String render(DependencyNode node) {

Collection<String> items = new ArrayList<>();
if (node.getArtifact().isOptional() && showOptional) {
items.add(printWithSmallFont("#lt;optional#gt;"));
}
if (showGroupId) {
items.add(node.getArtifact().getGroupId());
}
if (showArtifactId) {
items.add(node.getArtifact().getArtifactId());
}
if (showVersion) {
items.add(node.getEffectiveVersion());
}
if (showTypes) {
items.add(createTypeString(node.getTypes()));
}
if (showClassifiers) {
items.add(createClassifierString(node.getClassifiers()));
}
if (showScope) {
items.add(createScopeString(node.getScopes()));
}
if (items.isEmpty()) {
return "[\" \"]";
}

return "[\"" + NEWLINE_JOINER.join(items) + "\"]";
}

private static String createScopeString(Set<String> scopes) {
if (!scopes.isEmpty() && (scopes.size() > 1 || !scopes.contains(SCOPE_COMPILE))) {
return printWithSmallFont("(" + SLASH_JOINER.join(scopes) + ")");
}

return null;
}

private static String createTypeString(Set<String> types) {
if (types.size() > 1 || !types.contains("jar")) {
types.forEach(type -> type = "." + type);

return SLASH_JOINER.join(types.stream().map(type -> "." + type).collect(Collectors.toList()));
}

return null;
}

private static String createClassifierString(Set<String> classifiers) {
if( classifiers.size() > 1 ) {
return SLASH_JOINER.join(classifiers);
}

return null;
}

private static String printWithSmallFont(String stringToPrint) {
return "<font size=1>" + stringToPrint + "</font>";
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2014 - 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.ferstl.depgraph.dependency.mermaid;


import com.github.ferstl.depgraph.dependency.AbstractGraphStyleConfigurer;
import com.github.ferstl.depgraph.dependency.DependencyNode;
import com.github.ferstl.depgraph.dependency.dot.style.StyleConfiguration;
import com.github.ferstl.depgraph.graph.GraphBuilder;
import com.github.ferstl.depgraph.graph.mermaid.MermaidGraphFormatter;

public class MermaidGraphStyleConfigurer extends AbstractGraphStyleConfigurer {

@Override
public GraphBuilder<DependencyNode> configure(GraphBuilder<DependencyNode> graphBuilder) {
return graphBuilder
.useNodeNameRenderer(new MermaidDependencyNodeNameRenderer(this.showGroupId, this.showArtifactId, this.showTypes, this.showClassifiers, this.showVersionsOnNodes, this.showOptional, this.showScope))
.useEdgeRenderer(new MermaidDependencyEdgeRenderer(this.showVersionOnEdges))
.graphFormatter(new MermaidGraphFormatter());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2014 - 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.ferstl.depgraph.graph.mermaid;

public class MermaidEdgeStyle {
private static final String DUPLICATE_COLOR = "#000000"; // lightGray
private static final String CONFLICT_COLOR = "#FF0000"; // red

private int index;
private String color;
private int strokeSize;

private MermaidEdgeStyle() {}

private MermaidEdgeStyle(int index, String color, int strokeSize) {
this.index = index;
this.color = color;
this.strokeSize = strokeSize;
}

public static MermaidEdgeStyle createConflictStyle(int index) {
return new MermaidEdgeStyle(index, CONFLICT_COLOR, 10);
}

public static MermaidEdgeStyle createDuplicateStyle(int index) {
return new MermaidEdgeStyle(index, DUPLICATE_COLOR, 3);
}

@Override
public String toString() {
return "linkStyle " + index + " color:" + color + ", stroke:" + color + ", stroke-dasharray:" + strokeSize + "px";
}
}
Loading

0 comments on commit 8436913

Please sign in to comment.