code2llm 0.5.96__tar.gz → 0.5.97__tar.gz

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 (120) hide show
  1. {code2llm-0.5.96 → code2llm-0.5.97}/PKG-INFO +8 -7
  2. {code2llm-0.5.96 → code2llm-0.5.97}/README.md +7 -6
  3. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/__init__.py +1 -1
  4. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/mermaid_exporter.py +14 -23
  5. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/nlp/__init__.py +1 -1
  6. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm.egg-info/PKG-INFO +8 -7
  7. {code2llm-0.5.96 → code2llm-0.5.97}/pyproject.toml +1 -1
  8. {code2llm-0.5.96 → code2llm-0.5.97}/setup.py +1 -1
  9. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_analyzer.py +34 -0
  10. {code2llm-0.5.96 → code2llm-0.5.97}/LICENSE +0 -0
  11. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/__main__.py +0 -0
  12. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/__init__.py +0 -0
  13. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/call_graph.py +0 -0
  14. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/cfg.py +0 -0
  15. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/coupling.py +0 -0
  16. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/data_analysis.py +0 -0
  17. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/dfg.py +0 -0
  18. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/pipeline_detector.py +0 -0
  19. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/side_effects.py +0 -0
  20. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/smells.py +0 -0
  21. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/analysis/type_inference.py +0 -0
  22. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/api.py +0 -0
  23. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli.py +0 -0
  24. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_analysis.py +0 -0
  25. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_commands.py +0 -0
  26. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_exports/__init__.py +0 -0
  27. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_exports/code2logic.py +0 -0
  28. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_exports/formats.py +0 -0
  29. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_exports/orchestrator.py +0 -0
  30. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_exports/prompt.py +0 -0
  31. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/cli_parser.py +0 -0
  32. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/__init__.py +0 -0
  33. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/analyzer.py +0 -0
  34. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/config.py +0 -0
  35. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/file_analyzer.py +0 -0
  36. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/file_cache.py +0 -0
  37. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/file_filter.py +0 -0
  38. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/gitignore.py +0 -0
  39. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/__init__.py +0 -0
  40. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/base.py +0 -0
  41. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/cpp.py +0 -0
  42. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/csharp.py +0 -0
  43. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/generic.py +0 -0
  44. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/go_lang.py +0 -0
  45. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/java.py +0 -0
  46. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/php.py +0 -0
  47. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/ruby.py +0 -0
  48. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/rust.py +0 -0
  49. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/lang/typescript.py +0 -0
  50. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/large_repo.py +0 -0
  51. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/models.py +0 -0
  52. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/refactoring.py +0 -0
  53. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/repo_files.py +0 -0
  54. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming/__init__.py +0 -0
  55. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming/cache.py +0 -0
  56. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming/incremental.py +0 -0
  57. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming/prioritizer.py +0 -0
  58. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming/scanner.py +0 -0
  59. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming/strategies.py +0 -0
  60. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/streaming_analyzer.py +0 -0
  61. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/core/toon_size_manager.py +0 -0
  62. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/__init__.py +0 -0
  63. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/article_view.py +0 -0
  64. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/base.py +0 -0
  65. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/context_exporter.py +0 -0
  66. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/context_view.py +0 -0
  67. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/evolution_exporter.py +0 -0
  68. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/flow_constants.py +0 -0
  69. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/flow_exporter.py +0 -0
  70. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/flow_renderer.py +0 -0
  71. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/html_dashboard.py +0 -0
  72. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/index_generator.py +0 -0
  73. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/json_exporter.py +0 -0
  74. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/llm_exporter.py +0 -0
  75. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/map_exporter.py +0 -0
  76. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/project_yaml_exporter.py +0 -0
  77. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/readme_exporter.py +0 -0
  78. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/report_generators.py +0 -0
  79. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon/__init__.py +0 -0
  80. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon/helpers.py +0 -0
  81. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon/metrics.py +0 -0
  82. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon/module_detail.py +0 -0
  83. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon/renderer.py +0 -0
  84. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon.py +0 -0
  85. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/toon_view.py +0 -0
  86. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/validate_project.py +0 -0
  87. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/exporters/yaml_exporter.py +0 -0
  88. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/generators/__init__.py +0 -0
  89. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/generators/llm_flow.py +0 -0
  90. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/generators/llm_task.py +0 -0
  91. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/generators/mermaid.py +0 -0
  92. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/nlp/config.py +0 -0
  93. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/nlp/entity_resolution.py +0 -0
  94. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/nlp/intent_matching.py +0 -0
  95. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/nlp/normalization.py +0 -0
  96. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/nlp/pipeline.py +0 -0
  97. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/patterns/__init__.py +0 -0
  98. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/patterns/detector.py +0 -0
  99. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/refactor/__init__.py +0 -0
  100. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm/refactor/prompt_engine.py +0 -0
  101. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm.egg-info/SOURCES.txt +0 -0
  102. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm.egg-info/dependency_links.txt +0 -0
  103. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm.egg-info/entry_points.txt +0 -0
  104. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm.egg-info/requires.txt +0 -0
  105. {code2llm-0.5.96 → code2llm-0.5.97}/code2llm.egg-info/top_level.txt +0 -0
  106. {code2llm-0.5.96 → code2llm-0.5.97}/setup.cfg +0 -0
  107. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_advanced_analysis.py +0 -0
  108. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_deep_analysis.py +0 -0
  109. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_edge_cases.py +0 -0
  110. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_flow_exporter.py +0 -0
  111. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_format_quality.py +0 -0
  112. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_multilanguage_e2e.py +0 -0
  113. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_nlp_pipeline.py +0 -0
  114. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_nonpython_cc_calls.py +0 -0
  115. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_pipeline_detector.py +0 -0
  116. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_project_toon_export.py +0 -0
  117. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_prompt_engine.py +0 -0
  118. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_prompt_txt.py +0 -0
  119. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_refactoring_engine.py +0 -0
  120. {code2llm-0.5.96 → code2llm-0.5.97}/tests/test_toon_v2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code2llm
3
- Version: 0.5.96
3
+ Version: 0.5.97
4
4
  Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
5
5
  Home-page: https://github.com/wronai/stts
6
6
  Author: STTS Project
@@ -76,8 +76,8 @@ When you run `code2llm ./ -f all`, the following files are created:
76
76
  # Quick health check (TOON format only)
77
77
  code2llm ./ -f toon
78
78
 
79
- # Generate all formats + project.toon.yaml + prompt.txt (single-project mode)
80
- code2llm ./ -f all -o ./project --no-chunk
79
+ # Generate all formats (what created these files)
80
+ code2llm ./ -f all
81
81
 
82
82
  # LLM-ready context only
83
83
  code2llm ./ -f context
@@ -192,12 +192,13 @@ grep -E "^ .*[0-9]{3,}$" project.toon.yaml | sort -t',' -k2 -n -r | head -10
192
192
 
193
193
  ### `prompt.txt` - Ready-to-Send LLM Prompt
194
194
  **Purpose**: Pre-formatted prompt listing all generated files for LLM conversation
195
- **Generation**: Written when `code2llm` runs with a source path and requests `-f all` (including `--no-chunk`) or `code2logic`; `-f all` also writes `project.toon.yaml`
195
+ **Generation**: Written when `code2llm` runs with a source path and requests `-f all` (including `--no-chunk`) or `code2logic`
196
196
  **Contents**:
197
- - **Files section**: Lists all existing generated files with descriptions
197
+ - **Files section**: Lists all existing generated files with descriptions, including `project.toon.yaml` when generated by `-f all`
198
198
  - **Source files section**: Highlights important source files such as `cli_exports/orchestrator.py`
199
199
  - **Missing section**: Shows which files weren't generated (if any)
200
- - **Task section**: Instructions for LLM analysis
200
+ - **Task section**: Refactoring brief with concrete execution instructions, not just analysis
201
+ - **Priority Order section**: State-dependent refactoring priorities, starting with blockers and then architecture cleanup
201
202
  - **Requirements section**: Guidelines for suggested changes
202
203
 
203
204
  **Example usage**:
@@ -372,7 +373,7 @@ code2llm ./ -f yaml --separate-orphans
372
373
 
373
374
  **Generated by**: `code2llm ./ -f all --readme`
374
375
  **Analysis Date**: 2026-03-26
375
- **Total Functions**: 931
376
+ **Total Functions**: 934
376
377
  **Total Classes**: 106
377
378
  **Modules**: 122
378
379
 
@@ -26,8 +26,8 @@ When you run `code2llm ./ -f all`, the following files are created:
26
26
  # Quick health check (TOON format only)
27
27
  code2llm ./ -f toon
28
28
 
29
- # Generate all formats + project.toon.yaml + prompt.txt (single-project mode)
30
- code2llm ./ -f all -o ./project --no-chunk
29
+ # Generate all formats (what created these files)
30
+ code2llm ./ -f all
31
31
 
32
32
  # LLM-ready context only
33
33
  code2llm ./ -f context
@@ -142,12 +142,13 @@ grep -E "^ .*[0-9]{3,}$" project.toon.yaml | sort -t',' -k2 -n -r | head -10
142
142
 
143
143
  ### `prompt.txt` - Ready-to-Send LLM Prompt
144
144
  **Purpose**: Pre-formatted prompt listing all generated files for LLM conversation
145
- **Generation**: Written when `code2llm` runs with a source path and requests `-f all` (including `--no-chunk`) or `code2logic`; `-f all` also writes `project.toon.yaml`
145
+ **Generation**: Written when `code2llm` runs with a source path and requests `-f all` (including `--no-chunk`) or `code2logic`
146
146
  **Contents**:
147
- - **Files section**: Lists all existing generated files with descriptions
147
+ - **Files section**: Lists all existing generated files with descriptions, including `project.toon.yaml` when generated by `-f all`
148
148
  - **Source files section**: Highlights important source files such as `cli_exports/orchestrator.py`
149
149
  - **Missing section**: Shows which files weren't generated (if any)
150
- - **Task section**: Instructions for LLM analysis
150
+ - **Task section**: Refactoring brief with concrete execution instructions, not just analysis
151
+ - **Priority Order section**: State-dependent refactoring priorities, starting with blockers and then architecture cleanup
151
152
  - **Requirements section**: Guidelines for suggested changes
152
153
 
153
154
  **Example usage**:
@@ -322,7 +323,7 @@ code2llm ./ -f yaml --separate-orphans
322
323
 
323
324
  **Generated by**: `code2llm ./ -f all --readme`
324
325
  **Analysis Date**: 2026-03-26
325
- **Total Functions**: 931
326
+ **Total Functions**: 934
326
327
  **Total Classes**: 106
327
328
  **Modules**: 122
328
329
 
@@ -8,7 +8,7 @@ Includes NLP Processing Pipeline for query normalization, intent matching,
8
8
  and entity resolution with multilingual support.
9
9
  """
10
10
 
11
- __version__ = "0.5.96"
11
+ __version__ = "0.5.97"
12
12
  __author__ = "STTS Project"
13
13
 
14
14
  # Core analysis components (lightweight, always needed)
@@ -12,6 +12,7 @@ New 3-level flow diagrams (Plan R1):
12
12
  """
13
13
 
14
14
  from collections import defaultdict
15
+ import re
15
16
  from pathlib import Path
16
17
  from typing import Dict, List, Set, Tuple, Optional
17
18
  from .base import Exporter
@@ -581,32 +582,22 @@ class MermaidExporter(Exporter):
581
582
  code2llm.core.analyze → code2llm__core__analyze
582
583
  code2llm.core.PipelineDetector.__init__ → code2llm__core__PipelineDetector____init__
583
584
  """
584
- # Convert dots to double underscores to preserve hierarchy
585
- safe = name.replace('.', '__')
586
- # Replace other unsafe chars
587
- safe = safe.replace('-', '_').replace(':', '_').replace(' ', '_')
588
- # Keep reasonable length but preserve class+method uniqueness
589
- if len(safe) > 60:
590
- parts = name.split('.')
591
- if len(parts) >= 3:
592
- # module__Class__method or module__subpackage__Class__method
593
- module = parts[0]
594
- method = parts[-1]
595
- # Include class name if present (parts[-2] is usually class or subpackage)
596
- if len(parts) >= 4 and parts[-2][0].isupper():
597
- # Definitely a class: module.sub.Class.method
598
- class_name = parts[-2]
599
- safe = f"{module}__{class_name}__{method}"
600
- else:
601
- # Might be module.subpackage.function
602
- middle = '__'.join(parts[1:-1])
603
- safe = f"{module}__{middle}__{method}"
604
- safe = safe[:60]
605
- return safe
585
+ return self._sanitize_identifier(name, prefix="N")
606
586
 
607
587
  def _safe_module(self, name: str) -> str:
608
588
  """Create safe subgraph name."""
609
- return name.replace('.', '_').replace('-', '_').replace('/', '_').replace(' ', '_')
589
+ return self._sanitize_identifier(name, prefix="M")
590
+
591
+ @staticmethod
592
+ def _sanitize_identifier(name: str, prefix: str) -> str:
593
+ """Convert an arbitrary string into a Mermaid-safe identifier."""
594
+ safe = (name or "").replace('.', '__')
595
+ safe = re.sub(r'[^A-Za-z0-9_]+', '_', safe)
596
+ if not safe:
597
+ return prefix
598
+ if not safe[0].isalpha():
599
+ safe = f"{prefix}_{safe}"
600
+ return safe
610
601
 
611
602
  def _module_of(self, func_name: str) -> str:
612
603
  """Extract module from qualified name.
@@ -4,7 +4,7 @@ Provides query normalization, intent matching, and entity resolution
4
4
  with multilingual support and fuzzy matching.
5
5
  """
6
6
 
7
- __version__ = "0.5.96"
7
+ __version__ = "0.5.97"
8
8
 
9
9
  from .pipeline import NLPPipeline
10
10
  from .normalization import QueryNormalizer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code2llm
3
- Version: 0.5.96
3
+ Version: 0.5.97
4
4
  Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
5
5
  Home-page: https://github.com/wronai/stts
6
6
  Author: STTS Project
@@ -76,8 +76,8 @@ When you run `code2llm ./ -f all`, the following files are created:
76
76
  # Quick health check (TOON format only)
77
77
  code2llm ./ -f toon
78
78
 
79
- # Generate all formats + project.toon.yaml + prompt.txt (single-project mode)
80
- code2llm ./ -f all -o ./project --no-chunk
79
+ # Generate all formats (what created these files)
80
+ code2llm ./ -f all
81
81
 
82
82
  # LLM-ready context only
83
83
  code2llm ./ -f context
@@ -192,12 +192,13 @@ grep -E "^ .*[0-9]{3,}$" project.toon.yaml | sort -t',' -k2 -n -r | head -10
192
192
 
193
193
  ### `prompt.txt` - Ready-to-Send LLM Prompt
194
194
  **Purpose**: Pre-formatted prompt listing all generated files for LLM conversation
195
- **Generation**: Written when `code2llm` runs with a source path and requests `-f all` (including `--no-chunk`) or `code2logic`; `-f all` also writes `project.toon.yaml`
195
+ **Generation**: Written when `code2llm` runs with a source path and requests `-f all` (including `--no-chunk`) or `code2logic`
196
196
  **Contents**:
197
- - **Files section**: Lists all existing generated files with descriptions
197
+ - **Files section**: Lists all existing generated files with descriptions, including `project.toon.yaml` when generated by `-f all`
198
198
  - **Source files section**: Highlights important source files such as `cli_exports/orchestrator.py`
199
199
  - **Missing section**: Shows which files weren't generated (if any)
200
- - **Task section**: Instructions for LLM analysis
200
+ - **Task section**: Refactoring brief with concrete execution instructions, not just analysis
201
+ - **Priority Order section**: State-dependent refactoring priorities, starting with blockers and then architecture cleanup
201
202
  - **Requirements section**: Guidelines for suggested changes
202
203
 
203
204
  **Example usage**:
@@ -372,7 +373,7 @@ code2llm ./ -f yaml --separate-orphans
372
373
 
373
374
  **Generated by**: `code2llm ./ -f all --readme`
374
375
  **Analysis Date**: 2026-03-26
375
- **Total Functions**: 931
376
+ **Total Functions**: 934
376
377
  **Total Classes**: 106
377
378
  **Modules**: 122
378
379
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code2llm"
7
- version = "0.5.96"
7
+ version = "0.5.97"
8
8
  description = "High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
  import os
5
5
 
6
6
  # Read version
7
- version = "0.5.95"
7
+ version = "0.5.96"
8
8
 
9
9
  # Read long description
10
10
  def read_readme():
@@ -6,6 +6,7 @@ import shutil
6
6
  from pathlib import Path
7
7
  from code2llm import ProjectAnalyzer, Config
8
8
  from code2llm.core.config import FAST_CONFIG, FilterConfig
9
+ from code2llm.core.models import AnalysisResult, FunctionInfo
9
10
 
10
11
 
11
12
  class TestProjectAnalyzer:
@@ -222,6 +223,39 @@ class TestExporters:
222
223
  content = output.read_text()
223
224
  assert "flowchart TD" in content
224
225
 
226
+ def test_mermaid_export_sanitizes_unsafe_identifiers(self, tmp_path):
227
+ """Mermaid IDs should not leak unsafe path-like characters."""
228
+ from code2llm.exporters import MermaidExporter
229
+
230
+ result = AnalysisResult(
231
+ project_path="/test",
232
+ analysis_mode="static",
233
+ )
234
+ result.functions["~/github/src/hell.module.func_a"] = FunctionInfo(
235
+ name="func_a",
236
+ qualified_name="~/github/src/hell.module.func_a",
237
+ file="/test/file.py",
238
+ line=1,
239
+ calls=["func_b"],
240
+ )
241
+ result.functions["~/github/src/hell.module.func_b"] = FunctionInfo(
242
+ name="func_b",
243
+ qualified_name="~/github/src/hell.module.func_b",
244
+ file="/test/file.py",
245
+ line=5,
246
+ )
247
+
248
+ output = tmp_path / "unsafe.mmd"
249
+ exporter = MermaidExporter()
250
+ exporter.export(result, str(output))
251
+
252
+ content = output.read_text()
253
+ assert "~" not in content
254
+ assert "/" not in content
255
+ assert "subgraph" in content
256
+ assert "func_a" in content
257
+ assert "func_b" in content
258
+
225
259
 
226
260
  if __name__ == "__main__":
227
261
  pytest.main([__file__, "-v"])
File without changes
File without changes
File without changes
File without changes