Skip to content

Commit

Permalink
feat(report): links to npmjs/ nodejs.org for npm respectively node co…
Browse files Browse the repository at this point in the history
…re modules (#854)

## Description

- for npm modules in the dot reporters link to npmjs.com
- for node modules link to nodejs.org

## Motivation and Context

Fixes #852 

## How Has This Been Tested?

- [x] green ci
- [x] additional automated integration tests

## Types of changes

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Documentation only change
- [ ] Refactor (non-breaking change which fixes an issue without
changing functionality)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
  • Loading branch information
sverweij committed Oct 20, 2023
1 parent 1775912 commit 08dce74
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 64 deletions.
55 changes: 21 additions & 34 deletions src/report/dot/module-utl.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { basename, sep, dirname, join } from "node:path/posix";
import { basename, sep, dirname } from "node:path/posix";
import has from "lodash/has.js";
import { formatPercentage } from "../utl/index.mjs";
import { formatPercentage, getURLForModule } from "../utl/index.mjs";
import theming from "./theming.mjs";

const PROTOCOL_PREFIX_RE = /^[a-z]+:\/\//;

function attributizeObject(pObject) {
return (
Object.keys(pObject)
Expand All @@ -25,7 +23,7 @@ function extractFirstTransgression(pModule) {
...pDependency,
rule: pDependency.rules[0],
}
: pDependency
: pDependency,
),
};
}
Expand All @@ -37,15 +35,15 @@ function applyTheme(pTheme) {
.map((pDependency) => ({
...pDependency,
themeAttrs: attributizeObject(
theming.determineAttributes(pDependency, pTheme.dependencies)
theming.determineAttributes(pDependency, pTheme.dependencies),
),
}))
.map((pDependency) => ({
...pDependency,
hasExtraAttributes: Boolean(pDependency.rule || pDependency.themeAttrs),
})),
themeAttrs: attributizeObject(
theming.determineAttributes(pModule, pTheme.modules)
theming.determineAttributes(pModule, pTheme.modules),
),
});
}
Expand All @@ -68,13 +66,14 @@ function makeInstabilityString(pModule, pShowMetrics = false) {

if (pShowMetrics && has(pModule, "instability") && !pModule.consolidated) {
lInstabilityString = ` <FONT color="#808080" point-size="8">${formatPercentage(
pModule.instability
pModule.instability,
)}</FONT>`;
}
return lInstabilityString;
}

function folderify(pShowMetrics) {
/** @param {import("../../../types/cruise-result").IModule} pModule*/
return (pModule) => {
let lAdditions = {};
let lDirectoryName = dirname(pModule.source);
Expand All @@ -86,7 +85,7 @@ function folderify(pShowMetrics) {

lAdditions.label = `<${basename(pModule.source)}${makeInstabilityString(
pModule,
pShowMetrics
pShowMetrics,
)}>`;
lAdditions.tooltip = basename(pModule.source);

Expand All @@ -98,37 +97,25 @@ function folderify(pShowMetrics) {
}

/**
* Sort of smartly concatenate the given prefix and source:
*
* if it's an uri pattern (e.g. https://yadda, file://snorkel/bla)
* simply concat.
*
* in all other cases path.posix.join the two
*
* @param {string} pPrefix - prefix
* @param {string} pSource - filename
* @return {string} prefix and filename concatenated
* @param {string} pPrefix
* @returns {URL?: string}
*/
function smartURIConcat(pPrefix, pSource) {
if (pPrefix.match(PROTOCOL_PREFIX_RE)) {
return `${pPrefix}${pSource}`;
} else {
return join(pPrefix, pSource);
}
}

function addURL(pPrefix) {
return (pModule) => ({
...pModule,
...(pModule.coreModule || pModule.couldNotResolve
? {}
: { URL: smartURIConcat(pPrefix, pModule.source) }),
});
return (pModule) => {
if (pModule.couldNotResolve) {
return pModule;
}

return {
...pModule,
URL: getURLForModule(pModule, pPrefix),
};
};
}

function makeLabel(pModule, pShowMetrics) {
return `<${dirname(pModule.source)}/<BR/><B>${basename(
pModule.source
pModule.source,
)}</B>${makeInstabilityString(pModule, pShowMetrics)}>`;
}

Expand Down
77 changes: 75 additions & 2 deletions src/report/utl/index.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { join } from "node:path/posix";

const PROTOCOL_PREFIX_RE = /^[a-z]+:\/\//;

// eslint-disable-next-line no-undefined
export const formatPercentage = new Intl.NumberFormat(undefined, {
style: "percent",
Expand All @@ -6,9 +10,78 @@ export const formatPercentage = new Intl.NumberFormat(undefined, {
export function formatViolation(
pViolation,
pViolationType2Formatter,
pDefaultFormatter
pDefaultFormatter,
) {
return (pViolationType2Formatter[pViolation.type] || pDefaultFormatter)(
pViolation
pViolation,
);
}

/**
* Sort of smartly concatenate the given prefix and source:
*
* if it's an uri pattern (e.g. https://yadda, file://snorkel/bla)
* simply concat.
*
* in all other cases path.posix.join the two
*
* @param {string} pPrefix - prefix
* @param {string} pSource - filename
* @return {string} prefix and filename concatenated
*/
function smartURIConcat(pPrefix, pSource) {
if (pPrefix.match(PROTOCOL_PREFIX_RE)) {
return `${pPrefix}${pSource}`;
} else {
return join(pPrefix, pSource);
}
}

/**
*
* @param {string} pSource
* @returns {string}
*/
function deriveExternalPackageName(pSource) {
const lRE =
/node_modules\/(?<packageName>[^@][^/]+)|(?<atPackageName>@[^/]+\/[^/]+)/;
const lMatch = pSource.match(lRE);
if (lMatch) {
return lMatch.groups.packageName || lMatch.groups.atPackageName;
}
return "";
}

/**
* @param {string} pSource
* @returns {string}
*/
function deriveCorePackageName(pSource) {
return pSource.split("/").shift();
}

/**
*
* @param {import("../../../types/cruise-result").IModule} pModule
* @param {string} pPrefix
* @returns {string}
*/
export function getURLForModule(pModule, pPrefix) {
// TODO: derive the URLs from configuration
if (pModule.dependencyTypes?.some((pType) => pType === "core")) {
return "https://nodejs.org/api/{{packageName}}.html".replace(
"{{packageName}}",
deriveCorePackageName(pModule.source),
);
} else if (
pModule.dependencyTypes?.some((pType) => pType.startsWith("npm"))
) {
return "https://www.npmjs.com/package/{{packageName}}".replace(
"{{packageName}}",
deriveExternalPackageName(pModule.source),
);
} else if (pPrefix) {
return smartURIConcat(pPrefix, pModule.source);
}
return pModule.source;
}
6 changes: 3 additions & 3 deletions test/cli/__fixtures__/cjs.dir.filtered.dot
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ strict digraph "dependency-cruiser output"{
node [shape="box" style="rounded, filled" height="0.2" color="black" fillcolor="#ffffcc" fontcolor="black" fontname="Helvetica" fontsize="9"]
edge [arrowhead="normal" arrowsize="0.6" penwidth="2.0" color="#00000033" fontname="Helvetica" fontsize="9"]

"fs" [label=<fs> tooltip="fs" color="grey" fontcolor="grey"]
"http" [label=<http> tooltip="http" color="grey" fontcolor="grey"]
"path" [label=<path> tooltip="path" color="grey" fontcolor="grey"]
"fs" [label=<fs> tooltip="fs" URL="https://nodejs.org/api/fs.html" color="grey" fontcolor="grey"]
"http" [label=<http> tooltip="http" URL="https://nodejs.org/api/http.html" color="grey" fontcolor="grey"]
"path" [label=<path> tooltip="path" URL="https://nodejs.org/api/path.html" color="grey" fontcolor="grey"]
subgraph "cluster_test" {label="test" subgraph "cluster_test/cli" {label="cli" subgraph "cluster_test/cli/__fixtures__" {label="__fixtures__" subgraph "cluster_test/cli/__fixtures__/cjs" {label="cjs" "test/cli/__fixtures__/cjs/one_only_one.js" [label=<one_only_one.js> tooltip="one_only_one.js" URL="test/cli/__fixtures__/cjs/one_only_one.js" ] } } } }
"test/cli/__fixtures__/cjs/one_only_one.js" -> "path" [style="dashed" penwidth="1.0"]
subgraph "cluster_test" {label="test" subgraph "cluster_test/cli" {label="cli" subgraph "cluster_test/cli/__fixtures__" {label="__fixtures__" subgraph "cluster_test/cli/__fixtures__/cjs" {label="cjs" "test/cli/__fixtures__/cjs/one_only_two.js" [label=<one_only_two.js> tooltip="one_only_two.js" URL="test/cli/__fixtures__/cjs/one_only_two.js" ] } } } }
Expand Down

0 comments on commit 08dce74

Please sign in to comment.