pkgviz 0.7.2 → 0.7.3
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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +1 -1
- package/.next/build-manifest.json +2 -2
- package/.next/cache/webpack/client-production/7.pack +0 -0
- package/.next/cache/webpack/client-production/8.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/server-production/11.pack +0 -0
- package/.next/cache/webpack/server-production/12.pack +0 -0
- package/.next/cache/webpack/server-production/13.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/favicon.ico/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +1 -1
- package/.next/server/app-paths-manifest.json +1 -1
- package/.next/server/chunks/610.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/trace +2 -2
- package/package.json +2 -3
- package/src/app/actions/graph.actions.ts +25 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +77 -0
- package/src/app/layout.tsx +30 -0
- package/src/app/page.tsx +5 -0
- package/src/app/utils/buildGraph.ts +119 -0
- package/src/app/utils/getParsedFileStructure.ts +225 -0
- package/src/app/utils/markCyclicPackages.ts +275 -0
- package/src/app/utils/parser/cpp/extractCppPackageFromImport.ts +18 -0
- package/src/app/utils/parser/cpp/parseCppFile.ts +150 -0
- package/src/app/utils/parser/delphi/extractPackageFromImport.ts +21 -0
- package/src/app/utils/parser/delphi/parseFile.ts +179 -0
- package/src/app/utils/parser/java/extractJavaPackageFromImport.ts +39 -0
- package/src/app/utils/parser/java/findEntryPoint.ts +24 -0
- package/src/app/utils/parser/java/getIntrinsicPackagesRecursive.ts +33 -0
- package/src/app/utils/parser/java/parseJavaFile.ts +114 -0
- package/src/app/utils/parser/kotlin/extractPackageFromImport.ts +19 -0
- package/src/app/utils/parser/kotlin/parseFile.ts +147 -0
- package/src/app/utils/parser/python/extractPythonPackageFromImport.ts +18 -0
- package/src/app/utils/parser/python/parseFile.ts +171 -0
- package/src/app/utils/parser/typescript/extractTypeScriptPackageFromImport.ts +18 -0
- package/src/app/utils/parser/typescript/parseFile.ts +130 -0
- package/src/components/Breadcrumb.tsx +34 -0
- package/src/components/Cytoscape.tsx +23 -0
- package/src/components/Header.tsx +28 -0
- package/src/components/Loader.tsx +10 -0
- package/src/components/Setting.tsx +17 -0
- package/src/components/Settings.tsx +189 -0
- package/src/components/Switch.tsx +31 -0
- package/src/components/ThemeToggle.tsx +25 -0
- package/src/components/ZoomInput.tsx +94 -0
- package/src/components/useCytoscape.ts +343 -0
- package/src/contexts/SettingsContext.tsx +88 -0
- package/src/i18n/en.ts +27 -0
- package/src/i18n/i18n.ts +12 -0
- package/src/layouts/breadthfirst/layout.ts +30 -0
- package/src/layouts/breadthfirst/style.ts +8 -0
- package/src/layouts/circle/layout.ts +11 -0
- package/src/layouts/circle/style.ts +18 -0
- package/src/layouts/concentric/layout.ts +10 -0
- package/src/layouts/concentric/style.ts +16 -0
- package/src/layouts/constants.ts +17 -0
- package/src/layouts/elk/layout.ts +55 -0
- package/src/layouts/elk/style.ts +14 -0
- package/src/layouts/getLayoutStyle.ts +19 -0
- package/src/layouts/getWeightBuckets.ts +58 -0
- package/src/layouts/grid/layout.ts +11 -0
- package/src/layouts/grid/style.ts +20 -0
- package/src/layouts/index.ts +14 -0
- package/src/layouts/style.ts +191 -0
- package/src/screens/home/Home.tsx +48 -0
- package/src/shared/constants/index.ts +7 -0
- package/src/shared/types/index.ts +68 -0
- package/src/shared/utils/detectLanguage.ts +255 -0
- package/src/shared/utils/getJsonAsync.ts +13 -0
- package/src/shared/utils/getProjectName.ts +3 -0
- package/src/shared/utils/parseEnv.ts +91 -0
- package/src/shared/utils/parseProjectPath.ts +8 -0
- package/src/store/useLocalStorage.ts +29 -0
- package/src/utils/filter/filterByPackagePrefix.ts +23 -0
- package/src/utils/filter/filterEmptyPackages.ts +36 -0
- package/src/utils/filter/filterSubPackagesFromDepth.ts +170 -0
- package/src/utils/filter/filterVendorPackages.ts +17 -0
- package/src/utils/filter/toggleCompoundNodes.ts +40 -0
- package/src/utils/hasChildren.ts +7 -0
- /package/.next/static/{VVBfFRai9p1x3oVXujjYO → cGbLRcmdy7k8HGus5vhzm}/_buildManifest.js +0 -0
- /package/.next/static/{VVBfFRai9p1x3oVXujjYO → cGbLRcmdy7k8HGus5vhzm}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import cytoscape from 'cytoscape';
|
|
2
|
+
import elk from 'cytoscape-elk';
|
|
3
|
+
cytoscape.use(elk as cytoscape.Ext);
|
|
4
|
+
|
|
5
|
+
type ElkLayoutOptions = cytoscape.BaseLayoutOptions &
|
|
6
|
+
cytoscape.AnimatedLayoutOptions & {
|
|
7
|
+
readonly name: 'elk';
|
|
8
|
+
readonly animate: boolean;
|
|
9
|
+
readonly animateFilter: (node: cytoscape.NodeSingular, i: number) => boolean;
|
|
10
|
+
readonly animationDuration: number;
|
|
11
|
+
readonly animationEasing: string | undefined;
|
|
12
|
+
readonly fit: boolean;
|
|
13
|
+
readonly nodeDimensionsIncludeLabels: boolean;
|
|
14
|
+
readonly nodeLayoutOptions?: (node: cytoscape.NodeSingular) => Record<string, unknown> | void;
|
|
15
|
+
readonly elk: Record<string, unknown>;
|
|
16
|
+
readonly priority: (edge: cytoscape.EdgeSingular) => number | null;
|
|
17
|
+
readonly padding?: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/***
|
|
21
|
+
* @url https://eclipse.dev/elk/reference/algorithms/org-eclipse-elk-layered.html
|
|
22
|
+
*/
|
|
23
|
+
export const layout: ElkLayoutOptions = {
|
|
24
|
+
name: 'elk',
|
|
25
|
+
|
|
26
|
+
/***
|
|
27
|
+
* @url http://www.eclipse.org/elk/reference.html
|
|
28
|
+
* @info Drop prefix from options name, e.g. org.eclipse.elk.direction becomes elk.direction
|
|
29
|
+
* @info Enums use the name of the enum as string Direction.DOWN becomes elk.direction: 'DOWN'
|
|
30
|
+
*/
|
|
31
|
+
elk: {
|
|
32
|
+
algorithm: 'layered',
|
|
33
|
+
'elk.direction': 'DOWN',
|
|
34
|
+
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
|
35
|
+
},
|
|
36
|
+
animate: true, // Whether to transition the node positions
|
|
37
|
+
animateFilter: function (/* node, i */) {
|
|
38
|
+
return true;
|
|
39
|
+
}, // Whether to animate specific nodes when animation is on; non-animated nodes immediately go to their final positions
|
|
40
|
+
animationDuration: 500, // Duration of animation in ms if enabled
|
|
41
|
+
animationEasing: undefined, // Easing of animation if enabled
|
|
42
|
+
|
|
43
|
+
fit: true, // Whether to fit
|
|
44
|
+
nodeDimensionsIncludeLabels: false, // Boolean which changes whether label dimensions are included when calculating node dimensions
|
|
45
|
+
nodeLayoutOptions: undefined, // Per-node options function
|
|
46
|
+
// padding: 20, // Padding on fit
|
|
47
|
+
transform: function (_node, pos) {
|
|
48
|
+
return pos;
|
|
49
|
+
}, // A function that applies a transform to the final node position
|
|
50
|
+
ready: undefined, // Callback on layoutready
|
|
51
|
+
stop: undefined, // Callback on layoutstop
|
|
52
|
+
priority: function (/* edge */) {
|
|
53
|
+
return null;
|
|
54
|
+
}, // Edges with a non-nil value are skipped when geedy edge cycle breaking is enabled
|
|
55
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { LayoutOptions } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
import { getStyle as getBreadthfirstStyle } from '@/layouts/breadthfirst/style';
|
|
4
|
+
import { getStyle as getCircleStyle } from '@/layouts/circle/style';
|
|
5
|
+
import { getStyle as getConcentricStyle } from '@/layouts/concentric/style';
|
|
6
|
+
import { getStyle as getGridStyle } from '@/layouts/grid/style';
|
|
7
|
+
|
|
8
|
+
export function getLayoutStyle(cytoscapeLayout: LayoutOptions['name']) {
|
|
9
|
+
switch (cytoscapeLayout) {
|
|
10
|
+
case 'breadthfirst':
|
|
11
|
+
return getBreadthfirstStyle();
|
|
12
|
+
case 'circle':
|
|
13
|
+
return getCircleStyle();
|
|
14
|
+
case 'concentric':
|
|
15
|
+
return getConcentricStyle();
|
|
16
|
+
case 'grid':
|
|
17
|
+
return getGridStyle();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ElementsDefinition } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
export function getWeightBuckets(
|
|
4
|
+
categoryCount: number,
|
|
5
|
+
algorithm: 'linear' | 'log' | 'quantile' = 'linear',
|
|
6
|
+
filteredElements: ElementsDefinition
|
|
7
|
+
) {
|
|
8
|
+
if (!filteredElements) return { thresholds: [], counts: [] };
|
|
9
|
+
|
|
10
|
+
const weights = filteredElements.edges.map(e => Number(e.data.weight));
|
|
11
|
+
const max = getMaxEdgeWeight(filteredElements);
|
|
12
|
+
|
|
13
|
+
const thresholds: number[] = [];
|
|
14
|
+
const counts = new Array(categoryCount).fill(0);
|
|
15
|
+
|
|
16
|
+
if (algorithm === 'linear') {
|
|
17
|
+
for (let i = 1; i < categoryCount; i++) {
|
|
18
|
+
thresholds.push((i * max) / categoryCount);
|
|
19
|
+
}
|
|
20
|
+
thresholds.push(max);
|
|
21
|
+
} else if (algorithm === 'log') {
|
|
22
|
+
const logMax = Math.log(max);
|
|
23
|
+
for (let i = 1; i < categoryCount; i++) {
|
|
24
|
+
thresholds.push(Math.exp((i * logMax) / categoryCount));
|
|
25
|
+
}
|
|
26
|
+
thresholds.push(max);
|
|
27
|
+
} else if (algorithm === 'quantile') {
|
|
28
|
+
const sorted = [...weights].sort((a, b) => a - b);
|
|
29
|
+
for (let i = 1; i < categoryCount; i++) {
|
|
30
|
+
const qIndex = Math.floor((i * sorted.length) / categoryCount);
|
|
31
|
+
thresholds.push(sorted[qIndex]);
|
|
32
|
+
}
|
|
33
|
+
thresholds.push(max);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Count how many weights fall into each bucket
|
|
37
|
+
weights.forEach(w => {
|
|
38
|
+
for (let i = 0; i < thresholds.length; i++) {
|
|
39
|
+
if (w <= thresholds[i]) {
|
|
40
|
+
counts[i]++;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
thresholds: thresholds.map(Math.round),
|
|
48
|
+
counts,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getMaxEdgeWeight(filteredElements: ElementsDefinition) {
|
|
53
|
+
return (
|
|
54
|
+
filteredElements?.edges.reduce((max, edge) => {
|
|
55
|
+
return edge.data.weight > max ? edge.data.weight : max;
|
|
56
|
+
}, 0) ?? 0
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GridLayoutOptions, NodeSingular } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
export const layout: GridLayoutOptions = {
|
|
4
|
+
name: 'grid',
|
|
5
|
+
// fit: true,
|
|
6
|
+
// padding: 30, // Add some space around the graph
|
|
7
|
+
avoidOverlap: true,
|
|
8
|
+
|
|
9
|
+
// Sort nodes alphabetically by their ID
|
|
10
|
+
sort: (a: NodeSingular, b: NodeSingular) => a.data('id').localeCompare(b.data('id')),
|
|
11
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { StylesheetJson } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
export function getStyle() {
|
|
4
|
+
const style: StylesheetJson = [
|
|
5
|
+
{
|
|
6
|
+
selector: 'node',
|
|
7
|
+
style: {
|
|
8
|
+
shape: 'rectangle',
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
selector: 'edge',
|
|
13
|
+
style: {
|
|
14
|
+
'text-margin-x': 0, // Reset text margins for straight lines
|
|
15
|
+
'text-margin-y': 0,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
return style;
|
|
20
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { layout as breadthfirstLayout } from '@/layouts/breadthfirst/layout';
|
|
2
|
+
export { getStyle as getBreadthfirstStyle } from '@/layouts/breadthfirst/style';
|
|
3
|
+
|
|
4
|
+
export { layout as circleLayout } from '@/layouts/circle/layout';
|
|
5
|
+
export { getStyle as getCircleStyle } from '@/layouts/circle/style';
|
|
6
|
+
|
|
7
|
+
export { layout as concentricLayout } from '@/layouts/concentric/layout';
|
|
8
|
+
export { getStyle as getConcentricStyle } from '@/layouts/concentric/style';
|
|
9
|
+
|
|
10
|
+
export { layout as elkLayout } from '@/layouts/elk/layout';
|
|
11
|
+
export { getStyle as getElkStyle } from '@/layouts/elk/style';
|
|
12
|
+
|
|
13
|
+
export { layout as gridLayout } from '@/layouts/grid/layout';
|
|
14
|
+
export { getStyle as getGridStyle } from '@/layouts/grid/style';
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { ElementsDefinition, NodeSingular, StylesheetJson } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
import { getWeightBuckets } from '@/layouts/getWeightBuckets';
|
|
4
|
+
|
|
5
|
+
export type ThemeKey = 'dark' | 'light';
|
|
6
|
+
|
|
7
|
+
const palette = {
|
|
8
|
+
light: {
|
|
9
|
+
canvasBg: '#ffffff',
|
|
10
|
+
// edge: '#9E9E9E',
|
|
11
|
+
edge: '#000',
|
|
12
|
+
weightXs: '#000',
|
|
13
|
+
weightMd: '#000',
|
|
14
|
+
weightXl: '#000',
|
|
15
|
+
|
|
16
|
+
nodeBg: '#E8F1FF',
|
|
17
|
+
nodeBorder: '#0B5FFF',
|
|
18
|
+
nodeBorderVendor: '#E2D5FF',
|
|
19
|
+
nodeBgVendor: '#D1C4FF',
|
|
20
|
+
nodeText: '#0B5FFF',
|
|
21
|
+
|
|
22
|
+
selectedFill: '#0B5FFF',
|
|
23
|
+
selectedFillVendor: '#a025aa',
|
|
24
|
+
selectedRing: '#0B5FFF',
|
|
25
|
+
selectedText: '#FFF',
|
|
26
|
+
},
|
|
27
|
+
dark: {
|
|
28
|
+
canvasBg: '#171717',
|
|
29
|
+
edge: '#707070',
|
|
30
|
+
weightXs: '#5A5A5A',
|
|
31
|
+
weightMd: '#8A8A8A',
|
|
32
|
+
weightXl: '#C0C0C0',
|
|
33
|
+
|
|
34
|
+
nodeBg: '#1E2533',
|
|
35
|
+
nodeBgVendor: '#241431',
|
|
36
|
+
nodeBorder: '#2A3A4A',
|
|
37
|
+
nodeBorderVendor: '#351542',
|
|
38
|
+
nodeText: '#E8F0FF',
|
|
39
|
+
|
|
40
|
+
selectedFill: '#2E6FFF',
|
|
41
|
+
selectedFillVendor: '#4E25AA',
|
|
42
|
+
selectedRing: '#BBD3FF',
|
|
43
|
+
selectedText: '#FFFFFF',
|
|
44
|
+
},
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
export const getCanvasBg = (theme: ThemeKey) => palette[theme].canvasBg;
|
|
48
|
+
|
|
49
|
+
export function getStyle(filteredElements: ElementsDefinition, theme: ThemeKey): StylesheetJson {
|
|
50
|
+
const colors = palette[theme];
|
|
51
|
+
const { thresholds } = getWeightBuckets(3, 'linear', filteredElements);
|
|
52
|
+
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
selector: 'node',
|
|
56
|
+
style: {
|
|
57
|
+
shape: 'bottom-round-rectangle',
|
|
58
|
+
'background-color': colors.nodeBg,
|
|
59
|
+
'border-color': colors.nodeBorder,
|
|
60
|
+
color: colors.nodeText,
|
|
61
|
+
label: 'data(name)',
|
|
62
|
+
'text-valign': 'center',
|
|
63
|
+
'text-halign': 'center',
|
|
64
|
+
width: (node: NodeSingular) => {
|
|
65
|
+
return node.data('name').length * 7;
|
|
66
|
+
},
|
|
67
|
+
height: (node: NodeSingular) => {
|
|
68
|
+
return node.height() / 2 + 10;
|
|
69
|
+
},
|
|
70
|
+
padding: '8px 8px',
|
|
71
|
+
'border-width': 1,
|
|
72
|
+
'font-size': '14px',
|
|
73
|
+
'overlay-opacity': 0, // avoid gray overlay
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
selector: 'node.isVendor',
|
|
78
|
+
style: {
|
|
79
|
+
'background-color': colors.nodeBgVendor,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{ selector: 'node.packageCycle', style: { 'border-color': '#d80303', 'border-width': 3 } },
|
|
83
|
+
{ selector: 'node.isParent', style: { 'font-weight': 'bold' } },
|
|
84
|
+
{
|
|
85
|
+
selector: 'node:selected',
|
|
86
|
+
style: {
|
|
87
|
+
'background-color': colors.selectedFill,
|
|
88
|
+
'border-color': colors.selectedRing,
|
|
89
|
+
'border-width': 3,
|
|
90
|
+
color: colors.selectedText,
|
|
91
|
+
'background-opacity': 1,
|
|
92
|
+
opacity: 1,
|
|
93
|
+
'overlay-opacity': 0,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
selector: 'node.isVendor:selected',
|
|
98
|
+
style: { 'background-color': colors.selectedFillVendor },
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
selector: 'node:parent, node:parent:selected',
|
|
102
|
+
style: {
|
|
103
|
+
'background-opacity': 0.3,
|
|
104
|
+
'background-color': colors.selectedFill,
|
|
105
|
+
color: colors.nodeText,
|
|
106
|
+
'border-width': 2,
|
|
107
|
+
'border-color': colors.nodeBorder,
|
|
108
|
+
'text-valign': 'top',
|
|
109
|
+
'text-margin-y': -5,
|
|
110
|
+
padding: '10px',
|
|
111
|
+
'padding-top': '20px',
|
|
112
|
+
'text-halign': 'center',
|
|
113
|
+
'font-size': 14,
|
|
114
|
+
'font-weight': 'bold',
|
|
115
|
+
'font-style': 'italic',
|
|
116
|
+
label: 'data(name)',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
selector: 'node:parent.isVendor, node:parent.isVendor:selected',
|
|
121
|
+
style: {
|
|
122
|
+
'background-color': colors.nodeBgVendor,
|
|
123
|
+
'border-color': colors.nodeBorderVendor,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
selector: 'edge',
|
|
128
|
+
style: {
|
|
129
|
+
'arrow-scale': 1,
|
|
130
|
+
'target-arrow-color': colors.edge,
|
|
131
|
+
'target-arrow-shape': 'chevron',
|
|
132
|
+
'target-arrow-fill': 'filled',
|
|
133
|
+
'line-color': colors.edge,
|
|
134
|
+
'curve-style': 'straight',
|
|
135
|
+
opacity: 1,
|
|
136
|
+
'line-opacity': 1,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
selector: 'edge.hushed',
|
|
141
|
+
style: {
|
|
142
|
+
opacity: 0.04,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
selector: 'edge.highlight-outgoer, edge.highlight-incomer, edge.highlight-dependency',
|
|
147
|
+
style: {
|
|
148
|
+
opacity: 1,
|
|
149
|
+
'line-opacity': 1,
|
|
150
|
+
width: 4,
|
|
151
|
+
'line-color': colors.weightXl,
|
|
152
|
+
'target-arrow-color': colors.weightXl,
|
|
153
|
+
'source-arrow-color': colors.weightXl,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{ selector: 'edge[weight <= 1]', style: { label: '' } },
|
|
157
|
+
{
|
|
158
|
+
selector: `edge[weight > 1][weight <= ${thresholds[0]}]`,
|
|
159
|
+
style: {
|
|
160
|
+
width: 1,
|
|
161
|
+
'line-color': colors.weightXs,
|
|
162
|
+
'target-arrow-color': colors.weightXs,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
selector: `edge[weight > ${thresholds[0]}][weight <= ${thresholds[1]}]`,
|
|
167
|
+
style: {
|
|
168
|
+
width: 4,
|
|
169
|
+
'arrow-scale': 2,
|
|
170
|
+
'line-color': colors.weightMd,
|
|
171
|
+
'target-arrow-color': colors.weightMd,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
selector: `edge[weight > ${thresholds[1]}]`,
|
|
176
|
+
style: {
|
|
177
|
+
width: 8,
|
|
178
|
+
'line-color': colors.weightXl,
|
|
179
|
+
'target-arrow-color': colors.weightXl,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
selector: 'edge.packageCycle',
|
|
184
|
+
style: { 'line-color': '#d80303', 'target-arrow-color': '#d80303' },
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
selector: 'edge.packageCycle',
|
|
188
|
+
style: { 'line-color': '#d80303', 'target-arrow-color': '#d80303' },
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import type { ElementsDefinition } from 'cytoscape';
|
|
3
|
+
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
5
|
+
import { getGraphAction } from '@/app/actions/graph.actions';
|
|
6
|
+
import Breadcrumb from '@/components/Breadcrumb';
|
|
7
|
+
import Header from '@/components/Header';
|
|
8
|
+
import Loader from '@/components/Loader';
|
|
9
|
+
import Settings from '@/components/Settings';
|
|
10
|
+
import { Cytoscape } from '@/components/Cytoscape';
|
|
11
|
+
import { SettingsProvider } from '@/contexts/SettingsContext';
|
|
12
|
+
|
|
13
|
+
export default function HomeScreen() {
|
|
14
|
+
const [currentPackage, setCurrentPackage] = useState<string>('');
|
|
15
|
+
const [packageGraph, setPackageGraph] = useState<ElementsDefinition | null>(null);
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!packageGraph) {
|
|
19
|
+
getGraphAction().then(setPackageGraph);
|
|
20
|
+
}
|
|
21
|
+
}, [packageGraph]);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
<Header title="nav.packages">
|
|
26
|
+
<Breadcrumb
|
|
27
|
+
path={currentPackage.replace(/\./g, '/')}
|
|
28
|
+
onNavigate={(path: string) => setCurrentPackage(path.replace(/\//g, '.'))}
|
|
29
|
+
/>
|
|
30
|
+
</Header>
|
|
31
|
+
|
|
32
|
+
<SettingsProvider>
|
|
33
|
+
<main data-testid="main" className="flex flex-1 flex-row dark:bg-[#171717]">
|
|
34
|
+
<Settings />
|
|
35
|
+
{packageGraph ? (
|
|
36
|
+
<Cytoscape
|
|
37
|
+
currentPackage={currentPackage}
|
|
38
|
+
setCurrentPackage={setCurrentPackage}
|
|
39
|
+
packageGraph={packageGraph}
|
|
40
|
+
/>
|
|
41
|
+
) : (
|
|
42
|
+
<Loader />
|
|
43
|
+
)}
|
|
44
|
+
</main>
|
|
45
|
+
</SettingsProvider>
|
|
46
|
+
</>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Language Detection Types
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* List of supported coding languages
|
|
6
|
+
*/
|
|
7
|
+
export enum Language {
|
|
8
|
+
Cpp = 'cpp',
|
|
9
|
+
Delphi = 'delphi',
|
|
10
|
+
JavaScript = 'javascript',
|
|
11
|
+
Kotlin = 'kotlin',
|
|
12
|
+
Python = 'python',
|
|
13
|
+
TypeScript = 'typescript',
|
|
14
|
+
Java = 'java',
|
|
15
|
+
Unknown = 'unknown',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Language Detection Result
|
|
20
|
+
*/
|
|
21
|
+
export interface LanguageDetectionResult {
|
|
22
|
+
language: Language;
|
|
23
|
+
confidence: number;
|
|
24
|
+
indicators: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//////////////////////////////////////////////////////////////////////////
|
|
28
|
+
// Parser Types
|
|
29
|
+
|
|
30
|
+
export interface ParsedFile {
|
|
31
|
+
readonly calls: MethodCall[];
|
|
32
|
+
readonly className: string;
|
|
33
|
+
readonly imports: ImportDefinition[];
|
|
34
|
+
readonly methods: MethodDefinition[];
|
|
35
|
+
readonly package: string;
|
|
36
|
+
readonly path: string; // Relative path from project root
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ParsedDirectory {
|
|
40
|
+
[k: string]: ParsedDirectory | ParsedFile;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Method Definition
|
|
45
|
+
*/
|
|
46
|
+
export interface MethodDefinition {
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly returnType: string;
|
|
49
|
+
readonly parameters: string[];
|
|
50
|
+
readonly visibility: 'public' | 'protected' | 'private' | 'default';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Method Call
|
|
55
|
+
*/
|
|
56
|
+
export interface MethodCall {
|
|
57
|
+
readonly callee: string;
|
|
58
|
+
readonly method: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Import Definition
|
|
63
|
+
*/
|
|
64
|
+
export interface ImportDefinition {
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly pkg: string;
|
|
67
|
+
readonly isIntrinsic?: boolean;
|
|
68
|
+
}
|