dependency-cruiser 15.3.1-beta-2 → 15.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/configs/plugins/3d-reporter-plugin.mjs +127 -0
  2. package/configs/plugins/stats-reporter-plugin.mjs +82 -0
  3. package/package.json +44 -34
  4. package/src/cache/metadata-strategy.mjs +1 -1
  5. package/src/cli/init-config/config-template.mjs +15 -7
  6. package/src/cli/tools/svg-in-html-snippets/{script.snippet.js → script.js} +47 -12
  7. package/src/cli/tools/svg-in-html-snippets/style.css +101 -0
  8. package/src/cli/tools/wrap-stream-in-html.mjs +57 -15
  9. package/src/config-utl/extract-depcruise-config/index.mjs +1 -1
  10. package/src/config-utl/extract-webpack-resolve-config.mjs +14 -11
  11. package/src/enrich/add-validations.mjs +3 -3
  12. package/src/enrich/soften-known-violations.mjs +4 -4
  13. package/src/enrich/summarize/index.mjs +3 -3
  14. package/src/extract/gather-initial-sources.mjs +2 -2
  15. package/src/extract/get-dependencies.mjs +2 -2
  16. package/src/extract/resolve/determine-dependency-types.mjs +3 -3
  17. package/src/extract/resolve/index.mjs +3 -3
  18. package/src/extract/resolve/merge-manifests.mjs +4 -8
  19. package/src/extract/resolve/module-classifiers.mjs +2 -10
  20. package/src/extract/transpile/meta.d.ts +1 -1
  21. package/src/graph-utl/filter-bank.mjs +2 -2
  22. package/src/main/index.d.ts +1 -1
  23. package/src/main/options/normalize.mjs +1 -1
  24. package/src/main/rule-set/normalize.mjs +1 -1
  25. package/src/meta.js +1 -1
  26. package/src/report/anon/index.mjs +7 -7
  27. package/src/report/azure-devops.mjs +11 -11
  28. package/src/report/csv.mjs +3 -2
  29. package/src/report/dot/default-theme.mjs +1 -1
  30. package/src/report/error-html/index.mjs +6 -6
  31. package/src/report/error.mjs +1 -1
  32. package/src/report/html/index.mjs +1 -1
  33. package/src/report/markdown.mjs +5 -5
  34. package/src/validate/index.d.ts +4 -4
  35. package/src/validate/match-folder-dependency-rule.mjs +2 -2
  36. package/src/validate/match-module-rule.mjs +12 -12
  37. package/src/validate/violates-required-rule.mjs +2 -2
  38. package/types/baseline-violations.d.mts +3 -0
  39. package/types/{extract-babel-config.d.ts → config-utl/extract-babel-config.d.mts} +1 -1
  40. package/types/{extract-depcruise-config.d.ts → config-utl/extract-depcruise-config.d.mts} +2 -2
  41. package/types/{extract-ts-config.d.ts → config-utl/extract-ts-config.d.mts} +1 -1
  42. package/types/{extract-webpack-resolve-config.d.ts → config-utl/extract-webpack-resolve-config.d.mts} +4 -3
  43. package/types/{configuration.d.ts → configuration.d.mts} +2 -2
  44. package/types/{cruise-result.d.ts → cruise-result.d.mts} +12 -8
  45. package/types/{dependency-cruiser.d.ts → dependency-cruiser.d.mts} +9 -9
  46. package/types/{filter-types.d.ts → filter-types.d.mts} +1 -1
  47. package/types/{options.d.ts → options.d.mts} +7 -7
  48. package/types/plugins/3d-reporter-plugin.d.mts +13 -0
  49. package/types/plugins/mermaid-reporter-plugin.d.mts +14 -0
  50. package/types/plugins/stats-reporter-plugin.d.mts +13 -0
  51. package/types/{reporter-options.d.ts → reporter-options.d.mts} +2 -2
  52. package/types/{resolve-options.d.ts → resolve-options.d.mts} +1 -1
  53. package/types/{restrictions.d.ts → restrictions.d.mts} +1 -1
  54. package/types/{rule-set.d.ts → rule-set.d.mts} +3 -3
  55. package/types/{rule-summary.d.ts → rule-summary.d.mts} +1 -1
  56. package/types/{strict-filter-types.d.ts → strict-filter-types.d.mts} +3 -3
  57. package/types/{strict-options.d.ts → strict-options.d.mts} +7 -7
  58. package/types/{strict-restrictions.d.ts → strict-restrictions.d.mts} +2 -2
  59. package/types/{strict-rule-set.d.ts → strict-rule-set.d.mts} +5 -5
  60. package/types/{violations.d.ts → violations.d.mts} +2 -2
  61. package/src/cli/tools/svg-in-html-snippets/footer.snippet.html +0 -2
  62. package/src/cli/tools/svg-in-html-snippets/header.snippet.html +0 -108
  63. package/types/baseline-violations.d.ts +0 -3
  64. /package/types/{cache-options.d.ts → cache-options.d.mts} +0 -0
  65. /package/types/{shared-types.d.ts → shared-types.d.mts} +0 -0
@@ -0,0 +1,127 @@
1
+ import * as path from "node:path";
2
+ import figures from "figures";
3
+
4
+ const TEMPLATE = `
5
+ <html>
6
+ <head>
7
+ <style> body { margin: 0; } </style>
8
+ <script type="text/javascript" src="https://unpkg.com/three"></script>
9
+ <script type="text/javascript" src="https://unpkg.com/three-spritetext"></script>
10
+ <script type="text/javascript" src="https://unpkg.com/3d-force-graph"></script>
11
+ </head>
12
+
13
+ <body>
14
+ <div id="3d-graph"></div>
15
+
16
+ <script>
17
+ const gData = {
18
+ nodes: @@NODES@@,
19
+ links: @@LINKS@@
20
+ };
21
+
22
+ const elem = document.getElementById('3d-graph')
23
+ const Graph = ForceGraph3D()
24
+ (elem)
25
+ .graphData(gData)
26
+ .nodeAutoColorBy('group')
27
+ .nodeLabel(node => node.label)
28
+ .onNodeHover(node => elem.style.cursor = node ? 'pointer' : null)
29
+ .onNodeClick(node => {
30
+ // Aim at node from outside it
31
+ const distance = 40;
32
+ const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z);
33
+
34
+ Graph.cameraPosition(
35
+ { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio }, // new position
36
+ node, // lookAt ({ x, y, z })
37
+ 3000 // ms transition duration
38
+ )
39
+ })
40
+ /* nice idea, but the 3D graph tends to look cluttered. Also GPU/ CPU
41
+ intensive when run on a serious code base (e.g. react that has
42
+ ~4500 nodes and ~10000 links
43
+ */
44
+ .nodeThreeObject(node => {
45
+ const sprite = new SpriteText(node.displayname);
46
+ sprite.material.depthWrite = true; // make sprite background transparent
47
+ sprite.color = node.color;
48
+ sprite.textHeight = 6;
49
+ return sprite;
50
+ })
51
+ .linkOpacity(0.2)
52
+ .linkWidth(2)
53
+ .linkDirectionalArrowLength(4)
54
+ .linkDirectionalParticles(7) // cool but a bit GPU intensive
55
+ .linkLabel(link => link.label)
56
+ .onLinkHover(link => elem.style.cursor = link ? 'pointer' : null)
57
+
58
+ </script>
59
+ </body>
60
+ </html>`;
61
+
62
+ function deriveGroup(pFileName) {
63
+ let lReturnValue = "unknown";
64
+ const lGroupPositionInRe = 2;
65
+ const lMatch = path.dirname(pFileName).match(/^([^/]+)\/([^/]+)/);
66
+ if (lMatch) {
67
+ // eslint-disable-next-line security/detect-object-injection
68
+ lReturnValue = lMatch[lGroupPositionInRe];
69
+ }
70
+ return lReturnValue;
71
+ }
72
+
73
+ function formatFileName(pFileName) {
74
+ return `${path.dirname(pFileName)}/<b>${path.basename(pFileName)}</b>`;
75
+ }
76
+ function formatDependency(pFrom, pTo) {
77
+ return `${formatFileName(pFrom)} ${figures.arrowRight}</br>${formatFileName(
78
+ pTo
79
+ )}`;
80
+ }
81
+
82
+ /**
83
+ *
84
+ * @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult
85
+ */
86
+ function render3DThing(pCruiseResult) {
87
+ const lNodes = pCruiseResult.modules.map((pModule) => {
88
+ return {
89
+ id: pModule.source,
90
+ displayname: path.basename(pModule.source),
91
+ dirname: path.dirname(pModule.source),
92
+ label: formatFileName(pModule.source),
93
+ group: deriveGroup(pModule.source),
94
+ };
95
+ });
96
+ const lLinks = pCruiseResult.modules.reduce(
97
+ (pAll, pCurrentModule) =>
98
+ pAll.concat(
99
+ pCurrentModule.dependencies.map((pDependency) => ({
100
+ source: pCurrentModule.source,
101
+ target: pDependency.resolved,
102
+ label: formatDependency(pCurrentModule.source, pDependency.resolved),
103
+ }))
104
+ ),
105
+ []
106
+ );
107
+
108
+ return TEMPLATE.replace(/@@NODES@@/g, JSON.stringify(lNodes)).replace(
109
+ /@@LINKS@@/g,
110
+ JSON.stringify(lLinks)
111
+ );
112
+ }
113
+
114
+ /**
115
+ * Sample plugin: 3d representation
116
+ *
117
+ * @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult -
118
+ * the output of a dependency-cruise adhering to dependency-cruiser's
119
+ * cruise result schema
120
+ * @return {import('../../types/dependency-cruiser').IReporterOutput} -
121
+ * output: a string
122
+ * exitCode: 0
123
+ */
124
+ export default (pCruiseResult) => ({
125
+ output: render3DThing(pCruiseResult),
126
+ exitCode: 0,
127
+ });
@@ -0,0 +1,82 @@
1
+ const MEDIAN = 0.5;
2
+ const P75 = 0.75;
3
+ const DEFAULT_JSON_INDENT = 2;
4
+
5
+ function doMagic(pCruiseResult) {
6
+ let lReturnValue = {};
7
+
8
+ if (pCruiseResult.modules.some((pModule) => pModule.dependents)) {
9
+ const lDependentCounts = pCruiseResult.modules
10
+ .map((pModule) => pModule.dependents.length)
11
+ .sort();
12
+
13
+ lReturnValue = {
14
+ minDependentsPerModule: lDependentCounts[0] || 0,
15
+ maxDependentsPerModule:
16
+ lDependentCounts[Math.max(lDependentCounts.length - 1, 0)] || 0,
17
+ meanDependentsPerModule:
18
+ lDependentCounts.reduce((pAll, pCurrent) => pAll + pCurrent, 0) /
19
+ pCruiseResult.summary.totalCruised,
20
+ medianDependentsPerModule:
21
+ lDependentCounts[
22
+ Math.max(0, Math.floor(lDependentCounts.length * MEDIAN))
23
+ ],
24
+ p75DependentsPerModule:
25
+ lDependentCounts[
26
+ Math.max(0, Math.floor(lDependentCounts.length * P75))
27
+ ],
28
+ };
29
+ }
30
+ return lReturnValue;
31
+ }
32
+ /**
33
+ * returns an object with some stats from the ICruiseResult pCruiseResult it
34
+ * got passed
35
+ *
36
+ * @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult - a result from a cruise.
37
+ * @return {string} an object with some stats
38
+ */
39
+ function samplePluginReporter(pCruiseResult) {
40
+ const lDependencyCounts = pCruiseResult.modules
41
+ .map((pModule) => pModule.dependencies.length)
42
+ .sort();
43
+
44
+ return {
45
+ moduleCount: pCruiseResult.summary.totalCruised,
46
+ dependencyCount: pCruiseResult.summary.totalDependenciesCruised,
47
+ minDependenciesPerModule: lDependencyCounts[0] || 0,
48
+ maxDependenciesPerModule:
49
+ lDependencyCounts[Math.max(lDependencyCounts.length - 1, 0)] || 0,
50
+ meanDependenciesPerModule:
51
+ pCruiseResult.summary.totalDependenciesCruised /
52
+ pCruiseResult.summary.totalCruised,
53
+ medianDependenciesPerModule:
54
+ lDependencyCounts[
55
+ Math.max(0, Math.floor(lDependencyCounts.length * MEDIAN))
56
+ ],
57
+ p75DependenciesPerModule:
58
+ lDependencyCounts[
59
+ Math.max(0, Math.floor(lDependencyCounts.length * P75))
60
+ ],
61
+ ...doMagic(pCruiseResult),
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Sample plugin
67
+ *
68
+ * @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult -
69
+ * the output of a dependency-cruise adhering to dependency-cruiser's
70
+ * cruise result schema
71
+ * @return {import('../../types/dependency-cruiser').IReporterOutput} -
72
+ * output: some stats on modules and dependencies in json format
73
+ * exitCode: 0
74
+ */
75
+ export default (pCruiseResult) => ({
76
+ output: JSON.stringify(
77
+ samplePluginReporter(pCruiseResult),
78
+ null,
79
+ DEFAULT_JSON_INDENT
80
+ ),
81
+ exitCode: 0,
82
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-cruiser",
3
- "version": "15.3.1-beta-2",
3
+ "version": "15.5.0",
4
4
  "description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
5
5
  "keywords": [
6
6
  "static analysis",
@@ -51,39 +51,49 @@
51
51
  },
52
52
  "exports": {
53
53
  ".": {
54
- "import": "./src/main/index.mjs",
55
- "types": "./types/dependency-cruiser.d.ts"
54
+ "types": "./types/dependency-cruiser.d.mts",
55
+ "import": "./src/main/index.mjs"
56
56
  },
57
57
  "./config-utl/extract-babel-config": {
58
- "import": "./src/config-utl/extract-babel-config.mjs",
59
- "types": "./types/extract-babel-config.d.ts"
58
+ "types": "./types/config-utl/extract-babel-config.d.mts",
59
+ "import": "./src/config-utl/extract-babel-config.mjs"
60
60
  },
61
61
  "./config-utl/extract-depcruise-config": {
62
- "import": "./src/config-utl/extract-depcruise-config/index.mjs",
63
- "types": "./types/extract-depcruise-config.d.ts"
62
+ "types": "./types/config-utl/extract-depcruise-config.d.mts",
63
+ "import": "./src/config-utl/extract-depcruise-config/index.mjs"
64
64
  },
65
65
  "./config-utl/extract-ts-config": {
66
- "import": "./src/config-utl/extract-ts-config.mjs",
67
- "types": "./types/extract-ts-config.d.ts"
66
+ "types": "./types/config-utl/extract-ts-config.d.mts",
67
+ "import": "./src/config-utl/extract-ts-config.mjs"
68
68
  },
69
69
  "./config-utl/extract-webpack-resolve-config": {
70
- "import": "./src/config-utl/extract-webpack-resolve-config.mjs",
71
- "types": "./types/extract-webpack-resolve-config.d.ts"
70
+ "types": "./types/config-utl/extract-webpack-resolve-config.d.mts",
71
+ "import": "./src/config-utl/extract-webpack-resolve-config.mjs"
72
72
  },
73
- "./sample-reporter-plugin": "./configs/plugins/stats-reporter-plugin.mjs",
74
- "./sample-3d-reporter-plugin": "./configs/plugins/3d-reporter-plugin.mjs",
75
- "./mermaid-reporter-plugin": "./src/report/mermaid.mjs"
73
+ "./sample-reporter-plugin": {
74
+ "types": "./types/plugins/stats-reporter-plugin.d.mts",
75
+ "import": "./configs/plugins/stats-reporter-plugin.mjs"
76
+ },
77
+ "./sample-3d-reporter-plugin": {
78
+ "types": "./types/plugins/3d-reporter-plugin.d.mts",
79
+ "import": "./configs/plugins/3d-reporter-plugin.mjs"
80
+ },
81
+ "./mermaid-reporter-plugin": {
82
+ "types": "./types/plugins/mermaid-reporter-plugin.d.mts",
83
+ "import": "./src/report/mermaid.mjs"
84
+ }
76
85
  },
77
- "types": "types/dependency-cruiser.d.ts",
86
+ "types": "types/dependency-cruiser.d.mts",
78
87
  "files": [
79
88
  "bin",
80
89
  "configs/**/*.js",
90
+ "configs/plugins/",
81
91
  "src",
82
92
  "!src/**/*.json",
83
93
  "!src/**/*.hbs",
84
94
  "!src/**/*.md",
85
95
  "!**/*.DS_Store",
86
- "types/*.d.ts",
96
+ "types/**/*.d.mts",
87
97
  "LICENSE",
88
98
  "package.json",
89
99
  "README.md"
@@ -103,7 +113,7 @@
103
113
  "depcruise:graph:doc:fmt-archi": "./bin/depcruise-fmt.mjs -T archi -f - node_modules/.cache/tmp_graph_deps.json | dot -T svg -Gordering=in -Grankdir=TD | tee doc/real-world-samples/dependency-cruiser-archi-graph.svg | node bin/wrap-stream-in-html.mjs > docs/dependency-cruiser-archi-graph.html",
104
114
  "depcruise:graph:doc:fmt-dir": "./bin/depcruise-fmt.mjs -T ddot -f - node_modules/.cache/tmp_graph_deps.json | dot -T svg -Grankdir=TD | tee doc/real-world-samples/dependency-cruiser-dir-graph.svg | node bin/wrap-stream-in-html.mjs > docs/dependency-cruiser-dir-graph.html",
105
115
  "depcruise:graph:doc:fmt-schema": "cd tools/schema && node ../../bin/dependency-cruise.mjs . --output-type dot | dot -T svg | tee ../overview.svg | node ../../bin/wrap-stream-in-html.mjs > ../../docs/schema-overview.html && cd -",
106
- "depcruise:graph:doc:fmt-types": "cd types && node ../bin/dependency-cruise.mjs . --output-type dot | dot -T svg > overview.svg && cd -",
116
+ "depcruise:graph:doc:fmt-types": "cd types && node ../bin/dependency-cruise.mjs . --output-type dot | dot -T svg | tee overview.svg | ../bin/wrap-stream-in-html.mjs > overview.html && cd -",
107
117
  "depcruise:graph:doc:samples": "sh tools/generate-samples.sh",
108
118
  "depcruise:graph:mermaid": "node ./bin/dependency-cruise.mjs bin src --include-only ^src/ --collapse 2 --output-type mermaid",
109
119
  "depcruise:graph:mermaid:diff": "node ./bin/dependency-cruise.mjs bin src test types tools --config configs/.dependency-cruiser-unlimited.mjs --output-type mermaid --reaches \"$(watskeburt $SHA)\"",
@@ -113,8 +123,8 @@
113
123
  "depcruise:report:view": "node ./bin/dependency-cruise.mjs src bin test configs types --output-type err-html --config configs/.dependency-cruiser-show-metrics-config.mjs --output-to - | browser",
114
124
  "depcruise:focus": "node ./bin/dependency-cruise.mjs src bin test configs types tools --progress --no-cache --output-type text --focus",
115
125
  "depcruise:reaches": "node ./bin/dependency-cruise.mjs src bin test configs types tools --progress --no-cache --config configs/.dependency-cruiser-unlimited.mjs --output-type text --reaches",
116
- "format": "prettier --log-level warn --write \"src/**/*.js\" \"configs/**/*.js\" \"tools/**/*.mjs\" \"bin/*\" \"types/*.d.ts\" \"test/**/*.spec.{cjs,js}\" \"test/**/*.{spec,utl}.mjs\"",
117
- "format:check": "prettier --log-level warn --check \"src/**/*.js\" \"configs/**/*.js\" \"tools/**/*.mjs\" \"bin/*\" \"types/*.d.ts\" \"test/**/*.spec.{cjs,js}\" \"test/**/*.{spec,utl}.mjs\"",
126
+ "format": "prettier --log-level warn --write \"src/**/*.js\" \"configs/**/*.js\" \"tools/**/*.mjs\" \"bin/*\" \"types/*.d.mts\" \"test/**/*.spec.{cjs,js}\" \"test/**/*.{spec,utl}.mjs\"",
127
+ "format:check": "prettier --log-level warn --check \"src/**/*.js\" \"configs/**/*.js\" \"tools/**/*.mjs\" \"bin/*\" \"types/*.d.mts\" \"test/**/*.spec.{cjs,js}\" \"test/**/*.{spec,utl}.mjs\"",
118
128
  "lint": "npm-run-all --parallel --aggregate-output lint:eslint format:check lint:types",
119
129
  "lint:eslint": "eslint bin/dependency-cruise.mjs bin src test configs tools/**/*.mjs --cache --cache-location node_modules/.cache/eslint/",
120
130
  "lint:eslint:fix": "eslint --fix bin src test configs tools/**/*.mjs --cache --cache-location node_modules/.cache/eslint/",
@@ -122,8 +132,8 @@
122
132
  "lint:fix": "npm-run-all lint:eslint:fix format lint:types:fix",
123
133
  "lint:types": "npm-run-all lint:types:tsc lint:types:lint",
124
134
  "lint:types:tsc": "tsc --project types/tsconfig.json",
125
- "lint:types:lint": "eslint --no-ignore --config types/.eslintrc.json types/*.d.ts",
126
- "lint:types:fix": "eslint --no-ignore --config types/.eslintrc.json --fix types/*.d.ts",
135
+ "lint:types:lint": "eslint --no-ignore --config types/.eslintrc.json types/*.d.mts",
136
+ "lint:types:fix": "eslint --no-ignore --config types/.eslintrc.json --fix types/*.d.mts",
127
137
  "prepare": "husky install",
128
138
  "scm:push": "run-p --aggregate-output scm:push:*",
129
139
  "scm:push:bitbucket-mirror": "run-p --aggregate-output scm:push:bitbucket-mirror:*",
@@ -163,7 +173,7 @@
163
173
  "commander": "11.1.0",
164
174
  "enhanced-resolve": "5.15.0",
165
175
  "figures": "6.0.1",
166
- "ignore": "5.2.4",
176
+ "ignore": "5.3.0",
167
177
  "indent-string": "5.0.0",
168
178
  "interpret": "^3.1.1",
169
179
  "is-installed-globally": "1.0.0",
@@ -177,23 +187,23 @@
177
187
  "semver-try-require": "6.2.3",
178
188
  "teamcity-service-messages": "0.1.14",
179
189
  "tsconfig-paths-webpack-plugin": "4.1.0",
180
- "watskeburt": "2.0.1",
190
+ "watskeburt": "2.0.2",
181
191
  "wrap-ansi": "9.0.0"
182
192
  },
183
193
  "devDependencies": {
184
194
  "@babel/core": "7.23.3",
185
195
  "@babel/plugin-transform-modules-commonjs": "7.23.3",
186
196
  "@babel/preset-typescript": "7.23.3",
187
- "@swc/core": "1.3.96",
188
- "@types/lodash": "4.14.201",
189
- "@types/node": "20.9.0",
190
- "@types/prompts": "2.4.8",
191
- "@typescript-eslint/eslint-plugin": "6.10.0",
192
- "@typescript-eslint/parser": "6.10.0",
193
- "@vue/compiler-sfc": "3.3.8",
197
+ "@swc/core": "1.3.99",
198
+ "@types/lodash": "4.14.202",
199
+ "@types/node": "20.10.0",
200
+ "@types/prompts": "2.4.9",
201
+ "@typescript-eslint/eslint-plugin": "6.12.0",
202
+ "@typescript-eslint/parser": "6.12.0",
203
+ "@vue/compiler-sfc": "3.3.9",
194
204
  "c8": "8.0.1",
195
205
  "coffeescript": "2.7.0",
196
- "eslint": "8.53.0",
206
+ "eslint": "8.54.0",
197
207
  "eslint-config-moving-meadow": "4.0.2",
198
208
  "eslint-config-prettier": "9.0.0",
199
209
  "eslint-plugin-budapestian": "6.0.0",
@@ -209,15 +219,15 @@
209
219
  "mocha": "10.2.0",
210
220
  "normalize-newline": "4.1.0",
211
221
  "npm-run-all": "4.1.5",
212
- "prettier": "3.0.3",
222
+ "prettier": "3.1.0",
213
223
  "proxyquire": "2.1.3",
214
224
  "shx": "0.3.4",
215
225
  "svelte": "3.59.1",
216
226
  "symlink-dir": "5.2.0",
217
- "typescript": "5.2.2",
227
+ "typescript": "5.3.2",
218
228
  "upem": "9.0.2",
219
229
  "vue-template-compiler": "2.7.15",
220
- "yarn": "1.22.19"
230
+ "yarn": "1.22.21"
221
231
  },
222
232
  "overrides": {
223
233
  "semver": "^7.5.4",
@@ -15,7 +15,7 @@ import { bus } from "#utl/bus.mjs";
15
15
  export default class MetaDataStrategy {
16
16
  /**
17
17
  * @param {string} _pDirectory
18
- * @param {import("../../types/cruise-result.js").ICruiseResult} _pCachedCruiseResult
18
+ * @param {import("../../types/cruise-result.mjs").ICruiseResult} _pCachedCruiseResult
19
19
  * @param {Object} pOptions
20
20
  * @param {Set<string>} pOptions.extensions
21
21
  * @param {Set<import("watskeburt").changeTypeType>=} pOptions.interestingChangeTypes
@@ -25,10 +25,10 @@ module.exports = {
25
25
  from: {
26
26
  orphan: true,
27
27
  pathNot: [
28
- '(^|/)\\.[^/]+\\.(js|cjs|mjs|ts|json)$', // dot files
29
- '\\.d\\.ts$', // TypeScript declaration files
30
- '(^|/)tsconfig\\.json$', // TypeScript config
31
- '(^|/)(babel|webpack)\\.config\\.(js|cjs|mjs|ts|json)$' // other configs
28
+ '(^|/)[.][^/]+[.](js|cjs|mjs|ts|json)$', // dot files
29
+ '[.]d[.]ts$', // TypeScript declaration files
30
+ '(^|/)tsconfig[.]json$', // TypeScript config
31
+ '(^|/)(babel|webpack)[.]config[.](js|cjs|mjs|ts|json)$' // other configs
32
32
  ]
33
33
  },
34
34
  to: {},
@@ -136,7 +136,7 @@ module.exports = {
136
136
  severity: 'error',
137
137
  from: {},
138
138
  to: {
139
- path: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$'
139
+ path: '[.](spec|test)[.](js|mjs|cjs|ts|ls|coffee|litcoffee|coffee[.]md)$'
140
140
  }
141
141
  },
142
142
  {
@@ -150,11 +150,19 @@ module.exports = {
150
150
  'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
151
151
  from: {
152
152
  path: '{{sourceLocationRE}}',
153
- pathNot: '\\.(spec|test)\\.(js|mjs|cjs|ts|ls|coffee|litcoffee|coffee\\.md)$'
153
+ pathNot: '[.](spec|test)[.](js|mjs|cjs|ts|ls|coffee|litcoffee|coffee[.]md)$'
154
154
  },
155
155
  to: {
156
156
  dependencyTypes: [
157
- 'npm-dev'
157
+ 'npm-dev',
158
+ ],
159
+ // type only dependencies are not a problem as they don't end up in the
160
+ // production code or are ignored by the runtime.
161
+ dependencyTypesNot: [
162
+ 'type-only'
163
+ ],
164
+ pathNot: [
165
+ 'node_modules/@types/'
158
166
  ]
159
167
  }
160
168
  },
@@ -10,7 +10,7 @@ var title2ElementMap = (function makeElementMap() {
10
10
 
11
11
  function getHoverHandler(pTitle2ElementMap) {
12
12
  /** @type {string} */
13
- var currentHighlightedTitle;
13
+ var currentHighlightedTitle = "";
14
14
 
15
15
  /** @param {MouseEvent} pMouseEvent */
16
16
  return function hoverHighlightHandler(pMouseEvent) {
@@ -31,7 +31,7 @@ function getHoverHandler(pTitle2ElementMap) {
31
31
 
32
32
  function getSelectHandler(pTitle2ElementMap) {
33
33
  /** @type {string} */
34
- var currentHighlightedTitle;
34
+ var currentHighlightedTitle = "";
35
35
 
36
36
  /** @param {MouseEvent} pMouseEvent */
37
37
  return function selectHighlightHandler(pMouseEvent) {
@@ -64,6 +64,9 @@ function Mode() {
64
64
  this._mode = SELECT;
65
65
  }
66
66
 
67
+ /**
68
+ * @returns {number}
69
+ */
67
70
  function get() {
68
71
  return this._mode || HOVER;
69
72
  }
@@ -210,23 +213,23 @@ function addHighlight(pGroup) {
210
213
  }
211
214
  }
212
215
 
213
- var hints = {
216
+ var gHints = {
214
217
  HIDDEN: 1,
215
218
  SHOWN: 2,
216
219
  state: this.HIDDEN,
217
220
  show: function () {
218
221
  document.getElementById("hints").removeAttribute("style");
219
- hints.state = hints.SHOWN;
222
+ gHints.state = gHints.SHOWN;
220
223
  },
221
224
  hide: function () {
222
225
  document.getElementById("hints").style = "display:none";
223
- hints.state = hints.HIDDEN;
226
+ gHints.state = gHints.HIDDEN;
224
227
  },
225
228
  toggle: function () {
226
- if ((hints.state || hints.HIDDEN) === hints.HIDDEN) {
227
- hints.show();
229
+ if ((gHints.state || gHints.HIDDEN) === gHints.HIDDEN) {
230
+ gHints.show();
228
231
  } else {
229
- hints.hide();
232
+ gHints.hide();
230
233
  }
231
234
  },
232
235
  };
@@ -236,16 +239,48 @@ function keyboardEventHandler(pKeyboardEvent) {
236
239
  if (pKeyboardEvent.key === "Escape") {
237
240
  resetNodesAndEdges();
238
241
  gMode.setToHover();
239
- hints.hide();
242
+ gHints.hide();
240
243
  }
241
244
  if (pKeyboardEvent.key === "F1") {
242
245
  pKeyboardEvent.preventDefault();
243
- hints.toggle();
246
+ gHints.toggle();
244
247
  }
245
248
  }
246
249
 
247
250
  document.addEventListener("contextmenu", getSelectHandler(title2ElementMap));
248
251
  document.addEventListener("mouseover", getHoverHandler(title2ElementMap));
249
252
  document.addEventListener("keydown", keyboardEventHandler);
250
- document.getElementById("close-hints").addEventListener("click", hints.hide);
251
- document.getElementById("button_help").addEventListener("click", hints.toggle);
253
+ document.getElementById("close-hints").addEventListener("click", gHints.hide);
254
+ document.getElementById("button_help").addEventListener("click", gHints.toggle);
255
+ document.querySelector("svg").insertAdjacentHTML(
256
+ "afterbegin",
257
+ `<linearGradient id="edgeGradient">
258
+ <stop offset="0%" stop-color="fuchsia"/>
259
+ <stop offset="100%" stop-color="purple"/>
260
+ </linearGradient>
261
+ `,
262
+ );
263
+
264
+ // Add a small increment to the last value of the path to make gradients on
265
+ // horizontal paths work. Without them all browsers I tested with (firefox,
266
+ // chrome) do not render the gradient, but instead make the line transparent
267
+ // (or the color of the background, I haven't looked into it that deeply,
268
+ // but for the hack it doesn't matter which).
269
+ function skewLineABit(lDrawingInstructions) {
270
+ var lLastValue = lDrawingInstructions.match(/(\d+\.?\d*)$/)[0];
271
+ // Smaller values than .001 _should_ work as well, but don't in all
272
+ // cases. Even this value is so small that it is not visible to the
273
+ // human eye (tested with the two I have at my disposal).
274
+ var lIncrement = 0.001;
275
+ var lNewLastValue = parseFloat(lLastValue) + lIncrement;
276
+
277
+ return lDrawingInstructions.replace(lLastValue, lNewLastValue);
278
+ }
279
+
280
+ nodeListToArray(document.querySelectorAll("path"))
281
+ .filter(function (pElement) {
282
+ return pElement.parentElement.classList.contains("edge");
283
+ })
284
+ .forEach(function (pElement) {
285
+ pElement.attributes.d.value = skewLineABit(pElement.attributes.d.value);
286
+ });
@@ -0,0 +1,101 @@
1
+ .node:active path,
2
+ .node:hover path,
3
+ .node.current path,
4
+ .node:active polygon,
5
+ .node:hover polygon,
6
+ .node.current polygon {
7
+ stroke: fuchsia;
8
+ stroke-width: 2;
9
+ }
10
+
11
+ .edge:active path,
12
+ .edge:hover path,
13
+ .edge.current path,
14
+ .edge:active ellipse,
15
+ .edge:hover ellipse,
16
+ .edge.current ellipse {
17
+ stroke: url(#edgeGradient);
18
+ stroke-width: 3;
19
+ stroke-opacity: 1;
20
+ }
21
+
22
+ .edge:active polygon,
23
+ .edge:hover polygon,
24
+ .edge.current polygon {
25
+ stroke: fuchsia;
26
+ stroke-width: 3;
27
+ fill: fuchsia;
28
+ stroke-opacity: 1;
29
+ fill-opacity: 1;
30
+ }
31
+
32
+ .edge:active text,
33
+ .edge:hover text {
34
+ fill: fuchsia;
35
+ }
36
+
37
+ .cluster path {
38
+ stroke-width: 3;
39
+ }
40
+
41
+ .cluster:active path,
42
+ .cluster:hover path {
43
+ fill: #ffff0011;
44
+ }
45
+
46
+ div.hint {
47
+ background-color: #000000aa;
48
+ color: white;
49
+ font-family: Arial, Helvetica, sans-serif;
50
+ border-radius: 1rem;
51
+ position: fixed;
52
+ top: calc(50% - 4em);
53
+ right: calc(50% - 10em);
54
+ border: none;
55
+ padding: 1em 3em 1em 1em;
56
+ }
57
+
58
+ .hint button {
59
+ position: absolute;
60
+ font-weight: bolder;
61
+ right: 0.6em;
62
+ top: 0.6em;
63
+ color: inherit;
64
+ background-color: inherit;
65
+ border: 1px solid currentColor;
66
+ border-radius: 1em;
67
+ margin-left: 0.6em;
68
+ }
69
+
70
+ .hint a {
71
+ color: inherit;
72
+ }
73
+
74
+ #button_help {
75
+ color: white;
76
+ background-color: #00000011;
77
+ border-radius: 1em;
78
+ position: fixed;
79
+ top: 1em;
80
+ right: 1em;
81
+ font-size: 24pt;
82
+ font-weight: bolder;
83
+ width: 2em;
84
+ height: 2em;
85
+ border: none;
86
+ }
87
+
88
+ #button_help:hover {
89
+ cursor: pointer;
90
+ background-color: #00000077;
91
+ }
92
+
93
+ @media print {
94
+ #button_help {
95
+ display: none;
96
+ }
97
+
98
+ div.hint {
99
+ display: none;
100
+ }
101
+ }