feat: automated README updates and better maintenance docs
This commit is contained in:
125
scripts/update_readme.py
Normal file
125
scripts/update_readme.py
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
def update_readme():
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
readme_path = os.path.join(base_dir, "README.md")
|
||||
index_path = os.path.join(base_dir, "skills_index.json")
|
||||
|
||||
print(f"📖 Reading skills index from: {index_path}")
|
||||
with open(index_path, 'r', encoding='utf-8') as f:
|
||||
skills = json.load(f)
|
||||
|
||||
total_skills = len(skills)
|
||||
print(f"🔢 Total skills found: {total_skills}")
|
||||
|
||||
print(f"📝 Updating README at: {readme_path}")
|
||||
with open(readme_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# 1. Update Title Count
|
||||
# Pattern: # 🌌 Antigravity Awesome Skills: [NUM]+ Agentic Skills
|
||||
content = re.sub(
|
||||
r'(# 🌌 Antigravity Awesome Skills: )\d+(\+ Agentic Skills)',
|
||||
f'\\g<1>{total_skills}\\g<2>',
|
||||
content
|
||||
)
|
||||
|
||||
# 2. Update Blockquote Count
|
||||
# Pattern: Collection of [NUM]+ Universal
|
||||
content = re.sub(
|
||||
r'(Collection of )\d+(\+ Universal)',
|
||||
f'\\g<1>{total_skills}\\g<2>',
|
||||
content
|
||||
)
|
||||
|
||||
# 3. Update Intro Text Count
|
||||
# Pattern: library of **[NUM] high-performance skills**
|
||||
content = re.sub(
|
||||
r'(library of \*\*)\d+( high-performance skills\*\*)',
|
||||
f'\\g<1>{total_skills}\\g<2>',
|
||||
content
|
||||
)
|
||||
|
||||
# 4. Update Registry Header Count
|
||||
# Pattern: ## Full Skill Registry ([NUM]/[NUM])
|
||||
content = re.sub(
|
||||
r'(## Full Skill Registry \()\d+/\d+(\))',
|
||||
f'\\g<1>{total_skills}/{total_skills}\\g<2>',
|
||||
content
|
||||
)
|
||||
|
||||
# 5. Generate New Registry Table
|
||||
print("🔄 Generating new registry table...")
|
||||
|
||||
# Store the Note block to preserve it
|
||||
note_pattern = r'(> \[!NOTE\].*?)\n\n\| Skill Name'
|
||||
note_match = re.search(note_pattern, content, re.DOTALL)
|
||||
note_block = ""
|
||||
if note_match:
|
||||
note_block = note_match.group(1)
|
||||
else:
|
||||
# Fallback default note if not found (though it should be there)
|
||||
note_block = "> [!NOTE] > **Document Skills**: We provide both **community** and **official Anthropic** versions for DOCX, PDF, PPTX, and XLSX. Locally, the official versions are used by default (via symlinks). In the repository, both versions are available for flexibility."
|
||||
|
||||
table_header = "| Skill Name | Description | Path |\n| :--- | :--- | :--- |"
|
||||
table_rows = []
|
||||
|
||||
for skill in skills:
|
||||
name = skill.get('name', 'Unknown')
|
||||
desc = skill.get('description', '').replace('\n', ' ').strip()
|
||||
path = skill.get('path', '')
|
||||
|
||||
# Escape pipes in description to strictly avoid breaking the table
|
||||
desc = desc.replace('|', '\|')
|
||||
|
||||
row = f"| **{name}** | {desc} | `{path}` |"
|
||||
table_rows.append(row)
|
||||
|
||||
new_table_section = f"{note_block}\n\n{table_header}\n" + "\n".join(table_rows)
|
||||
|
||||
# Replace the old table section
|
||||
# We look for the start of the section and the end (which is either the next H2 or EOF)
|
||||
# The section starts after "## Full Skill Registry (X/X)"
|
||||
|
||||
# First, find the header position
|
||||
header_pattern = r'## Full Skill Registry \(\d+/\d+\)'
|
||||
header_match = re.search(header_pattern, content)
|
||||
|
||||
if not header_match:
|
||||
print("❌ Could not find 'Full Skill Registry' header.")
|
||||
return
|
||||
|
||||
start_pos = header_match.end()
|
||||
|
||||
# Find the next section (## ...) or end of file
|
||||
next_section_match = re.search(r'\n## ', content[start_pos:])
|
||||
|
||||
if next_section_match:
|
||||
end_pos = start_pos + next_section_match.start()
|
||||
# Keep everything after the table
|
||||
rest_of_file = content[end_pos:]
|
||||
else:
|
||||
# Table goes to end of file
|
||||
rest_of_file = ""
|
||||
|
||||
# Check for text between Header and Table (usually just newlines or the Note)
|
||||
# We replace everything from Header End to Next Section with our New Table Section
|
||||
# but we need to supply the pre-table Note which we extracted/re-generated above.
|
||||
|
||||
# Simplification: We construct the top part (before header), add header, add new table section, add rest.
|
||||
|
||||
before_header = content[:header_match.start()]
|
||||
new_header = f"## Full Skill Registry ({total_skills}/{total_skills})"
|
||||
|
||||
new_content = f"{before_header}{new_header}\n\n{new_table_section}\n{rest_of_file}"
|
||||
|
||||
with open(readme_path, 'w', encoding='utf-8') as f:
|
||||
f.write(new_content)
|
||||
|
||||
print("✅ README.md updated successfully.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
update_readme()
|
||||
Reference in New Issue
Block a user