Skip to content

Commit 6884ffe

Browse files
author
Michael Kriegel
committed
Added clustering / highlight feature for conflicting versions
1 parent fda53cd commit 6884ffe

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ node-dependency-visualizer has the following options:
2424
| :----- | :---------- |
2525
| --treewalk-prefix (-p) PREFIX | The tree walk only continues on modules, that start with PREFIX. |
2626
| --show-leaf-dependencies (-l) | The leaf dependencies (those on which recursion stops) are only emitted when this option is set. |
27+
| --no-highlight-conflicting-versions (-c) | Does not highlight / cluster different versions of the same module. |
2728

2829
node-dependency-visualizer emits a dot digraph, which can be piped directly into graphviz dot.
2930

js/cli.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const commandLineArgs = require('command-line-args');
77
const optionDefinitions = [
88
{ name: 'treewalk-prefix', alias: 'p', type: String },
99
{ name: 'show-leaf-dependencies', alias: 'l', type: Boolean },
10+
{ name: 'no-highlight-conflicting-versions', alias: 'c', type: Boolean },
1011
];
1112

1213
const options = commandLineArgs(optionDefinitions);
@@ -22,5 +23,5 @@ ls.stdout.on("data", (chunk) => {
2223

2324
ls.stdout.on("close", () => {
2425
const tree = JSON.parse(data);
25-
process.stdout.write(treeWalk(tree, options["treewalk-prefix"], options["show-leaf-dependencies"]));
26+
process.stdout.write(treeWalk(tree, options["treewalk-prefix"], options["show-leaf-dependencies"], options["no-highlight-conflicting-versions"] !== true));
2627
});

js/tree.js

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,61 @@
11

2-
function treeWalk(name, node, stopTreewalkPrefix, showUnprefixedDependencies) {
2+
function treeWalk(name, node, stopTreewalkPrefix, showUnprefixedDependencies, depVersions) {
33
let result = "";
4-
const depVersions = new Map();
54
const version = node.version;
6-
const lastDepVersion = depVersions.get(name);
75
const nodeName = `${name}\\n${version}`;
8-
if (lastDepVersion !== undefined && lastDepVersion !== version) {
9-
const lastDepVersionNodeName = `${name}\\n${lastDepVersion}`;
10-
result += ` "${nodeName}"[fillcolor=red]\n`;
11-
result += ` "${lastDepVersionNodeName}"[fillcolor=red]\n`;
12-
result += `"${lastDepVersionNodeName}" -> "${nodeName}"[color=red arrowhead=none]`;
6+
if (depVersions !== undefined && version !== undefined) {
7+
const duplicates = depVersions.get(name);
8+
if (duplicates !== undefined) {
9+
if (duplicates.has(version) === false) duplicates.add(version);
10+
} else {
11+
const duplicates = new Set();
12+
duplicates.add(version);
13+
depVersions.set(name, duplicates);
14+
}
1315
}
14-
if (version !== undefined) depVersions.set(name, version);
1516
for (const depName in node.dependencies) {
1617
const dependency = node.dependencies[depName];
1718
const depNodeName = `${depName}\\n${dependency.version}`;
1819
if (stopTreewalkPrefix === undefined || depName.startsWith(stopTreewalkPrefix)) {
1920
result += ` "${nodeName}" -> "${depNodeName}"\n`;
20-
result += treeWalk(depName, dependency, stopTreewalkPrefix, showUnprefixedDependencies);
21+
result += treeWalk(depName, dependency, stopTreewalkPrefix, showUnprefixedDependencies, depVersions);
2122
} else if (showUnprefixedDependencies) {
2223
result += ` "${nodeName}" -> "${depNodeName}"\n`;
2324
}
2425
}
2526
return result;
2627
}
2728

28-
module.exports = function(node, stopTreewalkPrefix, showUnprefixedDependencies) {
29-
return `strict digraph DeviceTypeHierarchy_Oblamatikproducts {
30-
rankdir=BT;
31-
compound=true;
32-
node[shape=record,style=filled,fillcolor=white]
33-
${treeWalk(node.name, node, stopTreewalkPrefix, showUnprefixedDependencies)}
29+
module.exports = function(node, stopTreewalkPrefix, showUnprefixedDependencies, highlightConflictingVersions) {
30+
const depVersions = highlightConflictingVersions === true ? new Map() : undefined;
31+
const data = treeWalk(node.name, node, stopTreewalkPrefix, showUnprefixedDependencies, depVersions);
32+
let conflicts = "";
33+
if (highlightConflictingVersions) {
34+
for (const [pkgName, versions] of depVersions) {
35+
if (versions.size > 1) {
36+
conflicts += ` subgraph "cluster_${pkgName}" {
37+
node[shape=rectangle,style=filled,fillcolor=white]
38+
edge[style=invis];
39+
color=red;
40+
`;
41+
const versionsArray = Array.from(versions);
42+
while (versionsArray.length > 0) {
43+
const version = versionsArray.pop();
44+
for (let i = 0; i < versionsArray.length; i++) {
45+
const otherVersion = versionsArray[i];
46+
conflicts += ` "${pkgName}\\n${version}" -> "${pkgName}\\n${otherVersion}";\n`
47+
}
48+
}
49+
conflicts += " }\n";
50+
}
51+
}
52+
}
53+
return `strict digraph DeviceTypeHierarchy {
54+
rankdir=BT;
55+
compound=true;
56+
node[shape=rectangle,style=filled,fillcolor=white]
57+
${conflicts}
58+
${data}
3459
}
3560
`;
3661
};

0 commit comments

Comments
 (0)