|
1 | 1 |
|
2 |
| -function treeWalk(name, node, stopTreewalkPrefix, showUnprefixedDependencies) { |
| 2 | +function treeWalk(name, node, stopTreewalkPrefix, showUnprefixedDependencies, depVersions) { |
3 | 3 | let result = "";
|
4 |
| - const depVersions = new Map(); |
5 | 4 | const version = node.version;
|
6 |
| - const lastDepVersion = depVersions.get(name); |
7 | 5 | 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 | + } |
13 | 15 | }
|
14 |
| - if (version !== undefined) depVersions.set(name, version); |
15 | 16 | for (const depName in node.dependencies) {
|
16 | 17 | const dependency = node.dependencies[depName];
|
17 | 18 | const depNodeName = `${depName}\\n${dependency.version}`;
|
18 | 19 | if (stopTreewalkPrefix === undefined || depName.startsWith(stopTreewalkPrefix)) {
|
19 | 20 | result += ` "${nodeName}" -> "${depNodeName}"\n`;
|
20 |
| - result += treeWalk(depName, dependency, stopTreewalkPrefix, showUnprefixedDependencies); |
| 21 | + result += treeWalk(depName, dependency, stopTreewalkPrefix, showUnprefixedDependencies, depVersions); |
21 | 22 | } else if (showUnprefixedDependencies) {
|
22 | 23 | result += ` "${nodeName}" -> "${depNodeName}"\n`;
|
23 | 24 | }
|
24 | 25 | }
|
25 | 26 | return result;
|
26 | 27 | }
|
27 | 28 |
|
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} |
34 | 59 | }
|
35 | 60 | `;
|
36 | 61 | };
|
0 commit comments