Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,49 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - 2026-01-18

### Added

**Enhanced Tooltips**
- Node tooltips now display "Links out" and "Links in" counts
- Color-coded: orange for outgoing links, green for incoming links
- Helps quickly understand node connectivity

**Links Count Panel**
- New "Links count" tab in the Unlinked Modules panel
- Configurable threshold filter (default: 1) to find nodes by connection count
- Checkboxes to filter by "links in" or "links out" criteria
- Click on any item to navigate and zoom to it on the graph
- Useful for finding highly connected or isolated nodes

**Display Filters**
- Show/hide nodes by type: Modules, Classes, Functions, External
- Show/hide links by type: Module→Module, Module→Entity, Dependencies
- All filters available in the expanded Display panel

**CSV Export**
- New `--csv PATH` option to export graph data to CSV file
- Columns: name, type (module/function/class/external), parent_module, full_path, links_out, links_in, lines
- Example: `codegraph /path/to/code --csv output.csv`

### Changed

- Legend panel moved to the right of Controls panel (both at top-left area)
- Renamed "Unlinked Modules" panel header, now uses tabs interface
- "Unlinked" is now a tab showing modules with zero connections
- "Links count" tab provides flexible filtering by connection count

### Refactored

**Template Extraction**
- HTML, CSS, and JavaScript moved to separate files in `codegraph/templates/`
- `templates/index.html` - HTML structure with placeholders
- `templates/styles.css` - all CSS styles
- `templates/main.js` - all JavaScript code
- `vizualyzer.py` reduced from ~2000 to ~340 lines
- Easier to maintain and edit frontend code separately

## [1.1.0] - 2025-01-18

### Added
Expand Down
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,32 @@ It is based only on lexical and syntax parsing, so it doesn't need to install al

![Node Information](docs/img/node_information.png)

**Tooltips** - Hover over any node to see details: type, parent module, full path, and connection count.
**Tooltips** - Hover over any node to see details: type, parent module, full path, lines of code, and connection counts (links in/out).

### Links Count

![Links Count](docs/img/links_count.png)

**Links Count Panel** - Find nodes by their connection count. Filter by "links in" or "links out" with configurable threshold.

### Unlinked Modules

![Unlinked Nodes](docs/img/listing_unlinked_nodes.png)

**Unlinked Panel** - Shows modules with no connections. Click to navigate to them on the graph.

### Massive Objects Detection

![Massive Objects](docs/img/massive_objects_detection.png)

**Massive Objects Panel** - Find large code entities by lines of code. Filter by type (modules, classes, functions) with configurable threshold.

### Display Settings

![Display Settings](docs/img/graph_display_settings.png)

**Display Filters** - Show/hide nodes by type (Modules, Classes, Functions, External) and links by type (Module→Module, Module→Entity, Dependencies).

### UI Tips

![UI Tips](docs/img/tips_in_ui.png)
Expand Down Expand Up @@ -63,9 +81,27 @@ This will generate an interactive HTML visualization and open it in your browser
| Option | Description |
|--------|-------------|
| `--output PATH` | Custom output path for HTML file (default: `./codegraph.html`) |
| `--csv PATH` | Export graph data to CSV file |
| `--matplotlib` | Use legacy matplotlib visualization instead of D3.js |
| `-o, --object-only` | Print dependencies to console only, no visualization |

### CSV Export

Export graph data to CSV for analysis in spreadsheets or other tools:

```console
codegraph /path/to/code --csv output.csv
```

CSV columns:
- `name` - Entity name
- `type` - module / function / class / external
- `parent_module` - Parent module (for functions/classes)
- `full_path` - File path
- `links_out` - Outgoing dependencies count
- `links_in` - Incoming dependencies count
- `lines` - Lines of code

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for full version history.
2 changes: 1 addition & 1 deletion codegraph/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.1.0"
__version__ = "1.2.0"
12 changes: 11 additions & 1 deletion codegraph/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@
type=click.Path(),
help="Output path for D3.js HTML file (default: ./codegraph.html)",
)
def cli(paths, object_only, file_path, distance, matplotlib, output):
@click.option(
"--csv",
type=click.Path(),
help="Export graph data to CSV file (specify output path)",
)
def cli(paths, object_only, file_path, distance, matplotlib, output, csv):
"""
Tool that creates a graph of code to show dependencies between code entities (methods, classes, etc.).
CodeGraph does not execute code, it is based only on lex and syntax parsing.
Expand All @@ -56,6 +61,7 @@ def cli(paths, object_only, file_path, distance, matplotlib, output):
distance=distance,
matplotlib=matplotlib,
output=output,
csv=csv,
)
main(args)

Expand All @@ -72,6 +78,10 @@ def main(args):
click.echo(f" Distance {distance}: {', '.join(files)}")
elif args.object_only:
pprint.pprint(usage_graph)
elif args.csv:
import codegraph.vizualyzer as vz

vz.export_to_csv(usage_graph, entity_metadata=entity_metadata, output_path=args.csv)
else:
import codegraph.vizualyzer as vz

Expand Down
169 changes: 169 additions & 0 deletions codegraph/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CodeGraph - Interactive Visualization</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
/* STYLES_PLACEHOLDER */
</style>
</head>
<body>
<div id="graph"></div>
<div class="tooltip" id="tooltip"></div>

<!-- Search box -->
<div class="search-container">
<div class="search-box">
<input type="text" class="search-input" id="searchInput" placeholder="Search nodes... (Ctrl+F)" autocomplete="off">
<button class="search-clear" id="searchClear">&times;</button>
<div class="autocomplete-list" id="autocompleteList"></div>
</div>
</div>

<!-- Highlight info banner -->
<div class="highlight-info" id="highlightInfo">
<span id="highlightText">Highlighting: </span>
<button id="clearHighlight">Clear (Esc)</button>
</div>

<div class="panel controls" id="controls-panel">
<div class="panel-header">
<h4>Controls</h4>
<button class="panel-toggle" title="Collapse">−</button>
</div>
<div class="panel-content">
<p><kbd>Ctrl+F</kbd> Search nodes</p>
<p><kbd>Scroll</kbd> Zoom in/out</p>
<p><kbd>Drag</kbd> on background - Pan</p>
<p><kbd>Drag</kbd> on node - Pin node position</p>
<p><kbd>Click</kbd> module/entity - Collapse/Expand</p>
<p><kbd>Double-click</kbd> - Unpin / Focus on node</p>
<p><kbd>Esc</kbd> Clear search highlight</p>
</div>
</div>
<div class="panel legend" id="legend-panel">
<div class="panel-header">
<h4>Legend</h4>
<button class="panel-toggle" title="Collapse">−</button>
</div>
<div class="panel-content">
<div class="legend-section">
<h4>Nodes</h4>
<div class="legend-item">
<div class="legend-color legend-module"></div>
<span>Module (.py file)</span>
</div>
<div class="legend-item">
<div class="legend-color legend-entity"></div>
<span>Entity (function/class)</span>
</div>
<div class="legend-item">
<div class="legend-color legend-external"></div>
<span>External dependency</span>
</div>
</div>
<div class="legend-section">
<h4>Links</h4>
<div class="legend-item">
<div class="legend-line legend-link-module"></div>
<span>Module → Module</span>
</div>
<div class="legend-item">
<div class="legend-line legend-link-entity" style="border-top: 2px dashed #009c2c; background: none; height: 0;"></div>
<span>Module → Entity</span>
</div>
<div class="legend-item">
<div class="legend-line legend-link-dep"></div>
<span>Entity → Dependency</span>
</div>
</div>
</div>
</div>
<div class="panel stats" id="stats">
<div class="panel-header">
<h4>Statistics</h4>
<button class="panel-toggle" title="Collapse">−</button>
</div>
<div class="panel-content" id="stats-content"></div>
</div>
<div class="panel unlinked-modules" id="unlinked-modules">
<div class="panel-header">
<h4>Connections</h4>
<button class="panel-toggle" title="Collapse">−</button>
</div>
<div class="panel-content">
<div class="unlinked-tabs">
<button class="unlinked-tab active" data-tab="unlinked-list">Unlinked <span class="count" id="unlinked-count"></span></button>
<button class="unlinked-tab" data-tab="links-count-list">Links count <span class="count" id="links-count"></span></button>
</div>
<div id="unlinked-list" class="unlinked-tab-content active"></div>
<div id="links-count-list" class="unlinked-tab-content">
<div class="links-filter">
<div class="filter-row">
<label><input type="checkbox" id="links-in-check" checked> Links in</label>
<label><input type="checkbox" id="links-out-check" checked> Links out</label>
</div>
<div class="filter-row">
<span>More than:</span>
<input type="number" id="links-threshold" value="5" min="0">
</div>
</div>
<div id="links-count-content"></div>
</div>
</div>
</div>
<div class="panel massive-objects" id="massive-objects">
<div class="panel-header">
<h4>Massive Objects <span class="count" id="massive-count"></span></h4>
<button class="panel-toggle" title="Collapse">−</button>
</div>
<div class="panel-content">
<div class="filters">
<div class="filter-row">
<label><input type="checkbox" id="filter-modules" checked> Modules</label>
<label><input type="checkbox" id="filter-classes" checked> Classes</label>
<label><input type="checkbox" id="filter-functions" checked> Functions</label>
</div>
<div class="filter-row">
<span>Min lines:</span>
<input type="number" id="massive-threshold" value="50" min="1">
</div>
</div>
<ul id="massive-list"></ul>
</div>
</div>
<div class="panel size-toggle" id="size-toggle-panel">
<div class="panel-header">
<h4>Display</h4>
<button class="panel-toggle" title="Collapse">−</button>
</div>
<div class="panel-content">
<label>
<input type="checkbox" id="size-by-code" checked>
Size by lines of code
</label>
<div class="display-section">
<h5>Show nodes</h5>
<label><input type="checkbox" id="show-modules" checked> Modules</label>
<label><input type="checkbox" id="show-classes" checked> Classes</label>
<label><input type="checkbox" id="show-functions" checked> Functions</label>
<label><input type="checkbox" id="show-external" checked> External</label>
</div>
<div class="display-section">
<h5>Show links</h5>
<label><input type="checkbox" id="show-link-module" checked> Module → Module</label>
<label><input type="checkbox" id="show-link-entity" checked> Module → Entity</label>
<label><input type="checkbox" id="show-link-dependency" checked> Dependencies</label>
</div>
</div>
</div>

<script>
const graphData = /* GRAPH_DATA_PLACEHOLDER */;

/* SCRIPT_PLACEHOLDER */
</script>
</body>
</html>
Loading