88
99import json
1010import re
11+ import subprocess
12+ import sys
1113from pathlib import Path
1214from datetime import datetime
1315from typing import List , Dict
@@ -37,6 +39,35 @@ def generate_sparkline(counts: List[int]) -> str:
3739 return sparkline
3840
3941
42+ def generate_growth_chart (repo_root : Path ) -> bool :
43+ """Generate growth chart using the chart generation script."""
44+ try :
45+ # Run the chart generation script in the virtual environment
46+ venv_python = repo_root / "chart-env" / "bin" / "python3"
47+ chart_script = repo_root / "scripts" / "generate_growth_chart.py"
48+
49+ if venv_python .exists () and chart_script .exists ():
50+ result = subprocess .run (
51+ [str (venv_python ), str (chart_script )],
52+ cwd = str (repo_root ),
53+ capture_output = True ,
54+ text = True
55+ )
56+ return result .returncode == 0
57+ else :
58+ # Fallback: try with system python
59+ result = subprocess .run (
60+ [sys .executable , str (chart_script )],
61+ cwd = str (repo_root ),
62+ capture_output = True ,
63+ text = True
64+ )
65+ return result .returncode == 0
66+ except Exception as e :
67+ print (f"⚠️ Chart generation failed: { e } " )
68+ return False
69+
70+
4071def load_growth_data (repo_root : Path ) -> tuple :
4172 """Load growth history and current metadata."""
4273 growth_file = repo_root / "growth_history.json"
@@ -80,18 +111,26 @@ def update_readme_with_stats(repo_root: Path):
80111 except :
81112 formatted_date = datetime .now ().strftime ('%Y-%m-%d' )
82113
83- # Generate sparkline from growth history
114+ # Generate growth chart
115+ chart_generated = generate_growth_chart (repo_root )
116+
117+ # Get counts for fallback text
84118 counts = [entry ["count" ] for entry in growth_data .get ("entries" , [])]
85119 if not counts :
86120 counts = [current_count ]
87121
88- sparkline = generate_sparkline (counts )
122+ # Create stats section with proper chart
123+ if chart_generated :
124+ chart_section = ""
125+ else :
126+ # Fallback to sparkline if chart generation fails
127+ chart_section = generate_sparkline (counts )
89128
90129 # Create stats section
91130 stats_section = f"""
92131## 📊 Library Statistics
93132
94- { sparkline }
133+ { chart_section }
95134
96135**Total System Prompts:** { current_count :,} | **Last Updated:** { formatted_date }
97136
@@ -103,26 +142,31 @@ def update_readme_with_stats(repo_root: Path):
103142 with open (readme_file , 'r' , encoding = 'utf-8' ) as f :
104143 content = f .read ()
105144
106- # Check if stats section already exists
107- stats_pattern = r'## 📊 Library Statistics.*?(?=##|\Z)'
108-
109- if re .search (stats_pattern , content , re .DOTALL ):
110- # Replace existing stats section
111- new_content = re .sub (stats_pattern , stats_section .strip () + '\n \n ' , content , flags = re .DOTALL )
112- print ("✅ Updated existing statistics section" )
145+ # Use markers to only update the statistics section, preserving manual edits
146+ stats_begin_marker = "<!-- BEGIN_STATS_SECTION -->"
147+ stats_end_marker = "<!-- END_STATS_SECTION -->"
148+
149+ # Check if markers exist
150+ if stats_begin_marker in content and stats_end_marker in content :
151+ # Replace only the content between markers
152+ pattern = f"{ stats_begin_marker } .*?{ stats_end_marker } "
153+ replacement = f"{ stats_begin_marker } \n { stats_section .strip ()} \n { stats_end_marker } "
154+ new_content = re .sub (pattern , replacement , content , flags = re .DOTALL )
155+ print ("✅ Updated existing statistics section between markers" )
113156 else :
114- # Insert stats section after the badges but before Table of Contents
157+ # Insert stats section with markers after the badges but before Table of Contents
115158 # Look for the pattern: badges -> image -> Table of Contents
116159 toc_pattern = r'(!\[alt text\].*?\n\n)(## Table of Contents)'
117160
118161 if re .search (toc_pattern , content , re .DOTALL ):
162+ stats_with_markers = f"{ stats_begin_marker } \n { stats_section .strip ()} \n { stats_end_marker } \n \n "
119163 new_content = re .sub (
120164 toc_pattern ,
121- r'\1' + stats_section + r'\2' ,
165+ r'\1' + stats_with_markers + r'\2' ,
122166 content ,
123167 flags = re .DOTALL
124168 )
125- print ("✅ Added new statistics section before Table of Contents" )
169+ print ("✅ Added new statistics section with markers before Table of Contents" )
126170 else :
127171 # Fallback: add after the first heading
128172 lines = content .split ('\n ' )
@@ -132,9 +176,10 @@ def update_readme_with_stats(repo_root: Path):
132176 insert_pos = i
133177 break
134178
135- lines .insert (insert_pos , stats_section .strip ())
179+ stats_with_markers = f"{ stats_begin_marker } \n { stats_section .strip ()} \n { stats_end_marker } "
180+ lines .insert (insert_pos , stats_with_markers )
136181 new_content = '\n ' .join (lines )
137- print ("✅ Added new statistics section (fallback method)" )
182+ print ("✅ Added new statistics section with markers (fallback method)" )
138183
139184 # Write updated content
140185 with open (readme_file , 'w' , encoding = 'utf-8' ) as f :
0 commit comments